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

Guoliang Sun edited comment on CALCITE-5887 at 8/3/23 6:42 AM:
---------------------------------------------------------------

The problem was introduced by this issue:

https://issues.apache.org/jira/browse/CALCITE-2571


was (Author: JIRAUSER298470):
The problem was introduced by this issue

> Trim function can’t work well with SqlDelegatingConformance
> -----------------------------------------------------------
>
>                 Key: CALCITE-5887
>                 URL: https://issues.apache.org/jira/browse/CALCITE-5887
>             Project: Calcite
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 1.35.0
>            Reporter: Guoliang Sun
>            Priority: Major
>
> In Calcite, there are test cases that override this function, e.g.: 
> SqlFunctionsTest#testTrim.
> But the use case ignores the fact that the function is optimized in SQL with 
> rules, which I'll illustrate with an example below.
>  
> Take the following SQL as an example of the expected result: *calcite*
> {code:java}
> select trim(both 'io' from 'iocalciteio'){code}
>  
>  
> I wanted to use Calcite's SQLConformance by way of a custom extension, so I 
> inherited SqlDelegatingConformance, overrode the allowExtendedTrim method, 
> and set it when SqlParser was initialized.
>  
> The SQL is then optimized by a series of parsing transformations, and at this 
> point it comes to {*}CoreRules.PROJECT_REDUCE_EXPRESSIONS{*}, which calls 
> RexExecutorImpl to compute the RexNode expression, reducing the constants by 
> generating code for optimization purposes. In the 
> *{color:#172b4d}RexExecutorImpl#compile{color}* method, you can see that the 
> SqlConformance is written to Default, which will cause the custom 
> *SqlDelegatingConformance* set earlier to not take effect, see the code below.
> {code:java}
> private static String compile(RexBuilder rexBuilder, List<RexNode> constExps,
>     RexToLixTranslator.InputGetter getter, RelDataType rowType) {
>   final RexProgramBuilder programBuilder =
>       new RexProgramBuilder(rowType, rexBuilder);
>   for (RexNode node : constExps) {
>     programBuilder.addProject(
>         node, "c" + programBuilder.getProjectList().size());
>   }
>   final RelDataTypeFactory typeFactory = rexBuilder.getTypeFactory();
>   final JavaTypeFactory javaTypeFactory = typeFactory instanceof 
> JavaTypeFactory
>       ? (JavaTypeFactory) typeFactory
>       : new JavaTypeFactoryImpl(typeFactory.getTypeSystem());
>   final BlockBuilder blockBuilder = new BlockBuilder();
>   final ParameterExpression root0_ =
>       Expressions.parameter(Object.class, "root0");
>   final ParameterExpression root_ = DataContext.ROOT;
>   blockBuilder.add(
>       Expressions.declare(
>           Modifier.FINAL, root_,
>           Expressions.convert_(root0_, DataContext.class)));
>   final SqlConformance conformance = SqlConformanceEnum.DEFAULT;
>   final RexProgram program = programBuilder.getProgram();
>   final List<Expression> expressions =
>       RexToLixTranslator.translateProjects(program, javaTypeFactory,
>           conformance, blockBuilder, null, null, root_, getter, null);
>   blockBuilder.add(
>       Expressions.return_(null,
>           Expressions.newArrayInit(Object[].class, expressions)));
>   final MethodDeclaration methodDecl =
>       Expressions.methodDecl(Modifier.PUBLIC, Object[].class,
>           BuiltInMethod.FUNCTION1_APPLY.method.getName(),
>           ImmutableList.of(root0_), blockBuilder.toBlock());
>   String code = Expressions.toString(methodDecl);
>   if (CalciteSystemProperty.DEBUG.value()) {
>     Util.debugCode(System.out, code);
>   }
>   return code;
> } {code}
>  
>  
> When you get {*}SqlConformanceEnum.DEFAULT{*}, you get a MethodCallExpression 
> in the *TrimImplementor#implementSafe* method that doesn't allow Trim to do 
> multiple character operations on SQL, so Calcite throws an exception in the 
> SqlFunctions#trim method.
> *{color:#de350b}Trim error: trim character must be exactly 1 character{color}*
>  
> Coincidentally, this exception is caught by the try catch in the 
> {color:#172b4d}*RexExecutable#reduce*{color} method, which returns the 
> initial unoptimized expression, with no exception output, and after the final 
> execution is complete, you can only see that the result is not as expected.
> By the way, I don't think it's reasonable to output the exception message, if 
> the optimization fails, at least it should be logged for troubleshooting.
>  
> Regarding solution ideas, I can think of two ways at the moment and would 
> like to know what the community thinks, or if the community thinks this is a 
> problem?
>  * Change SQLConformance to global
>  * Change CalciteConnectionConfigImpl to global
> This would allow you to get the SQLConformance information that has been set 
> in the configuration elsewhere, there are many places in Calcite where 
> DEFAULT may be written because you can't get the configuration information.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to