@@ -37,7 +37,7 @@ use sqlparser::ast::Ident;
37
37
use sqlparser:: dialect:: GenericDialect ;
38
38
use sqlparser:: parser:: Parser ;
39
39
use std:: borrow:: { Borrow , Cow } ;
40
- use std:: cmp:: Ordering ;
40
+ use std:: cmp:: { min , Ordering } ;
41
41
use std:: collections:: HashSet ;
42
42
use std:: ops:: Range ;
43
43
use std:: sync:: Arc ;
@@ -683,6 +683,69 @@ pub fn transpose<T>(original: Vec<Vec<T>>) -> Vec<Vec<T>> {
683
683
}
684
684
}
685
685
686
+ /// Computes the `skip` and `fetch` parameters of a single limit that would be
687
+ /// equivalent to two consecutive limits with the given `skip`/`fetch` parameters.
688
+ ///
689
+ /// There are multiple cases to consider:
690
+ ///
691
+ /// # Case 0: Parent and child are disjoint (`child_fetch <= skip`).
692
+ ///
693
+ /// ```text
694
+ /// Before merging:
695
+ /// |........skip........|---fetch-->| Parent limit
696
+ /// |...child_skip...|---child_fetch-->| Child limit
697
+ /// ```
698
+ ///
699
+ /// After merging:
700
+ /// ```text
701
+ /// |.........(child_skip + skip).........|
702
+ /// ```
703
+ ///
704
+ /// # Case 1: Parent is beyond child's range (`skip < child_fetch <= skip + fetch`).
705
+ ///
706
+ /// Before merging:
707
+ /// ```text
708
+ /// |...skip...|------------fetch------------>| Parent limit
709
+ /// |...child_skip...|-------------child_fetch------------>| Child limit
710
+ /// ```
711
+ ///
712
+ /// After merging:
713
+ /// ```text
714
+ /// |....(child_skip + skip)....|---(child_fetch - skip)-->|
715
+ /// ```
716
+ ///
717
+ /// # Case 2: Parent is within child's range (`skip + fetch < child_fetch`).
718
+ ///
719
+ /// Before merging:
720
+ /// ```text
721
+ /// |...skip...|---fetch-->| Parent limit
722
+ /// |...child_skip...|-------------child_fetch------------>| Child limit
723
+ /// ```
724
+ ///
725
+ /// After merging:
726
+ /// ```text
727
+ /// |....(child_skip + skip)....|---fetch-->|
728
+ /// ```
729
+ pub fn combine_limit (
730
+ parent_skip : usize ,
731
+ parent_fetch : Option < usize > ,
732
+ child_skip : usize ,
733
+ child_fetch : Option < usize > ,
734
+ ) -> ( usize , Option < usize > ) {
735
+ let combined_skip = child_skip. saturating_add ( parent_skip) ;
736
+
737
+ let combined_fetch = match ( parent_fetch, child_fetch) {
738
+ ( Some ( parent_fetch) , Some ( child_fetch) ) => {
739
+ Some ( min ( parent_fetch, child_fetch. saturating_sub ( parent_skip) ) )
740
+ }
741
+ ( Some ( parent_fetch) , None ) => Some ( parent_fetch) ,
742
+ ( None , Some ( child_fetch) ) => Some ( child_fetch. saturating_sub ( parent_skip) ) ,
743
+ ( None , None ) => None ,
744
+ } ;
745
+
746
+ ( combined_skip, combined_fetch)
747
+ }
748
+
686
749
#[ cfg( test) ]
687
750
mod tests {
688
751
use crate :: ScalarValue :: Null ;
0 commit comments