Search in sources :

Example 6 with ComparisonExpression

use of org.voltdb.expressions.ComparisonExpression in project voltdb by VoltDB.

the class ParsedUnionStmt method breakUpSetOpSubquery.

/**
     * Break up UNION/INTERSECT (ALL) set ops into individual selects that are part
     * of the IN/EXISTS subquery into multiple expressions for each set op child
     * combined by the conjunction AND/OR expression.
     * col IN ( queryA UNION queryB ) - > col IN (queryA) OR col IN (queryB)
     * col IN ( queryA INTERSECTS queryB ) - > col IN (queryA) AND col IN (queryB)
     * The EXCEPT set op is LEFT as is
     * Also the ALL qualifier is dropped because IN/EXISTS expressions only
     * need just one tuple in the results set
     *
     * @param subqueryExpr - IN/EXISTS expression with a possible SET OP subquery
     * @return simplified expression
     */
protected static AbstractExpression breakUpSetOpSubquery(AbstractExpression expr) {
    assert (expr != null);
    SelectSubqueryExpression subqueryExpr = null;
    if (expr.getExpressionType() == ExpressionType.COMPARE_EQUAL && expr.getRight() instanceof SelectSubqueryExpression) {
        subqueryExpr = (SelectSubqueryExpression) expr.getRight();
    } else if (expr.getExpressionType() == ExpressionType.OPERATOR_EXISTS && expr.getLeft() instanceof SelectSubqueryExpression) {
        subqueryExpr = (SelectSubqueryExpression) expr.getLeft();
    }
    if (subqueryExpr == null) {
        return expr;
    }
    AbstractParsedStmt subquery = subqueryExpr.getSubqueryStmt();
    if (!(subquery instanceof ParsedUnionStmt)) {
        return expr;
    }
    ParsedUnionStmt setOpStmt = (ParsedUnionStmt) subquery;
    if (UnionType.EXCEPT == setOpStmt.m_unionType || UnionType.EXCEPT_ALL == setOpStmt.m_unionType) {
        setOpStmt.m_unionType = UnionType.EXCEPT;
        return expr;
    }
    if (UnionType.UNION_ALL == setOpStmt.m_unionType) {
        setOpStmt.m_unionType = UnionType.UNION;
    } else if (UnionType.INTERSECT_ALL == setOpStmt.m_unionType) {
        setOpStmt.m_unionType = UnionType.INTERSECT;
    }
    ExpressionType conjuctionType = (setOpStmt.m_unionType == UnionType.UNION) ? ExpressionType.CONJUNCTION_OR : ExpressionType.CONJUNCTION_AND;
    AbstractExpression retval = null;
    AbstractParsedStmt parentStmt = subquery.m_parentStmt;
    // It's a subquery which means it must have a parent
    assert (parentStmt != null);
    for (AbstractParsedStmt child : setOpStmt.m_children) {
        // add table to the query cache
        String withoutAlias = null;
        StmtSubqueryScan tableCache = parentStmt.addSubqueryToStmtCache(child, withoutAlias);
        AbstractExpression childSubqueryExpr = new SelectSubqueryExpression(subqueryExpr.getExpressionType(), tableCache);
        AbstractExpression newExpr = null;
        try {
            newExpr = expr.getExpressionType().getExpressionClass().newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage(), e);
        }
        newExpr.setExpressionType(expr.getExpressionType());
        if (ExpressionType.COMPARE_EQUAL == expr.getExpressionType()) {
            newExpr.setLeft(expr.getLeft().clone());
            newExpr.setRight(childSubqueryExpr);
            assert (newExpr instanceof ComparisonExpression);
            ((ComparisonExpression) newExpr).setQuantifier(((ComparisonExpression) expr).getQuantifier());
        } else {
            newExpr.setLeft(childSubqueryExpr);
        }
        // Recurse
        newExpr = ParsedUnionStmt.breakUpSetOpSubquery(newExpr);
        if (retval == null) {
            retval = newExpr;
        } else {
            retval = new ConjunctionExpression(conjuctionType, retval, newExpr);
        }
    }
    return retval;
}
Also used : StmtSubqueryScan(org.voltdb.planner.parseinfo.StmtSubqueryScan) ComparisonExpression(org.voltdb.expressions.ComparisonExpression) AbstractExpression(org.voltdb.expressions.AbstractExpression) SelectSubqueryExpression(org.voltdb.expressions.SelectSubqueryExpression) ExpressionType(org.voltdb.types.ExpressionType) ConjunctionExpression(org.voltdb.expressions.ConjunctionExpression)

Example 7 with ComparisonExpression

use of org.voltdb.expressions.ComparisonExpression in project voltdb by VoltDB.

