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

kgyrtkirk 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 c3fd74a  [CALCITE-2841] Simplification: push negation into Case 
expression
c3fd74a is described below

commit c3fd74a897ca1b469b6b776baeaa3c660ce5876a
Author: Zoltan Haindrich <k...@rxd.hu>
AuthorDate: Thu Oct 4 15:25:29 2018 +0200

    [CALCITE-2841] Simplification: push negation into Case expression
    
    Earlier NOT was not pushed into CASE expressions.
    Also ensure that recursion under NOT happens.
---
 .../java/org/apache/calcite/rex/RexSimplify.java   | 26 +++++++++++++++++++++-
 .../org/apache/calcite/test/RexProgramTest.java    | 16 +++++++++++++
 .../org/apache/calcite/test/RelOptRulesTest.xml    |  4 ++--
 .../apache/calcite/test/SqlToRelConverterTest.xml  |  4 ++--
 core/src/test/resources/sql/some.iq                |  2 +-
 core/src/test/resources/sql/sub-query.iq           | 14 ++++++------
 6 files changed, 53 insertions(+), 13 deletions(-)

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 ab29c96..7ae8195 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
@@ -507,7 +507,31 @@ public class RexSimplify {
       return simplify(
           rexBuilder.makeCall(SqlStdOperatorTable.AND, newOperands), 
unknownAs);
     }
-    return call;
+    if (a.getKind() == SqlKind.CASE) {
+      final List<RexNode> newOperands = new ArrayList<>();
+      List<RexNode> operands = ((RexCall) a).getOperands();
+      for (int i = 0; i < operands.size(); i += 2) {
+        if (i + 1 == operands.size()) {
+          newOperands.add(rexBuilder.makeCall(SqlStdOperatorTable.NOT, 
operands.get(i + 0)));
+        } else {
+          newOperands.add(operands.get(i + 0));
+          newOperands.add(rexBuilder.makeCall(SqlStdOperatorTable.NOT, 
operands.get(i + 1)));
+        }
+      }
+      return simplify(
+          rexBuilder.makeCall(SqlStdOperatorTable.CASE, newOperands), 
unknownAs);
+    }
+    RexNode a2 = simplify(a, unknownAs.negate());
+    if (a == a2) {
+      return call;
+    }
+    if (a2.isAlwaysTrue()) {
+      return rexBuilder.makeLiteral(false);
+    }
+    if (a2.isAlwaysFalse()) {
+      return rexBuilder.makeLiteral(true);
+    }
+    return rexBuilder.makeCall(SqlStdOperatorTable.NOT, a2);
   }
 
   private RexNode simplifyIs(RexCall call) {
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 3ff9260..3234050 100644
--- a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
@@ -1902,6 +1902,22 @@ public class RexProgramTest extends 
RexProgramBuilderBase {
     checkSimplify(caseNode, "<=(/(?0.notNullInt0, 1), 1)");
   }
 
+  @Test public void testPushNotIntoCase() {
+    checkSimplify(
+        not(
+            case_(
+                isTrue(vBool()), vBool(1),
+                gt(div(vIntNotNull(), literal(2)), literal(1)), vBool(2),
+                vBool(3))),
+        "CASE(IS TRUE(?0.bool0), NOT(?0.bool1), >(/(?0.notNullInt0, 2), 1), 
NOT(?0.bool2), NOT(?0.bool3))");
+  }
+
+  @Test public void testNotRecursion() {
+    checkSimplify(
+        not(coalesce(nullBool, trueLiteral)),
+        "false");
+  }
+
   @Test public void testSimplifyAnd() {
     RelDataType booleanNotNullableType =
         typeFactory.createTypeWithNullability(
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 5accc18..8c7e46c 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -8562,7 +8562,7 @@ LogicalProject(DEPTNO=[$0])
             <![CDATA[
 LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], 
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
   LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], 
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
-    LogicalFilter(condition=[OR(=($5, 4), NOT(CASE(IS NOT NULL($10), true, 
false)))])
+    LogicalFilter(condition=[OR(=($5, 4), IS NULL($10))])
       LogicalJoin(condition=[=($0, $9)], joinType=[left])
         LogicalTableScan(table=[[CATALOG, SALES, EMP]])
         LogicalProject(DEPTNO=[$0], i=[true])
@@ -8573,7 +8573,7 @@ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], 
MGR=[$3], HIREDATE=[$4], SAL=[$
             <![CDATA[
 LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], 
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
   LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], 
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
-    LogicalFilter(condition=[OR(=($5, 4), NOT(CASE(IS NOT NULL($10), true, 
false)))])
+    LogicalFilter(condition=[OR(=($5, 4), IS NULL($10))])
       LogicalJoin(condition=[=($0, $9)], joinType=[left])
         LogicalTableScan(table=[[CATALOG, SALES, EMP]])
         LogicalProject(DEPTNO=[$0], i=[true])
diff --git 
a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml 
b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
index 7642f98..fbe4df8 100644
--- a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
@@ -2098,7 +2098,7 @@ from emp]]>
         </Resource>
         <Resource name="plan">
             <![CDATA[
-LogicalProject(EMPNO=[$0], EXPR$1=[NOT(CASE(=($9, 0), false, IS NOT NULL($13), 
true, IS NULL($11), null:BOOLEAN, <($10, $9), null:BOOLEAN, false))])
+LogicalProject(EMPNO=[$0], EXPR$1=[OR(=($9, 0), AND(<($10, $9), null, <>($9, 
0), IS NULL($13)), AND(<>($9, 0), IS NULL($13), >=($10, $9)))])
   LogicalJoin(condition=[=($11, $12)], joinType=[left])
     LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], 
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f0=[$9], $f1=[$10], 
DEPTNO0=[$7])
       LogicalJoin(condition=[true], joinType=[inner])
@@ -2242,7 +2242,7 @@ from emp]]>
         </Resource>
         <Resource name="plan">
             <![CDATA[
-LogicalProject(EMPNO=[$0], EXPR$1=[NOT(CASE(=($9, 0), false, IS NOT NULL($13), 
true, IS NULL($11), null:BOOLEAN, <($10, $9), null:BOOLEAN, false))])
+LogicalProject(EMPNO=[$0], EXPR$1=[OR(=($9, 0), AND(<($10, $9), null, <>($9, 
0), IS NULL($13)), AND(<>($9, 0), IS NULL($13), >=($10, $9)))])
   LogicalJoin(condition=[=($11, $12)], joinType=[left])
     LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], 
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f0=[$9], $f1=[$10], 
DEPTNO0=[$7])
       LogicalJoin(condition=[true], joinType=[inner])
