org.apache.calcite.plan.RelOptPredicateList - java examples

Here are the examples of the java api org.apache.calcite.plan.RelOptPredicateList taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

36 Examples 7

19 View Complete Implementation : RelMdMaxRowCount.java
Copyright Apache License 2.0
Author : apache
public Double getMaxRowCount(Aggregate rel, RelMetadataQuery mq) {
    if (rel.getGroupSet().isEmpty()) {
        // Aggregate with no GROUP BY always returns 1 row (even on empty table).
        return 1D;
    }
    // Aggregate with constant GROUP BY always returns 1 row
    if (rel.getGroupType() == Aggregate.Group.SIMPLE) {
        final RelOptPredicateList predicateList = mq.getPulledUpPredicates(rel.getInput());
        if (predicateList != null && allGroupKeysAreConstant(rel, predicateList)) {
            return 1D;
        }
    }
    final Double rowCount = mq.getMaxRowCount(rel.getInput());
    if (rowCount == null) {
        return null;
    }
    return rowCount * rel.getGroupSets().size();
}

19 View Complete Implementation : ReduceExpressionsRule.java
Copyright Apache License 2.0
Author : apache
// to be removed before 2.0
@Deprecated
protected static boolean reduceExpressions(RelNode rel, List<RexNode> expList, RelOptPredicateList predicates, boolean unknownAsFalse) {
    return reduceExpressions(rel, expList, predicates, unknownAsFalse, true);
}

19 View Complete Implementation : ReduceExpressionsRule.java
Copyright Apache License 2.0
Author : apache
// ~ Methods ----------------------------------------------------------------
/**
 * Reduces a list of expressions.
 *
 * @param rel     Relational expression
 * @param expList List of expressions, modified in place
 * @param predicates Constraints known to hold on input expressions
 * @return whether reduction found something to change, and succeeded
 */
protected static boolean reduceExpressions(RelNode rel, List<RexNode> expList, RelOptPredicateList predicates) {
    return reduceExpressions(rel, expList, predicates, false, true);
}

19 View Complete Implementation : ReduceExpressionsRule.java
Copyright Apache License 2.0
Author : apache
/**
 * Creates a map containing each (e, constant) pair that occurs within
 * a predicate list.
 *
 * @param clazz Clreplaced of expression that is considered constant
 * @param rexBuilder Rex builder
 * @param predicates Predicate list
 * @param <C> what to consider a constant: {@link RexLiteral} to use a narrow
 *           definition of constant, or {@link RexNode} to use
 *           {@link RexUtil#isConstant(RexNode)}
 * @return Map from values to constants
 *
 * @deprecated Use {@link RelOptPredicateList#constantMap}
 */
// to be removed before 2.0
@Deprecated
public static <C extends RexNode> ImmutableMap<RexNode, C> predicateConstants(Clreplaced<C> clazz, RexBuilder rexBuilder, RelOptPredicateList predicates) {
    return RexUtil.predicateConstants(clazz, rexBuilder, predicates.pulledUpPredicates);
}

18 View Complete Implementation : RelMdColumnUniqueness.java
Copyright Apache License 2.0
Author : apache
/**
 * Deduce constant columns from predicates of rel and return the union
 * bitsets of checkingColumns and the constant columns.
 */
private static ImmutableBitSet decorateWithConstantColumnsFromPredicates(ImmutableBitSet checkingColumns, RelNode rel, RelMetadataQuery mq) {
    final RelOptPredicateList predicates = mq.getPulledUpPredicates(rel);
    if (predicates != null) {
        final Set<Integer> constantIndexes = new HashSet();
        predicates.constantMap.keySet().forEach(rex -> {
            if (rex instanceof RexInputRef) {
                constantIndexes.add(((RexInputRef) rex).getIndex());
            }
        });
        if (!constantIndexes.isEmpty()) {
            return checkingColumns.union(ImmutableBitSet.of(constantIndexes));
        }
    }
    // If no constant columns deduced, return the original "checkingColumns".
    return checkingColumns;
}

18 View Complete Implementation : RelMdMaxRowCount.java
Copyright Apache License 2.0
Author : apache
private static boolean allGroupKeysAreConstant(Aggregate aggregate, RelOptPredicateList predicateList) {
    final RexBuilder rexBuilder = aggregate.getCluster().getRexBuilder();
    for (int key : aggregate.getGroupSet()) {
        if (!predicateList.constantMap.containsKey(rexBuilder.makeInputRef(aggregate.getInput(), key))) {
            return false;
        }
    }
    return true;
}

18 View Complete Implementation : RelMdPredicates.java
Copyright Apache License 2.0
Author : apache
/**
 * Infers predicates for a {@link org.apache.calcite.rel.core.Join} (including
 * {@code SemiJoin}).
 */
public RelOptPredicateList getPredicates(Join join, RelMetadataQuery mq) {
    RelOptCluster cluster = join.getCluster();
    RexBuilder rexBuilder = cluster.getRexBuilder();
    final RexExecutor executor = Util.first(cluster.getPlanner().getExecutor(), RexUtil.EXECUTOR);
    final RelNode left = join.getInput(0);
    final RelNode right = join.getInput(1);
    final RelOptPredicateList leftInfo = mq.getPulledUpPredicates(left);
    final RelOptPredicateList rightInfo = mq.getPulledUpPredicates(right);
    JoinConditionBasedPredicateInference joinInference = new JoinConditionBasedPredicateInference(join, RexUtil.composeConjunction(rexBuilder, leftInfo.pulledUpPredicates), RexUtil.composeConjunction(rexBuilder, rightInfo.pulledUpPredicates), new RexSimplify(rexBuilder, RelOptPredicateList.EMPTY, executor));
    return joinInference.inferPredicates(false);
}

18 View Complete Implementation : RexProgram.java
Copyright Apache License 2.0
Author : apache
// to be removed before 2.0
@Deprecated
public RexProgram normalize(RexBuilder rexBuilder, boolean simplify) {
    final RelOptPredicateList predicates = RelOptPredicateList.EMPTY;
    return normalize(rexBuilder, simplify ? new RexSimplify(rexBuilder, predicates, RexUtil.EXECUTOR) : null);
}

18 View Complete Implementation : RexProgramTestBase.java
Copyright Apache License 2.0
Author : apache
protected void checkSimplifyFilter(RexNode node, RelOptPredicateList predicates, String expected) {
    final RexNode simplified = simplify.withPredicates(predicates).simplifyUnknownAs(node, RexUnknownAs.FALSE);
    replacedertThat(simplified.toStringRaw(), equalTo(expected));
}

18 View Complete Implementation : RelMdPredicates.java
Copyright Apache License 2.0
Author : lealone
/**
 * Infers predicates for a {@link org.apache.calcite.rel.core.Join} (including
 * {@link org.apache.calcite.rel.core.SemiJoin}).
 */
public RelOptPredicateList getPredicates(Join join, RelMetadataQuery mq) {
    RelOptCluster cluster = join.getCluster();
    RexBuilder rexBuilder = cluster.getRexBuilder();
    final RexExecutor executor = Util.first(cluster.getPlanner().getExecutor(), RexUtil.EXECUTOR);
    final RelNode left = join.getInput(0);
    final RelNode right = join.getInput(1);
    final RelOptPredicateList leftInfo = mq.getPulledUpPredicates(left);
    final RelOptPredicateList rightInfo = mq.getPulledUpPredicates(right);
    JoinConditionBasedPredicateInference joinInference = new JoinConditionBasedPredicateInference(join, RexUtil.composeConjunction(rexBuilder, leftInfo.pulledUpPredicates), RexUtil.composeConjunction(rexBuilder, rightInfo.pulledUpPredicates), new RexSimplify(rexBuilder, RelOptPredicateList.EMPTY, executor));
    return joinInference.inferPredicates(false);
}

17 View Complete Implementation : RelMdPredicates.java
Copyright Apache License 2.0
Author : apache
/**
 * @see RelMetadataQuery#getPulledUpPredicates(RelNode)
 */
public RelOptPredicateList getPredicates(RelSubset r, RelMetadataQuery mq) {
    if (!Bug.CALCITE_1048_FIXED) {
        return RelOptPredicateList.EMPTY;
    }
    final RexBuilder rexBuilder = r.getCluster().getRexBuilder();
    RelOptPredicateList list = null;
    for (RelNode r2 : r.getRels()) {
        RelOptPredicateList list2 = mq.getPulledUpPredicates(r2);
        if (list2 != null) {
            list = list == null ? list2 : list.union(rexBuilder, list2);
        }
    }
    return Util.first(list, RelOptPredicateList.EMPTY);
}