the class IndexScanPlanNode method buildSkipNullPredicate.

public static AbstractExpression buildSkipNullPredicate(int nullExprIndex, Index catalogIndex, StmtTableScan tableScan, List<AbstractExpression> searchkeyExpressions, List<Boolean> compareNotDistinct) {
    String exprsjson = catalogIndex.getExpressionsjson();
    List<AbstractExpression> indexedExprs = null;
    if (exprsjson.isEmpty()) {
        indexedExprs = new ArrayList<>();
        List<ColumnRef> indexedColRefs = CatalogUtil.getSortedCatalogItems(catalogIndex.getColumns(), "index");
        assert (nullExprIndex < indexedColRefs.size());
        for (int i = 0; i <= nullExprIndex; i++) {
            ColumnRef colRef = indexedColRefs.get(i);
            Column col = colRef.getColumn();
            TupleValueExpression tve = new TupleValueExpression(tableScan.getTableName(), tableScan.getTableAlias(), col, col.getIndex());
            indexedExprs.add(tve);
        }
    } else {
        try {
            indexedExprs = AbstractExpression.fromJSONArrayString(exprsjson, tableScan);
            assert (nullExprIndex < indexedExprs.size());
        } catch (JSONException e) {
            e.printStackTrace();
            assert (false);
        }
    }
    // For a partial index extract all TVE expressions from it predicate if it's NULL-rejecting expression
    // These TVEs do not need to be added to the skipNUll predicate because it's redundant.
    AbstractExpression indexPredicate = null;
    Set<TupleValueExpression> notNullTves = null;
    String indexPredicateJson = catalogIndex.getPredicatejson();
    if (!StringUtil.isEmpty(indexPredicateJson)) {
        try {
            indexPredicate = AbstractExpression.fromJSONString(indexPredicateJson, tableScan);
            assert (indexPredicate != null);
        } catch (JSONException e) {
            e.printStackTrace();
            assert (false);
        }
        if (ExpressionUtil.isNullRejectingExpression(indexPredicate, tableScan.getTableAlias())) {
            notNullTves = new HashSet<>();
            notNullTves.addAll(ExpressionUtil.getTupleValueExpressions(indexPredicate));
        }
    }
    AbstractExpression nullExpr = indexedExprs.get(nullExprIndex);
    AbstractExpression skipNullPredicate = null;
    if (notNullTves == null || !notNullTves.contains(nullExpr)) {
        List<AbstractExpression> exprs = new ArrayList<>();
        for (int i = 0; i < nullExprIndex; i++) {
            AbstractExpression idxExpr = indexedExprs.get(i);
            ExpressionType exprType = ExpressionType.COMPARE_EQUAL;
            if (i < compareNotDistinct.size() && compareNotDistinct.get(i)) {
                exprType = ExpressionType.COMPARE_NOTDISTINCT;
            }
            AbstractExpression expr = new ComparisonExpression(exprType, idxExpr, searchkeyExpressions.get(i).clone());
            exprs.add(expr);
        }
        // then we add "nullExpr IS NULL" to the expression for matching tuples to skip. (ENG-11096)
        if (nullExprIndex == searchkeyExpressions.size() || compareNotDistinct.get(nullExprIndex) == false) {
            // nullExprIndex == m_searchkeyExpressions.size() - 1
            AbstractExpression expr = new OperatorExpression(ExpressionType.OPERATOR_IS_NULL, nullExpr, null);
            exprs.add(expr);
        } else {
            return null;
        }
        skipNullPredicate = ExpressionUtil.combinePredicates(exprs);
        skipNullPredicate.finalizeValueTypes();
    }
    return skipNullPredicate;
}
Also used : TupleValueExpression(org.voltdb.expressions.TupleValueExpression) ArrayList(java.util.ArrayList) JSONException(org.json_voltpatches.JSONException) ComparisonExpression(org.voltdb.expressions.ComparisonExpression) AbstractExpression(org.voltdb.expressions.AbstractExpression) Column(org.voltdb.catalog.Column) OperatorExpression(org.voltdb.expressions.OperatorExpression) ColumnRef(org.voltdb.catalog.ColumnRef) ExpressionType(org.voltdb.types.ExpressionType)

Example 8 with ComparisonExpression

use of org.voltdb.expressions.ComparisonExpression in project voltdb by VoltDB.

the class SubPlanAssembler method replaceInListFilterWithEqualityFilter.

