[ 
https://issues.apache.org/jira/browse/CALCITE-2082?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17195656#comment-17195656
 ] 

Julian Hyde commented on CALCITE-2082:
--------------------------------------

bq. was there a PR for this patch?

Yes, it was part of https://github.com/apache/calcite/pull/2111.

bq. Also, please notice that this is a breaking change,

Yes.

bq. Why we must now have a {{SqlOperandMetadata}}

This 
[change|https://github.com/apache/calcite/commit/39cf82b8bf94b9240fe4592706d8eeb2952712f0#diff-9fe616c8f4434e9f6692853abf0bb778L607]
 illustrates:
{noformat}
@@ -604,15 +604,20 @@ public static boolean matchRoutinesByParameterCount(
     return (Iterator) Iterators.filter(
         Iterators.filter(routines, SqlFunction.class),
         function -> {
-          List<RelDataType> paramTypes = function.getParamTypes();
-          if (paramTypes == null) {
+          if (Objects.requireNonNull(function).getOperandTypeChecker() == null
+              || !function.getOperandTypeChecker().isFixedParameters()) {
             // no parameter information for builtins; keep for now,
             // the type coerce will not work here.
             return true;
           }
+          final SqlOperandMetadata operandMetadata =
+              (SqlOperandMetadata) function.getOperandTypeChecker();
+          final List<RelDataType> paramTypes =
+              operandMetadata.paramTypes(typeFactory);
           final List<RelDataType> permutedArgTypes;
           if (argNames != null) {
-            permutedArgTypes = permuteArgTypes(function, argNames, argTypes);
+            final List<String> paramNames = operandMetadata.paramNames();
+            permutedArgTypes = permuteArgTypes(paramNames, argNames, argTypes);
             if (permutedArgTypes == null) {
               return false;
             } {noformat}
Previously, we called {{function.getParamTypes()}}.  How could the function 
possibly know its own types if we do not support a type factory, and the 
function was created before the current statement, and in fact before any type 
factories were created?

Breaking the API was unavoidable - you must pass in a {{RelDataTypeFactory}} in 
order to get a type, and the previous API had no way to pass a factory. Note 
that you can get the number and names of parameters without passing a factory.

The new API makes a stronger distinction between UDFs and built-in functions. 
UDFs' parameters are fixed in number and type, and have names. Built-ins may be 
overloaded - that is, the parameters may vary in number and type - but the 
parameters do not have names.

bq. My application had several UDFs with {{SqlOperandTypeChecker}}, and they 
already complied with "Do not store types (RelDataType) or type factories 
(RelDataTypeFactory) in SqlOperator instances"

How did you do this in your application? (Except if your UDFs had no 
parameters.)

> Do not store types or type factories inside operators
> -----------------------------------------------------
>
>                 Key: CALCITE-2082
>                 URL: https://issues.apache.org/jira/browse/CALCITE-2082
>             Project: Calcite
>          Issue Type: Bug
>            Reporter: Julian Hyde
>            Assignee: Julian Hyde
>            Priority: Major
>             Fix For: 1.26.0
>
>
> Do not store types (RelDataType) or type factories (RelDataTypeFactory) in 
> SqlOperator instances.
> *Rationale*: a {{SqlOperator}} has a lifetime that spans many statements; but 
> a type factory is only for one statement, and each type belongs to that 
> factory. We want to share {{SqlOperator}} instances across connections, 
> therefore we need to create them before there is a type factory.
> Typically, a method that returns a type should have a type factory argument 
> with which to create it.
> The current situation is technical debt. There are a couple of pieces of code 
> tagged with this case number; see the fix to CALCITE-2072.
> In particular:
> * Remove method {{List<RelDataType> SqlOperator.getParamTypes()}};
> * Remove {{RelDataTypeFactory}} argument from {{SqlUserDefinedAggFunction}} 
> constructor, and remove its {{typeFactory}} field.
> We will add {{interface SqlOperandMetadata extends SqlOperatorTypeChecker}}, 
> which has new methods {{List<RelDataType>> paramTypes(RelDataTypeFactory)}} 
> and {{List<String> paramNames()}}.
> This interface will typically be implemented only for user-defined functions. 
> Unlike SQL built-in functions, UDFs have a fixed set of parameters (although 
> some of them may be optional), and the parameters have names.
> In {{interface SqlOperandTypeChecker}}, add method {{boolean 
> isFixedParameters()}}. Will typically return true for UDFs, false for 
> built-in functions. Returns false for table window functions (e.g. {{HOP}}), 
> even though these have named parameters (which tends to make them look a bit 
> like UDFs).



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to