17 View Complete Implementation : ReduceExpressionsRule.java
Copyright Apache License 2.0
Author : apache
/**
 * Reduces a list of expressions.
 *
 * <p>The {@code matchNullability} flag comes into play when reducing a
 * expression whose type is nullable. Suppose we are reducing an expression
 * {@code CASE WHEN 'a' = 'a' THEN 1 ELSE NULL END}. Before reduction the
 * type is {@code INTEGER} (nullable), but after reduction the literal 1 has
 * type {@code INTEGER NOT NULL}.
 *
 * <p>In some situations it is more important to preserve types; in this
 * case you should use {@code matchNullability = true} (which used to be
 * the default behavior of this method), and it will cast the literal to
 * {@code INTEGER} (nullable).
 *
 * <p>In other situations, you would rather propagate the new stronger type,
 * because it may allow further optimizations later; preplaced
 * {@code matchNullability = false} and no cast will be added, but you may
 * need to adjust types elsewhere in the expression tree.
 *
 * @param rel     Relational expression
 * @param expList List of expressions, modified in place
 * @param predicates Constraints known to hold on input expressions
 * @param unknownAsFalse Whether UNKNOWN will be treated as FALSE
 * @param matchNullability Whether Calcite should add a CAST to a literal
 *                         resulting from simplification and expression if the
 *                         expression had nullable type and the literal is
 *                         NOT NULL
 *
 * @return whether reduction found something to change, and succeeded
 */
protected static boolean reduceExpressions(RelNode rel, List<RexNode> expList, RelOptPredicateList predicates, boolean unknownAsFalse, boolean matchNullability) {
    final RelOptCluster cluster = rel.getCluster();
    final RexBuilder rexBuilder = cluster.getRexBuilder();
    final RexExecutor executor = Util.first(cluster.getPlanner().getExecutor(), RexUtil.EXECUTOR);
    final RexSimplify simplify = new RexSimplify(rexBuilder, predicates, executor);
    // Simplify predicates in place
    final RexUnknownAs unknownAs = RexUnknownAs.falseIf(unknownAsFalse);
    final boolean reduced = reduceExpressionsInternal(rel, simplify, unknownAs, expList, predicates);
    boolean simplified = false;
    for (int i = 0; i < expList.size(); i++) {
        final RexNode expr2 = simplify.simplifyPreservingType(expList.get(i), unknownAs, matchNullability);
        if (!expr2.equals(expList.get(i))) {
            expList.set(i, expr2);
            simplified = true;
        }
    }
    return reduced || simplified;
}

15 View Complete Implementation : RelMdAllPredicates.java
Copyright Apache License 2.0
Author : apache
/**
 * Add the Filter condition to the list obtained from the input.
 */
public RelOptPredicateList getAllPredicates(Filter filter, RelMetadataQuery mq) {
    final RelNode input = filter.getInput();
    final RexBuilder rexBuilder = filter.getCluster().getRexBuilder();
    final RexNode pred = filter.getCondition();
    final RelOptPredicateList predsBelow = mq.getAllPredicates(input);
    if (predsBelow == null) {
        // Safety check
        return null;
    }
    // Extract input fields referenced by Filter condition
    final Set<RelDataTypeField> inputExtraFields = new LinkedHashSet<>();
    final RelOptUtil.InputFinder inputFinder = new RelOptUtil.InputFinder(inputExtraFields);
    pred.accept(inputFinder);
    final ImmutableBitSet inputFieldsUsed = inputFinder.inputBitSet.build();
    // Infer column origin expressions for given references
    final Map<RexInputRef, Set<RexNode>> mapping = new LinkedHashMap<>();
    for (int idx : inputFieldsUsed) {
        final RexInputRef ref = RexInputRef.of(idx, filter.getRowType().getFieldList());
        final Set<RexNode> originalExprs = mq.getExpressionLineage(filter, ref);
        if (originalExprs == null) {
            // Bail out
            return null;
        }
        mapping.put(ref, originalExprs);
    }
    // Replace with new expressions and return union of predicates
    final Set<RexNode> allExprs = RelMdExpressionLineage.createAllPossibleExpressions(rexBuilder, pred, mapping);
    if (allExprs == null) {
        return null;
    }
    return predsBelow.union(rexBuilder, RelOptPredicateList.of(rexBuilder, allExprs));
}

15 View Complete Implementation : RelMdPredicates.java
Copyright Apache License 2.0
Author : apache
/**
 * Infers predicates for a Intersect.
 */
public RelOptPredicateList getPredicates(Intersect intersect, RelMetadataQuery mq) {
    final RexBuilder rexBuilder = intersect.getCluster().getRexBuilder();
    final RexExecutorImpl rexImpl = (RexExecutorImpl) (intersect.getCluster().getPlanner().getExecutor());
    final RexImplicationChecker rexImplicationChecker = new RexImplicationChecker(rexBuilder, rexImpl, intersect.getRowType());
    Set<RexNode> finalPredicates = new HashSet<>();
    for (Ord<RelNode> input : Ord.zip(intersect.getInputs())) {
        RelOptPredicateList info = mq.getPulledUpPredicates(input.e);
        if (info == null || info.pulledUpPredicates.isEmpty()) {
            continue;
        }
        for (RexNode pred : info.pulledUpPredicates) {
            if (finalPredicates.stream().anyMatch(finalPred -> rexImplicationChecker.implies(finalPred, pred))) {
                // There's already a stricter predicate in finalPredicates,
                // thus no need to count this one.
                continue;
            }
            // Remove looser predicate and add this one into finalPredicates
            finalPredicates = finalPredicates.stream().filter(finalPred -> !rexImplicationChecker.implies(pred, finalPred)).collect(Collectors.toSet());
            finalPredicates.add(pred);
        }
    }
    return RelOptPredicateList.of(rexBuilder, finalPredicates);
}

15 View Complete Implementation : RelMdPredicates.java
Copyright Apache License 2.0
Author : apache
/**
 * Add the Filter condition to the pulledPredicates list from the input.
 */
public RelOptPredicateList getPredicates(Filter filter, RelMetadataQuery mq) {
    final RelNode input = filter.getInput();
    final RexBuilder rexBuilder = filter.getCluster().getRexBuilder();
    final RelOptPredicateList inputInfo = mq.getPulledUpPredicates(input);
    return Util.first(inputInfo, RelOptPredicateList.EMPTY).union(rexBuilder, RelOptPredicateList.of(rexBuilder, RexUtil.retainDeterministic(RelOptUtil.conjunctions(filter.getCondition()))));
}

15 View Complete Implementation : ReduceExpressionsRule.java
Copyright Apache License 2.0
Author : apache
protected static boolean reduceExpressionsInternal(RelNode rel, RexSimplify simplify, RexUnknownAs unknownAs, List<RexNode> expList, RelOptPredicateList predicates) {
    // Replace predicates on CASE to CASE on predicates.
    boolean changed = new CaseShuttle().mutate(expList);
    // Find reducible expressions.
    final List<RexNode> constExps = new ArrayList<>();
    List<Boolean> addCasts = new ArrayList<>();
    final List<RexNode> removableCasts = new ArrayList<>();
    findReducibleExps(rel.getCluster().getTypeFactory(), expList, predicates.constantMap, constExps, addCasts, removableCasts);
    if (constExps.isEmpty() && removableCasts.isEmpty()) {
        return changed;
    }
    // Remove redundant casts before reducing constant expressions.
    // If the argument to the redundant cast is a reducible constant,
    // reducing that argument to a constant first will result in not being
    // able to locate the original cast expression.
    if (!removableCasts.isEmpty()) {
        final List<RexNode> reducedExprs = new ArrayList<>();
        for (RexNode exp : removableCasts) {
            RexCall call = (RexCall) exp;
            reducedExprs.add(call.getOperands().get(0));
        }
        RexReplacer replacer = new RexReplacer(simplify, unknownAs, removableCasts, reducedExprs, Collections.nCopies(removableCasts.size(), false));
        replacer.mutate(expList);
    }
    if (constExps.isEmpty()) {
        return true;
    }
    final List<RexNode> constExps2 = Lists.newArrayList(constExps);
    if (!predicates.constantMap.isEmpty()) {
        // noinspection unchecked
        final List<Map.Entry<RexNode, RexNode>> pairs = Lists.newArrayList(predicates.constantMap.entrySet());
        RexReplacer replacer = new RexReplacer(simplify, unknownAs, Pair.left(pairs), Pair.right(pairs), Collections.nCopies(pairs.size(), false));
        replacer.mutate(constExps2);
    }
    // Compute the values they reduce to.
    RexExecutor executor = rel.getCluster().getPlanner().getExecutor();
    if (executor == null) {
        // Cannot reduce expressions: caller has not set an executor in their
        // environment. Caller should execute something like the following before
        // invoking the planner:
        // 
        // final RexExecutorImpl executor =
        // new RexExecutorImpl(Schemas.createDataContext(null));
        // rootRel.getCluster().getPlanner().setExecutor(executor);
        return changed;
    }
    final List<RexNode> reducedValues = new ArrayList<>();
    executor.reduce(simplify.rexBuilder, constExps2, reducedValues);
    // Use RexNode.digest to judge whether each newly generated RexNode
    // is equivalent to the original one.
    if (RexUtil.strings(constExps).equals(RexUtil.strings(reducedValues))) {
        return changed;
    }
    // For Project, we have to be sure to preserve the result
    // types, so always cast regardless of the expression type.
    // For other RelNodes like Filter, in general, this isn't necessary,
    // and the presence of casts could hinder other rules such as sarg
    // replacedysis, which require bare literals.  But there are special cases,
    // like when the expression is a UDR argument, that need to be
    // handled as special cases.
    if (rel instanceof Project) {
        addCasts = Collections.nCopies(reducedValues.size(), true);
    }
    new RexReplacer(simplify, unknownAs, constExps, reducedValues, addCasts).mutate(expList);
    return true;
}

