This is an automated email from the ASF dual-hosted git repository.

silun 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 3e8a082445 [CALCITE-7372] TopDownGeneralDecorrelator will throw an 
error when the JOIN condition has correlation
3e8a082445 is described below

commit 3e8a082445090d529b12742183a3f9a14af3b685
Author: Zhen Chen <[email protected]>
AuthorDate: Wed Jan 14 11:14:48 2026 +0800

    [CALCITE-7372] TopDownGeneralDecorrelator will throw an error when the JOIN 
condition has correlation
---
 .../sql2rel/TopDownGeneralDecorrelator.java        | 15 ++++++--
 core/src/test/resources/sql/new-decorr.iq          | 45 ++++++++++++++++++++++
 2 files changed, 57 insertions(+), 3 deletions(-)

diff --git 
a/core/src/main/java/org/apache/calcite/sql2rel/TopDownGeneralDecorrelator.java 
b/core/src/main/java/org/apache/calcite/sql2rel/TopDownGeneralDecorrelator.java
index d3ccaa334d..10b9a411ff 100644
--- 
a/core/src/main/java/org/apache/calcite/sql2rel/TopDownGeneralDecorrelator.java
+++ 
b/core/src/main/java/org/apache/calcite/sql2rel/TopDownGeneralDecorrelator.java
@@ -680,11 +680,13 @@ public RelNode unnestInternal(Join join, boolean 
allowEmptyOutputFromRewrite) {
     UnnestedQuery rightInfo;
 
     if (!leftHasCorrelation && !join.getJoinType().generatesNullsOnRight()
-        && join.getJoinType().projectsRight()) {
-      // there is no need to push down domain D to left side when both 
following conditions
+        && join.getJoinType().projectsRight()
+        && rightHasCorrelation) {
+      // there is no need to push down domain D to left side when all 
following conditions
       // are satisfied:
       // 1. there is no correlation on left side
       // 2. join type will not generate NULL values on right side and will 
project right
+      // 3. there is correlation on right side to carry domain D
       // In this case, the left side will start a decorrelation independently
       newLeft = decorrelateQuery(join.getLeft(), builder);
       Map<Integer, Integer> leftOldToNewOutputs = new HashMap<>();
@@ -692,16 +694,23 @@ public RelNode unnestInternal(Join join, boolean 
allowEmptyOutputFromRewrite) {
           .forEach(i -> leftOldToNewOutputs.put(i, i));
       leftInfo = new UnnestedQuery(join.getLeft(), newLeft, new TreeMap<>(), 
leftOldToNewOutputs);
     } else {
+      // when neither the left nor the right side has correlation,
+      // but the join condition has correlation, domain D is pushed down to 
the left by default.
       newLeft = unnest(join.getLeft(), allowEmptyOutputFromRewrite);
       pushDownToLeft = true;
       leftInfo = requireNonNull(mapRelToUnnestedQuery.get(join.getLeft()));
     }
     if (!rightHasCorrelation && !join.getJoinType().generatesNullsOnLeft()) {
-      // there is no need to push down domain D to right side when both 
following conditions
+      // there is no need to push down domain D to right side when all 
following conditions
       // are satisfied:
       // 1. there is no correlation on right side
       // 2. join type will not generate NULL values on left side
+      // 3. there is domain D pushed down to left side
       // In this case, the right side will start a decorrelation independently
+
+      // either the left or the right side must carry domain D,
+      // and rightHasCorrelation is false, pushDownToLeft must be true here
+      assert pushDownToLeft;
       newRight = decorrelateQuery(join.getRight(), builder);
       Map<Integer, Integer> rightOldToNewOutputs = new HashMap<>();
       IntStream.range(0, newRight.getRowType().getFieldCount())
diff --git a/core/src/test/resources/sql/new-decorr.iq 
b/core/src/test/resources/sql/new-decorr.iq
new file mode 100644
index 0000000000..148d4721ac
--- /dev/null
+++ b/core/src/test/resources/sql/new-decorr.iq
@@ -0,0 +1,45 @@
+# new-decorr.iq
+#
+# 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.
+#
+
+# This is used to test for bugs associated with new decorrelator.
+# Most of the test cases here come from the .iq file removed in 
CoreQuidemTest2.
+# This file maybe can be deleted after these .iq files are made available.
+
+!use post
+!set outputformat mysql
+
+# [CALCITE-7372] TopDownGeneralDecorrelator will throw an error when the JOIN 
condition has correlation
+# This case comes from sub-query.iq [CALCITE-7257]
+WITH t0(t0a, t0b) AS (VALUES (1, 1), (2, 0)),
+     t1(t1a, t1b, t1c) AS (VALUES (1, 1, 3)),
+     t2(t2a, t2b, t2c) AS (VALUES (1, 1, 5), (2, 2, 7))
+SELECT * FROM t0 WHERE t0a <
+(SELECT sum(t1c) FROM
+  (SELECT t1c
+   FROM   t1 JOIN t2 ON (t1a < t0a AND t2b >= t1b))
+);
++-----+-----+
+| T0A | T0B |
++-----+-----+
+|   2 |   0 |
++-----+-----+
+(1 row)
+
+!ok
+
+# End new-decorr.iq

Reply via email to