Search in sources :

Example 1 with RexSubQuery

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

the class HiveParserUtils method rexSubQueryIn.

/**
 * Proxy to {@link RexSubQuery#in(RelNode, com.google.common.collect.ImmutableList)}.
 */
public static RexSubQuery rexSubQueryIn(RelNode relNode, Collection<RexNode> rexNodes) {
    Class[] argTypes = new Class[] { RelNode.class, null };
    argTypes[1] = useShadedImmutableList ? shadedImmutableListClz : immutableListClz;
    Method method = HiveReflectionUtils.tryGetMethod(RexSubQuery.class, "in", argTypes);
    Preconditions.checkState(method != null, "Cannot get the method to create an IN sub-query");
    try {
        return (RexSubQuery) method.invoke(null, relNode, toImmutableList(rexNodes));
    } catch (IllegalAccessException | InvocationTargetException e) {
        throw new FlinkHiveException("Failed to create RexSubQuery", e);
    }
}
Also used : RelNode(org.apache.calcite.rel.RelNode) FlinkHiveException(org.apache.flink.connectors.hive.FlinkHiveException) Method(java.lang.reflect.Method) RexSubQuery(org.apache.calcite.rex.RexSubQuery) InvocationTargetException(java.lang.reflect.InvocationTargetException)

Example 2 with RexSubQuery

use of org.apache.calcite.rex.RexSubQuery 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)

Example 3 with RexSubQuery

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

the class HiveSubQueryRemoveRule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    final RelNode relNode = call.rel(0);
    final RelBuilder builder = call.builder();
    // if subquery is in FILTER
    if (relNode instanceof HiveFilter) {
        final HiveFilter filter = call.rel(0);
        final RexSubQuery e = RexUtil.SubQueryFinder.find(filter.getCondition());
        assert e != null;
        final RelOptUtil.Logic logic = LogicVisitor.find(RelOptUtil.Logic.TRUE, ImmutableList.of(filter.getCondition()), e);
        builder.push(filter.getInput());
        final int fieldCount = builder.peek().getRowType().getFieldCount();
        SubqueryConf subqueryConfig = filter.getCluster().getPlanner().getContext().unwrap(SubqueryConf.class);
        boolean isCorrScalarQuery = subqueryConfig.getCorrScalarRexSQWithAgg().contains(e.rel);
        final RexNode target = apply(call.getMetadataQuery(), e, HiveFilter.getVariablesSet(e), logic, builder, 1, fieldCount, isCorrScalarQuery);
        final RexShuttle shuttle = new ReplaceSubQueryShuttle(e, target);
        builder.filter(shuttle.apply(filter.getCondition()));
        builder.project(fields(builder, filter.getRowType().getFieldCount()));
        RelNode newRel = builder.build();
        call.transformTo(newRel);
    } else if (relNode instanceof HiveProject) {
        // if subquery is in PROJECT
        final HiveProject project = call.rel(0);
        final RexSubQuery e = RexUtil.SubQueryFinder.find(project.getProjects());
        assert e != null;
        final RelOptUtil.Logic logic = LogicVisitor.find(RelOptUtil.Logic.TRUE_FALSE_UNKNOWN, project.getProjects(), e);
        builder.push(project.getInput());
        final int fieldCount = builder.peek().getRowType().getFieldCount();
        SubqueryConf subqueryConfig = project.getCluster().getPlanner().getContext().unwrap(SubqueryConf.class);
        boolean isCorrScalarQuery = subqueryConfig.getCorrScalarRexSQWithAgg().contains(e.rel);
        final RexNode target = apply(call.getMetadataQuery(), e, HiveFilter.getVariablesSet(e), logic, builder, 1, fieldCount, isCorrScalarQuery);
        final RexShuttle shuttle = new ReplaceSubQueryShuttle(e, target);
        builder.project(shuttle.apply(project.getProjects()), project.getRowType().getFieldNames());
        call.transformTo(builder.build());
    }
}
Also used : RelBuilder(org.apache.calcite.tools.RelBuilder) RexShuttle(org.apache.calcite.rex.RexShuttle) RelOptUtil(org.apache.calcite.plan.RelOptUtil) SubqueryConf(org.apache.hadoop.hive.ql.optimizer.calcite.SubqueryConf) HiveFilter(org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveFilter) RelNode(org.apache.calcite.rel.RelNode) HiveProject(org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveProject) RexSubQuery(org.apache.calcite.rex.RexSubQuery) RexNode(org.apache.calcite.rex.RexNode)

Example 4 with RexSubQuery

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

the class HiveFilter method traverseFilter.

