@@ -23,6 +23,7 @@ use datafusion_expr::{WindowFrameBound, WindowFrameUnits};
2323use datafusion_physical_plan:: execution_plan:: CardinalityEffect ;
2424use datafusion_physical_plan:: limit:: GlobalLimitExec ;
2525use datafusion_physical_plan:: sorts:: sort:: SortExec ;
26+ use datafusion_physical_plan:: sorts:: sort_preserving_merge:: SortPreservingMergeExec ;
2627use datafusion_physical_plan:: windows:: BoundedWindowAggExec ;
2728use datafusion_physical_plan:: ExecutionPlan ;
2829use std:: cmp;
@@ -91,6 +92,22 @@ impl PhysicalOptimizerRule for LimitPushPastWindows {
9192 return Ok ( Transformed :: no ( node) ) ;
9293 }
9394
95+ // Apply the limit if we hit a sortpreservingmerge node
96+ if let Some ( spm) = node. as_any ( ) . downcast_ref :: < SortPreservingMergeExec > ( ) {
97+ let latest = latest_limit. take ( ) ;
98+ let Some ( fetch) = latest else {
99+ latest_max = 0 ;
100+ return Ok ( Transformed :: no ( node) ) ;
101+ } ;
102+ let fetch = match spm. fetch ( ) {
103+ None => fetch + latest_max,
104+ Some ( existing) => cmp:: min ( existing, fetch + latest_max) ,
105+ } ;
106+ let spm: Arc < dyn ExecutionPlan > = spm. with_fetch ( Some ( fetch) ) . unwrap ( ) ;
107+ latest_max = 0 ;
108+ return Ok ( Transformed :: complete ( spm) ) ;
109+ }
110+
94111 // Apply the limit if we hit a sort node
95112 if let Some ( sort) = node. as_any ( ) . downcast_ref :: < SortExec > ( ) {
96113 let latest = latest_limit. take ( ) ;
0 commit comments