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

rubenql 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 0a13d9905a [CALCITE-6652] RelDecorrelator can't decorrelate query with 
limit 1
0a13d9905a is described below

commit 0a13d9905a1620b4b1ff1ab710dead8d32852c59
Author: suibianwanwan <[email protected]>
AuthorDate: Fri Feb 14 18:46:10 2025 +0800

    [CALCITE-6652] RelDecorrelator can't decorrelate query with limit 1
---
 .../apache/calcite/sql2rel/RelDecorrelator.java    | 166 ++++++++-
 .../main/java/org/apache/calcite/util/Util.java    |   2 +-
 .../org/apache/calcite/test/RelOptRulesTest.java   | 105 ++++++
 .../org/apache/calcite/test/RelOptRulesTest.xml    | 400 +++++++++++++++++++++
 .../apache/calcite/test/SqlToRelConverterTest.xml  |  18 +-
 core/src/test/resources/sql/sub-query.iq           | 346 +++++++++++++++---
 6 files changed, 975 insertions(+), 62 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 6a7376f132..0f0eb0cdc3 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/RelDecorrelator.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/RelDecorrelator.java
@@ -31,6 +31,7 @@
 import org.apache.calcite.plan.hep.HepRelVertex;
 import org.apache.calcite.rel.BiRel;
 import org.apache.calcite.rel.RelCollation;
+import org.apache.calcite.rel.RelFieldCollation;
 import org.apache.calcite.rel.RelHomogeneousShuttle;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.Aggregate;
@@ -73,6 +74,7 @@
 import org.apache.calcite.rex.RexUtil;
 import org.apache.calcite.rex.RexVisitorImpl;
 import org.apache.calcite.runtime.PairList;
+import org.apache.calcite.sql.SqlAggFunction;
 import org.apache.calcite.sql.SqlExplainFormat;
 import org.apache.calcite.sql.SqlExplainLevel;
 import org.apache.calcite.sql.SqlFunction;
@@ -94,6 +96,7 @@
 import org.apache.calcite.util.mapping.Mappings;
 import org.apache.calcite.util.trace.CalciteTrace;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSortedMap;
@@ -523,6 +526,19 @@ protected RexNode removeCorrelationExpr(
       return null;
     }
 
+    if (isCorVarDefined && (rel.fetch != null || rel.offset != null)) {
+      if (rel.fetch != null
+          && rel.offset == null
+          && RexLiteral.intValue(rel.fetch) == 1) {
+        return decorrelateFetchOneSort(rel, frame);
+      }
+      // Can not decorrelate if the sort has per-correlate-key attributes like
+      // offset or fetch limit, because these attributes scope would change to
+      // global after decorrelation. They should take effect within the scope
+      // of the correlation key actually.
+      return null;
+    }
+
     final RelNode newInput = frame.r;
 
     Mappings.TargetMapping mapping =
@@ -767,16 +783,6 @@ private static void shiftMapping(Map<Integer, Integer> 
mapping, int startIndex,
   public @Nullable Frame getInvoke(RelNode r, boolean isCorVarDefined, 
@Nullable RelNode parent) {
     final Frame frame = dispatcher.invoke(r, isCorVarDefined);
     currentRel = parent;
-    if (frame != null && isCorVarDefined && r instanceof Sort) {
-      final Sort sort = (Sort) r;
-      // Can not decorrelate if the sort has per-correlate-key attributes like
-      // offset or fetch limit, because these attributes scope would change to
-      // global after decorrelation. They should take effect within the scope
-      // of the correlation key actually.
-      if (sort.offset != null || sort.fetch != null) {
-        return null;
-      }
-    }
     if (frame != null) {
       map.put(r, frame);
     }
@@ -795,6 +801,146 @@ private static void shiftMapping(Map<Integer, Integer> 
mapping, int startIndex,
     return null;
   }
 
+  protected @Nullable Frame decorrelateFetchOneSort(Sort sort, final Frame 
frame) {
+    Frame aggFrame = decorrelateSortAsAggregate(sort, frame);
+    if (aggFrame != null) {
+      return aggFrame;
+    }
+    //
+    // Rewrite logic:
+    //
+    // If sorted without offset and fetch = 1 (enforced by the caller), 
rewrite the sort to be
+    //   Aggregate(group=(corVar.. , field..))
+    //     project(first_value(field) over (partition by corVar order by (sort 
collation)))
+    //       input
+    //
+    // 1. For the original sorted input, apply the FIRST_VALUE window function 
to produce
+    //    the result of sorting with LIMIT 1, and the same as the decorrelate 
of aggregate,
+    //    add correlated variables in partition list to maintain semantic 
consistency.
+    // 2. To ensure that there is at most one row of output for
+    //    any combination of correlated variables, distinct for correlated 
variables.
+    // 3. Since we have partitioned by all correlated variables
+    //    in the sorted output field window, so for any combination of 
correlated variables,
+    //    all other field values are unique. So the following two are 
equivalent:
+    //      - group by corVar1, covVar2, field1, field2
+    //      - any_value(fields1), any_value(fields2) group by corVar1, covVar2
+    //    Here we use the first.
+    final Map<Integer, Integer> mapOldToNewOutputs = new HashMap<>();
+    final NavigableMap<CorDef, Integer> corDefOutputs = new TreeMap<>();
+
+    final PairList<RexNode, String> corVarProjects = PairList.of();
+    List<RelDataTypeField> fieldList = frame.r.getRowType().getFieldList();
+    for (Map.Entry<CorDef, Integer> entry : frame.corDefOutputs.entrySet()) {
+      corDefOutputs.put(entry.getKey(),
+          sort.getRowType().getFieldCount() + corVarProjects.size());
+      RexInputRef.add2(corVarProjects, entry.getValue(), fieldList);
+    }
+
+    final List<RexNode> sortExprs =
+        new ArrayList<>(sort.getCollation().getFieldCollations().size());
+    for (RelFieldCollation collation : 
sort.getCollation().getFieldCollations()) {
+      Integer newIdx = 
requireNonNull(frame.oldToNewOutputs.get(collation.getFieldIndex()));
+      RexNode node = RexInputRef.of(newIdx, fieldList);
+      if (collation.direction == RelFieldCollation.Direction.DESCENDING) {
+        node = relBuilder.desc(node);
+      }
+      if (collation.nullDirection == RelFieldCollation.NullDirection.FIRST) {
+        node = relBuilder.nullsFirst(node);
+      } else if (collation.nullDirection == 
RelFieldCollation.NullDirection.LAST) {
+        node = relBuilder.nullsLast(node);
+      }
+      sortExprs.add(node);
+    }
+
+    final PairList<RexNode, String> newProjExprs = PairList.of();
+    for (RelDataTypeField field : sort.getRowType().getFieldList()) {
+      final int newIdx =
+          requireNonNull(frame.oldToNewOutputs.get(field.getIndex()));
+
+      RelBuilder.AggCall aggCall =
+          relBuilder.aggregateCall(SqlStdOperatorTable.FIRST_VALUE,
+              RexInputRef.of(newIdx, fieldList));
+
+      // Convert each field from the sorted output to a window function that 
partitions by
+      // correlated variables, orders by the collation, and return the 
first_value.
+      RexNode winCall = aggCall.over()
+          .orderBy(sortExprs)
+          .partitionBy(corVarProjects.leftList())
+          .toRex();
+      mapOldToNewOutputs.put(newProjExprs.size(), newProjExprs.size());
+      newProjExprs.add(winCall, field.getName());
+    }
+    newProjExprs.addAll(corVarProjects);
+    RelNode result = relBuilder.push(frame.r)
+        .project(newProjExprs.leftList(), newProjExprs.rightList())
+        .distinct().build();
+
+    return register(sort, result, mapOldToNewOutputs, corDefOutputs);
+  }
+
+  protected @Nullable Frame decorrelateSortAsAggregate(Sort sort, final Frame 
frame) {
+    final Map<Integer, Integer> mapOldToNewOutputs = new HashMap<>();
+    final NavigableMap<CorDef, Integer> corDefOutputs = new TreeMap<>();
+    if (sort.getCollation().getFieldCollations().size() == 1
+        && sort.getRowType().getFieldCount() == 1
+        && !frame.corDefOutputs.isEmpty()) {
+      //
+      // Rewrite logic:
+      //
+      // If sorted with no OFFSET and FETCH = 1, and only one collation field,
+      // rewrite the Sort as Aggregate using MIN/MAX function.
+      // Example:
+      //  Sort(sort0=[$0], dir0=[ASC], fetch=[1])
+      //   input
+      // Rewrite to:
+      //  Aggregate(group=(corVar), agg=[min($0))
+      //
+      // Note: MIN/MAX is not strictly equivalent to LIMIT 1. When the input 
has 0 rows,
+      // MIN/MAX returns NULL, while LIMIT 1 returns 0 rows.
+      // However, in the decorrelate, we add correlated variables to the group 
list
+      // to ensure equivalence when Correlate is transformed to Join. When the 
group list
+      // is non-empty, MIN/MAX will also return 0 rows if the input has 0 rows.
+      // So in this case, the transformation is legal.
+      RelFieldCollation collation = 
Util.first(sort.getCollation().getFieldCollations());
+
+      if (collation.nullDirection != RelFieldCollation.NullDirection.LAST) {
+        return null;
+      }
+
+      SqlAggFunction aggFunction;
+      switch (collation.getDirection()) {
+      case ASCENDING:
+      case STRICTLY_ASCENDING:
+        aggFunction = SqlStdOperatorTable.MIN;
+        break;
+      case DESCENDING:
+      case STRICTLY_DESCENDING:
+        aggFunction = SqlStdOperatorTable.MAX;
+        break;
+      default:
+        return null;
+      }
+
+      final int newIdx = 
requireNonNull(frame.oldToNewOutputs.get(collation.getFieldIndex()));
+      RelBuilder.AggCall aggCall = relBuilder.push(frame.r)
+          .aggregateCall(aggFunction, 
relBuilder.fields(ImmutableList.of(newIdx)));
+
+      // As with the aggregate decorrelate, add correlated variables to the 
group list.
+      final List<RexInputRef> groupKey = new ArrayList<>();
+      for (Map.Entry<CorDef, Integer> entry : frame.corDefOutputs.entrySet()) {
+        groupKey.add(RexInputRef.of(entry.getValue(), frame.r.getRowType()));
+        corDefOutputs.put(entry.getKey(), corDefOutputs.size());
+      }
+
+      RelNode aggregate = relBuilder.aggregate(relBuilder.groupKey(groupKey), 
aggCall).build();
+
+      // Add the mapping for the added aggregate fields.
+      mapOldToNewOutputs.put(0, groupKey.size());
+      return register(sort, aggregate, mapOldToNewOutputs, corDefOutputs);
+    }
+    return null;
+  }
+
   public @Nullable Frame decorrelateRel(LogicalProject rel, boolean 
isCorVarDefined) {
     return decorrelateRel((Project) rel, isCorVarDefined);
   }
