You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@calcite.apache.org by "Caican Cai (Jira)" <ji...@apache.org> on 2026/03/26 05:56:00 UTC

[jira] [Resolved] (CALCITE-7450) ValuesReduceRule dropping LogicalValues incorrectly

     [ 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)