use of org.h2.command.ddl.AlterTableAddConstraint in project h2database by h2database.
the class Parser method parseTableColumnDefinition.
private void parseTableColumnDefinition(CommandWithColumns command, Schema schema, String tableName) {
DefineCommand c = parseAlterTableAddConstraintIf(tableName, schema, false);
if (c != null) {
command.addConstraintCommand(c);
} else {
String columnName = readColumnIdentifier();
Column column = parseColumnForTable(columnName, true);
if (column.isAutoIncrement() && column.isPrimaryKey()) {
column.setPrimaryKey(false);
IndexColumn[] cols = { new IndexColumn() };
cols[0].columnName = column.getName();
AlterTableAddConstraint pk = new AlterTableAddConstraint(session, schema, false);
pk.setType(CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_PRIMARY_KEY);
pk.setTableName(tableName);
pk.setIndexColumns(cols);
command.addConstraintCommand(pk);
}
command.addColumn(column);
String constraintName = null;
if (readIf("CONSTRAINT")) {
constraintName = readColumnIdentifier();
}
// For compatibility with Apache Ignite.
boolean allowAffinityKey = database.getMode().allowAffinityKey;
boolean affinity = allowAffinityKey && readIfAffinity();
if (readIf("PRIMARY")) {
read("KEY");
boolean hash = readIf("HASH");
IndexColumn[] cols = { new IndexColumn() };
cols[0].columnName = column.getName();
AlterTableAddConstraint pk = new AlterTableAddConstraint(session, schema, false);
pk.setConstraintName(constraintName);
pk.setPrimaryKeyHash(hash);
pk.setType(CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_PRIMARY_KEY);
pk.setTableName(tableName);
pk.setIndexColumns(cols);
command.addConstraintCommand(pk);
if (readIf("AUTO_INCREMENT")) {
parseAutoIncrement(column);
}
if (affinity) {
CreateIndex idx = createAffinityIndex(schema, tableName, cols);
command.addConstraintCommand(idx);
}
} else if (affinity) {
read("KEY");
IndexColumn[] cols = { new IndexColumn() };
cols[0].columnName = column.getName();
CreateIndex idx = createAffinityIndex(schema, tableName, cols);
command.addConstraintCommand(idx);
} else if (readIf("UNIQUE")) {
AlterTableAddConstraint unique = new AlterTableAddConstraint(session, schema, false);
unique.setConstraintName(constraintName);
unique.setType(CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_UNIQUE);
IndexColumn[] cols = { new IndexColumn() };
cols[0].columnName = columnName;
unique.setIndexColumns(cols);
unique.setTableName(tableName);
command.addConstraintCommand(unique);
}
if (NullConstraintType.NULL_IS_NOT_ALLOWED == parseNotNullConstraint()) {
column.setNullable(false);
}
if (readIf("CHECK")) {
Expression expr = readExpression();
column.addCheckConstraint(session, expr);
}
if (readIf("REFERENCES")) {
AlterTableAddConstraint ref = new AlterTableAddConstraint(session, schema, false);
ref.setConstraintName(constraintName);
ref.setType(CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_REFERENTIAL);
IndexColumn[] cols = { new IndexColumn() };
cols[0].columnName = columnName;
ref.setIndexColumns(cols);
ref.setTableName(tableName);
parseReferences(ref, schema, tableName);
command.addConstraintCommand(ref);
}
}
}
use of org.h2.command.ddl.AlterTableAddConstraint in project h2database by h2database.
the class Parser method parseAlterTableAddConstraintIf.
private DefineCommand parseAlterTableAddConstraintIf(String tableName, Schema schema, boolean ifTableExists) {
String constraintName = null, comment = null;
boolean ifNotExists = false;
boolean allowIndexDefinition = database.getMode().indexDefinitionInCreateTable;
boolean allowAffinityKey = database.getMode().allowAffinityKey;
if (readIf("CONSTRAINT")) {
ifNotExists = readIfNotExists();
constraintName = readIdentifierWithSchema(schema.getName());
checkSchema(schema);
comment = readCommentIf();
allowIndexDefinition = true;
}
if (readIf("PRIMARY")) {
read("KEY");
AlterTableAddConstraint command = new AlterTableAddConstraint(session, schema, ifNotExists);
command.setType(CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_PRIMARY_KEY);
command.setComment(comment);
command.setConstraintName(constraintName);
command.setTableName(tableName);
command.setIfTableExists(ifTableExists);
if (readIf("HASH")) {
command.setPrimaryKeyHash(true);
}
read("(");
command.setIndexColumns(parseIndexColumnList());
if (readIf("INDEX")) {
String indexName = readIdentifierWithSchema();
command.setIndex(getSchema().findIndex(session, indexName));
}
return command;
} else if (allowIndexDefinition && (isToken("INDEX") || isToken("KEY"))) {
// MySQL
// need to read ahead, as it could be a column name
int start = lastParseIndex;
read();
if (DataType.getTypeByName(currentToken, database.getMode()) != null) {
// known data type
parseIndex = start;
read();
return null;
}
CreateIndex command = new CreateIndex(session, schema);
command.setComment(comment);
command.setTableName(tableName);
command.setIfTableExists(ifTableExists);
if (!readIf("(")) {
command.setIndexName(readUniqueIdentifier());
read("(");
}
command.setIndexColumns(parseIndexColumnList());
// MySQL compatibility
if (readIf("USING")) {
read("BTREE");
}
return command;
} else if (allowAffinityKey && readIfAffinity()) {
read("KEY");
read("(");
CreateIndex command = createAffinityIndex(schema, tableName, parseIndexColumnList());
command.setIfTableExists(ifTableExists);
return command;
}
AlterTableAddConstraint command;
if (readIf("CHECK")) {
command = new AlterTableAddConstraint(session, schema, ifNotExists);
command.setType(CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_CHECK);
command.setCheckExpression(readExpression());
} else if (readIf("UNIQUE")) {
readIf("KEY");
readIf("INDEX");
command = new AlterTableAddConstraint(session, schema, ifNotExists);
command.setType(CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_UNIQUE);
if (!readIf("(")) {
constraintName = readUniqueIdentifier();
read("(");
}
command.setIndexColumns(parseIndexColumnList());
if (readIf("INDEX")) {
String indexName = readIdentifierWithSchema();
command.setIndex(getSchema().findIndex(session, indexName));
}
// MySQL compatibility
if (readIf("USING")) {
read("BTREE");
}
} else if (readIf("FOREIGN")) {
command = new AlterTableAddConstraint(session, schema, ifNotExists);
command.setType(CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_REFERENTIAL);
read("KEY");
read("(");
command.setIndexColumns(parseIndexColumnList());
if (readIf("INDEX")) {
String indexName = readIdentifierWithSchema();
command.setIndex(schema.findIndex(session, indexName));
}
read("REFERENCES");
parseReferences(command, schema, tableName);
} else {
if (constraintName != null) {
throw getSyntaxError();
}
return null;
}
if (readIf("NOCHECK")) {
command.setCheckExisting(false);
} else {
readIf("CHECK");
command.setCheckExisting(true);
}
command.setTableName(tableName);
command.setIfTableExists(ifTableExists);
command.setConstraintName(constraintName);
command.setComment(comment);
return command;
}
use of org.h2.command.ddl.AlterTableAddConstraint in project ignite by apache.
the class GridSqlQueryParser method parseCreateTable.
/**
* Parse {@code CREATE TABLE} statement.
*
* @param createTbl {@code CREATE TABLE} statement.
* @see <a href="http://h2database.com/html/grammar.html#create_table">H2 {@code CREATE TABLE} spec.</a>
*/
private GridSqlCreateTable parseCreateTable(CreateTable createTbl) {
GridSqlCreateTable res = new GridSqlCreateTable();
res.templateName(QueryUtils.TEMPLATE_PARTITIONED);
Query qry = CREATE_TABLE_QUERY.get(createTbl);
if (qry != null) {
throw new IgniteSQLException("CREATE TABLE ... AS ... syntax is not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
List<DefineCommand> constraints = CREATE_TABLE_CONSTRAINTS.get(createTbl);
if (F.isEmpty(constraints)) {
throw new IgniteSQLException("No PRIMARY KEY defined for CREATE TABLE", IgniteQueryErrorCode.PARSING);
}
if (constraints.size() > 1) {
throw new IgniteSQLException("Too many constraints - only PRIMARY KEY is supported for CREATE TABLE", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
DefineCommand constraint = constraints.get(0);
if (!(constraint instanceof AlterTableAddConstraint)) {
throw new IgniteSQLException("Unsupported type of constraint for CREATE TABLE - only PRIMARY KEY " + "is supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
AlterTableAddConstraint alterTbl = (AlterTableAddConstraint) constraint;
if (alterTbl.getType() != Command.ALTER_TABLE_ADD_CONSTRAINT_PRIMARY_KEY) {
throw new IgniteSQLException("Unsupported type of constraint for CREATE TABLE - only PRIMARY KEY " + "is supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
Schema schema = SCHEMA_COMMAND_SCHEMA.get(createTbl);
res.schemaName(schema.getName());
CreateTableData data = CREATE_TABLE_DATA.get(createTbl);
if (data.globalTemporary) {
throw new IgniteSQLException("GLOBAL TEMPORARY keyword is not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
if (data.temporary) {
throw new IgniteSQLException("TEMPORARY keyword is not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
if (data.isHidden) {
throw new IgniteSQLException("HIDDEN keyword is not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
if (!data.persistIndexes) {
throw new IgniteSQLException("MEMORY and NOT PERSISTENT keywords are not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
LinkedHashMap<String, GridSqlColumn> cols = new LinkedHashMap<>(data.columns.size());
for (Column col : data.columns) {
if (cols.put(col.getName(), parseColumn(col)) != null)
throw new IgniteSQLException("Duplicate column name: " + col.getName(), IgniteQueryErrorCode.PARSING);
}
if (cols.containsKey(QueryUtils.KEY_FIELD_NAME.toUpperCase()) || cols.containsKey(QueryUtils.VAL_FIELD_NAME.toUpperCase())) {
throw new IgniteSQLException("Direct specification of _KEY and _VAL columns is forbidden", IgniteQueryErrorCode.PARSING);
}
IndexColumn[] pkIdxCols = CREATE_TABLE_PK.get(createTbl);
if (F.isEmpty(pkIdxCols))
throw new AssertionError("No PRIMARY KEY columns specified");
LinkedHashSet<String> pkCols = new LinkedHashSet<>();
for (IndexColumn pkIdxCol : pkIdxCols) {
GridSqlColumn gridCol = cols.get(pkIdxCol.columnName);
if (gridCol == null) {
throw new IgniteSQLException("PRIMARY KEY column is not defined: " + pkIdxCol.columnName, IgniteQueryErrorCode.PARSING);
}
pkCols.add(gridCol.columnName());
}
int keyColsNum = pkCols.size();
int valColsNum = cols.size() - keyColsNum;
if (valColsNum == 0) {
throw new IgniteSQLException("Table must have at least one non PRIMARY KEY column.", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
res.columns(cols);
res.primaryKeyColumns(pkCols);
res.tableName(data.tableName);
res.ifNotExists(CREATE_TABLE_IF_NOT_EXISTS.get(createTbl));
List<String> extraParams = data.tableEngineParams != null ? new ArrayList<String>() : null;
if (data.tableEngineParams != null)
for (String s : data.tableEngineParams) extraParams.addAll(F.asList(s.split(",")));
res.params(extraParams);
if (!F.isEmpty(extraParams)) {
Map<String, String> params = new HashMap<>();
for (String p : extraParams) {
String[] parts = p.split(PARAM_NAME_VALUE_SEPARATOR);
if (parts.length > 2) {
throw new IgniteSQLException("Invalid parameter (key[=value] expected): " + p, IgniteQueryErrorCode.PARSING);
}
String name = parts[0].trim().toUpperCase();
String val = parts.length > 1 ? parts[1].trim() : null;
if (F.isEmpty(name)) {
throw new IgniteSQLException("Invalid parameter (key[=value] expected): " + p, IgniteQueryErrorCode.PARSING);
}
if (params.put(name, val) != null)
throw new IgniteSQLException("Duplicate parameter: " + p, IgniteQueryErrorCode.PARSING);
}
for (Map.Entry<String, String> e : params.entrySet()) processExtraParam(e.getKey(), e.getValue(), res);
}
// Process key wrapping.
Boolean wrapKey = res.wrapKey();
if (wrapKey != null && !wrapKey) {
if (keyColsNum > 1) {
throw new IgniteSQLException(PARAM_WRAP_KEY + " cannot be false when composite primary key exists.", IgniteQueryErrorCode.PARSING);
}
if (!F.isEmpty(res.keyTypeName())) {
throw new IgniteSQLException(PARAM_WRAP_KEY + " cannot be false when " + PARAM_KEY_TYPE + " is set.", IgniteQueryErrorCode.PARSING);
}
}
boolean wrapKey0 = (res.wrapKey() != null && res.wrapKey()) || !F.isEmpty(res.keyTypeName()) || keyColsNum > 1;
res.wrapKey(wrapKey0);
// Process value wrapping.
Boolean wrapVal = res.wrapValue();
if (wrapVal != null && !wrapVal) {
if (valColsNum > 1) {
throw new IgniteSQLException(PARAM_WRAP_VALUE + " cannot be false when multiple non-primary key " + "columns exist.", IgniteQueryErrorCode.PARSING);
}
if (!F.isEmpty(res.valueTypeName())) {
throw new IgniteSQLException(PARAM_WRAP_VALUE + " cannot be false when " + PARAM_VAL_TYPE + " is set.", IgniteQueryErrorCode.PARSING);
}
res.wrapValue(false);
} else
// By default value is always wrapped to allow for ALTER TABLE ADD COLUMN commands.
res.wrapValue(true);
if (!F.isEmpty(res.valueTypeName()) && F.eq(res.keyTypeName(), res.valueTypeName())) {
throw new IgniteSQLException("Key and value type names " + "should be different for CREATE TABLE: " + res.valueTypeName(), IgniteQueryErrorCode.PARSING);
}
if (res.affinityKey() == null) {
LinkedHashSet<String> pkCols0 = res.primaryKeyColumns();
if (!F.isEmpty(pkCols0) && pkCols0.size() == 1 && wrapKey0)
res.affinityKey(pkCols0.iterator().next());
}
return res;
}
use of org.h2.command.ddl.AlterTableAddConstraint in project h2database by h2database.
the class Parser method parseReferences.
private void parseReferences(AlterTableAddConstraint command, Schema schema, String tableName) {
if (readIf("(")) {
command.setRefTableName(schema, tableName);
command.setRefIndexColumns(parseIndexColumnList());
} else {
String refTableName = readIdentifierWithSchema(schema.getName());
command.setRefTableName(getSchema(), refTableName);
if (readIf("(")) {
command.setRefIndexColumns(parseIndexColumnList());
}
}
if (readIf("INDEX")) {
String indexName = readIdentifierWithSchema();
command.setRefIndex(getSchema().findIndex(session, indexName));
}
while (readIf("ON")) {
if (readIf("DELETE")) {
command.setDeleteAction(parseAction());
} else {
read("UPDATE");
command.setUpdateAction(parseAction());
}
}
if (readIf("NOT")) {
read("DEFERRABLE");
} else {
readIf("DEFERRABLE");
}
}
use of org.h2.command.ddl.AlterTableAddConstraint in project h2database by h2database.
the class TestTriggersConstraints method testMultiPartForeignKeys.
/**
* Regression test: we had a bug where the AlterTableAddConstraint class
* used to sometimes pick the wrong unique index for a foreign key.
*/
private void testMultiPartForeignKeys() throws SQLException {
Connection conn = getConnection("trigger");
Statement stat = conn.createStatement();
stat.execute("DROP TABLE IF EXISTS TEST1");
stat.execute("DROP TABLE IF EXISTS TEST2");
stat.execute("create table test1(id int primary key, col1 int)");
stat.execute("alter table test1 add constraint unique_test1 " + "unique (id,col1)");
stat.execute("create table test2(id int primary key, col1 int)");
stat.execute("alter table test2 add constraint fk_test2 " + "foreign key(id,col1) references test1 (id,col1)");
stat.execute("insert into test1 values (1,1)");
stat.execute("insert into test1 values (2,2)");
stat.execute("insert into test1 values (3,3)");
stat.execute("insert into test2 values (1,1)");
assertThrows(23506, stat).execute("insert into test2 values (2,1)");
assertSingleValue(stat, "select count(*) from test1", 3);
assertSingleValue(stat, "select count(*) from test2", 1);
stat.execute("drop table test1");
stat.execute("drop table test2");
conn.close();
}
Aggregations