Darpan Lunagariya (e6data computing) created CALCITE-7450:
-------------------------------------------------------------

             Summary: Bug in 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)


When we have *custom functions* defined and use them on LogicalValues, the 
ValuesReduceRule will drop the tuples in a wrong way, which it should not do. 
The project expression reduction handles it correctly and it specifically 
checks that after reduction, did the RexCall reduced into RexLiteral or not, if 
not, then we return at that time, but this is not handled in filter expression 
reduction.

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, 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 
CUSTOM_FUNC(t.a) > 2
{code}
I have just registered CUSTOM_FUNC in operator table, but I did not register 
Janino CallImplementor. Possibility is that this function is executed at 
runtime and some application just expect calcite to produce the Plan for it. 
For this query,
{code:java}
// RelNode tree after conversion to RelNode from SqlNode:
LogicalProject(A=[$0], B=[$1], C=[$2])
  LogicalFilter(condition=[>(CUSTOM_FUNC($0), 2)])
    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