diff --git a/core/src/main/java/org/apache/calcite/util/Util.java 
b/core/src/main/java/org/apache/calcite/util/Util.java
index b9b8e2085b..d911103f26 100644
--- a/core/src/main/java/org/apache/calcite/util/Util.java
+++ b/core/src/main/java/org/apache/calcite/util/Util.java
@@ -2086,7 +2086,7 @@ public static <T> Iterable<T> orEmpty(@Nullable 
Iterable<T> v0) {
    *
    * @throws java.lang.IndexOutOfBoundsException if the list is empty
    */
-  public <E> E first(List<E> list) {
+  public static <E> E first(List<E> list) {
     return list.get(0);
   }
 
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 61518e7701..3fa407691c 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -8577,6 +8577,111 @@ private void checkSemiJoinRuleOnAntiJoin(RelOptRule 
rule) {
         .check();
   }
 
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6652";>[CALCITE-6652]
+   * RelDecorrelator can't decorrelate query with limit 1</a>.
+   */
+  @Test void testDecorrelateProjectWithFetchOne() {
+    final String query = "SELECT name, "
+        + "(SELECT sal FROM emp where dept.deptno = emp.deptno order by sal 
limit 1) "
+        + "FROM dept";
+    sql(query).withRule(CoreRules.PROJECT_SUB_QUERY_TO_CORRELATE)
+        .withLateDecorrelate(true)
+        .check();
+  }
+
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6652";>[CALCITE-6652]
+   * RelDecorrelator can't decorrelate query with limit 1</a>.
+   */
+  @Test void testDecorrelateProjectWithFetchOneDesc() {
+    final String query = "SELECT name, "
+        + "(SELECT emp.sal FROM emp WHERE dept.deptno = emp.deptno "
+        + "ORDER BY emp.sal desc nulls last LIMIT 1) "
+        + "FROM dept";
+    sql(query).withRule(CoreRules.PROJECT_SUB_QUERY_TO_CORRELATE)
+        .withLateDecorrelate(true)
+        .check();
+  }
+
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6652";>[CALCITE-6652]
+   * RelDecorrelator can't decorrelate query with limit 1</a>.
+   */
+  @Test void testDecorrelateFilterWithFetchOne() {
+    final String query = "SELECT name FROM dept "
+        + "WHERE 10 > (SELECT emp.sal FROM emp where dept.deptno = emp.deptno "
+        + "ORDER BY emp.sal limit 1)";
+    sql(query).withRule(CoreRules.FILTER_SUB_QUERY_TO_CORRELATE)
+        .withLateDecorrelate(true)
+        .check();
+  }
+
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6652";>[CALCITE-6652]
+   * RelDecorrelator can't decorrelate query with limit 1</a>.
+   */
+  @Test void testDecorrelateFilterWithFetchOneDesc() {
+    final String query = "SELECT name FROM dept "
+        + "WHERE 10 > (SELECT emp.sal FROM emp where dept.deptno = emp.deptno "
+        + "ORDER BY emp.sal desc nulls last limit 1)";
+    sql(query).withRule(CoreRules.FILTER_SUB_QUERY_TO_CORRELATE)
+        .withLateDecorrelate(true)
+        .check();
+  }
+
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6652";>[CALCITE-6652]
+   * RelDecorrelator can't decorrelate query with limit 1</a>.
+   */
+  @Test void testDecorrelateFilterWithFetchOneDesc1() {
+    final String query = "SELECT name FROM dept "
+        + "WHERE 10 > (SELECT emp.sal FROM emp where dept.deptno = emp.deptno "
+        + "ORDER BY emp.sal desc limit 1)";
+    sql(query).withRule(CoreRules.FILTER_SUB_QUERY_TO_CORRELATE)
+        .withLateDecorrelate(true)
+        .check();
+  }
+
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6652";>[CALCITE-6652]
+   * RelDecorrelator can't decorrelate query with limit 1</a>.
+   */
+  @Test void testDecorrelateProjectWithMultiKeyAndFetchOne() {
+    final String query = "SELECT name, "
+        + "(SELECT sal FROM emp where dept.deptno = emp.deptno "
+        + "order by year(hiredate), emp.sal limit 1) FROM dept";
+    sql(query).withRule(CoreRules.PROJECT_SUB_QUERY_TO_CORRELATE)
+        .withLateDecorrelate(true)
+        .check();
+  }
+
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6652";>[CALCITE-6652]
+   * RelDecorrelator can't decorrelate query with limit 1</a>.
+   */
+  @Test void testDecorrelateProjectWithMultiKeyAndFetchOne1() {
+    final String query = "SELECT name, "
+        + "(SELECT sal FROM emp where dept.deptno = emp.deptno and dept.name = 
emp.ename "
+        + "order by year(hiredate), emp.sal limit 1) FROM dept";
+    sql(query).withRule(CoreRules.PROJECT_SUB_QUERY_TO_CORRELATE)
+        .withLateDecorrelate(true)
+        .check();
+  }
+
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6652";>[CALCITE-6652]
+   * RelDecorrelator can't decorrelate query with limit 1</a>.
+   */
+  @Test void testDecorrelateFilterWithMultiKeyAndFetchOne() {
+    final String query = "SELECT name FROM dept "
+        + "WHERE 10 > (SELECT emp.sal FROM emp where dept.deptno = emp.deptno "
+        + "order by year(hiredate), emp.sal desc limit 1)";
+    sql(query).withRule(CoreRules.FILTER_SUB_QUERY_TO_CORRELATE)
+        .withLateDecorrelate(true)
+        .check();
+  }
+
   /** Test case for
    * <a href="https://issues.apache.org/jira/browse/CALCITE-434";>[CALCITE-434]
    * Converting predicates on date dimension columns into date ranges</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 3d2f5bf0ee..67402c92e6 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -2274,6 +2274,406 @@ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], 
MGR=[$3], HIREDATE=[$4], SAL=[$
         LogicalProject(i=[true])
           LogicalFilter(condition=[=($cor0.DEPTNO, $7)])
             LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+  </TestCase>
+  <TestCase name="testDecorrelateFilterWithFetchOne">
+    <Resource name="sql">
+      <![CDATA[SELECT name FROM dept WHERE 10 > (SELECT emp.sal FROM emp where 
dept.deptno = emp.deptno ORDER BY emp.sal limit 1)]]>
+    </Resource>
+    <Resource name="planBefore">
+      <![CDATA[
+LogicalProject(NAME=[$1])
+  LogicalFilter(condition=[>(10, $SCALAR_QUERY({
+LogicalSort(sort0=[$0], dir0=[ASC], fetch=[1])
+  LogicalProject(SAL=[$5])
+    LogicalFilter(condition=[=($cor0.DEPTNO, $7)])
+      LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+}))], variablesSet=[[$cor0]])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+    </Resource>
+    <Resource name="planMid">
+      <![CDATA[
+LogicalProject(NAME=[$1])
+  LogicalProject(DEPTNO=[$0], NAME=[$1])
+    LogicalFilter(condition=[>(10, $2)])
+      LogicalCorrelate(correlation=[$cor0], joinType=[left], 
requiredColumns=[{0}])
+        LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+        LogicalSort(sort0=[$0], dir0=[ASC], fetch=[1])
+          LogicalProject(SAL=[$5])
+            LogicalFilter(condition=[=($cor0.DEPTNO, $7)])
+              LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+    <Resource name="planAfter">
+      <![CDATA[
+LogicalProject(NAME=[$1])
+  LogicalProject(DEPTNO=[$0], NAME=[$1], DEPTNO0=[CAST($2):INTEGER], 
$f1=[CAST($3):INTEGER])
+    LogicalJoin(condition=[=($0, $2)], joinType=[inner])
+      LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+      LogicalFilter(condition=[>(10, $1)])
+        LogicalAggregate(group=[{1}], agg#0=[MIN($0)])
+          LogicalProject(SAL=[$5], DEPTNO=[$7])
+            LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+  </TestCase>
+  <TestCase name="testDecorrelateFilterWithFetchOneDesc">
+    <Resource name="sql">
+      <![CDATA[SELECT name FROM dept WHERE 10 > (SELECT emp.sal FROM emp where 
dept.deptno = emp.deptno ORDER BY emp.sal desc nulls last limit 1)]]>
+    </Resource>
+    <Resource name="planBefore">
+      <![CDATA[
+LogicalProject(NAME=[$1])
+  LogicalFilter(condition=[>(10, $SCALAR_QUERY({
+LogicalSort(sort0=[$0], dir0=[DESC-nulls-last], fetch=[1])
+  LogicalProject(SAL=[$5])
+    LogicalFilter(condition=[=($cor0.DEPTNO, $7)])
+      LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+}))], variablesSet=[[$cor0]])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+    </Resource>
+    <Resource name="planMid">
+      <![CDATA[
+LogicalProject(NAME=[$1])
+  LogicalProject(DEPTNO=[$0], NAME=[$1])
+    LogicalFilter(condition=[>(10, $2)])
+      LogicalCorrelate(correlation=[$cor0], joinType=[left], 
requiredColumns=[{0}])
+        LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+        LogicalSort(sort0=[$0], dir0=[DESC-nulls-last], fetch=[1])
+          LogicalProject(SAL=[$5])
+            LogicalFilter(condition=[=($cor0.DEPTNO, $7)])
+              LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+    <Resource name="planAfter">
+      <![CDATA[
+LogicalProject(NAME=[$1])
+  LogicalProject(DEPTNO=[$0], NAME=[$1], DEPTNO0=[CAST($2):INTEGER], 
$f1=[CAST($3):INTEGER])
+    LogicalJoin(condition=[=($0, $2)], joinType=[inner])
+      LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+      LogicalFilter(condition=[>(10, $1)])
+        LogicalAggregate(group=[{1}], agg#0=[MAX($0)])
+          LogicalProject(SAL=[$5], DEPTNO=[$7])
+            LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+  </TestCase>
+  <TestCase name="testDecorrelateFilterWithFetchOneDesc1">
+    <Resource name="sql">
+      <![CDATA[SELECT name FROM dept WHERE 10 > (SELECT emp.sal FROM emp where 
dept.deptno = emp.deptno ORDER BY emp.sal desc limit 1)]]>
+    </Resource>
+    <Resource name="planBefore">
+      <![CDATA[
+LogicalProject(NAME=[$1])
+  LogicalFilter(condition=[>(10, $SCALAR_QUERY({
+LogicalSort(sort0=[$0], dir0=[DESC], fetch=[1])
+  LogicalProject(SAL=[$5])
+    LogicalFilter(condition=[=($cor0.DEPTNO, $7)])
+      LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+}))], variablesSet=[[$cor0]])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+    </Resource>
+    <Resource name="planMid">
+      <![CDATA[
+LogicalProject(NAME=[$1])
+  LogicalProject(DEPTNO=[$0], NAME=[$1])
+    LogicalFilter(condition=[>(10, $2)])
+      LogicalCorrelate(correlation=[$cor0], joinType=[left], 
requiredColumns=[{0}])
+        LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+        LogicalSort(sort0=[$0], dir0=[DESC], fetch=[1])
+          LogicalProject(SAL=[$5])
+            LogicalFilter(condition=[=($cor0.DEPTNO, $7)])
+              LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+    <Resource name="planAfter">
+      <![CDATA[
+LogicalProject(NAME=[$1])
+  LogicalProject(DEPTNO=[$0], NAME=[$1], SAL=[CAST($2):INTEGER], 
DEPTNO0=[CAST($3):INTEGER])
+    LogicalJoin(condition=[=($0, $3)], joinType=[inner])
+      LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+      LogicalFilter(condition=[>(10, $0)])
+        LogicalAggregate(group=[{0, 1}])
+          LogicalProject(SAL=[FIRST_VALUE($5) OVER (PARTITION BY $7 ORDER BY 
$5 DESC NULLS FIRST RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED 
FOLLOWING)], DEPTNO=[$7])
+            LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+  </TestCase>
+  <TestCase name="testDecorrelateFilterWithMultiKeyAndFetchOne">
+    <Resource name="sql">
+      <![CDATA[SELECT name FROM dept WHERE 10 > (SELECT emp.sal FROM emp where 
dept.deptno = emp.deptno order by year(hiredate), emp.sal desc limit 1)]]>
+    </Resource>
+    <Resource name="planBefore">
+      <![CDATA[
+LogicalProject(NAME=[$1])
+  LogicalFilter(condition=[>(10, $SCALAR_QUERY({
+LogicalProject(SAL=[$0])
+  LogicalSort(sort0=[$1], sort1=[$0], dir0=[ASC], dir1=[DESC], fetch=[1])
+    LogicalProject(SAL=[$5], EXPR$1=[EXTRACT(FLAG(YEAR), $4)])
+      LogicalFilter(condition=[=($cor0.DEPTNO, $7)])
+        LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+}))], variablesSet=[[$cor0]])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+    </Resource>
+    <Resource name="planMid">
+      <![CDATA[
+LogicalProject(NAME=[$1])
+  LogicalProject(DEPTNO=[$0], NAME=[$1])
+    LogicalFilter(condition=[>(10, $2)])
+      LogicalCorrelate(correlation=[$cor0], joinType=[left], 
requiredColumns=[{0}])
+        LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+        LogicalProject(SAL=[$0])
+          LogicalSort(sort0=[$1], sort1=[$0], dir0=[ASC], dir1=[DESC], 
fetch=[1])
+            LogicalProject(SAL=[$5], EXPR$1=[EXTRACT(FLAG(YEAR), $4)])
+              LogicalFilter(condition=[=($cor0.DEPTNO, $7)])
+                LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+    <Resource name="planAfter">
+      <![CDATA[
+LogicalProject(NAME=[$1])
+  LogicalProject(DEPTNO=[$0], NAME=[$1], SAL=[CAST($2):INTEGER], 
DEPTNO0=[CAST($3):INTEGER])
+    LogicalJoin(condition=[=($0, $3)], joinType=[inner])
+      LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+      LogicalFilter(condition=[>(10, $0)])
+        LogicalProject(SAL=[$0], DEPTNO=[$2])
+          LogicalAggregate(group=[{0, 1, 2}])
+            LogicalProject(SAL=[FIRST_VALUE($5) OVER (PARTITION BY $7 ORDER BY 
EXTRACT(FLAG(YEAR), $4) NULLS LAST, $5 DESC NULLS FIRST RANGE BETWEEN UNBOUNDED 
PRECEDING AND UNBOUNDED FOLLOWING)], EXPR$1=[FIRST_VALUE(EXTRACT(FLAG(YEAR), 
$4)) OVER (PARTITION BY $7 ORDER BY EXTRACT(FLAG(YEAR), $4) NULLS LAST, $5 DESC 
NULLS FIRST RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)], 
DEPTNO=[$7])
+              LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+  </TestCase>
+  <TestCase name="testDecorrelateProjectFetchOne">
+    <Resource name="sql">
+      <![CDATA[SELECT name, (SELECT mgr FROM emp where dept.deptno = 
emp.deptno order by mgr limit 1) FROM dept]]>
+    </Resource>
+    <Resource name="planBefore">
+      <![CDATA[
+LogicalProject(variablesSet=[[$cor0]], NAME=[$1], EXPR$1=[$SCALAR_QUERY({
+LogicalSort(sort0=[$0], dir0=[ASC], fetch=[1])
+  LogicalProject(MGR=[$3])
+    LogicalFilter(condition=[=($cor0.DEPTNO, $7)])
+      LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+})])
+  LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+    </Resource>
+    <Resource name="planMid">
+      <![CDATA[
+LogicalProject(NAME=[$1], EXPR$1=[$2])
+  LogicalCorrelate(correlation=[$cor0], joinType=[left], requiredColumns=[{0}])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+    LogicalSort(sort0=[$0], dir0=[ASC], fetch=[1])
+      LogicalProject(MGR=[$3])
+        LogicalFilter(condition=[=($cor0.DEPTNO, $7)])
+          LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+    <Resource name="planAfter">
+      <![CDATA[
+LogicalProject(NAME=[$1], EXPR$1=[$3])
+  LogicalJoin(condition=[=($0, $2)], joinType=[left])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+    LogicalAggregate(group=[{0}], agg#0=[MIN($1)])
+      LogicalProject(DEPTNO=[$7], MGR=[$3])
+        LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+  </TestCase>
+  <TestCase name="testDecorrelateProjectFetchOneDesc">
+    <Resource name="sql">
+      <![CDATA[SELECT name, (SELECT emp.mgr FROM emp WHERE dept.deptno = 
emp.deptno ORDER BY emp.mgr desc LIMIT 1) FROM dept]]>
+    </Resource>
+    <Resource name="planBefore">
+      <![CDATA[
+LogicalProject(variablesSet=[[$cor0]], NAME=[$1], EXPR$1=[$SCALAR_QUERY({
+LogicalSort(sort0=[$0], dir0=[DESC], fetch=[1])
+  LogicalProject(MGR=[$3])
+    LogicalFilter(condition=[=($cor0.DEPTNO, $7)])
+      LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+})])
+  LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+    </Resource>
+    <Resource name="planMid">
+      <![CDATA[
+LogicalProject(NAME=[$1], EXPR$1=[$2])
+  LogicalCorrelate(correlation=[$cor0], joinType=[left], requiredColumns=[{0}])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+    LogicalSort(sort0=[$0], dir0=[DESC], fetch=[1])
+      LogicalProject(MGR=[$3])
+        LogicalFilter(condition=[=($cor0.DEPTNO, $7)])
+          LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+    <Resource name="planAfter">
+      <![CDATA[
+LogicalProject(NAME=[$1], EXPR$1=[$3])
+  LogicalJoin(condition=[=($0, $2)], joinType=[left])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+    LogicalAggregate(group=[{0}], agg#0=[MAX($1)])
+      LogicalProject(DEPTNO=[$7], MGR=[$3])
+        LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+  </TestCase>
+  <TestCase name="testDecorrelateProjectWithFetchOne">
+    <Resource name="sql">
+      <![CDATA[SELECT name, (SELECT sal FROM emp where dept.deptno = 
emp.deptno order by sal limit 1) FROM dept]]>
+    </Resource>
+    <Resource name="planBefore">
+      <![CDATA[
+LogicalProject(variablesSet=[[$cor0]], NAME=[$1], EXPR$1=[$SCALAR_QUERY({
+LogicalSort(sort0=[$0], dir0=[ASC], fetch=[1])
+  LogicalProject(SAL=[$5])
+    LogicalFilter(condition=[=($cor0.DEPTNO, $7)])
+      LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+})])
+  LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+    </Resource>
+    <Resource name="planMid">
+      <![CDATA[
+LogicalProject(NAME=[$1], EXPR$1=[$2])
+  LogicalCorrelate(correlation=[$cor0], joinType=[left], requiredColumns=[{0}])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+    LogicalSort(sort0=[$0], dir0=[ASC], fetch=[1])
+      LogicalProject(SAL=[$5])
+        LogicalFilter(condition=[=($cor0.DEPTNO, $7)])
+          LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+    <Resource name="planAfter">
+      <![CDATA[
+LogicalProject(NAME=[$1], EXPR$1=[$3])
+  LogicalJoin(condition=[=($0, $2)], joinType=[left])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+    LogicalAggregate(group=[{1}], agg#0=[MIN($0)])
+      LogicalProject(SAL=[$5], DEPTNO=[$7])
+        LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+  </TestCase>
+  <TestCase name="testDecorrelateProjectWithFetchOneDesc">
+    <Resource name="sql">
+      <![CDATA[SELECT name, (SELECT emp.sal FROM emp WHERE dept.deptno = 
emp.deptno ORDER BY emp.sal desc nulls last LIMIT 1) FROM dept]]>
+    </Resource>
+    <Resource name="planBefore">
+      <![CDATA[
+LogicalProject(variablesSet=[[$cor0]], NAME=[$1], EXPR$1=[$SCALAR_QUERY({
+LogicalSort(sort0=[$0], dir0=[DESC-nulls-last], fetch=[1])
+  LogicalProject(SAL=[$5])
+    LogicalFilter(condition=[=($cor0.DEPTNO, $7)])
+      LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+})])
+  LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+    </Resource>
+    <Resource name="planMid">
+      <![CDATA[
+LogicalProject(NAME=[$1], EXPR$1=[$2])
+  LogicalCorrelate(correlation=[$cor0], joinType=[left], requiredColumns=[{0}])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+    LogicalSort(sort0=[$0], dir0=[DESC-nulls-last], fetch=[1])
+      LogicalProject(SAL=[$5])
+        LogicalFilter(condition=[=($cor0.DEPTNO, $7)])
+          LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+    <Resource name="planAfter">
+      <![CDATA[
+LogicalProject(NAME=[$1], EXPR$1=[$3])
+  LogicalJoin(condition=[=($0, $2)], joinType=[left])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+    LogicalAggregate(group=[{1}], agg#0=[MAX($0)])
+      LogicalProject(SAL=[$5], DEPTNO=[$7])
+        LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+  </TestCase>
+  <TestCase name="testDecorrelateProjectWithMultiKeyAndFetchOne">
+    <Resource name="sql">
+      <![CDATA[SELECT name, (SELECT sal FROM emp where dept.deptno = 
emp.deptno order by year(hiredate), emp.sal limit 1) FROM dept]]>
+    </Resource>
+    <Resource name="planBefore">
+      <![CDATA[
+LogicalProject(variablesSet=[[$cor0]], NAME=[$1], EXPR$1=[$SCALAR_QUERY({
+LogicalProject(SAL=[$0])
+  LogicalSort(sort0=[$1], sort1=[$0], dir0=[ASC], dir1=[ASC], fetch=[1])
+    LogicalProject(SAL=[$5], EXPR$1=[EXTRACT(FLAG(YEAR), $4)])
+      LogicalFilter(condition=[=($cor0.DEPTNO, $7)])
+        LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+})])
+  LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+    </Resource>
+    <Resource name="planMid">
+      <![CDATA[
+LogicalProject(NAME=[$1], EXPR$1=[$2])
+  LogicalCorrelate(correlation=[$cor0], joinType=[left], requiredColumns=[{0}])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+    LogicalProject(SAL=[$0])
+      LogicalSort(sort0=[$1], sort1=[$0], dir0=[ASC], dir1=[ASC], fetch=[1])
+        LogicalProject(SAL=[$5], EXPR$1=[EXTRACT(FLAG(YEAR), $4)])
+          LogicalFilter(condition=[=($cor0.DEPTNO, $7)])
+            LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+    <Resource name="planAfter">
+      <![CDATA[
+LogicalProject(NAME=[$1], EXPR$1=[$2])
+  LogicalJoin(condition=[=($0, $3)], joinType=[left])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+    LogicalProject(SAL=[$0], DEPTNO=[$2])
+      LogicalAggregate(group=[{0, 1, 2}])
+        LogicalProject(SAL=[FIRST_VALUE($5) OVER (PARTITION BY $7 ORDER BY 
EXTRACT(FLAG(YEAR), $4) NULLS LAST, $5 NULLS LAST RANGE BETWEEN UNBOUNDED 
PRECEDING AND UNBOUNDED FOLLOWING)], EXPR$1=[FIRST_VALUE(EXTRACT(FLAG(YEAR), 
$4)) OVER (PARTITION BY $7 ORDER BY EXTRACT(FLAG(YEAR), $4) NULLS LAST, $5 
NULLS LAST RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)], 
DEPTNO=[$7])
+          LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+  </TestCase>
+  <TestCase name="testDecorrelateProjectWithMultiKeyAndFetchOne1">
+    <Resource name="sql">
+      <![CDATA[SELECT name, (SELECT sal FROM emp where dept.deptno = 
emp.deptno and dept.name = emp.ename order by year(hiredate), emp.sal limit 1) 
FROM dept]]>
+    </Resource>
+    <Resource name="planBefore">
+      <![CDATA[
+LogicalProject(variablesSet=[[$cor0]], NAME=[$1], EXPR$1=[$SCALAR_QUERY({
+LogicalProject(SAL=[$0])
+  LogicalSort(sort0=[$1], sort1=[$0], dir0=[ASC], dir1=[ASC], fetch=[1])
+    LogicalProject(SAL=[$5], EXPR$1=[EXTRACT(FLAG(YEAR), $4)])
+      LogicalFilter(condition=[AND(=($cor0.DEPTNO, $7), 
=(CAST($cor0.NAME):VARCHAR(20) NOT NULL, $1))])
+        LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+})])
+  LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+]]>
+    </Resource>
+    <Resource name="planMid">
+      <![CDATA[
+LogicalProject(NAME=[$1], EXPR$1=[$2])
+  LogicalCorrelate(correlation=[$cor0], joinType=[left], requiredColumns=[{0, 
1}])
+    LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+    LogicalProject(SAL=[$0])
+      LogicalSort(sort0=[$1], sort1=[$0], dir0=[ASC], dir1=[ASC], fetch=[1])
+        LogicalProject(SAL=[$5], EXPR$1=[EXTRACT(FLAG(YEAR), $4)])
+          LogicalFilter(condition=[AND(=($cor0.DEPTNO, $7), 
=(CAST($cor0.NAME):VARCHAR(20) NOT NULL, $1))])
+            LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+    <Resource name="planAfter">
+      <![CDATA[
+LogicalProject(NAME=[$1], EXPR$1=[$4])
+  LogicalJoin(condition=[AND(=($0, $5), =($3, $6))], joinType=[left])
+    LogicalProject(DEPTNO=[$0], NAME=[$1], DEPTNO0=[$0], 
NAME0=[CAST($1):VARCHAR(20) NOT NULL])
+      LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+    LogicalProject(SAL=[$0], DEPTNO=[$2], ENAME=[$3])
+      LogicalAggregate(group=[{0, 1, 2, 3}])
+        LogicalProject(SAL=[FIRST_VALUE($5) OVER (PARTITION BY $7, $1 ORDER BY 
EXTRACT(FLAG(YEAR), $4) NULLS LAST, $5 NULLS LAST RANGE BETWEEN UNBOUNDED 
PRECEDING AND UNBOUNDED FOLLOWING)], EXPR$1=[FIRST_VALUE(EXTRACT(FLAG(YEAR), 
$4)) OVER (PARTITION BY $7, $1 ORDER BY EXTRACT(FLAG(YEAR), $4) NULLS LAST, $5 
NULLS LAST RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)], 
DEPTNO=[$7], ENAME=[$1])
+          LogicalTableScan(table=[[CATALOG, SALES, EMP]])
 ]]>
     </Resource>
   </TestCase>
diff --git 
a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml 
b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
index 78f0f6a769..07a33d50f8 100644
--- a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
@@ -2058,16 +2058,14 @@ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], 
MGR=[$3], HIREDATE=[$4], SAL=[$
     <Resource name="plan">
       <![CDATA[
 LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], 
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
-  LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], 
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], $f0=[$9])
-    LogicalFilter(condition=[IS NOT NULL($9)])
-      LogicalCorrelate(correlation=[$cor0], joinType=[left], 
requiredColumns=[{7}])
-        LogicalTableScan(table=[[CATALOG, SALES, EMP]])
-        LogicalAggregate(group=[{}], agg#0=[MIN($0)])
-          LogicalProject($f0=[true])
-            LogicalSort(fetch=[1])
-              LogicalProject(EXPR$0=[1])
-                LogicalFilter(condition=[=($cor0.DEPTNO, $0)])
-                  LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+  LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], 
SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], DEPTNO0=[CAST($9):INTEGER], 
$f1=[CAST($10):BOOLEAN])
+    LogicalJoin(condition=[=($7, $9)], joinType=[inner])
+      LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+      LogicalAggregate(group=[{0}], agg#0=[MIN($1)])
+        LogicalProject(DEPTNO=[$1], $f0=[true])
+          LogicalAggregate(group=[{0, 1}])
+            LogicalProject(EXPR$0=[FIRST_VALUE(1) OVER (PARTITION BY $0)], 
DEPTNO=[$0])
+              LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
 ]]>
     </Resource>
   </TestCase>
diff --git a/core/src/test/resources/sql/sub-query.iq 
b/core/src/test/resources/sql/sub-query.iq
index 01bfadc4b8..37523909f2 100644
--- a/core/src/test/resources/sql/sub-query.iq
+++ b/core/src/test/resources/sql/sub-query.iq
@@ -549,6 +549,271 @@ where sal + 100 not in (
 
 !ok
 
+# [CALCITE-6652] RelDecorrelator can't decorrelate query with limit 1
+SELECT dname FROM "scott".dept WHERE 2000 > (SELECT emp.sal FROM "scott".emp 
where dept.deptno = emp.deptno ORDER BY emp.sal limit 1);
+
+EnumerableCalc(expr#0..1=[{inputs}], DNAME=[$t1])
+  EnumerableHashJoin(condition=[=($0, $2)], joinType=[semi])
+    EnumerableCalc(expr#0..2=[{inputs}], proj#0..1=[{exprs}])
+      EnumerableTableScan(table=[[scott, DEPT]])
+    EnumerableCalc(expr#0..1=[{inputs}], expr#2=[2000.00:DECIMAL(12, 2)], 
expr#3=[CAST($t1):DECIMAL(12, 2)], expr#4=[>($t2, $t3)], proj#0..1=[{exprs}], 
$condition=[$t4])
+      EnumerableAggregate(group=[{7}], agg#0=[MIN($5)])
+        EnumerableCalc(expr#0..7=[{inputs}], expr#8=[IS NOT NULL($t7)], 
proj#0..7=[{exprs}], $condition=[$t8])
+          EnumerableTableScan(table=[[scott, EMP]])
+!plan
++------------+
+| DNAME      |
++------------+
+| ACCOUNTING |
+| RESEARCH   |
+| SALES      |
++------------+
+(3 rows)
+
+!ok
+
+# [CALCITE-6652] RelDecorrelator can't decorrelate query with limit 1
+SELECT dname FROM "scott".dept WHERE 4000 > (SELECT emp.sal FROM "scott".emp 
where dept.deptno = emp.deptno ORDER BY emp.sal desc nulls last limit 1);
+
+EnumerableCalc(expr#0..1=[{inputs}], DNAME=[$t1])
+  EnumerableHashJoin(condition=[=($0, $2)], joinType=[semi])
+    EnumerableCalc(expr#0..2=[{inputs}], proj#0..1=[{exprs}])
+      EnumerableTableScan(table=[[scott, DEPT]])
+    EnumerableCalc(expr#0..1=[{inputs}], expr#2=[4000.00:DECIMAL(12, 2)], 
expr#3=[CAST($t1):DECIMAL(12, 2)], expr#4=[>($t2, $t3)], proj#0..1=[{exprs}], 
$condition=[$t4])
+      EnumerableAggregate(group=[{7}], agg#0=[MAX($5)])
+        EnumerableCalc(expr#0..7=[{inputs}], expr#8=[IS NOT NULL($t7)], 
proj#0..7=[{exprs}], $condition=[$t8])
+          EnumerableTableScan(table=[[scott, EMP]])
+!plan
++----------+
+| DNAME    |
++----------+
+| RESEARCH |
+| SALES    |
++----------+
+(2 rows)
+
+!ok
+
+# [CALCITE-6652] RelDecorrelator can't decorrelate query with limit 1
+# The case of the subquery that returns 0 rows
+SELECT dname FROM "scott".dept WHERE 2000 > (SELECT emp.sal FROM "scott".emp 
where dept.deptno = emp.deptno and mgr > 8000 ORDER BY emp.sal limit 1);
+
+EnumerableCalc(expr#0..1=[{inputs}], DNAME=[$t1])
+  EnumerableHashJoin(condition=[=($0, $2)], joinType=[semi])
+    EnumerableCalc(expr#0..2=[{inputs}], proj#0..1=[{exprs}])
+      EnumerableTableScan(table=[[scott, DEPT]])
+    EnumerableCalc(expr#0..1=[{inputs}], expr#2=[2000.00:DECIMAL(12, 2)], 
expr#3=[CAST($t1):DECIMAL(12, 2)], expr#4=[>($t2, $t3)], proj#0..1=[{exprs}], 
$condition=[$t4])
+      EnumerableAggregate(group=[{7}], agg#0=[MIN($5)])
+        EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t3):INTEGER], 
expr#9=[8000], expr#10=[>($t8, $t9)], expr#11=[IS NOT NULL($t7)], 
expr#12=[AND($t10, $t11)], proj#0..7=[{exprs}], $condition=[$t12])
+          EnumerableTableScan(table=[[scott, EMP]])
+!plan
++-------+
+| DNAME |
++-------+
++-------+
+(0 rows)
+
+!ok
+
+# [CALCITE-6652] RelDecorrelator can't decorrelate query with limit 1
+SELECT dname FROM "scott".dept WHERE 2000 > (SELECT emp.sal FROM "scott".emp 
where dept.deptno = emp.deptno ORDER BY year(hiredate), emp.sal limit 1);
+
+EnumerableCalc(expr#0..3=[{inputs}], DNAME=[$t3])
+  EnumerableHashJoin(condition=[=($1, $2)], joinType=[inner])
+    EnumerableCalc(expr#0..2=[{inputs}], expr#3=[2000.00:DECIMAL(12, 2)], 
expr#4=[CAST($t1):DECIMAL(12, 2)], expr#5=[>($t3, $t4)], SAL=[$t1], 
DEPTNO=[$t0], $condition=[$t5])
+      EnumerableAggregate(group=[{1, 3, 4}])
+        EnumerableWindow(window#0=[window(partition {1} order by [2, 0] range 
between UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING aggs [FIRST_VALUE($0), 
FIRST_VALUE($2)])])
+          EnumerableCalc(expr#0..7=[{inputs}], expr#8=[FLAG(YEAR)], 
expr#9=[EXTRACT($t8, $t4)], expr#10=[IS NOT NULL($t7)], SAL=[$t5], 
DEPTNO=[$t7], $2=[$t9], $condition=[$t10])
+            EnumerableTableScan(table=[[scott, EMP]])
+    EnumerableCalc(expr#0..2=[{inputs}], proj#0..1=[{exprs}])
+      EnumerableTableScan(table=[[scott, DEPT]])
+!plan
++----------+
+| DNAME    |
++----------+
+| RESEARCH |
+| SALES    |
++----------+
+(2 rows)
+
+!ok
+
+# [CALCITE-6652] RelDecorrelator can't decorrelate query with limit 1
+# The case of the subquery that returns 0 rows
+SELECT dname FROM "scott".dept WHERE 2000 > (SELECT emp.sal FROM "scott".emp 
where dept.deptno = emp.deptno and mgr > 8000 ORDER BY year(hiredate), emp.sal 
limit 1);
+
+EnumerableCalc(expr#0..3=[{inputs}], DNAME=[$t3])
+  EnumerableHashJoin(condition=[=($1, $2)], joinType=[inner])
+    EnumerableCalc(expr#0..2=[{inputs}], expr#3=[2000.00:DECIMAL(12, 2)], 
expr#4=[CAST($t1):DECIMAL(12, 2)], expr#5=[>($t3, $t4)], SAL=[$t1], 
DEPTNO=[$t0], $condition=[$t5])
+      EnumerableAggregate(group=[{1, 3, 4}])
+        EnumerableWindow(window#0=[window(partition {1} order by [2, 0] range 
between UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING aggs [FIRST_VALUE($0), 
FIRST_VALUE($2)])])
+          EnumerableCalc(expr#0..7=[{inputs}], expr#8=[FLAG(YEAR)], 
expr#9=[EXTRACT($t8, $t4)], expr#10=[CAST($t3):INTEGER], expr#11=[8000], 
expr#12=[>($t10, $t11)], expr#13=[IS NOT NULL($t7)], expr#14=[AND($t12, $t13)], 
SAL=[$t5], DEPTNO=[$t7], $2=[$t9], $condition=[$t14])
+            EnumerableTableScan(table=[[scott, EMP]])
+    EnumerableCalc(expr#0..2=[{inputs}], proj#0..1=[{exprs}])
+      EnumerableTableScan(table=[[scott, DEPT]])
+!plan
++-------+
+| DNAME |
++-------+
++-------+
+(0 rows)
+
+!ok
+
+# [CALCITE-6652] RelDecorrelator can't decorrelate query with limit 1
+SELECT dname, (SELECT emp.sal FROM "scott".emp where dept.deptno = emp.deptno 
ORDER BY emp.sal desc nulls last limit 1) FROM "scott".dept;
+
+EnumerableCalc(expr#0..3=[{inputs}], DNAME=[$t1], EXPR$1=[$t3])
+  EnumerableMergeJoin(condition=[=($0, $2)], joinType=[left])
+    EnumerableCalc(expr#0..2=[{inputs}], proj#0..1=[{exprs}])
+      EnumerableTableScan(table=[[scott, DEPT]])
+    EnumerableSort(sort0=[$0], dir0=[ASC])
+      EnumerableAggregate(group=[{7}], agg#0=[MAX($5)])
+        EnumerableCalc(expr#0..7=[{inputs}], expr#8=[IS NOT NULL($t7)], 
proj#0..7=[{exprs}], $condition=[$t8])
+          EnumerableTableScan(table=[[scott, EMP]])
+!plan
++------------+---------+
+| DNAME      | EXPR$1  |
++------------+---------+
+| ACCOUNTING | 5000.00 |
+| OPERATIONS |         |
+| RESEARCH   | 3000.00 |
+| SALES      | 2850.00 |
++------------+---------+
+(4 rows)
+
+!ok
+
+# [CALCITE-6652] RelDecorrelator can't decorrelate query with limit 1
+# subquery contains null
+SELECT dname, (SELECT emp.comm FROM "scott".emp where dept.deptno = emp.deptno 
ORDER BY emp.comm desc limit 1) FROM "scott".dept;
+
+EnumerableCalc(expr#0..3=[{inputs}], DNAME=[$t1], EXPR$1=[$t2])
+  EnumerableMergeJoin(condition=[=($0, $3)], joinType=[left])
+    EnumerableCalc(expr#0..2=[{inputs}], proj#0..1=[{exprs}])
+      EnumerableTableScan(table=[[scott, DEPT]])
+    EnumerableSort(sort0=[$1], dir0=[ASC])
+      EnumerableCalc(expr#0..1=[{inputs}], w0$o0=[$t1], DEPTNO=[$t0])
+        EnumerableAggregate(group=[{7, 8}])
+          EnumerableWindow(window#0=[window(partition {7} order by [6 DESC] 
range between UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING aggs 
[FIRST_VALUE($6)])])
+            EnumerableCalc(expr#0..7=[{inputs}], expr#8=[IS NOT NULL($t7)], 
proj#0..7=[{exprs}], $condition=[$t8])
+              EnumerableTableScan(table=[[scott, EMP]])
+!plan
++------------+--------+
+| DNAME      | EXPR$1 |
++------------+--------+
+| ACCOUNTING |        |
+| OPERATIONS |        |
+| RESEARCH   |        |
+| SALES      |        |
++------------+--------+
+(4 rows)
+
+!ok
+
+# [CALCITE-6652] RelDecorrelator can't decorrelate query with limit 1
+# subquery contains null
+SELECT dname, (SELECT emp.comm FROM "scott".emp where dept.deptno = emp.deptno 
ORDER BY emp.comm limit 1) FROM "scott".dept;
+
+EnumerableCalc(expr#0..3=[{inputs}], DNAME=[$t1], EXPR$1=[$t3])
+  EnumerableMergeJoin(condition=[=($0, $2)], joinType=[left])
+    EnumerableCalc(expr#0..2=[{inputs}], proj#0..1=[{exprs}])
+      EnumerableTableScan(table=[[scott, DEPT]])
+    EnumerableSort(sort0=[$0], dir0=[ASC])
+      EnumerableAggregate(group=[{7}], agg#0=[MIN($6)])
+        EnumerableCalc(expr#0..7=[{inputs}], expr#8=[IS NOT NULL($t7)], 
proj#0..7=[{exprs}], $condition=[$t8])
+          EnumerableTableScan(table=[[scott, EMP]])
+!plan
++------------+--------+
+| DNAME      | EXPR$1 |
++------------+--------+
+| ACCOUNTING |        |
+| OPERATIONS |        |
+| RESEARCH   |        |
+| SALES      |   0.00 |
++------------+--------+
+(4 rows)
+
+!ok
+
+# [CALCITE-6652] RelDecorrelator can't decorrelate query with limit 1
+# The case of the subquery that returns 0 rows
+SELECT dname, (SELECT emp.sal FROM "scott".emp where dept.deptno = emp.deptno 
and mgr > 8000 ORDER BY emp.sal limit 1) FROM "scott".dept;
+
+EnumerableCalc(expr#0..3=[{inputs}], DNAME=[$t1], EXPR$1=[$t3])
+  EnumerableMergeJoin(condition=[=($0, $2)], joinType=[left])
+    EnumerableCalc(expr#0..2=[{inputs}], proj#0..1=[{exprs}])
+      EnumerableTableScan(table=[[scott, DEPT]])
+    EnumerableSort(sort0=[$0], dir0=[ASC])
+      EnumerableAggregate(group=[{7}], agg#0=[MIN($5)])
+        EnumerableCalc(expr#0..7=[{inputs}], expr#8=[CAST($t3):INTEGER], 
expr#9=[8000], expr#10=[>($t8, $t9)], expr#11=[IS NOT NULL($t7)], 
expr#12=[AND($t10, $t11)], proj#0..7=[{exprs}], $condition=[$t12])
+          EnumerableTableScan(table=[[scott, EMP]])
+!plan
++------------+--------+
+| DNAME      | EXPR$1 |
++------------+--------+
+| ACCOUNTING |        |
+| OPERATIONS |        |
+| RESEARCH   |        |
+| SALES      |        |
++------------+--------+
+(4 rows)
+
+!ok
+
+# [CALCITE-6652] RelDecorrelator can't decorrelate query with limit 1
+SELECT dname, (SELECT emp.sal FROM "scott".emp where dept.deptno = emp.deptno 
ORDER BY year(hiredate), emp.sal limit 1) FROM "scott".dept;
+
+EnumerableCalc(expr#0..3=[{inputs}], DNAME=[$t1], EXPR$1=[$t2])
+  EnumerableMergeJoin(condition=[=($0, $3)], joinType=[left])
+    EnumerableCalc(expr#0..2=[{inputs}], proj#0..1=[{exprs}])
+      EnumerableTableScan(table=[[scott, DEPT]])
+    EnumerableSort(sort0=[$1], dir0=[ASC])
+      EnumerableCalc(expr#0..2=[{inputs}], SAL=[$t1], DEPTNO=[$t0])
+        EnumerableAggregate(group=[{1, 3, 4}])
+          EnumerableWindow(window#0=[window(partition {1} order by [2, 0] 
range between UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING aggs 
[FIRST_VALUE($0), FIRST_VALUE($2)])])
+            EnumerableCalc(expr#0..7=[{inputs}], expr#8=[FLAG(YEAR)], 
expr#9=[EXTRACT($t8, $t4)], expr#10=[IS NOT NULL($t7)], SAL=[$t5], 
DEPTNO=[$t7], $2=[$t9], $condition=[$t10])
+              EnumerableTableScan(table=[[scott, EMP]])
+!plan
++------------+---------+
+| DNAME      | EXPR$1  |
++------------+---------+
+| ACCOUNTING | 2450.00 |
+| OPERATIONS |         |
+| RESEARCH   |  800.00 |
+| SALES      |  950.00 |
++------------+---------+
+(4 rows)
+
+!ok
+
+# [CALCITE-6652] RelDecorrelator can't decorrelate query with limit 1
+# The case of the subquery that returns 0 rows
+SELECT dname, (SELECT emp.sal FROM "scott".emp where dept.deptno = emp.deptno 
and mgr > 8000 ORDER BY year(hiredate), emp.sal limit 1) FROM "scott".dept;
+
+EnumerableCalc(expr#0..3=[{inputs}], DNAME=[$t1], EXPR$1=[$t2])
+  EnumerableMergeJoin(condition=[=($0, $3)], joinType=[left])
+    EnumerableCalc(expr#0..2=[{inputs}], proj#0..1=[{exprs}])
+      EnumerableTableScan(table=[[scott, DEPT]])
+    EnumerableSort(sort0=[$1], dir0=[ASC])
+      EnumerableCalc(expr#0..2=[{inputs}], SAL=[$t1], DEPTNO=[$t0])
+        EnumerableAggregate(group=[{1, 3, 4}])
+          EnumerableWindow(window#0=[window(partition {1} order by [2, 0] 
range between UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING aggs 
[FIRST_VALUE($0), FIRST_VALUE($2)])])
+            EnumerableCalc(expr#0..7=[{inputs}], expr#8=[FLAG(YEAR)], 
expr#9=[EXTRACT($t8, $t4)], expr#10=[CAST($t3):INTEGER], expr#11=[8000], 
expr#12=[>($t10, $t11)], expr#13=[IS NOT NULL($t7)], expr#14=[AND($t12, $t13)], 
SAL=[$t5], DEPTNO=[$t7], $2=[$t9], $condition=[$t14])
+              EnumerableTableScan(table=[[scott, EMP]])
+!plan
++------------+--------+
+| DNAME      | EXPR$1 |
++------------+--------+
+| ACCOUNTING |        |
+| OPERATIONS |        |
+| RESEARCH   |        |
+| SALES      |        |
++------------+--------+
+(4 rows)
+
+!ok
+
 # Condition that happens to eliminate all NULL keys.
 # The one missing row has {ename: 'MARTIN', comm: 1400}
 # Tested on Oracle.
@@ -1943,14 +2208,15 @@ select sal from "scott".emp e
 (0 rows)
 
 !ok
-EnumerableCalc(expr#0..2=[{inputs}], expr#3=[RAND()], 
expr#4=[CAST($t3):INTEGER NOT NULL], expr#5=[2], expr#6=[MOD($t4, $t5)], 
expr#7=[3], expr#8=[=($t6, $t7)], expr#9=[OR($t8, $t2)], SAL=[$t0], 
$condition=[$t9])
-  EnumerableCorrelate(correlation=[$cor0], joinType=[left], 
requiredColumns=[{1}])
-    EnumerableCalc(expr#0..7=[{inputs}], SAL=[$t5], DEPTNO=[$t7])
-      EnumerableTableScan(table=[[scott, EMP]])
-    EnumerableLimit(fetch=[1])
-      EnumerableSort(sort0=[$0], dir0=[DESC])
-        EnumerableAggregate(group=[{0}])
-          EnumerableCalc(expr#0..2=[{inputs}], expr#3=[false], expr#4=[$cor0], 
expr#5=[$t4.DEPTNO], expr#6=[=($t0, $t5)], cs=[$t3], $condition=[$t6])
+EnumerableCalc(expr#0..4=[{inputs}], expr#5=[RAND()], 
expr#6=[CAST($t5):INTEGER NOT NULL], expr#7=[2], expr#8=[MOD($t6, $t7)], 
expr#9=[3], expr#10=[=($t8, $t9)], expr#11=[OR($t10, $t3)], SAL=[$t1], 
$condition=[$t11])
+  EnumerableMergeJoin(condition=[=($2, $4)], joinType=[left])
+    EnumerableSort(sort0=[$2], dir0=[ASC])
+      EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5], 
DEPTNO=[$t7])
+        EnumerableTableScan(table=[[scott, EMP]])
+    EnumerableSort(sort0=[$1], dir0=[ASC])
+      EnumerableCalc(expr#0..1=[{inputs}], cs=[$t1], DEPTNO=[$t0])
+        EnumerableWindow(window#0=[window(partition {0} aggs 
[FIRST_VALUE($1)])], constants=[[false]])
+          EnumerableCalc(expr#0..2=[{inputs}], DEPTNO=[$t0])
             EnumerableTableScan(table=[[scott, DEPT]])
 !plan
 
@@ -2032,14 +2298,15 @@ select sal from "scott".emp e
 (0 rows)
 
 !ok
-EnumerableCalc(expr#0..2=[{inputs}], expr#3=[NOT($t2)], expr#4=[IS NOT 
NULL($t2)], expr#5=[OR($t3, $t4)], expr#6=[IS NOT TRUE($t5)], SAL=[$t0], 
$condition=[$t6])
-  EnumerableCorrelate(correlation=[$cor0], joinType=[left], 
requiredColumns=[{1}])
-    EnumerableCalc(expr#0..7=[{inputs}], SAL=[$t5], DEPTNO=[$t7])
-      EnumerableTableScan(table=[[scott, EMP]])
-    EnumerableLimit(fetch=[1])
-      EnumerableSort(sort0=[$0], dir0=[DESC])
-        EnumerableAggregate(group=[{0}])
-          EnumerableCalc(expr#0..2=[{inputs}], expr#3=[false], expr#4=[$cor0], 
expr#5=[$t4.DEPTNO], expr#6=[=($t5, $t0)], cs=[$t3], $condition=[$t6])
+EnumerableCalc(expr#0..4=[{inputs}], expr#5=[NOT($t3)], expr#6=[IS NOT 
NULL($t3)], expr#7=[OR($t5, $t6)], expr#8=[IS NOT TRUE($t7)], SAL=[$t1], 
$condition=[$t8])
+  EnumerableMergeJoin(condition=[=($2, $4)], joinType=[left])
+    EnumerableSort(sort0=[$2], dir0=[ASC])
+      EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5], 
DEPTNO=[$t7])
+        EnumerableTableScan(table=[[scott, EMP]])
+    EnumerableSort(sort0=[$1], dir0=[ASC])
+      EnumerableCalc(expr#0..1=[{inputs}], cs=[$t1], DEPTNO=[$t0])
+        EnumerableWindow(window#0=[window(partition {0} aggs 
[FIRST_VALUE($1)])], constants=[[false]])
+          EnumerableCalc(expr#0..2=[{inputs}], DEPTNO=[$t0])
             EnumerableTableScan(table=[[scott, DEPT]])
 !plan
 
@@ -2103,14 +2370,16 @@ select sal from "scott".emp e
 (11 rows)
 
 !ok
-EnumerableCalc(expr#0..2=[{inputs}], expr#3=[NOT($t2)], expr#4=[IS NOT 
NULL($t2)], expr#5=[OR($t3, $t4)], expr#6=[IS NOT TRUE($t5)], SAL=[$t0], 
$condition=[$t6])
-  EnumerableCorrelate(correlation=[$cor0], joinType=[left], 
requiredColumns=[{1}])
-    EnumerableCalc(expr#0..7=[{inputs}], SAL=[$t5], DEPTNO=[$t7])
-      EnumerableTableScan(table=[[scott, EMP]])
-    EnumerableLimit(fetch=[1])
-      EnumerableSort(sort0=[$0], dir0=[DESC])
-        EnumerableCalc(expr#0..2=[{inputs}], expr#3=[true], expr#4=[$cor0], 
expr#5=[$t4.DEPTNO], expr#6=[=($t5, $t0)], expr#7=[10], 
expr#8=[CAST($t0):INTEGER NOT NULL], expr#9=[=($t7, $t8)], expr#10=[AND($t6, 
$t9)], cs=[$t3], $condition=[$t10])
-          EnumerableTableScan(table=[[scott, DEPT]])
+EnumerableCalc(expr#0..4=[{inputs}], expr#5=[NOT($t3)], expr#6=[IS NOT 
NULL($t3)], expr#7=[OR($t5, $t6)], expr#8=[IS NOT TRUE($t7)], SAL=[$t1], 
$condition=[$t8])
+  EnumerableMergeJoin(condition=[=($2, $4)], joinType=[left])
+    EnumerableSort(sort0=[$2], dir0=[ASC])
+      EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5], 
DEPTNO=[$t7])
+        EnumerableTableScan(table=[[scott, EMP]])
+    EnumerableSort(sort0=[$1], dir0=[ASC])
+      EnumerableCalc(expr#0..1=[{inputs}], cs=[$t1], DEPTNO1=[$t0])
+        EnumerableWindow(window#0=[window(partition {0} aggs 
[FIRST_VALUE($1)])], constants=[[true]])
+          EnumerableCalc(expr#0..2=[{inputs}], expr#3=[10], 
expr#4=[CAST($t0):INTEGER NOT NULL], expr#5=[=($t3, $t4)], DEPTNO=[$t0], 
$condition=[$t5])
+            EnumerableTableScan(table=[[scott, DEPT]])
 !plan
 
 # Test filter literal NOT IN nullable correlated
@@ -2134,14 +2403,16 @@ select sal from "scott".emp e
 (11 rows)
 
 !ok
-EnumerableCalc(expr#0..2=[{inputs}], expr#3=[NOT($t2)], expr#4=[IS NOT 
NULL($t2)], expr#5=[OR($t3, $t4)], expr#6=[IS NOT TRUE($t5)], SAL=[$t0], 
$condition=[$t6])
-  EnumerableCorrelate(correlation=[$cor0], joinType=[left], 
requiredColumns=[{1}])
-    EnumerableCalc(expr#0..7=[{inputs}], SAL=[$t5], DEPTNO=[$t7])
-      EnumerableTableScan(table=[[scott, EMP]])
-    EnumerableLimit(fetch=[1])
-      EnumerableSort(sort0=[$0], dir0=[DESC])
-        EnumerableCalc(expr#0..2=[{inputs}], expr#3=[IS NOT NULL($t0)], 
expr#4=[$cor0], expr#5=[$t4.DEPTNO], expr#6=[=($t5, $t0)], 
expr#7=[CAST($t0):INTEGER], expr#8=[10], expr#9=[=($t7, $t8)], 
expr#10=[AND($t6, $t9)], cs=[$t3], $condition=[$t10])
-          EnumerableTableScan(table=[[scott, DEPT]])
+EnumerableCalc(expr#0..4=[{inputs}], expr#5=[NOT($t3)], expr#6=[IS NOT 
NULL($t3)], expr#7=[OR($t5, $t6)], expr#8=[IS NOT TRUE($t7)], SAL=[$t1], 
$condition=[$t8])
+  EnumerableMergeJoin(condition=[=($2, $4)], joinType=[left])
+    EnumerableSort(sort0=[$2], dir0=[ASC])
+      EnumerableCalc(expr#0..7=[{inputs}], EMPNO=[$t0], SAL=[$t5], 
DEPTNO=[$t7])
+        EnumerableTableScan(table=[[scott, EMP]])
+    EnumerableSort(sort0=[$1], dir0=[ASC])
+      EnumerableCalc(expr#0..1=[{inputs}], cs=[$t1], DEPTNO=[$t0])
+        EnumerableWindow(window#0=[window(partition {0} aggs 
[FIRST_VALUE($1)])], constants=[[true]])
+          EnumerableCalc(expr#0..2=[{inputs}], expr#3=[CAST($t0):INTEGER], 
expr#4=[10], expr#5=[=($t3, $t4)], DEPTNO=[$t0], $condition=[$t5])
+            EnumerableTableScan(table=[[scott, DEPT]])
 !plan
 
 # Test filter null IN required is unknown correlated
@@ -2168,15 +2439,8 @@ select sal from "scott".emp e
 (14 rows)
 
 !ok
-EnumerableCalc(expr#0..2=[{inputs}], SAL=[$t0])
-  EnumerableCorrelate(correlation=[$cor0], joinType=[left], 
requiredColumns=[{1}])
-    EnumerableCalc(expr#0..7=[{inputs}], SAL=[$t5], DEPTNO=[$t7])
-      EnumerableTableScan(table=[[scott, EMP]])
-    EnumerableLimit(fetch=[1])
-      EnumerableSort(sort0=[$0], dir0=[DESC])
-        EnumerableAggregate(group=[{0}])
-          EnumerableCalc(expr#0..2=[{inputs}], expr#3=[true], expr#4=[$cor0], 
expr#5=[$t4.DEPTNO], expr#6=[=($t5, $t0)], cs=[$t3], $condition=[$t6])
-            EnumerableTableScan(table=[[scott, DEPT]])
+EnumerableCalc(expr#0..7=[{inputs}], SAL=[$t5])
+  EnumerableTableScan(table=[[scott, EMP]])
 !plan
 
 

Reply via email to