This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/main by this push:
new 9827aaad30 fix(arrow-data): account for FixedSizeList parent offset in
MutableArrayData (#11636)
9827aaad30 is described below
commit 9827aaad30258bf348a0d4f2b792505d6d24a88f
Author: Chang Yong Lik <[email protected]>
AuthorDate: Sat Oct 17 07:45:08 2026 +0000
fix(arrow-data): account for FixedSizeList parent offset in
MutableArrayData (#11636)
# Which issue does this PR close?
- Closes #11588.
# Rationale for this change
`MutableArrayData::extend` on a `FixedSizeList` with a nonzero parent
offset copied the child values from the start of the child instead of
from the offset.
# What changes are included in this PR?
`build_extend` in `transform/fixed_size_list.rs` adds `array.offset()`
to `start` before computing the child range, the same way #10934 did for
structs.
# Are these changes tested?
Yes, `test_extend_fixed_size_list_accounts_for_parent_offset` in
`arrow-data/src/data.rs` (next to the struct test from #10934). It fails
without the fix.
# Are there any significant user-facing changes?
No.
AI use: I used Claude Code to find the cause and write the fix and test.
I reviewed the change and checked that the test fails without the fix.
---
arrow-data/src/data.rs | 23 +++++++++++++++++++++++
arrow-data/src/transform/fixed_size_list.rs | 21 ++++++++++++++++++++-
2 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/arrow-data/src/data.rs b/arrow-data/src/data.rs
index d58bdcf963..6d34884808 100644
--- a/arrow-data/src/data.rs
+++ b/arrow-data/src/data.rs
@@ -2760,6 +2760,29 @@ mod tests {
assert_eq!(output.child_data()[0].buffer::<i32>(0), &[1, 2, 3, 4]);
}
+ #[test]
+ fn test_extend_fixed_size_list_accounts_for_parent_offset() {
+ let field = Arc::new(Field::new("item", DataType::Int32, false));
+ let child = ArrayData::builder(DataType::Int32)
+ .len(6)
+ .add_buffer(Buffer::from_slice_ref([0, 1, 2, 3, 4, 5]))
+ .build()
+ .unwrap();
+
+ let data = ArrayData::builder(DataType::FixedSizeList(field, 2))
+ .len(2)
+ .offset(1)
+ .add_child_data(child)
+ .build()
+ .unwrap();
+
+ let mut mutable = MutableArrayData::new(vec![&data], false,
data.len());
+ mutable.try_extend(0, 0, data.len()).unwrap();
+ let output = mutable.freeze();
+
+ assert_eq!(output.child_data()[0].buffer::<i32>(0), &[2, 3, 4, 5]);
+ }
+
#[test]
fn test_null_count() {
let mut bit_v: [u8; 2] = [0; 2];
diff --git a/arrow-data/src/transform/fixed_size_list.rs
b/arrow-data/src/transform/fixed_size_list.rs
index de791884b9..f5234ec712 100644
--- a/arrow-data/src/transform/fixed_size_list.rs
+++ b/arrow-data/src/transform/fixed_size_list.rs
@@ -25,11 +25,30 @@ pub(super) fn build_extend(array: &ArrayData) -> Extend<'_>
{
DataType::FixedSizeList(_, i) => *i as usize,
_ => unreachable!(),
};
+ let offset = array.offset();
Box::new(
move |mutable: &mut _MutableArrayData, index: usize, start: usize,
len: usize| {
+ let start = start.checked_add(offset).ok_or_else(|| {
+ ArrowError::InvalidArgumentError(format!(
+ "fixed size list offset {offset} with start {start}
overflows usize"
+ ))
+ })?;
+ let end = start.checked_add(len).ok_or_else(|| {
+ ArrowError::InvalidArgumentError(format!(
+ "fixed size list start {start} with length {len} overflows
usize"
+ ))
+ })?;
+ let (child_start, child_end) = start
+ .checked_mul(size)
+ .zip(end.checked_mul(size))
+ .ok_or_else(|| {
+ ArrowError::InvalidArgumentError(format!(
+ "fixed size list range {start}..{end} with size {size}
overflows usize"
+ ))
+ })?;
for child in &mut mutable.child_data {
- child.try_extend(index, start * size, (start + len) * size)?;
+ child.try_extend(index, child_start, child_end)?;
}
Ok(())
},