Search in sources :

Example 21 with GridH2Table

use of org.apache.ignite.internal.processors.query.h2.opt.GridH2Table in project ignite by apache.

the class PartitionExtractor method extractFromEqual.

/**
 * Extract partition information from equality.
 *
 * @param op Operation.
 * @param tblModel Table model.
 * @param disjunct Disjunction flag. When set possible join expression will not be processed.
 * @return Partition.
 */
private PartitionNode extractFromEqual(GridSqlOperation op, PartitionTableModel tblModel, boolean disjunct) throws IgniteCheckedException {
    assert op.operationType() == GridSqlOperationType.EQUAL;
    GridSqlElement left = op.child(0);
    GridSqlElement right = op.child(1);
    GridSqlColumn leftCol = unwrapColumn(left);
    if (leftCol == null)
        return PartitionAllNode.INSTANCE;
    if (!(leftCol.column().getTable() instanceof GridH2Table))
        return PartitionAllNode.INSTANCE;
    GridSqlConst rightConst;
    GridSqlParameter rightParam;
    if (right instanceof GridSqlConst) {
        rightConst = (GridSqlConst) right;
        rightParam = null;
    } else if (right instanceof GridSqlParameter) {
        rightConst = null;
        rightParam = (GridSqlParameter) right;
    } else {
        if (right instanceof GridSqlColumn) {
            if (!disjunct) {
                PartitionJoinCondition cond = parseJoinCondition(op);
                if (cond != null && !cond.cross())
                    tblModel.addJoin(cond);
            }
        }
        return PartitionAllNode.INSTANCE;
    }
    PartitionSingleNode part = extractSingle(leftCol, rightConst, rightParam, tblModel);
    return part != null ? part : PartitionAllNode.INSTANCE;
}
Also used : PartitionJoinCondition(org.apache.ignite.internal.sql.optimizer.affinity.PartitionJoinCondition) GridSqlConst(org.apache.ignite.internal.processors.query.h2.sql.GridSqlConst) GridSqlColumn(org.apache.ignite.internal.processors.query.h2.sql.GridSqlColumn) GridH2Table(org.apache.ignite.internal.processors.query.h2.opt.GridH2Table) GridSqlElement(org.apache.ignite.internal.processors.query.h2.sql.GridSqlElement) GridSqlParameter(org.apache.ignite.internal.processors.query.h2.sql.GridSqlParameter) PartitionSingleNode(org.apache.ignite.internal.sql.optimizer.affinity.PartitionSingleNode)

Example 22 with GridH2Table

use of org.apache.ignite.internal.processors.query.h2.opt.GridH2Table in project ignite by apache.

the class PartitionExtractor method tryExtractBetween.

/**
 * Try to extract partitions from {@code op} assuming that it's between operation or simple range.
 *
 * @param op Sql operation.
 * @param tblModel Table model.
 * @return {@code PartitionSingleNode} if operation reduced to one partition,
 *   {@code PartitionGroupNode} if operation reduced to multiple partitions or null if operation is neither
 *   between nor simple range. Null also returns if it's not possible to extract partitions from given operation.
 * @throws IgniteCheckedException If failed.
 */
