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))),