Search in sources :

Example 6 with GridSqlOperation

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

the class GridSubqueryJoinOptimizer method pullOutSubQryFromSelectExpr.

/**
 * Pulls out subquery from select expression.
 *
 * @param select Parent query where to find and pull out subqueries.
 */
private static void pullOutSubQryFromSelectExpr(GridSqlSelect select) {
    for (int i = 0; i < select.allColumns(); i++) {
        boolean wasPulledOut = false;
        GridSqlAst col = select.columns(false).get(i);
        if (col instanceof GridSqlSubquery)
            wasPulledOut = pullOutSubQryFromSelectExpr(select, null, i);
        else if (col instanceof GridSqlOperation && ((GridSqlOperation) col).operationType() == EXISTS)
            // We actially can't rewrite select query under exists operator. So we skip it.
            continue;
        else {
            ASTNodeFinder finder = new ASTNodeFinder(col, ELEMENT_WITH_SUBQUERY);
            ASTNodeFinder.Result res;
            while ((res = finder.findNext()) != null) wasPulledOut |= pullOutSubQryFromSelectExpr(select, res.getEl(), res.getIdx());
        }
        if (// we have to analyze just pulled out element as well
        wasPulledOut)
            i--;
    }
}
Also used : GridSqlSubquery(org.apache.ignite.internal.processors.query.h2.sql.GridSqlSubquery) GridSqlAst(org.apache.ignite.internal.processors.query.h2.sql.GridSqlAst) GridSqlOperation(org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation)

Example 7 with GridSqlOperation

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

the class GridSubqueryJoinOptimizer method pullOutSubQryFromInClause.

/**
 * Pull out sub-select from IN clause to the parent select level.
 * <p>
 * Example:
 * <pre>
 *   Before:
 *     SELECT name
 *       FROM emp e
 *      WHERE e.dep_id IN (SELECT d.id FROM dep d WHERE d.name = 'dep1')
 *        AND sal > 2000
 *
 *   After:
 *     SELECT name
 *       FROM emp e
 *       JOIN dep d
 *      WHERE sal > 2000 AND d.id = e.dep_id and d.name = 'dep1
 * </pre>
 *
 * @param parent Parent select.
 * @param targetEl Target sql element. Can be {@code null}.
 * @param childInd Column index.
 */
private static boolean pullOutSubQryFromInClause(GridSqlSelect parent, @Nullable GridSqlAst targetEl, int childInd) {
    // extract sub-query
    GridSqlSubquery subQry = targetEl != null ? targetEl.child(childInd).child(1) : parent.where().child(1);
    if (!isSimpleSelect(subQry.subquery()))
        return false;
    GridSqlSelect subS = subQry.subquery();
    GridSqlAst leftExpr = targetEl != null ? targetEl.child(childInd).child(0) : parent.where().child(0);
    // 4) c1 + c2/const IN (SELECT in_col FROM ...)
    if (subS.visibleColumns() != 1)
        return false;
    List<GridSqlElement> conditions = new ArrayList<>();
    if (leftExpr instanceof GridSqlArray) {
        GridSqlAst col = subS.columns(true).get(0);
        if (!(col instanceof GridSqlArray) || leftExpr.size() != col.size())
            return false;
        for (int i = 0; i < col.size(); i++) {
            GridSqlElement el = leftExpr.child(i);
            conditions.add(new GridSqlOperation(EQUAL, el, col.child(i)));
        }
    } else if (targetEl instanceof GridSqlFunction)
        return false;
    else
        conditions.add(new GridSqlOperation(EQUAL, leftExpr, subS.columns(true).get(0)));
    // save old condition and IN expression to restore them
    // in case of unsuccessfull pull out
    GridSqlElement oldCond = (GridSqlElement) subS.where();
    if (oldCond != null)
        conditions.add(oldCond);
    GridSqlElement oldInExpr = targetEl != null ? targetEl.child(childInd) : (GridSqlElement) parent.where();
    // update sub-query condition and convert IN clause to EXISTS
    subS.where(buildConditionBush(conditions));
    GridSqlOperation existsExpr = new GridSqlOperation(EXISTS, subQry);
    if (targetEl != null)
        targetEl.child(childInd, existsExpr);
    else
        parent.where(existsExpr);
    boolean res = pullOutSubQryFromExistsClause(parent, targetEl, childInd);
    if (!res) {
        // restore original query in case of failure
        if (targetEl != null)
            targetEl.child(childInd, oldInExpr);
        else
            parent.where(oldInExpr);
        subS.where(oldCond);
    }
    return res;
}
Also used : GridSqlSubquery(org.apache.ignite.internal.processors.query.h2.sql.GridSqlSubquery) GridSqlAst(org.apache.ignite.internal.processors.query.h2.sql.GridSqlAst) ArrayList(java.util.ArrayList) GridSqlElement(org.apache.ignite.internal.processors.query.h2.sql.GridSqlElement) GridSqlFunction(org.apache.ignite.internal.processors.query.h2.sql.GridSqlFunction) GridSqlOperation(org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation) GridSqlArray(org.apache.ignite.internal.processors.query.h2.sql.GridSqlArray) GridSqlSelect(org.apache.ignite.internal.processors.query.h2.sql.GridSqlSelect)