private PartitionNode tryExtractBetween(GridSqlOperation op, PartitionTableModel tblModel) throws IgniteCheckedException {
    // Between operation (or similar range) should contain exact two children.
    assert op.size() == 2;
    GridSqlAst left = op.child();
    GridSqlAst right = op.child(1);
    GridSqlOperationType leftOpType = retrieveOperationType(left);
    GridSqlOperationType rightOpType = retrieveOperationType(right);
    if ((GridSqlOperationType.BIGGER == rightOpType || GridSqlOperationType.BIGGER_EQUAL == rightOpType) && (GridSqlOperationType.SMALLER == leftOpType || GridSqlOperationType.SMALLER_EQUAL == leftOpType)) {
        GridSqlAst tmp = left;
        left = right;
        right = tmp;
    } else if (!((GridSqlOperationType.BIGGER == leftOpType || GridSqlOperationType.BIGGER_EQUAL == leftOpType) && (GridSqlOperationType.SMALLER == rightOpType || GridSqlOperationType.SMALLER_EQUAL == rightOpType)))
        return null;
    // Try parse left AST.
    GridSqlColumn leftCol;
    if (left instanceof GridSqlOperation && left.child() instanceof GridSqlColumn && (((GridSqlColumn) left.child()).column().getTable() instanceof GridH2Table))
        leftCol = left.child();
    else
        return null;
    // Try parse right AST.
    GridSqlColumn rightCol;
    if (right instanceof GridSqlOperation && right.child() instanceof GridSqlColumn)
        rightCol = right.child();
    else
        return null;
    GridH2Table tbl = (GridH2Table) leftCol.column().getTable();
    // Check that columns might be used for partition pruning.
    if (!tbl.isColumnForPartitionPruning(leftCol.column()))
        return null;
    // Check that both left and right AST use same column.
    if (!F.eq(leftCol.schema(), rightCol.schema()) || !F.eq(leftCol.columnName(), rightCol.columnName()) || !F.eq(leftCol.tableAlias(), rightCol.tableAlias()))
        return null;
    // Check columns type
    if (!(leftCol.column().getType() == Value.BYTE || leftCol.column().getType() == Value.SHORT || leftCol.column().getType() == Value.INT || leftCol.column().getType() == Value.LONG))
        return null;
    // Try parse left AST right value (value to the right of '>' or '>=').
    GridSqlConst leftConst;
    if (left.child(1) instanceof GridSqlConst)
        leftConst = left.child(1);
    else
        return null;
    // Try parse right AST right value (value to the right of '<' or '<=').
    GridSqlConst rightConst;
    if (right.child(1) instanceof GridSqlConst)
        rightConst = right.child(1);
    else
        return null;
    long leftLongVal;
    long rightLongVal;
    try {
        leftLongVal = leftConst.value().getLong();
        rightLongVal = rightConst.value().getLong();
    } catch (Exception e) {
        return null;
    }
    // Increment left long value if '>' is used.
    if (((GridSqlOperation) left).operationType() == GridSqlOperationType.BIGGER)
        leftLongVal++;
    // Decrement right long value if '<' is used.
    if (((GridSqlOperation) right).operationType() == GridSqlOperationType.SMALLER)
        rightLongVal--;
    Set<PartitionSingleNode> parts = new HashSet<>();
    PartitionTable tbl0 = tblModel.table(leftCol.tableAlias());
    // If table is in ignored set, then we cannot use it for partition extraction.
    if (tbl0 == null)
        return null;
    for (long i = leftLongVal; i <= rightLongVal; i++) {
        int part = partResolver.partition(i, leftCol.column().getType(), tbl0.cacheName());
        parts.add(new PartitionConstantNode(tbl0, part));
        if (parts.size() > maxPartsCntBetween)
            return null;
    }
    return parts.isEmpty() ? PartitionNoneNode.INSTANCE : parts.size() == 1 ? parts.iterator().next() : new PartitionGroupNode(parts);
}
Also used : PartitionTable(org.apache.ignite.internal.sql.optimizer.affinity.PartitionTable) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) GridSqlConst(org.apache.ignite.internal.processors.query.h2.sql.GridSqlConst) GridSqlAst(org.apache.ignite.internal.processors.query.h2.sql.GridSqlAst) GridSqlColumn(org.apache.ignite.internal.processors.query.h2.sql.GridSqlColumn) GridH2Table(org.apache.ignite.internal.processors.query.h2.opt.GridH2Table) PartitionSingleNode(org.apache.ignite.internal.sql.optimizer.affinity.PartitionSingleNode) PartitionConstantNode(org.apache.ignite.internal.sql.optimizer.affinity.PartitionConstantNode) GridSqlOperationType(org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType) GridSqlOperation(org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation) PartitionGroupNode(org.apache.ignite.internal.sql.optimizer.affinity.PartitionGroupNode) HashSet(java.util.HashSet)

Example 23 with GridH2Table

use of org.apache.ignite.internal.processors.query.h2.opt.GridH2Table in project ignite by apache.

the class PartitionExtractor method prepareTable.

/**
 * Prepare single table.
 *
 * @param from Expression.
 * @param tblModel Table model.
 * @return Added table or {@code null} if table is exlcuded from the model.
 */