diff --git a/core/src/test/resources/sql/some.iq 
b/core/src/test/resources/sql/some.iq
index df3e99b..fbceee7 100644
--- a/core/src/test/resources/sql/some.iq
+++ b/core/src/test/resources/sql/some.iq
@@ -108,7 +108,7 @@ from "scott".emp;
 (14 rows)
 
 !ok
-EnumerableCalc(expr#0..10=[{inputs}], expr#11=[0], expr#12=[=($t1, $t11)], 
expr#13=[false], expr#14=[<=($t8, $t0)], expr#15=[IS TRUE($t14)], 
expr#16=[true], expr#17=[>($t1, $t2)], expr#18=[null:NULL], expr#19=[CASE($t12, 
$t13, $t15, $t16, $t17, $t18, $t14)], expr#20=[NOT($t19)], EMPNO=[$t3], 
ENAME=[$t4], JOB=[$t5], MGR=[$t6], HIREDATE=[$t7], SAL=[$t8], COMM=[$t9], 
DEPTNO=[$t10], X=[$t20])
+EnumerableCalc(expr#0..10=[{inputs}], expr#11=[0], expr#12=[=($t1, $t11)], 
expr#13=[>($t1, $t2)], expr#14=[null:BOOLEAN], expr#15=[<>($t1, $t11)], 
expr#16=[<=($t8, $t0)], expr#17=[IS NOT TRUE($t16)], expr#18=[AND($t13, $t14, 
$t15, $t17)], expr#19=[>($t8, $t0)], expr#20=[<=($t1, $t2)], expr#21=[AND($t19, 
$t15, $t17, $t20)], expr#22=[OR($t12, $t18, $t21)], EMPNO=[$t3], ENAME=[$t4], 
JOB=[$t5], MGR=[$t6], HIREDATE=[$t7], SAL=[$t8], COMM=[$t9], DEPTNO=[$t10], 
X=[$t22])
   EnumerableJoin(condition=[true], joinType=[inner])
     EnumerableAggregate(group=[{}], m=[MAX($6)], c=[COUNT()], d=[COUNT($6)])
       EnumerableTableScan(table=[[scott, EMP]])
