This is an automated email from the ASF dual-hosted git repository.

alamb pushed a commit to branch 57_maintenance
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git


The following commit(s) were added to refs/heads/57_maintenance by this push:
     new 8fd4fdbccd [57_maintenance] Fix sliced sparse union ArrayData 
conversion (#11812)
8fd4fdbccd is described below

commit 8fd4fdbccdc02b75bfe7acc6a8f69c6b4fb73923
Author: Jeffrey Vo <[email protected]>
AuthorDate: Fri Oct 23 00:22:46 2026 +0900

    [57_maintenance] Fix sliced sparse union ArrayData conversion (#11812)
    
    - Backport https://github.com/apache/arrow-rs/pull/11649
    - For inclusion in https://github.com/apache/arrow-rs/issues/11666
    
    Cherry-pick of
    
https://github.com/apache/arrow-rs/commit/a9341121687aea7881063ff07b88c14967ee9a9d
    
    Co-authored-by: Kyon <[email protected]>
---
 arrow-array/src/array/union_array.rs | 55 +++++++++++++++++++++++++++++++++++-
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/arrow-array/src/array/union_array.rs 
b/arrow-array/src/array/union_array.rs
index 73e3045faa..cc2d0a17eb 100644
--- a/arrow-array/src/array/union_array.rs
+++ b/arrow-array/src/array/union_array.rs
@@ -702,7 +702,11 @@ impl From<ArrayData> for UnionArray {
         let max_id = fields.iter().map(|(i, _)| i).max().unwrap_or_default() 
as usize;
         let mut boxed_fields = vec![None; max_id + 1];
         for (cd, (field_id, _)) in data.child_data().iter().zip(fields.iter()) 
{
-            boxed_fields[field_id as usize] = Some(make_array(cd.clone()));
+            let cd = match mode {
+                UnionMode::Sparse => cd.slice(data.offset(), data.len()),
+                UnionMode::Dense => cd.clone(),
+            };
+            boxed_fields[field_id as usize] = Some(make_array(cd));
         }
         Self {
             data_type: data.data_type().clone(),
@@ -1685,6 +1689,55 @@ mod tests {
         test_slice_union(record_batch_slice);
     }
 
+    #[test]
+    fn test_union_from_sliced_array_data() {
+        for mode in [UnionMode::Sparse, UnionMode::Dense] {
+            let fields = UnionFields::try_new(
+                [3, 7],
+                [
+                    Field::new("ints", DataType::Int32, false),
+                    Field::new("floats", DataType::Float64, false),
+                ],
+            )
+            .unwrap();
+            let offsets = (mode == UnionMode::Dense).then(|| vec![0, 1, 2, 
3].into());
+            let array = UnionArray::try_new(
+                fields,
+                vec![3, 7, 3, 7].into(),
+                offsets,
+                vec![
+                    Arc::new(Int32Array::from(vec![10, 20, 30, 40])),
+                    Arc::new(Float64Array::from(vec![1.0, 2.0, 3.0, 4.0])),
+                ],
+            )
+            .unwrap();
+            for (offset, len) in [(1, 2), (0, 2), (4, 0), (0, 4)] {
+                let expected = array.slice(offset, len);
+                let actual = make_array(array.to_data().slice(offset, len));
+                let actual = 
actual.as_any().downcast_ref::<UnionArray>().unwrap();
+                for i in 0..len {
+                    assert_eq!(actual.value(i).to_data(), 
expected.value(i).to_data());
+                }
+                assert_eq!(actual.to_data(), expected.to_data());
+            }
+        }
+    }
+
+    #[test]
+    fn test_sparse_union_from_sliced_array_data_logical_nulls() {
+        let child = Int32Array::from(vec![Some(10), None, Some(30)]);
+        let fields =
+            UnionFields::try_new([0], [Field::new("ints", DataType::Int32, 
true)]).unwrap();
+        let array =
+            UnionArray::try_new(fields, vec![0, 0, 0].into(), None, 
vec![Arc::new(child)]).unwrap();
+        for (offset, len) in [(0, 1), (1, 1), (2, 1), (3, 0)] {
+            let expected = array.slice(offset, len);
+            let actual = make_array(array.to_data().slice(offset, len));
+            assert_eq!(actual.logical_nulls(), expected.logical_nulls());
+            assert_eq!(actual.to_data(), expected.to_data());
+        }
+    }
+
     #[test]
     fn test_custom_type_ids() {
         let data_type = DataType::Union(

Reply via email to