calcite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jh...@apache.org
Subject [1/2] calcite git commit: [CALCITE-1778] Query with "WHERE CASE ..." throws AssertionError "Cast for just nullability not allowed"
Date Tue, 09 May 2017 01:48:47 GMT
Repository: calcite
Updated Branches:
  refs/heads/master 60b4f4eb1 -> 520c0ccc9


[CALCITE-1778] Query with "WHERE CASE ..." throws AssertionError "Cast for just nullability
not allowed"

Solve by making RelBuilder remove nullability casts before creating filters.

Remove some spaces from test logs.


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

Branch: refs/heads/master
Commit: 6b8e2c3d3e4468206ac974a090fa8e7db6b4e347
Parents: 60b4f4e
Author: Julian Hyde <jhyde@apache.org>
Authored: Mon May 8 14:55:29 2017 -0700
Committer: Julian Hyde <jhyde@apache.org>
Committed: Mon May 8 17:12:55 2017 -0700

----------------------------------------------------------------------
 .../rel/rules/FilterProjectTransposeRule.java   | 27 ++++----
 .../rel/rules/ReduceExpressionsRule.java        |  9 +--
 .../org/apache/calcite/rex/RexSimplify.java     | 10 +++
 .../org/apache/calcite/tools/RelBuilder.java    | 10 ++-
 .../apache/calcite/test/RelOptRulesTest.java    | 15 ++++-
 .../org/apache/calcite/test/RelOptRulesTest.xml | 71 +++++++++++++-------
 6 files changed, 94 insertions(+), 48 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/6b8e2c3d/core/src/main/java/org/apache/calcite/rel/rules/FilterProjectTransposeRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/FilterProjectTransposeRule.java
b/core/src/main/java/org/apache/calcite/rel/rules/FilterProjectTransposeRule.java
index 2c0797b..d774b2a 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/FilterProjectTransposeRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/FilterProjectTransposeRule.java
@@ -24,10 +24,9 @@ import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.Filter;
 import org.apache.calcite.rel.core.Project;
 import org.apache.calcite.rel.core.RelFactories;
-import org.apache.calcite.rel.type.RelDataTypeFactory;
-import org.apache.calcite.rex.RexCall;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexOver;
+import org.apache.calcite.rex.RexSimplify;
 import org.apache.calcite.rex.RexUtil;
 import org.apache.calcite.tools.RelBuilder;
 import org.apache.calcite.tools.RelBuilderFactory;
