[CALCITE-5288] '(a > 5 and a < 15) or (a > 10 and a < 20)' should be simplified to 'SEARCH(a, Sarg[(5..20)])'
This closes #2912
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 006ce25..0bc462d 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
@@ -2902,14 +2902,16 @@
boolean needToFix() {
// Fix and converts to SEARCH if:
// 1. A Sarg has complexity greater than 1;
- // 2. The terms are reduced as simpler Sarg points;
- // 3. The terms are reduced as simpler Sarg comparison.
+ // 2. A Sarg was merged with another Sarg or range;
+ // 3. The terms are reduced as simpler Sarg points;
+ // 4. The terms are reduced as simpler Sarg comparison.
// Ignore 'negate' just to be compatible with previous versions of this
// method. "build().complexity()" would be a better estimate, if we could
// switch to it breaking lots of plans.
final Collection<RexSargBuilder> builders = map.values();
- return builders.stream().anyMatch(b -> b.build(false).complexity() > 1)
+ return builders.stream()
+ .anyMatch(b -> b.build(false).complexity() > 1 || b.mergedSarg)
|| newTermsCount == 1
&& builders.stream().allMatch(b -> simpleSarg(b.build()));
}
@@ -2972,6 +2974,8 @@
final boolean negate;
final List<RelDataType> types = new ArrayList<>();
final RangeSet<Comparable> rangeSet = TreeRangeSet.create();
+ boolean hasSarg;
+ boolean mergedSarg;
RexUnknownAs nullAs = FALSE;
RexSargBuilder(RexNode ref, RexBuilder rexBuilder, boolean negate) {
@@ -3033,6 +3037,7 @@
void addRange(Range<Comparable> range, RelDataType type) {
types.add(type);
rangeSet.add(range);
+ mergedSarg |= hasSarg;
nullAs = nullAs.or(UNKNOWN);
}
@@ -3049,6 +3054,8 @@
}
types.add(type);
rangeSet.addAll(r);
+ mergedSarg |= !rangeSet.isEmpty();
+ hasSarg = true;
switch (nullAs) {
case TRUE:
this.nullAs = this.nullAs.or(TRUE);
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 bd548eb..637f83a 100644
--- a/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java
+++ b/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java
@@ -1243,6 +1243,20 @@
RelOptPredicateList.of(rexBuilder,
ImmutableList.of(le(aRef, literal(5)), le(bRef, literal(5)))),
"false");
+
+ // condition "(a >= 1 and a <= 3) or (a >= 2 and a <= 4)"
+ // yelds "a >= 1 and a <= 4"
+ checkSimplifyFilter(
+ or(and(ge(aRef, literal(1)), le(aRef, literal(3))),
+ and(ge(aRef, literal(2)), le(aRef, literal(4)))),
+ "SEARCH(?0.a, Sarg[[1..4]])");
+
+ // condition "(a >= 1 and a <= 3) or (a >= 0 and a <= 2)"
+ // yelds "a >= 0 and a <= 3"
+ checkSimplifyFilter(
+ or(and(ge(aRef, literal(1)), le(aRef, literal(3))),
+ and(ge(aRef, literal(0)), le(aRef, literal(2)))),
+ "SEARCH(?0.a, Sarg[[0..3]])");
}
/** Test case for