This is an automated email from the ASF dual-hosted git repository.
zhenchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/main by this push:
new eb0534dac4 [CALCITE-6176] JOIN_SUB_QUERY_TO_CORRELATE rule incorrectly
handles EXISTS in LEFT JOIN ON clause
eb0534dac4 is described below
commit eb0534dac4949fe4116f0fbb0c861edf8912b766
Author: Zhen Chen <[email protected]>
AuthorDate: Mon Nov 17 23:07:20 2025 +0800
[CALCITE-6176] JOIN_SUB_QUERY_TO_CORRELATE rule incorrectly handles EXISTS
in LEFT JOIN ON clause
---
.../org/apache/calcite/test/RelOptRulesTest.java | 60 +++++++++
.../org/apache/calcite/test/RelOptRulesTest.xml | 136 +++++++++++++++++++++
core/src/test/resources/sql/join.iq | 62 ++++++++++
3 files changed, 258 insertions(+)
diff --git a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
index 6b2d1533c6..92e27614e5 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -10038,6 +10038,66 @@ public interface Config extends RelRule.Config {
.checkUnchanged();
}
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-6176">[CALCITE-6176]
+ * JOIN_SUB_QUERY_TO_CORRELATE rule incorrectly handles EXISTS in LEFT JOIN
ON clause</a>. */
+ @Test void testJoinSubQueryRemoveRuleWithNotExists() {
+ final String sql = "select *\n"
+ + "from (select 1 id) t1\n"
+ + "left join (select 2 id) t2\n"
+ + "on not exists(select *\n"
+ + " from (select 3 id) p\n"
+ + " where p.id = t2.id)";
+ sql(sql)
+ .withRule(CoreRules.JOIN_SUB_QUERY_TO_CORRELATE)
+ .check();
+ }
+
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-6176">[CALCITE-6176]
+ * JOIN_SUB_QUERY_TO_CORRELATE rule incorrectly handles EXISTS in LEFT JOIN
ON clause</a>. */
+ @Test void testJoinSubQueryRemoveRuleWithOrExists() {
+ final String sql = "select *\n"
+ + "from (select 1 id) t1\n"
+ + "left join (select 2 id) t2\n"
+ + "on t1.id = t2.id or exists(select *\n"
+ + " from (select 3 id) p\n"
+ + " where p.id = t2.id)";
+ sql(sql)
+ .withRule(CoreRules.JOIN_SUB_QUERY_TO_CORRELATE)
+ .check();
+ }
+
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-6176">[CALCITE-6176]
+ * JOIN_SUB_QUERY_TO_CORRELATE rule incorrectly handles EXISTS in LEFT JOIN
ON clause</a>. */
+ @Test void testJoinSubQueryRemoveRuleWithOrNotExists() {
+ final String sql = "select *\n"
+ + "from (select 1 id) t1\n"
+ + "left join (select 2 id) t2\n"
+ + "on t1.id = t2.id or not exists(select *\n"
+ + " from (select 3 id) p\n"
+ + " where p.id = t2.id)";
+ sql(sql)
+ .withRule(CoreRules.JOIN_SUB_QUERY_TO_CORRELATE)
+ .check();
+ }
+
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-6176">[CALCITE-6176]
+ * JOIN_SUB_QUERY_TO_CORRELATE rule incorrectly handles EXISTS in LEFT JOIN
ON clause</a>. */
+ @Test void testJoinSubQueryRemoveRuleWithAndNotExists() {
+ final String sql = "select *\n"
+ + "from (select 1 id union all select 2) t1\n"
+ + "left join (select 2 id) t2\n"
+ + "on t1.id = t2.id and not exists(select *\n"
+ + " from (select 3 id) p\n"
+ + " where p.id = t1.id)";
+ sql(sql)
+ .withRule(CoreRules.JOIN_SUB_QUERY_TO_CORRELATE)
+ .check();
+ }
+
/** Test case for
* <a
href="https://issues.apache.org/jira/browse/CALCITE-2295">[CALCITE-2295]
* Correlated SubQuery with Project will generate error plan</a>. */
diff --git
a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
index 651b6ad520..0fe14272f3 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -8293,6 +8293,74 @@ LogicalProject(SAL=[$5])
LogicalProject(SAL=[$5], $f9=[=($5, 4)])
LogicalFilter(condition=[AND(=($7, 20), >($5, 1000))])
LogicalTableScan(table=[[CATALOG, SALES, EMPNULLABLES]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testJoinSubQueryRemoveRuleWithAndNotExists">
+ <Resource name="sql">
+ <![CDATA[select *
+from (select 1 id union all select 2) t1
+left join (select 2 id) t2
+on t1.id = t2.id and not exists(select *
+ from (select 3 id) p
+ where p.id = t1.id)]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(ID=[$0], ID0=[$1])
+ LogicalJoin(condition=[AND(=($0, $1), NOT(EXISTS({
+LogicalFilter(condition=[=($0, $cor0.ID)])
+ LogicalValues(tuples=[[{ 3 }]])
+})))], joinType=[left])
+ LogicalValues(tuples=[[{ 1 }, { 2 }]])
+ LogicalValues(tuples=[[{ 2 }]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject(ID=[$0], ID0=[$1])
+ LogicalProject(ID=[$0], ID0=[$2])
+ LogicalJoin(condition=[AND(=($0, $2), IS NULL($1))], joinType=[left])
+ LogicalCorrelate(correlation=[$cor0], joinType=[left],
requiredColumns=[{0}])
+ LogicalValues(tuples=[[{ 1 }, { 2 }]])
+ LogicalProject(i=[true])
+ LogicalFilter(condition=[=($0, $cor0.ID)])
+ LogicalValues(tuples=[[{ 3 }]])
+ LogicalValues(tuples=[[{ 2 }]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testJoinSubQueryRemoveRuleWithNotExists">
+ <Resource name="sql">
+ <![CDATA[select *
+from (select 1 id) t1
+left join (select 2 id) t2
+on not exists(select *
+ from (select 3 id) p
+ where p.id = t2.id)]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(ID=[$0], ID0=[$1])
+ LogicalJoin(condition=[NOT(EXISTS({
+LogicalFilter(condition=[=($0, $cor0.ID0)])
+ LogicalValues(tuples=[[{ 3 }]])
+}))], joinType=[left])
+ LogicalValues(tuples=[[{ 1 }]])
+ LogicalValues(tuples=[[{ 2 }]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject(ID=[$0], ID0=[$1])
+ LogicalProject(ID=[$0], ID0=[$1])
+ LogicalJoin(condition=[IS NULL($2)], joinType=[left])
+ LogicalValues(tuples=[[{ 1 }]])
+ LogicalCorrelate(correlation=[$cor0], joinType=[left],
requiredColumns=[{0}])
+ LogicalValues(tuples=[[{ 2 }]])
+ LogicalProject(i=[true])
+ LogicalFilter(condition=[=($0, $cor0.ID)])
+ LogicalValues(tuples=[[{ 3 }]])
]]>
</Resource>
</TestCase>
@@ -8325,6 +8393,74 @@ LogicalProject(EMPNO=[$0])
LogicalProject(DEPTNO=[$0], i=[true])
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testJoinSubQueryRemoveRuleWithOrExists">
+ <Resource name="sql">
+ <![CDATA[select *
+from (select 1 id) t1
+left join (select 2 id) t2
+on t1.id = t2.id or exists(select *
+ from (select 3 id) p
+ where p.id = t2.id)]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(ID=[$0], ID0=[$1])
+ LogicalJoin(condition=[OR(=($0, $1), EXISTS({
+LogicalFilter(condition=[=($0, $cor0.ID0)])
+ LogicalValues(tuples=[[{ 3 }]])
+}))], joinType=[left])
+ LogicalValues(tuples=[[{ 1 }]])
+ LogicalValues(tuples=[[{ 2 }]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject(ID=[$0], ID0=[$1])
+ LogicalProject(ID=[$0], ID0=[$1])
+ LogicalJoin(condition=[OR(=($0, $1), IS NOT NULL($2))], joinType=[left])
+ LogicalValues(tuples=[[{ 1 }]])
+ LogicalCorrelate(correlation=[$cor0], joinType=[left],
requiredColumns=[{0}])
+ LogicalValues(tuples=[[{ 2 }]])
+ LogicalProject(i=[true])
+ LogicalFilter(condition=[=($0, $cor0.ID)])
+ LogicalValues(tuples=[[{ 3 }]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testJoinSubQueryRemoveRuleWithOrNotExists">
+ <Resource name="sql">
+ <![CDATA[select *
+from (select 1 id) t1
+left join (select 2 id) t2
+on t1.id = t2.id or not exists(select *
+ from (select 3 id) p
+ where p.id = t2.id)]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(ID=[$0], ID0=[$1])
+ LogicalJoin(condition=[OR(=($0, $1), NOT(EXISTS({
+LogicalFilter(condition=[=($0, $cor0.ID0)])
+ LogicalValues(tuples=[[{ 3 }]])
+})))], joinType=[left])
+ LogicalValues(tuples=[[{ 1 }]])
+ LogicalValues(tuples=[[{ 2 }]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject(ID=[$0], ID0=[$1])
+ LogicalProject(ID=[$0], ID0=[$1])
+ LogicalJoin(condition=[OR(=($0, $1), IS NULL($2))], joinType=[left])
+ LogicalValues(tuples=[[{ 1 }]])
+ LogicalCorrelate(correlation=[$cor0], joinType=[left],
requiredColumns=[{0}])
+ LogicalValues(tuples=[[{ 2 }]])
+ LogicalProject(i=[true])
+ LogicalFilter(condition=[=($0, $cor0.ID)])
+ LogicalValues(tuples=[[{ 3 }]])
]]>
</Resource>
</TestCase>
diff --git a/core/src/test/resources/sql/join.iq
b/core/src/test/resources/sql/join.iq
index 1e1f5135e2..0c7573baee 100644
--- a/core/src/test/resources/sql/join.iq
+++ b/core/src/test/resources/sql/join.iq
@@ -1030,4 +1030,66 @@ natural join "scott".dept order by empno;
!ok
+# [CALCITE-6176] JOIN_SUB_QUERY_TO_CORRELATE rule incorrectly handles EXISTS
in LEFT JOIN ON clause
+select *
+from (select 1 id) t1
+left join (select 2 id) t2
+on not exists(select *
+ from (select 3 id) p
+ where p.id = t2.id);
++----+-----+
+| ID | ID0 |
++----+-----+
+| 1 | 2 |
++----+-----+
+(1 row)
+
+!ok
+
+select *
+from (select 1 id union all select 2) t1
+left join (select 2 id) t2
+on t1.id = t2.id and not exists(select *
+ from (select 3 id) p
+ where p.id = t1.id);
++----+-----+
+| ID | ID0 |
++----+-----+
+| 1 | |
+| 2 | 2 |
++----+-----+
+(2 rows)
+
+!ok
+
+select *
+from (select 1 id) t1
+left join (select 2 id) t2
+on t1.id = t2.id or exists(select *
+ from (select 3 id) p
+ where p.id = t2.id);
++----+-----+
+| ID | ID0 |
++----+-----+
+| 1 | |
++----+-----+
+(1 row)
+
+!ok
+
+select *
+from (select 1 id) t1
+left join (select 2 id) t2
+on t1.id = t2.id or not exists(select *
+ from (select 3 id) p
+ where p.id = t2.id);
++----+-----+
+| ID | ID0 |
++----+-----+
+| 1 | 2 |
++----+-----+
+(1 row)
+
+!ok
+
# End join.iq