Search in sources :

Example 6 with IndexType

use of org.h2.index.IndexType in project h2database by h2database.

the class TableLink method readMetaData.

private void readMetaData() throws SQLException {
    DatabaseMetaData meta = conn.getConnection().getMetaData();
    storesLowerCase = meta.storesLowerCaseIdentifiers();
    storesMixedCase = meta.storesMixedCaseIdentifiers();
    storesMixedCaseQuoted = meta.storesMixedCaseQuotedIdentifiers();
    supportsMixedCaseIdentifiers = meta.supportsMixedCaseIdentifiers();
    ResultSet rs = meta.getTables(null, originalSchema, originalTable, null);
    if (rs.next() && rs.next()) {
        throw DbException.get(ErrorCode.SCHEMA_NAME_MUST_MATCH, originalTable);
    }
    rs.close();
    rs = meta.getColumns(null, originalSchema, originalTable, null);
    int i = 0;
    ArrayList<Column> columnList = New.arrayList();
    HashMap<String, Column> columnMap = new HashMap<>();
    String catalog = null, schema = null;
    while (rs.next()) {
        String thisCatalog = rs.getString("TABLE_CAT");
        if (catalog == null) {
            catalog = thisCatalog;
        }
        String thisSchema = rs.getString("TABLE_SCHEM");
        if (schema == null) {
            schema = thisSchema;
        }
        if (!Objects.equals(catalog, thisCatalog) || !Objects.equals(schema, thisSchema)) {
            // if the table exists in multiple schemas or tables,
            // use the alternative solution
            columnMap.clear();
            columnList.clear();
            break;
        }
        String n = rs.getString("COLUMN_NAME");
        n = convertColumnName(n);
        int sqlType = rs.getInt("DATA_TYPE");
        String sqlTypeName = rs.getString("TYPE_NAME");
        long precision = rs.getInt("COLUMN_SIZE");
        precision = convertPrecision(sqlType, precision);
        int scale = rs.getInt("DECIMAL_DIGITS");
        scale = convertScale(sqlType, scale);
        int displaySize = MathUtils.convertLongToInt(precision);
        int type = DataType.convertSQLTypeToValueType(sqlType, sqlTypeName);
        Column col = new Column(n, type, precision, scale, displaySize);
        col.setTable(this, i++);
        columnList.add(col);
        columnMap.put(n, col);
    }
    rs.close();
    if (originalTable.indexOf('.') < 0 && !StringUtils.isNullOrEmpty(schema)) {
        qualifiedTableName = schema + "." + originalTable;
    } else {
        qualifiedTableName = originalTable;
    }
    try (Statement stat = conn.getConnection().createStatement()) {
        rs = stat.executeQuery("SELECT * FROM " + qualifiedTableName + " T WHERE 1=0");
        if (columnList.isEmpty()) {
            // alternative solution
            ResultSetMetaData rsMeta = rs.getMetaData();
            for (i = 0; i < rsMeta.getColumnCount(); ) {
                String n = rsMeta.getColumnName(i + 1);
                n = convertColumnName(n);
                int sqlType = rsMeta.getColumnType(i + 1);
                long precision = rsMeta.getPrecision(i + 1);
                precision = convertPrecision(sqlType, precision);
                int scale = rsMeta.getScale(i + 1);
                scale = convertScale(sqlType, scale);
                int displaySize = rsMeta.getColumnDisplaySize(i + 1);
                int type = DataType.getValueTypeFromResultSet(rsMeta, i + 1);
                Column col = new Column(n, type, precision, scale, displaySize);
                col.setTable(this, i++);
                columnList.add(col);
                columnMap.put(n, col);
            }
        }
        rs.close();
    } catch (Exception e) {
        throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, e, originalTable + "(" + e.toString() + ")");
    }
    Column[] cols = columnList.toArray(new Column[0]);
    setColumns(cols);
    int id = getId();
    linkedIndex = new LinkedIndex(this, id, IndexColumn.wrap(cols), IndexType.createNonUnique(false));
    indexes.add(linkedIndex);
    try {
        rs = meta.getPrimaryKeys(null, originalSchema, originalTable);
    } catch (Exception e) {
        // Some ODBC bridge drivers don't support it:
        // some combinations of "DataDirect SequeLink(R) for JDBC"
        // http://www.datadirect.com/index.ssp
        rs = null;
    }
    String pkName = "";
    ArrayList<Column> list;
    if (rs != null && rs.next()) {
        // the problem is, the rows are not sorted by KEY_SEQ
        list = New.arrayList();
        do {
            int idx = rs.getInt("KEY_SEQ");
            if (pkName == null) {
                pkName = rs.getString("PK_NAME");
            }
            while (list.size() < idx) {
                list.add(null);
            }
            String col = rs.getString("COLUMN_NAME");
            col = convertColumnName(col);
            Column column = columnMap.get(col);
            if (idx == 0) {
                // workaround for a bug in the SQLite JDBC driver
                list.add(column);
            } else {
                list.set(idx - 1, column);
            }
        } while (rs.next());
        addIndex(list, IndexType.createPrimaryKey(false, false));
        rs.close();
    }
    try {
        rs = meta.getIndexInfo(null, originalSchema, originalTable, false, true);
    } catch (Exception e) {
        // Oracle throws an exception if the table is not found or is a
        // SYNONYM
        rs = null;
    }
    String indexName = null;
    list = New.arrayList();
    IndexType indexType = null;
    if (rs != null) {
        while (rs.next()) {
            if (rs.getShort("TYPE") == DatabaseMetaData.tableIndexStatistic) {
                // ignore index statistics
                continue;
            }
            String newIndex = rs.getString("INDEX_NAME");
            if (pkName.equals(newIndex)) {
                continue;
            }
            if (indexName != null && !indexName.equals(newIndex)) {
                addIndex(list, indexType);
                indexName = null;
            }
            if (indexName == null) {
                indexName = newIndex;
                list.clear();
            }
            boolean unique = !rs.getBoolean("NON_UNIQUE");
            indexType = unique ? IndexType.createUnique(false, false) : IndexType.createNonUnique(false);
            String col = rs.getString("COLUMN_NAME");
            col = convertColumnName(col);
            Column column = columnMap.get(col);
            list.add(column);
        }
        rs.close();
    }
    if (indexName != null) {
        addIndex(list, indexType);
    }
}
Also used : HashMap(java.util.HashMap) LinkedIndex(org.h2.index.LinkedIndex) PreparedStatement(java.sql.PreparedStatement) Statement(java.sql.Statement) DatabaseMetaData(java.sql.DatabaseMetaData) DbException(org.h2.message.DbException) SQLException(java.sql.SQLException) JdbcSQLException(org.h2.jdbc.JdbcSQLException) ResultSetMetaData(java.sql.ResultSetMetaData) ResultSet(java.sql.ResultSet) IndexType(org.h2.index.IndexType)

