Skip to content

Commit ab4e790

Browse files
committed
fix(arreflect): full multi-level ptr deref in all builder loops, add tests
Replace single-level if-isPtr-Elem() with for-Kind-Ptr-deref loop in: buildPrimitiveArray, iterSlice, buildStructArray, buildMapArray, buildFixedSizeListArray — matching buildDictionaryArray/buildListLikeArray. Add multi_level_pointer_int32 and multi_level_pointer_struct tests.
1 parent a7d7773 commit ab4e790

2 files changed

Lines changed: 67 additions & 22 deletions

File tree

arrow/array/arreflect/reflect_go_to_arrow.go

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,16 @@ func buildPrimitiveArray(vals reflect.Value, mem memory.Allocator) (arrow.Array,
9898
for i := 0; i < vals.Len(); i++ {
9999
v := vals.Index(i)
100100
if isPtr {
101-
if v.IsNil() {
102-
b.AppendNull()
101+
for v.Kind() == reflect.Ptr {
102+
if v.IsNil() {
103+
b.AppendNull()
104+
break
105+
}
106+
v = v.Elem()
107+
}
108+
if v.Kind() == reflect.Ptr {
103109
continue
104110
}
105-
v = v.Elem()
106111
}
107112
if err := appendPrimitiveValue(b, v, dt); err != nil {
108113
return nil, err
@@ -207,11 +212,16 @@ func iterSlice(vals reflect.Value, isPtr bool, appendNull func(), appendVal func
207212
for i := 0; i < vals.Len(); i++ {
208213
v := vals.Index(i)
209214
if isPtr {
210-
if v.IsNil() {
211-
appendNull()
215+
for v.Kind() == reflect.Ptr {
216+
if v.IsNil() {
217+
appendNull()
218+
break
219+
}
220+
v = v.Elem()
221+
}
222+
if v.Kind() == reflect.Ptr {
212223
continue
213224
}
214-
v = v.Elem()
215225
}
216226
if err := appendVal(v); err != nil {
217227
return err
@@ -421,11 +431,16 @@ func buildStructArray(vals reflect.Value, mem memory.Allocator) (arrow.Array, er
421431
for i := 0; i < vals.Len(); i++ {
422432
v := vals.Index(i)
423433
if isPtr {
424-
if v.IsNil() {
425-
sb.AppendNull()
434+
for v.Kind() == reflect.Ptr {
435+
if v.IsNil() {
436+
sb.AppendNull()
437+
break
438+
}
439+
v = v.Elem()
440+
}
441+
if v.Kind() == reflect.Ptr {
426442
continue
427443
}
428-
v = v.Elem()
429444
}
430445
sb.Append(true)
431446
for fi, fm := range fields {
@@ -787,11 +802,16 @@ func buildMapArray(vals reflect.Value, mem memory.Allocator) (arrow.Array, error
787802
for i := 0; i < vals.Len(); i++ {
788803
m := vals.Index(i)
789804
if isPtr {
790-
if m.IsNil() {
791-
mb.AppendNull()
805+
for m.Kind() == reflect.Ptr {
806+
if m.IsNil() {
807+
mb.AppendNull()
808+
break
809+
}
810+
m = m.Elem()
811+
}
812+
if m.Kind() == reflect.Ptr {
792813
continue
793814
}
794-
m = m.Elem()
795815
}
796816
if m.IsNil() {
797817
mb.AppendNull()
@@ -841,11 +861,16 @@ func buildFixedSizeListArray(vals reflect.Value, mem memory.Allocator) (arrow.Ar
841861
for i := 0; i < vals.Len(); i++ {
842862
elem := vals.Index(i)
843863
if isPtr {
844-
if elem.IsNil() {
845-
fb.AppendNull()
864+
for elem.Kind() == reflect.Ptr {
865+
if elem.IsNil() {
866+
fb.AppendNull()
867+
break
868+
}
869+
elem = elem.Elem()
870+
}
871+
if elem.Kind() == reflect.Ptr {
846872
continue
847873
}
848-
elem = elem.Elem()
849874
}
850875
fb.Append(true)
851876
for j := 0; j < int(n); j++ {

arrow/array/arreflect/reflect_go_to_arrow_test.go

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,19 @@ func TestBuildPrimitiveArray(t *testing.T) {
4848
}
4949
})
5050

51-
t.Run("string", func(t *testing.T) {
52-
vals := []string{"hello", "world", "foo"}
51+
t.Run("multi_level_pointer_int32", func(t *testing.T) {
52+
v := int32(42)
53+
pv := &v
54+
var nilPv *int32
55+
vals := []**int32{&pv, &nilPv, &pv}
5356
arr, err := buildArray(reflect.ValueOf(vals), tagOpts{}, mem)
5457
require.NoError(t, err)
5558
defer arr.Release()
56-
assert.Equal(t, arrow.STRING, arr.DataType().ID())
57-
typed := arr.(*array.String)
58-
for i, want := range vals {
59-
assert.Equal(t, want, typed.Value(i), "[%d] value mismatch", i)
60-
}
59+
assert.Equal(t, 3, arr.Len())
60+
assert.False(t, arr.IsNull(0))
61+
assert.True(t, arr.IsNull(1))
62+
assert.False(t, arr.IsNull(2))
63+
assert.Equal(t, int32(42), arr.(*array.Int32).Value(0))
6164
})
6265

6366
t.Run("pointer_with_null", func(t *testing.T) {
@@ -312,6 +315,23 @@ func TestBuildStructArray(t *testing.T) {
312315
assert.Equal(t, int32(10), bxArr.Value(0))
313316
assert.Equal(t, int32(20), bxArr.Value(1))
314317
})
318+
319+
t.Run("multi_level_pointer_struct", func(t *testing.T) {
320+
type S struct {
321+
X int32
322+
}
323+
s := S{X: 99}
324+
ps := &s
325+
var nilPs *S
326+
vals := []**S{&ps, &nilPs, &ps}
327+
arr, err := buildArray(reflect.ValueOf(vals), tagOpts{}, mem)
328+
require.NoError(t, err)
329+
defer arr.Release()
330+
assert.Equal(t, 3, arr.Len())
331+
assert.False(t, arr.IsNull(0))
332+
assert.True(t, arr.IsNull(1))
333+
assert.False(t, arr.IsNull(2))
334+
})
315335
}
316336

317337
func TestBuildListArray(t *testing.T) {

0 commit comments

Comments
 (0)