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>. */

Reply via email to