Skip to content

Commit

Permalink
Move LimitPushdown to physical-optimizer crate (#11945)
Browse files Browse the repository at this point in the history
* Move LimitPushdown to physical-optimizer crate

* Add comment about test code location

* asf header

* Fix clippy

---------

Co-authored-by: Andrew Lamb <[email protected]>
  • Loading branch information
lewiszlw and alamb authored Aug 12, 2024
1 parent 34ec9d4 commit 2cf0956
Show file tree
Hide file tree
Showing 9 changed files with 749 additions and 726 deletions.
65 changes: 64 additions & 1 deletion datafusion/common/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use sqlparser::ast::Ident;
use sqlparser::dialect::GenericDialect;
use sqlparser::parser::Parser;
use std::borrow::{Borrow, Cow};
use std::cmp::Ordering;
use std::cmp::{min, Ordering};
use std::collections::HashSet;
use std::ops::Range;
use std::sync::Arc;
Expand Down Expand Up @@ -683,6 +683,69 @@ pub fn transpose<T>(original: Vec<Vec<T>>) -> Vec<Vec<T>> {
}
}

/// Computes the `skip` and `fetch` parameters of a single limit that would be
/// equivalent to two consecutive limits with the given `skip`/`fetch` parameters.
///
/// There are multiple cases to consider:
///
/// # Case 0: Parent and child are disjoint (`child_fetch <= skip`).
///
/// ```text
/// Before merging:
/// |........skip........|---fetch-->| Parent limit
/// |...child_skip...|---child_fetch-->| Child limit
/// ```
///
/// After merging:
/// ```text
/// |.........(child_skip + skip).........|
/// ```
///
/// # Case 1: Parent is beyond child's range (`skip < child_fetch <= skip + fetch`).
///
/// Before merging:
/// ```text
/// |...skip...|------------fetch------------>| Parent limit
/// |...child_skip...|-------------child_fetch------------>| Child limit
/// ```
///
/// After merging:
/// ```text
/// |....(child_skip + skip)....|---(child_fetch - skip)-->|
/// ```
///
/// # Case 2: Parent is within child's range (`skip + fetch < child_fetch`).
///
/// Before merging:
/// ```text
/// |...skip...|---fetch-->| Parent limit
/// |...child_skip...|-------------child_fetch------------>| Child limit
/// ```
///
/// After merging:
/// ```text
/// |....(child_skip + skip)....|---fetch-->|
/// ```
pub fn combine_limit(
parent_skip: usize,
parent_fetch: Option<usize>,
child_skip: usize,
child_fetch: Option<usize>,
) -> (usize, Option<usize>) {
let combined_skip = child_skip.saturating_add(parent_skip);

let combined_fetch = match (parent_fetch, child_fetch) {
(Some(parent_fetch), Some(child_fetch)) => {
Some(min(parent_fetch, child_fetch.saturating_sub(parent_skip)))
}
(Some(parent_fetch), None) => Some(parent_fetch),
(None, Some(child_fetch)) => Some(child_fetch.saturating_sub(parent_skip)),
(None, None) => None,
};

(combined_skip, combined_fetch)
}

#[cfg(test)]
mod tests {
use crate::ScalarValue::Null;
Expand Down
Loading

0 comments on commit 2cf0956

Please sign in to comment.