Search in sources :

Example 11 with GridSqlOperation

use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation in project ignite by apache.

the class PartitionExtractor method extractFromIn.

/**
 * Extract partition information from IN.
 *
 * @param op Operation.
 * @param tblModel Table model.
 * @return Partition.
 */
private PartitionNode extractFromIn(GridSqlOperation op, PartitionTableModel tblModel) throws IgniteCheckedException {
    // Operation should contain at least two children: left (column) and right (const or column).
    if (op.size() < 2)
        return PartitionAllNode.INSTANCE;
    // Left operand should be column.
    GridSqlAst left = op.child();
    GridSqlColumn leftCol = unwrapColumn(left);
    if (leftCol == null)
        return PartitionAllNode.INSTANCE;
    // Can work only with Ignite tables.
    if (!(leftCol.column().getTable() instanceof GridH2Table))
        return PartitionAllNode.INSTANCE;
    Set<PartitionSingleNode> parts = new HashSet<>();
    for (int i = 1; i < op.size(); i++) {
        GridSqlAst right = op.child(i);
        GridSqlConst rightConst;
        GridSqlParameter rightParam;
        if (right instanceof GridSqlConst) {
            rightConst = (GridSqlConst) right;
            rightParam = null;
        } else if (right instanceof GridSqlParameter) {
            rightConst = null;
            rightParam = (GridSqlParameter) right;
        } else
            // set globally. Hence, returning null.
            return PartitionAllNode.INSTANCE;
        // Extract.
        PartitionSingleNode part = extractSingle(leftCol, rightConst, rightParam, tblModel);
        // Same thing as above: single unknown partition in disjunction defeats optimization.
        if (part == null)
            return PartitionAllNode.INSTANCE;
        parts.add(part);
    }
    return parts.size() == 1 ? parts.iterator().next() : new PartitionGroupNode(parts);
}
Also used : 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) GridSqlParameter(org.apache.ignite.internal.processors.query.h2.sql.GridSqlParameter) PartitionGroupNode(org.apache.ignite.internal.sql.optimizer.affinity.PartitionGroupNode) HashSet(java.util.HashSet)

Example 12 with GridSqlOperation

use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation in project ignite by apache.

the class PartitionExtractor method parseJoinCondition.

/**
 * Try parsing condition as simple JOIN codition. Only equijoins are supported for now, so anything more complex
 * than "A.a = B.b" are not processed.
 *
 * @param on Initial AST.
 * @return Join condition or {@code null} if not simple equijoin.
 */
private static PartitionJoinCondition parseJoinCondition(GridSqlElement on) {
    if (on instanceof GridSqlOperation) {
        GridSqlOperation on0 = (GridSqlOperation) on;
        if (on0.operationType() == GridSqlOperationType.EQUAL) {
            // Check for cross-join first.
            GridSqlConst leftConst = unwrapConst(on0.child(0));
            GridSqlConst rightConst = unwrapConst(on0.child(1));
            if (leftConst != null && rightConst != null) {
                try {
                    int leftConstval = leftConst.value().getInt();
                    int rightConstVal = rightConst.value().getInt();
                    if (leftConstval == rightConstVal)
                        return PartitionJoinCondition.CROSS;
                } catch (Exception ignore) {
                // No-op.
                }
            }
            // This is not cross-join, neither normal join between columns.
            if (leftConst != null || rightConst != null)
                return null;
            // Check for normal equi-join.
            GridSqlColumn left = unwrapColumn(on0.child(0));
            GridSqlColumn right = unwrapColumn(on0.child(1));
            if (left != null && right != null) {
                String leftAlias = left.tableAlias();
                String rightAlias = right.tableAlias();
                String leftCol = left.columnName();
                String rightCol = right.columnName();
                return new PartitionJoinCondition(leftAlias, rightAlias, leftCol, rightCol);
            }
        }
    }
    return null;
}
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) GridSqlOperation(org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation) IgniteCheckedException(org.apache.ignite.IgniteCheckedException)

Example 13 with GridSqlOperation

use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation in project ignite by apache.

the class DmlAstUtils method findKeyValueEqualityCondition.

/**
 * @param where Element to test.
 * @return Whether given element corresponds to {@code WHERE _key = ?}, and key is a literal expressed
 * in query or a query param.
 */
