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

mbudiu 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 3eac1f7d56 [CALCITE-7272] Subqueries cannot be decorrelated if have 
set op
3eac1f7d56 is described below

commit 3eac1f7d567217e7fce13857712c7e0b6a1ab1e3
Author: iwanttobepowerful <[email protected]>
AuthorDate: Mon Dec 15 17:32:41 2025 +0800

    [CALCITE-7272] Subqueries cannot be decorrelated if have set op
---
 .../apache/calcite/sql2rel/RelDecorrelator.java    |  216 +++-
 .../calcite/sql2rel/RelDecorrelatorTest.java       |  415 +++++++
 .../org/apache/calcite/test/RelOptRulesTest.xml    |   10 +-
 core/src/test/resources/sql/sub-query.iq           | 1185 ++++++++++++++++++++
 4 files changed, 1779 insertions(+), 47 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/sql2rel/RelDecorrelator.java 
b/core/src/main/java/org/apache/calcite/sql2rel/RelDecorrelator.java
index db647da89c..c5986208d2 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/RelDecorrelator.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/RelDecorrelator.java
@@ -44,6 +44,7 @@
 import org.apache.calcite.rel.core.JoinRelType;
 import org.apache.calcite.rel.core.Project;
 import org.apache.calcite.rel.core.RelFactories;
+import org.apache.calcite.rel.core.SetOp;
 import org.apache.calcite.rel.core.Sort;
 import org.apache.calcite.rel.logical.LogicalAggregate;
 import org.apache.calcite.rel.logical.LogicalCorrelate;
@@ -817,8 +818,7 @@ protected RexNode removeCorrelationExpr(
       }
     }
 
-    if (rel.getGroupType() == Aggregate.Group.SIMPLE
-        && rel.getGroupSet().isEmpty()
+    if ((rel.hasEmptyGroup() || rel.getGroupSet().isEmpty())
         && !frame.corDefOutputs.isEmpty()
         && !parentPropagatesNullValues) {
       newRel = rewriteScalarAggregate(rel, newRel, outputMap, corDefOutputs);
@@ -930,71 +930,63 @@ private RelNode rewriteScalarAggregate(Aggregate oldRel,
       RelNode newRel,
       Map<Integer, Integer> outputMap,
       NavigableMap<CorDef, Integer> corDefOutputs) {
-    final Pair<CorrelationId, Frame> outerFramePair = 
requireNonNull(this.frameStack.peek());
-    final Frame outFrame = outerFramePair.right;
-    RexBuilder rexBuilder = relBuilder.getRexBuilder();
+    final CorelMap localCorelMap = new CorelMapBuilder().build(oldRel);
+    final List<CorRef> corVarList = new 
ArrayList<>(localCorelMap.mapRefRelToCorRef.values());
+    Collections.sort(corVarList);
 
-    int groupKeySize = (int) corDefOutputs.keySet().stream()
-        .filter(a -> a.corr.equals(outerFramePair.left))
-        .count();
-    List<RelDataTypeField> newRelFields = newRel.getRowType().getFieldList();
-    ImmutableBitSet.Builder corFieldBuilder = ImmutableBitSet.builder();
+    final NavigableMap<CorDef, Integer> valueGenCorDefOutputs = new 
TreeMap<>();
+    final RelNode valueGen =
+        requireNonNull(createValueGenerator(corVarList, 0, 
valueGenCorDefOutputs));
+    final int valueGenFieldCount = valueGen.getRowType().getFieldCount();
 
-    // Here we record the mapping between the original index and the new 
project.
-    // For the count, we map it as `case when x is null then 0 else x`.
+    // Build join conditions
     final Map<Integer, RexNode> newProjectMap = new HashMap<>();
     final List<RexNode> conditions = new ArrayList<>();
     for (Map.Entry<CorDef, Integer> corDefOutput : corDefOutputs.entrySet()) {
-      CorDef corDef = corDefOutput.getKey();
-      Integer corIndex = corDefOutput.getValue();
-      if (corDef.corr.equals(outerFramePair.left)) {
-        int newIdx = 
requireNonNull(outFrame.oldToNewOutputs.get(corDef.field));
-        corFieldBuilder.set(newIdx);
-
-        RelDataType type = 
outFrame.r.getRowType().getFieldList().get(newIdx).getType();
-        RexNode left = new RexInputRef(corFieldBuilder.cardinality() - 1, 
type);
-        newProjectMap.put(corIndex + groupKeySize, left);
-        conditions.add(
-            relBuilder.isNotDistinctFrom(left,
-                new RexInputRef(corIndex + groupKeySize,
-                    newRelFields.get(corIndex).getType())));
-      }
-    }
-
-    ImmutableBitSet groupSet = corFieldBuilder.build();
-    // Build [09] LogicalAggregate(group=[{0}]) to obtain the distinct set of
-    // corVar from outFrame.
-    relBuilder.push(outFrame.r)
-        .aggregate(relBuilder.groupKey(groupSet));
+      final CorDef corDef = corDefOutput.getKey();
+      final int leftPos = requireNonNull(valueGenCorDefOutputs.get(corDef));
+      final int rightPos = corDefOutput.getValue();
+      final RelDataType leftType = 
valueGen.getRowType().getFieldList().get(leftPos).getType();
+      final RelDataType rightType = 
newRel.getRowType().getFieldList().get(rightPos).getType();
+      final RexNode leftRef = new RexInputRef(leftPos, leftType);
+      final RexNode rightRef = new RexInputRef(valueGenFieldCount + rightPos, 
rightType);
+      conditions.add(relBuilder.isNotDistinctFrom(leftRef, rightRef));
+      newProjectMap.put(valueGenFieldCount + rightPos, leftRef);
+    }
+    final RexNode joinCond = 
RexUtil.composeConjunction(relBuilder.getRexBuilder(), conditions);
 
     // Build [08] LogicalJoin(condition=[IS NOT DISTINCT FROM($0, $1)], 
joinType=[left])
     // to ensure each corVar's aggregate result is output.
-    final RelNode join = relBuilder.push(newRel)
-        .join(JoinRelType.LEFT, conditions).build();
+    final RelNode join = relBuilder.push(valueGen).push(newRel)
+        .join(JoinRelType.LEFT, joinCond).build();
+    RelDataType joinRowType = join.getRowType();
 
+    RexBuilder rexBuilder = relBuilder.getRexBuilder();
+    // Here we record the mapping between the original index and the new 
project.
+    // For the count, we map it as `case when x is null then 0 else x`.
     for (int i1 = 0; i1 < oldRel.getAggCallList().size(); i1++) {
       AggregateCall aggCall = oldRel.getAggCallList().get(i1);
       if (aggCall.getAggregation() instanceof SqlCountAggFunction) {
         int index = requireNonNull(outputMap.get(i1 + 
oldRel.getGroupSet().size()));
-        final RexInputRef ref = RexInputRef.of(index + groupKeySize, 
join.getRowType());
-        RexNode specificCountValue =
-            rexBuilder.makeCall(SqlStdOperatorTable.CASE,
-                ImmutableList.of(relBuilder.isNotNull(ref), ref, 
relBuilder.literal(0)));
+        final RexInputRef ref = RexInputRef.of(index + valueGenFieldCount, 
joinRowType);
+        ImmutableList<RexNode> exprs =
+            ImmutableList.of(relBuilder.isNotNull(ref), ref, 
relBuilder.literal(0));
+        RexNode specificCountValue = 
rexBuilder.makeCall(SqlStdOperatorTable.CASE, exprs);
         newProjectMap.put(ref.getIndex(), specificCountValue);
       }
     }
 
+    // Build [07] LogicalProject(DEPTNO=[$0], EXPR$0=[CASE(IS NOT NULL($2), 
$2, 0)])
+    // to handle COUNT function by converting nulls to zero.
     final List<RexNode> newProjects = new ArrayList<>();
