Ruben Q L created CALCITE-4414:
----------------------------------

             Summary: RelMdSelectivity#getSelectivity for Calc can propagate a 
predicate with wrong references
                 Key: CALCITE-4414
                 URL: https://issues.apache.org/jira/browse/CALCITE-4414
             Project: Calcite
          Issue Type: Bug
          Components: core
            Reporter: Ruben Q L
            Assignee: Ruben Q L
             Fix For: 1.27.0


{{RelMdSelectivity#getSelectivity(Calc rel, RelMetadataQuery mq, RexNode 
predicate)}} method:
{code}
  public Double getSelectivity(Calc rel, RelMetadataQuery mq, RexNode 
predicate) {
    final RexProgram rexProgram = rel.getProgram();
    final RexLocalRef programCondition = rexProgram.getCondition();
    if (programCondition == null) {
      return getSelectivity(rel.getInput(), mq, predicate); // [2]
    } else {
      // [1]
      return mq.getSelectivity(rel.getInput(),
          RelMdUtil.minusPreds(
              rel.getCluster().getRexBuilder(),
              predicate,
              rexProgram.expandLocalRef(programCondition)));
    }
  }
{code}
Currently passes down the predicate to its input [1] without considering any 
possible translation, since the predicate might include expressions generate by 
the Calc's projections, hence when the Calc's input analyzes the predicate it 
can end up trying to access fields that do not exist on its rowType.

This can lead to unforeseeable consequences, like the test attached to the 
first comment, where after {{RelMdSelectivity#getSelectivity(Calc)}} we reach 
{{RelMdSelectivity#getSelectivity(Union)}} and this method ends up in an 
{{ArrayIndexOutOfBoundsException}} becaus it tries to access a field ($1) that 
does not exists on its rowType (which only has $0). This $1 is actually 
projected by the Calc which is on top of the Union.

Notice in the code snipped above that in our test example the issue only 
happens in line [1], and not in [2] because the "if" block calls 
{{getSelectivity}} instead of {{mq.getSelectivity}}, although I find this a bit 
questionable and maybe {{mq.getSelectivity}} should be called here as well.




--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to