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

xiong 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 b852db228c [CALCITE-6780] AbstractSqlTester fails to build query for 
expression TRIM(string)
b852db228c is described below

commit b852db228c3cb6194c7e00057178a2e628f9be96
Author: Zhe Hu <[email protected]>
AuthorDate: Thu Jan 16 21:51:15 2025 +0800

    [CALCITE-6780] AbstractSqlTester fails to build query for expression 
TRIM(string)
---
 .../apache/calcite/runtime/CalciteResource.java    |  4 +--
 .../org/apache/calcite/runtime/SqlFunctions.java   |  2 +-
 .../calcite/runtime/CalciteResource.properties     |  2 +-
 .../apache/calcite/sql/test/AbstractSqlTester.java |  5 ++++
 .../org/apache/calcite/test/SqlOperatorTest.java   | 34 ++++++++++++----------
 5 files changed, 28 insertions(+), 19 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java 
b/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
index 0f0dbaacc5..d927ab0b3f 100644
--- a/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
+++ b/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
@@ -948,8 +948,8 @@ ExInst<CalciteException> 
illegalArgumentForTableFunctionCall(String a0,
   @BaseMessage("Illegal arguments: The length of the keys array {0,number,#} 
is not equal to the length of the values array {1,number,#} in MAP_FROM_ARRAYS 
function")
   ExInst<CalciteException> illegalArgumentsInMapFromArraysFunc(int arg0, int 
arg1);
 
-  @BaseMessage("Trim error: trim character must be exactly 1 character")
-  ExInst<CalciteException> trimError();
+  @BaseMessage("Invalid argument ''{0}'': the length of the string describing 
the trimmed character must be 1")
+  ExInst<CalciteException> trimError(String seek);
 
   @BaseMessage("Invalid types for arithmetic: {0} {1} {2}")
   ExInst<CalciteException> invalidTypesForArithmetic(String clazzName0, String 
op,
diff --git a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java 
b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
index 1f8a125816..4b82aca272 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -1818,7 +1818,7 @@ public static String trim(boolean left, boolean right, 
String seek,
   public static String trim(boolean left, boolean right, String seek,
       String s, boolean strict) {
     if (strict && seek.length() != 1) {
-      throw RESOURCE.trimError().ex();
+      throw RESOURCE.trimError(seek).ex();
     }
     int j = s.length();
     if (right) {
diff --git 
a/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties 
b/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
index cda103f7df..462af08ac1 100644
--- 
a/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
+++ 
b/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
@@ -309,7 +309,7 @@ IllegalMapValuesWithNullKey=Illegal arguments for 
'MAP_VALUES' function: using a
 InvalidPrecisionForDecimalType=DECIMAL precision {0,number,#} must be between 
1 and {1,number,#}
 InvalidScaleForDecimalType=DECIMAL scale {0,number,#} must be between 
{1,number,#} and {2,number,#}
 IllegalArgumentsInMapFromArraysFunc=Illegal arguments: The length of the keys 
array {0,number,#} is not equal to the length of the values array {1,number,#} 
in MAP_FROM_ARRAYS function
-TrimError=Trim error: trim character must be exactly 1 character
+TrimError=Invalid argument ''{0}'': the length of the string describing the 
trimmed character must be 1
 InvalidTypesForArithmetic=Invalid types for arithmetic: {0} {1} {2}
 InvalidTypesForComparison=Invalid types for comparison: {0} {1} {2}
 CannotConvert=Cannot convert {0} to {1}
diff --git 
a/testkit/src/main/java/org/apache/calcite/sql/test/AbstractSqlTester.java 
b/testkit/src/main/java/org/apache/calcite/sql/test/AbstractSqlTester.java
index 8f7e2699cd..7f7191f9c1 100644
--- a/testkit/src/main/java/org/apache/calcite/sql/test/AbstractSqlTester.java
+++ b/testkit/src/main/java/org/apache/calcite/sql/test/AbstractSqlTester.java
@@ -385,6 +385,11 @@ protected String buildQuery2(SqlTestFactory factory, 
String expression) {
                 && isNull(call.operand(0))) {
               literalSet.add(call);
               return call;
+            } else if (operator == SqlStdOperatorTable.TRIM) {
+              // see 
https://issues.apache.org/jira/projects/CALCITE/issues/CALCITE-6780
+              // don't extract trimmed literal for TRIM function
+              call.operand(2).accept(this);
+              return call;
             } else if (ops.contains(operator)) {
               // "Argument to function 'LOCALTIME' must be a
               // literal"
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 bc68c4b47c..3512f6a9e4 100644
--- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
+++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
@@ -11706,31 +11706,35 @@ void assertSubFunReturns(boolean binary, String s, 
int start,
     // SQL:2003 6.29.11 Trimming a CHAR yields a VARCHAR
     f.checkString("trim('a' from 'aAa')", "A", "VARCHAR(3) NOT NULL");
     f.checkString("trim(both 'a' from 'aAa')", "A", "VARCHAR(3) NOT NULL");
+    f.checkString("trim(' aAa ')", "aAa", "VARCHAR(5) NOT NULL");
+    f.checkString("trim(both ' ' from ' aAa ')", "aAa", "VARCHAR(5) NOT NULL");
     f.checkString("trim(leading 'a' from 'aAa')", "Aa", "VARCHAR(3) NOT NULL");
     f.checkString("trim(trailing 'a' from 'aAa')", "aA", "VARCHAR(3) NOT 
NULL");
+    f.checkNull("trim(null)");
     f.checkNull("trim(cast(null as varchar(1)) from 'a')");
     f.checkNull("trim('a' from cast(null as varchar(1)))");
 
-    // SQL:2003 6.29.9: trim string must have length=1. Failure occurs
-    // at runtime.
-    //
-    // TODO: Change message to "Invalid argument\(s\) for
-    // 'TRIM' function".
-    // The message should come from a resource file, and should still
-    // have the SQL error code 22027.
+    // SQL:2003 6.29.9 and SQL:2016 6.30.11: trim string must have length=1.
+    // Failure occurs at runtime.
     f.checkFails("trim('xy' from 'abcde')",
-        "Trim error: trim character must be exactly 1 character",
+        "Invalid argument 'xy': the length of the string describing "
+            + "the trimmed character must be 1",
         true);
     f.checkFails("trim('' from 'abcde')",
-        "Trim error: trim character must be exactly 1 character",
+        "Invalid argument '': the length of the string describing "
+            + "the trimmed character must be 1",
         true);
 
-    final SqlOperatorFixture f1 = 
f.withConformance(SqlConformanceEnum.MYSQL_5);
-    f1.checkString("trim(leading 'eh' from 'hehe__hehe')", "__hehe",
-        "VARCHAR(10) NOT NULL");
-    f1.checkString("trim(trailing 'eh' from 'hehe__hehe')", "hehe__",
-        "VARCHAR(10) NOT NULL");
-    f1.checkString("trim('eh' from 'hehe__hehe')", "__", "VARCHAR(10) NOT 
NULL");
+    final Consumer<SqlOperatorFixture> consumer = f1 -> {
+      f1.checkString("trim(leading 'eh' from 'hehe__hehe')", "__hehe",
+          "VARCHAR(10) NOT NULL");
+      f1.checkString("trim(trailing 'eh' from 'hehe__hehe')", "hehe__",
+          "VARCHAR(10) NOT NULL");
+      f1.checkString("trim('eh' from 'hehe__hehe')", "__", "VARCHAR(10) NOT 
NULL");
+    };
+    final List<SqlConformanceEnum> conformanceEnums =
+        list(SqlConformanceEnum.MYSQL_5, SqlConformanceEnum.SQL_SERVER_2008);
+    f.forEachConformance(conformanceEnums, consumer);
   }
 
   @Test void testRtrimFunc() {

Reply via email to