You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jc...@apache.org on 2017/06/19 16:49:32 UTC

calcite git commit: [CALCITE-1846] Metadata pulled up predicates should skip non-deterministic calls (Ted Xu)

Repository: calcite
Updated Branches:
  refs/heads/master d47191e8c -> 86a5cc9a4


[CALCITE-1846] Metadata pulled up predicates should skip non-deterministic calls (Ted Xu)

Close apache/calcite#475


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/86a5cc9a
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/86a5cc9a
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/86a5cc9a

Branch: refs/heads/master
Commit: 86a5cc9a45b28bdc6b60d27d6bb018f441109f66
Parents: d47191e
Author: Ted Xu <fr...@gmail.com>
Authored: Sun Jun 18 10:49:24 2017 +0800
Committer: Jesus Camacho Rodriguez <jc...@apache.org>
Committed: Mon Jun 19 17:23:22 2017 +0100

----------------------------------------------------------------------
 .../calcite/rel/metadata/RelMdPredicates.java   |  6 +-
 .../java/org/apache/calcite/rex/RexUtil.java    | 10 ++++
 .../apache/calcite/test/RelMetadataTest.java    | 60 ++++++++++++++++++++
 .../org/apache/calcite/test/RexProgramTest.java | 24 ++++++++
 4 files changed, 98 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/86a5cc9a/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 5c3a35e..8c826fb 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
@@ -286,7 +286,8 @@ public class RelMdPredicates
     return Util.first(inputInfo, RelOptPredicateList.EMPTY)
         .union(rexBuilder,
             RelOptPredicateList.of(rexBuilder,
-                RelOptUtil.conjunctions(filter.getCondition())));
+                RexUtil.retainDeterministic(
+                    RelOptUtil.conjunctions(filter.getCondition()))));
   }
 
   /** Infers predicates for a {@link org.apache.calcite.rel.core.SemiJoin}. */
@@ -646,7 +647,8 @@ public class RelMdPredicates
           pulledUpPredicates = Iterables.concat(
                 RelOptUtil.conjunctions(leftChildPredicates),
                 RelOptUtil.conjunctions(rightChildPredicates),
-                RelOptUtil.conjunctions(joinRel.getCondition()),
+                RexUtil.retainDeterministic(
+                  RelOptUtil.conjunctions(joinRel.getCondition())),
                 inferredPredicates);
         }
         return RelOptPredicateList.of(rexBuilder, pulledUpPredicates,

http://git-wip-us.apache.org/repos/asf/calcite/blob/86a5cc9a/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 df82fc9..94a3119 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexUtil.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexUtil.java
@@ -564,6 +564,16 @@ public class RexUtil {
     }
   }
 
