@@ -575,7 +575,30 @@ protected RexNode removeCorrelationExpr(
575575 }
576576
577577 if (isCorVarDefined && (rel .fetch != null || rel .offset != null )) {
578- return decorrelateFetchOneSort (rel , frame );
578+ if (rel .offset == null
579+ && rel .fetch != null
580+ && RexLiteral .longValue (rel .fetch ) == 0 ) {
581+ return null ;
582+ }
583+
584+ //
585+ // Rewrite logic:
586+ //
587+ // For correlated Sort with LIMIT/OFFSET:
588+ // Special case: if OFFSET is null and FETCH = 1,
589+ // we may rewrite as an Aggregate using MIN/MAX.
590+ Frame aggFrame = decorrelateSortAsAggregate (rel , frame );
591+ if (aggFrame != null ) {
592+ return aggFrame ;
593+ }
594+
595+ // General case: rewrite as
596+ // Project(original_fields..., corVars..., rn)
597+ // where rn = ROW_NUMBER() OVER (PARTITION BY corVars ORDER BY sortExprs
598+ // ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
599+ // Filter(rn > offset, rn <= offset + fetch)
600+ // This preserves per-corVar LIMIT/OFFSET semantics.
601+ return decorrelateSortWithRowNumber (rel , frame );
579602 }
580603
581604 final RelNode newInput = frame .r ;
@@ -1036,32 +1059,7 @@ private static void shiftMapping(Map<Integer, Integer> mapping, int startIndex,
10361059 return null ;
10371060 }
10381061
1039- protected @ Nullable Frame decorrelateFetchOneSort (Sort sort , final Frame frame ) {
1040- if (sort .offset == null
1041- && sort .fetch != null
1042- && RexLiteral .intValue (sort .fetch ) == 0 ) {
1043- return null ;
1044- }
1045-
1046- //
1047- // Rewrite logic:
1048- //
1049- // For correlated Sort with LIMIT/OFFSET:
1050- // 1) Special case: if OFFSET is null and FETCH = 1, we may rewrite as an Aggregate
1051- // using MIN/MAX (see decorrelateSortAsAggregate).
1052- // 2) General case: rewrite as
1053- // Project(original_fields..., corVars..., rn)
1054- // where rn = ROW_NUMBER() OVER (PARTITION BY corVars ORDER BY sortExprs
1055- // ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
1056- // Filter(rn > offset, rn <= offset + fetch)
1057- // This preserves per-corVar LIMIT/OFFSET semantics.
1058- //
1059-
1060- Frame aggFrame = decorrelateSortAsAggregate (sort , frame );
1061- if (aggFrame != null ) {
1062- return aggFrame ;
1063- }
1064-
1062+ protected @ Nullable Frame decorrelateSortWithRowNumber (Sort sort , final Frame frame ) {
10651063 final Map <Integer , Integer > mapOldToNewOutputs = new HashMap <>();
10661064 final NavigableMap <CorDef , Integer > corDefOutputs = new TreeMap <>();
10671065
@@ -1143,7 +1141,7 @@ private static void shiftMapping(Map<Integer, Integer> mapping, int startIndex,
11431141 if (sort .offset != null ) {
11441142 return null ;
11451143 }
1146- if (sort .fetch == null || RexLiteral .intValue (sort .fetch ) != 1 ) {
1144+ if (sort .fetch == null || RexLiteral .longValue (sort .fetch ) != 1 ) {
11471145 return null ;
11481146 }
11491147
@@ -1376,7 +1374,7 @@ private static void shiftMapping(Map<Integer, Integer> mapping, int startIndex,
13761374 final int newOutput =
13771375 newLocalOutputs .indexOf (newLocalOutput )
13781376 + requireNonNull (mapNewInputToNewOffset .get (newInput ),
1379- () -> "mapNewInputToNewOffset.get(" + newInput + ")" )
1377+ () -> "mapNewInputToNewOffset.get(" + newInput + ")" )
13801378 + valueGenFieldOffset ;
13811379
13821380 corDefOutputs .put (corRef .def (), newOutput );
@@ -3339,7 +3337,7 @@ private CorelMap(Multimap<RelNode, CorRef> mapRefRelToCorRef,
33393337 && mapRefRelToCorRef .equals (((CorelMap ) obj ).mapRefRelToCorRef )
33403338 && mapCorToCorRel .equals (((CorelMap ) obj ).mapCorToCorRel )
33413339 && mapFieldAccessToCorRef .equals (
3342- ((CorelMap ) obj ).mapFieldAccessToCorRef );
3340+ ((CorelMap ) obj ).mapFieldAccessToCorRef );
33433341 }
33443342
33453343 @ Override public int hashCode () {
0 commit comments