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 b7e68db  fix(arrow/cdata): handle export struct with no fields (#175)
b7e68db is described below

commit b7e68dbd5cbd0fe144cf5fef5a892835c5b1539e
Author: Matt Topol <[email protected]>
AuthorDate: Mon Oct 28 16:35:13 2024 -0400

    fix(arrow/cdata): handle export struct with no fields (#175)
    
    Fixes #172
    
    Includes a test that reproduced the original reported issue
---
 arrow/cdata/cdata_exports.go        |  7 +++++++
 arrow/cdata/cdata_test.go           | 25 +++++++++++++++++++++++++
 arrow/cdata/cdata_test_framework.go |  8 +++++++-
 3 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/arrow/cdata/cdata_exports.go b/arrow/cdata/cdata_exports.go
index d367348..6d1e038 100644
--- a/arrow/cdata/cdata_exports.go
+++ b/arrow/cdata/cdata_exports.go
@@ -401,6 +401,9 @@ func exportArray(arr arrow.Array, out *CArrowArray, 
outSchema *CArrowSchema) {
                out.children = (**CArrowArray)(unsafe.Pointer(&childPtrs[0]))
        case *array.Struct:
                out.n_children = C.int64_t(arr.NumField())
+               if arr.NumField() == 0 {
+                       return
+               }
                childPtrs := allocateArrowArrayPtrArr(arr.NumField())
                children := allocateArrowArrayArr(arr.NumField())
                for i := 0; i < arr.NumField(); i++ {
@@ -421,6 +424,10 @@ func exportArray(arr arrow.Array, out *CArrowArray, 
outSchema *CArrowSchema) {
                exportArray(arr.Dictionary(), out.dictionary, nil)
        case array.Union:
                out.n_children = C.int64_t(arr.NumFields())
+               if arr.NumFields() == 0 {
+                       return
+               }
+
                childPtrs := allocateArrowArrayPtrArr(arr.NumFields())
                children := allocateArrowArrayArr(arr.NumFields())
                for i := 0; i < arr.NumFields(); i++ {
diff --git a/arrow/cdata/cdata_test.go b/arrow/cdata/cdata_test.go
index 2a86ea6..ebd4fcf 100644
--- a/arrow/cdata/cdata_test.go
+++ b/arrow/cdata/cdata_test.go
@@ -598,6 +598,28 @@ func createTestStructArr() arrow.Array {
        return bld.NewArray()
 }
 
+func createTestEmptyStructArr() arrow.Array {
+       bld := array.NewStructBuilder(memory.DefaultAllocator, arrow.StructOf())
+       defer bld.Release()
+
+       bld.AppendNull()
+       return bld.NewArray()
+}
+
+func createTestEmptyDenseUnionArr() arrow.Array {
+       bld := array.NewEmptyDenseUnionBuilder(memory.DefaultAllocator)
+       defer bld.Release()
+
+       return bld.NewArray()
+}
+
+func createTestEmptySparseUnionArr() arrow.Array {
+       bld := array.NewEmptySparseUnionBuilder(memory.DefaultAllocator)
+       defer bld.Release()
+
+       return bld.NewArray()
+}
+
 func createTestRunEndsArr() arrow.Array {
        bld := array.NewRunEndEncodedBuilder(memory.DefaultAllocator,
                arrow.PrimitiveTypes.Int32, arrow.PrimitiveTypes.Int8)
@@ -687,6 +709,9 @@ func TestNestedArrays(t *testing.T) {
                {"sparse union", createTestSparseUnion},
                {"dense union", createTestDenseUnion},
                {"run-end encoded", createTestRunEndsArr},
+               {"empty struct", createTestEmptyStructArr},
+               {"empty dense union", createTestEmptyDenseUnionArr},
+               {"empty sparse union", createTestEmptySparseUnionArr},
        }
 
        for _, tt := range tests {
diff --git a/arrow/cdata/cdata_test_framework.go 
b/arrow/cdata/cdata_test_framework.go
index c979c3f..331e80b 100644
--- a/arrow/cdata/cdata_test_framework.go
+++ b/arrow/cdata/cdata_test_framework.go
@@ -309,6 +309,9 @@ func createCArr(arr arrow.Array, alloc 
*mallocator.Mallocator) *CArrowArray {
                children = (**CArrowArray)(unsafe.Pointer(&clist[0]))
                nchildren += 1
        case *array.Struct:
+               if arr.NumField() == 0 {
+                       break
+               }
                clist := allocateChildrenPtrArr(alloc, arr.NumField())
                for i := 0; i < arr.NumField(); i++ {
                        clist[i] = createCArr(arr.Field(i), alloc)
@@ -322,6 +325,9 @@ func createCArr(arr arrow.Array, alloc 
*mallocator.Mallocator) *CArrowArray {
                children = (**CArrowArray)(unsafe.Pointer(&clist[0]))
                nchildren += 2
        case array.Union:
+               if arr.NumFields() == 0 {
+                       break
+               }
                clist := allocateChildrenPtrArr(alloc, arr.NumFields())
                for i := 0; i < arr.NumFields(); i++ {
                        clist[i] = createCArr(arr.Field(i), alloc)
@@ -356,7 +362,7 @@ func createCArr(arr arrow.Array, alloc 
*mallocator.Mallocator) *CArrowArray {
        tr.bufs = make([][]byte, 0, nbuffers)
        cbufs := allocateBufferMallocatorPtrArr(alloc, nbuffers)
        for i, b := range buffers[bufOffset:] {
-               if b != nil {
+               if b != nil && b.Len() > 0 {
                        raw := alloc.Allocate(b.Len())
                        copy(raw, b.Bytes())
                        tr.bufs = append(tr.bufs, raw)

Reply via email to