// traverse the given node to find all correlated variables
// Note that correlated variables are supported in Filter only i.e. Where & Having
private static void traverseFilter(RexNode node, Set<CorrelationId> allVars) {
    if (node instanceof RexSubQuery) {
        RexSubQuery rexSubQuery = (RexSubQuery) node;
        // Also check for case where operator has 0 inputs .e.g TableScan
        if (rexSubQuery.rel.getInputs().isEmpty()) {
            return;
        }
        RelNode input = rexSubQuery.rel.getInput(0);
        while (input != null && !(input instanceof HiveFilter) && input.getInputs().size() >= 1) {
            // we don't expect corr vars within UNION for now
            if (input.getInputs().size() > 1) {
                if (input instanceof HiveJoin) {
                    findCorrelatedVar(((HiveJoin) input).getJoinFilter(), allVars);
                }
                return;
            }
            input = input.getInput(0);
        }
        if (input != null && input instanceof HiveFilter) {
            findCorrelatedVar(((HiveFilter) input).getCondition(), allVars);
        }
        return;
    }
    // AND, NOT etc
    if (node instanceof RexCall) {
        int numOperands = ((RexCall) node).getOperands().size();
        for (int i = 0; i < numOperands; i++) {
            RexNode op = ((RexCall) node).getOperands().get(i);
            traverseFilter(op, allVars);
        }
    }
}
Also used : RexCall(org.apache.calcite.rex.RexCall) RelNode(org.apache.calcite.rel.RelNode) RexSubQuery(org.apache.calcite.rex.RexSubQuery) RexNode(org.apache.calcite.rex.RexNode)

Example 5 with RexSubQuery

use of org.apache.calcite.rex.RexSubQuery in project hazelcast by hazelcast.

the class QueryConverter method hasNestedExists.

private static boolean hasNestedExists(RelNode root) {
    class NestedExistsFinder extends RelVisitor {

        private boolean found;

        private int depth;

        @Override
        public void visit(RelNode node, int ordinal, @Nullable RelNode parent) {
            if (node instanceof LogicalFilter) {
                RexSubQuery exists = getExists((LogicalFilter) node);
                if (exists != null) {
                    found |= depth > 0;
                    depth++;
                    go(exists.rel);
                    depth--;
                }
            }
            super.visit(node, ordinal, parent);
        }

        private boolean find() {
            go(root);
            return found;
        }

        private RexSubQuery getExists(LogicalFilter filter) {
            RexSubQuery[] existsSubQuery = { null };
            filter.getCondition().accept(new RexVisitorImpl<Void>(true) {

                @Override
                public Void visitSubQuery(RexSubQuery subQuery) {
                    if (subQuery.getKind() == SqlKind.EXISTS) {
                        existsSubQuery[0] = subQuery;
                    }
                    return super.visitSubQuery(subQuery);
                }
            });
            return existsSubQuery[0];
        }
    }
    return new NestedExistsFinder().find();
}
Also used : RelNode(org.apache.calcite.rel.RelNode) LogicalFilter(org.apache.calcite.rel.logical.LogicalFilter) RelVisitor(org.apache.calcite.rel.RelVisitor) RexSubQuery(org.apache.calcite.rex.RexSubQuery) Nullable(javax.annotation.Nullable)

Aggregations

RexSubQuery (org.apache.calcite.rex.RexSubQuery)6 RelNode (org.apache.calcite.rel.RelNode)5 RexNode (org.apache.calcite.rex.RexNode)4 RexCall (org.apache.calcite.rex.RexCall)2 RexVisitorImpl (org.apache.calcite.rex.RexVisitorImpl)2 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 Method (java.lang.reflect.Method)1 ArrayList (java.util.ArrayList)1 Nullable (javax.annotation.Nullable)1 RelOptUtil (org.apache.calcite.plan.RelOptUtil)1 RelVisitor (org.apache.calcite.rel.RelVisitor)1 LogicalFilter (org.apache.calcite.rel.logical.LogicalFilter)1 RexCorrelVariable (org.apache.calcite.rex.RexCorrelVariable)1 RexFieldAccess (org.apache.calcite.rex.RexFieldAccess)1 RexShuttle (org.apache.calcite.rex.RexShuttle)1 RelBuilder (org.apache.calcite.tools.RelBuilder)1 Pair (org.apache.calcite.util.Pair)1 FlinkHiveException (org.apache.flink.connectors.hive.FlinkHiveException)1 SubqueryConf (org.apache.hadoop.hive.ql.optimizer.calcite.SubqueryConf)1 HiveFilter (org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveFilter)1