提交 86462170 authored 作者: Noel Grandin's avatar Noel Grandin

Add support for dropping multiple columns in ALTER TABLE DROP COLUMN...

上级 7014d46a
......@@ -289,12 +289,13 @@ ALTER TABLE TEST ALTER COLUMN NAME SET NULL;
"
"Commands (DDL)","ALTER TABLE DROP COLUMN","
ALTER TABLE tableName DROP COLUMN [ IF EXISTS ] columnName
ALTER TABLE tableName DROP COLUMN [ IF EXISTS ] ( columnName [,...] )
","
Removes a column from a table.
Removes column(s) from a table.
This command commits an open transaction in this connection.
","
ALTER TABLE TEST DROP COLUMN NAME
ALTER TABLE TEST DROP COLUMN NAME1, NAME2
"
"Commands (DDL)","ALTER TABLE DROP CONSTRAINT","
......
......@@ -27,6 +27,8 @@ Change Log
<h2>Version 1.4.189 Beta (2015-09-13)</h2>
<ul>
<li>Add support for dropping multiple columns in ALTER TABLE DROP COLUMN...
</li>
<li>Fix bug in XA management when doing rollback after prepare. Patch by Stephane Lacoin.
</li>
<li>MVStore CLOB and BLOB: An exception with the message "Block not found" could be thrown
......
......@@ -5415,12 +5415,17 @@ public class Parser {
AlterTableAlterColumn command = new AlterTableAlterColumn(
session, table.getSchema());
command.setType(CommandInterface.ALTER_TABLE_DROP_COLUMN);
String columnName = readColumnIdentifier();
ArrayList<Column> columnsToRemove = New.arrayList();
do {
String columnName = readColumnIdentifier();
if (ifExists && !table.doesColumnExist(columnName)) {
return new NoOperation(session);
}
Column column = table.getColumn(columnName);
columnsToRemove.add(column);
} while (readIf(","));
command.setTable(table);
if (ifExists && !table.doesColumnExist(columnName)) {
return new NoOperation(session);
}
command.setOldColumn(table.getColumn(columnName));
command.setColumnsToRemove(columnsToRemove);
return command;
}
} else if (readIf("CHANGE")) {
......
......@@ -7,7 +7,7 @@ package org.h2.command.ddl;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import org.h2.api.ErrorCode;
import org.h2.command.CommandInterface;
import org.h2.command.Parser;
......@@ -57,6 +57,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
private String addAfter;
private boolean ifNotExists;
private ArrayList<Column> columnsToAdd;
private ArrayList<Column> columnsToRemove;
public AlterTableAlterColumn(Session session, Schema schema) {
super(session, schema);
......@@ -85,7 +86,6 @@ public class AlterTableAlterColumn extends SchemaCommand {
session.getUser().checkRight(table, Right.ALL);
table.checkSupportAlter();
table.lock(session, true, true);
Sequence sequence = oldColumn == null ? null : oldColumn.getSequence();
if (newColumn != null) {
checkDefaultReferencesTable(newColumn.getDefaultExpression());
}
......@@ -116,6 +116,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
break;
}
case CommandInterface.ALTER_TABLE_ALTER_COLUMN_DEFAULT: {
Sequence sequence = oldColumn == null ? null : oldColumn.getSequence();
checkDefaultReferencesTable(defaultExpression);
oldColumn.setSequence(null);
oldColumn.setDefaultExpression(session, defaultExpression);
......@@ -162,11 +163,11 @@ public class AlterTableAlterColumn extends SchemaCommand {
break;
}
case CommandInterface.ALTER_TABLE_DROP_COLUMN: {
if (table.getColumns().length == 1) {
if (table.getColumns().length - columnsToRemove.size() < 1) {
throw DbException.get(ErrorCode.CANNOT_DROP_LAST_COLUMN,
oldColumn.getSQL());
columnsToRemove.get(0).getSQL());
}
table.dropSingleColumnConstraintsAndIndexes(session, oldColumn);
table.dropMultipleColumnsConstraintsAndIndexes(session, columnsToRemove);
copyData();
break;
}
......@@ -282,8 +283,20 @@ public class AlterTableAlterColumn extends SchemaCommand {
newColumns.add(col.getClone());
}
if (type == CommandInterface.ALTER_TABLE_DROP_COLUMN) {
int position = oldColumn.getColumnId();
newColumns.remove(position);
for (Column removeCol : columnsToRemove) {
Column foundCol = null;
for (Iterator<Column> iter = newColumns.iterator(); iter.hasNext(); ) {
Column newCol = iter.next();
if (newCol.getName() == removeCol.getName()) {
foundCol = newCol;
break;
}
}
if (foundCol == null) {
throw DbException.throwInternalError(removeCol.getCreateSQL());
}
newColumns.remove(foundCol);
}
} else if (type == CommandInterface.ALTER_TABLE_ADD_COLUMN) {
int position;
if (addBefore != null) {
......@@ -509,4 +522,8 @@ public class AlterTableAlterColumn extends SchemaCommand {
public void setNewColumns(ArrayList<Column> columnsToAdd) {
this.columnsToAdd = columnsToAdd;
}
public void setColumnsToRemove(ArrayList<Column> columnsToRemove) {
this.columnsToRemove = columnsToRemove;
}
}
......@@ -9,7 +9,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import org.h2.api.ErrorCode;
import org.h2.command.Prepared;
import org.h2.constraint.Constraint;
......@@ -531,49 +530,53 @@ public abstract class Table extends SchemaObjectBase {
}
/**
* Check that this column is not referenced by a multi-column constraint or
* Check that these columns are not referenced by a multi-column constraint or
* multi-column index. If it is, an exception is thrown. Single-column
* references and indexes are dropped.
*
* @param session the session
* @param col the column
* @param columsToDrop the columns to drop
* @throws DbException if the column is referenced by multi-column
* constraints or indexes
*/
public void dropSingleColumnConstraintsAndIndexes(Session session,
Column col) {
ArrayList<Constraint> constraintsToDrop = New.arrayList();
public void dropMultipleColumnsConstraintsAndIndexes(Session session,
ArrayList<Column> columsToDrop) {
HashSet<Constraint> constraintsToDrop = New.hashSet();
if (constraints != null) {
for (int i = 0, size = constraints.size(); i < size; i++) {
Constraint constraint = constraints.get(i);
HashSet<Column> columns = constraint.getReferencedColumns(this);
if (!columns.contains(col)) {
continue;
}
if (columns.size() == 1) {
constraintsToDrop.add(constraint);
} else {
throw DbException.get(
ErrorCode.COLUMN_IS_REFERENCED_1, constraint.getSQL());
for (Column col : columsToDrop) {
for (int i = 0, size = constraints.size(); i < size; i++) {
Constraint constraint = constraints.get(i);
HashSet<Column> columns = constraint.getReferencedColumns(this);
if (!columns.contains(col)) {
continue;
}
if (columns.size() == 1) {
constraintsToDrop.add(constraint);
} else {
throw DbException.get(
ErrorCode.COLUMN_IS_REFERENCED_1, constraint.getSQL());
}
}
}
}
ArrayList<Index> indexesToDrop = New.arrayList();
HashSet<Index> indexesToDrop = New.hashSet();
ArrayList<Index> indexes = getIndexes();
if (indexes != null) {
for (int i = 0, size = indexes.size(); i < size; i++) {
Index index = indexes.get(i);
if (index.getCreateSQL() == null) {
continue;
}
if (index.getColumnIndex(col) < 0) {
continue;
}
if (index.getColumns().length == 1) {
indexesToDrop.add(index);
} else {
throw DbException.get(
ErrorCode.COLUMN_IS_REFERENCED_1, index.getSQL());
for (Column col : columsToDrop) {
for (int i = 0, size = indexes.size(); i < size; i++) {
Index index = indexes.get(i);
if (index.getCreateSQL() == null) {
continue;
}
if (index.getColumnIndex(col) < 0) {
continue;
}
if (index.getColumns().length == 1) {
indexesToDrop.add(index);
} else {
throw DbException.get(
ErrorCode.COLUMN_IS_REFERENCED_1, index.getSQL());
}
}
}
}
......
......@@ -10,7 +10,6 @@ import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.h2.api.ErrorCode;
import org.h2.test.TestBase;
......@@ -38,6 +37,7 @@ public class TestAlter extends TestBase {
stat = conn.createStatement();
testAlterTableAlterColumnAsSelfColumn();
testAlterTableDropColumnWithReferences();
testAlterTableDropMultipleColumns();
testAlterTableAlterColumnWithConstraint();
testAlterTableAlterColumn();
testAlterTableAddColumnIdentity();
......@@ -108,6 +108,17 @@ public class TestAlter extends TestBase {
}
private void testAlterTableDropMultipleColumns() throws SQLException {
stat.execute("create table test(id int, name varchar, name2 varchar)");
stat.execute("alter table test drop column name, name2");
stat.execute("drop table test");
stat.execute("create table test(id int, name varchar, name2 varchar)");
assertThrows(ErrorCode.CANNOT_DROP_LAST_COLUMN, stat).
execute("alter table test drop column id, name, name2");
stat.execute("drop table test");
}
/**
* Tests a bug we used to have where altering the name of a column that had
* a check constraint that referenced itself would result in not being able
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论