Repository: calcite Updated Branches: refs/heads/master b0fa9f379 -> 8281668fb
[CALCITE-993] Pull up all constant expressions, not just literals, as predicates Close apache/calcite#170 Project: http://git-wip-us.apache.org/repos/asf/calcite/repo Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/9be2bdb9 Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/9be2bdb9 Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/9be2bdb9 Branch: refs/heads/master Commit: 9be2bdb96a0f40de463ab867ab8232712c544ed8 Parents: b0fa9f3 Author: jpullokk <[email protected]> Authored: Wed Nov 25 19:02:48 2015 -0800 Committer: Julian Hyde <[email protected]> Committed: Fri Dec 4 13:32:56 2015 -0800 ---------------------------------------------------------------------- .../calcite/rel/metadata/RelMdPredicates.java | 9 +++- .../java/org/apache/calcite/rex/RexUtil.java | 57 ++++++++++++++++++++ .../apache/calcite/test/RelMetadataTest.java | 6 +-- 3 files changed, 67 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/calcite/blob/9be2bdb9/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java index f9c04d7..a35d571 100644 --- a/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java +++ b/core/src/main/java/org/apache/calcite/rel/metadata/RelMdPredicates.java @@ -190,6 +190,11 @@ public class RelMdPredicates { projectPullUpPredicates.add( rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, rexBuilder.makeInputRef(project, expr.i), literal)); + } else if (expr.e instanceof RexCall + && RexUtil.isConstant(expr.e)) { + projectPullUpPredicates.add( + rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, + rexBuilder.makeInputRef(project, expr.i), expr.e)); } } return RelOptPredicateList.of(projectPullUpPredicates); @@ -366,8 +371,8 @@ public class RelMdPredicates { final RexNode leftChildPredicates; final RexNode rightChildPredicates; - public JoinConditionBasedPredicateInference(Join joinRel, - RexNode lPreds, RexNode rPreds) { + JoinConditionBasedPredicateInference(Join joinRel, RexNode lPreds, + RexNode rPreds) { this(joinRel, joinRel instanceof SemiJoin, lPreds, rPreds); } http://git-wip-us.apache.org/repos/asf/calcite/blob/9be2bdb9/core/src/main/java/org/apache/calcite/rex/RexUtil.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rex/RexUtil.java b/core/src/main/java/org/apache/calcite/rex/RexUtil.java index d65d9be..6aaf377 100644 --- a/core/src/main/java/org/apache/calcite/rex/RexUtil.java +++ b/core/src/main/java/org/apache/calcite/rex/RexUtil.java @@ -237,6 +237,63 @@ public class RexUtil { return false; } + /** + * Walks over an expression and determines whether it is constant. + */ + private static class ConstantFinder implements RexVisitor<Boolean> { + static final ConstantFinder INSTANCE = new ConstantFinder(); + + public Boolean visitLiteral(RexLiteral literal) { + return true; + } + + public Boolean visitInputRef(RexInputRef inputRef) { + return false; + } + + public Boolean visitLocalRef(RexLocalRef localRef) { + return false; + } + + public Boolean visitOver(RexOver over) { + return false; + } + + public Boolean visitCorrelVariable(RexCorrelVariable correlVariable) { + return false; + } + + public Boolean visitDynamicParam(RexDynamicParam dynamicParam) { + return true; + } + + public Boolean visitCall(RexCall call) { + // Constant if operator is deterministic and all operands are + // constant. + return call.getOperator().isDeterministic() + && RexVisitorImpl.visitArrayAnd(this, call.getOperands()); + } + + public Boolean visitRangeRef(RexRangeRef rangeRef) { + return false; + } + + public Boolean visitFieldAccess(RexFieldAccess fieldAccess) { + // "<expr>.FIELD" is constant iff "<expr>" is constant. + return fieldAccess.getReferenceExpr().accept(this); + } + } + + /** + * Returns whether node is made up of constants. + * + * @param node to inspect + * @return true if node is made up of constants, false otherwise + */ + public static boolean isConstant(RexNode node) { + return node.accept(ConstantFinder.INSTANCE); + } + /** * Returns whether a given node contains a RexCall with a specified operator * http://git-wip-us.apache.org/repos/asf/calcite/blob/9be2bdb9/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java index 98b3a42..ddae101 100644 --- a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java +++ b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java @@ -1270,14 +1270,14 @@ public class RelMetadataTest extends SqlToRelTestBase { } @Test public void testPullUpPredicatesFromProject() { - final String sql = "select deptno, mgr, x, 'y' as y from (\n" - + " select deptno, mgr, cast(null as integer) as x\n" + final String sql = "select deptno, mgr, x, 'y' as y, z from (\n" + + " select deptno, mgr, cast(null as integer) as x, cast('1' as int) as z\n" + " from emp\n" + " where mgr is null and deptno < 10)"; final RelNode rel = convertSql(sql); RelOptPredicateList list = RelMetadataQuery.getPulledUpPredicates(rel); assertThat(list.pulledUpPredicates.toString(), - is("[IS NULL($1), <($0, 10), IS NULL($2), =($3, 'y')]")); + is("[IS NULL($1), <($0, 10), IS NULL($2), =($4, CAST('1'):INTEGER NOT NULL), =($3, 'y')]")); } /** Custom metadata interface. */
