提交 1dd4130d authored 作者: lukaseder's avatar lukaseder

[#285] Add support for ALTER TABLE IF EXISTS

上级 5e7df467
...@@ -16,6 +16,7 @@ import java.util.ArrayList; ...@@ -16,6 +16,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashSet; import java.util.HashSet;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.api.Trigger; import org.h2.api.Trigger;
import org.h2.command.ddl.AlterIndexRename; import org.h2.command.ddl.AlterIndexRename;
...@@ -5421,21 +5422,24 @@ public class Parser { ...@@ -5421,21 +5422,24 @@ public class Parser {
} }
private Prepared parseAlterTable() { private Prepared parseAlterTable() {
Table table = readTableOrView(); boolean ifTableExists = readIfExists(false);
String tableName = readIdentifierWithSchema();
Schema schema = getSchema();
if (readIf("ADD")) { if (readIf("ADD")) {
Prepared command = parseAlterTableAddConstraintIf(table.getName(), Prepared command = parseAlterTableAddConstraintIf(tableName,
table.getSchema()); schema, ifTableExists);
if (command != null) { if (command != null) {
return command; return command;
} }
return parseAlterTableAddColumn(table); return parseAlterTableAddColumn(tableName, schema, ifTableExists);
} else if (readIf("SET")) { } else if (readIf("SET")) {
read("REFERENTIAL_INTEGRITY"); read("REFERENTIAL_INTEGRITY");
int type = CommandInterface.ALTER_TABLE_SET_REFERENTIAL_INTEGRITY; int type = CommandInterface.ALTER_TABLE_SET_REFERENTIAL_INTEGRITY;
boolean value = readBooleanSetting(); boolean value = readBooleanSetting();
AlterTableSet command = new AlterTableSet(session, AlterTableSet command = new AlterTableSet(session,
table.getSchema(), type, value); schema, type, value);
command.setTableName(table.getName()); command.setTableName(tableName);
command.setIfTableExists(ifTableExists);
if (readIf("CHECK")) { if (readIf("CHECK")) {
command.setCheckExisting(true); command.setCheckExisting(true);
} else if (readIf("NOCHECK")) { } else if (readIf("NOCHECK")) {
...@@ -5446,87 +5450,93 @@ public class Parser { ...@@ -5446,87 +5450,93 @@ public class Parser {
if (readIf("COLUMN")) { if (readIf("COLUMN")) {
// PostgreSQL syntax // PostgreSQL syntax
String columnName = readColumnIdentifier(); String columnName = readColumnIdentifier();
Column column = table.getColumn(columnName);
read("TO"); read("TO");
AlterTableRenameColumn command = new AlterTableRenameColumn( AlterTableRenameColumn command = new AlterTableRenameColumn(
session); session, schema);
command.setTable(table); command.setTableName(tableName);
command.setColumn(column); command.setIfTableExists(ifTableExists);
command.setOldColumnName(columnName);
String newName = readColumnIdentifier(); String newName = readColumnIdentifier();
command.setNewColumnName(newName); command.setNewColumnName(newName);
return command; return command;
} else if (readIf("CONSTRAINT")) { } else if (readIf("CONSTRAINT")) {
String constraintName = readIdentifierWithSchema(table String constraintName = readIdentifierWithSchema(schema.getName());
.getSchema().getName()); checkSchema(schema);
checkSchema(table.getSchema());
read("TO"); read("TO");
AlterTableRenameConstraint command = new AlterTableRenameConstraint( AlterTableRenameConstraint command = new AlterTableRenameConstraint(
session, table.getSchema()); session, schema);
command.setConstraintName(constraintName); command.setConstraintName(constraintName);
String newName = readColumnIdentifier(); String newName = readColumnIdentifier();
command.setNewConstraintName(newName); command.setNewConstraintName(newName);
return command; return commandIfTableExists(schema, tableName, ifTableExists, command);
} else { } else {
read("TO"); read("TO");
String newName = readIdentifierWithSchema(table.getSchema() String newName = readIdentifierWithSchema(schema.getName());
.getName()); checkSchema(schema);
checkSchema(table.getSchema());
AlterTableRename command = new AlterTableRename(session, AlterTableRename command = new AlterTableRename(session,
getSchema()); getSchema());
command.setOldTable(table); command.setOldTableName(tableName);
command.setNewTableName(newName); command.setNewTableName(newName);
command.setIfTableExists(ifTableExists);
command.setHidden(readIf("HIDDEN")); command.setHidden(readIf("HIDDEN"));
return command; return command;
} }
} else if (readIf("DROP")) { } else if (readIf("DROP")) {
if (readIf("CONSTRAINT")) { if (readIf("CONSTRAINT")) {
boolean ifExists = readIfExists(false); boolean ifExists = readIfExists(false);
String constraintName = readIdentifierWithSchema(table String constraintName = readIdentifierWithSchema(schema.getName());
.getSchema().getName());
ifExists = readIfExists(ifExists); ifExists = readIfExists(ifExists);
checkSchema(table.getSchema()); checkSchema(schema);
AlterTableDropConstraint command = new AlterTableDropConstraint( AlterTableDropConstraint command = new AlterTableDropConstraint(
session, getSchema(), ifExists); session, getSchema(), ifExists);
command.setConstraintName(constraintName); command.setConstraintName(constraintName);
return command; return commandIfTableExists(schema, tableName, ifTableExists, command);
} else if (readIf("FOREIGN")) { } else if (readIf("FOREIGN")) {
// MySQL compatibility // MySQL compatibility
read("KEY"); read("KEY");
String constraintName = readIdentifierWithSchema(table String constraintName = readIdentifierWithSchema(schema.getName());
.getSchema().getName()); checkSchema(schema);
checkSchema(table.getSchema());
AlterTableDropConstraint command = new AlterTableDropConstraint( AlterTableDropConstraint command = new AlterTableDropConstraint(
session, getSchema(), false); session, getSchema(), false);
command.setConstraintName(constraintName); command.setConstraintName(constraintName);
return command; return commandIfTableExists(schema, tableName, ifTableExists, command);
} else if (readIf("INDEX")) { } else if (readIf("INDEX")) {
// MySQL compatibility // MySQL compatibility
String indexName = readIdentifierWithSchema(); String indexName = readIdentifierWithSchema();
DropIndex command = new DropIndex(session, getSchema()); DropIndex command = new DropIndex(session, getSchema());
command.setIndexName(indexName); command.setIndexName(indexName);
return command; return commandIfTableExists(schema, tableName, ifTableExists, command);
} else if (readIf("PRIMARY")) { } else if (readIf("PRIMARY")) {
read("KEY"); read("KEY");
Table table = tableIfTableExists(schema, tableName, ifTableExists);
if (table == null) {
return new NoOperation(session);
}
Index idx = table.getPrimaryKey(); Index idx = table.getPrimaryKey();
DropIndex command = new DropIndex(session, table.getSchema()); DropIndex command = new DropIndex(session, schema);
command.setIndexName(idx.getName()); command.setIndexName(idx.getName());
return command; return command;
} else { } else {
readIf("COLUMN"); readIf("COLUMN");
boolean ifExists = readIfExists(false); boolean ifExists = readIfExists(false);
AlterTableAlterColumn command = new AlterTableAlterColumn( AlterTableAlterColumn command = new AlterTableAlterColumn(
session, table.getSchema()); session, schema);
command.setType(CommandInterface.ALTER_TABLE_DROP_COLUMN); command.setType(CommandInterface.ALTER_TABLE_DROP_COLUMN);
ArrayList<Column> columnsToRemove = New.arrayList(); ArrayList<Column> columnsToRemove = New.arrayList();
Table table = tableIfTableExists(schema, tableName, ifTableExists);
do { do {
String columnName = readColumnIdentifier(); String columnName = readColumnIdentifier();
if (table == null) {
return new NoOperation(session);
}
if (ifExists && !table.doesColumnExist(columnName)) { if (ifExists && !table.doesColumnExist(columnName)) {
return new NoOperation(session); return new NoOperation(session);
} }
Column column = table.getColumn(columnName); Column column = table.getColumn(columnName);
columnsToRemove.add(column); columnsToRemove.add(column);
} while (readIf(",")); } while (readIf(","));
command.setTable(table); command.setTableName(tableName);
command.setIfTableExists(ifTableExists);
command.setColumnsToRemove(columnsToRemove); command.setColumnsToRemove(columnsToRemove);
return command; return command;
} }
...@@ -5534,32 +5544,34 @@ public class Parser { ...@@ -5534,32 +5544,34 @@ public class Parser {
// MySQL compatibility // MySQL compatibility
readIf("COLUMN"); readIf("COLUMN");
String columnName = readColumnIdentifier(); String columnName = readColumnIdentifier();
Column column = table.getColumn(columnName);
String newColumnName = readColumnIdentifier(); String newColumnName = readColumnIdentifier();
Column column = columnIfTableExists(schema, tableName, columnName, ifTableExists);
boolean nullable = column == null ? true : column.isNullable();
// new column type ignored. RENAME and MODIFY are // new column type ignored. RENAME and MODIFY are
// a single command in MySQL but two different commands in H2. // a single command in MySQL but two different commands in H2.
parseColumnForTable(newColumnName, column.isNullable()); parseColumnForTable(newColumnName, nullable);
AlterTableRenameColumn command = new AlterTableRenameColumn(session); AlterTableRenameColumn command = new AlterTableRenameColumn(session, schema);
command.setTable(table); command.setTableName(tableName);
command.setColumn(column); command.setIfTableExists(ifTableExists);
command.setOldColumnName(columnName);
command.setNewColumnName(newColumnName); command.setNewColumnName(newColumnName);
return command; return command;
} else if (readIf("MODIFY")) { } else if (readIf("MODIFY")) {
// MySQL compatibility // MySQL compatibility
readIf("COLUMN"); readIf("COLUMN");
String columnName = readColumnIdentifier(); String columnName = readColumnIdentifier();
Column column = table.getColumn(columnName); return parseAlterTableAlterColumnType(schema, tableName, columnName, ifTableExists);
return parseAlterTableAlterColumnType(table, columnName, column);
} else if (readIf("ALTER")) { } else if (readIf("ALTER")) {
readIf("COLUMN"); readIf("COLUMN");
String columnName = readColumnIdentifier(); String columnName = readColumnIdentifier();
Column column = table.getColumn(columnName); Column column = columnIfTableExists(schema, tableName, columnName, ifTableExists);
if (readIf("RENAME")) { if (readIf("RENAME")) {
read("TO"); read("TO");
AlterTableRenameColumn command = new AlterTableRenameColumn( AlterTableRenameColumn command = new AlterTableRenameColumn(
session); session, schema);
command.setTable(table); command.setTableName(tableName);
command.setColumn(column); command.setIfTableExists(ifTableExists);
command.setOldColumnName(columnName);
String newName = readColumnIdentifier(); String newName = readColumnIdentifier();
command.setNewColumnName(newName); command.setNewColumnName(newName);
return command; return command;
...@@ -5567,8 +5579,9 @@ public class Parser { ...@@ -5567,8 +5579,9 @@ public class Parser {
// PostgreSQL compatibility // PostgreSQL compatibility
if (readIf("DEFAULT")) { if (readIf("DEFAULT")) {
AlterTableAlterColumn command = new AlterTableAlterColumn( AlterTableAlterColumn command = new AlterTableAlterColumn(
session, table.getSchema()); session, schema);
command.setTable(table); command.setTableName(tableName);
command.setIfTableExists(ifTableExists);
command.setOldColumn(column); command.setOldColumn(column);
command.setType(CommandInterface.ALTER_TABLE_ALTER_COLUMN_DEFAULT); command.setType(CommandInterface.ALTER_TABLE_ALTER_COLUMN_DEFAULT);
command.setDefaultExpression(null); command.setDefaultExpression(null);
...@@ -5577,24 +5590,26 @@ public class Parser { ...@@ -5577,24 +5590,26 @@ public class Parser {
read("NOT"); read("NOT");
read("NULL"); read("NULL");
AlterTableAlterColumn command = new AlterTableAlterColumn( AlterTableAlterColumn command = new AlterTableAlterColumn(
session, table.getSchema()); session, schema);
command.setTable(table); command.setTableName(tableName);
command.setIfTableExists(ifTableExists);
command.setOldColumn(column); command.setOldColumn(column);
command.setType(CommandInterface.ALTER_TABLE_ALTER_COLUMN_NULL); command.setType(CommandInterface.ALTER_TABLE_ALTER_COLUMN_NULL);
return command; return command;
} else if (readIf("TYPE")) { } else if (readIf("TYPE")) {
// PostgreSQL compatibility // PostgreSQL compatibility
return parseAlterTableAlterColumnType(table, columnName, column); return parseAlterTableAlterColumnType(schema, tableName, columnName, ifTableExists);
} else if (readIf("SET")) { } else if (readIf("SET")) {
if (readIf("DATA")) { if (readIf("DATA")) {
// Derby compatibility // Derby compatibility
read("TYPE"); read("TYPE");
return parseAlterTableAlterColumnType(table, columnName, return parseAlterTableAlterColumnType(schema, tableName, columnName,
column); ifTableExists);
} }
AlterTableAlterColumn command = new AlterTableAlterColumn( AlterTableAlterColumn command = new AlterTableAlterColumn(
session, table.getSchema()); session, schema);
command.setTable(table); command.setTableName(tableName);
command.setIfTableExists(ifTableExists);
command.setOldColumn(column); command.setOldColumn(column);
if (readIf("NULL")) { if (readIf("NULL")) {
command.setType(CommandInterface.ALTER_TABLE_ALTER_COLUMN_NULL); command.setType(CommandInterface.ALTER_TABLE_ALTER_COLUMN_NULL);
...@@ -5612,45 +5627,66 @@ public class Parser { ...@@ -5612,45 +5627,66 @@ public class Parser {
} else if (readIf("RESTART")) { } else if (readIf("RESTART")) {
readIf("WITH"); readIf("WITH");
Expression start = readExpression(); Expression start = readExpression();
AlterSequence command = new AlterSequence(session, AlterSequence command = new AlterSequence(session, schema);
table.getSchema());
command.setColumn(column); command.setColumn(column);
command.setStartWith(start); command.setStartWith(start);
return command; return commandIfTableExists(schema, tableName, ifTableExists, command);
} else if (readIf("SELECTIVITY")) { } else if (readIf("SELECTIVITY")) {
AlterTableAlterColumn command = new AlterTableAlterColumn( AlterTableAlterColumn command = new AlterTableAlterColumn(
session, table.getSchema()); session, schema);
command.setTable(table); command.setTableName(tableName);
command.setIfTableExists(ifTableExists);
command.setType(CommandInterface.ALTER_TABLE_ALTER_COLUMN_SELECTIVITY); command.setType(CommandInterface.ALTER_TABLE_ALTER_COLUMN_SELECTIVITY);
command.setOldColumn(column); command.setOldColumn(column);
command.setSelectivity(readExpression()); command.setSelectivity(readExpression());
return command; return command;
} else { } else {
return parseAlterTableAlterColumnType(table, columnName, column); return parseAlterTableAlterColumnType(schema, tableName, columnName, ifTableExists);
} }
} }
throw getSyntaxError(); throw getSyntaxError();
} }
private AlterTableAlterColumn parseAlterTableAlterColumnType(Table table, private Table tableIfTableExists(Schema schema, String tableName, boolean ifTableExists) {
String columnName, Column column) { Table table = schema.findTableOrView(session, tableName);
Column newColumn = parseColumnForTable(columnName, column.isNullable()); if (table == null && !ifTableExists) {
throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, tableName);
}
return table;
}
private Column columnIfTableExists(Schema schema, String tableName, String columnName, boolean ifTableExists) {
Table table = tableIfTableExists(schema, tableName, ifTableExists);
return table == null ? null : table.getColumn(columnName);
}
private Prepared commandIfTableExists(Schema schema, String tableName, boolean ifTableExists, Prepared commandIfTableExists) {
return tableIfTableExists(schema, tableName, ifTableExists) == null
? new NoOperation(session)
: commandIfTableExists;
}
private AlterTableAlterColumn parseAlterTableAlterColumnType(Schema schema, String tableName,
String columnName, boolean ifTableExists) {
Column oldColumn = columnIfTableExists(schema, tableName, columnName, ifTableExists);
Column newColumn = parseColumnForTable(columnName, oldColumn == null ? true : oldColumn.isNullable());
AlterTableAlterColumn command = new AlterTableAlterColumn(session, AlterTableAlterColumn command = new AlterTableAlterColumn(session,
table.getSchema()); schema);
command.setTable(table); command.setTableName(tableName);
command.setIfTableExists(ifTableExists);
command.setType(CommandInterface.ALTER_TABLE_ALTER_COLUMN_CHANGE_TYPE); command.setType(CommandInterface.ALTER_TABLE_ALTER_COLUMN_CHANGE_TYPE);
command.setOldColumn(column); command.setOldColumn(oldColumn);
command.setNewColumn(newColumn); command.setNewColumn(newColumn);
return command; return command;
} }
private AlterTableAlterColumn parseAlterTableAddColumn(Table table) { private AlterTableAlterColumn parseAlterTableAddColumn(String tableName, Schema schema, boolean ifTableExists) {
readIf("COLUMN"); readIf("COLUMN");
Schema schema = table.getSchema();
AlterTableAlterColumn command = new AlterTableAlterColumn(session, AlterTableAlterColumn command = new AlterTableAlterColumn(session,
schema); schema);
command.setType(CommandInterface.ALTER_TABLE_ADD_COLUMN); command.setType(CommandInterface.ALTER_TABLE_ADD_COLUMN);
command.setTable(table); command.setTableName(tableName);
command.setIfTableExists(ifTableExists);
ArrayList<Column> columnsToAdd = New.arrayList(); ArrayList<Column> columnsToAdd = New.arrayList();
if (readIf("(")) { if (readIf("(")) {
command.setIfNotExists(false); command.setIfNotExists(false);
...@@ -5705,7 +5741,7 @@ public class Parser { ...@@ -5705,7 +5741,7 @@ public class Parser {
} }
private DefineCommand parseAlterTableAddConstraintIf(String tableName, private DefineCommand parseAlterTableAddConstraintIf(String tableName,
Schema schema) { Schema schema, boolean ifTableExists) {
String constraintName = null, comment = null; String constraintName = null, comment = null;
boolean ifNotExists = false; boolean ifNotExists = false;
boolean allowIndexDefinition = database.getMode().indexDefinitionInCreateTable; boolean allowIndexDefinition = database.getMode().indexDefinitionInCreateTable;
...@@ -5724,6 +5760,7 @@ public class Parser { ...@@ -5724,6 +5760,7 @@ public class Parser {
command.setComment(comment); command.setComment(comment);
command.setConstraintName(constraintName); command.setConstraintName(constraintName);
command.setTableName(tableName); command.setTableName(tableName);
command.setIfTableExists(ifTableExists);
if (readIf("HASH")) { if (readIf("HASH")) {
command.setPrimaryKeyHash(true); command.setPrimaryKeyHash(true);
} }
...@@ -5748,6 +5785,7 @@ public class Parser { ...@@ -5748,6 +5785,7 @@ public class Parser {
CreateIndex command = new CreateIndex(session, schema); CreateIndex command = new CreateIndex(session, schema);
command.setComment(comment); command.setComment(comment);
command.setTableName(tableName); command.setTableName(tableName);
command.setIfTableExists(ifTableExists);
if (!readIf("(")) { if (!readIf("(")) {
command.setIndexName(readUniqueIdentifier()); command.setIndexName(readUniqueIdentifier());
read("("); read("(");
...@@ -5807,6 +5845,7 @@ public class Parser { ...@@ -5807,6 +5845,7 @@ public class Parser {
command.setCheckExisting(true); command.setCheckExisting(true);
} }
command.setTableName(tableName); command.setTableName(tableName);
command.setIfTableExists(ifTableExists);
command.setConstraintName(constraintName); command.setConstraintName(constraintName);
command.setComment(comment); command.setComment(comment);
return command; return command;
...@@ -5902,7 +5941,7 @@ public class Parser { ...@@ -5902,7 +5941,7 @@ public class Parser {
if (!readIf(")")) { if (!readIf(")")) {
do { do {
DefineCommand c = parseAlterTableAddConstraintIf(tableName, DefineCommand c = parseAlterTableAddConstraintIf(tableName,
schema); schema, false);
if (c != null) { if (c != null) {
command.addConstraintCommand(c); command.addConstraintCommand(c);
} else { } else {
......
...@@ -49,6 +49,7 @@ public class AlterTableAddConstraint extends SchemaCommand { ...@@ -49,6 +49,7 @@ public class AlterTableAddConstraint extends SchemaCommand {
private String comment; private String comment;
private boolean checkExisting; private boolean checkExisting;
private boolean primaryKeyHash; private boolean primaryKeyHash;
private boolean ifTableExists;
private final boolean ifNotExists; private final boolean ifNotExists;
private ArrayList<Index> createdIndexes = New.arrayList(); private ArrayList<Index> createdIndexes = New.arrayList();
...@@ -58,6 +59,10 @@ public class AlterTableAddConstraint extends SchemaCommand { ...@@ -58,6 +59,10 @@ public class AlterTableAddConstraint extends SchemaCommand {
this.ifNotExists = ifNotExists; this.ifNotExists = ifNotExists;
} }
public void setIfTableExists(boolean b) {
ifTableExists = b;
}
private String generateConstraintName(Table table) { private String generateConstraintName(Table table) {
if (constraintName == null) { if (constraintName == null) {
constraintName = getSchema().getUniqueConstraintName( constraintName = getSchema().getUniqueConstraintName(
...@@ -90,7 +95,13 @@ public class AlterTableAddConstraint extends SchemaCommand { ...@@ -90,7 +95,13 @@ public class AlterTableAddConstraint extends SchemaCommand {
session.commit(true); session.commit(true);
} }
Database db = session.getDatabase(); Database db = session.getDatabase();
Table table = getSchema().getTableOrView(session, tableName); Table table = getSchema().findTableOrView(session, tableName);
if (table == null) {
if (ifTableExists) {
return 0;
}
throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, tableName);
}
if (getSchema().findConstraint(session, constraintName) != null) { if (getSchema().findConstraint(session, constraintName) != null) {
if (ifNotExists) { if (ifNotExists) {
return 0; return 0;
......
...@@ -48,7 +48,7 @@ import org.h2.util.New; ...@@ -48,7 +48,7 @@ import org.h2.util.New;
*/ */
public class AlterTableAlterColumn extends SchemaCommand { public class AlterTableAlterColumn extends SchemaCommand {
private Table table; private String tableName;
private Column oldColumn; private Column oldColumn;
private Column newColumn; private Column newColumn;
private int type; private int type;
...@@ -56,6 +56,7 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -56,6 +56,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
private Expression newSelectivity; private Expression newSelectivity;
private String addBefore; private String addBefore;
private String addAfter; private String addAfter;
private boolean ifTableExists;
private boolean ifNotExists; private boolean ifNotExists;
private ArrayList<Column> columnsToAdd; private ArrayList<Column> columnsToAdd;
private ArrayList<Column> columnsToRemove; private ArrayList<Column> columnsToRemove;
...@@ -64,8 +65,12 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -64,8 +65,12 @@ public class AlterTableAlterColumn extends SchemaCommand {
super(session, schema); super(session, schema);
} }
public void setTable(Table table) { public void setIfTableExists(boolean b) {
this.table = table; ifTableExists = b;
}
public void setTableName(String tableName) {
this.tableName = tableName;
} }
public void setOldColumn(Column oldColumn) { public void setOldColumn(Column oldColumn) {
...@@ -84,16 +89,23 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -84,16 +89,23 @@ public class AlterTableAlterColumn extends SchemaCommand {
public int update() { public int update() {
session.commit(true); session.commit(true);
Database db = session.getDatabase(); Database db = session.getDatabase();
Table table = getSchema().findTableOrView(session, tableName);
if (table == null) {
if (ifTableExists) {
return 0;
}
throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, tableName);
}
session.getUser().checkRight(table, Right.ALL); session.getUser().checkRight(table, Right.ALL);
table.checkSupportAlter(); table.checkSupportAlter();
table.lock(session, true, true); table.lock(session, true, true);
if (newColumn != null) { if (newColumn != null) {
checkDefaultReferencesTable(newColumn.getDefaultExpression()); checkDefaultReferencesTable(table, newColumn.getDefaultExpression());
checkClustering(newColumn); checkClustering(newColumn);
} }
if (columnsToAdd != null) { if (columnsToAdd != null) {
for (Column column : columnsToAdd) { for (Column column : columnsToAdd) {
checkDefaultReferencesTable(column.getDefaultExpression()); checkDefaultReferencesTable(table, column.getDefaultExpression());
checkClustering(column); checkClustering(column);
} }
} }
...@@ -103,7 +115,7 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -103,7 +115,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
// no change // no change
break; break;
} }
checkNoNullValues(); checkNoNullValues(table);
oldColumn.setNullable(false); oldColumn.setNullable(false);
db.updateMeta(session, table); db.updateMeta(session, table);
break; break;
...@@ -113,17 +125,17 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -113,17 +125,17 @@ public class AlterTableAlterColumn extends SchemaCommand {
// no change // no change
break; break;
} }
checkNullable(); checkNullable(table);
oldColumn.setNullable(true); oldColumn.setNullable(true);
db.updateMeta(session, table); db.updateMeta(session, table);
break; break;
} }
case CommandInterface.ALTER_TABLE_ALTER_COLUMN_DEFAULT: { case CommandInterface.ALTER_TABLE_ALTER_COLUMN_DEFAULT: {
Sequence sequence = oldColumn == null ? null : oldColumn.getSequence(); Sequence sequence = oldColumn == null ? null : oldColumn.getSequence();
checkDefaultReferencesTable(defaultExpression); checkDefaultReferencesTable(table, defaultExpression);
oldColumn.setSequence(null); oldColumn.setSequence(null);
oldColumn.setDefaultExpression(session, defaultExpression); oldColumn.setDefaultExpression(session, defaultExpression);
removeSequence(sequence); removeSequence(table, sequence);
db.updateMeta(session, table); db.updateMeta(session, table);
break; break;
} }
...@@ -132,7 +144,7 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -132,7 +144,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
// need to copy the table because the length is only a constraint, // need to copy the table because the length is only a constraint,
// and does not affect the storage structure. // and does not affect the storage structure.
if (oldColumn.isWideningConversion(newColumn)) { if (oldColumn.isWideningConversion(newColumn)) {
convertAutoIncrementColumn(newColumn); convertAutoIncrementColumn(table, newColumn);
oldColumn.copy(newColumn); oldColumn.copy(newColumn);
db.updateMeta(session, table); db.updateMeta(session, table);
} else { } else {
...@@ -140,12 +152,12 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -140,12 +152,12 @@ public class AlterTableAlterColumn extends SchemaCommand {
oldColumn.setDefaultExpression(session, null); oldColumn.setDefaultExpression(session, null);
oldColumn.setConvertNullToDefault(false); oldColumn.setConvertNullToDefault(false);
if (oldColumn.isNullable() && !newColumn.isNullable()) { if (oldColumn.isNullable() && !newColumn.isNullable()) {
checkNoNullValues(); checkNoNullValues(table);
} else if (!oldColumn.isNullable() && newColumn.isNullable()) { } else if (!oldColumn.isNullable() && newColumn.isNullable()) {
checkNullable(); checkNullable(table);
} }
convertAutoIncrementColumn(newColumn); convertAutoIncrementColumn(table, newColumn);
copyData(); copyData(table);
} }
break; break;
} }
...@@ -162,7 +174,7 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -162,7 +174,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
table.isTemporary()); table.isTemporary());
} }
} }
copyData(); copyData(table);
break; break;
} }
case CommandInterface.ALTER_TABLE_DROP_COLUMN: { case CommandInterface.ALTER_TABLE_DROP_COLUMN: {
...@@ -171,7 +183,7 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -171,7 +183,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
columnsToRemove.get(0).getSQL()); columnsToRemove.get(0).getSQL());
} }
table.dropMultipleColumnsConstraintsAndIndexes(session, columnsToRemove); table.dropMultipleColumnsConstraintsAndIndexes(session, columnsToRemove);
copyData(); copyData(table);
break; break;
} }
case CommandInterface.ALTER_TABLE_ALTER_COLUMN_SELECTIVITY: { case CommandInterface.ALTER_TABLE_ALTER_COLUMN_SELECTIVITY: {
...@@ -186,7 +198,7 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -186,7 +198,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
return 0; return 0;
} }
private void checkDefaultReferencesTable(Expression defaultExpression) { private void checkDefaultReferencesTable(Table table, Expression defaultExpression) {
if (defaultExpression == null) { if (defaultExpression == null) {
return; return;
} }
...@@ -209,7 +221,7 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -209,7 +221,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
} }
} }
private void convertAutoIncrementColumn(Column c) { private void convertAutoIncrementColumn(Table table, Column c) {
if (c.isAutoIncrement()) { if (c.isAutoIncrement()) {
if (c.isPrimaryKey()) { if (c.isPrimaryKey()) {
c.setOriginalSQL("IDENTITY"); c.setOriginalSQL("IDENTITY");
...@@ -221,7 +233,7 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -221,7 +233,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
} }
} }
private void removeSequence(Sequence sequence) { private void removeSequence(Table table, Sequence sequence) {
if (sequence != null) { if (sequence != null) {
table.removeSequence(sequence); table.removeSequence(sequence);
sequence.setBelongsToTable(false); sequence.setBelongsToTable(false);
...@@ -230,7 +242,7 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -230,7 +242,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
} }
} }
private void copyData() { private void copyData(Table table) {
if (table.isTemporary()) { if (table.isTemporary()) {
throw DbException.getUnsupportedException("TEMP TABLE"); throw DbException.getUnsupportedException("TEMP TABLE");
} }
...@@ -239,7 +251,7 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -239,7 +251,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
String tempName = db.getTempTableName(baseName, session); String tempName = db.getTempTableName(baseName, session);
Column[] columns = table.getColumns(); Column[] columns = table.getColumns();
ArrayList<Column> newColumns = New.arrayList(); ArrayList<Column> newColumns = New.arrayList();
Table newTable = cloneTableStructure(columns, db, tempName, newColumns); Table newTable = cloneTableStructure(table, columns, db, tempName, newColumns);
try { try {
// check if a view would become invalid // check if a view would become invalid
// (because the column to drop is referenced or so) // (because the column to drop is referenced or so)
...@@ -289,7 +301,7 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -289,7 +301,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
} }
} }
private Table cloneTableStructure(Column[] columns, Database db, private Table cloneTableStructure(Table table, Column[] columns, Database db,
String tempName, ArrayList<Column> newColumns) { String tempName, ArrayList<Column> newColumns) {
for (Column col : columns) { for (Column col : columns) {
newColumns.add(col.getClone()); newColumns.add(col.getClone());
...@@ -479,7 +491,7 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -479,7 +491,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
} }
} }
private void checkNullable() { private void checkNullable(Table table) {
for (Index index : table.getIndexes()) { for (Index index : table.getIndexes()) {
if (index.getColumnIndex(oldColumn) < 0) { if (index.getColumnIndex(oldColumn) < 0) {
continue; continue;
...@@ -492,7 +504,7 @@ public class AlterTableAlterColumn extends SchemaCommand { ...@@ -492,7 +504,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
} }
} }
private void checkNoNullValues() { private void checkNoNullValues(Table table) {
String sql = "SELECT COUNT(*) FROM " + String sql = "SELECT COUNT(*) FROM " +
table.getSQL() + " WHERE " + table.getSQL() + " WHERE " +
oldColumn.getSQL() + " IS NULL"; oldColumn.getSQL() + " IS NULL";
......
...@@ -20,7 +20,8 @@ import org.h2.table.Table; ...@@ -20,7 +20,8 @@ import org.h2.table.Table;
*/ */
public class AlterTableRename extends SchemaCommand { public class AlterTableRename extends SchemaCommand {
private Table oldTable; private boolean ifTableExists;
private String oldTableName;
private String newTableName; private String newTableName;
private boolean hidden; private boolean hidden;
...@@ -28,8 +29,12 @@ public class AlterTableRename extends SchemaCommand { ...@@ -28,8 +29,12 @@ public class AlterTableRename extends SchemaCommand {
super(session, schema); super(session, schema);
} }
public void setOldTable(Table table) { public void setIfTableExists(boolean b) {
oldTable = table; ifTableExists = b;
}
public void setOldTableName(String name) {
oldTableName = name;
} }
public void setNewTableName(String name) { public void setNewTableName(String name) {
...@@ -40,6 +45,13 @@ public class AlterTableRename extends SchemaCommand { ...@@ -40,6 +45,13 @@ public class AlterTableRename extends SchemaCommand {
public int update() { public int update() {
session.commit(true); session.commit(true);
Database db = session.getDatabase(); Database db = session.getDatabase();
Table oldTable = getSchema().findTableOrView(session, oldTableName);
if (oldTable == null) {
if (ifTableExists) {
return 0;
}
throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, oldTableName);
}
session.getUser().checkRight(oldTable, Right.ALL); session.getUser().checkRight(oldTable, Right.ALL);
Table t = getSchema().findTableOrView(session, newTableName); Table t = getSchema().findTableOrView(session, newTableName);
if (t != null && hidden && newTableName.equals(oldTable.getName())) { if (t != null && hidden && newTableName.equals(oldTable.getName())) {
......
...@@ -5,12 +5,15 @@ ...@@ -5,12 +5,15 @@
*/ */
package org.h2.command.ddl; package org.h2.command.ddl;
import org.h2.api.ErrorCode;
import org.h2.command.CommandInterface; import org.h2.command.CommandInterface;
import org.h2.engine.Database; import org.h2.engine.Database;
import org.h2.engine.DbObject; import org.h2.engine.DbObject;
import org.h2.engine.Right; import org.h2.engine.Right;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.expression.Expression; import org.h2.expression.Expression;
import org.h2.message.DbException;
import org.h2.schema.Schema;
import org.h2.table.Column; import org.h2.table.Column;
import org.h2.table.Table; import org.h2.table.Table;
...@@ -18,22 +21,27 @@ import org.h2.table.Table; ...@@ -18,22 +21,27 @@ import org.h2.table.Table;
* This class represents the statement * This class represents the statement
* ALTER TABLE ALTER COLUMN RENAME * ALTER TABLE ALTER COLUMN RENAME
*/ */
public class AlterTableRenameColumn extends DefineCommand { public class AlterTableRenameColumn extends SchemaCommand {
private Table table; private boolean ifTableExists;
private Column column; private String tableName;
private String oldName;
private String newName; private String newName;
public AlterTableRenameColumn(Session session) { public AlterTableRenameColumn(Session session, Schema schema) {
super(session); super(session, schema);
} }
public void setTable(Table table) { public void setIfTableExists(boolean b) {
this.table = table; this.ifTableExists = b;
} }
public void setColumn(Column column) { public void setTableName(String tableName) {
this.column = column; this.tableName = tableName;
}
public void setOldColumnName(String oldName) {
this.oldName = oldName;
} }
public void setNewColumnName(String newName) { public void setNewColumnName(String newName) {
...@@ -44,6 +52,14 @@ public class AlterTableRenameColumn extends DefineCommand { ...@@ -44,6 +52,14 @@ public class AlterTableRenameColumn extends DefineCommand {
public int update() { public int update() {
session.commit(true); session.commit(true);
Database db = session.getDatabase(); Database db = session.getDatabase();
Table table = getSchema().findTableOrView(session, tableName);
if (table == null) {
if (ifTableExists) {
return 0;
}
throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, tableName);
}
Column column = table.getColumn(oldName);
session.getUser().checkRight(table, Right.ALL); session.getUser().checkRight(table, Right.ALL);
table.checkSupportAlter(); table.checkSupportAlter();
// we need to update CHECK constraint // we need to update CHECK constraint
......
...@@ -27,6 +27,7 @@ public class CreateIndex extends SchemaCommand { ...@@ -27,6 +27,7 @@ public class CreateIndex extends SchemaCommand {
private String indexName; private String indexName;
private IndexColumn[] indexColumns; private IndexColumn[] indexColumns;
private boolean primaryKey, unique, hash, spatial; private boolean primaryKey, unique, hash, spatial;
private boolean ifTableExists;
private boolean ifNotExists; private boolean ifNotExists;
private String comment; private String comment;
...@@ -34,6 +35,10 @@ public class CreateIndex extends SchemaCommand { ...@@ -34,6 +35,10 @@ public class CreateIndex extends SchemaCommand {
super(session, schema); super(session, schema);
} }
public void setIfTableExists(boolean b) {
this.ifTableExists = b;
}
public void setIfNotExists(boolean ifNotExists) { public void setIfNotExists(boolean ifNotExists) {
this.ifNotExists = ifNotExists; this.ifNotExists = ifNotExists;
} }
...@@ -57,7 +62,13 @@ public class CreateIndex extends SchemaCommand { ...@@ -57,7 +62,13 @@ public class CreateIndex extends SchemaCommand {
} }
Database db = session.getDatabase(); Database db = session.getDatabase();
boolean persistent = db.isPersistent(); boolean persistent = db.isPersistent();
Table table = getSchema().getTableOrView(session, tableName); Table table = getSchema().findTableOrView(session, tableName);
if (table == null) {
if (ifTableExists) {
return 0;
}
throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, tableName);
}
if (getSchema().findIndex(session, indexName) != null) { if (getSchema().findIndex(session, indexName) != null) {
if (ifNotExists) { if (ifNotExists) {
return 0; return 0;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
*/ */
package org.h2.command.dml; package org.h2.command.dml;
import org.h2.api.ErrorCode;
import org.h2.command.CommandInterface; import org.h2.command.CommandInterface;
import org.h2.command.ddl.SchemaCommand; import org.h2.command.ddl.SchemaCommand;
import org.h2.engine.Right; import org.h2.engine.Right;
...@@ -19,6 +20,7 @@ import org.h2.table.Table; ...@@ -19,6 +20,7 @@ import org.h2.table.Table;
*/ */
public class AlterTableSet extends SchemaCommand { public class AlterTableSet extends SchemaCommand {
private boolean ifTableExists;
private String tableName; private String tableName;
private final int type; private final int type;
...@@ -40,13 +42,23 @@ public class AlterTableSet extends SchemaCommand { ...@@ -40,13 +42,23 @@ public class AlterTableSet extends SchemaCommand {
return true; return true;
} }
public void setIfTableExists(boolean b) {
this.ifTableExists = b;
}
public void setTableName(String tableName) { public void setTableName(String tableName) {
this.tableName = tableName; this.tableName = tableName;
} }
@Override @Override
public int update() { public int update() {
Table table = getSchema().getTableOrView(session, tableName); Table table = getSchema().findTableOrView(session, tableName);
if (table == null) {
if (ifTableExists) {
return 0;
}
throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, tableName);
}
session.getUser().checkRight(table, Right.ALL); session.getUser().checkRight(table, Right.ALL);
table.lock(session, true, true); table.lock(session, true, true);
switch (type) { switch (type) {
......
...@@ -10227,3 +10227,207 @@ select 0 from (( ...@@ -10227,3 +10227,207 @@ select 0 from ((
> rows: 0 > rows: 0
}; };
> update count: 0 > update count: 0
create table x(id int not null);
> ok
alter table if exists y add column a varchar;
> ok
alter table if exists x add column a varchar;
> ok
alter table if exists x add column a varchar;
> exception
alter table if exists y alter column a rename to b;
> ok
alter table if exists x alter column a rename to b;
> ok
alter table if exists x alter column a rename to b;
> exception
alter table if exists y alter column b set default 'a';
> ok
alter table if exists x alter column b set default 'a';
> ok
insert into x(id) values(1);
> update count: 1
select b from x;
> B
> -
> a
> rows: 1
delete from x;
> update count: 1
alter table if exists y alter column b drop default;
> ok
alter table if exists x alter column b drop default;
> ok
alter table if exists y alter column b set not null;
> ok
alter table if exists x alter column b set not null;
> ok
insert into x(id) values(1);
> exception
alter table if exists y alter column b drop not null;
> ok
alter table if exists x alter column b drop not null;
> ok
insert into x(id) values(1);
> update count: 1
select b from x;
> B
> ----
> null
> rows: 1
delete from x;
> update count: 1
alter table if exists y add constraint x_pk primary key (id);
> ok
alter table if exists x add constraint x_pk primary key (id);
> ok
alter table if exists x add constraint x_pk primary key (id);
> exception
insert into x(id) values(1);
> update count: 1
insert into x(id) values(1);
> exception
delete from x;
> update count: 1
alter table if exists y add constraint x_chk check (b = 'a');
> ok
alter table if exists x add constraint x_chk check (b = 'a');
> ok
alter table if exists x add constraint x_chk check (b = 'a');
> exception
insert into x(id, b) values(1, 'b');
> exception
alter table if exists y rename constraint x_chk to x_chk1;
> ok
alter table if exists x rename constraint x_chk to x_chk1;
> ok
alter table if exists x rename constraint x_chk to x_chk1;
> exception
alter table if exists y drop constraint x_chk1;
> ok
alter table if exists x drop constraint x_chk1;
> ok
alter table if exists y rename to z;
> ok
alter table if exists x rename to z;
> ok
alter table if exists x rename to z;
> ok
insert into z(id, b) values(1, 'b');
> update count: 1
delete from z;
> update count: 1
alter table if exists y add constraint z_uk unique (b);
> ok
alter table if exists z add constraint z_uk unique (b);
> ok
alter table if exists z add constraint z_uk unique (b);
> exception
insert into z(id, b) values(1, 'b');
> update count: 1
insert into z(id, b) values(1, 'b');
> exception
delete from z;
> update count: 1
alter table if exists y drop column b;
> ok
alter table if exists z drop column b;
> ok
alter table if exists z drop column b;
> exception
alter table if exists y drop primary key;
> ok
alter table if exists z drop primary key;
> ok
alter table if exists z drop primary key;
> exception
create table x (id int not null primary key);
> ok
alter table if exists y add constraint z_fk foreign key (id) references x (id);
> ok
alter table if exists z add constraint z_fk foreign key (id) references x (id);
> ok
alter table if exists z add constraint z_fk foreign key (id) references x (id);
> exception
insert into z (id) values (1);
> exception
alter table if exists y drop foreign key z_fk;
> ok
alter table if exists z drop foreign key z_fk;
> ok
alter table if exists z drop foreign key z_fk;
> exception
insert into z (id) values (1);
> update count: 1
delete from z;
> update count: 1
drop table x;
> ok
drop table z;
> ok
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论