Search in sources :

Example 1 with RexVisitorImpl

use of org.apache.calcite.rex.RexVisitorImpl in project hive by apache.

the class HiveCalciteUtil method checkMaterializable.

/**
 * Check if the expression is usable for query materialization, returning the first failing expression.
 */
public static RexCall checkMaterializable(RexNode expr) {
    boolean deterministic = true;
    RexCall failingCall = null;
    if (expr == null) {
        return null;
    }
    RexVisitor<Void> visitor = new RexVisitorImpl<Void>(true) {

        @Override
        public Void visitCall(org.apache.calcite.rex.RexCall call) {
            // non-deterministic functions as well as runtime constants are not materializable.
            if (!call.getOperator().isDeterministic() || call.getOperator().isDynamicFunction()) {
                throw new Util.FoundOne(call);
            }
            return super.visitCall(call);
        }
    };
    try {
        expr.accept(visitor);
    } catch (Util.FoundOne e) {
        failingCall = (RexCall) e.getNode();
    }
    return failingCall;
}
Also used : RexCall(org.apache.calcite.rex.RexCall) RexUtil(org.apache.calcite.rex.RexUtil) SqlValidatorUtil(org.apache.calcite.sql.validate.SqlValidatorUtil) RelOptUtil(org.apache.calcite.plan.RelOptUtil) Util(org.apache.calcite.util.Util) RexVisitorImpl(org.apache.calcite.rex.RexVisitorImpl)

Example 2 with RexVisitorImpl

use of org.apache.calcite.rex.RexVisitorImpl in project drill by axbaretto.

the class DrillRelOptUtil method findOperators.

/**
 * Travesal RexNode to find at least one operator in the given collection. Continue search if RexNode has a
 * RexInputRef which refers to a RexNode in project expressions.
 *
 * @param node : RexNode to search
 * @param projExprs : the list of project expressions. Empty list means there is No project operator underneath.
 * @param operators collection of operators to find
 * @return : Return null if there is NONE; return the first appearance of item/flatten RexCall.
 */
public static RexCall findOperators(final RexNode node, final List<RexNode> projExprs, final Collection<String> operators) {
    try {
        RexVisitor<Void> visitor = new RexVisitorImpl<Void>(true) {

            public Void visitCall(RexCall call) {
                if (operators.contains(call.getOperator().getName().toLowerCase())) {
                    throw new Util.FoundOne(call);
                /* throw exception to interrupt tree walk (this is similar to
                                              other utility methods in RexUtil.java */
                }
                return super.visitCall(call);
            }

            public Void visitInputRef(RexInputRef inputRef) {
                if (projExprs.size() == 0) {
                    return super.visitInputRef(inputRef);
                } else {
                    final int index = inputRef.getIndex();
                    RexNode n = projExprs.get(index);
                    if (n instanceof RexCall) {
                        RexCall r = (RexCall) n;
                        if (operators.contains(r.getOperator().getName().toLowerCase())) {
                            throw new Util.FoundOne(r);
                        }
                    }
                    return super.visitInputRef(inputRef);
                }
            }
        };
        node.accept(visitor);
        return null;
    } catch (Util.FoundOne e) {
        Util.swallow(e, null);
        return (RexCall) e.getNode();
    }
}
Also used : RexCall(org.apache.calcite.rex.RexCall) RexInputRef(org.apache.calcite.rex.RexInputRef) RelOptUtil(org.apache.calcite.plan.RelOptUtil) SqlValidatorUtil(org.apache.calcite.sql.validate.SqlValidatorUtil) Util(org.apache.calcite.util.Util) RexVisitorImpl(org.apache.calcite.rex.RexVisitorImpl) RexNode(org.apache.calcite.rex.RexNode)

Example 3 with RexVisitorImpl

use of org.apache.calcite.rex.RexVisitorImpl in project drill by apache.

the class DrillRelMdSelectivity method getScanSelectivityInternal.

