This is an automated email from the ASF dual-hosted git repository. github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-11906-deeb7256110c6c2325db66ad741c5f56749d3b93 in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
commit b5e7cad208f488cc7d4d50c795d2d180192cb37b Author: NingLin Liu <[email protected]> AuthorDate: Mon Oct 26 04:41:38 2026 +0000 fix(arrow-data): extend Interval(DayTime) as IntervalDayTime in MutableArrayData (#11906) # Which issue does this PR close? - Closes #11862. # Rationale for this change `ArrayData::build` only requires an `Interval(DayTime)` values buffer to be aligned to `align_of::<IntervalDayTime>()` (4 bytes, since it is a `#[repr(C)]` struct of two `i32`s). `MutableArrayData` extended it as `i64`, so `Buffer::typed_data::<i64>` asserted 8-byte alignment and panicked on a valid, 4-byte aligned buffer. Every kernel built on `MutableArrayData` (`zip`, `merge`, `concat` of some layouts, ...) hit this. This is the `DayTime` counterpart of #5917, which #10171 fixed for `MonthDayNano`. # What changes are included in this PR? `build_extend` and `build_extend_nulls` now use `IntervalDayTime` for `Interval(DayTime)`, the same way `MonthDayNano` uses `IntervalMonthDayNano`. The element size is unchanged (8 bytes), so the produced buffers are identical; only the alignment requirement drops to the one `ArrayData` already validates. # Are these changes tested? Yes. Added `test_interval_day_time_aligned_to_4` in `arrow/tests/array_transform.rs`, which builds an `Interval(DayTime)` array on a buffer starting at 4 mod 8, extends it and a null through `MutableArrayData`, and checks the result. It panics at `arrow-buffer/src/buffer/immutable.rs:334` without the change and passes with it. `cargo test -p arrow --test array_transform`, `cargo test -p arrow-data -p arrow-select` and `cargo clippy -p arrow-data --all-targets -- -D warnings` pass. # Are there any user-facing changes? No API changes; kernels no longer panic on 4-byte aligned `Interval(DayTime)` arrays. This PR was prepared with AI assistance and reviewed/tested by the author. --- arrow-data/src/transform/mod.rs | 15 ++++++++++----- arrow/tests/array_transform.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/arrow-data/src/transform/mod.rs b/arrow-data/src/transform/mod.rs index c4cd2bee5b..cc6c20b2fd 100644 --- a/arrow-data/src/transform/mod.rs +++ b/arrow-data/src/transform/mod.rs @@ -23,7 +23,9 @@ use super::{ArrayData, ArrayDataBuilder, ByteView, data::new_buffers}; use crate::bit_mask::set_bits; use arrow_buffer::buffer::{BooleanBuffer, NullBuffer}; -use arrow_buffer::{ArrowNativeType, Buffer, IntervalMonthDayNano, MutableBuffer, bit_util, i256}; +use arrow_buffer::{ + ArrowNativeType, Buffer, IntervalDayTime, IntervalMonthDayNano, MutableBuffer, bit_util, i256, +}; use arrow_schema::{ArrowError, DataType, IntervalUnit, UnionMode}; use half::f16; use num_integer::Integer; @@ -259,8 +261,11 @@ fn build_extend(array: &ArrayData) -> Extend<'_> { DataType::Date64 | DataType::Time64(_) | DataType::Timestamp(_, _) - | DataType::Duration(_) - | DataType::Interval(IntervalUnit::DayTime) => primitive::build_extend::<i64>(array), + | DataType::Duration(_) => primitive::build_extend::<i64>(array), + // `IntervalDayTime` is two `i32`s, so its buffers need only be 4-byte aligned + DataType::Interval(IntervalUnit::DayTime) => { + primitive::build_extend::<IntervalDayTime>(array) + } DataType::Interval(IntervalUnit::MonthDayNano) => { primitive::build_extend::<IntervalMonthDayNano>(array) } @@ -308,8 +313,8 @@ fn build_extend_nulls(data_type: &DataType) -> ExtendNulls { DataType::Date64 | DataType::Time64(_) | DataType::Timestamp(_, _) - | DataType::Duration(_) - | DataType::Interval(IntervalUnit::DayTime) => primitive::extend_nulls::<i64>, + | DataType::Duration(_) => primitive::extend_nulls::<i64>, + DataType::Interval(IntervalUnit::DayTime) => primitive::extend_nulls::<IntervalDayTime>, DataType::Interval(IntervalUnit::MonthDayNano) => { primitive::extend_nulls::<IntervalMonthDayNano> } diff --git a/arrow/tests/array_transform.rs b/arrow/tests/array_transform.rs index ff005b8630..287fa684a3 100644 --- a/arrow/tests/array_transform.rs +++ b/arrow/tests/array_transform.rs @@ -1292,3 +1292,29 @@ fn test_interval_month_day_nano_aligned_to_8() { // roundtripping through arraydata shouldnt panic MutableArrayData::new(vec![&b], false, 0); } + +#[test] +fn test_interval_day_time_aligned_to_4() { + let ty = DataType::Interval(arrow_schema::IntervalUnit::DayTime); + + // `IntervalDayTime` only requires 4-byte alignment, so this slice is valid + // even though it does not start on an 8-byte boundary + let buffer = Buffer::from_slice_ref([0i32, 1, 2, 3, 4]).slice(4); + let b = ArrayData::builder(ty) + .len(2) + .add_buffer(buffer) + .build() + .unwrap(); + + let mut mutable = MutableArrayData::new(vec![&b], true, 3); + mutable.try_extend(0, 0, 2).unwrap(); + mutable.try_extend_nulls(1).unwrap(); + let result = &arrow_array::IntervalDayTimeArray::from(mutable.freeze()); + + let expected = arrow_array::IntervalDayTimeArray::from(vec![ + Some(arrow_buffer::IntervalDayTime::new(1, 2)), + Some(arrow_buffer::IntervalDayTime::new(3, 4)), + None, + ]); + assert_eq!(result, &expected); +}