15 View Complete Implementation : ReduceExpressionsRule.java
Copyright Apache License 2.0
Author : lealone
protected static boolean reduceExpressionsInternal(RelNode rel, RexSimplify simplify, RexUnknownAs unknownAs, List<RexNode> expList, RelOptPredicateList predicates) {
    boolean changed = false;
    // Replace predicates on CASE to CASE on predicates.
    changed |= new CaseShuttle().mutate(expList);
    // Find reducible expressions.
    final List<RexNode> constExps = new ArrayList<>();
    List<Boolean> addCasts = new ArrayList<>();
    final List<RexNode> removableCasts = new ArrayList<>();
    findReducibleExps(rel.getCluster().getTypeFactory(), expList, predicates.constantMap, constExps, addCasts, removableCasts);
    if (constExps.isEmpty() && removableCasts.isEmpty()) {
        return changed;
    }
    // Remove redundant casts before reducing constant expressions.
    // If the argument to the redundant cast is a reducible constant,
    // reducing that argument to a constant first will result in not being
    // able to locate the original cast expression.
    if (!removableCasts.isEmpty()) {
        final List<RexNode> reducedExprs = new ArrayList<>();
        for (RexNode exp : removableCasts) {
            RexCall call = (RexCall) exp;
            reducedExprs.add(call.getOperands().get(0));
        }
        RexReplacer replacer = new RexReplacer(simplify, unknownAs, removableCasts, reducedExprs, Collections.nCopies(removableCasts.size(), false));
        replacer.mutate(expList);
    }
    if (constExps.isEmpty()) {
        return true;
    }
    final List<RexNode> constExps2 = Lists.newArrayList(constExps);
    if (!predicates.constantMap.isEmpty()) {
        // noinspection unchecked
        final List<Map.Entry<RexNode, RexNode>> pairs = Lists.newArrayList(predicates.constantMap.entrySet());
        RexReplacer replacer = new RexReplacer(simplify, unknownAs, Pair.left(pairs), Pair.right(pairs), Collections.nCopies(pairs.size(), false));
        replacer.mutate(constExps2);
    }
    // Compute the values they reduce to.
    RexExecutor executor = rel.getCluster().getPlanner().getExecutor();
    if (executor == null) {
        // Cannot reduce expressions: caller has not set an executor in their
        // environment. Caller should execute something like the following before
        // invoking the planner:
        // 
        // final RexExecutorImpl executor =
        // new RexExecutorImpl(Schemas.createDataContext(null));
        // rootRel.getCluster().getPlanner().setExecutor(executor);
        return changed;
    }
    final List<RexNode> reducedValues = new ArrayList<>();
    executor.reduce(simplify.rexBuilder, constExps2, reducedValues);
    // Use RexNode.digest to judge whether each newly generated RexNode
    // is equivalent to the original one.
    if (RexUtil.strings(constExps).equals(RexUtil.strings(reducedValues))) {
        return changed;
    }
    // For Project, we have to be sure to preserve the result
    // types, so always cast regardless of the expression type.
    // For other RelNodes like Filter, in general, this isn't necessary,
    // and the presence of casts could hinder other rules such as sarg
    // replacedysis, which require bare literals.  But there are special cases,
    // like when the expression is a UDR argument, that need to be
    // handled as special cases.
    if (rel instanceof Project) {
        addCasts = Collections.nCopies(reducedValues.size(), true);
    }
    new RexReplacer(simplify, unknownAs, constExps, reducedValues, addCasts).mutate(expList);
    return true;
}

14 View Complete Implementation : RelMdAllPredicates.java
Copyright Apache License 2.0
Author : apache
/**
 * Extract predicates for a Union.
 */
public RelOptPredicateList getAllPredicates(Union union, RelMetadataQuery mq) {
    final RexBuilder rexBuilder = union.getCluster().getRexBuilder();
    final Multimap<List<String>, RelTableRef> qualifiedNamesToRefs = HashMultimap.create();
    RelOptPredicateList newPreds = RelOptPredicateList.EMPTY;
    for (int i = 0; i < union.getInputs().size(); i++) {
        final RelNode input = union.getInput(i);
        final RelOptPredicateList inputPreds = mq.getAllPredicates(input);
        if (inputPreds == null) {
            // Bail out
            return null;
        }
        // Gather table references
        final Set<RelTableRef> tableRefs = mq.getTableReferences(input);
        if (i == 0) {
            // Left input references remain unchanged
            for (RelTableRef leftRef : tableRefs) {
                qualifiedNamesToRefs.put(leftRef.getQualifiedName(), leftRef);
            }
            newPreds = newPreds.union(rexBuilder, inputPreds);
        } else {
            // Right input references might need to be updated if there are table name
            // clashes with left input
            final Map<RelTableRef, RelTableRef> currentTablesMapping = new HashMap<>();
            for (RelTableRef rightRef : tableRefs) {
                int shift = 0;
                Collection<RelTableRef> lRefs = qualifiedNamesToRefs.get(rightRef.getQualifiedName());
                if (lRefs != null) {
                    shift = lRefs.size();
                }
                currentTablesMapping.put(rightRef, RelTableRef.of(rightRef.getTable(), shift + rightRef.getEnreplacedyNumber()));
            }
            // Add to existing qualified names
            for (RelTableRef newRef : currentTablesMapping.values()) {
                qualifiedNamesToRefs.put(newRef.getQualifiedName(), newRef);
            }
            // Update preds
            final List<RexNode> updatedPreds = Lists.newArrayList(Iterables.transform(inputPreds.pulledUpPredicates, e -> RexUtil.swapTableReferences(rexBuilder, e, currentTablesMapping)));
            newPreds = newPreds.union(rexBuilder, RelOptPredicateList.of(rexBuilder, updatedPreds));
        }
    }
    return newPreds;
}

14 View Complete Implementation : RelMdPredicates.java
Copyright Apache License 2.0
Author : apache
/**
 * Infers predicates for an Aggregate.
 *
 * <p>Pulls up predicates that only contains references to columns in the
 * GroupSet. For e.g.
 *
 * <blockquote><pre>
 * inputPullUpExprs : { a > 7, b + c < 10, a + e = 9}
 * groupSet         : { a, b}
 * pulledUpExprs    : { a > 7}
 * </pre></blockquote>
 */
public RelOptPredicateList getPredicates(Aggregate agg, RelMetadataQuery mq) {
    final RelNode input = agg.getInput();
    final RexBuilder rexBuilder = agg.getCluster().getRexBuilder();
    final RelOptPredicateList inputInfo = mq.getPulledUpPredicates(input);
    final List<RexNode> aggPullUpPredicates = new ArrayList<>();
    ImmutableBitSet groupKeys = agg.getGroupSet();
    if (groupKeys.isEmpty()) {
        // "GROUP BY ()" can convert an empty relation to a non-empty relation, so
        // it is not valid to pull up predicates. In particular, consider the
        // predicate "false": it is valid on all input rows (trivially - there are
        // no rows!) but not on the output (there is one row).
        return RelOptPredicateList.EMPTY;
    }
    Mapping m = Mappings.create(MappingType.PARTIAL_FUNCTION, input.getRowType().getFieldCount(), agg.getRowType().getFieldCount());
    int i = 0;
    for (int j : groupKeys) {
        m.set(j, i++);
    }
    for (RexNode r : inputInfo.pulledUpPredicates) {
        ImmutableBitSet rCols = RelOptUtil.InputFinder.bits(r);
        if (groupKeys.contains(rCols)) {
            r = r.accept(new RexPermuteInputsShuttle(m, input));
            aggPullUpPredicates.add(r);
        }
    }
    return RelOptPredicateList.of(rexBuilder, aggPullUpPredicates);
}

13 View Complete Implementation : RelMdPredicates.java
Copyright Apache License 2.0
Author : dremio
public RelOptPredicateList getPredicates(RelSubset subset, RelMetadataQuery mq) {
    // Currently disabled in Calcite upstream
    // Only go over the best node if it exists, and try the original node otherwise
    RelOptPredicateList predicates = mq.getPulledUpPredicates(Util.first(subset.getBest(), subset.getOriginal()));
    return predicates;
}

