Search in sources :

Example 31 with IndexColumn

use of org.h2.table.IndexColumn in project ignite by apache.

the class H2Utils method unwrapKeyColumns.

/**
 * Create list of index columns. Where possible _KEY columns will be unwrapped.
 *
 * @param tbl GridH2Table instance
 * @param idxCols List of index columns.
 *
 * @return Array of key and affinity columns. Key's, if it possible, splitted into simple components.
 */
@NotNull
public static IndexColumn[] unwrapKeyColumns(GridH2Table tbl, IndexColumn[] idxCols) {
    ArrayList<IndexColumn> keyCols = new ArrayList<>();
    boolean isSql = tbl.rowDescriptor().tableDescriptor().sql();
    if (!isSql)
        return idxCols;
    GridQueryTypeDescriptor type = tbl.rowDescriptor().type();
    for (IndexColumn idxCol : idxCols) {
        if (idxCol.column.getColumnId() == KEY_COL) {
            if (QueryUtils.isSqlType(type.keyClass())) {
                int altKeyColId = tbl.rowDescriptor().getAlternativeColumnId(QueryUtils.KEY_COL);
                // Remap simple key to alternative column.
                IndexColumn idxKeyCol = new IndexColumn();
                idxKeyCol.column = tbl.getColumn(altKeyColId);
                idxKeyCol.columnName = idxKeyCol.column.getName();
                idxKeyCol.sortType = idxCol.sortType;
                keyCols.add(idxKeyCol);
            } else {
                boolean added = false;
                for (String propName : type.fields().keySet()) {
                    GridQueryProperty prop = type.property(propName);
                    if (prop.key()) {
                        added = true;
                        Column col = tbl.getColumn(propName);
                        keyCols.add(tbl.indexColumn(col.getColumnId(), SortOrder.ASCENDING));
                    }
                }
                // we have to fall back to whole-key index.
                if (!added)
                    keyCols.add(idxCol);
            }
        } else
            keyCols.add(idxCol);
    }
    return keyCols.toArray(new IndexColumn[0]);
}
Also used : GridQueryProperty(org.apache.ignite.internal.processors.query.GridQueryProperty) IndexColumn(org.h2.table.IndexColumn) Column(org.h2.table.Column) ArrayList(java.util.ArrayList) ValueString(org.h2.value.ValueString) IndexColumn(org.h2.table.IndexColumn) GridQueryTypeDescriptor(org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor) NotNull(org.jetbrains.annotations.NotNull)

Example 32 with IndexColumn

use of org.h2.table.IndexColumn in project ignite by apache.

the class H2Utils method indexColumnsSql.

/**
 * Generate String represenation of given indexed columns.
 *
 * @param idxCols Indexed columns.
 * @return String represenation of given indexed columns.
 */
public static String indexColumnsSql(IndexColumn[] idxCols) {
    GridStringBuilder sb = new SB();
    boolean first = true;
    for (IndexColumn col : idxCols) {
        if (first)
            first = false;
        else
            sb.a(", ");
        sb.a(withQuotes(col.columnName)).a(" ").a(col.sortType == SortOrder.ASCENDING ? "ASC" : "DESC");
    }
    return sb.toString();
}
Also used : GridStringBuilder(org.apache.ignite.internal.util.GridStringBuilder) SB(org.apache.ignite.internal.util.typedef.internal.SB) IndexColumn(org.h2.table.IndexColumn)

Example 33 with IndexColumn

use of org.h2.table.IndexColumn in project ignite by apache.

the class H2TableDescriptor method createUserIndex.

/**
 * Create user index.
 *
 * @param idxDesc Index descriptor.
 * @param cacheVisitor Cache visitor.
 * @return Index.
 */
