This is an automated email from the ASF dual-hosted git repository.
zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-go.git
The following commit(s) were added to refs/heads/main by this push:
new 9d23a674 fix(array): support dense union slice offsets (#877)
9d23a674 is described below
commit 9d23a674a30f766b93e4ba878ede62a30040588f
Author: Minh Vu <[email protected]>
AuthorDate: Thu Jul 2 19:01:09 2026 +0200
fix(array): support dense union slice offsets (#877)
Normalize the type-id and offset value buffers to each input array's
logical window before constructing dense union data, so a dense union can be
built from type-id and offset arrays that were sliced at different offsets. The
union is built at offset 0 with zero-copy buffer sharing.
---
arrow/array/union.go | 20 ++++++++++++++++++--
arrow/array/union_test.go | 44 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+), 2 deletions(-)
diff --git a/arrow/array/union.go b/arrow/array/union.go
index d9d18267..f3159242 100644
--- a/arrow/array/union.go
+++ b/arrow/array/union.go
@@ -558,14 +558,30 @@ func NewDenseUnionFromArraysWithFieldCodes(typeIDs,
offsets arrow.Array, childre
}
ty := arrow.DenseUnionFromArrays(children, fields, codes)
- buffers := []*memory.Buffer{nil, typeIDs.Data().Buffers()[1],
offsets.Data().Buffers()[1]}
+ typeIDBuffer := typeIDs.Data().Buffers()[1]
+ if typeIDBuffer != nil {
+ typeIDBuffer = memory.SliceBuffer(typeIDBuffer,
+ arrow.Int8Traits.BytesRequired(typeIDs.Data().Offset()),
+ arrow.Int8Traits.BytesRequired(typeIDs.Len()))
+ defer typeIDBuffer.Release()
+ }
+
+ offsetBuffer := offsets.Data().Buffers()[1]
+ if offsetBuffer != nil {
+ offsetBuffer = memory.SliceBuffer(offsetBuffer,
+
arrow.Int32Traits.BytesRequired(offsets.Data().Offset()),
+ arrow.Int32Traits.BytesRequired(offsets.Len()))
+ defer offsetBuffer.Release()
+ }
+
+ buffers := []*memory.Buffer{nil, typeIDBuffer, offsetBuffer}
childData := make([]arrow.ArrayData, len(children))
for i, c := range children {
childData[i] = c.Data()
}
- data := NewData(ty, typeIDs.Len(), buffers, childData, 0,
typeIDs.Data().Offset())
+ data := NewData(ty, typeIDs.Len(), buffers, childData, 0, 0)
defer data.Release()
return NewDenseUnionData(data), nil
}
diff --git a/arrow/array/union_test.go b/arrow/array/union_test.go
index 5d975d57..7421b1bc 100644
--- a/arrow/array/union_test.go
+++ b/arrow/array/union_test.go
@@ -471,6 +471,50 @@ func (s *UnionFactorySuite) TestMakeDenseUnions() {
s.Nil(result)
s.EqualError(err, "arrow/array: union typeIDs and offsets must
have the same length")
})
+
+ s.Run("mismatched type id and offset data offsets", func() {
+ expected, err := array.NewDenseUnionFromArrays(s.typeIDs,
offsets, children)
+ s.NoError(err)
+ defer expected.Release()
+
+ baseTypeIDs := s.typeidsFromSlice(3, 0, 1, 2, 0, 1, 3, 2, 0, 2,
1)
+ defer baseTypeIDs.Release()
+ slicedTypeIDs := array.NewSlice(baseTypeIDs, 1,
int64(baseTypeIDs.Len()))
+ defer slicedTypeIDs.Release()
+
+ result, err := array.NewDenseUnionFromArrays(slicedTypeIDs,
offsets, children)
+ s.NoError(err)
+ defer result.Release()
+ s.Zero(result.Data().Offset())
+ s.NoError(result.ValidateFull())
+ s.True(array.Equal(expected, result))
+
+ baseOffsets := s.offsetsFromSlice(99, 0, 0, 0, 1, 1, 0, 1, 2,
1, 2)
+ defer baseOffsets.Release()
+ slicedOffsets := array.NewSlice(baseOffsets, 1,
int64(baseOffsets.Len()))
+ defer slicedOffsets.Release()
+
+ result, err = array.NewDenseUnionFromArrays(s.typeIDs,
slicedOffsets, children)
+ s.NoError(err)
+ defer result.Release()
+ s.Zero(result.Data().Offset())
+ s.NoError(result.ValidateFull())
+ s.True(array.Equal(expected, result))
+
+ baseOffsets = s.offsetsFromSlice(-1, -1, 0, 0, 0, 1, 1, 0, 1,
2, 1, 2)
+ defer baseOffsets.Release()
+ slicedOffsets = array.NewSlice(baseOffsets, 2,
int64(baseOffsets.Len()))
+ defer slicedOffsets.Release()
+ s.Equal(1, slicedTypeIDs.Data().Offset())
+ s.Equal(2, slicedOffsets.Data().Offset())
+
+ result, err = array.NewDenseUnionFromArrays(slicedTypeIDs,
slicedOffsets, children)
+ s.NoError(err)
+ defer result.Release()
+ s.Zero(result.Data().Offset())
+ s.NoError(result.ValidateFull())
+ s.True(array.Equal(expected, result))
+ })
}
func (s *UnionFactorySuite) TestDenseUnionStringRoundTrip() {