12 View Complete Implementation : RelMdPredicates.java
Copyright Apache License 2.0
Author : apache
/**
 * Infers predicates for a project.
 *
 * <ol>
 * <li>create a mapping from input to projection. Map only positions that
 * directly reference an input column.
 * <li>Expressions that only contain above columns are retained in the
 * Project's pullExpressions list.
 * <li>For e.g. expression 'a + e = 9' below will not be pulled up because 'e'
 * is not in the projection list.
 *
 * <blockquote><pre>
 * inputPullUpExprs:      {a > 7, b + c < 10, a + e = 9}
 * projectionExprs:       {a, b, c, e / 2}
 * projectionPullupExprs: {a > 7, b + c < 10}
 * </pre></blockquote>
 *
 * </ol>
 */
public RelOptPredicateList getPredicates(Project project, RelMetadataQuery mq) {
    final RelNode input = project.getInput();
    final RexBuilder rexBuilder = project.getCluster().getRexBuilder();
    final RelOptPredicateList inputInfo = mq.getPulledUpPredicates(input);
    final List<RexNode> projectPullUpPredicates = new ArrayList<>();
    ImmutableBitSet.Builder columnsMappedBuilder = ImmutableBitSet.builder();
    Mapping m = Mappings.create(MappingType.PARTIAL_FUNCTION, input.getRowType().getFieldCount(), project.getRowType().getFieldCount());
    for (Ord<RexNode> expr : Ord.zip(project.getProjects())) {
        if (expr.e instanceof RexInputRef) {
            int sIdx = ((RexInputRef) expr.e).getIndex();
            m.set(sIdx, expr.i);
            columnsMappedBuilder.set(sIdx);
        // Project can also generate constants. We need to include them.
        } else if (RexLiteral.isNullLiteral(expr.e)) {
            projectPullUpPredicates.add(rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL, rexBuilder.makeInputRef(project, expr.i)));
        } else if (RexUtil.isConstant(expr.e)) {
            final List<RexNode> args = ImmutableList.of(rexBuilder.makeInputRef(project, expr.i), expr.e);
            final SqlOperator op = args.get(0).getType().isNullable() || args.get(1).getType().isNullable() ? SqlStdOperatorTable.IS_NOT_DISTINCT_FROM : SqlStdOperatorTable.EQUALS;
            projectPullUpPredicates.add(rexBuilder.makeCall(op, args));
        }
    }
    // Go over childPullUpPredicates. If a predicate only contains columns in
    // 'columnsMapped' construct a new predicate based on mapping.
    final ImmutableBitSet columnsMapped = columnsMappedBuilder.build();
    for (RexNode r : inputInfo.pulledUpPredicates) {
        RexNode r2 = projectPredicate(rexBuilder, input, r, columnsMapped);
        if (!r2.isAlwaysTrue()) {
            r2 = r2.accept(new RexPermuteInputsShuttle(m, input));
            projectPullUpPredicates.add(r2);
        }
    }
    return RelOptPredicateList.of(rexBuilder, projectPullUpPredicates);
}

12 View Complete Implementation : RelMdAllPredicates.java
Copyright Apache License 2.0
Author : lealone
/**
 * Add the Join condition to the list obtained from the input.
 */
public RelOptPredicateList getAllPredicates(Join join, RelMetadataQuery mq) {
    if (join.getJoinType() != JoinRelType.INNER) {
        // We cannot map origin of this expression.
        return null;
    }
    final RexBuilder rexBuilder = join.getCluster().getRexBuilder();
    final RexNode pred = join.getCondition();
    final Multimap<List<String>, RelTableRef> qualifiedNamesToRefs = HashMultimap.create();
    RelOptPredicateList newPreds = RelOptPredicateList.EMPTY;
    for (RelNode input : join.getInputs()) {
        final RelOptPredicateList inputPreds = mq.getAllPredicates(input);
        if (inputPreds == null) {
            // Bail out
            return null;
        }
        // Gather table references
        final Set<RelTableRef> tableRefs = mq.getTableReferences(input);
        if (input == join.getLeft()) {
            // Left input references remain unchanged
            for (RelTableRef leftRef : tableRefs) {
                qualifiedNamesToRefs.put(leftRef.getQualifiedName(), leftRef);
            }
            newPreds = newPreds.union(rexBuilder, inputPreds);
        } else {
            // Right input references might need to be updated if there are table name
            // clashes with left input
            final Map<RelTableRef, RelTableRef> currentTablesMapping = new HashMap<>();
            for (RelTableRef rightRef : tableRefs) {
                int shift = 0;
                Collection<RelTableRef> lRefs = qualifiedNamesToRefs.get(rightRef.getQualifiedName());
                if (lRefs != null) {
                    shift = lRefs.size();
                }
                currentTablesMapping.put(rightRef, RelTableRef.of(rightRef.getTable(), shift + rightRef.getEnreplacedyNumber()));
            }
            final List<RexNode> updatedPreds = Lists.newArrayList(Iterables.transform(inputPreds.pulledUpPredicates, e -> RexUtil.swapTableReferences(rexBuilder, e, currentTablesMapping)));
            newPreds = newPreds.union(rexBuilder, RelOptPredicateList.of(rexBuilder, updatedPreds));
        }
    }
    // Extract input fields referenced by Join condition
    final Set<RelDataTypeField> inputExtraFields = new LinkedHashSet<>();
    final RelOptUtil.InputFinder inputFinder = new RelOptUtil.InputFinder(inputExtraFields);
    pred.accept(inputFinder);
    final ImmutableBitSet inputFieldsUsed = inputFinder.inputBitSet.build();
    // Infer column origin expressions for given references
    final Map<RexInputRef, Set<RexNode>> mapping = new LinkedHashMap<>();
    for (int idx : inputFieldsUsed) {
        final RexInputRef inputRef = RexInputRef.of(idx, join.getRowType().getFieldList());
        final Set<RexNode> originalExprs = mq.getExpressionLineage(join, inputRef);
        if (originalExprs == null) {
            // Bail out
            return null;
        }
        final RexInputRef ref = RexInputRef.of(idx, join.getRowType().getFieldList());
        mapping.put(ref, originalExprs);
    }
    // Replace with new expressions and return union of predicates
    final Set<RexNode> allExprs = RelMdExpressionLineage.createAllPossibleExpressions(rexBuilder, pred, mapping);
    if (allExprs == null) {
        return null;
    }
    return newPreds.union(rexBuilder, RelOptPredicateList.of(rexBuilder, allExprs));
}

11 View Complete Implementation : RelMdAllPredicates.java
Copyright Apache License 2.0
Author : apache
/**
 * Add the Join condition to the list obtained from the input.
 */
public RelOptPredicateList getAllPredicates(Join join, RelMetadataQuery mq) {
    if (join.getJoinType().isOuterJoin()) {
        // We cannot map origin of this expression.
        return null;
    }
    final RexBuilder rexBuilder = join.getCluster().getRexBuilder();
    final RexNode pred = join.getCondition();
    final Multimap<List<String>, RelTableRef> qualifiedNamesToRefs = HashMultimap.create();
    RelOptPredicateList newPreds = RelOptPredicateList.EMPTY;
    for (RelNode input : join.getInputs()) {
        final RelOptPredicateList inputPreds = mq.getAllPredicates(input);
        if (inputPreds == null) {
            // Bail out
            return null;
        }
        // Gather table references
        final Set<RelTableRef> tableRefs = mq.getTableReferences(input);
        if (input == join.getLeft()) {
            // Left input references remain unchanged
            for (RelTableRef leftRef : tableRefs) {
                qualifiedNamesToRefs.put(leftRef.getQualifiedName(), leftRef);
            }
            newPreds = newPreds.union(rexBuilder, inputPreds);
        } else {
            // Right input references might need to be updated if there are table name
            // clashes with left input
            final Map<RelTableRef, RelTableRef> currentTablesMapping = new HashMap<>();
            for (RelTableRef rightRef : tableRefs) {
                int shift = 0;
                Collection<RelTableRef> lRefs = qualifiedNamesToRefs.get(rightRef.getQualifiedName());
                if (lRefs != null) {
                    shift = lRefs.size();
                }
                currentTablesMapping.put(rightRef, RelTableRef.of(rightRef.getTable(), shift + rightRef.getEnreplacedyNumber()));
            }
            final List<RexNode> updatedPreds = Lists.newArrayList(Iterables.transform(inputPreds.pulledUpPredicates, e -> RexUtil.swapTableReferences(rexBuilder, e, currentTablesMapping)));
            newPreds = newPreds.union(rexBuilder, RelOptPredicateList.of(rexBuilder, updatedPreds));
        }
    }
    // Extract input fields referenced by Join condition
    final Set<RelDataTypeField> inputExtraFields = new LinkedHashSet<>();
    final RelOptUtil.InputFinder inputFinder = new RelOptUtil.InputFinder(inputExtraFields);
    pred.accept(inputFinder);
    final ImmutableBitSet inputFieldsUsed = inputFinder.inputBitSet.build();
    // Infer column origin expressions for given references
    final Map<RexInputRef, Set<RexNode>> mapping = new LinkedHashMap<>();
    final RelDataType fullRowType = SqlValidatorUtil.createJoinType(rexBuilder.getTypeFactory(), join.getLeft().getRowType(), join.getRight().getRowType(), null, ImmutableList.of());
    for (int idx : inputFieldsUsed) {
        final RexInputRef inputRef = RexInputRef.of(idx, fullRowType.getFieldList());
        final Set<RexNode> originalExprs = mq.getExpressionLineage(join, inputRef);
        if (originalExprs == null) {
            // Bail out
            return null;
        }
        final RexInputRef ref = RexInputRef.of(idx, fullRowType.getFieldList());
        mapping.put(ref, originalExprs);
    }
    // Replace with new expressions and return union of predicates
    final Set<RexNode> allExprs = RelMdExpressionLineage.createAllPossibleExpressions(rexBuilder, pred, mapping);
    if (allExprs == null) {
        return null;
    }
    return newPreds.union(rexBuilder, RelOptPredicateList.of(rexBuilder, allExprs));
}