-    for (int index : ImmutableBitSet.range(groupKeySize, 
join.getRowType().getFieldCount())) {
+    for (int index : ImmutableBitSet.range(valueGenFieldCount, 
joinRowType.getFieldCount())) {
       if (newProjectMap.containsKey(index)) {
         newProjects.add(requireNonNull(newProjectMap.get(index)));
       } else {
-        newProjects.add(RexInputRef.of(index, join.getRowType()));
+        newProjects.add(RexInputRef.of(index, joinRowType));
       }
     }
 
-    // Build [07] LogicalProject(DEPTNO=[$0], EXPR$0=[CASE(IS NOT NULL($2), 
$2, 0)])
-    // to handle COUNT function by converting nulls to zero.
     return relBuilder.push(join)
         .project(newProjects, newRel.getRowType().getFieldNames())
         .build();
@@ -1184,6 +1176,144 @@ private static void shiftMapping(Map<Integer, Integer> 
mapping, int startIndex,
     return null;
   }
 
+  /**
+   * Given the SQL:
+   * SELECT ename,
+   *    (SELECT sum(c)
+   *    FROM
+   *        (SELECT deptno AS c
+   *        FROM dept
+   *        WHERE dept.deptno = emp.deptno
+   *        UNION ALL
+   *        SELECT 2 AS c
+   *        FROM bonus
+   *        WHERE bonus.job = emp.job) AS union_subquery
+   *    ) AS correlated_sum
+   * FROM emp;
+   *
+   * <p>from:
+   * LogicalUnion(all=[true])
+   *   LogicalProject(C=[CAST($0):INTEGER NOT NULL])
+   *     LogicalFilter(condition=[=($0, $cor0.DEPTNO)])
+   *       LogicalTableScan(table=[[scott, DEPT]])
+   *   LogicalProject(C=[2])
+   *     LogicalFilter(condition=[=($1, $cor0.JOB)])
+   *       LogicalTableScan(table=[[scott, BONUS]])
+   *
+   * <p>to:
+   * LogicalUnion(all=[true])
+   *   LogicalProject(JOB=[$0], DEPTNO=[$1], C=[$2])
+   *     LogicalJoin(condition=[IS NOT DISTINCT FROM($1, $3)], 
joinType=[inner])
+   *       LogicalAggregate(group=[{0, 1}])
+   *         LogicalProject(JOB=[$2], DEPTNO=[$7])
+   *           LogicalTableScan(table=[[scott, EMP]])
+   *       LogicalProject(C=[CAST($0):INTEGER NOT NULL], DEPTNO=[$0])
+   *         LogicalTableScan(table=[[scott, DEPT]])
+   *   LogicalProject(JOB=[$0], DEPTNO=[$1], C=[$2])
+   *     LogicalJoin(condition=[IS NOT DISTINCT FROM($0, $3)], 
joinType=[inner])
+   *       LogicalAggregate(group=[{0, 1}])
+   *         LogicalProject(JOB=[$2], DEPTNO=[$7])
+   *           LogicalTableScan(table=[[scott, EMP]])
+   *       LogicalProject(C=[2], JOB=[$1])
+   *         LogicalFilter(condition=[IS NOT NULL($1)])
+   *           LogicalTableScan(table=[[scott, BONUS]])
+   */
+  public @Nullable Frame decorrelateRel(SetOp rel, boolean isCorVarDefined,
+      boolean parentPropagatesNullValues) {
+    if (!isCorVarDefined) {
+      return decorrelateRel((RelNode) rel, false, parentPropagatesNullValues);
+    }
+
+    final CorelMap localCorelMap = new CorelMapBuilder().build(rel);
+    final List<CorRef> corVarList = new 
ArrayList<>(localCorelMap.mapRefRelToCorRef.values());
+    Collections.sort(corVarList);
+
+    final NavigableMap<CorDef, Integer> valueGenCorDefOutputs = new 
TreeMap<>();
+    final RelNode valueGen =
+        requireNonNull(createValueGenerator(corVarList, 0, 
valueGenCorDefOutputs));
+    final int valueGenFieldCount = valueGen.getRowType().getFieldCount();
+    // Original SetOp payload width.
+    final int payloadFieldCount = rel.getRowType().getFieldCount();
+    final List<RelNode> newInputs = new ArrayList<>();
+    final Map<Integer, Integer> setOpOldToNewOutputs = new HashMap<>();
+    final NavigableMap<CorDef, Integer> setOpCorDefOutputs = new TreeMap<>();
+
+    for (int i = 0; i < rel.getInputs().size(); i++) {
+      RelNode oldInput = rel.getInput(i);
+      Frame frame = getInvoke(oldInput, true, rel, parentPropagatesNullValues);
+      if (frame == null) {
+        // If input has not been rewritten, do not rewrite this rel.
+        return null;
+      }
+
+      // Build join conditions: for each CorDef of this branch that belongs
+      // to the current outFrameCorrId, equate valueGen(col) with branch(col).
+      final List<RexNode> conditions = new ArrayList<>();
+      for (Map.Entry<CorDef, Integer> e : frame.corDefOutputs.entrySet()) {
+        final CorDef corDef = e.getKey();
+        final int leftPos = requireNonNull(valueGenCorDefOutputs.get(corDef));
+        final int rightPos = e.getValue();
+        final RelDataType leftType = 
valueGen.getRowType().getFieldList().get(leftPos).getType();
+        final RelDataType rightType = 
frame.r.getRowType().getFieldList().get(rightPos).getType();
+        final RexNode leftRef = new RexInputRef(leftPos, leftType);
+        final RexNode rightRef = new RexInputRef(valueGenFieldCount + 
rightPos, rightType);
+        conditions.add(relBuilder.isNotDistinctFrom(leftRef, rightRef));
+      }
+      final RexNode joinCondition =
+          RexUtil.composeConjunction(relBuilder.getRexBuilder(), conditions);
+      RelNode join = relBuilder.push(valueGen).push(frame.r)
+              .join(JoinRelType.INNER, joinCondition).build();
+
+      final List<RelDataTypeField> joinFields = 
join.getRowType().getFieldList();
+
+      // Build the final projection for this branch:
+      // all correlated columns (from valueGen), original payload columns 
(from branch)
+      final PairList<RexNode, String> projects = PairList.of();
+      final Map<Integer, Integer> childOldToNew = new HashMap<>();
+      final NavigableMap<CorDef, Integer> childCorDefOutputs = new TreeMap<>();
+
+      // a) Correlated columns, in the order of valueGenCorDefOutputs.
+      int newPos = 0;
+      for (Map.Entry<CorDef, Integer> e : valueGenCorDefOutputs.entrySet()) {
+        final int srcIndex = e.getValue();
+        RexInputRef inputRef = RexInputRef.of(srcIndex, join.getRowType());
+        String name = joinFields.get(srcIndex).getName();
+
+        projects.add(inputRef, name);
+        childCorDefOutputs.put(e.getKey(), newPos);
+        newPos++;
+      }
+
+      // b) Original SetOp payload columns.
+      for (int oldIndex = 0; oldIndex < payloadFieldCount; oldIndex++) {
+        final Integer srcInFrame = 
requireNonNull(frame.oldToNewOutputs.get(oldIndex));
+        final int srcInJoin = valueGenFieldCount + srcInFrame;
+        RexInputRef inputRef = RexInputRef.of(srcInJoin, join.getRowType());
+        String name = joinFields.get(srcInJoin).getName();
+
+        projects.add(inputRef, name);
+        childOldToNew.put(oldIndex, newPos);
+        newPos++;
+      }
+
+      final RelNode newInput = relBuilder.push(join)
+          .projectNamed(projects.leftList(), projects.rightList(), true)
+          .build();
+      newInputs.add(newInput);
+
+      register(oldInput, newInput, childOldToNew, childCorDefOutputs);
+
+      // Use the first branch as prototype for the SetOp's frame mappings.
+      if (i == 0) {
+        setOpOldToNewOutputs.putAll(childOldToNew);
+        setOpCorDefOutputs.putAll(childCorDefOutputs);
+      }
+    }
+
+    final SetOp newSetOp = rel.copy(rel.getTraitSet(), newInputs, rel.all);
+    return register(rel, newSetOp, setOpOldToNewOutputs, setOpCorDefOutputs);
+  }
+
   public @Nullable Frame decorrelateRel(LogicalProject rel, boolean 
isCorVarDefined,
       boolean parentPropagatesNullValues) {
     return decorrelateRel((Project) rel, isCorVarDefined, 
parentPropagatesNullValues);
diff --git 
a/core/src/test/java/org/apache/calcite/sql2rel/RelDecorrelatorTest.java 
b/core/src/test/java/org/apache/calcite/sql2rel/RelDecorrelatorTest.java
index b92606be5b..80a3dda646 100644
--- a/core/src/test/java/org/apache/calcite/sql2rel/RelDecorrelatorTest.java
+++ b/core/src/test/java/org/apache/calcite/sql2rel/RelDecorrelatorTest.java
@@ -425,6 +425,421 @@ public static Frameworks.ConfigBuilder config() {
     assertThat(after, hasTree(planAfter));
   }
 
+  @Test void testCorrelationInSetOp0() {
+    final FrameworkConfig frameworkConfig = config().build();
+    final RelBuilder builder = RelBuilder.create(frameworkConfig);
+    final RelOptCluster cluster = builder.getCluster();
+    final Planner planner = Frameworks.getPlanner(frameworkConfig);
+    final String sql = "SELECT ename,\n"
+        + "    (SELECT sum(c)\n"
+        + "    FROM\n"
+        + "        (SELECT deptno AS c\n"
+        + "        FROM dept\n"
+        + "        WHERE dept.deptno = emp.deptno\n"
+        + "        UNION ALL\n"
+        + "        SELECT 2 AS c\n"
+        + "        FROM bonus) AS union_subquery\n"
+        + "    ) AS correlated_sum\n"
+        + "FROM emp\n"
+        + "ORDER BY ename";
+    final RelNode originalRel;
+    try {
+      final SqlNode parse = planner.parse(sql);
+      final SqlNode validate = planner.validate(parse);
+      originalRel = planner.rel(validate).rel;
+    } catch (Exception e) {
+      throw TestUtil.rethrow(e);
+    }
+
+    final HepProgram hepProgram = HepProgram.builder()
+        .addRuleCollection(
+            ImmutableList.of(
+                // SubQuery program rules
+                CoreRules.FILTER_SUB_QUERY_TO_CORRELATE,
+                CoreRules.PROJECT_SUB_QUERY_TO_CORRELATE,
+                CoreRules.JOIN_SUB_QUERY_TO_CORRELATE))
+        .build();
+    final Program program =
+        Programs.of(hepProgram, true,
+            requireNonNull(cluster.getMetadataProvider()));
+    final RelNode before =
+        program.run(cluster.getPlanner(), originalRel, cluster.traitSet(),
+            Collections.emptyList(), Collections.emptyList());
+    final String planBefore = ""
+        + "LogicalSort(sort0=[$0], dir0=[ASC])\n"
+        + "  LogicalProject(ENAME=[$1], CORRELATED_SUM=[$8])\n"
+        + "    LogicalCorrelate(correlation=[$cor0], joinType=[left], 
requiredColumns=[{7}])\n"
+        + "      LogicalTableScan(table=[[scott, EMP]])\n"
+        + "      LogicalAggregate(group=[{}], EXPR$0=[SUM($0)])\n"
+        + "        LogicalUnion(all=[true])\n"
+        + "          LogicalProject(C=[CAST($0):INTEGER NOT NULL])\n"
+        + "            LogicalFilter(condition=[=($0, $cor0.DEPTNO)])\n"
+        + "              LogicalTableScan(table=[[scott, DEPT]])\n"
+        + "          LogicalProject(C=[2])\n"
+        + "            LogicalTableScan(table=[[scott, BONUS]])\n";
+    assertThat(before, hasTree(planBefore));
+
+    // Decorrelate without any rules, just "purely" decorrelation algorithm on 
RelDecorrelator
+    final RelNode after =
+        RelDecorrelator.decorrelateQuery(before, builder, 
RuleSets.ofList(Collections.emptyList()),
+            RuleSets.ofList(Collections.emptyList()));
+    // Verify plan
+    final String planAfter = ""
+        + "LogicalSort(sort0=[$0], dir0=[ASC])\n"
+        + "  LogicalProject(ENAME=[$1], CORRELATED_SUM=[$9])\n"
+        + "    LogicalJoin(condition=[IS NOT DISTINCT FROM($7, $8)], 
joinType=[left])\n"
+        + "      LogicalTableScan(table=[[scott, EMP]])\n"
+        + "      LogicalAggregate(group=[{0}], EXPR$0=[SUM($1)])\n"
+        + "        LogicalProject(DEPTNO=[$0], C=[$1])\n"
+        + "          LogicalUnion(all=[true])\n"
+        + "            LogicalProject(DEPTNO=[$0], C=[$1])\n"
+        + "              LogicalJoin(condition=[IS NOT DISTINCT FROM($0, $2)], 
joinType=[inner])\n"
+        + "                LogicalAggregate(group=[{0}])\n"
+        + "                  LogicalProject(DEPTNO=[$7])\n"
+        + "                    LogicalTableScan(table=[[scott, EMP]])\n"
+        + "                LogicalProject(C=[CAST($0):INTEGER NOT NULL], 
DEPTNO=[$0])\n"
+        + "                  LogicalTableScan(table=[[scott, DEPT]])\n"
+        + "            LogicalProject(DEPTNO=[$0], C=[$1])\n"
+        + "              LogicalJoin(condition=[true], joinType=[inner])\n"
+        + "                LogicalAggregate(group=[{0}])\n"
+        + "                  LogicalProject(DEPTNO=[$7])\n"
+        + "                    LogicalTableScan(table=[[scott, EMP]])\n"
+        + "                LogicalProject(C=[2])\n"
+        + "                  LogicalTableScan(table=[[scott, BONUS]])\n";
+    assertThat(after, hasTree(planAfter));
+  }
+
+  /** Test case for <a 
href="https://issues.apache.org/jira/browse/CALCITE-7272";>[CALCITE-7272]
+   * Subqueries cannot be decorrelated if have set op</a>. */
+  @Test void testCorrelationInSetOp1() {
+    final FrameworkConfig frameworkConfig = config().build();
+    final RelBuilder builder = RelBuilder.create(frameworkConfig);
+    final RelOptCluster cluster = builder.getCluster();
+    final Planner planner = Frameworks.getPlanner(frameworkConfig);
+    final String sql = "SELECT ename,\n"
+        + "    (SELECT sum(c)\n"
+        + "    FROM\n"
+        + "        (SELECT deptno AS c\n"
+        + "        FROM dept\n"
+        + "        WHERE dept.deptno = emp.deptno\n"
+        + "        UNION ALL\n"
+        + "        SELECT 2 AS c\n"
+        + "        FROM bonus\n"
+        + "        WHERE bonus.job = emp.job) AS union_subquery\n"
+        + "    ) AS correlated_sum\n"
+        + "FROM emp\n"
+        + "ORDER BY ename";
+
+    final RelNode originalRel;
+    try {
+      final SqlNode parse = planner.parse(sql);
+      final SqlNode validate = planner.validate(parse);
+      originalRel = planner.rel(validate).rel;
+    } catch (Exception e) {
+      throw TestUtil.rethrow(e);
+    }
+
+    final HepProgram hepProgram = HepProgram.builder()
+        .addRuleCollection(
+            ImmutableList.of(
+                // SubQuery program rules
+                CoreRules.FILTER_SUB_QUERY_TO_CORRELATE,
+                CoreRules.PROJECT_SUB_QUERY_TO_CORRELATE,
+                CoreRules.JOIN_SUB_QUERY_TO_CORRELATE))
+        .build();
+    final Program program =
+        Programs.of(hepProgram, true,
+            requireNonNull(cluster.getMetadataProvider()));
+    final RelNode before =
+        program.run(cluster.getPlanner(), originalRel, cluster.traitSet(),
+            Collections.emptyList(), Collections.emptyList());
+    final String planBefore = ""
+        + "LogicalSort(sort0=[$0], dir0=[ASC])\n"
+        + "  LogicalProject(ENAME=[$1], CORRELATED_SUM=[$8])\n"
+        + "    LogicalCorrelate(correlation=[$cor0], joinType=[left], 
requiredColumns=[{2, 7}])\n"
+        + "      LogicalTableScan(table=[[scott, EMP]])\n"
+        + "      LogicalAggregate(group=[{}], EXPR$0=[SUM($0)])\n"
+        + "        LogicalUnion(all=[true])\n"
+        + "          LogicalProject(C=[CAST($0):INTEGER NOT NULL])\n"
+        + "            LogicalFilter(condition=[=($0, $cor0.DEPTNO)])\n"
+        + "              LogicalTableScan(table=[[scott, DEPT]])\n"
+        + "          LogicalProject(C=[2])\n"
+        + "            LogicalFilter(condition=[=($1, $cor0.JOB)])\n"
+        + "              LogicalTableScan(table=[[scott, BONUS]])\n";
+    assertThat(before, hasTree(planBefore));
+
+    // Decorrelate without any rules, just "purely" decorrelation algorithm on 
RelDecorrelator
+    final RelNode after =
+        RelDecorrelator.decorrelateQuery(before, builder, 
RuleSets.ofList(Collections.emptyList()),
+            RuleSets.ofList(Collections.emptyList()));
+    // Verify plan
+    final String planAfter = ""
+        + "LogicalSort(sort0=[$0], dir0=[ASC])\n"
+        + "  LogicalProject(ENAME=[$1], CORRELATED_SUM=[$10])\n"
+        + "    LogicalJoin(condition=[AND(IS NOT DISTINCT FROM($2, $8), IS NOT 
DISTINCT FROM($7, $9))], joinType=[left])\n"
+        + "      LogicalTableScan(table=[[scott, EMP]])\n"
+        + "      LogicalAggregate(group=[{0, 1}], EXPR$0=[SUM($2)])\n"
+        + "        LogicalProject(JOB=[$0], DEPTNO=[$1], C=[$2])\n"
+        + "          LogicalUnion(all=[true])\n"
+        + "            LogicalProject(JOB=[$0], DEPTNO=[$1], C=[$2])\n"
+        + "              LogicalJoin(condition=[IS NOT DISTINCT FROM($1, $3)], 
joinType=[inner])\n"
+        + "                LogicalAggregate(group=[{0, 1}])\n"
+        + "                  LogicalProject(JOB=[$2], DEPTNO=[$7])\n"
+        + "                    LogicalTableScan(table=[[scott, EMP]])\n"
+        + "                LogicalProject(C=[CAST($0):INTEGER NOT NULL], 
DEPTNO=[$0])\n"
+        + "                  LogicalTableScan(table=[[scott, DEPT]])\n"
+        + "            LogicalProject(JOB=[$0], DEPTNO=[$1], C=[$2])\n"
+        + "              LogicalJoin(condition=[IS NOT DISTINCT FROM($0, $3)], 
joinType=[inner])\n"
+        + "                LogicalAggregate(group=[{0, 1}])\n"
+        + "                  LogicalProject(JOB=[$2], DEPTNO=[$7])\n"
+        + "                    LogicalTableScan(table=[[scott, EMP]])\n"
+        + "                LogicalProject(C=[2], JOB=[$1])\n"
+        + "                  LogicalFilter(condition=[IS NOT NULL($1)])\n"
+        + "                    LogicalTableScan(table=[[scott, BONUS]])\n";
+    assertThat(after, hasTree(planAfter));
+  }
+
+  /** Test case for <a 
href="https://issues.apache.org/jira/browse/CALCITE-7272";>[CALCITE-7272]
+   * Subqueries cannot be decorrelated if have set op</a>. */
+  @Test void testCorrelationInSetOp2() {
+    final FrameworkConfig frameworkConfig = config().build();
+    final RelBuilder builder = RelBuilder.create(frameworkConfig);
+    final RelOptCluster cluster = builder.getCluster();
+    final Planner planner = Frameworks.getPlanner(frameworkConfig);
+    final String sql = "SELECT d.dname\n"
+        + "FROM dept d\n"
+        + "WHERE EXISTS (\n"
+        + "  SELECT 1\n"
+        + "  FROM emp e\n"
+        + "  WHERE e.deptno = d.deptno\n"
+        + "  AND (\n"
+        + "    SELECT SUM(x)\n"
+        + "    FROM (\n"
+        + "        SELECT COUNT(*) as x\n"
+        + "        FROM bonus b\n"
+        + "        WHERE b.ename = e.ename\n"
+        + "        UNION ALL\n"
+        + "        SELECT COUNT(*) as x\n"
+        + "        FROM emp e2\n"
+        + "        WHERE e2.deptno = d.deptno\n"
+        + "    ) t\n"
+        + "  ) > 5)";
+    final RelNode originalRel;
+    try {
+      final SqlNode parse = planner.parse(sql);
+      final SqlNode validate = planner.validate(parse);
+      originalRel = planner.rel(validate).rel;
+    } catch (Exception e) {
+      throw TestUtil.rethrow(e);
+    }
+
+    final HepProgram hepProgram = HepProgram.builder()
+        .addRuleCollection(
+            ImmutableList.of(
+                // SubQuery program rules
+                CoreRules.FILTER_SUB_QUERY_TO_CORRELATE,
+                CoreRules.PROJECT_SUB_QUERY_TO_CORRELATE,
+                CoreRules.JOIN_SUB_QUERY_TO_CORRELATE))
+        .build();
+    final Program program =
+        Programs.of(hepProgram, true,
+            requireNonNull(cluster.getMetadataProvider()));
+    final RelNode before =
+        program.run(cluster.getPlanner(), originalRel, cluster.traitSet(),
+            Collections.emptyList(), Collections.emptyList());
+    final String planBefore = ""
+        + "LogicalProject(DNAME=[$1])\n"
+        + "  LogicalProject(DEPTNO=[$0], DNAME=[$1], LOC=[$2])\n"
+        + "    LogicalCorrelate(correlation=[$cor0], joinType=[inner], 
requiredColumns=[{0}])\n"
+        + "      LogicalTableScan(table=[[scott, DEPT]])\n"
+        + "      LogicalAggregate(group=[{0}])\n"
+        + "        LogicalProject(i=[true])\n"
+        + "          LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], 
MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7])\n"
+        + "            LogicalFilter(condition=[AND(=($7, $cor0.DEPTNO), >($8, 
5))])\n"
+        + "              LogicalCorrelate(correlation=[$cor1], 
joinType=[left], requiredColumns=[{1}])\n"
+        + "                LogicalTableScan(table=[[scott, EMP]])\n"
+        + "                LogicalAggregate(group=[{}], EXPR$0=[SUM($0)])\n"
+        + "                  LogicalUnion(all=[true])\n"
+        + "                    LogicalAggregate(group=[{}], X=[COUNT()])\n"
+        + "                      LogicalFilter(condition=[=($0, 
$cor1.ENAME)])\n"
+        + "                        LogicalTableScan(table=[[scott, BONUS]])\n"
+        + "                    LogicalAggregate(group=[{}], X=[COUNT()])\n"
+        + "                      LogicalFilter(condition=[=($7, 
$cor0.DEPTNO)])\n"
+        + "                        LogicalTableScan(table=[[scott, EMP]])\n";
+    assertThat(before, hasTree(planBefore));
+
+    // Decorrelate without any rules, just "purely" decorrelation algorithm on 
RelDecorrelator
+    final RelNode after =
+        RelDecorrelator.decorrelateQuery(before, builder, 
RuleSets.ofList(Collections.emptyList()),
+            RuleSets.ofList(Collections.emptyList()));
+    // Verify plan
+    final String planAfter = ""
+        + "LogicalProject(DNAME=[$1])\n"
+        + "  LogicalJoin(condition=[=($0, $3)], joinType=[inner])\n"
+        + "    LogicalTableScan(table=[[scott, DEPT]])\n"
+        + "    LogicalProject(DEPTNO0=[$0], $f1=[true])\n"
+        + "      LogicalAggregate(group=[{0}])\n"
+        + "        LogicalProject(DEPTNO0=[$8])\n"
+        + "          LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], 
MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], 
DEPTNO0=[CAST($8):TINYINT], ENAME0=[$9], EXPR$0=[CAST($10):BIGINT])\n"
+        + "            LogicalJoin(condition=[AND(IS NOT DISTINCT FROM($1, 
$9), =($7, $8))], joinType=[inner])\n"
+        + "              LogicalTableScan(table=[[scott, EMP]])\n"
+        + "              LogicalFilter(condition=[>($2, 5)])\n"
+        + "                LogicalAggregate(group=[{0, 1}], 
EXPR$0=[SUM($2)])\n"
+        + "                  LogicalProject(DEPTNO=[$0], ENAME=[$1], X=[$2])\n"
+        + "                    LogicalUnion(all=[true])\n"
+        + "                      LogicalProject(DEPTNO=[$0], ENAME=[$1], 
X=[$3])\n"
+        + "                        LogicalJoin(condition=[IS NOT DISTINCT 
FROM($1, $2)], joinType=[inner])\n"
+        + "                          LogicalJoin(condition=[true], 
joinType=[inner])\n"
+        + "                            LogicalProject(DEPTNO=[$0])\n"
+        + "                              LogicalTableScan(table=[[scott, 
DEPT]])\n"
+        + "                            LogicalProject(ENAME=[$1])\n"
+        + "                              LogicalTableScan(table=[[scott, 
EMP]])\n"
+        + "                          LogicalProject(ENAME=[$0], X=[CASE(IS NOT 
NULL($2), $2, 0)])\n"
+        + "                            LogicalJoin(condition=[IS NOT DISTINCT 
FROM($0, $1)], joinType=[left])\n"
+        + "                              LogicalProject(ENAME=[$1])\n"
+        + "                                LogicalTableScan(table=[[scott, 
EMP]])\n"
+        + "                              LogicalAggregate(group=[{0}], 
X=[COUNT()])\n"
+        + "                                LogicalProject(ENAME=[$0])\n"
+        + "                                  LogicalFilter(condition=[IS NOT 
NULL($0)])\n"
+        + "                                    LogicalTableScan(table=[[scott, 
BONUS]])\n"
+        + "                      LogicalProject(DEPTNO=[$0], ENAME=[$1], 
X=[$3])\n"
+        + "                        LogicalJoin(condition=[IS NOT DISTINCT 
FROM($0, $2)], joinType=[inner])\n"
+        + "                          LogicalJoin(condition=[true], 
joinType=[inner])\n"
+        + "                            LogicalProject(DEPTNO=[$0])\n"
+        + "                              LogicalTableScan(table=[[scott, 
DEPT]])\n"
+        + "                            LogicalProject(ENAME=[$1])\n"
+        + "                              LogicalTableScan(table=[[scott, 
EMP]])\n"
+        + "                          LogicalProject(DEPTNO=[$0], X=[CASE(IS 
NOT NULL($2), $2, 0)])\n"
+        + "                            LogicalJoin(condition=[IS NOT DISTINCT 
FROM($0, $1)], joinType=[left])\n"
+        + "                              LogicalProject(DEPTNO=[$0])\n"
+        + "                                LogicalTableScan(table=[[scott, 
DEPT]])\n"
+        + "                              LogicalAggregate(group=[{0}], 
X=[COUNT()])\n"
+        + "                                LogicalProject(DEPTNO=[$7])\n"
+        + "                                  LogicalFilter(condition=[IS NOT 
NULL($7)])\n"
+        + "                                    LogicalTableScan(table=[[scott, 
EMP]])\n";
+    assertThat(after, hasTree(planAfter));
+  }
+
+  /** Test case for <a 
href="https://issues.apache.org/jira/browse/CALCITE-7272";>[CALCITE-7272]
+   * Subqueries cannot be decorrelated if have set op</a>. */
+  @Test void testCorrelationInSetOp3() {
+    final FrameworkConfig frameworkConfig = config().build();
+    final RelBuilder builder = RelBuilder.create(frameworkConfig);
+    final RelOptCluster cluster = builder.getCluster();
+    final Planner planner = Frameworks.getPlanner(frameworkConfig);
+    final String sql = "SELECT d.dname\n"
+        + "FROM dept d\n"
+        + "WHERE EXISTS (\n"
+        + "  SELECT 1\n"
+        + "  FROM emp e\n"
+        + "  WHERE (\n"
+        + "    SELECT SUM(x)\n"
+        + "    FROM (\n"
+        + "        SELECT COUNT(*) as x\n"
+        + "        FROM bonus b\n"
+        + "        WHERE b.ename = e.ename\n"
+        + "        UNION ALL\n"
+        + "        SELECT COUNT(*) as x\n"
+        + "        FROM emp e2\n"
+        + "        WHERE e2.deptno = d.deptno\n"
+        + "    ) t\n"
+        + "  ) > 5)";
+    final RelNode originalRel;
+    try {
+      final SqlNode parse = planner.parse(sql);
+      final SqlNode validate = planner.validate(parse);
+      originalRel = planner.rel(validate).rel;
+    } catch (Exception e) {
+      throw TestUtil.rethrow(e);
+    }
+
+    final HepProgram hepProgram = HepProgram.builder()
+        .addRuleCollection(
+            ImmutableList.of(
+                // SubQuery program rules
+                CoreRules.FILTER_SUB_QUERY_TO_CORRELATE,
+                CoreRules.PROJECT_SUB_QUERY_TO_CORRELATE,
+                CoreRules.JOIN_SUB_QUERY_TO_CORRELATE))
+        .build();
+    final Program program =
+        Programs.of(hepProgram, true,
+            requireNonNull(cluster.getMetadataProvider()));
+    final RelNode before =
+        program.run(cluster.getPlanner(), originalRel, cluster.traitSet(),
+            Collections.emptyList(), Collections.emptyList());
+    final String planBefore = ""
+        + "LogicalProject(DNAME=[$1])\n"
+        + "  LogicalProject(DEPTNO=[$0], DNAME=[$1], LOC=[$2])\n"
+        + "    LogicalCorrelate(correlation=[$cor1], joinType=[inner], 
requiredColumns=[{0}])\n"
+        + "      LogicalTableScan(table=[[scott, DEPT]])\n"
+        + "      LogicalAggregate(group=[{0}])\n"
+        + "        LogicalProject(i=[true])\n"
+        + "          LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], 
MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7])\n"
+        + "            LogicalFilter(condition=[>($8, 5)])\n"
+        + "              LogicalCorrelate(correlation=[$cor0], 
joinType=[left], requiredColumns=[{1}])\n"
+        + "                LogicalTableScan(table=[[scott, EMP]])\n"
+        + "                LogicalAggregate(group=[{}], EXPR$0=[SUM($0)])\n"
+        + "                  LogicalUnion(all=[true])\n"
+        + "                    LogicalAggregate(group=[{}], X=[COUNT()])\n"
+        + "                      LogicalFilter(condition=[=($0, 
$cor0.ENAME)])\n"
+        + "                        LogicalTableScan(table=[[scott, BONUS]])\n"
+        + "                    LogicalAggregate(group=[{}], X=[COUNT()])\n"
+        + "                      LogicalFilter(condition=[=($7, 
$cor1.DEPTNO)])\n"
+        + "                        LogicalTableScan(table=[[scott, EMP]])\n";
+    assertThat(before, hasTree(planBefore));
+
+    // Decorrelate without any rules, just "purely" decorrelation algorithm on 
RelDecorrelator
+    final RelNode after =
+        RelDecorrelator.decorrelateQuery(before, builder, 
RuleSets.ofList(Collections.emptyList()),
+            RuleSets.ofList(Collections.emptyList()));
+    // Verify plan
+    final String planAfter = ""
+        + "LogicalProject(DNAME=[$1])\n"
+        + "  LogicalJoin(condition=[IS NOT DISTINCT FROM($0, $3)], 
joinType=[inner])\n"
+        + "    LogicalTableScan(table=[[scott, DEPT]])\n"
+        + "    LogicalProject(DEPTNO0=[$0], $f1=[true])\n"
+        + "      LogicalAggregate(group=[{0}])\n"
+        + "        LogicalProject(DEPTNO0=[$9])\n"
+        + "          LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], 
MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], ENAME0=[$8], 
DEPTNO0=[CAST($9):TINYINT], EXPR$0=[CAST($10):BIGINT])\n"
+        + "            LogicalJoin(condition=[IS NOT DISTINCT FROM($1, $8)], 
joinType=[inner])\n"
+        + "              LogicalTableScan(table=[[scott, EMP]])\n"
+        + "              LogicalFilter(condition=[>($2, 5)])\n"
+        + "                LogicalAggregate(group=[{0, 1}], 
EXPR$0=[SUM($2)])\n"
+        + "                  LogicalProject(ENAME=[$0], DEPTNO=[$1], X=[$2])\n"
+        + "                    LogicalUnion(all=[true])\n"
+        + "                      LogicalProject(ENAME=[$0], DEPTNO=[$1], 
X=[$3])\n"
+        + "                        LogicalJoin(condition=[IS NOT DISTINCT 
FROM($0, $2)], joinType=[inner])\n"
+        + "                          LogicalJoin(condition=[true], 
joinType=[inner])\n"
+        + "                            LogicalProject(ENAME=[$1])\n"
+        + "                              LogicalTableScan(table=[[scott, 
EMP]])\n"
+        + "                            LogicalProject(DEPTNO=[$0])\n"
+        + "                              LogicalTableScan(table=[[scott, 
DEPT]])\n"
+        + "                          LogicalProject(ENAME=[$0], X=[CASE(IS NOT 
NULL($2), $2, 0)])\n"
+        + "                            LogicalJoin(condition=[IS NOT DISTINCT 
FROM($0, $1)], joinType=[left])\n"
+        + "                              LogicalProject(ENAME=[$1])\n"
+        + "                                LogicalTableScan(table=[[scott, 
EMP]])\n"
+        + "                              LogicalAggregate(group=[{0}], 
X=[COUNT()])\n"
+        + "                                LogicalProject(ENAME=[$0])\n"
+        + "                                  LogicalFilter(condition=[IS NOT 
NULL($0)])\n"
+        + "                                    LogicalTableScan(table=[[scott, 
BONUS]])\n"
+        + "                      LogicalProject(ENAME=[$0], DEPTNO=[$1], 
X=[$3])\n"
+        + "                        LogicalJoin(condition=[IS NOT DISTINCT 
FROM($1, $2)], joinType=[inner])\n"
+        + "                          LogicalJoin(condition=[true], 
joinType=[inner])\n"
+        + "                            LogicalProject(ENAME=[$1])\n"
+        + "                              LogicalTableScan(table=[[scott, 
EMP]])\n"
+        + "                            LogicalProject(DEPTNO=[$0])\n"
+        + "                              LogicalTableScan(table=[[scott, 
DEPT]])\n"
+        + "                          LogicalProject(DEPTNO=[$0], X=[CASE(IS 
NOT NULL($2), $2, 0)])\n"
+        + "                            LogicalJoin(condition=[IS NOT DISTINCT 
FROM($0, $1)], joinType=[left])\n"
+        + "                              LogicalProject(DEPTNO=[$0])\n"
+        + "                                LogicalTableScan(table=[[scott, 
DEPT]])\n"
+        + "                              LogicalAggregate(group=[{0}], 
X=[COUNT()])\n"
+        + "                                LogicalProject(DEPTNO=[$7])\n"
+        + "                                  LogicalFilter(condition=[IS NOT 
NULL($7)])\n"
+        + "                                    LogicalTableScan(table=[[scott, 
EMP]])\n";
+    assertThat(after, hasTree(planAfter));
+  }
+
   /**
    * Test case for
    * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6468";>[CALCITE-6468] 
RelDecorrelator
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 e651fcd74e..2eafe44bd8 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -17372,8 +17372,9 @@ LogicalProject(EXPR$0=[CAST(OR(AND(IS TRUE(>($0, $9)), 
IS NOT TRUE(OR(IS NULL($1
     LogicalTableScan(table=[[CATALOG, SALES, EMP]])
     LogicalProject(m=[$2], c=[CASE(IS NOT NULL($3), $3, 0)], d=[CASE(IS NOT 
NULL($3), $3, 0)], trueLiteral=[$4], NAME=[$0])
       LogicalJoin(condition=[IS NOT DISTINCT FROM($0, $1)], joinType=[left])
-        LogicalAggregate(group=[{2}])
-          LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+        LogicalAggregate(group=[{0}])
+          LogicalProject(JOB=[$2])
+            LogicalTableScan(table=[[CATALOG, SALES, EMP]])
         LogicalAggregate(group=[{0}], m=[MIN($1)], c=[COUNT()], 
trueLiteral=[LITERAL_AGG(true)])
           LogicalProject(NAME=[$1], DEPTNO=[$0])
             LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
@@ -21626,8 +21627,9 @@ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], 
MGR=[$3], HIREDATE=[$4], SAL=[$
       LogicalTableScan(table=[[CATALOG, SALES, EMP]])
       LogicalProject(m=[$2], c=[CASE(IS NOT NULL($3), $3, 0)], d=[CASE(IS NOT 
NULL($3), $3, 0)], trueLiteral=[$4], NAME=[$0])
         LogicalJoin(condition=[IS NOT DISTINCT FROM($0, $1)], joinType=[left])
-          LogicalAggregate(group=[{2}])
-            LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+          LogicalAggregate(group=[{0}])
+            LogicalProject(JOB=[$2])
+              LogicalTableScan(table=[[CATALOG, SALES, EMP]])
           LogicalAggregate(group=[{0}], m=[MIN($1)], c=[COUNT()], 
trueLiteral=[LITERAL_AGG(true)])
             LogicalProject(NAME=[$1], DEPTNO=[$0])
               LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
diff --git a/core/src/test/resources/sql/sub-query.iq 
b/core/src/test/resources/sql/sub-query.iq
index 9f320c7ef0..47f8f6497d 100644
--- a/core/src/test/resources/sql/sub-query.iq
+++ b/core/src/test/resources/sql/sub-query.iq
@@ -5619,4 +5619,1189 @@ where c+d=a*c);
 (2 rows)
 
 !ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+WITH
+  customers(id, name, city) AS (
+    VALUES
+      (1, 'Alice', 'New York'),
+      (2, 'Bob', 'San Francisco'),
+      (3, 'Charlie', 'Los Angeles')
+  ),
+  orders(id, customer_id, total_amount) AS (
+    VALUES
+      (100, 1, 500.00),
+      (101, 2, 150.00),
+      (102, 1, 300.00)
+  ),
+  lineitems(id, order_id, product_name, price) AS (
+    VALUES
+      (1, 100, 'Laptop', 1000.00),
+      (2, 100, 'Mouse', 20.00),
+      (3, 100, 'Keyboard', 50.00),
+      (4, 101, 'Monitor', 150.00)
+  ),
+  payments(id, customer_id, amount) AS (
+    VALUES
+      (1, 1, 200.00),
+      (2, 1, 200.00),
+      (3, 1, 100.00),
+      (4, 2, 150.00)
+  )
+SELECT c.id, c.name
+FROM customers c
+WHERE EXISTS (
+  SELECT 1
+  FROM orders o
+  WHERE o.customer_id = c.id
+    AND (
+      SELECT SUM(cnt)
+      FROM (
+        SELECT COUNT(*) AS cnt
+        FROM lineitems li
+        WHERE li.order_id = o.id
+        UNION ALL
+        SELECT COUNT(*) AS cnt
+        FROM payments p
+        WHERE p.customer_id = c.id
+      ) AS union_sub
+    ) > 5
+);
++----+---------+
+| ID | NAME    |
++----+---------+
+|  1 | Alice   |
++----+---------+
+(1 row)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+SELECT d.dname
+FROM dept d
+WHERE EXISTS (
+  SELECT 1
+  FROM emp e
+  WHERE e.deptno = d.deptno
+  AND (
+    SELECT SUM(x)
+    FROM (
+        SELECT COUNT(*) as x
+        FROM bonus b
+        WHERE b.ename = e.ename
+        UNION ALL
+        SELECT COUNT(*) as x
+        FROM emp e2
+        WHERE e2.deptno = d.deptno
+    ) t
+  ) > 5
+);
++-------+
+| DNAME |
++-------+
+| SALES |
++-------+
+(1 row)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+SELECT d.dname
+FROM dept d
+WHERE EXISTS (
+  SELECT 1
+  FROM emp e
+  WHERE (
+    SELECT SUM(x)
+    FROM (
+        SELECT COUNT(*) as x
+        FROM bonus b
+        WHERE b.ename = e.ename
+        UNION ALL
+        SELECT COUNT(*) as x
+        FROM emp e2
+        WHERE e2.deptno = d.deptno
+    ) t
+  ) > 5
+);
++-------+
+| DNAME |
++-------+
+| SALES |
++-------+
+(1 row)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+SELECT ename,
+    (SELECT sum(c)
+    FROM
+        (SELECT deptno AS c
+        FROM dept
+        WHERE dept.deptno = emp.deptno
+        UNION ALL
+        SELECT 2 AS c
+        FROM bonus
+        WHERE bonus.job = emp.job) AS union_subquery
+    ) AS correlated_sum
+FROM emp
+ORDER BY ename;
++--------+----------------+
+| ENAME  | CORRELATED_SUM |
++--------+----------------+
+| ADAMS  |             20 |
+| ALLEN  |             30 |
+| BLAKE  |             30 |
+| CLARK  |             10 |
+| FORD   |             20 |
+| JAMES  |             30 |
+| JONES  |             20 |
+| KING   |             10 |
+| MARTIN |             30 |
+| MILLER |             10 |
+| SCOTT  |             20 |
+| SMITH  |             20 |
+| TURNER |             30 |
+| WARD   |             30 |
++--------+----------------+
+(14 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+SELECT ename,
+    (SELECT sum(c)
+    FROM
+        (SELECT deptno AS c
+        FROM dept
+        WHERE dept.deptno = emp.deptno
+        UNION ALL
+        SELECT 2 AS c
+        FROM bonus) AS union_subquery
+    ) AS correlated_sum
+FROM emp
+ORDER BY ename;
++--------+----------------+
+| ENAME  | CORRELATED_SUM |
++--------+----------------+
+| ADAMS  |             20 |
+| ALLEN  |             30 |
+| BLAKE  |             30 |
+| CLARK  |             10 |
+| FORD   |             20 |
+| JAMES  |             30 |
+| JONES  |             20 |
+| KING   |             10 |
+| MARTIN |             30 |
+| MILLER |             10 |
+| SCOTT  |             20 |
+| SMITH  |             20 |
+| TURNER |             30 |
+| WARD   |             30 |
++--------+----------------+
+(14 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+SELECT *,
+  (SELECT COUNT(*)
+   FROM (
+     SELECT * FROM emp WHERE emp.deptno = dept.deptno
+     UNION ALL
+     SELECT * FROM emp) AS sub
+   GROUP BY deptno) AS num_dept_groups
+FROM dept;
+more than one value in agg SINGLE_VALUE
+!error
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a = t0a
+  UNION ALL
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      8 |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a = t0a
+  UNION ALL
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+);
++-----+-----+
+| T0A | T0B |
++-----+-----+
+|   1 |   1 |
++-----+-----+
+(1 row)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a = t0a
+  UNION ALL
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2a = t0a) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      8 |
+|   2 |      7 |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a > t0a
+  UNION ALL
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2b <= t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      5 |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(t1c) FROM
+  (SELECT t1c
+  FROM   t1
+  WHERE  t1a = t0a
+  UNION ALL
+  SELECT t2c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      8 |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT count(t1c) FROM
+  (SELECT t1c
+  FROM   t1
+  WHERE  t1a = t0a
+  UNION ALL
+  SELECT t2c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      2 |
+|   2 |      0 |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(d) FROM
+  (SELECT t1a - t0a as d
+  FROM   t1
+  UNION ALL
+  SELECT t2a - t0a as d
+  FROM   t2) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      1 |
+|   2 |     -2 |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a = t0a
+  UNION DISTINCT
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      8 |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a = t0a
+  UNION DISTINCT
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+);
++-----+-----+
+| T0A | T0B |
++-----+-----+
+|   1 |   1 |
++-----+-----+
+(1 row)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a = t0a
+  UNION DISTINCT
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2a = t0a) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      8 |
+|   2 |      7 |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a > t0a
+  UNION DISTINCT
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2b <= t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      5 |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(t1c) FROM
+  (SELECT t1c
+  FROM   t1
+  WHERE  t1a = t0a
+  UNION DISTINCT
+  SELECT t2c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      8 |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT count(t1c) FROM
+  (SELECT t1c
+  FROM   t1
+  WHERE  t1a = t0a
+  UNION DISTINCT
+  SELECT t2c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      2 |
+|   2 |      0 |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(d) FROM
+  (SELECT t1a - t0a as d
+  FROM   t1
+  UNION DISTINCT
+  SELECT t2a - t0a as d
+  FROM   t2) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      1 |
+|   2 |     -1 |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a = t0a
+  INTERSECT ALL
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |        |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a = t0a
+  INTERSECT ALL
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+);
++-----+-----+
+| T0A | T0B |
++-----+-----+
++-----+-----+
+(0 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a = t0a
+  INTERSECT ALL
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2a = t0a) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |        |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a > t0a
+  INTERSECT ALL
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2b <= t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |        |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(t1c) FROM
+  (SELECT t1c
+  FROM   t1
+  WHERE  t1a = t0a
+  INTERSECT ALL
+  SELECT t2c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |        |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT count(t1c) FROM
+  (SELECT t1c
+  FROM   t1
+  WHERE  t1a = t0a
+  INTERSECT ALL
+  SELECT t2c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      0 |
+|   2 |      0 |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(d) FROM
+  (SELECT t1a - t0a as d
+  FROM   t1
+  INTERSECT ALL
+  SELECT t2a - t0a as d
+  FROM   t2) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      0 |
+|   2 |     -1 |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a = t0a
+  INTERSECT DISTINCT
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |        |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a = t0a
+  INTERSECT DISTINCT
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+);
++-----+-----+
+| T0A | T0B |
++-----+-----+
++-----+-----+
+(0 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a = t0a
+  INTERSECT DISTINCT
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2a = t0a) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |        |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a > t0a
+  INTERSECT DISTINCT
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2b <= t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |        |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(t1c) FROM
+  (SELECT t1c
+  FROM   t1
+  WHERE  t1a = t0a
+  INTERSECT DISTINCT
+  SELECT t2c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |        |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT count(t1c) FROM
+  (SELECT t1c
+  FROM   t1
+  WHERE  t1a = t0a
+  INTERSECT DISTINCT
+  SELECT t2c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      0 |
+|   2 |      0 |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(d) FROM
+  (SELECT t1a - t0a as d
+  FROM   t1
+  INTERSECT DISTINCT
+  SELECT t2a - t0a as d
+  FROM   t2) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      0 |
+|   2 |     -1 |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a = t0a
+  EXCEPT ALL
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      3 |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a = t0a
+  EXCEPT ALL
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+);
++-----+-----+
+| T0A | T0B |
++-----+-----+
+|   1 |   1 |
++-----+-----+
+(1 row)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a = t0a
+  EXCEPT ALL
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2a = t0a) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      3 |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a > t0a
+  EXCEPT ALL
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2b <= t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |        |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(t1c) FROM
+  (SELECT t1c
+  FROM   t1
+  WHERE  t1a = t0a
+  EXCEPT ALL
+  SELECT t2c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      3 |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT count(t1c) FROM
+  (SELECT t1c
+  FROM   t1
+  WHERE  t1a = t0a
+  EXCEPT ALL
+  SELECT t2c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      1 |
+|   2 |      0 |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(d) FROM
+  (SELECT t1a - t0a as d
+  FROM   t1
+  EXCEPT ALL
+  SELECT t2a - t0a as d
+  FROM   t2) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |        |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a = t0a
+  EXCEPT DISTINCT
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      3 |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a = t0a
+  EXCEPT DISTINCT
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+);
++-----+-----+
+| T0A | T0B |
++-----+-----+
+|   1 |   1 |
++-----+-----+
+(1 row)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a = t0a
+  EXCEPT DISTINCT
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2a = t0a) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      3 |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(c) FROM
+  (SELECT t1c as c
+  FROM   t1
+  WHERE  t1a > t0a
+  EXCEPT DISTINCT
+  SELECT t2c as c
+  FROM   t2
+  WHERE  t2b <= t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |        |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(t1c) FROM
+  (SELECT t1c
+  FROM   t1
+  WHERE  t1a = t0a
+  EXCEPT DISTINCT
+  SELECT t2c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      3 |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT count(t1c) FROM
+  (SELECT t1c
+  FROM   t1
+  WHERE  t1a = t0a
+  EXCEPT DISTINCT
+  SELECT t2c
+  FROM   t2
+  WHERE  t2b = t0b) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |      1 |
+|   2 |      0 |
++-----+--------+
+(2 rows)
+
+!ok
+
+# [CALCITE-7272] Subqueries cannot be decorrelated if have set op
+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 t0a, (SELECT sum(d) FROM
+  (SELECT t1a - t0a as d
+  FROM   t1
+  EXCEPT DISTINCT
+  SELECT t2a - t0a as d
+  FROM   t2) as tmp
+)
+FROM t0;
++-----+--------+
+| T0A | EXPR$1 |
++-----+--------+
+|   1 |        |
+|   2 |        |
++-----+--------+
+(2 rows)
+
+!ok
+
 # End sub-query.iq

Reply via email to