This is an automated email from the ASF dual-hosted git repository.

zabetak 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 b0ecd066df [CALCITE-6608] RexBuilder#makeIn should create EQUALS 
instead of SEARCH for single point values
b0ecd066df is described below

commit b0ecd066df37bbc2398973165ddffe96135b4303
Author: Stamatis Zampetakis <[email protected]>
AuthorDate: Thu Oct 3 13:44:20 2024 +0200

    [CALCITE-6608] RexBuilder#makeIn should create EQUALS instead of SEARCH for 
single point values
    
    Close apache/calcite#3991
---
 .../java/org/apache/calcite/rex/RexBuilder.java    |  8 ++-
 .../org/apache/calcite/rex/RexBuilderTest.java     | 83 ++++++++++++++++++++++
 .../org/apache/calcite/rex/RexProgramTest.java     |  9 +++
 .../org/apache/calcite/test/RelBuilderTest.java    |  3 +-
 4 files changed, 100 insertions(+), 3 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/rex/RexBuilder.java 
b/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
index 9491aa6ec3..e6d7b1bd3b 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexBuilder.java
@@ -1749,11 +1749,17 @@ public class RexBuilder {
    *
    * <p>If all of the expressions are literals, creates a call {@link Sarg}
    * literal, "SEARCH(arg, SARG([point0..point0], [point1..point1], ...)";
-   * otherwise creates a disjunction, "arg = point0 OR arg = point1 OR ...". */
+   * otherwise creates a disjunction, "arg = point0 OR arg = point1 OR ...".
+   *
+   * <p>If there is only a single expression, creates a plain equality
+   * {@code arg = point0}. */
   public RexNode makeIn(RexNode arg, List<? extends RexNode> ranges) {
     if (areAssignable(arg, ranges)) {
       final Sarg sarg = toSarg(Comparable.class, ranges, RexUnknownAs.UNKNOWN);
       if (sarg != null) {
+        if (sarg.isPoints() && sarg.pointCount == 1) {
+          return makeCall(SqlStdOperatorTable.EQUALS, arg, ranges.get(0));
+        }
         final List<RelDataType> types = ranges.stream()
             .map(RexNode::getType)
             .collect(Collectors.toList());
diff --git a/core/src/test/java/org/apache/calcite/rex/RexBuilderTest.java 
b/core/src/test/java/org/apache/calcite/rex/RexBuilderTest.java
index 8329de9044..fb181b423b 100644
--- a/core/src/test/java/org/apache/calcite/rex/RexBuilderTest.java
+++ b/core/src/test/java/org/apache/calcite/rex/RexBuilderTest.java
@@ -957,6 +957,89 @@ class RexBuilderTest {
     assertThat(inCall.getKind(), is(SqlKind.SEARCH));
   }
 
+  /**
+   * Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6608";>[CALCITE-6608]
+   * RexBuilder#makeIn should create EQUALS instead of SEARCH for single point 
values</a>.
+   */
+  @Test void testMakeInReturnsEqualsForSingleLiteral() {
+    RelDataTypeFactory typeFactory = new 
SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
+    RexBuilder rexBuilder = new RexBuilder(typeFactory);
+    RelDataType intType = typeFactory.createSqlType(SqlTypeName.INTEGER);
+    RexNode column = rexBuilder.makeInputRef(intType, 0);
+    RexLiteral literal = rexBuilder.makeLiteral(100, intType);
+    RexNode inCall = rexBuilder.makeIn(column, ImmutableList.of(literal));
+    assertThat(inCall, hasToString("=($0, 100)"));
+  }
+
+  /**
+   * Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6608";>[CALCITE-6608]
+   * RexBuilder#makeIn should create EQUALS instead of SEARCH for single point 
values</a>.
+   */
+  @Test void testMakeInReturnsEqualsForDuplicateLiterals() {
+    RelDataTypeFactory typeFactory = new 
SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
+    RexBuilder rexBuilder = new RexBuilder(typeFactory);
+    RelDataType intType = typeFactory.createSqlType(SqlTypeName.INTEGER);
+    RexNode column = rexBuilder.makeInputRef(intType, 0);
+    RexLiteral literal = rexBuilder.makeLiteral(100, intType);
+    RexNode inCall = rexBuilder.makeIn(column, ImmutableList.of(literal, 
literal));
+    assertThat(inCall, hasToString("=($0, 100)"));
+  }
+
+  /**
+   * Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6608";>[CALCITE-6608]
+   * RexBuilder#makeIn should create EQUALS instead of SEARCH for single point 
values</a>.
+   */
+  @Test void testMakeInReturnsEqualsForSingleExpression() {
+    RelDataTypeFactory typeFactory = new 
SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
+    RexBuilder rexBuilder = new RexBuilder(typeFactory);
+    RelDataType intType = typeFactory.createSqlType(SqlTypeName.INTEGER);
+    RexNode column0 = rexBuilder.makeInputRef(intType, 0);
+    RexNode plusCall =
+        rexBuilder.makeCall(SqlStdOperatorTable.PLUS,
+            rexBuilder.makeInputRef(intType, 1),
+            rexBuilder.makeInputRef(intType, 2));
+    RexNode inCall = rexBuilder.makeIn(column0, ImmutableList.of(plusCall));
+    assertThat(inCall, hasToString("=($0, +($1, $2))"));
+  }
+
+  /**
+   * Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6608";>[CALCITE-6608]
+   * RexBuilder#makeIn should create EQUALS instead of SEARCH for single point 
values</a>.
+   */
+  @Test void testMakeInReturnsEqualsForDuplicateExpressions() {
+    RelDataTypeFactory typeFactory = new 
SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
+    RexBuilder rexBuilder = new RexBuilder(typeFactory);
+    RelDataType intType = typeFactory.createSqlType(SqlTypeName.INTEGER);
+    RexNode column0 = rexBuilder.makeInputRef(intType, 0);
+    RexNode plusCall =
+        rexBuilder.makeCall(SqlStdOperatorTable.PLUS,
+            rexBuilder.makeInputRef(intType, 1),
+            rexBuilder.makeInputRef(intType, 2));
+    RexNode inCall = rexBuilder.makeIn(column0, ImmutableList.of(plusCall, 
plusCall));
+    assertThat(inCall, hasToString("=($0, +($1, $2))"));
+  }
+
+  @Test void testMakeInReturnsOrForMultipleExpressions() {
+    RelDataTypeFactory typeFactory = new 
SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
+    RexBuilder rexBuilder = new RexBuilder(typeFactory);
+    RelDataType intType = typeFactory.createSqlType(SqlTypeName.INTEGER);
+    RexNode column0 = rexBuilder.makeInputRef(intType, 0);
+    RexNode plusCall =
+        rexBuilder.makeCall(SqlStdOperatorTable.PLUS,
+            rexBuilder.makeInputRef(intType, 1),
+            rexBuilder.makeInputRef(intType, 2));
+    RexNode minusCall =
+        rexBuilder.makeCall(SqlStdOperatorTable.MINUS,
+            rexBuilder.makeInputRef(intType, 1),
+            rexBuilder.makeInputRef(intType, 2));
+    RexNode inCall = rexBuilder.makeIn(column0, ImmutableList.of(plusCall, 
minusCall));
+    assertThat(inCall, hasToString("OR(=($0, +($1, $2)), =($0, -($1, $2)))"));
+  }
+
   /** Test case for
    * <a 
href="https://issues.apache.org/jira/browse/CALCITE-4555";>[CALCITE-4555]
    * Invalid zero literal value is used for
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 4e64c3c867..4b062a7655 100644
--- a/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java
+++ b/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java
@@ -1872,6 +1872,15 @@ class RexProgramTest extends RexProgramTestBase {
     checkSimplify(expr, simplified);
   }
 
+  @Test void testSimplifySearchWithSinglePointSargToEquals() {
+    Range<BigDecimal> r100 = Range.singleton(BigDecimal.valueOf(100));
+    RangeSet<BigDecimal> rangeSet = 
ImmutableRangeSet.<BigDecimal>builder().add(r100).build();
+    Sarg<BigDecimal> sarg = Sarg.of(RexUnknownAs.UNKNOWN, rangeSet);
+    RexLiteral searchLiteral = rexBuilder.makeSearchArgumentLiteral(sarg, 
tInt());
+    RexNode searchCall = rexBuilder.makeCall(SqlStdOperatorTable.SEARCH, 
vInt(), searchLiteral);
+    checkSimplify(searchCall, "=(?0.int0, 100)");
+  }
+
   /** 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>. */
diff --git a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java 
b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
index 28dfba9656..651518a823 100644
--- a/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
@@ -4611,8 +4611,7 @@ public class RelBuilderTest {
         + "LogicalFilter(condition=[OR(SEARCH($7, Sarg[10, 11, (15..+∞)]), 
=($2, 'CLERK'))])\n"
         + "  LogicalTableScan(table=[[scott, EMP]])\n";
     final String expectedWithoutSimplify = ""
-        + "LogicalFilter(condition=[OR(>($7, 15), SEARCH($2, 
Sarg['CLERK']:CHAR(5)), SEARCH($7, "
-        + "Sarg[10, 11, 20]))])\n"
+        + "LogicalFilter(condition=[OR(>($7, 15), =($2, 'CLERK'), SEARCH($7, 
Sarg[10, 11, 20]))])\n"
         + "  LogicalTableScan(table=[[scott, EMP]])\n";
     assertThat(f.apply(createBuilder()), hasTree(expected));
     assertThat(f.apply(createBuilder(c -> c.withSimplify(false))),

Reply via email to