11 View Complete Implementation : RelMdPredicates.java
Copyright Apache License 2.0
Author : apache
/**
 * Infers predicates for a Union.
 */
public RelOptPredicateList getPredicates(Union union, RelMetadataQuery mq) {
    final RexBuilder rexBuilder = union.getCluster().getRexBuilder();
    Set<RexNode> finalPredicates = new HashSet<>();
    final List<RexNode> finalResidualPredicates = new ArrayList<>();
    for (Ord<RelNode> input : Ord.zip(union.getInputs())) {
        RelOptPredicateList info = mq.getPulledUpPredicates(input.e);
        if (info.pulledUpPredicates.isEmpty()) {
            return RelOptPredicateList.EMPTY;
        }
        final Set<RexNode> predicates = new HashSet<>();
        final List<RexNode> residualPredicates = new ArrayList<>();
        for (RexNode pred : info.pulledUpPredicates) {
            if (input.i == 0) {
                predicates.add(pred);
                continue;
            }
            if (finalPredicates.contains(pred)) {
                predicates.add(pred);
            } else {
                residualPredicates.add(pred);
            }
        }
        // Add new residual predicates
        finalResidualPredicates.add(RexUtil.composeConjunction(rexBuilder, residualPredicates));
        // Add those that are not part of the final set to residual
        for (RexNode e : finalPredicates) {
            if (!predicates.contains(e)) {
                // This node was in previous union inputs, but it is not in this one
                for (int j = 0; j < input.i; j++) {
                    finalResidualPredicates.set(j, RexUtil.composeConjunction(rexBuilder, Arrays.asList(finalResidualPredicates.get(j), e)));
                }
            }
        }
        // Final predicates
        finalPredicates = predicates;
    }
    final List<RexNode> predicates = new ArrayList<>(finalPredicates);
    final RelOptCluster cluster = union.getCluster();
    final RexExecutor executor = Util.first(cluster.getPlanner().getExecutor(), RexUtil.EXECUTOR);
    RexNode disjunctivePredicate = new RexSimplify(rexBuilder, RelOptPredicateList.EMPTY, executor).simplifyUnknownAs(rexBuilder.makeCall(SqlStdOperatorTable.OR, finalResidualPredicates), RexUnknownAs.FALSE);
    if (!disjunctivePredicate.isAlwaysTrue()) {
        predicates.add(disjunctivePredicate);
    }
    return RelOptPredicateList.of(rexBuilder, predicates);
}

11 View Complete Implementation : ReduceExpressionsUtil.java
Copyright Apache License 2.0
Author : dremio
public static boolean numReducibleExprs(Filter filter) {
    final List<RexNode> expList = Lists.newArrayList(filter.getCondition());
    final RelMetadataQuery mq = filter.getCluster().getMetadataQuery();
    final RelOptPredicateList predicates = mq.getPulledUpPredicates(filter.getInput());
    return reduceExpressions(filter, expList, predicates);
}

11 View Complete Implementation : ReduceExpressionsUtil.java
Copyright Apache License 2.0
Author : dremio
public static int numReducibleExprs(Project project) {
    final List<RexNode> expList = Lists.newArrayList(project.getProjects());
    final RelMetadataQuery mq = project.getCluster().getMetadataQuery();
    final RelOptPredicateList predicates = mq.getPulledUpPredicates(project.getInput());
    boolean reducible = reduceExpressions(project, expList, predicates);
    if (reducible) {
        int numReducible = 0;
        for (int i = 0; i < project.getProjects().size(); i++) {
            if (!project.getProjects().get(i).toString().equals(expList.get(i).toString())) {
                numReducible++;
            }
        }
        return numReducible;
    } else {
        return 0;
    }
}

10 View Complete Implementation : ValuesReduceRule.java
Copyright Apache License 2.0
Author : apache
// ~ Methods ----------------------------------------------------------------
/**
 * Does the work.
 *
 * @param call    Rule call
 * @param project Project, may be null
 * @param filter  Filter, may be null
 * @param values  Values rel to be reduced
 */
protected void apply(RelOptRuleCall call, LogicalProject project, LogicalFilter filter, LogicalValues values) {
    replacedert values != null;
    replacedert filter != null || project != null;
    final RexNode conditionExpr = (filter == null) ? null : filter.getCondition();
    final List<RexNode> projectExprs = (project == null) ? null : project.getProjects();
    RexBuilder rexBuilder = values.getCluster().getRexBuilder();
    // Find reducible expressions.
    final List<RexNode> reducibleExps = new ArrayList<>();
    final MyRexShuttle shuttle = new MyRexShuttle();
    for (final List<RexLiteral> literalList : values.getTuples()) {
        shuttle.literalList = literalList;
        if (conditionExpr != null) {
            RexNode c = conditionExpr.accept(shuttle);
            reducibleExps.add(c);
        }
        if (projectExprs != null) {
            int k = -1;
            for (RexNode projectExpr : projectExprs) {
                ++k;
                RexNode e = projectExpr.accept(shuttle);
                if (RexLiteral.isNullLiteral(e)) {
                    e = rexBuilder.makeAbstractCast(project.getRowType().getFieldList().get(k).getType(), e);
                }
                reducibleExps.add(e);
            }
        }
    }
    int fieldsPerRow = ((conditionExpr == null) ? 0 : 1) + ((projectExprs == null) ? 0 : projectExprs.size());
    replacedert fieldsPerRow > 0;
    replacedert reducibleExps.size() == (values.getTuples().size() * fieldsPerRow);
    // Compute the values they reduce to.
    final RelOptPredicateList predicates = RelOptPredicateList.EMPTY;
    ReduceExpressionsRule.reduceExpressions(values, reducibleExps, predicates, false, true);
    int changeCount = 0;
    final ImmutableList.Builder<ImmutableList<RexLiteral>> tuplesBuilder = ImmutableList.builder();
    for (int row = 0; row < values.getTuples().size(); ++row) {
        int i = 0;
        if (conditionExpr != null) {
            final RexNode reducedValue = reducibleExps.get((row * fieldsPerRow) + i);
            ++i;
            if (!reducedValue.isAlwaysTrue()) {
                ++changeCount;
                continue;
            }
        }
        final ImmutableList<RexLiteral> valuesList;
        if (projectExprs != null) {
            ++changeCount;
            final ImmutableList.Builder<RexLiteral> tupleBuilder = ImmutableList.builder();
            for (; i < fieldsPerRow; ++i) {
                final RexNode reducedValue = reducibleExps.get((row * fieldsPerRow) + i);
                if (reducedValue instanceof RexLiteral) {
                    tupleBuilder.add((RexLiteral) reducedValue);
                } else if (RexUtil.isNullLiteral(reducedValue, true)) {
                    tupleBuilder.add(rexBuilder.makeNullLiteral(reducedValue.getType()));
                } else {
                    return;
                }
            }
            valuesList = tupleBuilder.build();
        } else {
            valuesList = values.getTuples().get(row);
        }
        tuplesBuilder.add(valuesList);
    }
    if (changeCount > 0) {
        final RelDataType rowType;
        if (projectExprs != null) {
            rowType = project.getRowType();
        } else {
            rowType = values.getRowType();
        }
        final RelNode newRel = LogicalValues.create(values.getCluster(), rowType, tuplesBuilder.build());
        call.transformTo(newRel);
    } else {
        // Filter had no effect, so we can say that Filter(Values) ==
        // Values.
        call.transformTo(values);
    }
    // New plan is absolutely better than old plan. (Moreover, if
    // changeCount == 0, we've proved that the filter was trivial, and that
    // can send the volcano planner into a loop; see dtbug 2070.)
    if (filter != null) {
        call.getPlanner().setImportance(filter, 0.0);
    }
}