public GridH2IndexBase createUserIndex(GridQueryIndexDescriptor idxDesc, @Nullable SchemaIndexCacheVisitor cacheVisitor) {
    IndexColumn keyCol = tbl.indexColumn(QueryUtils.KEY_COL, SortOrder.ASCENDING);
    IndexColumn affCol = tbl.getAffinityKeyColumn();
    List<IndexColumn> cols = new ArrayList<>(idxDesc.fields().size() + 2);
    for (String field : idxDesc.fields()) {
        Column col = tbl.getColumn(field);
        cols.add(tbl.indexColumn(col.getColumnId(), idxDesc.descending(field) ? SortOrder.DESCENDING : SortOrder.ASCENDING));
    }
    GridH2RowDescriptor desc = tbl.rowDescriptor();
    if (idxDesc.type() == QueryIndexType.SORTED) {
        List<IndexColumn> unwrappedKeyCols = extractKeyColumns(tbl, keyCol, affCol);
        List<IndexColumn> colsWithUnwrappedKey = new ArrayList<>(cols);
        H2Utils.addUniqueColumns(colsWithUnwrappedKey, unwrappedKeyCols);
        cols = H2Utils.treeIndexColumns(desc, cols, keyCol, affCol);
        return idx.createSortedIndex(idxDesc.name(), tbl, false, false, colsWithUnwrappedKey, cols, idxDesc.inlineSize(), cacheVisitor);
    } else if (idxDesc.type() == QueryIndexType.GEOSPATIAL)
        return H2Utils.createSpatialIndex(tbl, idxDesc.name(), cols);
    throw new IllegalStateException("Index type: " + idxDesc.type());
}
Also used : GridH2RowDescriptor(org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor) Column(org.h2.table.Column) IndexColumn(org.h2.table.IndexColumn) ArrayList(java.util.ArrayList) IndexColumn(org.h2.table.IndexColumn)

Example 34 with IndexColumn

use of org.h2.table.IndexColumn in project ignite by apache.

the class H2TableDescriptor method createSystemIndexes.

/**
 * Create list of indexes. First must be primary key, after that all unique indexes and only then non-unique
 * indexes. All indexes must be subtypes of {@link H2TreeIndexBase}.
 *
 * @param tbl Table to create indexes for.
 * @return List of indexes.
 */
