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

Julian Hyde commented on CALCITE-3142:
--------------------------------------

It looks like the right direction.

In your example the expression is only derived if condition1 AND condition2 are 
true. I recall problems where AND switches to OR. E.g. an expression is derived 
if condition1 OR condition2 are true. Then later the same expression is needed 
if condition1 OR condition3 are true. Note that if condition1 is true the 
expression will be calculated twice. And if condition1 and condition2 are false 
and condition3 is true, we need to remember to calculate the expression. 
Complex flows like this occur especially when the SQL contains CASE.

I'm not being very clear, can you create a test case with this kind of 
scenario? Perhaps some of the linked Jira issues have this situation. I think 
it will make your solution much more robust.

 

> An NPE when rounding a nullable numeric
> ---------------------------------------
>
>                 Key: CALCITE-3142
>                 URL: https://issues.apache.org/jira/browse/CALCITE-3142
>             Project: Calcite
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 1.20.0
>            Reporter: Muhammad Gelbana
>            Assignee: Feng Zhu
>            Priority: Major
>              Labels: pull-request-available
>         Attachments: newcodegen.png
>
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> The following query throws a NPE in the generated code because it assumes the 
> divided value to be an initialized Java object (Not null), which is fine for 
> the first row, but not for the second.
> {code:sql}
> SELECT ROUND(CAST((X/Y) AS NUMERIC), 2) FROM (VALUES (1, 2), (NULLIF(5, 5), 
> NULLIF(5, 5))) A(X, Y){code}
> If I modify the query a little bit, it runs ok:
>  – No casting
> {code:sql}
> SELECT ROUND((X/Y), 2) FROM (VALUES (1, 2), (NULLIF(5, 5), NULLIF(5, 5))) 
> A(X, Y){code}
> – No rounding
> {code:sql}
> SELECT (X/Y)::NUMERIC FROM (VALUES (1, 2), (NULLIF(5, 5), NULLIF(5, 5))) A(X, 
> Y){code}
> +This is the optimized generated code+
> {code:java}
> final Object[] current = (Object[]) inputEnumerator.current();
> final Integer inp0_ = (Integer) current[0];
> final Integer inp1_ = (Integer) current[1];
> final java.math.BigDecimal v1 = new java.math.BigDecimal(
>   inp0_.intValue() / inp1_.intValue()); // <<< NPE
> return inp0_ == null || inp1_ == null ? (java.math.BigDecimal) null : 
> org.apache.calcite.runtime.SqlFunctions.sround(v1, 2);{code}
> +This is the non-optimized one+
> {code:java}
> final Object[] current = (Object[]) inputEnumerator.current();
> final Integer inp0_ = (Integer) current[0];
> final boolean inp0__unboxed = inp0_ == null;
> final Integer inp1_ = (Integer) current[1];
> final boolean inp1__unboxed = inp1_ == null;
> final boolean v = inp0__unboxed || inp1__unboxed;
> final int inp0__unboxed0 = inp0_.intValue(); // <<< NPE
> final int inp1__unboxed0 = inp1_.intValue(); // <<< NPE
> final int v0 = inp0__unboxed0 / inp1__unboxed0;
> final java.math.BigDecimal v1 = new java.math.BigDecimal(
>   v0);
> final java.math.BigDecimal v2 = v ? (java.math.BigDecimal) null : 
> org.apache.calcite.runtime.SqlFunctions.sround(v1, 2);
> return v2;{code}



--
This message was sent by Atlassian JIRA
(v7.6.14#76016)

Reply via email to