@SuppressWarnings("RedundantCast")
private static IgnitePair<GridSqlElement> findKeyValueEqualityCondition(GridSqlElement where) {
    if (!(where instanceof GridSqlOperation))
        return null;
    GridSqlOperation whereOp = (GridSqlOperation) where;
    // Does this WHERE limit only by _key?
    if (isKeyEqualityCondition(whereOp))
        return new IgnitePair<>((GridSqlElement) whereOp.child(1), null);
    // Or maybe it limits both by _key and _val?
    if (whereOp.operationType() != GridSqlOperationType.AND)
        return null;
    GridSqlElement left = whereOp.child(0);
    GridSqlElement right = whereOp.child(1);
    if (!(left instanceof GridSqlOperation && right instanceof GridSqlOperation))
        return null;
    GridSqlOperation leftOp = (GridSqlOperation) left;
    GridSqlOperation rightOp = (GridSqlOperation) right;
    if (isKeyEqualityCondition(leftOp)) {
        // _key = ? and _val = ?
        if (!isValueEqualityCondition(rightOp))
            return null;
        return new IgnitePair<>((GridSqlElement) leftOp.child(1), (GridSqlElement) rightOp.child(1));
    } else if (isKeyEqualityCondition(rightOp)) {
        // _val = ? and _key = ?
        if (!isValueEqualityCondition(leftOp))
            return null;
        return new IgnitePair<>((GridSqlElement) rightOp.child(1), (GridSqlElement) leftOp.child(1));
    } else
        // Neither
        return null;
}
Also used : IgnitePair(org.apache.ignite.internal.util.lang.IgnitePair) GridSqlElement(org.apache.ignite.internal.processors.query.h2.sql.GridSqlElement) GridSqlOperation(org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation)

Example 14 with GridSqlOperation

use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation in project ignite by apache.

the class GridSubqueryJoinOptimizer method pullOutSubQryFromTableList.

/**
 * Pull out sub-select from table list.
 * <p>
 * Example:
 * <pre>
 *   Before:
 *     SELECT d.name
 *       FROM emp e,
 *            (select * from dep) d
 *      WHERE e.dep_id = d.id
 *        AND e.sal > 2000
 *
 *   After:
 *     SELECT d.name
 *       FROM emp e
 *       JOIN dep d
 *      WHERE sal > 2000 AND d.id = e.dep_id
 * </pre>
 *
 * @param parent Parent select.
 * @param target Target sql element. Can be {@code null}.
 * @param childInd Column index.
 */
private static boolean pullOutSubQryFromTableList(GridSqlSelect parent, @Nullable GridSqlAst target, int childInd) {
    if (target != null && !ELEMENT_IS_JOIN.test(target))
        return false;
    GridSqlAlias wrappedSubQry = target != null ? target.child(childInd) : (GridSqlAlias) parent.from();
    GridSqlSubquery subQry = GridSqlAlias.unwrap(wrappedSubQry);
    if (!isSimpleSelect(subQry.subquery()))
        return false;
    GridSqlSelect subSel = subQry.subquery();
    if (!(subSel.from() instanceof GridSqlAlias) && !(subSel.from() instanceof GridSqlTable))
        // we can't deal with joins and others right now
        return false;
    GridSqlAlias subTbl = new GridSqlAlias(wrappedSubQry.alias(), GridSqlAlias.unwrap(subSel.from()));
    if (target == null)
        // it's true only when the subquery is only table in the table list
        // so we can safely replace entire FROM expression of the parent
        parent.from(subTbl);
    else
        target.child(childInd, subTbl);
    GridSqlAst where = subSel.where();
    if (where != null) {
        if (target != null) {
            GridSqlJoin join = (GridSqlJoin) target;
            join.child(GridSqlJoin.ON_CHILD, new GridSqlOperation(AND, join.on(), where));
        } else
            parent.where(parent.where() == null ? where : new GridSqlOperation(AND, parent.where(), where));
    }
    remapColumns(parent, subSel, // reference equality used intentionally here
    col -> wrappedSubQry == col.expressionInFrom(), subTbl);
    return true;
}
Also used : GridSqlAlias(org.apache.ignite.internal.processors.query.h2.sql.GridSqlAlias) GridSqlSubquery(org.apache.ignite.internal.processors.query.h2.sql.GridSqlSubquery) GridSqlAst(org.apache.ignite.internal.processors.query.h2.sql.GridSqlAst) GridSqlJoin(org.apache.ignite.internal.processors.query.h2.sql.GridSqlJoin) GridSqlTable(org.apache.ignite.internal.processors.query.h2.sql.GridSqlTable) GridSqlOperation(org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation) GridSqlSelect(org.apache.ignite.internal.processors.query.h2.sql.GridSqlSelect)

