Search in sources :

Example 1 with IndexType

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;
}
Also used : Table(org.h2.table.Table) Constraint(org.h2.constraint.Constraint) TableFilter(org.h2.table.TableFilter) Database(org.h2.engine.Database) ArrayList(java.util.ArrayList) ConstraintUnique(org.h2.constraint.ConstraintUnique) Index(org.h2.index.Index) ConstraintCheck(org.h2.constraint.ConstraintCheck) IndexType(org.h2.index.IndexType) ConstraintReferential(org.h2.constraint.ConstraintReferential)

Example 2 with IndexType

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;
}
Also used : Index(org.h2.index.Index) IndexType(org.h2.index.IndexType)

Example 3 with IndexType

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();
        }
    }
}
Also used : Column(org.h2.table.Column) IndexColumn(org.h2.table.IndexColumn)

Example 4 with IndexType

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);
}
Also used : Index(org.h2.index.Index) PageIndex(org.h2.index.PageIndex) PageDelegateIndex(org.h2.index.PageDelegateIndex) MultiVersionIndex(org.h2.index.MultiVersionIndex) PageBtreeIndex(org.h2.index.PageBtreeIndex) PageDataIndex(org.h2.index.PageDataIndex) ValueString(org.h2.value.ValueString) PageIndex(org.h2.index.PageIndex) CreateTableData(org.h2.command.ddl.CreateTableData) IndexColumn(org.h2.table.IndexColumn) IndexColumn(org.h2.table.IndexColumn) Column(org.h2.table.Column) MultiVersionIndex(org.h2.index.MultiVersionIndex) RegularTable(org.h2.table.RegularTable) CompareMode(org.h2.value.CompareMode) IndexType(org.h2.index.IndexType)

Example 5 with IndexType

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);
}
Also used : IndexType(org.h2.index.IndexType) IndexColumn(org.h2.table.IndexColumn)

Aggregations

IndexType (org.h2.index.IndexType)8 Index (org.h2.index.Index)6 IndexColumn (org.h2.table.IndexColumn)5 Constraint (org.h2.constraint.Constraint)4 Column (org.h2.table.Column)3 ArrayList (java.util.ArrayList)2 Database (org.h2.engine.Database)2 LinkedIndex (org.h2.index.LinkedIndex)2 MultiVersionIndex (org.h2.index.MultiVersionIndex)2 PageBtreeIndex (org.h2.index.PageBtreeIndex)2 PageDataIndex (org.h2.index.PageDataIndex)2 PageDelegateIndex (org.h2.index.PageDelegateIndex)2 DbException (org.h2.message.DbException)2 DatabaseMetaData (java.sql.DatabaseMetaData)1 PreparedStatement (java.sql.PreparedStatement)1 ResultSet (java.sql.ResultSet)1 ResultSetMetaData (java.sql.ResultSetMetaData)1 SQLException (java.sql.SQLException)1 Statement (java.sql.Statement)1 HashMap (java.util.HashMap)1