use of org.apache.calcite.rex.RexSimplify in project hive by apache.
the class HiveFilterSetOpTransposeRule method onMatch.
// ~ Methods ----------------------------------------------------------------
// implement RelOptRule
// We override the rule in order to do union all branch elimination
public void onMatch(RelOptRuleCall call) {
Filter filterRel = call.rel(0);
SetOp setOp = call.rel(1);
RexNode condition = filterRel.getCondition();
// create filters on top of each setop child, modifying the filter
// condition to reference each setop child
RexBuilder rexBuilder = filterRel.getCluster().getRexBuilder();
final RelBuilder relBuilder = call.builder();
List<RelDataTypeField> origFields = setOp.getRowType().getFieldList();
int[] adjustments = new int[origFields.size()];
final List<RelNode> newSetOpInputs = new ArrayList<>();
RelNode lastInput = null;
for (int index = 0; index < setOp.getInputs().size(); index++) {
RelNode input = setOp.getInput(index);
RexNode newCondition = condition.accept(new RelOptUtil.RexInputConverter(rexBuilder, origFields, input.getRowType().getFieldList(), adjustments));
if (setOp instanceof Union && setOp.all) {
final RelMetadataQuery mq = call.getMetadataQuery();
final RelOptPredicateList predicates = mq.getPulledUpPredicates(input);
if (predicates != null) {
ImmutableList.Builder<RexNode> listBuilder = ImmutableList.builder();
listBuilder.addAll(predicates.pulledUpPredicates);
listBuilder.add(newCondition);
RexExecutor executor = Util.first(filterRel.getCluster().getPlanner().getExecutor(), RexUtil.EXECUTOR);
final RexSimplify simplify = new RexSimplify(rexBuilder, RelOptPredicateList.EMPTY, executor);
final RexNode cond = RexUtil.composeConjunction(rexBuilder, listBuilder.build());
final RexNode x = simplify.simplifyUnknownAs(cond, RexUnknownAs.FALSE);
if (x.isAlwaysFalse()) {
// branch so it won't read any data.
if (index == setOp.getInputs().size() - 1) {
lastInput = relBuilder.push(input).filter(newCondition).build();
}
// remove this branch
continue;
}
}
}
newSetOpInputs.add(relBuilder.push(input).filter(newCondition).build());
}
if (newSetOpInputs.size() > 1) {
// create a new setop whose children are the filters created above
SetOp newSetOp = setOp.copy(setOp.getTraitSet(), newSetOpInputs);
call.transformTo(newSetOp);
} else {
// We have to keep at least a branch before we support empty values() in Hive
RelNode result = newSetOpInputs.size() == 1 ? newSetOpInputs.get(0) : lastInput;
call.transformTo(relBuilder.push(result).convert(filterRel.getRowType(), false).build());
}
}
use of org.apache.calcite.rex.RexSimplify 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;
}
Aggregations