+  public static List<RexNode> retainDeterministic(List<RexNode> list) {
+    List<RexNode> conjuctions = Lists.newArrayList();
+    for (RexNode x : list) {
+      if (isDeterministic(x)) {
+        conjuctions.add(x);
+      }
+    }
+    return conjuctions;
+  }
+
    /**
    * Returns whether a given node contains a RexCall with a specified operator
    *

http://git-wip-us.apache.org/repos/asf/calcite/blob/86a5cc9a/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 6f9af88..3109b89 100644
--- a/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelMetadataTest.java
@@ -78,8 +78,12 @@ import org.apache.calcite.rex.RexTableInputRef;
 import org.apache.calcite.rex.RexTableInputRef.RelTableRef;
 import org.apache.calcite.schema.SchemaPlus;
 import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlOperator;
+import org.apache.calcite.sql.SqlSpecialOperator;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
+import org.apache.calcite.sql.type.ReturnTypes;
 import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.tools.FrameworkConfig;
 import org.apache.calcite.tools.Frameworks;
 import org.apache.calcite.tools.RelBuilder;
 import org.apache.calcite.util.ImmutableBitSet;
@@ -2183,6 +2187,62 @@ public class RelMetadataTest extends SqlToRelTestBase {
     checkNodeTypeCount(sql, expected);
   }
 
+  private static final SqlOperator NONDETERMINISTIC_OP = new SqlSpecialOperator(
+          "NDC",
+          SqlKind.OTHER_FUNCTION,
+          0,
+          false,
+          ReturnTypes.BOOLEAN,
+          null, null) {
+    @Override public boolean isDeterministic() {
+      return false;
+    }
+  };
+
+  @Test public void testGetPredicatesForJoin() throws Exception {
+    final FrameworkConfig config = RelBuilderTest.config().build();
+    final RelBuilder builder = RelBuilder.create(config);
+    RelNode join = builder
+        .scan("EMP")
+        .scan("DEPT")
+        .join(JoinRelType.INNER, builder.call(NONDETERMINISTIC_OP))
+        .build();
+    RelMetadataQuery mq = RelMetadataQuery.instance();
+    assertTrue(mq.getPulledUpPredicates(join).pulledUpPredicates.isEmpty());
+
+    RelNode join1 = builder
+        .scan("EMP")
+        .scan("DEPT")
+        .join(JoinRelType.INNER,
+          builder.call(SqlStdOperatorTable.EQUALS,
+            builder.field(2, 0, 0),
+            builder.field(2, 1, 0)))
+        .build();
+    assertEquals("=($0, $8)",
+        mq.getPulledUpPredicates(join1).pulledUpPredicates.get(0).toString());
+  }
+
+  @Test public void testGetPredicatesForFilter() throws Exception {
+    final FrameworkConfig config = RelBuilderTest.config().build();
+    final RelBuilder builder = RelBuilder.create(config);
+    RelNode filter = builder
+        .scan("EMP")
+        .filter(builder.call(NONDETERMINISTIC_OP))
+        .build();
+    RelMetadataQuery mq = RelMetadataQuery.instance();
+    assertTrue(mq.getPulledUpPredicates(filter).pulledUpPredicates.isEmpty());
+
+    RelNode filter1 = builder
+        .scan("EMP")
+        .filter(
+          builder.call(SqlStdOperatorTable.EQUALS,
+            builder.field(1, 0, 0),
+            builder.field(1, 0, 1)))
+        .build();
+    assertEquals("=($0, $1)",
+        mq.getPulledUpPredicates(filter1).pulledUpPredicates.get(0).toString());
+  }
+
   /**
    * Matcher that succeeds for any collection that, when converted to strings
    * and sorted on those strings, matches the given reference string.

http://git-wip-us.apache.org/repos/asf/calcite/blob/86a5cc9a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java b/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
index f889347..fce0294 100644
--- a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
@@ -19,6 +19,7 @@ package org.apache.calcite.test;
 import org.apache.calcite.adapter.java.JavaTypeFactory;
 import org.apache.calcite.avatica.util.ByteString;
 import org.apache.calcite.jdbc.JavaTypeFactoryImpl;
+import org.apache.calcite.plan.RelOptUtil;
 import org.apache.calcite.plan.Strong;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
@@ -34,8 +35,11 @@ import org.apache.calcite.rex.RexProgram;
 import org.apache.calcite.rex.RexProgramBuilder;
 import org.apache.calcite.rex.RexSimplify;
 import org.apache.calcite.rex.RexUtil;
+import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.SqlOperator;
+import org.apache.calcite.sql.SqlSpecialOperator;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
+import org.apache.calcite.sql.type.ReturnTypes;
 import org.apache.calcite.sql.type.SqlTypeAssignmentRules;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.util.DateString;
@@ -65,6 +69,8 @@ import java.util.TreeMap;
 
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertThat;
 
 /**
@@ -1550,6 +1556,24 @@ public class RexProgramTest {
     checkSimplifyUnchanged(le(literalAbc, literalZero));
   }
 
+  @Test public void testIsDeterministic() {
+    SqlOperator ndc = new SqlSpecialOperator(
+            "NDC",
+            SqlKind.OTHER_FUNCTION,
+            0,
+            false,
+            ReturnTypes.BOOLEAN,
+            null, null) {
+      @Override public boolean isDeterministic() {
+        return false;
+      }
+    };
+    RexNode n = rexBuilder.makeCall(ndc);
+    assertFalse(RexUtil.isDeterministic(n));
+    assertEquals(0,
+            RexUtil.retainDeterministic(RelOptUtil.conjunctions(n)).size());
+  }
+
   private Calendar cal(int y, int m, int d, int h, int mm, int s) {
     final Calendar c = Util.calendar();
     c.set(Calendar.YEAR, y);