From 98f3048fb1407e2878162ffc80388d4f9dd094b2 Mon Sep 17 00:00:00 2001 From: Mihai Budiu Date: Thu, 3 Aug 2023 14:39:39 -0700 Subject: [PATCH] [CALCITE-5882] Compile-time evaluation of SPLIT function returns incorrect result Signed-off-by: Mihai Budiu --- .../calcite/sql/fun/SqlLibraryOperators.java | 4 +++- .../apache/calcite/test/RelOptRulesTest.java | 13 +++++++++++ .../apache/calcite/test/RelOptRulesTest.xml | 23 ++++++++++++++++--- .../apache/calcite/test/SqlOperatorTest.java | 18 +++++++-------- 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java index 7a5d11663154..dce8eb81dff7 100644 --- a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java +++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java @@ -333,7 +333,9 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding operatorBinding, Static.RESOURCE.delimiterIsRequired( operatorBinding.getOperator().getName(), type.toString())); } - return type; + + SqlTypeName typeName = SqlTypeUtil.isBinary(type) ? SqlTypeName.VARBINARY : SqlTypeName.VARCHAR; + return operatorBinding.getTypeFactory().createSqlType(typeName); } /** The "STRPOS(string, substring)" function. */ diff --git a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java index 762da942543f..a9b66f107630 100644 --- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java +++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java @@ -5130,6 +5130,19 @@ private HepProgram getTransitiveProgram() { .check(); } + /** Test case for + * [CALCITE-5882] Compile-time evaluation of SPLIT function returns incorrect result. */ + @Test public void testSplit() { + final String query = "select split('1|2|3', '|')"; + sql(query) + .withFactory( + t -> t.withOperatorTable(opTab -> + SqlLibraryOperatorTableFactory.INSTANCE.getOperatorTable( + SqlLibrary.BIG_QUERY))) // needed for SPLIT function + .withRule(CoreRules.PROJECT_REDUCE_EXPRESSIONS) + .check(); + } + /** Test case for right outer join, group by on key same as join * key, group by on (left)null generating side. */ @Test void testPushAggregateThroughOuterJoin12() { diff --git a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml index ea33f58f4eea..aa1330917124 100644 --- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml +++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml @@ -13899,6 +13899,23 @@ LogicalProject(B=[ST_BUFFER(ST_POINT(0.0:DECIMAL(2, 1), 0.0:DECIMAL(2, 1)), 1, 4 + + + + + + + + + + + @@ -13914,7 +13931,7 @@ LogicalProject(EXPR$0=[SPLIT('1|2|3', null:NULL)]) @@ -13931,7 +13948,7 @@ LogicalProject(EXPR$0=[SPLIT(null:NULL, '|')]) @@ -13948,7 +13965,7 @@ LogicalProject(EXPR$0=[SPLIT(null:NULL, null:NULL)]) diff --git a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java index 3fc1ec425a15..36e4068c423d 100644 --- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java +++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java @@ -7651,27 +7651,27 @@ private void testCurrentDateFunc(Pair pair) { false); final SqlOperatorFixture f = f0.withLibrary(SqlLibrary.BIG_QUERY); f.checkScalar("SPLIT('h,e,l,l,o')", "[h, e, l, l, o]", - "CHAR(9) NOT NULL ARRAY NOT NULL"); + "VARCHAR NOT NULL ARRAY NOT NULL"); f.checkScalar("SPLIT('h-e-l-l-o', '-')", "[h, e, l, l, o]", - "CHAR(9) NOT NULL ARRAY NOT NULL"); + "VARCHAR NOT NULL ARRAY NOT NULL"); f.checkScalar("SPLIT('hello', '-')", "[hello]", - "CHAR(5) NOT NULL ARRAY NOT NULL"); + "VARCHAR NOT NULL ARRAY NOT NULL"); f.checkScalar("SPLIT('')", "[]", - "CHAR(0) NOT NULL ARRAY NOT NULL"); + "VARCHAR NOT NULL ARRAY NOT NULL"); f.checkScalar("SPLIT('', '-')", "[]", - "CHAR(0) NOT NULL ARRAY NOT NULL"); + "VARCHAR NOT NULL ARRAY NOT NULL"); f.checkNull("SPLIT(null)"); f.checkNull("SPLIT('hello', null)"); // In ASCII, x'41' = 'A', x'42' = 'B', x'43' = 'C' f.checkScalar("SPLIT(x'414243', x'ff')", "[ABC]", - "BINARY(3) NOT NULL ARRAY NOT NULL"); + "VARBINARY NOT NULL ARRAY NOT NULL"); f.checkScalar("SPLIT(x'414243', x'41')", "[, BC]", - "BINARY(3) NOT NULL ARRAY NOT NULL"); + "VARBINARY NOT NULL ARRAY NOT NULL"); f.checkScalar("SPLIT(x'414243', x'42')", "[A, C]", - "BINARY(3) NOT NULL ARRAY NOT NULL"); + "VARBINARY NOT NULL ARRAY NOT NULL"); f.checkScalar("SPLIT(x'414243', x'43')", "[AB, ]", - "BINARY(3) NOT NULL ARRAY NOT NULL"); + "VARBINARY NOT NULL ARRAY NOT NULL"); f.checkFails("^SPLIT(x'aabbcc')^", "Call to function 'SPLIT' with argument of type 'BINARY\\(3\\)' " + "requires extra delimiter argument", false);