Skip to content

Commit 2cf0956

Browse files
lewiszlwalamb
andauthored
Move LimitPushdown to physical-optimizer crate (#11945)
* Move LimitPushdown to physical-optimizer crate * Add comment about test code location * asf header * Fix clippy --------- Co-authored-by: Andrew Lamb <[email protected]>
1 parent 34ec9d4 commit 2cf0956

File tree

9 files changed

+749
-726
lines changed

9 files changed

+749
-726
lines changed

datafusion/common/src/utils/mod.rs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use sqlparser::ast::Ident;
3737
use sqlparser::dialect::GenericDialect;
3838
use sqlparser::parser::Parser;
3939
use std::borrow::{Borrow, Cow};
40-
use std::cmp::Ordering;
40+
use std::cmp::{min, Ordering};
4141
use std::collections::HashSet;
4242
use std::ops::Range;
4343
use std::sync::Arc;
@@ -683,6 +683,69 @@ pub fn transpose<T>(original: Vec<Vec<T>>) -> Vec<Vec<T>> {
683683
}
684684
}
685685

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+
686749
#[cfg(test)]
687750
mod tests {
688751
use crate::ScalarValue::Null;

0 commit comments

Comments
 (0)