[
https://issues.apache.org/jira/browse/CALCITE-2082?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17195955#comment-17195955
]
Ruben Q L commented on CALCITE-2082:
------------------------------------
Thanks for the explanation [~julianhyde]. An example of my current use case
(which maybe is not the most orthodox way of using UDFs) could be:
{code:java}
// returns the total number of digits of a certain numeric value, e.g.:
// SELECT o.o_orderkey FROM orders o WHERE TOTAL_DIGITS(o.o_totalprice) > 10
public static final SqlOperator TOTAL_DIGITS = new SqlUserDefinedFunction(
new SqlIdentifier("TOTAL_DIGITS", SqlParserPos.ZERO), // SqlIdentifier
ReturnTypes.INTEGER, // SqlReturnTypeInference
InferTypes.FIRST_KNOWN, // SqlOperandTypeInference
OperandTypes.NUMERIC, // SqlOperandTypeChecker
null, // List<RelDataType> paramTypes
MyTotalDigitsImplementableFunction // Function
);
{code}
As you can see, I never had the need to use the {{List<RelDataType>
paramTypes}}, maybe mine is very particular scenario.
In any case, I've just discovered that, with the changes on the current ticket,
in order to avoid regressions and keep my UDFs working as before, I just need
to wrap a {{SqlOperandTypeChecker}} into a {{SqlOperandMetadata}}
implementation, with {{isFixedParameters()}} overridden to {{return false;}}
(which seems counter-intuitive for UDFs, but works fine for me). By doing this,
{{SqlOperandMetadata}}'s {{paramTypes}} and {{paramNames}} are not relevant,
and everything relies on the {{SqlOperandTypeChecker}}, as before. I understand
that this is a non-standard usage of UDFs, but it seems to suit my needs.
Thanks for the clarifications.
> 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)