Example 8 with GridSqlOperation

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

the class DmlAstUtils method isEqualityCondition.

/**
     * @param op Operation.
     * @param key true - check for key equality condition,
     *            otherwise check for value equality condition
     * @return Whether this condition is of form {@code colName} = ?
     */
private static boolean isEqualityCondition(GridSqlOperation op, boolean key) {
    if (op.operationType() != GridSqlOperationType.EQUAL)
        return false;
    GridSqlElement left = op.child(0);
    GridSqlElement right = op.child(1);
    if (!(left instanceof GridSqlColumn))
        return false;
    GridSqlColumn column = (GridSqlColumn) left;
    if (!(column.column().getTable() instanceof GridH2Table))
        return false;
    GridH2RowDescriptor desc = ((GridH2Table) column.column().getTable()).rowDescriptor();
    return (key ? desc.isKeyColumn(column.column().getColumnId()) : desc.isValueColumn(column.column().getColumnId())) && (right instanceof GridSqlConst || right instanceof GridSqlParameter);
}
Also used : GridH2RowDescriptor(org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor) GridH2Table(org.apache.ignite.internal.processors.query.h2.opt.GridH2Table)

Example 9 with GridSqlOperation

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

the class GridSubqueryJoinOptimizer method subQueryCanBePulledOut.

/**
 * Whether sub-query can be pulled out or not.
 *
 * @param subQry Sub-query.
 * @return {@code true} if sub-query cound be pulled out, {@code false} otherwise.
 */
private static boolean subQueryCanBePulledOut(GridSqlSubquery subQry) {
    GridSqlQuery subQ = subQry.subquery();
    if (!isSimpleSelect(subQ))
        return false;
    assert subQ instanceof GridSqlSelect;
    GridSqlSelect subS = (GridSqlSelect) subQ;
    if (subS.where() == null)
        return false;
    Predicate<GridSqlAst> andOrEqPre = ELEMENT_IS_AND_OPERATION.or(ELEMENT_IS_EQ);
    if (!andOrEqPre.test(subS.where()))
        return false;
    ASTNodeFinder opEqFinder = new ASTNodeFinder(subS.where(), (parent, child) -> ELEMENT_IS_EQ.test(parent), andOrEqPre);
    List<GridSqlColumn> sqlCols = new ArrayList<>();
    ASTNodeFinder.Result res;
    while ((res = opEqFinder.findNext()) != null) {
        GridSqlOperation op = (GridSqlOperation) res.getEl();
        assert op.size() == 2;
        GridSqlColumn[] colArr = new GridSqlColumn[2];
        for (int i = 0; i < 2; i++) {
            if (op.child(i) instanceof GridSqlColumn)
                colArr[i] = op.child(i);
            else if (op.child(i) instanceof GridSqlOperation && ((GridSqlOperation) op.child(i)).operationType() == NEGATE && op.child() instanceof GridSqlColumn)
                colArr[i] = op.child(i).child();
        }
        if (colArr[0] == null || colArr[1] == null || // whether the column refers to exactly the same table
        colArr[0].expressionInFrom() != colArr[1].expressionInFrom()) {
            if (colArr[0] != null && colArr[0].expressionInFrom() == subS.from())
                sqlCols.add(colArr[0]);
            if (colArr[1] != null && colArr[1].expressionInFrom() == subS.from())
                sqlCols.add(colArr[1]);
        }
    }
    GridSqlAst subTbl = GridSqlAlias.unwrap(subS.from());
    return subTbl instanceof GridSqlTable && isUniqueIndexExists(sqlCols, (GridSqlTable) subTbl);
}
Also used : ArrayList(java.util.ArrayList) GridSqlSelect(org.apache.ignite.internal.processors.query.h2.sql.GridSqlSelect) GridSqlQuery(org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuery) GridSqlAst(org.apache.ignite.internal.processors.query.h2.sql.GridSqlAst) GridSqlColumn(org.apache.ignite.internal.processors.query.h2.sql.GridSqlColumn) GridSqlTable(org.apache.ignite.internal.processors.query.h2.sql.GridSqlTable) GridSqlOperation(org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation)

Example 10 with GridSqlOperation

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

the class GridSubqueryJoinOptimizer method buildConditionBush.

/**
 * Creates tree from provided elements which will be connected with an AND operator.
 *
 * @param ops Ops.
 * @return Root of the resulting tree.
 */
private static GridSqlElement buildConditionBush(List<GridSqlElement> ops) {
    assert !F.isEmpty(ops);
    if (ops.size() == 1)
        return ops.get(0);
    int m = (ops.size() + 1) / 2;
    GridSqlElement left = buildConditionBush(ops.subList(0, m));
    GridSqlElement right = buildConditionBush(ops.subList(m, ops.size()));
    return new GridSqlOperation(AND, left, right);
}
Also used : GridSqlElement(org.apache.ignite.internal.processors.query.h2.sql.GridSqlElement) GridSqlOperation(org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation)

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