private void simplifyList(List<RexNode> terms, RexUnknownAs unknownAs) { unknownAs = UNKNOWN; // TODO for (int i = 0; i < terms.size(); i++) { terms.set(i, simplify(terms.get(i), unknownAs)); } }
final RexNode term = simplify(terms.get(i), unknownAs); switch (term.getKind()) { case LITERAL:
private void simplifyList(List<RexNode> terms, RexUnknownAs unknownAs) { unknownAs = UNKNOWN; // TODO for (int i = 0; i < terms.size(); i++) { terms.set(i, simplify(terms.get(i), unknownAs)); } }
/** * Simplifies a boolean expression, leaving UNKNOWN values as UNKNOWN, and * using the default executor. * * @deprecated Create a {@link RexSimplify}, then call its * {@link RexSimplify#simplify(RexNode, RexUnknownAs)} method. */ @Deprecated // to be removed before 2.0 public static RexNode simplify(RexBuilder rexBuilder, RexNode e) { return new RexSimplify(rexBuilder, RelOptPredicateList.EMPTY, EXECUTOR) .simplify(e); }
/** As {@link #simplify(RexNode)}, but specifying how UNKNOWN values are to be * treated. * * <p>If UNKNOWN is treated as FALSE, this may allow certain additional * simplifications. A result of UNKNOWN may yield FALSE, however it may still * yield UNKNOWN. (If the simplified expression has type BOOLEAN NOT NULL, * then of course it can only return FALSE.) */ public RexNode simplifyUnknownAs(RexNode e, RexUnknownAs unknownAs) { return verify(e, unknownAs, simplifier -> simplifier.simplify(e, unknownAs)); }
/** * Simplifies a boolean expression, leaving UNKNOWN values as UNKNOWN, and * using the default executor. * * @deprecated Create a {@link RexSimplify}, then call its * {@link RexSimplify#simplify(RexNode, RexUnknownAs)} method. */ @Deprecated // to be removed before 2.0 public static RexNode simplify(RexBuilder rexBuilder, RexNode e) { return new RexSimplify(rexBuilder, RelOptPredicateList.EMPTY, EXECUTOR) .simplify(e); }
/** As {@link #simplify(RexNode)}, but specifying how UNKNOWN values are to be * treated. * * <p>If UNKNOWN is treated as FALSE, this may allow certain additional * simplifications. A result of UNKNOWN may yield FALSE, however it may still * yield UNKNOWN. (If the simplified expression has type BOOLEAN NOT NULL, * then of course it can only return FALSE.) */ public RexNode simplifyUnknownAs(RexNode e, RexUnknownAs unknownAs) { return verify(e, unknownAs, simplifier -> simplifier.simplify(e, unknownAs)); }
/** * If boolean is true, simplify cond in input branch and return new branch. * Otherwise, simply return input branch. */ private CaseBranch generateBranch(boolean simplifyCond, RexSimplify simplifier, CaseBranch branch) { if (simplifyCond) { // the previous branch was merged, time to simplify it and // add it to the final result return new CaseBranch( simplifier.simplify(branch.cond, RexUnknownAs.FALSE), branch.value); } return branch; }
private void simplifyAndTerms(List<RexNode> terms) { RexSimplify simplify = this; for (int i = 0; i < terms.size(); i++) { RexNode t = terms.get(i); if (Predicate.of(t) == null) { continue; } terms.set(i, simplify.simplify(t, UNKNOWN)); RelOptPredicateList newPredicates = simplify.predicates.union(rexBuilder, RelOptPredicateList.of(rexBuilder, terms.subList(i, i + 1))); simplify = simplify.withPredicates(newPredicates); } for (int i = 0; i < terms.size(); i++) { RexNode t = terms.get(i); if (Predicate.of(t) != null) { continue; } terms.set(i, simplify.simplify(t, UNKNOWN)); } }
private void simplifyAndTerms(List<RexNode> terms) { RexSimplify simplify = this; for (int i = 0; i < terms.size(); i++) { RexNode t = terms.get(i); if (Predicate.of(t) == null) { continue; } terms.set(i, simplify.simplify(t, UNKNOWN)); RelOptPredicateList newPredicates = simplify.predicates.union(rexBuilder, RelOptPredicateList.of(rexBuilder, terms.subList(i, i + 1))); simplify = simplify.withPredicates(newPredicates); } for (int i = 0; i < terms.size(); i++) { RexNode t = terms.get(i); if (Predicate.of(t) != null) { continue; } terms.set(i, simplify.simplify(t, UNKNOWN)); } }
private void simplifyOrTerms(List<RexNode> terms) { // Suppose we are processing "e1(x) OR e2(x) OR e3(x)". When we are // visiting "e3(x)" we know both "e1(x)" and "e2(x)" are not true (they // may be unknown), because if either of them were true we would have // stopped. RexSimplify simplify = this; for (int i = 0; i < terms.size(); i++) { final RexNode t = terms.get(i); if (Predicate.of(t) == null) { continue; } final RexNode t2 = simplify.simplify(t, RexUnknownAs.UNKNOWN); terms.set(i, t2); final RexNode inverse = simplify.simplify(rexBuilder.makeCall(SqlStdOperatorTable.NOT, t2), RexUnknownAs.UNKNOWN); final RelOptPredicateList newPredicates = simplify.predicates.union(rexBuilder, RelOptPredicateList.of(rexBuilder, ImmutableList.of(inverse))); simplify = simplify.withPredicates(newPredicates); } for (int i = 0; i < terms.size(); i++) { final RexNode t = terms.get(i); if (Predicate.of(t) != null) { continue; } terms.set(i, simplify.simplify(t, RexUnknownAs.UNKNOWN)); } }
private void simplifyOrTerms(List<RexNode> terms) { // Suppose we are processing "e1(x) OR e2(x) OR e3(x)". When we are // visiting "e3(x)" we know both "e1(x)" and "e2(x)" are not true (they // may be unknown), because if either of them were true we would have // stopped. RexSimplify simplify = this; for (int i = 0; i < terms.size(); i++) { final RexNode t = terms.get(i); if (Predicate.of(t) == null) { continue; } final RexNode t2 = simplify.simplify(t, RexUnknownAs.UNKNOWN); terms.set(i, t2); final RexNode inverse = simplify.simplify(rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_TRUE, t2), RexUnknownAs.UNKNOWN); final RelOptPredicateList newPredicates = simplify.predicates.union(rexBuilder, RelOptPredicateList.of(rexBuilder, ImmutableList.of(inverse))); simplify = simplify.withPredicates(newPredicates); } for (int i = 0; i < terms.size(); i++) { final RexNode t = terms.get(i); if (Predicate.of(t) != null) { continue; } terms.set(i, simplify.simplify(t, RexUnknownAs.UNKNOWN)); } }
private RexNode simplifyCoalesce(RexCall call) { final Set<String> digests = new HashSet<>(); final List<RexNode> operands = new ArrayList<>(); for (RexNode operand : call.getOperands()) { operand = simplify(operand, UNKNOWN); if (digests.add(operand.toString())) { operands.add(operand); } if (!operand.getType().isNullable()) { break; } } switch (operands.size()) { case 0: return rexBuilder.makeNullLiteral(call.type); case 1: return operands.get(0); default: if (operands.equals(call.operands)) { return call; } return call.clone(call.type, operands); } }
private RexNode simplifyCoalesce(RexCall call) { final Set<RexNode> operandSet = new HashSet<>(); final List<RexNode> operands = new ArrayList<>(); for (RexNode operand : call.getOperands()) { operand = simplify(operand, UNKNOWN); if (!RexUtil.isNull(operand) && operandSet.add(operand)) { operands.add(operand); } if (!operand.getType().isNullable()) { break; } } switch (operands.size()) { case 0: return rexBuilder.makeNullLiteral(call.type); case 1: return operands.get(0); default: if (operands.equals(call.operands)) { return call; } return call.clone(call.type, operands); } }
@Override public RexNode visitCall(RexCall call) { RexUnknownAs unknownAs = this.unknownAs; switch (unknownAs) { case FALSE: switch (call.getKind()) { case AND: case CASE: // Default value is used for top operator unknownAs = unknownAsMap.getOrDefault(call, RexUnknownAs.FALSE); break; default: unknownAs = RexUnknownAs.FALSE; } for (RexNode operand : call.operands) { this.unknownAsMap.put(operand, unknownAs); } } RexNode node = super.visitCall(call); RexNode simplifiedNode = simplify.simplify(node, unknownAs); if (node == simplifiedNode) { return node; } if (simplifiedNode.getType().equals(call.getType())) { return simplifiedNode; } return simplify.rexBuilder.makeCast(call.getType(), simplifiedNode, matchNullability); } }
@Override public RexNode visitCall(RexCall call) { RexUnknownAs unknownAs = this.unknownAs; switch (unknownAs) { case FALSE: switch (call.getKind()) { case AND: case CASE: // Default value is used for top operator unknownAs = unknownAsMap.getOrDefault(call, RexUnknownAs.FALSE); break; default: unknownAs = RexUnknownAs.FALSE; } for (RexNode operand : call.operands) { this.unknownAsMap.put(operand, unknownAs); } } RexNode node = super.visitCall(call); RexNode simplifiedNode = simplify.simplify(node, unknownAs); if (node == simplifiedNode) { return node; } if (simplifiedNode.getType().equals(call.getType())) { return simplifiedNode; } return simplify.rexBuilder.makeCast(call.getType(), simplifiedNode, matchNullability); } }
private void checkDateRange(Fixture f, RexNode e, Matcher<String> intervalMatcher) { e = DateRangeRules.replaceTimeUnits(f.rexBuilder, e, "UTC"); final RexNode e2 = f.simplify.simplify(e); List<Interval> intervals = DruidDateTimeUtils.createInterval(e2); if (intervals == null) { throw new AssertionError("null interval"); } assertThat(intervals.toString(), intervalMatcher); }
private void checkDateRange(Fixture f, RexNode e, String timeZone, Matcher<String> matcher, Matcher<String> simplifyMatcher) { e = DateRangeRules.replaceTimeUnits(f.rexBuilder, e, timeZone); assertThat(e.toString(), matcher); final RexNode e2 = f.simplify.simplify(e); assertThat(e2.toString(), simplifyMatcher); }
private void checkDateRange(Fixture f, RexNode e, String timeZone, Matcher<String> matcher, Matcher<String> simplifyMatcher) { e = DateRangeRules.replaceTimeUnits(f.rexBuilder, e, timeZone); assertThat(e.toString(), matcher); final RexNode e2 = f.simplify.simplify(e); assertThat(e2.toString(), simplifyMatcher); }
@Test public void testSimplifyCaseBranchRemovalStrengthensType() { RexNode caseNode = case_(falseLiteral, nullBool, eq(div(vInt(), literal(2)), literal(3)), trueLiteral, falseLiteral); assertThat("Expected to have a nullable type for " + caseNode + ".", caseNode.getType().isNullable(), is(true)); RexNode res = simplify.simplify(caseNode); assertThat("Expected to have a nonNullable type for " + res + ".", res.getType().isNullable(), is(false)); }