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