public ArrayList<Index> createSystemIndexes(GridH2Table tbl) {
    ArrayList<Index> idxs = new ArrayList<>();
    IndexColumn keyCol = tbl.indexColumn(QueryUtils.KEY_COL, SortOrder.ASCENDING);
    IndexColumn affCol = tbl.getAffinityKeyColumn();
    if (affCol != null && H2Utils.equals(affCol, keyCol))
        affCol = null;
    List<IndexColumn> unwrappedKeyAndAffinityCols = extractKeyColumns(tbl, keyCol, affCol);
    List<IndexColumn> wrappedKeyCols = H2Utils.treeIndexColumns(tbl.rowDescriptor(), new ArrayList<>(2), keyCol, affCol);
    Index hashIdx = createHashIndex(tbl, wrappedKeyCols);
    if (hashIdx != null)
        idxs.add(hashIdx);
    // Add primary key index.
    Index pkIdx = idx.createSortedIndex(PK_IDX_NAME, tbl, true, false, unwrappedKeyAndAffinityCols, wrappedKeyCols, tbl.rowDescriptor().tableDescriptor().type().primaryKeyInlineSize(), null);
    idxs.add(pkIdx);
    if (type().valueClass() == String.class && !idx.distributedConfiguration().isDisableCreateLuceneIndexForStringValueType()) {
        try {
            luceneIdx = new GridLuceneIndex(idx.kernalContext(), tbl.cacheName(), type);
        } catch (IgniteCheckedException e1) {
            throw new IgniteException(e1);
        }
    }
    GridQueryIndexDescriptor textIdx = type.textIndex();
    if (textIdx != null) {
        try {
            luceneIdx = new GridLuceneIndex(idx.kernalContext(), tbl.cacheName(), type);
        } catch (IgniteCheckedException e1) {
            throw new IgniteException(e1);
        }
    }
    // Locate index where affinity column is first (if any).
    if (affCol != null) {
        boolean affIdxFound = false;
        for (GridQueryIndexDescriptor idxDesc : type.indexes().values()) {
            if (idxDesc.type() != QueryIndexType.SORTED)
                continue;
            String firstField = idxDesc.fields().iterator().next();
            Column col = tbl.getColumn(firstField);
            IndexColumn idxCol = tbl.indexColumn(col.getColumnId(), idxDesc.descending(firstField) ? SortOrder.DESCENDING : SortOrder.ASCENDING);
            affIdxFound |= H2Utils.equals(idxCol, affCol);
        }
        // Add explicit affinity key index if nothing alike was found.
        if (!affIdxFound) {
            List<IndexColumn> unwrappedKeyCols = extractKeyColumns(tbl, keyCol, null);
            ArrayList<IndexColumn> colsWithUnwrappedKey = new ArrayList<>(unwrappedKeyCols.size());
            colsWithUnwrappedKey.add(affCol);
            // We need to reorder PK columns to have affinity key as first column, that's why we can't use simple PK columns
            H2Utils.addUniqueColumns(colsWithUnwrappedKey, unwrappedKeyCols);
            List<IndexColumn> cols = H2Utils.treeIndexColumns(tbl.rowDescriptor(), new ArrayList<>(2), affCol, keyCol);
            idxs.add(idx.createSortedIndex(AFFINITY_KEY_IDX_NAME, tbl, false, true, colsWithUnwrappedKey, cols, tbl.rowDescriptor().tableDescriptor().type().affinityFieldInlineSize(), null));
        }
    }
    return idxs;
}
Also used : ArrayList(java.util.ArrayList) GridLuceneIndex(org.apache.ignite.internal.processors.query.h2.opt.GridLuceneIndex) GridLuceneIndex(org.apache.ignite.internal.processors.query.h2.opt.GridLuceneIndex) Index(org.h2.index.Index) H2PkHashIndex(org.apache.ignite.internal.processors.query.h2.database.H2PkHashIndex) IndexColumn(org.h2.table.IndexColumn) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) Column(org.h2.table.Column) IndexColumn(org.h2.table.IndexColumn) IgniteException(org.apache.ignite.IgniteException) GridQueryIndexDescriptor(org.apache.ignite.internal.processors.query.GridQueryIndexDescriptor)

Example 35 with IndexColumn

use of org.h2.table.IndexColumn in project ignite by apache.

the class GridSqlQueryParser method parseCreateTable.

/**
 * Parse {@code CREATE TABLE} statement.
 *
 * @param createTbl {@code CREATE TABLE} statement.
 * @see <a href="http://h2database.com/html/grammar.html#create_table">H2 {@code CREATE TABLE} spec.</a>
 */
