diff --git a/datafusion/common/src/utils/mod.rs b/datafusion/common/src/utils/mod.rs index f71cf23d5348b..94bbb91a7fa8b 100644 --- a/datafusion/common/src/utils/mod.rs +++ b/datafusion/common/src/utils/mod.rs @@ -1236,16 +1236,7 @@ pub fn adjust_offsets_for_slice( ) -> OffsetBuffer { let offsets = list.offsets(); - if let (Some(first), Some(last)) = (offsets.first(), offsets.last()) - && (!first.is_zero() || last.as_usize() != list.values().len()) - { - let offsets = offsets.iter().map(|offset| *offset - *first).collect(); - - //todo: use unsafe Offset::new_unchecked? - return OffsetBuffer::new(offsets); - } - - offsets.clone() + offsets.clone().subtract(offsets[0]) } /// For lists and large lists, truncates the sublist of null values diff --git a/datafusion/functions-nested/src/sort.rs b/datafusion/functions-nested/src/sort.rs index 0a34cce6b965f..ca9267bb88c82 100644 --- a/datafusion/functions-nested/src/sort.rs +++ b/datafusion/functions-nested/src/sort.rs @@ -471,12 +471,7 @@ fn take_by_indices( fn rebase_offsets( offsets: &OffsetBuffer, ) -> OffsetBuffer { - if offsets[0].as_usize() == 0 { - offsets.clone() - } else { - let rebased: Vec = offsets.iter().map(|o| *o - offsets[0]).collect(); - OffsetBuffer::new(rebased.into()) - } + offsets.clone().subtract(offsets[0]) } fn order_desc(modifier: &str) -> Result { diff --git a/datafusion/functions/src/string/common.rs b/datafusion/functions/src/string/common.rs index b51b92e9df1ed..7a5d2573ec257 100644 --- a/datafusion/functions/src/string/common.rs +++ b/datafusion/functions/src/string/common.rs @@ -27,7 +27,7 @@ use arrow::array::{ Array, ArrayRef, AsArray, GenericStringArray, NullBufferBuilder, OffsetSizeTrait, StringViewArray, new_null_array, }; -use arrow::buffer::{Buffer, OffsetBuffer, ScalarBuffer}; +use arrow::buffer::{Buffer, ScalarBuffer}; use arrow::datatypes::DataType; use datafusion_common::Result; use datafusion_common::cast::{as_generic_string_array, as_string_view_array}; @@ -636,15 +636,10 @@ fn case_conversion_ascii_array( let values = Buffer::from_vec(converted); // Shift offsets from `start`-based to 0-based so they index into `values`. - let offsets = if start == 0 { - string_array.offsets().clone() - } else { - let s = O::usize_as(start); - let rebased: Vec = value_offsets.iter().map(|&o| o - s).collect(); - // SAFETY: subtracting a constant from monotonic offsets preserves - // monotonicity, and `start` is the minimum offset, so no underflow. - unsafe { OffsetBuffer::new_unchecked(ScalarBuffer::from(rebased)) } - }; + let offsets = string_array + .offsets() + .clone() + .subtract(string_array.offsets()[0]); let nulls = string_array.nulls().cloned(); // SAFETY: offsets are monotonic and in-bounds for `values`; nulls diff --git a/datafusion/functions/src/unicode/initcap.rs b/datafusion/functions/src/unicode/initcap.rs index 9192f23844f16..8981d59aec8d2 100644 --- a/datafusion/functions/src/unicode/initcap.rs +++ b/datafusion/functions/src/unicode/initcap.rs @@ -18,7 +18,7 @@ use std::sync::Arc; use arrow::array::{Array, ArrayRef, GenericStringArray, OffsetSizeTrait}; -use arrow::buffer::{Buffer, OffsetBuffer}; +use arrow::buffer::Buffer; use arrow::datatypes::DataType; use crate::strings::{GenericStringArrayBuilder, StringViewArrayBuilder}; @@ -217,17 +217,10 @@ fn initcap_ascii_array( } let values = Buffer::from_vec(out); - let out_offsets = if first_offset == 0 { - offsets.clone() - } else { - // For sliced arrays, we need to rebase the offsets to reflect that the - // output only contains the bytes in the visible slice. - let rebased_offsets = offsets - .iter() - .map(|offset| T::usize_as(offset.as_usize() - first_offset)) - .collect::>(); - OffsetBuffer::::new(rebased_offsets.into()) - }; + + // Rebase offsets for sliced arrays to reflect that the + // output only contains the bytes in the visible slice. + let out_offsets = offsets.clone().subtract(offsets[0]); // SAFETY: ASCII case conversion preserves byte length, so the original // string boundaries are preserved. `out_offsets` is either identical to