private static PartitionTable prepareTable(GridSqlAst from, PartitionTableModel tblModel) {
    // Unwrap alias. We assume that every table must be aliased.
    assert from instanceof GridSqlAlias;
    String alias = ((GridSqlAlias) from).alias();
    from = from.child();
    if (from instanceof GridSqlTable) {
        // Normal table.
        GridSqlTable from0 = (GridSqlTable) from;
        GridH2Table tbl0 = from0.dataTable();
        // Unknown table type, e.g. temp table.
        if (tbl0 == null) {
            tblModel.addExcludedTable(alias);
            return null;
        }
        String cacheName = tbl0.cacheName();
        String affColName = null;
        String secondAffColName = null;
        for (Column col : tbl0.getColumns()) {
            if (tbl0.isColumnForPartitionPruningStrict(col)) {
                if (affColName == null)
                    affColName = col.getName();
                else {
                    secondAffColName = col.getName();
                    // Break as we cannot have more than two affinity key columns.
                    break;
                }
            }
        }
        PartitionTable tbl = new PartitionTable(alias, cacheName, affColName, secondAffColName);
        PartitionTableAffinityDescriptor aff = affinityForCache(tbl0.cacheInfo().config());
        if (aff == null) {
            // Non-standard affinity, exclude table.
            tblModel.addExcludedTable(alias);
            return null;
        }
        tblModel.addTable(tbl, aff);
        return tbl;
    } else {
        // Subquery/union/view, etc.
        assert alias != null;
        tblModel.addExcludedTable(alias);
        return null;
    }
}
Also used : PartitionTable(org.apache.ignite.internal.sql.optimizer.affinity.PartitionTable) GridSqlAlias(org.apache.ignite.internal.processors.query.h2.sql.GridSqlAlias) Column(org.h2.table.Column) GridSqlColumn(org.apache.ignite.internal.processors.query.h2.sql.GridSqlColumn) GridSqlTable(org.apache.ignite.internal.processors.query.h2.sql.GridSqlTable) GridH2Table(org.apache.ignite.internal.processors.query.h2.opt.GridH2Table) PartitionTableAffinityDescriptor(org.apache.ignite.internal.sql.optimizer.affinity.PartitionTableAffinityDescriptor)

Example 24 with GridH2Table

use of org.apache.ignite.internal.processors.query.h2.opt.GridH2Table in project ignite by apache.

the class UpdatePlanBuilder method verifyUpdateColumns.

/**
 * Check that UPDATE statement affects no key columns.
 *
 * @param statement Statement.
 */
private static void verifyUpdateColumns(GridSqlStatement statement) {
    if (!(statement instanceof GridSqlUpdate))
        return;
    GridSqlUpdate update = (GridSqlUpdate) statement;
    GridSqlElement updTarget = update.target();
    Set<GridSqlTable> tbls = new HashSet<>();
    DmlAstUtils.collectAllGridTablesInTarget(updTarget, tbls);
    if (tbls.size() != 1)
        throw new IgniteSQLException("Failed to determine target table for UPDATE", IgniteQueryErrorCode.TABLE_NOT_FOUND);
    GridSqlTable tbl = tbls.iterator().next();
    GridH2Table gridTbl = tbl.dataTable();
    if (gridTbl != null && updateAffectsKeyColumns(gridTbl, update.set().keySet()))
        throw new IgniteSQLException("SQL UPDATE can't modify key or its fields directly", IgniteQueryErrorCode.KEY_UPDATE);
    if (gridTbl != null)
        verifyDmlColumns(gridTbl, F.viewReadOnly(update.cols(), TO_H2_COL));
}
Also used : GridSqlTable(org.apache.ignite.internal.processors.query.h2.sql.GridSqlTable) GridH2Table(org.apache.ignite.internal.processors.query.h2.opt.GridH2Table) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException) GridSqlElement(org.apache.ignite.internal.processors.query.h2.sql.GridSqlElement) GridSqlUpdate(org.apache.ignite.internal.processors.query.h2.sql.GridSqlUpdate) HashSet(java.util.HashSet)

Example 25 with GridH2Table

use of org.apache.ignite.internal.processors.query.h2.opt.GridH2Table in project ignite by apache.

the class UpdatePlanBuilder method verifyDmlColumns.

/**
 * Checks that DML query (insert, merge, update, bulk load aka copy) columns: <br/>
 * 1) doesn't contain both entire key (_key or alias) and columns referring to part of the key; <br/>
 * 2) doesn't contain both entire value (_val or alias) and columns referring to part of the value. <br/>
 *
 * @param tab - updated table.
 * @param affectedCols - table's column names affected by dml query. Their order should be the same as in the
 * dml statement only to have the same columns order in the error message.
 * @throws IgniteSQLException if check failed.
 */
