[ 
https://issues.apache.org/jira/browse/CALCITE-7450?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Caican Cai resolved CALCITE-7450.
---------------------------------
    Fix Version/s: 1.42.0
       Resolution: Fixed

> ValuesReduceRule dropping LogicalValues incorrectly
> ---------------------------------------------------
>
>                 Key: CALCITE-7450
>                 URL: https://issues.apache.org/jira/browse/CALCITE-7450
>             Project: Calcite
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 1.41.0, 1.42.0
>            Reporter: Darpan Lunagariya (e6data computing)
>            Priority: Minor
>              Labels: pull-request-available
>             Fix For: 1.42.0
>
>   Original Estimate: 2h
>  Remaining Estimate: 2h
>
> In ValuesReduceRule, when a filter condition on LogicalValues contains a 
> function call that RexExecutorImpl cannot reduce to a RexLiteral (e.g., a UDF 
> with no Janino CallImplementor, or a non-deterministic function like RAND()). 
> This causes the rule to incorrectly drop the tuple.
>  
> The project expression path already handles this correctly, it checks whether 
> each reduced expression is a RexLiteral and bails out if not (lines 203-209). 
> The filter condition path lacks this same guard.
> Below are the relevant snippets from that rule:
> *For project:*
> {code:java}
> if (projectExprs != null) {
>   ++changeCount;
>   final ImmutableList.Builder<RexLiteral> tupleBuilder =
>       ImmutableList.builder();
>   for (; i < fieldsPerRow; ++i) {
>     final RexNode reducedValue =
>         reducibleExps.get((row * fieldsPerRow) + i);
>     if (reducedValue instanceof RexLiteral) {
>       tupleBuilder.add((RexLiteral) reducedValue);
>     } else if (RexUtil.isNullLiteral(reducedValue, true)) {
>       tupleBuilder.add(rexBuilder.makeNullLiteral(reducedValue.getType()));
>     } else {
>       return;
>     }
>   }
>   valuesList = tupleBuilder.build();
> } else {
>   valuesList = values.getTuples().get(row);
> }
> {code}
> *For filter:*
> {code:java}
> if (conditionExpr != null) {
>   final RexNode reducedValue =
>       reducibleExps.get((row * fieldsPerRow) + i);
>   ++i;
>   if (!reducedValue.isAlwaysTrue()) {
>     ++changeCount;
>     continue;
>   }
> }
> {code}
>  
> For filter conditions, we just check 
> {code:java}
> !reducedValue.isAlwaysTrue(){code}
> which will always be true in case of RexCall and that tuple will be dropped 
> incorrectly, instead, we should just return from that rule when we detect 
> RexCall is not converted into RexLiteral, as done in reducing the project 
> expression.
>  
> Here is one example:
> {code:sql}
> SELECT * FROM (VALUES (0, 1, 2), (3, 4, 5)) AS t(a, b, c) WHERE RAND(t.a) > 
> 0.5
> {code}
> For this query,
> {code:java}
> // RelNode tree after conversion to RelNode from SqlNode:
> LogicalProject(A=[$0], B=[$1], C=[$2])
>   LogicalFilter(condition=[>(RAND($0), CAST(0.5:DECIMAL(2, 1)):DOUBLE NOT 
> NULL)])
>     LogicalValues(tuples=[[{ 0, 1, 2 }, { 3, 4, 5 }]])
> // RelNode tree applying the rule:
> LogicalValues(tuples=[[]])
> {code}



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

Reply via email to