Skip to content

Commit f1d76ab

Browse files
committed
[CALCITE-7635] Simplification result of conjunction of comparisons depends on terms order
1 parent b3b8d64 commit f1d76ab

2 files changed

Lines changed: 41 additions & 4 deletions

File tree

core/src/main/java/org/apache/calcite/rex/RexSimplify.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,7 @@ private <C extends Comparable<C>> RexNode simplifyComparison(RexCall e,
800800
} else {
801801
e2 = rexBuilder.makeCall(e.getParserPosition(), e.op, operands);
802802
}
803-
return simplifyUsingPredicates(e2, clazz);
803+
return simplifyUsingPredicates(e2, clazz, unknownAs);
804804
}
805805

806806

@@ -1972,7 +1972,9 @@ private <C extends Comparable<C>> RexNode simplifyAnd2ForUnknownAsFalse(
19721972
// or weaken terms that are partially implied.
19731973
// E.g. given predicate "x >= 5" and term "x between 3 and 10"
19741974
// we weaken to term to "x between 5 and 10".
1975-
final RexNode term2 = simplifyUsingPredicates(term, clazz);
1975+
// Note: we use RexUnknownAs.FALSE because the current method
1976+
// simplifies AND expressions "For Unknown As False".
1977+
final RexNode term2 = simplifyUsingPredicates(term, clazz, FALSE);
19761978
if (term2 != term) {
19771979
terms.set(i, term = term2);
19781980
}
@@ -2097,7 +2099,7 @@ private <C extends Comparable<C>> RexNode simplifyAnd2ForUnknownAsFalse(
20972099
}
20982100

20992101
private <C extends Comparable<C>> RexNode simplifyUsingPredicates(RexNode e,
2100-
Class<C> clazz) {
2102+
Class<C> clazz, RexUnknownAs unknownAs) {
21012103
if (predicates.pulledUpPredicates.isEmpty()) {
21022104
return e;
21032105
}
@@ -2126,6 +2128,13 @@ private <C extends Comparable<C>> RexNode simplifyUsingPredicates(RexNode e,
21262128
} else if (rangeSet2.equals(RangeSets.rangeSetAll())) {
21272129
// Range is always satisfied given these predicates; but nullability might
21282130
// be problematic
2131+
if (unknownAs != UNKNOWN) {
2132+
// If unknownAs FALSE: row is already excluded for null input, so the IS_NOT_NULL
2133+
// guard is redundant, just return TRUE.
2134+
// If unknownAs TRUE: null rows pass regardless, and non-null rows also pass
2135+
// (range satisfied), the overall result is always TRUE.
2136+
return rexBuilder.makeLiteral(true);
2137+
}
21292138
return simplify(
21302139
rexBuilder.makeCall(RexUtil.getPos(e), SqlStdOperatorTable.IS_NOT_NULL, comparison.ref),
21312140
RexUnknownAs.UNKNOWN);

core/src/test/java/org/apache/calcite/rex/RexProgramTest.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import org.apache.calcite.util.TimestampWithTimeZoneString;
4949
import org.apache.calcite.util.Util;
5050

51+
import com.google.common.collect.Collections2;
5152
import com.google.common.collect.ImmutableList;
5253
import com.google.common.collect.ImmutableMap;
5354
import com.google.common.collect.ImmutableRangeSet;
@@ -2284,6 +2285,33 @@ private void checkExponentialCnf(int n) {
22842285
checkSimplify(rexNode, "false");
22852286
}
22862287

2288+
/** Test case for
2289+
* <a href="https://issues.apache.org/jira/browse/CALCITE-7635">[CALCITE-7635]
2290+
* Simplification result of conjunction of comparisons depends on terms order</a>. */
2291+
@Test void testSimplifyAndComparison() {
2292+
List<RexNode> args =
2293+
ImmutableList.of(lt(vInt(), literal(10)),
2294+
gt(vInt(), literal(0)),
2295+
lt(vInt(), literal(20)));
2296+
for (List<RexNode> params : Collections2.permutations(args)) {
2297+
checkSimplifyFilter(
2298+
and(params),
2299+
"SEARCH(?0.int0, Sarg[(0..10)])");
2300+
}
2301+
}
2302+
2303+
@Test void testSimplifyComparisonWithPredicates() {
2304+
RelOptPredicateList relOptPredicateList =
2305+
RelOptPredicateList.of(rexBuilder,
2306+
ImmutableList.of(lt(vInt(), literal(10)), gt(vInt(), literal(0))));
2307+
checkSimplifyWithPredicates(lt(vInt(), literal(20)), relOptPredicateList,
2308+
RexUnknownAs.UNKNOWN, "IS NOT NULL(?0.int0)");
2309+
checkSimplifyWithPredicates(lt(vInt(), literal(20)), relOptPredicateList,
2310+
RexUnknownAs.FALSE, "true");
2311+
checkSimplifyWithPredicates(lt(vInt(), literal(20)), relOptPredicateList,
2312+
RexUnknownAs.TRUE, "true");
2313+
}
2314+
22872315
/** Test case for
22882316
* <a href="https://issues.apache.org/jira/browse/CALCITE-7160">[CALCITE-7160]
22892317
* Simplify AND/OR with DISTINCT predicates to SEARCH</a>. */
@@ -4375,7 +4403,7 @@ private void checkSarg(String message, Sarg sarg,
43754403
checkSimplifyFilter(ne(refNullable, literal(9)), relOptPredicateList,
43764404
"false");
43774405
checkSimplifyFilter(ne(refNullable, literal(5)), relOptPredicateList,
4378-
"IS NOT NULL($0)");
4406+
"true");
43794407
}
43804408

43814409
/** Tests

0 commit comments

Comments
 (0)