diff --git a/core/src/test/resources/sql/sub-query.iq 
b/core/src/test/resources/sql/sub-query.iq
index e75a690..b9f6b3f 100644
--- a/core/src/test/resources/sql/sub-query.iq
+++ b/core/src/test/resources/sql/sub-query.iq
@@ -1038,7 +1038,7 @@ from "scott".emp;
 (14 rows)
 
 !ok
-EnumerableCalc(expr#0..3=[{inputs}], expr#4=[IS NULL($t3)], expr#5=[false], 
expr#6=[=($t2, $t5)], expr#7=[null:NULL], expr#8=[null:INTEGER], expr#9=[IS 
NULL($t8)], expr#10=[IS NOT NULL($t2)], expr#11=[true], expr#12=[CASE($t4, $t5, 
$t6, $t7, $t9, $t7, $t10, $t11, $t5)], expr#13=[NOT($t12)], SAL=[$t1], 
EXPR$1=[$t13])
+EnumerableCalc(expr#0..3=[{inputs}], expr#4=[IS NULL($t3)], 
expr#5=[null:BOOLEAN], expr#6=[OR($t4, $t5)], SAL=[$t1], EXPR$1=[$t6])
   EnumerableJoin(condition=[true], joinType=[left])
     EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5])
       EnumerableTableScan(table=[[scott, EMP]])
@@ -1074,7 +1074,7 @@ from "scott".emp;
 (14 rows)
 
 !ok
-EnumerableCalc(expr#0..3=[{inputs}], expr#4=[IS NULL($t3)], expr#5=[false], 
expr#6=[=($t2, $t5)], expr#7=[null:NULL], expr#8=[IS NOT NULL($t2)], 
expr#9=[true], expr#10=[CASE($t4, $t5, $t6, $t7, $t8, $t9, $t5)], 
expr#11=[NOT($t10)], SAL=[$t1], EXPR$1=[$t11])
+EnumerableCalc(expr#0..3=[{inputs}], expr#4=[IS NULL($t3)], expr#5=[false], 
expr#6=[=($t2, $t5)], expr#7=[IS TRUE($t6)], expr#8=[null:BOOLEAN], 
expr#9=[AND($t7, $t8)], expr#10=[IS NOT TRUE($t6)], expr#11=[IS NULL($t2)], 
expr#12=[AND($t10, $t11)], expr#13=[OR($t4, $t9, $t12)], SAL=[$t1], 
EXPR$1=[$t13])
   EnumerableJoin(condition=[true], joinType=[left])
     EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5])
       EnumerableTableScan(table=[[scott, EMP]])
@@ -1110,7 +1110,7 @@ from "scott".emp;
 (14 rows)
 
 !ok
-EnumerableCalc(expr#0..3=[{inputs}], expr#4=[IS NULL($t3)], expr#5=[false], 
expr#6=[=($t2, $t5)], expr#7=[null:NULL], expr#8=[null:INTEGER], expr#9=[IS 
NULL($t8)], expr#10=[IS NOT NULL($t2)], expr#11=[true], expr#12=[CASE($t4, $t5, 
$t6, $t7, $t9, $t7, $t10, $t11, $t5)], expr#13=[NOT($t12)], SAL=[$t1], 
EXPR$1=[$t13])
+EnumerableCalc(expr#0..3=[{inputs}], expr#4=[IS NULL($t3)], 
expr#5=[null:BOOLEAN], expr#6=[OR($t4, $t5)], SAL=[$t1], EXPR$1=[$t6])
   EnumerableJoin(condition=[true], joinType=[left])
     EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5])
       EnumerableTableScan(table=[[scott, EMP]])