Example 7 with IndexType

use of org.h2.index.IndexType in project h2database by h2database.

the class RegularTable method addIndex.

@Override
public Index addIndex(Session session, String indexName, int indexId, IndexColumn[] cols, IndexType indexType, boolean create, String indexComment) {
    if (indexType.isPrimaryKey()) {
        for (IndexColumn c : cols) {
            Column column = c.column;
            if (column.isNullable()) {
                throw DbException.get(ErrorCode.COLUMN_MUST_NOT_BE_NULLABLE_1, column.getName());
            }
            column.setPrimaryKey(true);
        }
    }
    boolean isSessionTemporary = isTemporary() && !isGlobalTemporary();
    if (!isSessionTemporary) {
        database.lockMeta(session);
    }
    Index index;
    if (isPersistIndexes() && indexType.isPersistent()) {
        int mainIndexColumn;
        if (database.isStarting() && database.getPageStore().getRootPageId(indexId) != 0) {
            mainIndexColumn = -1;
        } else if (!database.isStarting() && mainIndex.getRowCount(session) != 0) {
            mainIndexColumn = -1;
        } else {
            mainIndexColumn = getMainIndexColumn(indexType, cols);
        }
        if (mainIndexColumn != -1) {
            mainIndex.setMainIndexColumn(mainIndexColumn);
            index = new PageDelegateIndex(this, indexId, indexName, indexType, mainIndex, create, session);
        } else if (indexType.isSpatial()) {
            index = new SpatialTreeIndex(this, indexId, indexName, cols, indexType, true, create, session);
        } else {
            index = new PageBtreeIndex(this, indexId, indexName, cols, indexType, create, session);
        }
    } else {
        if (indexType.isHash()) {
            if (cols.length != 1) {
                throw DbException.getUnsupportedException("hash indexes may index only one column");
            }
            if (indexType.isUnique()) {
                index = new HashIndex(this, indexId, indexName, cols, indexType);
            } else {
                index = new NonUniqueHashIndex(this, indexId, indexName, cols, indexType);
            }
        } else if (indexType.isSpatial()) {
            index = new SpatialTreeIndex(this, indexId, indexName, cols, indexType, false, true, session);
        } else {
            index = new TreeIndex(this, indexId, indexName, cols, indexType);
        }
    }
    if (database.isMultiVersion()) {
        index = new MultiVersionIndex(index, this);
    }
    if (index.needRebuild() && rowCount > 0) {
        try {
            Index scan = getScanIndex(session);
            long remaining = scan.getRowCount(session);
            long total = remaining;
            Cursor cursor = scan.find(session, null, null);
            long i = 0;
            int bufferSize = (int) Math.min(rowCount, database.getMaxMemoryRows());
            ArrayList<Row> buffer = new ArrayList<>(bufferSize);
            String n = getName() + ":" + index.getName();
            int t = MathUtils.convertLongToInt(total);
            while (cursor.next()) {
                database.setProgress(DatabaseEventListener.STATE_CREATE_INDEX, n, MathUtils.convertLongToInt(i++), t);
                Row row = cursor.get();
                buffer.add(row);
                if (buffer.size() >= bufferSize) {
                    addRowsToIndex(session, buffer, index);
                }
                remaining--;
            }
            addRowsToIndex(session, buffer, index);
            if (SysProperties.CHECK && remaining != 0) {
                DbException.throwInternalError("rowcount remaining=" + remaining + " " + getName());
            }
        } catch (DbException e) {
            getSchema().freeUniqueName(indexName);
            try {
                index.remove(session);
            } catch (DbException e2) {
                // this could happen, for example on failure in the storage
                // but if that is not the case it means
                // there is something wrong with the database
                trace.error(e2, "could not remove index");
                throw e2;
            }
            throw e;
        }
    }
    index.setTemporary(isTemporary());
    if (index.getCreateSQL() != null) {
        index.setComment(indexComment);
        if (isSessionTemporary) {
            session.addLocalTempTableIndex(index);
        } else {
            database.addSchemaObject(session, index);
        }
    }
    indexes.add(index);
    setModified();
    return index;
}
Also used : SpatialTreeIndex(org.h2.index.SpatialTreeIndex) PageDelegateIndex(org.h2.index.PageDelegateIndex) NonUniqueHashIndex(org.h2.index.NonUniqueHashIndex) PageBtreeIndex(org.h2.index.PageBtreeIndex) ArrayList(java.util.ArrayList) NonUniqueHashIndex(org.h2.index.NonUniqueHashIndex) Index(org.h2.index.Index) HashIndex(org.h2.index.HashIndex) ScanIndex(org.h2.index.ScanIndex) PageBtreeIndex(org.h2.index.PageBtreeIndex) TreeIndex(org.h2.index.TreeIndex) PageDataIndex(org.h2.index.PageDataIndex) PageDelegateIndex(org.h2.index.PageDelegateIndex) MultiVersionIndex(org.h2.index.MultiVersionIndex) SpatialTreeIndex(org.h2.index.SpatialTreeIndex) NonUniqueHashIndex(org.h2.index.NonUniqueHashIndex) HashIndex(org.h2.index.HashIndex) Cursor(org.h2.index.Cursor) Constraint(org.h2.constraint.Constraint) DbException(org.h2.message.DbException) TreeIndex(org.h2.index.TreeIndex) SpatialTreeIndex(org.h2.index.SpatialTreeIndex) MultiVersionIndex(org.h2.index.MultiVersionIndex) Row(org.h2.result.Row)