5 View Complete Implementation : EnumerableCalc.java
Copyright Apache License 2.0
Author : apache
public Result implement(EnumerableRelImplementor implementor, Prefer pref) {
    final JavaTypeFactory typeFactory = implementor.getTypeFactory();
    final BlockBuilder builder = new BlockBuilder();
    final EnumerableRel child = (EnumerableRel) getInput();
    final Result result = implementor.visitChild(this, 0, child, pref);
    final PhysType physType = PhysTypeImpl.of(typeFactory, getRowType(), pref.prefer(result.format));
    // final Enumerable<Employee> inputEnumerable = <<child adapter>>;
    // return new Enumerable<IntString>() {
    // Enumerator<IntString> enumerator() {
    // return new Enumerator<IntString>() {
    // public void reset() {
    // ...
    Type outputJavaType = physType.getJavaRowType();
    final Type enumeratorType = Types.of(Enumerator.clreplaced, outputJavaType);
    Type inputJavaType = result.physType.getJavaRowType();
    ParameterExpression inputEnumerator = Expressions.parameter(Types.of(Enumerator.clreplaced, inputJavaType), "inputEnumerator");
    Expression input = EnumUtils.convert(Expressions.call(inputEnumerator, BuiltInMethod.ENUMERATOR_CURRENT.method), inputJavaType);
    final RexBuilder rexBuilder = getCluster().getRexBuilder();
    final RelMetadataQuery mq = getCluster().getMetadataQuery();
    final RelOptPredicateList predicates = mq.getPulledUpPredicates(child);
    final RexSimplify simplify = new RexSimplify(rexBuilder, predicates, RexUtil.EXECUTOR);
    final RexProgram program = this.program.normalize(rexBuilder, simplify);
    BlockStatement moveNextBody;
    if (program.getCondition() == null) {
        moveNextBody = Blocks.toFunctionBlock(Expressions.call(inputEnumerator, BuiltInMethod.ENUMERATOR_MOVE_NEXT.method));
    } else {
        final BlockBuilder builder2 = new BlockBuilder();
        Expression condition = RexToLixTranslator.translateCondition(program, typeFactory, builder2, new RexToLixTranslator.InputGetterImpl(Collections.singletonList(Pair.of(input, result.physType))), implementor.allCorrelateVariables, implementor.getConformance());
        builder2.add(Expressions.ifThen(condition, Expressions.return_(null, Expressions.constant(true))));
        moveNextBody = Expressions.block(Expressions.while_(Expressions.call(inputEnumerator, BuiltInMethod.ENUMERATOR_MOVE_NEXT.method), builder2.toBlock()), Expressions.return_(null, Expressions.constant(false)));
    }
    final BlockBuilder builder3 = new BlockBuilder();
    final SqlConformance conformance = (SqlConformance) implementor.map.getOrDefault("_conformance", SqlConformanceEnum.DEFAULT);
    List<Expression> expressions = RexToLixTranslator.translateProjects(program, typeFactory, conformance, builder3, physType, DataContext.ROOT, new RexToLixTranslator.InputGetterImpl(Collections.singletonList(Pair.of(input, result.physType))), implementor.allCorrelateVariables);
    builder3.add(Expressions.return_(null, physType.record(expressions)));
    BlockStatement currentBody = builder3.toBlock();
    final Expression inputEnumerable = builder.append("inputEnumerable", result.block, false);
    final Expression body = Expressions.new_(enumeratorType, NO_EXPRS, Expressions.list(Expressions.fieldDecl(Modifier.PUBLIC | Modifier.FINAL, inputEnumerator, Expressions.call(inputEnumerable, BuiltInMethod.ENUMERABLE_ENUMERATOR.method)), EnumUtils.overridingMethodDecl(BuiltInMethod.ENUMERATOR_RESET.method, NO_PARAMS, Blocks.toFunctionBlock(Expressions.call(inputEnumerator, BuiltInMethod.ENUMERATOR_RESET.method))), EnumUtils.overridingMethodDecl(BuiltInMethod.ENUMERATOR_MOVE_NEXT.method, NO_PARAMS, moveNextBody), EnumUtils.overridingMethodDecl(BuiltInMethod.ENUMERATOR_CLOSE.method, NO_PARAMS, Blocks.toFunctionBlock(Expressions.call(inputEnumerator, BuiltInMethod.ENUMERATOR_CLOSE.method))), Expressions.methodDecl(Modifier.PUBLIC, BRIDGE_METHODS ? Object.clreplaced : outputJavaType, "current", NO_PARAMS, currentBody)));
    builder.add(Expressions.return_(null, Expressions.new_(BuiltInMethod.ABSTRACT_ENUMERABLE_CTOR.constructor, // TODO: generics
    // Collections.singletonList(inputRowType),
    NO_EXPRS, ImmutableList.<MemberDeclaration>of(Expressions.methodDecl(Modifier.PUBLIC, enumeratorType, BuiltInMethod.ENUMERABLE_ENUMERATOR.method.getName(), NO_PARAMS, Blocks.toFunctionBlock(body))))));
    return implementor.result(physType, builder.toBlock());
}

5 View Complete Implementation : AggregateProjectPullUpConstantsRule.java
Copyright Apache License 2.0
Author : apache
// ~ Methods ----------------------------------------------------------------
public void onMatch(RelOptRuleCall call) {
    final Aggregate aggregate = call.rel(0);
    final RelNode input = call.rel(1);
    final int groupCount = aggregate.getGroupCount();
    if (groupCount == 1) {
        // No room for optimization since we cannot convert from non-empty
        // GROUP BY list to the empty one.
        return;
    }
    final RexBuilder rexBuilder = aggregate.getCluster().getRexBuilder();
    final RelMetadataQuery mq = call.getMetadataQuery();
    final RelOptPredicateList predicates = mq.getPulledUpPredicates(aggregate.getInput());
    if (predicates == null) {
        return;
    }
    final NavigableMap<Integer, RexNode> map = new TreeMap<>();
    for (int key : aggregate.getGroupSet()) {
        final RexInputRef ref = rexBuilder.makeInputRef(aggregate.getInput(), key);
        if (predicates.constantMap.containsKey(ref)) {
            map.put(key, predicates.constantMap.get(ref));
        }
    }
    // None of the group expressions are constant. Nothing to do.
    if (map.isEmpty()) {
        return;
    }
    if (groupCount == map.size()) {
        // At least a single item in group by is required.
        // Otherwise "GROUP BY 1, 2" might be altered to "GROUP BY ()".
        // Removing of the first element is not optimal here,
        // however it will allow us to use fast path below (just trim
        // groupCount).
        map.remove(map.navigableKeySet().first());
    }
    ImmutableBitSet newGroupSet = aggregate.getGroupSet();
    for (int key : map.keySet()) {
        newGroupSet = newGroupSet.clear(key);
    }
    final int newGroupCount = newGroupSet.cardinality();
    // If the constants are on the trailing edge of the group list, we just
    // reduce the group count.
    final RelBuilder relBuilder = call.builder();
    relBuilder.push(input);
    // Clone aggregate calls.
    final List<AggregateCall> newAggCalls = new ArrayList<>();
    for (AggregateCall aggCall : aggregate.getAggCallList()) {
        newAggCalls.add(aggCall.adaptTo(input, aggCall.getArgList(), aggCall.filterArg, groupCount, newGroupCount));
    }
    relBuilder.aggregate(relBuilder.groupKey(newGroupSet), newAggCalls);
    // Create a projection back again.
    List<Pair<RexNode, String>> projects = new ArrayList<>();
    int source = 0;
    for (RelDataTypeField field : aggregate.getRowType().getFieldList()) {
        RexNode expr;
        final int i = field.getIndex();
        if (i >= groupCount) {
            // Aggregate expressions' names and positions are unchanged.
            expr = relBuilder.field(i - map.size());
        } else {
            int pos = aggregate.getGroupSet().nth(i);
            if (map.containsKey(pos)) {
                // Re-generate the constant expression in the project.
                RelDataType originalType = aggregate.getRowType().getFieldList().get(projects.size()).getType();
                if (!originalType.equals(map.get(pos).getType())) {
                    expr = rexBuilder.makeCast(originalType, map.get(pos), true);
                } else {
                    expr = map.get(pos);
                }
            } else {
                // Project the aggregation expression, in its original
                // position.
                expr = relBuilder.field(source);
                ++source;
            }
        }
        projects.add(Pair.of(expr, field.getName()));
    }
    // inverse
    relBuilder.project(Pair.left(projects), Pair.right(projects));
    call.transformTo(relBuilder.build());
}

