use of org.h2.index.IndexType in project h2database by h2database.
the class AlterTableAddConstraint method tryUpdate.
/**
* Try to execute the statement.
*
* @return the update count
*/
private int tryUpdate() {
if (!transactional) {
session.commit(true);
}
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);
}
if (getSchema().findConstraint(session, constraintName) != null) {
if (ifNotExists) {
return 0;
}
throw DbException.get(ErrorCode.CONSTRAINT_ALREADY_EXISTS_1, constraintName);
}
session.getUser().checkRight(table, Right.ALL);
db.lockMeta(session);
table.lock(session, true, true);
Constraint constraint;
switch(type) {
case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_PRIMARY_KEY:
{
IndexColumn.mapColumns(indexColumns, table);
index = table.findPrimaryKey();
ArrayList<Constraint> constraints = table.getConstraints();
for (int i = 0; constraints != null && i < constraints.size(); i++) {
Constraint c = constraints.get(i);
if (Constraint.Type.PRIMARY_KEY == c.getConstraintType()) {
throw DbException.get(ErrorCode.SECOND_PRIMARY_KEY);
}
}
if (index != null) {
// if there is an index, it must match with the one declared
// we don't test ascending / descending
IndexColumn[] pkCols = index.getIndexColumns();
if (pkCols.length != indexColumns.length) {
throw DbException.get(ErrorCode.SECOND_PRIMARY_KEY);
}
for (int i = 0; i < pkCols.length; i++) {
if (pkCols[i].column != indexColumns[i].column) {
throw DbException.get(ErrorCode.SECOND_PRIMARY_KEY);
}
}
}
if (index == null) {
IndexType indexType = IndexType.createPrimaryKey(table.isPersistIndexes(), primaryKeyHash);
String indexName = table.getSchema().getUniqueIndexName(session, table, Constants.PREFIX_PRIMARY_KEY);
int id = getObjectId();
try {
index = table.addIndex(session, indexName, id, indexColumns, indexType, true, null);
} finally {
getSchema().freeUniqueName(indexName);
}
}
index.getIndexType().setBelongsToConstraint(true);
int constraintId = getObjectId();
String name = generateConstraintName(table);
ConstraintUnique pk = new ConstraintUnique(getSchema(), constraintId, name, table, true);
pk.setColumns(indexColumns);
pk.setIndex(index, true);
constraint = pk;
break;
}
case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_UNIQUE:
{
IndexColumn.mapColumns(indexColumns, table);
boolean isOwner = false;
if (index != null && canUseUniqueIndex(index, table, indexColumns)) {
isOwner = true;
index.getIndexType().setBelongsToConstraint(true);
} else {
index = getUniqueIndex(table, indexColumns);
if (index == null) {
index = createIndex(table, indexColumns, true);
isOwner = true;
}
}
int id = getObjectId();
String name = generateConstraintName(table);
ConstraintUnique unique = new ConstraintUnique(getSchema(), id, name, table, false);
unique.setColumns(indexColumns);
unique.setIndex(index, isOwner);
constraint = unique;
break;
}
case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_CHECK:
{
int id = getObjectId();
String name = generateConstraintName(table);
ConstraintCheck check = new ConstraintCheck(getSchema(), id, name, table);
TableFilter filter = new TableFilter(session, table, null, false, null, 0, null);
checkExpression.mapColumns(filter, 0);
checkExpression = checkExpression.optimize(session);
check.setExpression(checkExpression);
check.setTableFilter(filter);
constraint = check;
if (checkExisting) {
check.checkExistingData(session);
}
break;
}
case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_REFERENTIAL:
{
Table refTable = refSchema.resolveTableOrView(session, refTableName);
if (refTable == null) {
throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, refTableName);
}
session.getUser().checkRight(refTable, Right.ALL);
if (!refTable.canReference()) {
throw DbException.getUnsupportedException("Reference " + refTable.getSQL());
}
boolean isOwner = false;
IndexColumn.mapColumns(indexColumns, table);
if (index != null && canUseIndex(index, table, indexColumns, false)) {
isOwner = true;
index.getIndexType().setBelongsToConstraint(true);
} else {
index = getIndex(table, indexColumns, false);
if (index == null) {
index = createIndex(table, indexColumns, false);
isOwner = true;
}
}
if (refIndexColumns == null) {
Index refIdx = refTable.getPrimaryKey();
refIndexColumns = refIdx.getIndexColumns();
} else {
IndexColumn.mapColumns(refIndexColumns, refTable);
}
if (refIndexColumns.length != indexColumns.length) {
throw DbException.get(ErrorCode.COLUMN_COUNT_DOES_NOT_MATCH);
}
boolean isRefOwner = false;
if (refIndex != null && refIndex.getTable() == refTable && canUseIndex(refIndex, refTable, refIndexColumns, false)) {
isRefOwner = true;
refIndex.getIndexType().setBelongsToConstraint(true);
} else {
refIndex = null;
}
if (refIndex == null) {
refIndex = getIndex(refTable, refIndexColumns, false);
if (refIndex == null) {
refIndex = createIndex(refTable, refIndexColumns, true);
isRefOwner = true;
}
}
int id = getObjectId();
String name = generateConstraintName(table);
ConstraintReferential refConstraint = new ConstraintReferential(getSchema(), id, name, table);
refConstraint.setColumns(indexColumns);
refConstraint.setIndex(index, isOwner);
refConstraint.setRefTable(refTable);
refConstraint.setRefColumns(refIndexColumns);
refConstraint.setRefIndex(refIndex, isRefOwner);
if (checkExisting) {
refConstraint.checkExistingData(session);
}
refTable.addConstraint(refConstraint);
refConstraint.setDeleteAction(deleteAction);
refConstraint.setUpdateAction(updateAction);
constraint = refConstraint;
break;
}
default:
throw DbException.throwInternalError("type=" + type);
}
// parent relationship is already set with addConstraint
constraint.setComment(comment);
if (table.isTemporary() && !table.isGlobalTemporary()) {
session.addLocalTempTableConstraint(constraint);
} else {
db.addSchemaObject(session, constraint);
}
table.addConstraint(constraint);
return 0;
}
use of org.h2.index.IndexType in project h2database by h2database.
the class Select method prepare.
@Override
public void prepare() {
if (isPrepared) {
// sometimes a subquery is prepared twice (CREATE TABLE AS SELECT)
return;
}
if (SysProperties.CHECK && !checkInit) {
DbException.throwInternalError("not initialized");
}
if (orderList != null) {
sort = prepareOrder(orderList, expressions.size());
orderList = null;
}
ColumnNamer columnNamer = new ColumnNamer(session);
for (int i = 0; i < expressions.size(); i++) {
Expression e = expressions.get(i);
String proposedColumnName = e.getAlias();
String columnName = columnNamer.getColumnName(e, i, proposedColumnName);
// if the name changed, create an alias
if (!columnName.equals(proposedColumnName)) {
e = new Alias(e, columnName, true);
}
expressions.set(i, e.optimize(session));
}
if (condition != null) {
condition = condition.optimize(session);
for (TableFilter f : filters) {
// left outer join child on p = pc where c is null;
if (!f.isJoinOuter() && !f.isJoinOuterIndirect()) {
condition.createIndexConditions(session, f);
}
}
}
if (isGroupQuery && groupIndex == null && havingIndex < 0 && filters.size() == 1) {
if (condition == null) {
Table t = filters.get(0).getTable();
ExpressionVisitor optimizable = ExpressionVisitor.getOptimizableVisitor(t);
isQuickAggregateQuery = isEverything(optimizable);
}
}
cost = preparePlan(session.isParsingCreateView());
if (distinct && session.getDatabase().getSettings().optimizeDistinct && !isGroupQuery && filters.size() == 1 && expressions.size() == 1 && condition == null) {
Expression expr = expressions.get(0);
expr = expr.getNonAliasExpression();
if (expr instanceof ExpressionColumn) {
Column column = ((ExpressionColumn) expr).getColumn();
int selectivity = column.getSelectivity();
Index columnIndex = topTableFilter.getTable().getIndexForColumn(column, false, true);
if (columnIndex != null && selectivity != Constants.SELECTIVITY_DEFAULT && selectivity < 20) {
// the first column must be ascending
boolean ascending = columnIndex.getIndexColumns()[0].sortType == SortOrder.ASCENDING;
Index current = topTableFilter.getIndex();
// if another index is faster
if (columnIndex.canFindNext() && ascending && (current == null || current.getIndexType().isScan() || columnIndex == current)) {
IndexType type = columnIndex.getIndexType();
// indexes don't work
if (!type.isHash() && (!type.isUnique() || columnIndex.getColumns().length > 1)) {
topTableFilter.setIndex(columnIndex);
isDistinctQuery = true;
}
}
}
}
}
if (sort != null && !isQuickAggregateQuery && !isGroupQuery) {
Index index = getSortIndex();
Index current = topTableFilter.getIndex();
if (index != null && current != null) {
if (current.getIndexType().isScan() || current == index) {
topTableFilter.setIndex(index);
if (!topTableFilter.hasInComparisons()) {
// in(select ...) and in(1,2,3) may return the key in
// another order
sortUsingIndex = true;
}
} else if (index.getIndexColumns() != null && index.getIndexColumns().length >= current.getIndexColumns().length) {
IndexColumn[] sortColumns = index.getIndexColumns();
IndexColumn[] currentColumns = current.getIndexColumns();
boolean swapIndex = false;
for (int i = 0; i < currentColumns.length; i++) {
if (sortColumns[i].column != currentColumns[i].column) {
swapIndex = false;
break;
}
if (sortColumns[i].sortType != currentColumns[i].sortType) {
swapIndex = true;
}
}
if (swapIndex) {
topTableFilter.setIndex(index);
sortUsingIndex = true;
}
}
}
}
if (!isQuickAggregateQuery && isGroupQuery && getGroupByExpressionCount() > 0) {
Index index = getGroupSortedIndex();
Index current = topTableFilter.getIndex();
if (index != null && current != null && (current.getIndexType().isScan() || current == index)) {
topTableFilter.setIndex(index);
isGroupSortedQuery = true;
}
}
expressionArray = expressions.toArray(new Expression[0]);
isPrepared = true;
}
use of org.h2.index.IndexType in project h2database by h2database.
the class BaseIndex method initBaseIndex.
/**
* Initialize the base index.
*
* @param newTable the table
* @param id the object id
* @param name the index name
* @param newIndexColumns the columns that are indexed or null if this is
* not yet known
* @param newIndexType the index type
*/
protected void initBaseIndex(Table newTable, int id, String name, IndexColumn[] newIndexColumns, IndexType newIndexType) {
initSchemaObjectBase(newTable.getSchema(), id, name, Trace.INDEX);
this.indexType = newIndexType;
this.table = newTable;
if (newIndexColumns != null) {
this.indexColumns = newIndexColumns;
columns = new Column[newIndexColumns.length];
int len = columns.length;
columnIds = new int[len];
for (int i = 0; i < len; i++) {
Column col = newIndexColumns[i].column;
columns[i] = col;
columnIds[i] = col.getColumnId();
}
}
}
use of org.h2.index.IndexType in project h2database by h2database.
the class PageStore method addMeta.
private void addMeta(Row row, Session session, boolean redo) {
int id = row.getValue(0).getInt();
int type = row.getValue(1).getInt();
int parent = row.getValue(2).getInt();
int rootPageId = row.getValue(3).getInt();
String[] options = StringUtils.arraySplit(row.getValue(4).getString(), ',', false);
String columnList = row.getValue(5).getString();
String[] columns = StringUtils.arraySplit(columnList, ',', false);
Index meta;
if (trace.isDebugEnabled()) {
trace.debug("addMeta id=" + id + " type=" + type + " root=" + rootPageId + " parent=" + parent + " columns=" + columnList);
}
if (redo && rootPageId != 0) {
// ensure the page is empty, but not used by regular data
writePage(rootPageId, createData());
allocatePage(rootPageId);
}
metaRootPageId.put(id, rootPageId);
if (type == META_TYPE_DATA_INDEX) {
CreateTableData data = new CreateTableData();
if (SysProperties.CHECK) {
if (columns == null) {
throw DbException.throwInternalError(row.toString());
}
}
for (int i = 0, len = columns.length; i < len; i++) {
Column col = new Column("C" + i, Value.INT);
data.columns.add(col);
}
data.schema = metaSchema;
data.tableName = "T" + id;
data.id = id;
data.temporary = options[2].equals("temp");
data.persistData = true;
data.persistIndexes = true;
data.create = false;
data.session = session;
RegularTable table = new RegularTable(data);
boolean binaryUnsigned = SysProperties.SORT_BINARY_UNSIGNED;
if (options.length > 3) {
binaryUnsigned = Boolean.parseBoolean(options[3]);
}
CompareMode mode = CompareMode.getInstance(options[0], Integer.parseInt(options[1]), binaryUnsigned);
table.setCompareMode(mode);
meta = table.getScanIndex(session);
} else {
Index p = metaObjects.get(parent);
if (p == null) {
throw DbException.get(ErrorCode.FILE_CORRUPTED_1, "Table not found:" + parent + " for " + row + " meta:" + metaObjects);
}
RegularTable table = (RegularTable) p.getTable();
Column[] tableCols = table.getColumns();
int len = columns.length;
IndexColumn[] cols = new IndexColumn[len];
for (int i = 0; i < len; i++) {
String c = columns[i];
IndexColumn ic = new IndexColumn();
int idx = c.indexOf('/');
if (idx >= 0) {
String s = c.substring(idx + 1);
ic.sortType = Integer.parseInt(s);
c = c.substring(0, idx);
}
ic.column = tableCols[Integer.parseInt(c)];
cols[i] = ic;
}
IndexType indexType;
if (options[3].equals("d")) {
indexType = IndexType.createPrimaryKey(true, false);
Column[] tableColumns = table.getColumns();
for (IndexColumn indexColumn : cols) {
tableColumns[indexColumn.column.getColumnId()].setNullable(false);
}
} else {
indexType = IndexType.createNonUnique(true);
}
meta = table.addIndex(session, "I" + id, id, cols, indexType, false, null);
}
PageIndex index;
if (meta instanceof MultiVersionIndex) {
index = (PageIndex) ((MultiVersionIndex) meta).getBaseIndex();
} else {
index = (PageIndex) meta;
}
metaObjects.put(id, index);
}
use of org.h2.index.IndexType in project h2database by h2database.
the class ResultTempTable method createIndex.
private void createIndex() {
IndexColumn[] indexCols = null;
// sort columns. So we need to disregard the sort. Not ideal.
if (sort != null && !distinct) {
int[] colIndex = sort.getQueryColumnIndexes();
indexCols = new IndexColumn[colIndex.length];
for (int i = 0; i < colIndex.length; i++) {
IndexColumn indexColumn = new IndexColumn();
indexColumn.column = table.getColumn(colIndex[i]);
indexColumn.sortType = sort.getSortTypes()[i];
indexColumn.columnName = COLUMN_NAME + i;
indexCols[i] = indexColumn;
}
} else {
indexCols = new IndexColumn[columnCount];
for (int i = 0; i < columnCount; i++) {
IndexColumn indexColumn = new IndexColumn();
indexColumn.column = table.getColumn(i);
indexColumn.columnName = COLUMN_NAME + i;
indexCols[i] = indexColumn;
}
}
String indexName = table.getSchema().getUniqueIndexName(session, table, Constants.PREFIX_INDEX);
int indexId = session.getDatabase().allocateObjectId();
IndexType indexType = IndexType.createNonUnique(true);
index = table.addIndex(session, indexName, indexId, indexCols, indexType, true, null);
}
Aggregations