private double getScanSelectivityInternal(TableMetadata tableMetadata, RexNode predicate, List<SchemaPath> fieldNames, RexBuilder rexBuilder) {
    double sel = 1.0;
    if ((predicate == null) || predicate.isAlwaysTrue()) {
        return sel;
    }
    List<RexNode> conjuncts1 = RelOptUtil.conjunctions(predicate);
    // a Set that holds range predicates that are combined based on whether they are defined on the same column
    Set<RexNode> combinedRangePredicates = new HashSet<>();
    // pre-process the conjuncts such that predicates on the same column are grouped together
    List<RexNode> conjuncts2 = preprocessRangePredicates(conjuncts1, fieldNames, rexBuilder, combinedRangePredicates);
    for (RexNode pred : conjuncts2) {
        double orSel = 0;
        for (RexNode orPred : RelOptUtil.disjunctions(pred)) {
            if (isMultiColumnPredicate(orPred) && !combinedRangePredicates.contains(orPred)) {
                Set uniqueRefs = new HashSet<>();
                uniqueRefs.add(DrillRelOptUtil.findAllRexInputRefs(orPred));
                // If equality predicate involving single column - selectivity is 1.0
                if (uniqueRefs.size() == 1) {
                    try {
                        RexVisitor<Void> visitor = new RexVisitorImpl<Void>(true) {

                            @Override
                            public Void visitCall(RexCall call) {
                                if (call.getKind() != SqlKind.EQUALS) {
                                    throw new Util.FoundOne(call);
                                }
                                return super.visitCall(call);
                            }
                        };
                        pred.accept(visitor);
                        orSel += 1.0;
                    } catch (Util.FoundOne e) {
                        // CALCITE guess
                        orSel += RelMdUtil.guessSelectivity(orPred);
                    }
                }
            } else if (orPred.isA(SqlKind.EQUALS)) {
                orSel += computeEqualsSelectivity(tableMetadata, orPred, fieldNames);
            } else if (orPred.isA(RANGE_PREDICATE) || combinedRangePredicates.contains(orPred)) {
                orSel += computeRangeSelectivity(tableMetadata, orPred, fieldNames);
            } else if (orPred.isA(SqlKind.NOT_EQUALS)) {
                orSel += 1.0 - computeEqualsSelectivity(tableMetadata, orPred, fieldNames);
            } else if (orPred.isA(SqlKind.LIKE)) {
                // LIKE selectivity is 5% more than a similar equality predicate, capped at CALCITE guess
                orSel += Math.min(computeEqualsSelectivity(tableMetadata, orPred, fieldNames) + LIKE_PREDICATE_SELECTIVITY, guessSelectivity(orPred));
            } else if (orPred.isA(SqlKind.NOT)) {
                if (orPred instanceof RexCall) {
                    // LIKE selectivity is 5% more than a similar equality predicate, capped at CALCITE guess
                    RexNode childOp = ((RexCall) orPred).getOperands().get(0);
                    if (childOp.isA(SqlKind.LIKE)) {
                        orSel += 1.0 - Math.min(computeEqualsSelectivity(tableMetadata, childOp, fieldNames) + LIKE_PREDICATE_SELECTIVITY, guessSelectivity(childOp));
                    } else {
                        orSel += 1.0 - guessSelectivity(orPred);
                    }
                }
            } else if (orPred.isA(SqlKind.IS_NULL)) {
                orSel += 1.0 - computeIsNotNullSelectivity(tableMetadata, orPred, fieldNames);
            } else if (orPred.isA(SqlKind.IS_NOT_NULL)) {
                orSel += computeIsNotNullSelectivity(tableMetadata, orPred, fieldNames);
            } else {
                // Use the CALCITE guess.
                orSel += guessSelectivity(orPred);
            }
        }
        sel *= orSel;
    }
    // Cap selectivity if it exceeds 1.0
    return (sel > 1.0) ? 1.0 : sel;
}
Also used : HashSet(java.util.HashSet) EnumSet(java.util.EnumSet) Set(java.util.Set) RelOptUtil(org.apache.calcite.plan.RelOptUtil) RelMdUtil(org.apache.calcite.rel.metadata.RelMdUtil) RexUtil(org.apache.calcite.rex.RexUtil) DrillRelOptUtil(org.apache.drill.exec.planner.common.DrillRelOptUtil) PrelUtil(org.apache.drill.exec.planner.physical.PrelUtil) Util(org.apache.calcite.util.Util) RexCall(org.apache.calcite.rex.RexCall) RexVisitorImpl(org.apache.calcite.rex.RexVisitorImpl) RexNode(org.apache.calcite.rex.RexNode) HashSet(java.util.HashSet)

Example 4 with RexVisitorImpl

use of org.apache.calcite.rex.RexVisitorImpl in project drill by apache.

the class DrillRelMdSelectivity method findRexInputRef.

private static RexInputRef findRexInputRef(final RexNode node) {
    try {
        RexVisitor<Void> visitor = new RexVisitorImpl<Void>(true) {

            @Override
            public Void visitCall(RexCall call) {
                for (RexNode child : call.getOperands()) {
                    child.accept(this);
                }
                return super.visitCall(call);
            }

            @Override
            public Void visitInputRef(RexInputRef inputRef) {
                throw new Util.FoundOne(inputRef);
            }
        };
        node.accept(visitor);
        return null;
    } catch (Util.FoundOne e) {
        Util.swallow(e, null);
        return (RexInputRef) e.getNode();
    }
}
Also used : RexCall(org.apache.calcite.rex.RexCall) RexInputRef(org.apache.calcite.rex.RexInputRef) RelOptUtil(org.apache.calcite.plan.RelOptUtil) RelMdUtil(org.apache.calcite.rel.metadata.RelMdUtil) RexUtil(org.apache.calcite.rex.RexUtil) DrillRelOptUtil(org.apache.drill.exec.planner.common.DrillRelOptUtil) PrelUtil(org.apache.drill.exec.planner.physical.PrelUtil) Util(org.apache.calcite.util.Util) RexVisitorImpl(org.apache.calcite.rex.RexVisitorImpl) RexNode(org.apache.calcite.rex.RexNode)

