diff --git a/datafusion/physical-expr/src/equivalence/ordering.rs b/datafusion/physical-expr/src/equivalence/ordering.rs index ae502d4d5f67..4954c21728f6 100644 --- a/datafusion/physical-expr/src/equivalence/ordering.rs +++ b/datafusion/physical-expr/src/equivalence/ordering.rs @@ -135,12 +135,12 @@ impl OrderingEquivalenceClass { let mut ordering_idx = idx + 1; let mut removal = self.orderings[idx].is_empty(); while ordering_idx < self.orderings.len() { - work |= resolve_overlap(&mut self.orderings, idx, ordering_idx); + work |= self.resolve_overlap(idx, ordering_idx); if self.orderings[idx].is_empty() { removal = true; break; } - work |= resolve_overlap(&mut self.orderings, ordering_idx, idx); + work |= self.resolve_overlap(ordering_idx, idx); if self.orderings[ordering_idx].is_empty() { self.orderings.swap_remove(ordering_idx); } else { @@ -156,6 +156,26 @@ impl OrderingEquivalenceClass { } } + /// Trims `orderings[idx]` if some suffix of it overlaps with a prefix of + /// `orderings[pre_idx]`. Returns `true` if there is any overlap, `false` otherwise. + /// + /// For example, if `orderings[idx]` is `[a ASC, b ASC, c DESC]` and + /// `orderings[pre_idx]` is `[b ASC, c DESC]`, then the function will trim + /// `orderings[idx]` to `[a ASC]`. + fn resolve_overlap(&mut self, idx: usize, pre_idx: usize) -> bool { + let length = self.orderings[idx].len(); + let other_length = self.orderings[pre_idx].len(); + for overlap in 1..=length.min(other_length) { + if self.orderings[idx][length - overlap..] + == self.orderings[pre_idx][..overlap] + { + self.orderings[idx].truncate(length - overlap); + return true; + } + } + false + } + /// Returns the concatenation of all the orderings. This enables merge /// operations to preserve all equivalent orderings simultaneously. pub fn output_ordering(&self) -> Option { @@ -226,20 +246,6 @@ impl IntoIterator for OrderingEquivalenceClass { } } -/// Trims `orderings[idx]` if some suffix of it overlaps with a prefix of -/// `orderings[pre_idx]`. Returns `true` if there is any overlap, `false` otherwise. -fn resolve_overlap(orderings: &mut [LexOrdering], idx: usize, pre_idx: usize) -> bool { - let length = orderings[idx].len(); - let other_length = orderings[pre_idx].len(); - for overlap in 1..=length.min(other_length) { - if orderings[idx][length - overlap..] == orderings[pre_idx][..overlap] { - orderings[idx].truncate(length - overlap); - return true; - } - } - false -} - impl Display for OrderingEquivalenceClass { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "[")?;