Example 8 with IndexType

use of org.h2.index.IndexType in project h2database by h2database.

the class TableLink method addIndex.

private void addIndex(List<Column> list, IndexType indexType) {
    // bind the index to the leading recognized columns in the index
    // (null columns might come from a function-based index)
    int firstNull = list.indexOf(null);
    if (firstNull == 0) {
        trace.info("Omitting linked index - no recognized columns.");
        return;
    } else if (firstNull > 0) {
        trace.info("Unrecognized columns in linked index. " + "Registering the index against the leading {0} " + "recognized columns of {1} total columns.", firstNull, list.size());
        list = list.subList(0, firstNull);
    }
    Column[] cols = list.toArray(new Column[0]);
    Index index = new LinkedIndex(this, 0, IndexColumn.wrap(cols), indexType);
    indexes.add(index);
}
Also used : LinkedIndex(org.h2.index.LinkedIndex) Index(org.h2.index.Index) LinkedIndex(org.h2.index.LinkedIndex)

Example 9 with IndexType

use of org.h2.index.IndexType in project h2database by h2database.

the class AlterTableAddConstraint method createIndex.

private Index createIndex(Table t, IndexColumn[] cols, boolean unique) {
    int indexId = getObjectId();
    IndexType indexType;
    if (unique) {
        // for unique constraints
        indexType = IndexType.createUnique(t.isPersistIndexes(), false);
    } else {
        // constraints
        indexType = IndexType.createNonUnique(t.isPersistIndexes());
    }
    indexType.setBelongsToConstraint(true);
    String prefix = constraintName == null ? "CONSTRAINT" : constraintName;
    String indexName = t.getSchema().getUniqueIndexName(session, t, prefix + "_INDEX_");
    try {
        Index index = t.addIndex(session, indexName, indexId, cols, indexType, true, null);
        createdIndexes.add(index);
        return index;
    } finally {
        getSchema().freeUniqueName(indexName);
    }
}
Also used : Index(org.h2.index.Index) IndexType(org.h2.index.IndexType) Constraint(org.h2.constraint.Constraint)