Example 5 with RexVisitorImpl

use of org.apache.calcite.rex.RexVisitorImpl in project flink by apache.

the class SubQueryDecorrelator method analyzeCorConditions.

private static void analyzeCorConditions(final Set<CorrelationId> variableSet, final RexNode condition, final RexBuilder rexBuilder, final int maxCnfNodeCount, final List<RexNode> corConditions, final List<RexNode> nonCorConditions, final List<RexNode> unsupportedCorConditions) {
    // converts the expanded expression to conjunctive normal form,
    // like "(a AND b) OR c" will be converted to "(a OR c) AND (b OR c)"
    final RexNode cnf = FlinkRexUtil.toCnf(rexBuilder, maxCnfNodeCount, condition);
    // converts the cnf condition to a list of AND conditions
    final List<RexNode> conjunctions = RelOptUtil.conjunctions(cnf);
    // `true` for RexNode is supported correlation condition,
    // `false` for RexNode is unsupported correlation condition,
    // `null` for RexNode is not a correlation condition.
    final RexVisitorImpl<Boolean> visitor = new RexVisitorImpl<Boolean>(true) {

        @Override
        public Boolean visitFieldAccess(RexFieldAccess fieldAccess) {
            final RexNode ref = fieldAccess.getReferenceExpr();
            if (ref instanceof RexCorrelVariable) {
                return visitCorrelVariable((RexCorrelVariable) ref);
            } else {
                return super.visitFieldAccess(fieldAccess);
            }
        }

        @Override
        public Boolean visitCorrelVariable(RexCorrelVariable correlVariable) {
            return variableSet.contains(correlVariable.id);
        }

        @Override
        public Boolean visitSubQuery(RexSubQuery subQuery) {
            final List<Boolean> result = new ArrayList<>();
            for (RexNode operand : subQuery.operands) {
                result.add(operand.accept(this));
            }
            // in (select t3.d from t3)
            if (result.contains(true) || result.contains(false)) {
                return false;
            } else {
                return null;
            }
        }

        @Override
        public Boolean visitCall(RexCall call) {
            final List<Boolean> result = new ArrayList<>();
            for (RexNode operand : call.operands) {
                result.add(operand.accept(this));
            }
            if (result.contains(false)) {
                return false;
            } else if (result.contains(true)) {
                // return call.op.getKind() != SqlKind.OR || !result.contains(null);
                return call.op.getKind() != SqlKind.OR;
            } else {
                return null;
            }
        }
    };
    for (RexNode c : conjunctions) {
        Boolean r = c.accept(visitor);
        if (r == null) {
            nonCorConditions.add(c);
        } else if (r) {
            corConditions.add(c);
        } else {
            unsupportedCorConditions.add(c);
        }
    }
}
Also used : RexCall(org.apache.calcite.rex.RexCall) RexCorrelVariable(org.apache.calcite.rex.RexCorrelVariable) ArrayList(java.util.ArrayList) RexVisitorImpl(org.apache.calcite.rex.RexVisitorImpl) RexFieldAccess(org.apache.calcite.rex.RexFieldAccess) RexSubQuery(org.apache.calcite.rex.RexSubQuery) RexNode(org.apache.calcite.rex.RexNode)

Aggregations

RexVisitorImpl (org.apache.calcite.rex.RexVisitorImpl)11 RexNode (org.apache.calcite.rex.RexNode)9 RexCall (org.apache.calcite.rex.RexCall)8 RelOptUtil (org.apache.calcite.plan.RelOptUtil)7 RexInputRef (org.apache.calcite.rex.RexInputRef)7 Util (org.apache.calcite.util.Util)7 SqlValidatorUtil (org.apache.calcite.sql.validate.SqlValidatorUtil)5 RexUtil (org.apache.calcite.rex.RexUtil)3 ArrayList (java.util.ArrayList)2 HashSet (java.util.HashSet)2 RelNode (org.apache.calcite.rel.RelNode)2 RelMdUtil (org.apache.calcite.rel.metadata.RelMdUtil)2 RexSubQuery (org.apache.calcite.rex.RexSubQuery)2 Pair (org.apache.calcite.util.Pair)2 DrillRelOptUtil (org.apache.drill.exec.planner.common.DrillRelOptUtil)2 FieldsReWriterUtil (org.apache.drill.exec.planner.logical.FieldsReWriterUtil)2 PrelUtil (org.apache.drill.exec.planner.physical.PrelUtil)2 SlidingWindow (com.hazelcast.jet.sql.impl.opt.SlidingWindow)1 EnumSet (java.util.EnumSet)1 Set (java.util.Set)1