@@ -584,4 +584,67 @@ public static Frameworks.ConfigBuilder config() {
584584 + " LogicalTableScan(table=[[scott, DEPT]])\n " ;
585585 assertThat (decorrelatedNoRules , hasTree (planDecorrelatedNoRules ));
586586 }
587+
588+ @ Test void testDecorrelateCorrelatedOrderByLimitToRowNumberRows () {
589+ final FrameworkConfig frameworkConfig = config ().build ();
590+ final RelBuilder builder = RelBuilder .create (frameworkConfig );
591+ final RelOptCluster cluster = builder .getCluster ();
592+ final Planner planner = Frameworks .getPlanner (frameworkConfig );
593+ final String sql = ""
594+ + "SELECT dname FROM dept WHERE 2000 > (\n "
595+ + "SELECT emp.sal FROM emp where dept.deptno = emp.deptno\n "
596+ + "ORDER BY year(hiredate), emp.sal limit 1)" ;
597+ final RelNode originalRel ;
598+ try {
599+ final SqlNode parse = planner .parse (sql );
600+ final SqlNode validate = planner .validate (parse );
601+ originalRel = planner .rel (validate ).rel ;
602+ } catch (Exception e ) {
603+ throw TestUtil .rethrow (e );
604+ }
605+
606+ final HepProgram hepProgram = HepProgram .builder ()
607+ .addRuleCollection (
608+ ImmutableList .of (
609+ // SubQuery program rules
610+ CoreRules .FILTER_SUB_QUERY_TO_CORRELATE ,
611+ CoreRules .PROJECT_SUB_QUERY_TO_CORRELATE ,
612+ CoreRules .JOIN_SUB_QUERY_TO_CORRELATE ))
613+ .build ();
614+ final Program program =
615+ Programs .of (hepProgram , true ,
616+ requireNonNull (cluster .getMetadataProvider ()));
617+ final RelNode before =
618+ program .run (cluster .getPlanner (), originalRel , cluster .traitSet (),
619+ Collections .emptyList (), Collections .emptyList ());
620+ final String planBefore = ""
621+ + "LogicalProject(DNAME=[$1])\n "
622+ + " LogicalProject(DEPTNO=[$0], DNAME=[$1], LOC=[$2])\n "
623+ + " LogicalFilter(condition=[>(2000.00, CAST($3):DECIMAL(12, 2))])\n "
624+ + " LogicalCorrelate(correlation=[$cor0], joinType=[left], requiredColumns=[{0}])\n "
625+ + " LogicalTableScan(table=[[scott, DEPT]])\n "
626+ + " LogicalProject(SAL=[$0])\n "
627+ + " LogicalSort(sort0=[$1], sort1=[$0], dir0=[ASC], dir1=[ASC], fetch=[1])\n "
628+ + " LogicalProject(SAL=[$5], EXPR$1=[EXTRACT(FLAG(YEAR), $4)])\n "
629+ + " LogicalFilter(condition=[=($cor0.DEPTNO, $7)])\n "
630+ + " LogicalTableScan(table=[[scott, EMP]])\n " ;
631+ assertThat (before , hasTree (planBefore ));
632+
633+ // Decorrelate without any rules, just "purely" decorrelation algorithm on RelDecorrelator
634+ final RelNode after =
635+ RelDecorrelator .decorrelateQuery (before , builder , RuleSets .ofList (Collections .emptyList ()),
636+ RuleSets .ofList (Collections .emptyList ()));
637+ // Verify plan
638+ final String planAfter = ""
639+ + "LogicalProject(DNAME=[$1])\n "
640+ + " LogicalJoin(condition=[=($0, $4)], joinType=[inner])\n "
641+ + " LogicalTableScan(table=[[scott, DEPT]])\n "
642+ + " LogicalFilter(condition=[>(2000.00, CAST($0):DECIMAL(12, 2))])\n "
643+ + " LogicalProject(SAL=[$0], DEPTNO=[$2])\n "
644+ + " LogicalFilter(condition=[<=($3, 1)])\n "
645+ + " LogicalProject(SAL=[$5], EXPR$1=[EXTRACT(FLAG(YEAR), $4)], DEPTNO=[$7], rn=[ROW_NUMBER() OVER (PARTITION BY $7 ORDER BY EXTRACT(FLAG(YEAR), $4) NULLS LAST, $5 NULLS LAST ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)])\n "
646+ + " LogicalFilter(condition=[IS NOT NULL($7)])\n "
647+ + " LogicalTableScan(table=[[scott, EMP]])\n " ;
648+ assertThat (after , hasTree (planAfter ));
649+ }
587650}
0 commit comments