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;
+ }
}