Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1418,6 +1418,29 @@ private void handleOffsetFetch(@Nullable SqlNode offset, @Nullable SqlNode fetch
if (node instanceof SqlMerge) {
validatingSqlMerge = true;
}
if (node instanceof SqlJoin) {
// select * from "scott".dept,
// lateral (select count(cast(deptno as integer)) from "scott".emp
// where emp.deptno = dept.deptno);
// ==》
// select * from "scott".dept left join
// lateral (select count(cast(deptno as integer)) from "scott".emp
// where emp.deptno = dept.deptno) on true;
SqlJoin sqlJoin = (SqlJoin) node;
if (sqlJoin.getJoinType() == JoinType.COMMA && sqlJoin.getRight() instanceof SqlCall) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you explain where the discussion in the JIRA is reflected in this code?
I think the consensus there was that a left join is not always right

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, @mihaibudiu. The jira cases discusses how converting an inner lateral join to a left join is WRONG. Do not merge this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will recheck this. This repair method does have some issues. I will add more test cases to verify it.

SqlCall sqlCall = (SqlCall) sqlJoin.getRight();
if (sqlCall.getOperator() == SqlStdOperatorTable.LATERAL
&& sqlCall.operand(0) instanceof SqlSelect
&& isAggregate(sqlCall.operand(0))) {
return performUnconditionalRewrites(
new SqlJoin(sqlJoin.getParserPosition(),
sqlJoin.getLeft(), sqlJoin.isNaturalNode(),
JoinType.LEFT.symbol(node.getParserPosition()),
sqlJoin.getRight(), JoinConditionType.ON.symbol(node.getParserPosition()),
SqlLiteral.createBoolean(true, node.getParserPosition())), underFrom);
}
}
}
SqlCall call = (SqlCall) node;
final SqlKind kind = call.getKind();
final List<SqlNode> operands = call.getOperandList();
Expand Down
94 changes: 94 additions & 0 deletions core/src/test/resources/sql/lateral.iq
Original file line number Diff line number Diff line change
Expand Up @@ -246,4 +246,98 @@ where job = 'MANAGER';

!ok

# [CALCITE-4693] Query with Lateral Join should converted to Left Join When sub-query is aggregate query

select * from "scott".dept, lateral (select count(cast(deptno as integer)) from "scott".emp where emp.deptno = dept.deptno);
+--------+------------+----------+--------+
| DEPTNO | DNAME | LOC | EXPR$0 |
+--------+------------+----------+--------+
| 10 | ACCOUNTING | NEW YORK | 3 |
| 20 | RESEARCH | DALLAS | 5 |
| 30 | SALES | CHICAGO | 6 |
| 40 | OPERATIONS | BOSTON | 0 |
+--------+------------+----------+--------+
(4 rows)