5 View Complete Implementation : AggregateProjectPullUpConstantsRule.java
Copyright Apache License 2.0
Author : lealone
// ~ Methods ----------------------------------------------------------------
public void onMatch(RelOptRuleCall call) {
    final Aggregate aggregate = call.rel(0);
    final RelNode input = call.rel(1);
    replacedert !aggregate.indicator : "predicate ensured no grouping sets";
    final int groupCount = aggregate.getGroupCount();
    if (groupCount == 1) {
        // No room for optimization since we cannot convert from non-empty
        // GROUP BY list to the empty one.
        return;
    }
    final RexBuilder rexBuilder = aggregate.getCluster().getRexBuilder();
    final RelMetadataQuery mq = call.getMetadataQuery();
    final RelOptPredicateList predicates = mq.getPulledUpPredicates(aggregate.getInput());
    if (predicates == null) {
        return;
    }
    final NavigableMap<Integer, RexNode> map = new TreeMap<>();
    for (int key : aggregate.getGroupSet()) {
        final RexInputRef ref = rexBuilder.makeInputRef(aggregate.getInput(), key);
        if (predicates.constantMap.containsKey(ref)) {
            map.put(key, predicates.constantMap.get(ref));
        }
    }
    // None of the group expressions are constant. Nothing to do.
    if (map.isEmpty()) {
        return;
    }
    if (groupCount == map.size()) {
        // At least a single item in group by is required.
        // Otherwise "GROUP BY 1, 2" might be altered to "GROUP BY ()".
        // Removing of the first element is not optimal here,
        // however it will allow us to use fast path below (just trim
        // groupCount).
        map.remove(map.navigableKeySet().first());
    }
    ImmutableBitSet newGroupSet = aggregate.getGroupSet();
    for (int key : map.keySet()) {
        newGroupSet = newGroupSet.clear(key);
    }
    final int newGroupCount = newGroupSet.cardinality();
    // If the constants are on the trailing edge of the group list, we just
    // reduce the group count.
    final RelBuilder relBuilder = call.builder();
    relBuilder.push(input);
    // Clone aggregate calls.
    final List<AggregateCall> newAggCalls = new ArrayList<>();
    for (AggregateCall aggCall : aggregate.getAggCallList()) {
        newAggCalls.add(aggCall.adaptTo(input, aggCall.getArgList(), aggCall.filterArg, groupCount, newGroupCount));
    }
    relBuilder.aggregate(relBuilder.groupKey(newGroupSet), newAggCalls);
    // Create a projection back again.
    List<Pair<RexNode, String>> projects = new ArrayList<>();
    int source = 0;
    for (RelDataTypeField field : aggregate.getRowType().getFieldList()) {
        RexNode expr;
        final int i = field.getIndex();
        if (i >= groupCount) {
            // Aggregate expressions' names and positions are unchanged.
            expr = relBuilder.field(i - map.size());
        } else {
            int pos = aggregate.getGroupSet().nth(i);
            if (map.containsKey(pos)) {
                // Re-generate the constant expression in the project.
                RelDataType originalType = aggregate.getRowType().getFieldList().get(projects.size()).getType();
                if (!originalType.equals(map.get(pos).getType())) {
                    expr = rexBuilder.makeCast(originalType, map.get(pos), true);
                } else {
                    expr = map.get(pos);
                }
            } else {
                // Project the aggregation expression, in its original
                // position.
                expr = relBuilder.field(source);
                ++source;
            }
        }
        projects.add(Pair.of(expr, field.getName()));
    }
    // inverse
    relBuilder.project(Pair.left(projects), Pair.right(projects));
    call.transformTo(relBuilder.build());
}

3 View Complete Implementation : ExchangeRemoveConstantKeysRule.java
Copyright Apache License 2.0
Author : apache
@Override
public void onMatch(RelOptRuleCall call) {
    final Exchange exchange = call.rel(0);
    final RelMetadataQuery mq = call.getMetadataQuery();
    final RelNode input = exchange.getInput();
    final RelOptPredicateList predicates = mq.getPulledUpPredicates(input);
    if (predicates == null) {
        return;
    }
    final Set<Integer> constants = new HashSet<>();
    predicates.constantMap.keySet().forEach(key -> {
        if (key instanceof RexInputRef) {
            constants.add(((RexInputRef) key).getIndex());
        }
    });
    if (constants.isEmpty()) {
        return;
    }
    final List<Integer> distributionKeys = simplifyDistributionKeys(exchange.getDistribution(), constants);
    if (distributionKeys.size() != exchange.getDistribution().getKeys().size()) {
        call.transformTo(call.builder().push(exchange.getInput()).exchange(distributionKeys.isEmpty() ? RelDistributions.SINGLETON : RelDistributions.hash(distributionKeys)).build());
        call.getPlanner().setImportance(exchange, 0.0);
    }
}

3 View Complete Implementation : SortRemoveConstantKeysRule.java
Copyright Apache License 2.0
Author : apache
@Override
public void onMatch(RelOptRuleCall call) {
    final Sort sort = call.rel(0);
    final RelMetadataQuery mq = call.getMetadataQuery();
    final RelNode input = sort.getInput();
    final RelOptPredicateList predicates = mq.getPulledUpPredicates(input);
    if (predicates == null) {
        return;
    }
    final RexBuilder rexBuilder = sort.getCluster().getRexBuilder();
    final List<RelFieldCollation> collationsList = sort.getCollation().getFieldCollations().stream().filter(fc -> !predicates.constantMap.containsKey(rexBuilder.makeInputRef(input, fc.getFieldIndex()))).collect(Collectors.toList());
    if (collationsList.size() == sort.collation.getFieldCollations().size()) {
        return;
    }
    // No active collations. Remove the sort completely
    if (collationsList.isEmpty() && sort.offset == null && sort.fetch == null) {
        call.transformTo(input);
        call.getPlanner().setImportance(sort, 0.0);
        return;
    }
    final Sort result = sort.copy(sort.getTraitSet(), input, RelCollations.of(collationsList));
    call.transformTo(result);
    call.getPlanner().setImportance(sort, 0.0);
}

2 View Complete Implementation : UnionPullUpConstantsRule.java
Copyright Apache License 2.0
Author : apache
@Override
public void onMatch(RelOptRuleCall call) {
    final Union union = call.rel(0);
    final RexBuilder rexBuilder = union.getCluster().getRexBuilder();
    final RelMetadataQuery mq = call.getMetadataQuery();
    final RelOptPredicateList predicates = mq.getPulledUpPredicates(union);
    if (predicates == null) {
        return;
    }
    final Map<Integer, RexNode> constants = new HashMap<>();
    for (Map.Entry<RexNode, RexNode> e : predicates.constantMap.entrySet()) {
        if (e.getKey() instanceof RexInputRef) {
            constants.put(((RexInputRef) e.getKey()).getIndex(), e.getValue());
        }
    }
    // None of the expressions are constant. Nothing to do.
    if (constants.isEmpty()) {
        return;
    }
    // Create expressions for Project operators before and after the Union
    List<RelDataTypeField> fields = union.getRowType().getFieldList();
    List<RexNode> topChildExprs = new ArrayList<>();
    List<String> topChildExprsFields = new ArrayList<>();
    List<RexNode> refs = new ArrayList<>();
    ImmutableBitSet.Builder refsIndexBuilder = ImmutableBitSet.builder();
    for (RelDataTypeField field : fields) {
        final RexNode constant = constants.get(field.getIndex());
        if (constant != null) {
            topChildExprs.add(constant);
            topChildExprsFields.add(field.getName());
        } else {
            final RexNode expr = rexBuilder.makeInputRef(union, field.getIndex());
            topChildExprs.add(expr);
            topChildExprsFields.add(field.getName());
            refs.add(expr);
            refsIndexBuilder.set(field.getIndex());
        }
    }
    ImmutableBitSet refsIndex = refsIndexBuilder.build();
    // Update top Project positions
    final Mappings.TargetMapping mapping = RelOptUtil.permutation(refs, union.getInput(0).getRowType()).inverse();
    topChildExprs = ImmutableList.copyOf(RexUtil.apply(mapping, topChildExprs));
    // Create new Project-Union-Project sequences
    final RelBuilder relBuilder = call.builder();
    for (RelNode input : union.getInputs()) {
        List<Pair<RexNode, String>> newChildExprs = new ArrayList<>();
        for (int j : refsIndex) {
            newChildExprs.add(Pair.of(rexBuilder.makeInputRef(input, j), input.getRowType().getFieldList().get(j).getName()));
        }
        if (newChildExprs.isEmpty()) {
            // At least a single item in project is required.
            newChildExprs.add(Pair.of(topChildExprs.get(0), topChildExprsFields.get(0)));
        }
        // Add the input with project on top
        relBuilder.push(input);
        relBuilder.project(Pair.left(newChildExprs), Pair.right(newChildExprs));
    }
    relBuilder.union(union.all, union.getInputs().size());
    // Create top Project fixing nullability of fields
    relBuilder.project(topChildExprs, topChildExprsFields);
    relBuilder.convert(union.getRowType(), false);
    call.transformTo(relBuilder.build());
}

