Skip to content

Commit 720456c

Browse files
sbroedermihaibudiu
authored andcommitted
[CALCITE-7747] RexSimplify.simplifySearch does not simplify SEARCH(literal, Sarg) when pointCount >= 2
RexSimplify.simplifySearch only evaluated a SEARCH(subject, Sarg) call against its Sarg when sarg.isPoints() && sarg.pointCount <= 1, with no check for whether the subject itself is a constant. A single-point Sarg with any subject folded correctly, and a multi-point Sarg with a column-reference subject simplified correctly elsewhere, but a literal subject compared against a multi-point Sarg (for example, SEARCH(5, Sarg[1, 2])) fell through every branch unevaluated instead of folding to a boolean constant. This can occur whenever a rule substitutes a literal for a column reference in a SEARCH condition, such as when FilterSetOpTransposeRule pushes a filter through a branch of a Union that projects a constant. Fix simplifySearch so that when the search subject is itself a RexLiteral, the call is expanded via the existing RexUtil.expandSearch and the result is simplified recursively, regardless of point count. This matches the treatment already given to a single-point Sarg, but adds the recursive simplify() call needed to fold the expanded comparison tree down to a constant.
1 parent 1a0b436 commit 720456c

2 files changed

Lines changed: 27 additions & 2 deletions

File tree

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2608,9 +2608,13 @@ private RexNode simplifySearch(RexCall call, RexUnknownAs unknownAs) {
26082608
call.clone(call.type, ImmutableList.of(searchOperand, literal2)),
26092609
unknownAs);
26102610
}
2611+
} else if (searchOperand instanceof RexLiteral) {
2612+
// Subject is a constant; expand and re-simplify regardless of point count,
2613+
// since a constant subject can always be fully evaluated.
2614+
return simplify(RexUtil.expandSearch(rexBuilder, null, call), unknownAs);
26112615
} else if (sarg.isPoints() && sarg.pointCount <= 1) {
2612-
// Expand "SEARCH(x, Sarg([point])" to "x = point"
2613-
// and "SEARCH(x, Sarg([])" to "false"
2616+
// Expand "SEARCH(x, Sarg([point]))" to "x = point"
2617+
// and "SEARCH(x, Sarg([]))" to "false".
26142618
return RexUtil.expandSearch(rexBuilder, null, call);
26152619
}
26162620
}

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2262,6 +2262,27 @@ private void checkExponentialCnf(int n) {
22622262
checkSimplify(searchCall, "=(?0.int0, 100)");
22632263
}
22642264

2265+
/** Unit test for
2266+
* <a href="https://issues.apache.org/jira/browse/CALCITE-7747">[CALCITE-7747]
2267+
* RexSimplify.simplifySearch does not simplify SEARCH(literal, Sarg) when
2268+
* pointCount >= 2</a>. */
2269+
@Test void testSimplifySearchWithLiteralOperandAndMultiPointSargNotFolded() {
2270+
final RangeSet<BigDecimal> rangeSet =
2271+
ImmutableRangeSet.<BigDecimal>builder()
2272+
.add(Range.singleton(BigDecimal.valueOf(1)))
2273+
.add(Range.singleton(BigDecimal.valueOf(2)))
2274+
.build();
2275+
final Sarg<BigDecimal> sarg = Sarg.of(RexUnknownAs.UNKNOWN, rangeSet);
2276+
final RexLiteral searchLiteral =
2277+
rexBuilder.makeSearchArgumentLiteral(sarg, tInt());
2278+
final RexNode literalOperand = literal(5);
2279+
final RexNode searchCall =
2280+
rexBuilder.makeCall(SqlStdOperatorTable.SEARCH, literalOperand, searchLiteral);
2281+
// Expected (and true pre-Sarg, when this was OR(=(5,1), =(5,2))): folds to "false".
2282+
// Actual: simplifySearch returns the SEARCH call unchanged.
2283+
checkSimplify(searchCall, "false");
2284+
}
2285+
22652286
/** Unit test for
22662287
* <a href="https://issues.apache.org/jira/browse/CALCITE-5759">[CALCITE-5759]
22672288
* 'SEARCH(1, Sarg[IS NOT NULL])' should be simplified to 'TRUE'</a>. */

0 commit comments

Comments
 (0)