private static void verifyDmlColumns(GridH2Table tab, Collection<Column> affectedCols) {
    GridH2RowDescriptor desc = tab.rowDescriptor();
    // _key (_val) or it alias exist in the update columns.
    String keyColName = null;
    String valColName = null;
    // Whether fields that are part of the key (value) exist in the updated columns.
    boolean hasKeyProps = false;
    boolean hasValProps = false;
    for (Column col : affectedCols) {
        int colId = col.getColumnId();
        // Checking that it's not specified both _key(_val) and its alias by the way.
        if (desc.isKeyColumn(colId)) {
            if (keyColName == null)
                keyColName = col.getName();
            else
                throw new IgniteSQLException("Columns " + keyColName + " and " + col + " both refer to entire cache key object.", IgniteQueryErrorCode.PARSING);
        } else if (desc.isValueColumn(colId)) {
            if (valColName == null)
                valColName = col.getName();
            else
                throw new IgniteSQLException("Columns " + valColName + " and " + col + " both refer to entire cache value object.", IgniteQueryErrorCode.PARSING);
        } else {
            // Column ids 0..2 are _key, _val, _ver
            assert colId >= QueryUtils.DEFAULT_COLUMNS_COUNT : "Unexpected column [name=" + col + ", id=" + colId + "].";
            if (desc.isColumnKeyProperty(colId - QueryUtils.DEFAULT_COLUMNS_COUNT))
                hasKeyProps = true;
            else
                hasValProps = true;
        }
        // And check invariants for the fast fail.
        boolean hasEntireKeyCol = keyColName != null;
        boolean hasEntireValcol = valColName != null;
        if (hasEntireKeyCol && hasKeyProps)
            throw new IgniteSQLException("Column " + keyColName + " refers to entire key cache object. " + "It must not be mixed with other columns that refer to parts of key.", IgniteQueryErrorCode.PARSING);
        if (hasEntireValcol && hasValProps)
            throw new IgniteSQLException("Column " + valColName + " refers to entire value cache object. " + "It must not be mixed with other columns that refer to parts of value.", IgniteQueryErrorCode.PARSING);
        if (!ALLOW_KEY_VAL_UPDATES) {
            if (desc.isKeyColumn(colId) && !QueryUtils.isSqlType(desc.type().keyClass())) {
                throw new IgniteSQLException("Update of composite key column is not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
            }
            if (desc.isValueColumn(colId) && !QueryUtils.isSqlType(desc.type().valueClass())) {
                throw new IgniteSQLException("Update of composite value column is not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
            }
        }
    }
}
Also used : GridH2RowDescriptor(org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor) GridSqlColumn(org.apache.ignite.internal.processors.query.h2.sql.GridSqlColumn) Column(org.h2.table.Column) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException)

Aggregations

GridH2Table (org.apache.ignite.internal.processors.query.h2.opt.GridH2Table)66 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)26 IgniteSQLException (org.apache.ignite.internal.processors.query.IgniteSQLException)26 GridH2RowDescriptor (org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor)18 GridSqlColumn (org.apache.ignite.internal.processors.query.h2.sql.GridSqlColumn)18 Column (org.h2.table.Column)18 ArrayList (java.util.ArrayList)16 IgniteException (org.apache.ignite.IgniteException)15 HashSet (java.util.HashSet)13 GridSqlElement (org.apache.ignite.internal.processors.query.h2.sql.GridSqlElement)12 GridQueryTypeDescriptor (org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor)11 GridSqlTable (org.apache.ignite.internal.processors.query.h2.sql.GridSqlTable)11 SQLException (java.sql.SQLException)10 List (java.util.List)10 GridCacheContext (org.apache.ignite.internal.processors.cache.GridCacheContext)10 GridSqlSelect (org.apache.ignite.internal.processors.query.h2.sql.GridSqlSelect)8 Map (java.util.Map)7 IgniteEx (org.apache.ignite.internal.IgniteEx)7 GridQueryProperty (org.apache.ignite.internal.processors.query.GridQueryProperty)7 HashMap (java.util.HashMap)5