You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by da...@apache.org on 2019/07/19 06:06:13 UTC

[calcite] branch master updated: [CALCITE-3174] IS NOT DISTINCT FROM condition pushed from filter to join is not collapsed(Bohdan Kazydub)

This is an automated email from the ASF dual-hosted git repository.

danny0405 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/master by this push:
     new 6d7eca1  [CALCITE-3174] IS NOT DISTINCT FROM condition pushed from filter to join is not collapsed(Bohdan Kazydub)
6d7eca1 is described below

commit 6d7eca19bb0a22d059abe4e283d003d2848e55af
Author: Bohdan Kazydub <bo...@gmail.com>
AuthorDate: Fri Jul 5 13:27:58 2019 +0300

    [CALCITE-3174] IS NOT DISTINCT FROM condition pushed from filter to join is not collapsed(Bohdan Kazydub)
    
    If filter containing IS NOT DISTINCT FROM expression is pushed to join,
    this results to new join condition having this expanded IS NOT DISTINCT
    FROM expression (and not collapsed one), which can be further modified
    making impossible to identify the IS NOT DISTINCT FROM condition.
    
    close apache/calcite#1300
---
 .../apache/calcite/rel/rules/FilterJoinRule.java   | 25 +++++++++++++++++++++-
 .../org/apache/calcite/test/RelOptRulesTest.java   |  9 ++++++++
 .../org/apache/calcite/test/RelOptRulesTest.xml    | 22 +++++++++++++++++++
 3 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/core/src/main/java/org/apache/calcite/rel/rules/FilterJoinRule.java b/core/src/main/java/org/apache/calcite/rel/rules/FilterJoinRule.java
index 9087195..144af2c 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/FilterJoinRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/FilterJoinRule.java
@@ -27,6 +27,7 @@ import org.apache.calcite.rel.core.JoinRelType;
 import org.apache.calcite.rel.core.RelFactories;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.rex.RexCall;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexUtil;
 import org.apache.calcite.tools.RelBuilder;
@@ -140,7 +141,7 @@ public abstract class FilterJoinRule extends RelOptRule {
 
     final List<RexNode> aboveFilters =
         filter != null
-            ? conjunctions(filter.getCondition())
+            ? getConjunctions(filter)
             : new ArrayList<>();
     final ImmutableList<RexNode> origAboveFilters =
         ImmutableList.copyOf(aboveFilters);
@@ -287,6 +288,28 @@ public abstract class FilterJoinRule extends RelOptRule {
   }
 
   /**
+   * Get conjunctions of filter's condition but with collapsed
+   * {@code IS NOT DISTINCT FROM} expressions if needed.
+   *
+   * @param filter filter containing condition
+   * @return condition conjunctions with collapsed {@code IS NOT DISTINCT FROM}
+   * expressions if any
+   * @see RelOptUtil#conjunctions(RexNode)
+   */
+  private List<RexNode> getConjunctions(Filter filter) {
+    List<RexNode> conjunctions = conjunctions(filter.getCondition());
+    RexBuilder rexBuilder = filter.getCluster().getRexBuilder();
+    for (int i = 0; i < conjunctions.size(); i++) {
+      RexNode node = conjunctions.get(i);
+      if (node instanceof RexCall) {
+        conjunctions.set(i,
+            RelOptUtil.collapseExpandedIsNotDistinctFromExpr((RexCall) node, rexBuilder));
+      }
+    }
+    return conjunctions;
+  }
+
+  /**
    * Validates that target execution framework can satisfy join filters.
    *
    * <p>If the join filter cannot be satisfied (for example, if it is
diff --git a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
index 8e97702..dcf23dc 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -5876,6 +5876,15 @@ public class RelOptRulesTest extends RelOptTestBase {
     assertEquals(collationBefore, collationAfter);
   }
 
+  @Test public void testPushFiltertWithIsNotDistinctFromPastJoin() {
+    String query = "SELECT * FROM "
+        + "emp t1 INNER JOIN "
+        + "emp t2 "
+        + "ON t1.deptno = t2.deptno "
+        + "WHERE t1.ename is not distinct from t2.ename";
+    checkPlanning(FilterJoinRule.FILTER_ON_JOIN, query);
+  }
+
   /**
    * Custom implementation of {@link Filter} for use
    * in test case to verify that {@link FilterMultiJoinMergeRule}
diff --git a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
index 288dfce..2ca593c 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -11166,4 +11166,26 @@ MultiJoin(joinFilter=[true], isFullOuterJoin=[false], joinTypes=[[INNER, LEFT]],
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testPushFiltertWithIsNotDistinctFromPastJoin">
+        <Resource name="sql">
+            <![CDATA[SELECT * FROM emp t1 INNER JOIN emp t2 ON t1.deptno = t2.deptno WHERE t1.ename is not distinct from t2.ename]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], EMPNO0=[$9], ENAME0=[$10], JOB0=[$11], MGR0=[$12], HIREDATE0=[$13], SAL0=[$14], COMM0=[$15], DEPTNO0=[$16], SLACKER0=[$17])
+  LogicalFilter(condition=[OR(AND(IS NULL($1), IS NULL($10)), IS TRUE(=($1, $10)))])
+    LogicalJoin(condition=[=($7, $16)], joinType=[inner])
+      LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+      LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], EMPNO0=[$9], ENAME0=[$10], JOB0=[$11], MGR0=[$12], HIREDATE0=[$13], SAL0=[$14], COMM0=[$15], DEPTNO0=[$16], SLACKER0=[$17])
+  LogicalJoin(condition=[AND(=($7, $16), IS NOT DISTINCT FROM($1, $10))], joinType=[inner])
+    LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+    LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+    </TestCase>
 </Root>