private GridSqlCreateTable parseCreateTable(CreateTable createTbl) {
    GridSqlCreateTable res = new GridSqlCreateTable();
    res.templateName(QueryUtils.TEMPLATE_PARTITIONED);
    Query qry = CREATE_TABLE_QUERY.get(createTbl);
    if (qry != null) {
        throw new IgniteSQLException("CREATE TABLE ... AS ... syntax is not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
    }
    List<DefineCommand> constraints = CREATE_TABLE_CONSTRAINTS.get(createTbl);
    if (F.isEmpty(constraints)) {
        throw new IgniteSQLException("No PRIMARY KEY defined for CREATE TABLE", IgniteQueryErrorCode.PARSING);
    }
    if (constraints.size() > 1) {
        throw new IgniteSQLException("Too many constraints - only PRIMARY KEY is supported for CREATE TABLE", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
    }
    DefineCommand constraint = constraints.get(0);
    if (!(constraint instanceof AlterTableAddConstraint)) {
        throw new IgniteSQLException("Unsupported type of constraint for CREATE TABLE - only PRIMARY KEY " + "is supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
    }
    AlterTableAddConstraint alterTbl = (AlterTableAddConstraint) constraint;
    if (alterTbl.getType() != Command.ALTER_TABLE_ADD_CONSTRAINT_PRIMARY_KEY) {
        throw new IgniteSQLException("Unsupported type of constraint for CREATE TABLE - only PRIMARY KEY " + "is supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
    }
    Schema schema = SCHEMA_COMMAND_SCHEMA.get(createTbl);
    res.schemaName(schema.getName());
    CreateTableData data = CREATE_TABLE_DATA.get(createTbl);
    if (data.globalTemporary) {
        throw new IgniteSQLException("GLOBAL TEMPORARY keyword is not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
    }
    if (data.temporary) {
        throw new IgniteSQLException("TEMPORARY keyword is not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
    }
    if (data.isHidden) {
        throw new IgniteSQLException("HIDDEN keyword is not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
    }
    if (!data.persistIndexes) {
        throw new IgniteSQLException("MEMORY and NOT PERSISTENT keywords are not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
    }
    LinkedHashMap<String, GridSqlColumn> cols = new LinkedHashMap<>(data.columns.size());
    for (Column col : data.columns) {
        if (cols.put(col.getName(), parseColumn(col)) != null)
            throw new IgniteSQLException("Duplicate column name: " + col.getName(), IgniteQueryErrorCode.PARSING);
    }
    if (cols.containsKey(QueryUtils.KEY_FIELD_NAME.toUpperCase()) || cols.containsKey(QueryUtils.VAL_FIELD_NAME.toUpperCase())) {
        throw new IgniteSQLException("Direct specification of _KEY and _VAL columns is forbidden", IgniteQueryErrorCode.PARSING);
    }
    IndexColumn[] pkIdxCols = CREATE_TABLE_PK.get(createTbl);
    if (F.isEmpty(pkIdxCols))
        throw new AssertionError("No PRIMARY KEY columns specified");
    LinkedHashSet<String> pkCols = new LinkedHashSet<>();
    for (IndexColumn pkIdxCol : pkIdxCols) {
        GridSqlColumn gridCol = cols.get(pkIdxCol.columnName);
        if (gridCol == null) {
            throw new IgniteSQLException("PRIMARY KEY column is not defined: " + pkIdxCol.columnName, IgniteQueryErrorCode.PARSING);
        }
        pkCols.add(gridCol.columnName());
    }
    int keyColsNum = pkCols.size();
    int valColsNum = cols.size() - keyColsNum;
    if (valColsNum == 0) {
        throw new IgniteSQLException("Table must have at least one non PRIMARY KEY column.", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
    }
    res.columns(cols);
    res.primaryKeyColumns(pkCols);
    res.tableName(data.tableName);
    res.ifNotExists(CREATE_TABLE_IF_NOT_EXISTS.get(createTbl));
    List<String> extraParams = data.tableEngineParams != null ? new ArrayList<String>() : null;
    if (data.tableEngineParams != null)
        for (String s : data.tableEngineParams) extraParams.addAll(F.asList(s.split(",")));
    res.params(extraParams);
    if (!F.isEmpty(extraParams)) {
        Map<String, String> params = new HashMap<>();
        for (String p : extraParams) {
            String[] parts = p.split(PARAM_NAME_VALUE_SEPARATOR);
            if (parts.length > 2) {
                throw new IgniteSQLException("Invalid parameter (key[=value] expected): " + p, IgniteQueryErrorCode.PARSING);
            }
            String name = parts[0].trim().toUpperCase();
            String val = parts.length > 1 ? parts[1].trim() : null;
            if (F.isEmpty(name)) {
                throw new IgniteSQLException("Invalid parameter (key[=value] expected): " + p, IgniteQueryErrorCode.PARSING);
            }
            if (params.put(name, val) != null)
                throw new IgniteSQLException("Duplicate parameter: " + p, IgniteQueryErrorCode.PARSING);
        }
        for (Map.Entry<String, String> e : params.entrySet()) processExtraParam(e.getKey(), e.getValue(), res);
    }
    // Process key wrapping.
    Boolean wrapKey = res.wrapKey();
    if (wrapKey != null && !wrapKey) {
        if (keyColsNum > 1) {
            throw new IgniteSQLException(PARAM_WRAP_KEY + " cannot be false when composite primary key exists.", IgniteQueryErrorCode.PARSING);
        }
        if (!F.isEmpty(res.keyTypeName())) {
            throw new IgniteSQLException(PARAM_WRAP_KEY + " cannot be false when " + PARAM_KEY_TYPE + " is set.", IgniteQueryErrorCode.PARSING);
        }
    }
    boolean wrapKey0 = (res.wrapKey() != null && res.wrapKey()) || !F.isEmpty(res.keyTypeName()) || keyColsNum > 1;
    res.wrapKey(wrapKey0);
    // Process value wrapping.
    Boolean wrapVal = res.wrapValue();
    if (wrapVal != null && !wrapVal) {
        if (valColsNum > 1) {
            throw new IgniteSQLException(PARAM_WRAP_VALUE + " cannot be false when multiple non-primary key " + "columns exist.", IgniteQueryErrorCode.PARSING);
        }
        if (!F.isEmpty(res.valueTypeName())) {
            throw new IgniteSQLException(PARAM_WRAP_VALUE + " cannot be false when " + PARAM_VAL_TYPE + " is set.", IgniteQueryErrorCode.PARSING);
        }
        res.wrapValue(false);
    } else
        // By default value is always wrapped to allow for ALTER TABLE ADD COLUMN commands.
        res.wrapValue(true);
    if (!F.isEmpty(res.valueTypeName()) && F.eq(res.keyTypeName(), res.valueTypeName())) {
        throw new IgniteSQLException("Key and value type names " + "should be different for CREATE TABLE: " + res.valueTypeName(), IgniteQueryErrorCode.PARSING);
    }
    if (res.affinityKey() == null) {
        LinkedHashSet<String> pkCols0 = res.primaryKeyColumns();
        if (!F.isEmpty(pkCols0) && pkCols0.size() == 1 && wrapKey0)
            res.affinityKey(pkCols0.iterator().next());
    }
    return res;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Query(org.h2.command.dml.Query) LinkedHashMap(java.util.LinkedHashMap) IdentityHashMap(java.util.IdentityHashMap) HashMap(java.util.HashMap) Schema(org.h2.schema.Schema) DefineCommand(org.h2.command.ddl.DefineCommand) LinkedHashMap(java.util.LinkedHashMap) IndexColumn(org.h2.table.IndexColumn) GridSqlType.fromColumn(org.apache.ignite.internal.processors.query.h2.sql.GridSqlType.fromColumn) AlterTableAlterColumn(org.h2.command.ddl.AlterTableAlterColumn) Column(org.h2.table.Column) ExpressionColumn(org.h2.expression.ExpressionColumn) IndexColumn(org.h2.table.IndexColumn) AlterTableAddConstraint(org.h2.command.ddl.AlterTableAddConstraint) CreateTableData(org.h2.command.ddl.CreateTableData) AlterTableAddConstraint(org.h2.command.ddl.AlterTableAddConstraint) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) IdentityHashMap(java.util.IdentityHashMap) HashMap(java.util.HashMap)

Aggregations

IndexColumn (org.h2.table.IndexColumn)53 Column (org.h2.table.Column)23 ArrayList (java.util.ArrayList)14 Index (org.h2.index.Index)12 Value (org.h2.value.Value)12 IndexType (org.h2.index.IndexType)9 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)7 Constraint (org.h2.constraint.Constraint)6 ExpressionColumn (org.h2.expression.ExpressionColumn)6 LinkedHashMap (java.util.LinkedHashMap)5 CacheException (javax.cache.CacheException)5 TableFilter (org.h2.table.TableFilter)5 StatementBuilder (org.h2.util.StatementBuilder)5 ValueString (org.h2.value.ValueString)5 HashMap (java.util.HashMap)4 H2TreeIndex (org.apache.ignite.internal.processors.query.h2.database.H2TreeIndex)4 H2TreeIndexBase (org.apache.ignite.internal.processors.query.h2.database.H2TreeIndexBase)4 GridH2Table (org.apache.ignite.internal.processors.query.h2.opt.GridH2Table)4 Row (org.h2.result.Row)4 ResultSet (java.sql.ResultSet)3