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

stigahuang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git


The following commit(s) were added to refs/heads/master by this push:
     new 9b93ab8b5 IMPALA-13521: Calcite planner: Handle function problem with 
char params
9b93ab8b5 is described below

commit 9b93ab8b55901fabd0db3dfca5fb5209122c0e34
Author: Steve Carlin <[email protected]>
AuthorDate: Wed Nov 6 10:02:44 2024 -0800

    IMPALA-13521: Calcite planner: Handle function problem with char params
    
    There is an issue in Calcite that it treats literals as a CHAR type
    whereas Impala treats a literal as a STRING type. This is fixed at
    coercion time.
    
    However, at validation time, it is possible that a function is passed
    an operand which originated as a literal type, but the information is
    lost by the time it hits the function.  An example of this is in
    exprs.test:
    
    select from_unixtime(tmp.val, tmp.fmt) from (values
    (0 as val, 'yyyy-MM-dd HH:mm:ss' as fmt),
    (34304461, 'HH:mm:ss dd/yyyy/MM'),
    (68439783, 'yyyy||MMM||dd||HHmmss')) as tmp
    
    The validator sees the literal in the values clause and creates a char
    type. When we validate the from_unixtime, Calcite propagates the char
    type into the function. This was failing since the from_unixtime
    function prototype only takes string params.
    
    The fix for this is to do 2 passes.  Once with the char type and once
    with a string type if it detects any char types. If the type was
    actually a char type, it would fail later in the code after coercion
    is done (which would not change the char type to a string type).
    
    Change-Id: Icc07c6cacb81d02ba0659f2f3d8ececcc63f715e
    Reviewed-on: http://gerrit.cloudera.org:8080/22095
    Reviewed-by: Michael Smith <[email protected]>
    Tested-by: Impala Public Jenkins <[email protected]>
---
 .../calcite/operators/CommonOperatorFunctions.java | 28 +++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git 
a/java/calcite-planner/src/main/java/org/apache/impala/calcite/operators/CommonOperatorFunctions.java
 
b/java/calcite-planner/src/main/java/org/apache/impala/calcite/operators/CommonOperatorFunctions.java
index 0130c1c24..2c30b0007 100644
--- 
a/java/calcite-planner/src/main/java/org/apache/impala/calcite/operators/CommonOperatorFunctions.java
+++ 
b/java/calcite-planner/src/main/java/org/apache/impala/calcite/operators/CommonOperatorFunctions.java
@@ -63,7 +63,7 @@ public class CommonOperatorFunctions {
     RelDataTypeFactory factory = rexBuilder.getTypeFactory();
 
     // Resolve Impala function through Impala method.
-    Function fn = FunctionResolver.getSupertypeFunction(name, operandTypes);
+    Function fn = getSupertypeFunction(name, operandTypes);
 
     if (fn == null) {
       throw new IllegalArgumentException("Cannot infer return type for "
@@ -128,4 +128,30 @@ public class CommonOperatorFunctions {
   public static boolean isNullable(List<RelDataType> operandTypes) {
     return operandTypes.stream().anyMatch(rdt -> rdt.isNullable());
   }
+
+  private static Function getSupertypeFunction(String name,
+      List<RelDataType> operandTypes) {
+    Function fn = FunctionResolver.getSupertypeFunction(name, operandTypes);
+    if (fn != null) {
+      return fn;
+    }
+
+    // Hack. Calcite treats all string literal types as char. In this phase, a 
lower
+    // SqlNode may have a literal, but it is showing up as a char when we 
verify
+    // the function existence. If that function doesn't exist, we change the 
CHAR
+    // type to a STRING type and look for that prototype. If, for some reason, 
the
+    // real parameter was a CHAR and not a STRING, this will fail later when 
retrieving
+    // the exact function at physical conversion time.
+    boolean hasChar = false;
+    List<RelDataType> adjustedTypes = new ArrayList<>();
+    for (RelDataType opType : operandTypes) {
+      if (opType.getSqlTypeName().equals(SqlTypeName.CHAR)) {
+        adjustedTypes.add(ImpalaTypeConverter.getRelDataType(Type.STRING));
+        hasChar = true;
+      } else {
+        adjustedTypes.add(opType);
+      }
+    }
+    return hasChar ? FunctionResolver.getSupertypeFunction(name, 
adjustedTypes) : null;
+  }
 }

Reply via email to