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

zhong.zhu commented on KYLIN-5747:
----------------------------------

h1.Root Cause
When the plus sign is used in a row, and the arguments are all constants, 
calcite will do constant folding, and when calculating the value, it will 
convert the expression into java code, and each plus sign will determine 
whether it needs to be converted into a custom plus function or whether it 
should be used directly with the java additions.

into a custom plus function has three conditions: 1. plus left is not a basic 
type; 2. plus right is a bigDecimal type; 3. (more complex), any one of them 
can be satisfied

For '1' + 3 + '3', '1' + 3 is of type double, and '3' is of type string, so the 
second plus sign does not satisfy all three conditions, which results in the 
expression translated into java code as plus('1' + 3) + '3'.


h1.Dev Design
1. In calcite to generate java code, to determine the + sign needs to be 
converted to plus() it or directly use the addition in java, add a condition, 
when the parameters on both sides of the plus sign for the string type or 
numerical type, directly use plus()
i.e. fix the '1' + 3 + '3' in the previous sql, the java code is plus('1' + 3) 
+ '3'.
After the fix it is plus(plus('1' + 3), '3')
2. Change the return value of the custom plus function in calcite from Double 
to bigDecimal.
The reason:
- When calcite does constant folding to generate java code, it does isNullable 
derivation, and when the nullable of a call is false, it does an automatic 
unboxing.
- The expression 'a' + 3 is considered by calcite to be non-nullable when it 
does the nullable derivation because the two arguments are constants and 
neither of them is null, so the whole thing is considered non-null!
- In spark, 'a' + 3 results in null, so in our implementation of the plus 
method, 'a' + 3 also results in null
- In summary, when plus(string, number) returns Double, the java code for 'a' + 
3 + '3' is actually plus(plus('a' + 3).doubleValue(), '3'), which then throws 
an NPE when the calculation is performed.

The logic of isNullable involves a wider scope, and it is risky to modify it 
directly, so here we change the return value of plus to BigDecimal, to avoid 
unboxing.

> Calcite constant folding, adding strings to numbers, results not as expected 
> when multiple plus signs are used together
> -----------------------------------------------------------------------------------------------------------------------
>
>                 Key: KYLIN-5747
>                 URL: https://issues.apache.org/jira/browse/KYLIN-5747
>             Project: Kylin
>          Issue Type: Bug
>    Affects Versions: 5.0-beta
>            Reporter: zhong.zhu
>            Assignee: zhong.zhu
>            Priority: Critical
>             Fix For: 5.0.0
>
>
> Phenomenon:
> When more than one plus sign is used in a row and the parameters on both 
> sides of the plus sign are constants, the result is not as expected
> '1' + 3 + 3 → 7 (correct)
> '1' + 3 + '3' → 4.03 (wrong result)
> '1' + '3' + 'a' → error
> When multiple plus signs are used in a row, and the arguments on both sides 
> of the plus sign are constants, and the first plus sign results in null, the 
> use of plus signs in a row is not supported.
> e.g. 'q' + 1 + 1 -> error



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

Reply via email to