You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by vl...@apache.org on 2019/01/09 05:53:59 UTC

[calcite] branch master updated: [CALCITE-2344] Avoid inferring $0=null predicate from $0 IS NULL when $0 is not nullable

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

vladimirsitnikov 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 5ff5765  [CALCITE-2344] Avoid inferring $0=null predicate from $0 IS NULL when $0 is not nullable
5ff5765 is described below

commit 5ff57651c7bdbc61ecbc212293c21ae90d3d370f
Author: Laurent Goujon <la...@apache.org>
AuthorDate: Thu May 31 08:27:29 2018 -0700

    [CALCITE-2344] Avoid inferring $0=null predicate from $0 IS NULL when $0 is not nullable
    
    fixes #714
---
 .../java/org/apache/calcite/plan/RelOptUtil.java   |  2 +-
 .../main/java/org/apache/calcite/rex/RexUtil.java  | 11 +++--
 .../org/apache/calcite/test/RelOptRulesTest.java   | 42 +++++++++++++++++++
 .../org/apache/calcite/test/RelOptRulesTest.xml    | 48 ++++++++++++++++++++++
 4 files changed, 96 insertions(+), 7 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
index 0e68a11..1c69c15 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
@@ -377,7 +377,7 @@ public abstract class RelOptUtil {
         + "set type is " + expectedRowType.getFullTypeString()
         + "\nexpression type is " + actualRowType.getFullTypeString()
         + "\nset is " + equivalenceClass.toString()
-        + "\nexpression is " + newRel.toString();
+        + "\nexpression is " + RelOptUtil.toString(newRel);
     throw new AssertionError(s);
   }
 
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 053d950..9308577 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexUtil.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexUtil.java
@@ -367,18 +367,17 @@ public class RexUtil {
       return;
     }
     final List<RexNode> operands = ((RexCall) predicate).getOperands();
-    if (operands.size() != 2 && predicate.getKind() == SqlKind.EQUALS) {
-      decompose(excludeSet, predicate);
-      return;
-    }
-    // if it reaches here, we have rexNode equals rexNode
     final RexNode left;
     final RexNode right;
     if (predicate.getKind() == SqlKind.EQUALS) {
       left = operands.get(0);
       right = operands.get(1);
-    } else {
+    } else { // is null
       left = operands.get(0);
+      if (!left.getType().isNullable()) {
+        // There's no sense in inferring $0=null when $0 is not nullable
+        return;
+      }
       right = rexBuilder.makeNullLiteral(left.getType());
     }
     // Note that literals are immutable too, and they can only be compared
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 0f59cb6..9dca7b1 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -3269,6 +3269,48 @@ public class RelOptRulesTest extends RelOptTestBase {
         .check();
   }
 
+  /** Test case for DX-11490
+   * Make sure the planner doesn't fail over wrong push down
+   * of is null */
+  @Test public void testIsNullPushDown() {
+    HepProgramBuilder preBuilder = new HepProgramBuilder();
+    preBuilder.addRuleInstance(ProjectToWindowRule.PROJECT);
+
+    HepProgramBuilder builder = new HepProgramBuilder();
+    builder.addRuleInstance(ReduceExpressionsRule.PROJECT_INSTANCE);
+    builder.addRuleInstance(ReduceExpressionsRule.FILTER_INSTANCE);
+    HepPlanner hepPlanner = new HepPlanner(builder.build());
+
+    final String sql = "select empno, deptno, w_count from (\n"
+        + "  select empno, deptno, count(empno) over (w) w_count\n"
+        + "  from emp\n"
+        + "  window w as (partition by deptno order by empno)\n"
+        + ") sub_query where w_count is null";
+    sql(sql)
+        .withPre(preBuilder.build())
+        .with(hepPlanner)
+        .check();
+  }
+
+  @Test public void testIsNullPushDown2() {
+    HepProgramBuilder preBuilder = new HepProgramBuilder();
+    preBuilder.addRuleInstance(ProjectToWindowRule.PROJECT);
+
+    HepProgramBuilder builder = new HepProgramBuilder();
+    builder.addRuleInstance(ReduceExpressionsRule.PROJECT_INSTANCE);
+    builder.addRuleInstance(ReduceExpressionsRule.FILTER_INSTANCE);
+    HepPlanner hepPlanner = new HepPlanner(builder.build());
+
+    final String sql = "select empno, deptno, w_count from (\n"
+        + "  select empno, deptno, count(empno) over (ROWS BETWEEN 10 PRECEDING AND 1 PRECEDING) w_count\n"
+        + "  from emp\n"
+        + ") sub_query where w_count is null";
+    sql(sql)
+        .withPre(preBuilder.build())
+        .with(hepPlanner)
+        .check();
+  }
+
   /** Test case for
    * <a href="https://issues.apache.org/jira/browse/CALCITE-750">[CALCITE-750]
    * Allow windowed aggregate on top of regular aggregate</a>. */
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 743dac5..76da50b 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -197,6 +197,54 @@ LogicalProject(EXPR$0=[COUNT() OVER (PARTITION BY $0 ORDER BY $0 RANGE BETWEEN U
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testIsNullPushDown">
+        <Resource name="sql">
+            <![CDATA[select w_count from (
+  select count(*) over (w) w_count
+  from emp
+  window w as (partition by empno order by empno)
+) sub_query where w_count is null)]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalProject(EMPNO=[$0], DEPTNO=[$1], W_COUNT=[$2])
+  LogicalValues(tuples=[[]])
+]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+LogicalProject(EMPNO=[$0], DEPTNO=[$1], W_COUNT=[$2])
+  LogicalFilter(condition=[IS NULL($2)])
+    LogicalProject(EMPNO=[$0], DEPTNO=[$7], $2=[$9])
+      LogicalWindow(window#0=[window(partition {7} order by [0] range between UNBOUNDED PRECEDING and CURRENT ROW aggs [COUNT($0)])])
+        LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testIsNullPushDown2">
+        <Resource name="sql">
+            <![CDATA[select w_count from (
+  select count(*) over (w) w_count
+  from emp
+  window w as (partition by empno order by empno)
+) sub_query where w_count is null)]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalProject(EMPNO=[$0], DEPTNO=[$1], W_COUNT=[$2])
+  LogicalValues(tuples=[[]])
+]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+LogicalProject(EMPNO=[$0], DEPTNO=[$1], W_COUNT=[$2])
+  LogicalFilter(condition=[IS NULL($2)])
+    LogicalWindow(window#0=[window(partition {} order by [] rows between $2 PRECEDING and $3 PRECEDING aggs [COUNT($0)])])
+      LogicalProject(EMPNO=[$0], DEPTNO=[$7])
+        LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+    </TestCase>
     <TestCase name="testProjectToWindowRuleForMultipleWindows">
         <Resource name="sql">
             <![CDATA[select