Unverified 提交 a55fda66 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov 提交者: GitHub

Merge pull request #1329 from katzyn/ddl

Allow creation of delegate index in ALTER TABLE
......@@ -14,6 +14,7 @@ import org.h2.command.Parser;
import org.h2.command.Prepared;
import org.h2.constraint.Constraint;
import org.h2.constraint.ConstraintReferential;
import org.h2.constraint.ConstraintUnique;
import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.engine.DbObject;
......@@ -25,13 +26,16 @@ import org.h2.index.Index;
import org.h2.index.IndexType;
import org.h2.message.DbException;
import org.h2.result.ResultInterface;
import org.h2.result.SearchRow;
import org.h2.schema.Schema;
import org.h2.schema.SchemaObject;
import org.h2.schema.Sequence;
import org.h2.schema.TriggerObject;
import org.h2.table.Column;
import org.h2.table.Table;
import org.h2.table.TableBase;
import org.h2.table.TableView;
import org.h2.util.Utils;
/**
* This class represents the statements
......@@ -392,8 +396,7 @@ public class AlterTableAlterColumn extends CommandWithColumns {
data.session = session;
Table newTable = getSchema().createTable(data);
newTable.setComment(table.getComment());
StringBuilder buff = new StringBuilder();
buff.append(newTable.getCreateSQL());
String newTableSQL = newTable.getCreateSQL();
StringBuilder columnList = new StringBuilder();
for (Column nc : newColumns) {
if (columnList.length() > 0) {
......@@ -407,22 +410,15 @@ public class AlterTableAlterColumn extends CommandWithColumns {
columnList.append(nc.getSQL());
}
}
buff.append(" AS SELECT ");
if (columnList.length() == 0) {
// special case: insert into test select * from
buff.append('*');
} else {
buff.append(columnList);
}
buff.append(" FROM ").append(table.getSQL());
String newTableSQL = buff.toString();
String newTableName = newTable.getName();
Schema newTableSchema = newTable.getSchema();
newTable.removeChildrenAndResources(session);
execute(newTableSQL, true);
newTable = newTableSchema.getTableOrView(session, newTableName);
ArrayList<String> triggers = new ArrayList<>();
ArrayList<String> children = Utils.newSmallArrayList();
ArrayList<String> triggers = Utils.newSmallArrayList();
boolean hasDelegateIndex = false;
for (DbObject child : table.getChildren()) {
if (child instanceof Sequence) {
continue;
......@@ -456,10 +452,49 @@ public class AlterTableAlterColumn extends CommandWithColumns {
if (child instanceof TriggerObject) {
triggers.add(sql);
} else {
execute(sql, true);
if (!hasDelegateIndex) {
Index index = null;
if (child instanceof ConstraintUnique) {
ConstraintUnique constraint = (ConstraintUnique) child;
if (constraint.getConstraintType() == Constraint.Type.PRIMARY_KEY) {
index = constraint.getUniqueIndex();
}
} else if (child instanceof Index) {
index = (Index) child;
}
if (index != null
&& TableBase.getMainIndexColumn(index.getIndexType(), index.getIndexColumns())
!= SearchRow.ROWID_INDEX) {
execute(sql, true);
hasDelegateIndex = true;
continue;
}
}
children.add(sql);
}
}
}
StringBuilder buff = new StringBuilder();
buff.append("INSERT INTO ").append(newTable.getSQL());
buff.append(" SELECT ");
if (columnList.length() == 0) {
// special case: insert into test select * from
buff.append('*');
} else {
buff.append(columnList);
}
buff.append(" FROM ").append(table.getSQL());
try {
execute(buff.toString(), true);
} catch (Throwable t) {
// data was not inserted due to data conversion error or some
// unexpected reason
execute("DROP TABLE " + newTable.getSQL(), true);
throw t;
}
for (String sql : children) {
execute(sql, true);
}
table.setModified();
// remove the sequences from the columns (except dropped columns)
// otherwise the sequence is dropped if the table is dropped
......
......@@ -35,7 +35,6 @@ import org.h2.mvstore.tx.Transaction;
import org.h2.mvstore.tx.TransactionStore;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.result.SortOrder;
import org.h2.schema.SchemaObject;
import org.h2.table.Column;
import org.h2.table.IndexColumn;
......@@ -504,8 +503,8 @@ public class MVTable extends TableBase {
database.lockMeta(session);
}
MVIndex index;
int mainIndexColumn;
mainIndexColumn = getMainIndexColumn(indexType, cols);
int mainIndexColumn = primaryIndex.getMainIndexColumn() != SearchRow.ROWID_INDEX
? SearchRow.ROWID_INDEX : getMainIndexColumn(indexType, cols);
if (database.isStarting()) {
if (transactionStore.hasMap("index." + indexId)) {
mainIndexColumn = SearchRow.ROWID_INDEX;
......@@ -646,29 +645,6 @@ public class MVTable extends TableBase {
}
}
private int getMainIndexColumn(IndexType indexType, IndexColumn[] cols) {
if (primaryIndex.getMainIndexColumn() != SearchRow.ROWID_INDEX) {
return SearchRow.ROWID_INDEX;
}
if (!indexType.isPrimaryKey() || cols.length != 1) {
return SearchRow.ROWID_INDEX;
}
IndexColumn first = cols[0];
if (first.sortType != SortOrder.ASCENDING) {
return SearchRow.ROWID_INDEX;
}
switch (first.column.getType()) {
case Value.BYTE:
case Value.SHORT:
case Value.INT:
case Value.LONG:
break;
default:
return SearchRow.ROWID_INDEX;
}
return first.column.getColumnId();
}
private static void addRowsToIndex(Session session, ArrayList<Row> list,
Index index) {
sortRows(list, index);
......
......@@ -36,7 +36,6 @@ import org.h2.index.TreeIndex;
import org.h2.message.DbException;
import org.h2.message.Trace;
import org.h2.result.Row;
import org.h2.result.SortOrder;
import org.h2.schema.SchemaObject;
import org.h2.util.MathUtils;
import org.h2.util.Utils;
......@@ -199,7 +198,8 @@ public class RegularTable extends TableBase {
if (database.isStarting() &&
database.getPageStore().getRootPageId(indexId) != 0) {
mainIndexColumn = -1;
} else if (!database.isStarting() && mainIndex.getRowCount(session) != 0) {
} else if (!database.isStarting() && mainIndex.getRowCount(session) != 0
|| mainIndex.getMainIndexColumn() != -1) {
mainIndexColumn = -1;
} else {
mainIndexColumn = getMainIndexColumn(indexType, cols);
......@@ -289,29 +289,6 @@ public class RegularTable extends TableBase {
return index;
}
private int getMainIndexColumn(IndexType indexType, IndexColumn[] cols) {
if (mainIndex.getMainIndexColumn() != -1) {
return -1;
}
if (!indexType.isPrimaryKey() || cols.length != 1) {
return -1;
}
IndexColumn first = cols[0];
if (first.sortType != SortOrder.ASCENDING) {
return -1;
}
switch (first.column.getType()) {
case Value.BYTE:
case Value.SHORT:
case Value.INT:
case Value.LONG:
break;
default:
return -1;
}
return first.column.getColumnId();
}
@Override
public boolean canGetRowCount() {
return true;
......
......@@ -10,9 +10,13 @@ import java.util.List;
import org.h2.command.ddl.CreateTableData;
import org.h2.engine.Database;
import org.h2.engine.DbSettings;
import org.h2.index.IndexType;
import org.h2.mvstore.db.MVTableEngine;
import org.h2.result.SearchRow;
import org.h2.result.SortOrder;
import org.h2.util.StatementBuilder;
import org.h2.util.StringUtils;
import org.h2.value.Value;
/**
* The base class of a regular table, or a user defined table.
......@@ -31,6 +35,33 @@ public abstract class TableBase extends Table {
private final boolean globalTemporary;
/**
* Returns main index column if index is an primary key index and has only
* one column with _ROWID_ compatible data type.
*
* @param indexType type of an index
* @param cols columns of the index
* @return main index column or {@link SearchRow#ROWID_INDEX}
*/
public static int getMainIndexColumn(IndexType indexType, IndexColumn[] cols) {
if (!indexType.isPrimaryKey() || cols.length != 1) {
return SearchRow.ROWID_INDEX;
}
IndexColumn first = cols[0];
if (first.sortType != SortOrder.ASCENDING) {
return SearchRow.ROWID_INDEX;
}
switch (first.column.getType()) {
case Value.BYTE:
case Value.SHORT:
case Value.INT:
case Value.LONG:
return first.column.getColumnId();
default:
return SearchRow.ROWID_INDEX;
}
}
public TableBase(CreateTableData data) {
super(data.schema, data.id, data.tableName,
data.persistIndexes, data.persistData);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论