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. */

Reply via email to