@@ -1146,7 +1146,7 @@ from "scott".emp;
 (14 rows)
 
 !ok
-EnumerableCalc(expr#0..3=[{inputs}], expr#4=[IS NULL($t3)], expr#5=[false], 
expr#6=[=($t2, $t5)], expr#7=[null:NULL], expr#8=[null:INTEGER], expr#9=[IS 
NULL($t8)], expr#10=[IS NOT NULL($t2)], expr#11=[true], expr#12=[CASE($t4, $t5, 
$t6, $t7, $t9, $t7, $t10, $t11, $t5)], expr#13=[NOT($t12)], SAL=[$t1], 
EXPR$1=[$t13])
+EnumerableCalc(expr#0..3=[{inputs}], expr#4=[IS NULL($t3)], 
expr#5=[null:BOOLEAN], expr#6=[OR($t4, $t5)], SAL=[$t1], EXPR$1=[$t6])
   EnumerableJoin(condition=[true], joinType=[left])
     EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5])
       EnumerableTableScan(table=[[scott, EMP]])
@@ -1182,7 +1182,7 @@ from "scott".emp;
 (14 rows)
 
 !ok
-EnumerableCalc(expr#0..3=[{inputs}], expr#4=[IS NULL($t3)], expr#5=[false], 
expr#6=[=($t2, $t5)], expr#7=[null:NULL], expr#8=[null:INTEGER], expr#9=[IS 
NULL($t8)], expr#10=[IS NOT NULL($t2)], expr#11=[true], expr#12=[CASE($t4, $t5, 
$t6, $t7, $t9, $t7, $t10, $t11, $t5)], expr#13=[NOT($t12)], SAL=[$t1], 
EXPR$1=[$t13])
+EnumerableCalc(expr#0..3=[{inputs}], expr#4=[IS NULL($t3)], 
expr#5=[null:BOOLEAN], expr#6=[OR($t4, $t5)], SAL=[$t1], EXPR$1=[$t6])
   EnumerableJoin(condition=[true], joinType=[left])
     EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5])
       EnumerableTableScan(table=[[scott, EMP]])
@@ -1218,7 +1218,7 @@ from "scott".emp;
 (14 rows)
 
 !ok
-EnumerableCalc(expr#0..2=[{inputs}], expr#3=[IS NOT NULL($t2)], expr#4=[true], 
expr#5=[false], expr#6=[CASE($t3, $t4, $t5)], expr#7=[NOT($t6)], SAL=[$t1], 
EXPR$1=[$t7])
+EnumerableCalc(expr#0..2=[{inputs}], expr#3=[IS NULL($t2)], SAL=[$t1], 
EXPR$1=[$t3])
   EnumerableJoin(condition=[true], joinType=[left])
     EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5])
       EnumerableTableScan(table=[[scott, EMP]])
@@ -1252,7 +1252,7 @@ from "scott".emp;
 (14 rows)
 
 !ok
-EnumerableCalc(expr#0..3=[{inputs}], expr#4=[IS NULL($t3)], expr#5=[false], 
expr#6=[=($t2, $t5)], expr#7=[null:NULL], expr#8=[IS NOT NULL($t2)], 
expr#9=[true], expr#10=[CASE($t4, $t5, $t6, $t7, $t8, $t9, $t5)], 
expr#11=[NOT($t10)], SAL=[$t1], EXPR$1=[$t11])
+EnumerableCalc(expr#0..3=[{inputs}], expr#4=[IS NULL($t3)], expr#5=[false], 
expr#6=[=($t2, $t5)], expr#7=[IS TRUE($t6)], expr#8=[null:BOOLEAN], 
expr#9=[AND($t7, $t8)], expr#10=[IS NOT TRUE($t6)], expr#11=[IS NULL($t2)], 
expr#12=[AND($t10, $t11)], expr#13=[OR($t4, $t9, $t12)], SAL=[$t1], 
EXPR$1=[$t13])
   EnumerableJoin(condition=[true], joinType=[left])
     EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5])
       EnumerableTableScan(table=[[scott, EMP]])

Reply via email to