@@ -75,10 +75,10 @@ impl Rule for EliminateLimits {
7575 if let Operator :: Limit ( op) = graph. operator ( node_id) {
7676 let child_id = graph. children_at ( node_id) [ 0 ] ;
7777 if let Operator :: Limit ( child_op) = graph. operator ( child_id) {
78- let new_limit_op = LimitOperator {
79- offset : op. offset + child_op. offset ,
80- limit : cmp :: min ( op . limit , child_op . limit ) ,
81- } ;
78+ let offset = Self :: binary_options ( op . offset , child_op . offset , |a , b| a + b ) ;
79+ let limit = Self :: binary_options ( op. limit , child_op. limit , |a , b| cmp :: min ( a , b ) ) ;
80+
81+ let new_limit_op = LimitOperator { offset , limit } ;
8282
8383 graph. remove_node ( child_id, false ) ;
8484 graph. replace_node (
@@ -92,6 +92,21 @@ impl Rule for EliminateLimits {
9292 }
9393}
9494
95+ impl EliminateLimits {
96+ fn binary_options < F : Fn ( usize , usize ) -> usize > (
97+ a : Option < usize > ,
98+ b : Option < usize > ,
99+ _fn : F ,
100+ ) -> Option < usize > {
101+ match ( a, b) {
102+ ( Some ( a) , Some ( b) ) => Some ( _fn ( a, b) ) ,
103+ ( Some ( a) , None ) => Some ( a) ,
104+ ( None , Some ( b) ) => Some ( b) ,
105+ ( None , None ) => None ,
106+ }
107+ }
108+ }
109+
95110/// Add extra limits below JOIN:
96111/// 1. For LEFT OUTER and RIGHT OUTER JOIN, we push limits to the left and right sides,
97112/// respectively.
@@ -147,7 +162,7 @@ impl Rule for PushLimitIntoScan {
147162 if let Operator :: Scan ( scan_op) = graph. operator ( child_index) {
148163 let mut new_scan_op = scan_op. clone ( ) ;
149164
150- new_scan_op. limit = ( Some ( limit_op. offset ) , Some ( limit_op. limit ) ) ;
165+ new_scan_op. limit = ( limit_op. offset , limit_op. limit ) ;
151166
152167 graph. remove_node ( node_id, false ) ;
153168 graph. replace_node (
@@ -208,8 +223,8 @@ mod tests {
208223 ) ;
209224
210225 let new_limit_op = LimitOperator {
211- offset : 2 ,
212- limit : 1 ,
226+ offset : Some ( 2 ) ,
227+ limit : Some ( 1 ) ,
213228 } ;
214229
215230 optimizer
@@ -219,8 +234,8 @@ mod tests {
219234 let best_plan = optimizer. find_best ( ) ?;
220235
221236 if let Operator :: Limit ( op) = & best_plan. operator {
222- assert_eq ! ( op. limit, 1 ) ;
223- assert_eq ! ( op. offset, 3 ) ;
237+ assert_eq ! ( op. limit, Some ( 1 ) ) ;
238+ assert_eq ! ( op. offset, Some ( 3 ) ) ;
224239 } else {
225240 unreachable ! ( "Should be a project operator" )
226241 }
@@ -253,7 +268,7 @@ mod tests {
253268 }
254269
255270 if let Operator :: Limit ( op) = & best_plan. childrens [ 0 ] . childrens [ 0 ] . childrens [ 0 ] . operator {
256- assert_eq ! ( op. limit, 1 ) ;
271+ assert_eq ! ( op. limit, Some ( 1 ) ) ;
257272 } else {
258273 unreachable ! ( "Should be a limit operator" )
259274 }
0 commit comments