diff --git a/crates/polars-core/src/chunked_array/ops/append.rs b/crates/polars-core/src/chunked_array/ops/append.rs index c14405ed377d..3aff4cc9e51c 100644 --- a/crates/polars-core/src/chunked_array/ops/append.rs +++ b/crates/polars-core/src/chunked_array/ops/append.rs @@ -19,16 +19,20 @@ where T: PolarsDataType, for<'a> T::Physical<'a>: TotalOrd, { - // If either is empty (or completely null), copy the sorted flag from the other. - if ca.len() == ca.null_count() { + // TODO: attempt to maintain sortedness better in case of nulls. + + // If either is empty, copy the sorted flag from the other. + if ca.is_empty() { ca.set_sorted_flag(other.is_sorted_flag()); return; } - if other.len() == other.null_count() { + if other.is_empty() { return; } - // Both need to be sorted, in the same order. + // Both need to be sorted, in the same order, if the order is maintained. + // TODO: rework sorted flags, ascending and descending are not mutually + // exclusive for all-equal/all-null arrays. let ls = ca.is_sorted_flag(); let rs = other.is_sorted_flag(); if ls != rs || ls == IsSorted::Not || rs == IsSorted::Not { @@ -38,12 +42,23 @@ where // Check the order is maintained. let still_sorted = { - let left = ca.get(ca.last_non_null().unwrap()).unwrap(); - let right = other.get(other.first_non_null().unwrap()).unwrap(); - if ca.is_sorted_ascending_flag() { - left.tot_le(&right) + // To prevent potential quadratic append behavior we do not find + // the last non-null element in ca. + if let Some(left) = ca.last() { + if let Some(right_idx) = other.first_non_null() { + let right = other.get(right_idx).unwrap(); + if ca.is_sorted_ascending_flag() { + left.tot_le(&right) + } else { + left.tot_ge(&right) + } + } else { + // Right is only nulls, trivially sorted. + true + } } else { - left.tot_ge(&right) + // Last element in left is null, pessimistically assume not sorted. + false } }; if !still_sorted {