You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2020/08/25 03:28:24 UTC

[calcite] branch master updated: [CALCITE-4190] OR simplification incorrectly loses term

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

jhyde 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 401b018  [CALCITE-4190] OR simplification incorrectly loses term
401b018 is described below

commit 401b01897b9a3b588d38acb6459411c5f7805776
Author: Julian Hyde <jh...@apache.org>
AuthorDate: Sun Aug 23 14:47:18 2020 -0700

    [CALCITE-4190] OR simplification incorrectly loses term
---
 .../java/org/apache/calcite/rex/RexSimplify.java   | 13 +++++--
 .../org/apache/calcite/rex/RexProgramTest.java     | 42 ++++++++++++++++++++++
 2 files changed, 53 insertions(+), 2 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 5e92098..b48fd7e 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
@@ -47,6 +47,7 @@ import com.google.common.collect.Sets;
 import com.google.common.collect.TreeRangeSet;
 
 import java.util.ArrayList;
+import java.util.BitSet;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
@@ -526,11 +527,19 @@ public class RexSimplify {
     // may be unknown), because if either of them were true we would have
     // stopped.
     RexSimplify simplify = this;
+
+    // 'doneTerms' prevents us from visiting a term in both first and second
+    // loops. If we did this, the second visit would have a predicate saying
+    // that 'term' is false. Effectively, we sort terms: visiting
+    // 'allowedAsPredicate' terms in the first loop, and
+    // non-'allowedAsPredicate' in the second. Each term is visited once.
+    final BitSet doneTerms = new BitSet();
     for (int i = 0; i < terms.size(); i++) {
       final RexNode t = terms.get(i);
       if (!simplify.allowedAsPredicateDuringOrSimplification(t)) {
         continue;
       }
+      doneTerms.set(i);
       final RexNode t2 = simplify.simplify(t, unknownAs);
       terms.set(i, t2);
       final RexNode inverse =
@@ -542,8 +551,8 @@ public class RexSimplify {
     }
     for (int i = 0; i < terms.size(); i++) {
       final RexNode t = terms.get(i);
-      if (allowedAsPredicateDuringOrSimplification(t)) {
-        continue;
+      if (doneTerms.get(i)) {
+        continue; // we visited this term in the first loop
       }
       terms.set(i, simplify.simplify(t, unknownAs));
     }
diff --git a/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java b/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java
index dfd145c..92b6851 100644
--- a/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java
+++ b/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java
@@ -1562,6 +1562,48 @@ class RexProgramTest extends RexProgramTestBase {
         "true");
   }
 
+  @Test void testSimplifyRange() {
+    final RexNode aRef = input(tInt(), 0);
+    // ((0 < a and a <= 10) or a >= 15) and a <> 6 and a <> 12
+    RexNode expr = and(
+        or(
+            and(lt(literal(0), aRef),
+                le(aRef, literal(10))),
+            ge(aRef, literal(15))),
+        ne(aRef, literal(6)),
+        ne(aRef, literal(12)));
+    checkSimplifyUnchanged(expr);
+  }
+
+  @Test void testSimplifyRange2() {
+    final RexNode aRef = input(tInt(true), 0);
+    // a is null or a >= 15
+    RexNode expr = or(isNull(aRef),
+        ge(aRef, literal(15)));
+    checkSimplifyUnchanged(expr);
+  }
+
+  /** Unit test for
+   * <a href="https://issues.apache.org/jira/browse/CALCITE-4190">[CALCITE-4190]
+   * OR simplification incorrectly loses term</a>. */
+  @Test void testSimplifyRange3() {
+    final RexNode aRef = input(tInt(true), 0);
+    // (0 < a and a <= 10) or a is null or (8 < a and a < 12) or a >= 15
+    RexNode expr = or(
+        and(lt(literal(0), aRef),
+            le(aRef, literal(10))),
+        isNull(aRef),
+        and(lt(literal(8), aRef),
+            lt(aRef, literal(12))),
+        ge(aRef, literal(15)));
+    // [CALCITE-4190] causes "or a >= 15" to disappear from the simplified form.
+    final String expected = "OR(IS NULL($0),"
+        + " AND(<(0, $0), <=($0, 10)),"
+        + " AND(<(8, $0), <($0, 12)),"
+        + " >=($0, 15))";
+    checkSimplify(expr, expected);
+  }
+
   @Test void testSimplifyItemRangeTerms() {
     RexNode item = item(input(tArray(tInt()), 3), literal(1));
     // paranoid validation doesn't support array types, disable it for a moment