!ok
EnumerableCalc(expr#0..4=[{inputs}], expr#5=[IS NULL($t4)], expr#6=[0:BIGINT], expr#7=[CASE($t5, $t6, $t4)], proj#0..2=[{exprs}], EXPR$0=[$t7])
EnumerableHashJoin(condition=[=($0, $3)], joinType=[left])
EnumerableTableScan(table=[[scott, DEPT]])
EnumerableCalc(expr#0..2=[{inputs}], expr#3=[IS NOT NULL($t2)], expr#4=[0], expr#5=[CASE($t3, $t2, $t4)], DEPTNO=[$t0], EXPR$0=[$t5])
EnumerableNestedLoopJoin(condition=[IS NOT DISTINCT FROM($0, $1)], joinType=[left])
EnumerableCalc(expr#0..2=[{inputs}], DEPTNO=[$t0])
EnumerableTableScan(table=[[scott, DEPT]])
EnumerableAggregate(group=[{0}], EXPR$0=[COUNT($1)])
EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t7):INTEGER], expr#9=[IS NOT NULL($t7)], DEPTNO=[$t7], $f0=[$t8], $condition=[$t9])
EnumerableTableScan(table=[[scott, EMP]])
!plan

select * from "scott".dept, lateral (select count(cast(deptno as integer)) from "scott".emp where emp.deptno = dept.deptno + 10);
+--------+------------+----------+--------+
| DEPTNO | DNAME | LOC | EXPR$0 |
+--------+------------+----------+--------+
| 10 | ACCOUNTING | NEW YORK | 5 |
| 20 | RESEARCH | DALLAS | 6 |
| 30 | SALES | CHICAGO | 0 |
| 40 | OPERATIONS | BOSTON | 0 |
+--------+------------+----------+--------+
(4 rows)

!ok
EnumerableCalc(expr#0..5=[{inputs}], expr#6=[IS NULL($t5)], expr#7=[0:BIGINT], expr#8=[CASE($t6, $t7, $t5)], proj#0..2=[{exprs}], EXPR$0=[$t8])
EnumerableHashJoin(condition=[=($3, $4)], joinType=[left])
EnumerableCalc(expr#0..2=[{inputs}], expr#3=[10], expr#4=[+($t0, $t3)], proj#0..2=[{exprs}], $f3=[$t4])
EnumerableTableScan(table=[[scott, DEPT]])
EnumerableCalc(expr#0..2=[{inputs}], expr#3=[IS NOT NULL($t2)], expr#4=[0], expr#5=[CASE($t3, $t2, $t4)], DEPTNO0=[$t0], EXPR$0=[$t5])
EnumerableNestedLoopJoin(condition=[IS NOT DISTINCT FROM($0, $1)], joinType=[left])
EnumerableAggregate(group=[{0}])
EnumerableCalc(expr#0..2=[{inputs}], expr#3=[10], expr#4=[+($t0, $t3)], $f3=[$t4])
EnumerableTableScan(table=[[scott, DEPT]])
EnumerableAggregate(group=[{0}], EXPR$0=[COUNT($1)])
EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t7):INTEGER], expr#9=[IS NOT NULL($t7)], DEPTNO0=[$t8], $f0=[$t8], $condition=[$t9])
EnumerableTableScan(table=[[scott, EMP]])
!plan

select * from "scott".dept, lateral (select sum(cast(deptno as integer)) from "scott".emp where emp.deptno = dept.deptno);
+--------+------------+----------+--------+
| DEPTNO | DNAME | LOC | EXPR$0 |
+--------+------------+----------+--------+
| 10 | ACCOUNTING | NEW YORK | 30 |
| 20 | RESEARCH | DALLAS | 100 |
| 30 | SALES | CHICAGO | 180 |
| 40 | OPERATIONS | BOSTON | |
+--------+------------+----------+--------+
(4 rows)

!ok
EnumerableCalc(expr#0..4=[{inputs}], proj#0..2=[{exprs}], EXPR$0=[$t4])
EnumerableMergeJoin(condition=[=($0, $3)], joinType=[left])
EnumerableTableScan(table=[[scott, DEPT]])
EnumerableSort(sort0=[$0], dir0=[ASC])
EnumerableAggregate(group=[{0}], EXPR$0=[SUM($1)])
EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t7):INTEGER], expr#9=[IS NOT NULL($t7)], DEPTNO=[$t7], $f0=[$t8], $condition=[$t9])
EnumerableTableScan(table=[[scott, EMP]])
!plan

select * from "scott".dept, lateral (select sum(cast(deptno as integer)) from "scott".emp where emp.deptno = dept.deptno + 10);
+--------+------------+----------+--------+
| DEPTNO | DNAME | LOC | EXPR$0 |
+--------+------------+----------+--------+
| 10 | ACCOUNTING | NEW YORK | 100 |
| 20 | RESEARCH | DALLAS | 180 |
| 30 | SALES | CHICAGO | |
| 40 | OPERATIONS | BOSTON | |
+--------+------------+----------+--------+
(4 rows)

!ok
EnumerableCalc(expr#0..5=[{inputs}], proj#0..2=[{exprs}], EXPR$0=[$t5])
EnumerableHashJoin(condition=[=($3, $4)], joinType=[left])
EnumerableCalc(expr#0..2=[{inputs}], expr#3=[10], expr#4=[+($t0, $t3)], proj#0..2=[{exprs}], $f3=[$t4])
EnumerableTableScan(table=[[scott, DEPT]])
EnumerableAggregate(group=[{0}], EXPR$0=[SUM($1)])
EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t7):INTEGER], expr#9=[IS NOT NULL($t7)], DEPTNO0=[$t8], $f0=[$t8], $condition=[$t9])
EnumerableTableScan(table=[[scott, EMP]])
!plan

# End lateral.iq
Loading