Example 15 with GridSqlOperation

use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation in project ignite by apache.

the class GridSubqueryJoinOptimizer method isSimpleSelect.

/**
 * Whether Select query is simple or not.
 * <p>
 * We call query simple if it is select query (not union) and it has neither having nor grouping,
 * has no distinct clause, has no aggregations, has no limits, no sorting, no offset clause.
 * Also it is not SELECT FOR UPDATE.
 *
 * @param subQry Sub query.
 * @return {@code true} if it is simple query.
 */
private static boolean isSimpleSelect(GridSqlQuery subQry) {
    if (subQry instanceof GridSqlUnion)
        return false;
    GridSqlSelect select = (GridSqlSelect) subQry;
    boolean simple = F.isEmpty(select.sort()) && select.offset() == null && select.limit() == null && !select.isForUpdate() && !select.distinct() && select.havingColumn() < 0 && F.isEmpty(select.groupColumns());
    if (!simple)
        return false;
    for (GridSqlAst col : select.columns(true)) {
        if (!(col instanceof GridSqlElement))
            continue;
        // we have to traverse the tree because there may be such expressions
        // like ((MAX(col) - MIN(col)) / COUNT(col)
        ASTNodeFinder aggFinder = new ASTNodeFinder(col, (p, c) -> p instanceof GridSqlAggregateFunction);
        if (aggFinder.findNext() != null)
            return false;
        // In case of query like "SELECT * FROM (SELECT i||j FROM t) u;", where subquery contains pure operation
        // without an alias, we cannot determine which generated alias in the parent query the original expression
        // belongs to. So the best we can do is skip the case.
        ASTNodeFinder operationFinder = new ASTNodeFinder(col, (p, c) -> p instanceof GridSqlOperation, ast -> false);
        if (operationFinder.findNext() != null)
            return false;
    }
    return true;
}
Also used : GridSqlUnion(org.apache.ignite.internal.processors.query.h2.sql.GridSqlUnion) GridSqlAst(org.apache.ignite.internal.processors.query.h2.sql.GridSqlAst) GridSqlAggregateFunction(org.apache.ignite.internal.processors.query.h2.sql.GridSqlAggregateFunction) GridSqlElement(org.apache.ignite.internal.processors.query.h2.sql.GridSqlElement) GridSqlOperation(org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation) GridSqlSelect(org.apache.ignite.internal.processors.query.h2.sql.GridSqlSelect)

Aggregations

GridSqlOperation (org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation)10 GridSqlAst (org.apache.ignite.internal.processors.query.h2.sql.GridSqlAst)7 GridSqlColumn (org.apache.ignite.internal.processors.query.h2.sql.GridSqlColumn)7 GridSqlElement (org.apache.ignite.internal.processors.query.h2.sql.GridSqlElement)7 GridH2Table (org.apache.ignite.internal.processors.query.h2.opt.GridH2Table)6 GridSqlConst (org.apache.ignite.internal.processors.query.h2.sql.GridSqlConst)5 GridSqlSelect (org.apache.ignite.internal.processors.query.h2.sql.GridSqlSelect)5 GridSqlParameter (org.apache.ignite.internal.processors.query.h2.sql.GridSqlParameter)4 GridSqlSubquery (org.apache.ignite.internal.processors.query.h2.sql.GridSqlSubquery)4 GridH2RowDescriptor (org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor)3 PartitionSingleNode (org.apache.ignite.internal.sql.optimizer.affinity.PartitionSingleNode)3 ArrayList (java.util.ArrayList)2 HashSet (java.util.HashSet)2 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)2 GridSqlAlias (org.apache.ignite.internal.processors.query.h2.sql.GridSqlAlias)2 GridSqlFunction (org.apache.ignite.internal.processors.query.h2.sql.GridSqlFunction)2 GridSqlTable (org.apache.ignite.internal.processors.query.h2.sql.GridSqlTable)2 PartitionGroupNode (org.apache.ignite.internal.sql.optimizer.affinity.PartitionGroupNode)2 PartitionJoinCondition (org.apache.ignite.internal.sql.optimizer.affinity.PartitionJoinCondition)2 IgniteException (org.apache.ignite.IgniteException)1