Search in sources :

Example 6 with RexExecutor

use of org.apache.calcite.rex.RexExecutor in project calcite by apache.

the class RelOptUtil method containsNullableFields.

/**
 * Determines whether any of the fields in a given relational expression may
 * contain null values, taking into account constraints on the field types and
 * also deduced predicates.
 *
 * <p>The method is cautious: It may sometimes return {@code true} when the
 * actual answer is {@code false}. In particular, it does this when there
 * is no executor, or the executor is not a sub-class of
 * {@link RexExecutorImpl}.
 */
private static boolean containsNullableFields(RelNode r) {
    final RexBuilder rexBuilder = r.getCluster().getRexBuilder();
    final RelDataType rowType = r.getRowType();
    final List<RexNode> list = new ArrayList<>();
    final RelMetadataQuery mq = r.getCluster().getMetadataQuery();
    for (RelDataTypeField field : rowType.getFieldList()) {
        if (field.getType().isNullable()) {
            list.add(rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, rexBuilder.makeInputRef(field.getType(), field.getIndex())));
        }
    }
    if (list.isEmpty()) {
        // All columns are declared NOT NULL.
        return false;
    }
    final RelOptPredicateList predicates = mq.getPulledUpPredicates(r);
    if (predicates.pulledUpPredicates.isEmpty()) {
        // declared NULL are really NOT NULL.
        return true;
    }
    final RexExecutor executor = r.getCluster().getPlanner().getExecutor();
    if (!(executor instanceof RexExecutorImpl)) {
        // Cannot proceed without an executor.
        return true;
    }
    final RexImplicationChecker checker = new RexImplicationChecker(rexBuilder, (RexExecutorImpl) executor, rowType);
    final RexNode first = RexUtil.composeConjunction(rexBuilder, predicates.pulledUpPredicates, false);
    final RexNode second = RexUtil.composeConjunction(rexBuilder, list, false);
    // It does, so we have no nullable columns.
    return !checker.implies(first, second);
}
Also used : RelMetadataQuery(org.apache.calcite.rel.metadata.RelMetadataQuery) RexExecutorImpl(org.apache.calcite.rex.RexExecutorImpl) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RexExecutor(org.apache.calcite.rex.RexExecutor) ArrayList(java.util.ArrayList) RexBuilder(org.apache.calcite.rex.RexBuilder) RelDataType(org.apache.calcite.rel.type.RelDataType) RexNode(org.apache.calcite.rex.RexNode)

Example 7 with RexExecutor

use of org.apache.calcite.rex.RexExecutor in project calcite by apache.

the class ReduceExpressionsRule method reduceExpressions.

/**
 * 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; pass
 * {@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, unknownAsFalse, executor);
    // Simplify predicates in place
    boolean reduced = reduceExpressionsInternal(rel, simplify, expList, predicates);
    final ExprSimplifier simplifier = new ExprSimplifier(simplify, matchNullability);
    boolean simplified = false;
    for (int i = 0; i < expList.size(); i++) {
        RexNode expr2 = simplifier.apply(expList.get(i));
        if (!expr2.toString().equals(expList.get(i).toString())) {
            expList.remove(i);
            expList.add(i, expr2);
            simplified = true;
        }
    }
    return reduced || simplified;
}
Also used : RelOptCluster(org.apache.calcite.plan.RelOptCluster) RexSimplify(org.apache.calcite.rex.RexSimplify) RexExecutor(org.apache.calcite.rex.RexExecutor) RexBuilder(org.apache.calcite.rex.RexBuilder) ExprSimplifier(org.apache.calcite.rex.RexUtil.ExprSimplifier) RexNode(org.apache.calcite.rex.RexNode)

Example 8 with RexExecutor

use of org.apache.calcite.rex.RexExecutor in project calcite by apache.

the class ReduceExpressionsRule method reduceExpressionsInternal.

protected static boolean reduceExpressionsInternal(RelNode rel, RexSimplify simplify, 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 = Lists.newArrayList();
    List<Boolean> addCasts = Lists.newArrayList();
    final List<RexNode> removableCasts = Lists.newArrayList();
    findReducibleExps(rel.getCluster().getTypeFactory(), expList, predicates.constantMap, constExps, addCasts, removableCasts);
    if (constExps.isEmpty() && removableCasts.isEmpty()) {
        return changed;
    }
    // able to locate the original cast expression.
    if (!removableCasts.isEmpty()) {
        final List<RexNode> reducedExprs = Lists.newArrayList();
        for (RexNode exp : removableCasts) {
            RexCall call = (RexCall) exp;
            reducedExprs.add(call.getOperands().get(0));
        }
        RexReplacer replacer = new RexReplacer(simplify, 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, 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) {
        // rootRel.getCluster().getPlanner().setExecutor(executor);
        return changed;
    }
    final List<RexNode> reducedValues = Lists.newArrayList();
    executor.reduce(simplify.rexBuilder, constExps2, reducedValues);
    // is equivalent to the original one.
    if (RexUtil.strings(constExps).equals(RexUtil.strings(reducedValues))) {
        return changed;
    }
    // handled as special cases.
    if (rel instanceof Project) {
        addCasts = Collections.nCopies(reducedValues.size(), true);
    }
    RexReplacer replacer = new RexReplacer(simplify, constExps, reducedValues, addCasts);
    replacer.mutate(expList);
    return true;
}
Also used : RexCall(org.apache.calcite.rex.RexCall) Project(org.apache.calcite.rel.core.Project) LogicalProject(org.apache.calcite.rel.logical.LogicalProject) RexExecutor(org.apache.calcite.rex.RexExecutor) RexNode(org.apache.calcite.rex.RexNode)

Aggregations

RexExecutor (org.apache.calcite.rex.RexExecutor)8 RexBuilder (org.apache.calcite.rex.RexBuilder)7 RexNode (org.apache.calcite.rex.RexNode)6 RexSimplify (org.apache.calcite.rex.RexSimplify)6 ArrayList (java.util.ArrayList)4 RelOptPredicateList (org.apache.calcite.plan.RelOptPredicateList)4 RelNode (org.apache.calcite.rel.RelNode)4 RelOptCluster (org.apache.calcite.plan.RelOptCluster)3 RelMetadataQuery (org.apache.calcite.rel.metadata.RelMetadataQuery)3 ImmutableList (com.google.common.collect.ImmutableList)2 Project (org.apache.calcite.rel.core.Project)2 RelDataType (org.apache.calcite.rel.type.RelDataType)2 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)2 RexCall (org.apache.calcite.rex.RexCall)2 RexExecutorImpl (org.apache.calcite.rex.RexExecutorImpl)2 RelBuilder (org.apache.calcite.tools.RelBuilder)2 BiMap (com.google.common.collect.BiMap)1 HashBiMap (com.google.common.collect.HashBiMap)1 HashMap (java.util.HashMap)1 List (java.util.List)1