@@ -117,20 +116,18 @@ public class FilterProjectTransposeRule extends RelOptRule {
     RexNode newCondition =
         RelOptUtil.pushPastProject(filter.getCondition(), project);
 
-    // Remove cast of BOOLEAN NOT NULL to BOOLEAN or vice versa. Filter accepts
-    // nullable and not-nullable conditions, but a CAST might get in the way of
-    // other rewrites.
-    final RelDataTypeFactory typeFactory = filter.getCluster().getTypeFactory();
-    if (RexUtil.isNullabilityCast(typeFactory, newCondition)) {
-      newCondition = ((RexCall) newCondition).getOperands().get(0);
-    }
-
     final RelBuilder relBuilder = call.builder();
-    RelNode newFilterRel =
-        copyFilter
-            ? filter.copy(filter.getTraitSet(), project.getInput(),
-                newCondition)
-            : relBuilder.push(project.getInput()).filter(newCondition).build();
+    RelNode newFilterRel;
+    if (copyFilter) {
+      final RexSimplify simplify =
+          new RexSimplify(relBuilder.getRexBuilder(), false, RexUtil.EXECUTOR);
+      newCondition = simplify.removeNullabilityCast(newCondition);
+      newFilterRel = filter.copy(filter.getTraitSet(), project.getInput(),
+          newCondition);
+    } else {
+      newFilterRel =
+          relBuilder.push(project.getInput()).filter(newCondition).build();
+    }
 
     RelNode newProjRel =
         copyProject

http://git-wip-us.apache.org/repos/asf/calcite/blob/6b8e2c3d/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
index d5530c9..cc1b681 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
@@ -170,12 +170,9 @@ public abstract class ReduceExpressionsRule extends RelOptRule {
           || RexUtil.isNullLiteral(newConditionExp, true)) {
         call.transformTo(createEmptyRelOrEquivalent(call, filter));
       } else if (reduced) {
-        if (RexUtil.isNullabilityCast(filter.getCluster().getTypeFactory(),
-            newConditionExp)) {
-          newConditionExp = ((RexCall) newConditionExp).getOperands().get(0);
-        }
-        call.transformTo(call.builder().
-            push(filter.getInput()).filter(newConditionExp).build());
+        call.transformTo(call.builder()
+            .push(filter.getInput())
+            .filter(newConditionExp).build());
       } else {
         if (newConditionExp instanceof RexCall) {
           boolean reverse = newConditionExp.getKind() == SqlKind.NOT;

http://git-wip-us.apache.org/repos/asf/calcite/blob/6b8e2c3d/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
index fb791f5..97656d6 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
@@ -821,6 +821,16 @@ public class RexSimplify {
     }
   }
 
+  /** Removes any casts that change nullability but not type.
+   *
+   * <p>For example, {@code CAST(1 = 0 AS BOOLEAN)} becomes {@code 1 = 0}. */
+  public RexNode removeNullabilityCast(RexNode e) {
+    while (RexUtil.isNullabilityCast(rexBuilder.getTypeFactory(), e)) {
+      e = ((RexCall) e).operands.get(0);
+    }
+    return e;
+  }
+
   private static RexNode processRange(RexBuilder rexBuilder,
       List<RexNode> terms, Map<String, Pair<Range, List<RexNode>>>
rangeTerms,
       RexNode term, RexNode ref, RexLiteral constant, SqlKind comparison) {

http://git-wip-us.apache.org/repos/asf/calcite/blob/6b8e2c3d/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
index c2d76f0..2e6750d 100644
--- a/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
+++ b/core/src/main/java/org/apache/calcite/tools/RelBuilder.java
@@ -812,9 +812,15 @@ public class RelBuilder {
     if (x.isAlwaysFalse()) {
       return empty();
     }
-    if (!x.isAlwaysTrue()) {
+
+    // Remove cast of BOOLEAN NOT NULL to BOOLEAN or vice versa. Filter accepts
+    // nullable and not-nullable conditions, but a CAST might get in the way of
+    // other rewrites.
+    final RexNode x2 = simplifierUnknownAsFalse.removeNullabilityCast(x);
+
+    if (!x2.isAlwaysTrue()) {
       final Frame frame = stack.pop();
-      final RelNode filter = filterFactory.createFilter(frame.rel, x);
+      final RelNode filter = filterFactory.createFilter(frame.rel, x2);
       stack.push(new Frame(filter, frame.fields));
     }
     return this;

http://git-wip-us.apache.org/repos/asf/calcite/blob/6b8e2c3d/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
----------------------------------------------------------------------
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 f70640f..3f22f52 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -904,6 +904,17 @@ public class RelOptRulesTest extends RelOptTestBase {
             + "and upper(ename) = 'FOO'");
   }
 
+  /** Test case for
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-1778">[CALCITE-1778]
+   * Query with "WHERE CASE" throws AssertionError "Cast for just nullability
+   * not allowed"</a>. */
+  @Test public void testPushProjectPastFilter2() {
+    final String sql = "select count(*)\n"
+        + "from emp\n"
+        + "where case when mgr < 10 then true else false end";
+    sql(sql).withRule(ProjectFilterTransposeRule.INSTANCE).check();
+  }
+
   @Test public void testPushProjectPastJoin() {
     checkPlanning(ProjectJoinTransposeRule.INSTANCE,
         "select e.sal + b.comm from emp e inner join bonus b "
@@ -911,10 +922,10 @@ public class RelOptRulesTest extends RelOptTestBase {
   }
 
   private static final String NOT_STRONG_EXPR =
-      "case when e.sal < 11 then 11 else -1 * e.sal end ";
+      "case when e.sal < 11 then 11 else -1 * e.sal end";
 
   private static final String STRONG_EXPR =
-      "case when e.sal < 11 then -1 * e.sal else e.sal end ";
+      "case when e.sal < 11 then -1 * e.sal else e.sal end";
 
   /** Test case for
    * <a href="https://issues.apache.org/jira/browse/CALCITE-1753">[CALCITE-1753]

http://git-wip-us.apache.org/repos/asf/calcite/blob/6b8e2c3d/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
----------------------------------------------------------------------
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 dd3861b..046505c 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -865,8 +865,8 @@ LogicalProject(EXPR$0=[+($1, $4)])
     <TestCase name="testPushProjectPastInnerJoinStrong">
         <Resource name="sql">
             <![CDATA[select count(*), case when e.sal < 11 then -1 * e.sal else e.sal
end
-            from emp e inner join bonus b on e.ename = b.ename group by
-            case when e.sal < 11 then -1 * e.sal else e.sal end]]>
+from emp e inner join bonus b on e.ename = b.ename
+group by case when e.sal < 11 then -1 * e.sal else e.sal end]]>
         </Resource>
         <Resource name="planBefore">
             <![CDATA[
@@ -894,8 +894,8 @@ LogicalProject(EXPR$0=[$1], EXPR$1=[$0])
     <TestCase name="testPushProjectPastInnerJoin">
         <Resource name="sql">
             <![CDATA[select count(*), case when e.sal < 11 then 11 else -1 * e.sal
end
-            from emp e inner join bonus b on e.ename = b.ename group by
-            case when e.sal < 11 then 11 else -1 * e.sal end]]>
+from emp e inner join bonus b on e.ename = b.ename
+group by case when e.sal < 11 then 11 else -1 * e.sal end]]>
         </Resource>
         <Resource name="planBefore">
             <![CDATA[
@@ -923,8 +923,8 @@ LogicalProject(EXPR$0=[$1], EXPR$1=[$0])
     <TestCase name="testPushProjectPastLeftJoin">
         <Resource name="sql">
             <![CDATA[select count(*), case when e.sal < 11 then 11 else -1 * e.sal
end
-            from emp e left outer join bonus b on e.ename = b.ename group by
-            case when e.sal < 11 then 11 else -1 * e.sal end]]>
+from emp e left outer join bonus b on e.ename = b.ename
+group by case when e.sal < 11 then 11 else -1 * e.sal end]]>
         </Resource>
         <Resource name="planBefore">
             <![CDATA[
@@ -952,8 +952,8 @@ LogicalProject(EXPR$0=[$1], EXPR$1=[$0])
     <TestCase name="testPushProjectPastLeftJoinSwap">
         <Resource name="sql">
             <![CDATA[select count(*), case when e.sal < 11 then 11 else -1 * e.sal
end
-            from bonus b left outer join emp e on e.ename = b.ename group by
-            case when e.sal < 11 then 11 else -1 * e.sal end]]>
+from bonus b left outer join emp e on e.ename = b.ename
+group by case when e.sal < 11 then 11 else -1 * e.sal end]]>
         </Resource>
         <Resource name="planBefore">
             <![CDATA[
@@ -981,8 +981,8 @@ LogicalProject(EXPR$0=[$1], EXPR$1=[$0])
     <TestCase name="testPushProjectPastLeftJoinSwapStrong">
         <Resource name="sql">
             <![CDATA[select count(*), case when e.sal < 11 then -1 * e.sal else e.sal
end
-            from bonus b left outer join emp e on e.ename = b.ename group by
-            case when e.sal < 11 then -1 * e.sal else e.sal end]]>
+from bonus b left outer join emp e on e.ename = b.ename
+group by case when e.sal < 11 then -1 * e.sal else e.sal end]]>
         </Resource>
         <Resource name="planBefore">
             <![CDATA[
@@ -1039,8 +1039,8 @@ LogicalProject(EXPR$0=[$1], EXPR$1=[$0])
     <TestCase name="testPushProjectPastRightJoin">
         <Resource name="sql">
             <![CDATA[select count(*), case when e.sal < 11 then 11 else -1 * e.sal
end
-            from emp e right outer join bonus b on e.ename = b.ename group by
-            case when e.sal < 11 then 11 else -1 * e.sal end]]>
+from emp e right outer join bonus b on e.ename = b.ename
+group by case when e.sal < 11 then 11 else -1 * e.sal end]]>
         </Resource>
         <Resource name="planBefore">
             <![CDATA[
@@ -1067,9 +1067,10 @@ LogicalProject(EXPR$0=[$1], EXPR$1=[$0])
     </TestCase>
     <TestCase name="testPushProjectPastRightJoinStrong">
         <Resource name="sql">
-            <![CDATA[select count(*), case when e.sal < 11 then -1 * e.sal else e.sal
end
-            from emp e right outer join bonus b on e.ename = b.ename group by
-            case when e.sal < 11 then -1 * e.sal else e.sal end]]>
+            <![CDATA[select count(*),
+ case when e.sal < 11 then -1 * e.sal else e.sal end
+from emp e right outer join bonus b on e.ename = b.ename
+group by case when e.sal < 11 then -1 * e.sal else e.sal end]]>
         </Resource>
         <Resource name="planBefore">
             <![CDATA[
@@ -1097,8 +1098,8 @@ LogicalProject(EXPR$0=[$1], EXPR$1=[$0])
     <TestCase name="testPushProjectPastRightJoinSwap">
         <Resource name="sql">
             <![CDATA[select count(*), case when e.sal < 11 then 11 else -1 * e.sal
end
-            from bonus b right outer join emp e on e.ename = b.ename group by
-            case when e.sal < 11 then 11 else -1 * e.sal end]]>
+from bonus b right outer join emp e on e.ename = b.ename
+group by case when e.sal < 11 then 11 else -1 * e.sal end]]>
         </Resource>
         <Resource name="planBefore">
             <![CDATA[
@@ -1126,8 +1127,8 @@ LogicalProject(EXPR$0=[$1], EXPR$1=[$0])
     <TestCase name="testPushProjectPastRightJoinSwapStrong">
         <Resource name="sql">
             <![CDATA[select count(*), case when e.sal < 11 then -1 * e.sal else e.sal
end
-            from bonus b right outer join emp e on e.ename = b.ename group by
-            case when e.sal < 11 then -1 * e.sal else e.sal end]]>
+from bonus b right outer join emp e on e.ename = b.ename
+group by case when e.sal < 11 then -1 * e.sal else e.sal end]]>
         </Resource>
         <Resource name="planBefore">
             <![CDATA[
@@ -1155,8 +1156,8 @@ LogicalProject(EXPR$0=[$1], EXPR$1=[$0])
     <TestCase name="testPushProjectPastFullJoin">
         <Resource name="sql">
             <![CDATA[select count(*), case when e.sal < 11 then 11 else -1 * e.sal
end
-            from emp e full outer join bonus b on e.ename = b.ename group by
-            case when e.sal < 11 then 11 else -1 * e.sal end]]>
+from emp e full outer join bonus b on e.ename = b.ename
+group by case when e.sal < 11 then 11 else -1 * e.sal end]]>
         </Resource>
         <Resource name="planBefore">
             <![CDATA[
@@ -1184,8 +1185,8 @@ LogicalProject(EXPR$0=[$1], EXPR$1=[$0])
     <TestCase name="testPushProjectPastFullJoinStrong">
         <Resource name="sql">
             <![CDATA[select count(*), case when e.sal < 11 then -1 * e.sal else e.sal
end
-            from emp e full outer join bonus b on e.ename = b.ename group by
-            case when e.sal < 11 then -1 * e.sal else e.sal end]]>
+from emp e full outer join bonus b on e.ename = b.ename
+group by case when e.sal < 11 then -1 * e.sal else e.sal end]]>
         </Resource>
         <Resource name="planBefore">
             <![CDATA[
@@ -3753,6 +3754,30 @@ LogicalAggregate(group=[{1}], EXPR$1=[$SUM0($2)])
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testPushProjectPastFilter2">
+        <Resource name="sql">
+            <![CDATA[select count(*)
+from emp
+where case when mgr < 10 then true else false end]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+LogicalAggregate(group=[{}], EXPR$0=[COUNT()])
+  LogicalProject($f0=[0])
+    LogicalFilter(condition=[CASE(<($3, 10), true, false)])
+      LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalAggregate(group=[{}], EXPR$0=[COUNT()])
+  LogicalProject($f0=[0])
+    LogicalFilter(condition=[<($0, 10)])
+      LogicalProject(MGR=[$3])
+        LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+    </TestCase>
     <TestCase name="testTransitiveInferenceJoin">
         <Resource name="sql">
             <![CDATA[select 1 from sales.emp d inner join sales.emp e on d.deptno = e.deptno
where e.deptno > 7]]>


Mime
View raw message