Example 10 with IndexType

use of org.h2.index.IndexType in project h2database by h2database.

the class CreateIndex method update.

@Override
public int update() {
    if (!transactional) {
        session.commit(true);
    }
    Database db = session.getDatabase();
    boolean persistent = db.isPersistent();
    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 (ifNotExists) {
            return 0;
        }
        throw DbException.get(ErrorCode.INDEX_ALREADY_EXISTS_1, indexName);
    }
    session.getUser().checkRight(table, Right.ALL);
    table.lock(session, true, true);
    if (!table.isPersistIndexes()) {
        persistent = false;
    }
    int id = getObjectId();
    if (indexName == null) {
        if (primaryKey) {
            indexName = table.getSchema().getUniqueIndexName(session, table, Constants.PREFIX_PRIMARY_KEY);
        } else {
            indexName = table.getSchema().getUniqueIndexName(session, table, Constants.PREFIX_INDEX);
        }
    }
    IndexType indexType;
    if (primaryKey) {
        if (table.findPrimaryKey() != null) {
            throw DbException.get(ErrorCode.SECOND_PRIMARY_KEY);
        }
        indexType = IndexType.createPrimaryKey(persistent, hash);
    } else if (unique) {
        indexType = IndexType.createUnique(persistent, hash);
    } else if (affinity) {
        indexType = IndexType.createAffinity();
    } else {
        indexType = IndexType.createNonUnique(persistent, hash, spatial);
    }
    IndexColumn.mapColumns(indexColumns, table);
    table.addIndex(session, indexName, id, indexColumns, indexType, create, comment);
    return 0;
}
Also used : Table(org.h2.table.Table) Database(org.h2.engine.Database) IndexType(org.h2.index.IndexType)

Aggregations

IndexType (org.h2.index.IndexType)7 Index (org.h2.index.Index)6 Constraint (org.h2.constraint.Constraint)4 IndexColumn (org.h2.table.IndexColumn)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 Table (org.h2.table.Table)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