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