// Replace the IN LIST condition in the end expression referencing the first given rhs
// with an equality filter referencing the second given rhs.
private static void replaceInListFilterWithEqualityFilter(List<AbstractExpression> endExprs, AbstractExpression inListRhs, AbstractExpression equalityRhs) {
    for (AbstractExpression comparator : endExprs) {
        AbstractExpression otherExpr = comparator.getRight();
        if (otherExpr == inListRhs) {
            endExprs.remove(comparator);
            AbstractExpression replacement = new ComparisonExpression(ExpressionType.COMPARE_EQUAL, comparator.getLeft(), equalityRhs);
            endExprs.add(replacement);
            break;
        }
    }
}
Also used : ComparisonExpression(org.voltdb.expressions.ComparisonExpression) AbstractExpression(org.voltdb.expressions.AbstractExpression)

Example 9 with ComparisonExpression

use of org.voltdb.expressions.ComparisonExpression in project voltdb by VoltDB.

the class AbstractParsedStmt method optimizeInExpressions.

/**
     * Perform various optimizations for IN/EXISTS subqueries if possible
     *
     * @param expr to optimize
     * @return optimized expression
     */
private AbstractExpression optimizeInExpressions(AbstractExpression expr) {
    ExpressionType exprType = expr.getExpressionType();
    if (ExpressionType.CONJUNCTION_AND == exprType || ExpressionType.CONJUNCTION_OR == exprType) {
        AbstractExpression optimizedLeft = optimizeInExpressions(expr.getLeft());
        expr.setLeft(optimizedLeft);
        AbstractExpression optimizedRight = optimizeInExpressions(expr.getRight());
        expr.setRight(optimizedRight);
        return expr;
    }
    if (ExpressionType.COMPARE_EQUAL != exprType) {
        return expr;
    }
    assert (expr instanceof ComparisonExpression);
    if (((ComparisonExpression) expr).getQuantifier() != QuantifierType.ANY) {
        return expr;
    }
    /*
         * Verify that an IN expression can be safely converted to an EXISTS one
         * IN (SELECT" forms e.g. "(A, B) IN (SELECT X, Y, FROM ...) =>
         * EXISTS (SELECT 42 FROM ... AND|WHERE|HAVING A=X AND|WHERE|HAVING B=Y)
         */
    AbstractExpression inColumns = expr.getLeft();
    if (inColumns instanceof SelectSubqueryExpression) {
        // (expression must return a single row at most)
        return expr;
    }
    // The right hand operand of the equality operation must be a SELECT statement
    AbstractExpression rightExpr = expr.getRight();
    if (!(rightExpr instanceof SelectSubqueryExpression)) {
        return expr;
    }
    SelectSubqueryExpression subqueryExpr = (SelectSubqueryExpression) rightExpr;
    AbstractParsedStmt subquery = subqueryExpr.getSubqueryStmt();
    if (!(subquery instanceof ParsedSelectStmt)) {
        return expr;
    }
    ParsedSelectStmt selectStmt = (ParsedSelectStmt) subquery;
    //      seems to require 1 match that has exactly 10-14 rows (matching or not) with lesser or equal values of Y.
    if (selectStmt.hasLimitOrOffset()) {
        return expr;
    }
    ParsedSelectStmt.rewriteInSubqueryAsExists(selectStmt, inColumns);
    subqueryExpr.resolveCorrelations();
    AbstractExpression existsExpr = new OperatorExpression();
    existsExpr.setExpressionType(ExpressionType.OPERATOR_EXISTS);
    existsExpr.setLeft(subqueryExpr);
    return optimizeExistsExpression(existsExpr);
}
Also used : ComparisonExpression(org.voltdb.expressions.ComparisonExpression) AbstractExpression(org.voltdb.expressions.AbstractExpression) OperatorExpression(org.voltdb.expressions.OperatorExpression) SelectSubqueryExpression(org.voltdb.expressions.SelectSubqueryExpression) ExpressionType(org.voltdb.types.ExpressionType)

Example 10 with ComparisonExpression

use of org.voltdb.expressions.ComparisonExpression in project voltdb by VoltDB.

the class AbstractParsedStmt method parseOperationExpression.

/**
     *
     * @param paramsById
     * @param exprNode
     * @return
     */
