Iurii Gerzhedovich created CALCITE-7859:
-------------------------------------------

             Summary: SqlToRelConverter.convertMerge produces a wrong plan or 
fails when a sub-query in MERGE ... UPDATE SET is expanded (expand = true)
                 Key: CALCITE-7859
                 URL: https://issues.apache.org/jira/browse/CALCITE-7859
             Project: Calcite
          Issue Type: Bug
          Components: core
    Affects Versions: 1.42.0
            Reporter: Iurii Gerzhedovich


{{SqlToRelConverter.convertMerge}} assumes that the input of the projection of 
the MERGE source select is the join of the
source and the target:

{code:java}
LogicalJoin join = (LogicalJoin) mergeSourceRel.getInput(0);
int nSourceFields = join.getLeft().getRowType().getFieldCount();
...
relBuilder.push(join).project(projects, ...);
{code}

With {{expand = true}} (the default of {{SqlToRelConverter.Config}}) a 
sub-query in the SET expression is expanded into a
join or a correlate on top of that join, so the assumption does not hold.

1. Correlated sub-query: the input is a {{LogicalCorrelate}} and the conversion 
fails with
{noformat}
java.lang.ClassCastException: class LogicalCorrelate cannot be cast to class 
LogicalJoin
  at SqlToRelConverter.convertMerge
{noformat}

2. Uncorrelated sub-query: the input is a {{LogicalJoin}} of the source/target 
join and the sub-query, so the cast
succeeds, but {{join.getLeft()}} is the source/target join, and 
{{nSourceFields}} is the width of both tables instead
of the width of the source. All target columns are dropped from the projection, 
and the join with the sub-query
is discarded or referenced wrongly. Query (SqlToRelConverterTest catalog):

{code:sql}
merge into empnullables e
using (select * from emp) t
on e.empno = t.empno
when matched then update
set sal = (select max(d.deptno) from dept d)
{code}

Actual plan (the update row has only the SET expression, the 9 target columns 
are missing):
{noformat}
LogicalTableModify(table=[[CATALOG, SALES, EMPNULLABLES]], operation=[MERGE], 
updateColumnList=[[SAL]], flattened=[true])
  LogicalProject(EXPR$0=[$18])
    LogicalJoin(condition=[true], joinType=[left])
      ...
{noformat}

Expected:
{noformat}
LogicalProject(EMPNO0=[$9], ENAME0=[$10], JOB0=[$11], MGR0=[$12], 
HIREDATE0=[$13], SAL0=[$14], COMM0=[$15], DEPTNO0=[$16], SLACKER0=[$17], 
EXPR$0=[$18])
{noformat}

Fix: compute the number of source fields from the validator namespace of the 
source table reference, and build the new
projection over the real input of the source projection instead of over the 
first join found.



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

Reply via email to