Repository: calcite
Updated Branches:
  refs/heads/master 9f7e565ff -> c8e91ea1d


[CALCITE-2327] RexSimplify: AND(x, y, NOT(y)) ==> AND(x, null, IS NULL(y))


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

Branch: refs/heads/master
Commit: c8e91ea1db1e519d9d73bbb8b08ee27f710cb1d4
Parents: 6b2b9ff
Author: Vladimir Sitnikov <[email protected]>
Authored: Tue Aug 28 15:04:31 2018 +0300
Committer: Vladimir Sitnikov <[email protected]>
Committed: Tue Aug 28 15:06:33 2018 +0300

----------------------------------------------------------------------
 .../org/apache/calcite/rex/RexSimplify.java     | 22 ++++++++++++--------
 .../org/apache/calcite/test/RexProgramTest.java | 20 ++++++++++++++++++
 2 files changed, 33 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/c8e91ea1/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 1274391..f5a99ef 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
@@ -718,7 +718,7 @@ public class RexSimplify {
     // Example #1. x AND y AND z AND NOT (x AND y)  - not satisfiable
     // Example #2. x AND y AND NOT (x AND y)        - not satisfiable
     // Example #3. x AND y AND NOT (x AND y AND z)  - may be satisfiable
-    RexNode bestNotDisjunction = null;
+    List<RexNode> notSatisfiableNullables = null;
     for (RexNode notDisjunction : notTerms) {
       final List<RexNode> terms2 = RelOptUtil.conjunctions(notDisjunction);
       if (!terms.containsAll(terms2)) {
@@ -732,17 +732,21 @@ public class RexSimplify {
       // x AND NOT(x) is UNKNOWN for NULL input
       // So we search for the shortest notDisjunction then convert
       // original expression to NULL and x IS NULL
-      if (bestNotDisjunction == null
-          || bestNotDisjunction.toString().length() > 
notDisjunction.toString().length()) {
-        bestNotDisjunction = notDisjunction;
+      if (notSatisfiableNullables == null) {
+        notSatisfiableNullables = new ArrayList<>();
       }
+      notSatisfiableNullables.add(notDisjunction);
     }
-    if (bestNotDisjunction != null) {
+    if (notSatisfiableNullables != null) {
+      terms.removeAll(notSatisfiableNullables);
+      
terms.add(rexBuilder.makeNullLiteral(notSatisfiableNullables.get(0).getType()));
+      for (RexNode notSatisfiableNullable : notSatisfiableNullables) {
+        terms.add(
+            simplifyIs((RexCall)
+                rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL, 
notSatisfiableNullable)));
+      }
       // NULL AND (x IS NULL)
-      return rexBuilder.makeCall(SqlStdOperatorTable.AND,
-          rexBuilder.makeNullLiteral(bestNotDisjunction.getType()),
-          simplifyIs(
-              (RexCall) rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL, 
bestNotDisjunction)));
+      return rexBuilder.makeCall(SqlStdOperatorTable.AND, terms);
     }
     // Add the NOT disjunctions back in.
     for (RexNode notDisjunction : notTerms) {

http://git-wip-us.apache.org/repos/asf/calcite/blob/c8e91ea1/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 25c99e5..7d0afee 100644
--- a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RexProgramTest.java
@@ -581,6 +581,26 @@ public class RexProgramTest extends RexProgramBuilderBase {
 
   }
 
+  @Test public void xAndNotX() {
+    checkSimplify2(
+        and(vBool(), not(vBool()),
+            vBool(1), not(vBool(1))),
+        "AND(null, IS NULL(?0.bool0), IS NULL(?0.bool1))",
+        "false");
+
+    checkSimplify2(
+        and(vBool(),
+            vBool(1), not(vBool(1))),
+        "AND(?0.bool0, null, IS NULL(?0.bool1))",
+        "false");
+
+    checkSimplify2(
+        and(vBool(), not(vBool()),
+            vBoolNotNull(1), not(vBoolNotNull(1))),
+        "false",
+        "false");
+  }
+
   /** Unit test for {@link 
org.apache.calcite.rex.RexUtil#isLosslessCast(RexNode)}. */
   @Test public void testLosslessCast() {
     final RelDataType tinyIntType = 
typeFactory.createSqlType(SqlTypeName.TINYINT);

Reply via email to