This is an automated email from the ASF dual-hosted git repository.
mihaibudiu 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 720456ce32 [CALCITE-7747] RexSimplify.simplifySearch does not simplify
SEARCH(literal, Sarg) when pointCount >= 2
720456ce32 is described below
commit 720456ce322c81caeeb6595071aebc5a885dc6ce
Author: Sean Broeder <[email protected]>
AuthorDate: Thu Aug 27 17:10:19 2026 -0700
[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.
---
.../java/org/apache/calcite/rex/RexSimplify.java | 8 ++++++--
.../java/org/apache/calcite/rex/RexProgramTest.java | 21 +++++++++++++++++++++
2 files changed, 27 insertions(+), 2 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 cf18e7c6f5..81bec78f3e 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java
@@ -2608,9 +2608,13 @@ private RexNode simplifySearch(RexCall call,
RexUnknownAs unknownAs) {
call.clone(call.type, ImmutableList.of(searchOperand, literal2)),
unknownAs);
}
+ } else if (searchOperand instanceof RexLiteral) {
+ // Subject is a constant; expand and re-simplify regardless of point
count,
+ // since a constant subject can always be fully evaluated.
+ return simplify(RexUtil.expandSearch(rexBuilder, null, call),
unknownAs);
} else if (sarg.isPoints() && sarg.pointCount <= 1) {
- // Expand "SEARCH(x, Sarg([point])" to "x = point"
- // and "SEARCH(x, Sarg([])" to "false"
+ // Expand "SEARCH(x, Sarg([point]))" to "x = point"
+ // and "SEARCH(x, Sarg([]))" to "false".
return RexUtil.expandSearch(rexBuilder, null, call);
}
}
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 2a2efb7521..1d7925bb69 100644
--- a/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java
+++ b/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java
@@ -2262,6 +2262,27 @@ private void checkExponentialCnf(int n) {
checkSimplify(searchCall, "=(?0.int0, 100)");
}
+ /** Unit test for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-7747">[CALCITE-7747]
+ * RexSimplify.simplifySearch does not simplify SEARCH(literal, Sarg) when
+ * pointCount >= 2</a>. */
+ @Test void testSimplifySearchWithLiteralOperandAndMultiPointSargNotFolded() {
+ final RangeSet<BigDecimal> rangeSet =
+ ImmutableRangeSet.<BigDecimal>builder()
+ .add(Range.singleton(BigDecimal.valueOf(1)))
+ .add(Range.singleton(BigDecimal.valueOf(2)))
+ .build();
+ final Sarg<BigDecimal> sarg = Sarg.of(RexUnknownAs.UNKNOWN, rangeSet);
+ final RexLiteral searchLiteral =
+ rexBuilder.makeSearchArgumentLiteral(sarg, tInt());
+ final RexNode literalOperand = literal(5);
+ final RexNode searchCall =
+ rexBuilder.makeCall(SqlStdOperatorTable.SEARCH, literalOperand,
searchLiteral);
+ // Expected (and true pre-Sarg, when this was OR(=(5,1), =(5,2))): folds
to "false".
+ // Actual: simplifySearch returns the SEARCH call unchanged.
+ checkSimplify(searchCall, "false");
+ }
+
/** Unit test for
* <a
href="https://issues.apache.org/jira/browse/CALCITE-5759">[CALCITE-5759]
* 'SEARCH(1, Sarg[IS NOT NULL])' should be simplified to 'TRUE'</a>. */