2 View Complete Implementation : UnionPullUpConstantsRule.java
Copyright Apache License 2.0
Author : lealone
@Override
public void onMatch(RelOptRuleCall call) {
    final Union union = call.rel(0);
    final int count = union.getRowType().getFieldCount();
    if (count == 1) {
        // No room for optimization since we cannot create an empty Project
        // operator. If we created a Project with one column, this rule would
        // cycle.
        return;
    }
    final RexBuilder rexBuilder = union.getCluster().getRexBuilder();
    final RelMetadataQuery mq = call.getMetadataQuery();
    final RelOptPredicateList predicates = mq.getPulledUpPredicates(union);
    if (predicates == null) {
        return;
    }
    final Map<Integer, RexNode> constants = new HashMap<>();
    for (Map.Entry<RexNode, RexNode> e : predicates.constantMap.entrySet()) {
        if (e.getKey() instanceof RexInputRef) {
            constants.put(((RexInputRef) e.getKey()).getIndex(), e.getValue());
        }
    }
    // None of the expressions are constant. Nothing to do.
    if (constants.isEmpty()) {
        return;
    }
    // Create expressions for Project operators before and after the Union
    List<RelDataTypeField> fields = union.getRowType().getFieldList();
    List<RexNode> topChildExprs = new ArrayList<>();
    List<String> topChildExprsFields = new ArrayList<>();
    List<RexNode> refs = new ArrayList<>();
    ImmutableBitSet.Builder refsIndexBuilder = ImmutableBitSet.builder();
    for (RelDataTypeField field : fields) {
        final RexNode constant = constants.get(field.getIndex());
        if (constant != null) {
            topChildExprs.add(constant);
            topChildExprsFields.add(field.getName());
        } else {
            final RexNode expr = rexBuilder.makeInputRef(union, field.getIndex());
            topChildExprs.add(expr);
            topChildExprsFields.add(field.getName());
            refs.add(expr);
            refsIndexBuilder.set(field.getIndex());
        }
    }
    ImmutableBitSet refsIndex = refsIndexBuilder.build();
    // Update top Project positions
    final Mappings.TargetMapping mapping = RelOptUtil.permutation(refs, union.getInput(0).getRowType()).inverse();
    topChildExprs = ImmutableList.copyOf(RexUtil.apply(mapping, topChildExprs));
    // Create new Project-Union-Project sequences
    final RelBuilder relBuilder = call.builder();
    for (RelNode input : union.getInputs()) {
        List<Pair<RexNode, String>> newChildExprs = new ArrayList<>();
        for (int j : refsIndex) {
            newChildExprs.add(Pair.of(rexBuilder.makeInputRef(input, j), input.getRowType().getFieldList().get(j).getName()));
        }
        if (newChildExprs.isEmpty()) {
            // At least a single item in project is required.
            newChildExprs.add(Pair.of(topChildExprs.get(0), topChildExprsFields.get(0)));
        }
        // Add the input with project on top
        relBuilder.push(input);
        relBuilder.project(Pair.left(newChildExprs), Pair.right(newChildExprs));
    }
    relBuilder.union(union.all, union.getInputs().size());
    // Create top Project fixing nullability of fields
    relBuilder.project(topChildExprs, topChildExprsFields);
    relBuilder.convert(union.getRowType(), false);
    call.transformTo(relBuilder.build());
}

0 View Complete Implementation : JoinPushTransitivePredicatesRule.java
Copyright Apache License 2.0
Author : apache
@Override
public void onMatch(RelOptRuleCall call) {
    Join join = call.rel(0);
    final RelMetadataQuery mq = call.getMetadataQuery();
    RelOptPredicateList preds = mq.getPulledUpPredicates(join);
    if (preds.leftInferredPredicates.isEmpty() && preds.rightInferredPredicates.isEmpty()) {
        return;
    }
    final RexBuilder rexBuilder = join.getCluster().getRexBuilder();
    final RelBuilder relBuilder = call.builder();
    RelNode lChild = join.getLeft();
    if (preds.leftInferredPredicates.size() > 0) {
        RelNode curr = lChild;
        lChild = relBuilder.push(lChild).filter(preds.leftInferredPredicates).build();
        call.getPlanner().onCopy(curr, lChild);
    }
    RelNode rChild = join.getRight();
    if (preds.rightInferredPredicates.size() > 0) {
        RelNode curr = rChild;
        rChild = relBuilder.push(rChild).filter(preds.rightInferredPredicates).build();
        call.getPlanner().onCopy(curr, rChild);
    }
    RelNode newRel = join.copy(join.getTraitSet(), join.getCondition(), lChild, rChild, join.getJoinType(), join.isSemiJoinDone());
    call.getPlanner().onCopy(join, newRel);
    call.transformTo(newRel);
}

0 View Complete Implementation : ValuesReduceRule.java
Copyright Apache License 2.0
Author : lealone
// ~ Methods ----------------------------------------------------------------
/**
 * Does the work.
 *
 * @param call    Rule call
 * @param project Project, may be null
 * @param filter  Filter, may be null
 * @param values  Values rel to be reduced
 */
protected void apply(RelOptRuleCall call, LogicalProject project, LogicalFilter filter, LogicalValues values) {
    replacedert values != null;
    replacedert filter != null || project != null;
    final RexNode conditionExpr = (filter == null) ? null : filter.getCondition();
    final List<RexNode> projectExprs = (project == null) ? null : project.getProjects();
    RexBuilder rexBuilder = values.getCluster().getRexBuilder();
    // Find reducible expressions.
    final List<RexNode> reducibleExps = new ArrayList<>();
    final MyRexShuttle shuttle = new MyRexShuttle();
    for (final List<RexLiteral> literalList : values.getTuples()) {
        shuttle.literalList = literalList;
        if (conditionExpr != null) {
            RexNode c = conditionExpr.accept(shuttle);
            reducibleExps.add(c);
        }
        if (projectExprs != null) {
            int k = -1;
            for (RexNode projectExpr : projectExprs) {
                ++k;
                RexNode e = projectExpr.accept(shuttle);
                if (RexLiteral.isNullLiteral(e)) {
                    e = rexBuilder.makeAbstractCast(project.getRowType().getFieldList().get(k).getType(), e);
                }
                reducibleExps.add(e);
            }
        }
    }
    int fieldsPerRow = ((conditionExpr == null) ? 0 : 1) + ((projectExprs == null) ? 0 : projectExprs.size());
    replacedert fieldsPerRow > 0;
    replacedert reducibleExps.size() == (values.getTuples().size() * fieldsPerRow);
    // Compute the values they reduce to.
    final RelOptPredicateList predicates = RelOptPredicateList.EMPTY;
    ReduceExpressionsRule.reduceExpressions(values, reducibleExps, predicates, false, true);
    int changeCount = 0;
    final ImmutableList.Builder<ImmutableList<RexLiteral>> tuplesBuilder = ImmutableList.builder();
    for (int row = 0; row < values.getTuples().size(); ++row) {
        int i = 0;
        RexNode reducedValue;
        if (conditionExpr != null) {
            reducedValue = reducibleExps.get((row * fieldsPerRow) + i);
            ++i;
            if (!reducedValue.isAlwaysTrue()) {
                ++changeCount;
                continue;
            }
        }
        ImmutableList<RexLiteral> valuesList;
        if (projectExprs != null) {
            ++changeCount;
            final ImmutableList.Builder<RexLiteral> tupleBuilder = ImmutableList.builder();
            for (; i < fieldsPerRow; ++i) {
                reducedValue = reducibleExps.get((row * fieldsPerRow) + i);
                if (reducedValue instanceof RexLiteral) {
                    tupleBuilder.add((RexLiteral) reducedValue);
                } else if (RexUtil.isNullLiteral(reducedValue, true)) {
                    tupleBuilder.add(rexBuilder.constantNull());
                } else {
                    return;
                }
            }
            valuesList = tupleBuilder.build();
        } else {
            valuesList = values.getTuples().get(row);
        }
        tuplesBuilder.add(valuesList);
    }
    if (changeCount > 0) {
        final RelDataType rowType;
        if (projectExprs != null) {
            rowType = project.getRowType();
        } else {
            rowType = values.getRowType();
        }
        final RelNode newRel = LogicalValues.create(values.getCluster(), rowType, tuplesBuilder.build());
        call.transformTo(newRel);
    } else {
        // Filter had no effect, so we can say that Filter(Values) ==
        // Values.
        call.transformTo(values);
    }
    // New plan is absolutely better than old plan. (Moreover, if
    // changeCount == 0, we've proved that the filter was trivial, and that
    // can send the volcano planner into a loop; see dtbug 2070.)
    if (filter != null) {
        call.getPlanner().setImportance(filter, 0.0);
    }
}