private AbstractExpression parseOperationExpression(VoltXMLElement exprNode) {
    String optype = exprNode.attributes.get("optype");
    ExpressionType exprType = ExpressionType.get(optype);
    AbstractExpression expr = null;
    if (exprType == ExpressionType.INVALID) {
        throw new PlanningErrorException("Unsupported operation type '" + optype + "'");
    }
    try {
        expr = exprType.getExpressionClass().newInstance();
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException(e.getMessage(), e);
    }
    expr.setExpressionType(exprType);
    if (exprType == ExpressionType.OPERATOR_CASE_WHEN || exprType == ExpressionType.OPERATOR_ALTERNATIVE) {
        String valueType = exprNode.attributes.get("valuetype");
        expr.setValueType(VoltType.typeFromString(valueType));
    }
    if (expr instanceof ComparisonExpression) {
        String opsubtype = exprNode.attributes.get("opsubtype");
        if (opsubtype != null) {
            QuantifierType quantifier = QuantifierType.get(opsubtype);
            if (quantifier != QuantifierType.NONE) {
                ((ComparisonExpression) expr).setQuantifier(quantifier);
            }
        }
    }
    // get the first (left) node that is an element
    VoltXMLElement leftExprNode = exprNode.children.get(0);
    assert (leftExprNode != null);
    // recursively parse the left subtree (could be another operator or
    // a constant/tuple/param value operand).
    AbstractExpression leftExpr = parseExpressionNode(leftExprNode);
    assert ((leftExpr != null) || (exprType == ExpressionType.AGGREGATE_COUNT));
    expr.setLeft(leftExpr);
    // get the second (right) node that is an element (might be null)
    VoltXMLElement rightExprNode = null;
    if (exprNode.children.size() > 1) {
        rightExprNode = exprNode.children.get(1);
    }
    if (expr.needsRightExpression()) {
        assert (rightExprNode != null);
        // recursively parse the right subtree
        AbstractExpression rightExpr = parseExpressionNode(rightExprNode);
        assert (rightExpr != null);
        expr.setRight(rightExpr);
    } else {
        assert (rightExprNode == null);
        if (exprType == ExpressionType.OPERATOR_CAST) {
            String valuetype = exprNode.attributes.get("valuetype");
            assert (valuetype != null);
            VoltType voltType = VoltType.typeFromString(valuetype);
            expr.setValueType(voltType);
            // We don't support parameterized casting, such as specifically to "VARCHAR(3)" vs. VARCHAR,
            // so assume max length for variable-length types (VARCHAR and VARBINARY).
            int size = voltType.getMaxLengthInBytes();
            expr.setValueSize(size);
        }
    }
    if (exprType == ExpressionType.COMPARE_EQUAL && QuantifierType.ANY == ((ComparisonExpression) expr).getQuantifier()) {
        // Break up UNION/INTERSECT (ALL) set ops into individual selects connected by
        // AND/OR operator
        // col IN ( queryA UNION queryB ) - > col IN (queryA) OR col IN (queryB)
        // col IN ( queryA INTERSECTS queryB ) - > col IN (queryA) AND col IN (queryB)
        expr = ParsedUnionStmt.breakUpSetOpSubquery(expr);
    } else if (exprType == ExpressionType.OPERATOR_EXISTS) {
        expr = optimizeExistsExpression(expr);
    }
    return expr;
}
Also used : ComparisonExpression(org.voltdb.expressions.ComparisonExpression) AbstractExpression(org.voltdb.expressions.AbstractExpression) VoltType(org.voltdb.VoltType) QuantifierType(org.voltdb.types.QuantifierType) VoltXMLElement(org.hsqldb_voltpatches.VoltXMLElement) ExpressionType(org.voltdb.types.ExpressionType) JSONException(org.json_voltpatches.JSONException) Constraint(org.voltdb.catalog.Constraint)

Aggregations

AbstractExpression (org.voltdb.expressions.AbstractExpression)12 ComparisonExpression (org.voltdb.expressions.ComparisonExpression)12 ExpressionType (org.voltdb.types.ExpressionType)6 ArrayList (java.util.ArrayList)4 JSONException (org.json_voltpatches.JSONException)4 TupleValueExpression (org.voltdb.expressions.TupleValueExpression)3 SeqScanPlanNode (org.voltdb.plannodes.SeqScanPlanNode)3 OperatorExpression (org.voltdb.expressions.OperatorExpression)2 ParameterValueExpression (org.voltdb.expressions.ParameterValueExpression)2 RowSubqueryExpression (org.voltdb.expressions.RowSubqueryExpression)2 SelectSubqueryExpression (org.voltdb.expressions.SelectSubqueryExpression)2 AbstractPlanNode (org.voltdb.plannodes.AbstractPlanNode)2 VoltXMLElement (org.hsqldb_voltpatches.VoltXMLElement)1 VoltType (org.voltdb.VoltType)1 Column (org.voltdb.catalog.Column)1 ColumnRef (org.voltdb.catalog.ColumnRef)1 Constraint (org.voltdb.catalog.Constraint)1 Index (org.voltdb.catalog.Index)1 ConjunctionExpression (org.voltdb.expressions.ConjunctionExpression)1 ConstantValueExpression (org.voltdb.expressions.ConstantValueExpression)1