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

rubenada pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/main by this push:
     new f1d76ab815 [CALCITE-7635] Simplification result of conjunction of 
comparisons depends on terms order
f1d76ab815 is described below

commit f1d76ab815173373d7e99cd99348c680d6505927
Author: Ruben Quesada Lopez <[email protected]>
AuthorDate: Thu Jul 2 17:42:48 2026 +0100

    [CALCITE-7635] Simplification result of conjunction of comparisons depends 
on terms order
---
 .../java/org/apache/calcite/rex/RexSimplify.java   | 15 ++++++++---
 .../org/apache/calcite/rex/RexProgramTest.java     | 30 +++++++++++++++++++++-
 2 files changed, 41 insertions(+), 4 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 ae4b3501c9..58979c0f5c 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
@@ -800,7 +800,7 @@ private <C extends Comparable<C>> RexNode 
simplifyComparison(RexCall e,
     } else {
       e2 = rexBuilder.makeCall(e.getParserPosition(), e.op, operands);
     }
-    return simplifyUsingPredicates(e2, clazz);
+    return simplifyUsingPredicates(e2, clazz, unknownAs);
   }
 
 
@@ -1972,7 +1972,9 @@ private <C extends Comparable<C>> RexNode 
simplifyAnd2ForUnknownAsFalse(
         // or weaken terms that are partially implied.
         // E.g. given predicate "x >= 5" and term "x between 3 and 10"
         // we weaken to term to "x between 5 and 10".
-        final RexNode term2 = simplifyUsingPredicates(term, clazz);
+        // Note: we use RexUnknownAs.FALSE because the current method
+        // simplifies AND expressions "For Unknown As False".
+        final RexNode term2 = simplifyUsingPredicates(term, clazz, FALSE);
         if (term2 != term) {
           terms.set(i, term = term2);
         }
@@ -2097,7 +2099,7 @@ private <C extends Comparable<C>> RexNode 
simplifyAnd2ForUnknownAsFalse(
   }
 
   private <C extends Comparable<C>> RexNode simplifyUsingPredicates(RexNode e,
-      Class<C> clazz) {
+      Class<C> clazz, RexUnknownAs unknownAs) {
     if (predicates.pulledUpPredicates.isEmpty()) {
       return e;
     }
@@ -2126,6 +2128,13 @@ private <C extends Comparable<C>> RexNode 
simplifyUsingPredicates(RexNode e,
     } else if (rangeSet2.equals(RangeSets.rangeSetAll())) {
       // Range is always satisfied given these predicates; but nullability 
might
       // be problematic
+      if (unknownAs != UNKNOWN) {
+        // If unknownAs FALSE: row is already excluded for null input, so the 
IS_NOT_NULL
+        // guard is redundant, just return TRUE.
+        // If unknownAs TRUE: null rows pass regardless, and non-null rows 
also pass
+        // (range satisfied), the overall result is always TRUE.
+        return rexBuilder.makeLiteral(true);
+      }
       return simplify(
           rexBuilder.makeCall(RexUtil.getPos(e), 
SqlStdOperatorTable.IS_NOT_NULL, comparison.ref),
           RexUnknownAs.UNKNOWN);
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 91af635e52..e15af17d81 100644
--- a/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java
+++ b/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java
@@ -48,6 +48,7 @@
 import org.apache.calcite.util.TimestampWithTimeZoneString;
 import org.apache.calcite.util.Util;
 
+import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableRangeSet;
@@ -2284,6 +2285,33 @@ private void checkExponentialCnf(int n) {
     checkSimplify(rexNode, "false");
   }
 
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-7635";>[CALCITE-7635]
+   * Simplification result of conjunction of comparisons depends on terms 
order</a>. */
+  @Test void testSimplifyAndComparison() {
+    List<RexNode> args =
+        ImmutableList.of(lt(vInt(), literal(10)),
+        gt(vInt(), literal(0)),
+        lt(vInt(), literal(20)));
+    for (List<RexNode> params : Collections2.permutations(args)) {
+      checkSimplifyFilter(
+          and(params),
+          "SEARCH(?0.int0, Sarg[(0..10)])");
+    }
+  }
+
+  @Test void testSimplifyComparisonWithPredicates() {
+    RelOptPredicateList relOptPredicateList =
+        RelOptPredicateList.of(rexBuilder,
+            ImmutableList.of(lt(vInt(), literal(10)), gt(vInt(), literal(0))));
+    checkSimplifyWithPredicates(lt(vInt(), literal(20)), relOptPredicateList,
+        RexUnknownAs.UNKNOWN, "IS NOT NULL(?0.int0)");
+    checkSimplifyWithPredicates(lt(vInt(), literal(20)), relOptPredicateList,
+        RexUnknownAs.FALSE, "true");
+    checkSimplifyWithPredicates(lt(vInt(), literal(20)), relOptPredicateList,
+        RexUnknownAs.TRUE, "true");
+  }
+
   /** Test case for
    * <a 
href="https://issues.apache.org/jira/browse/CALCITE-7160";>[CALCITE-7160]
    * Simplify AND/OR with DISTINCT predicates to SEARCH</a>. */
@@ -4375,7 +4403,7 @@ private void checkSarg(String message, Sarg sarg,
     checkSimplifyFilter(ne(refNullable, literal(9)), relOptPredicateList,
         "false");
     checkSimplifyFilter(ne(refNullable, literal(5)), relOptPredicateList,
-        "IS NOT NULL($0)");
+        "true");
   }
 
   /** Tests

Reply via email to