SteveStevenpoor commented on code in PR #26627: URL: https://github.com/apache/flink/pull/26627#discussion_r2131987460
########## flink-table/flink-table-planner/src/test/resources/org/apache/flink/table/planner/plan/rules/logical/FlinkRightJoinToLeftJoinRuleTest.xml: ########## @@ -0,0 +1,144 @@ +<?xml version="1.0" ?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to you under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +--> +<Root> + <TestCase name="testRightJoinIsConverted"> + <Resource name="sql"> + <![CDATA[SELECT * FROM T1 RIGHT JOIN T2 ON a = c]]> + </Resource> + <Resource name="ast"> + <![CDATA[ +LogicalProject(a=[$0], b=[$1], c=[$2], d=[$3], e=[$4]) ++- LogicalJoin(condition=[=($0, $2)], joinType=[right]) + :- LogicalTableScan(table=[[default_catalog, default_database, T1]]) + +- LogicalTableScan(table=[[default_catalog, default_database, T2]]) +]]> + </Resource> + <Resource name="optimized rel plan"> + <![CDATA[ +LogicalProject(a=[$0], b=[$1], c=[$2], d=[$3], e=[$4]) ++- LogicalProject(a=[$3], b=[$4], c=[$0], d=[$1], e=[$2]) + +- LogicalJoin(condition=[=($3, $0)], joinType=[left]) + :- LogicalTableScan(table=[[default_catalog, default_database, T2]]) + +- LogicalTableScan(table=[[default_catalog, default_database, T1]]) +]]> + </Resource> + </TestCase> + + <TestCase name="testJoinChainIsConverted"> + <Resource name="sql"> + <![CDATA[SELECT * FROM (SELECT * FROM T1 JOIN T2 ON a = c) RIGHT JOIN T3 ON a = f]]> + </Resource> + <Resource name="ast"> + <![CDATA[ +LogicalProject(a=[$0], b=[$1], c=[$2], d=[$3], e=[$4], f=[$5], g=[$6]) ++- LogicalJoin(condition=[=($0, $5)], joinType=[right]) + :- LogicalProject(a=[$0], b=[$1], c=[$2], d=[$3], e=[$4]) + : +- LogicalJoin(condition=[=($0, $2)], joinType=[inner]) + : :- LogicalTableScan(table=[[default_catalog, default_database, T1]]) + : +- LogicalTableScan(table=[[default_catalog, default_database, T2]]) + +- LogicalTableScan(table=[[default_catalog, default_database, T3]]) +]]> + </Resource> + <Resource name="optimized rel plan"> + <![CDATA[ +LogicalProject(a=[$0], b=[$1], c=[$2], d=[$3], e=[$4], f=[$5], g=[$6]) ++- LogicalProject(a=[$2], b=[$3], c=[$4], d=[$5], e=[$6], f=[$0], g=[$1]) + +- LogicalJoin(condition=[=($2, $0)], joinType=[left]) + :- LogicalTableScan(table=[[default_catalog, default_database, T3]]) + +- LogicalProject(a=[$0], b=[$1], c=[$2], d=[$3], e=[$4]) + +- LogicalJoin(condition=[=($0, $2)], joinType=[inner]) + :- LogicalTableScan(table=[[default_catalog, default_database, T1]]) + +- LogicalTableScan(table=[[default_catalog, default_database, T2]]) +]]> + </Resource> + </TestCase> + + <TestCase name="testLeftJoinRemainsUnchanged"> + <Resource name="sql"> + <![CDATA[SELECT * FROM T1 LEFT JOIN T2 ON a = c]]> + </Resource> + <Resource name="ast"> + <![CDATA[ +LogicalProject(a=[$0], b=[$1], c=[$2], d=[$3], e=[$4]) ++- LogicalJoin(condition=[=($0, $2)], joinType=[left]) + :- LogicalTableScan(table=[[default_catalog, default_database, T1]]) + +- LogicalTableScan(table=[[default_catalog, default_database, T2]]) +]]> + </Resource> + <Resource name="optimized rel plan"> + <![CDATA[ +LogicalProject(a=[$0], b=[$1], c=[$2], d=[$3], e=[$4]) ++- LogicalJoin(condition=[=($0, $2)], joinType=[left]) + :- LogicalTableScan(table=[[default_catalog, default_database, T1]]) + +- LogicalTableScan(table=[[default_catalog, default_database, T2]]) +]]> + </Resource> + </TestCase> + + <TestCase name="testRightJoinWithExpressionCondition"> + <Resource name="sql"> + <![CDATA[SELECT * FROM T1 RIGHT JOIN T2 ON a + 1 = c - 1]]> + </Resource> + <Resource name="ast"> + <![CDATA[ +LogicalProject(a=[$0], b=[$1], c=[$2], d=[$3], e=[$4]) ++- LogicalProject(a=[$0], b=[$1], c=[$3], d=[$4], e=[$5]) + +- LogicalJoin(condition=[=($2, $6)], joinType=[right]) + :- LogicalProject(a=[$0], b=[$1], $f2=[+($0, 1)]) + : +- LogicalTableScan(table=[[default_catalog, default_database, T1]]) + +- LogicalProject(c=[$0], d=[$1], e=[$2], $f3=[-($0, 1)]) + +- LogicalTableScan(table=[[default_catalog, default_database, T2]]) +]]> + </Resource> + <Resource name="optimized rel plan"> + <![CDATA[ +LogicalProject(a=[$0], b=[$1], c=[$2], d=[$3], e=[$4]) ++- LogicalProject(a=[$0], b=[$1], c=[$3], d=[$4], e=[$5]) + +- LogicalProject(a=[$4], b=[$5], $f2=[$6], c=[$0], d=[$1], e=[$2], $f3=[$3]) + +- LogicalJoin(condition=[=($6, $3)], joinType=[left]) + :- LogicalProject(c=[$0], d=[$1], e=[$2], $f3=[-($0, 1)]) + : +- LogicalTableScan(table=[[default_catalog, default_database, T2]]) + +- LogicalProject(a=[$0], b=[$1], $f2=[+($0, 1)]) + +- LogicalTableScan(table=[[default_catalog, default_database, T1]]) +]]> + </Resource> + </TestCase> + + <TestCase name="testRightJoinWithProjection"> + <Resource name="sql"> + <![CDATA[SELECT b, d FROM T1 RIGHT JOIN T2 ON a = c]]> + </Resource> + <Resource name="ast"> + <![CDATA[ +LogicalProject(b=[$1], d=[$3]) ++- LogicalJoin(condition=[=($0, $2)], joinType=[right]) + :- LogicalTableScan(table=[[default_catalog, default_database, T1]]) + +- LogicalTableScan(table=[[default_catalog, default_database, T2]]) +]]> + </Resource> + <Resource name="optimized rel plan"> + <![CDATA[ +LogicalProject(b=[$1], d=[$3]) ++- LogicalProject(a=[$3], b=[$4], c=[$0], d=[$1], e=[$2]) Review Comment: When we call transformTo on RelOptRuleCall calcite verifies that output record before transformation is the same as after applying. Without projection it will look like this: > Type mismatch: rowtype of original rel: RecordType(INTEGER a, BIGINT b, INTEGER c, BIGINT d, BIGINT e) NOT NULL rowtype of new rel: RecordType(INTEGER c, BIGINT d, BIGINT e, INTEGER a, BIGINT b) NOT NULL Difference: c: INTEGER -> BIGINT d: BIGINT -> INTEGER Since I swap left and right input output record field order is changed. So I had to add this projection to return field order back to normal. `RelNode project = reorderProjectedFields(left, right, relBuilder);` Say we have T1 with field a, T2 with field b and T3 with field c `(T1 join T2) right join T3` without multijoin will return abc but with multijoin it will be converted to `T3 left join (T1 join T2) ===> multijoin(T3, T1, T2)` which will return cab. So the projection is necessary. And I can handle it in JoinToMultiJoinRule. I think I could create a child class from calcite's Join, something like ConvertedJoin, to override getRowType. But I decided to avoid it. Let me know what do you think! -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: issues-unsubscr...@flink.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org