From d36a0513450535674009d242f645c58b66b807a4 Mon Sep 17 00:00:00 2001 From: Minh Vu Date: Thu, 6 Aug 2026 00:12:40 +0200 Subject: [PATCH] fix(arrow/scalar): release partial struct extraction --- arrow/scalar/scalar.go | 5 +++++ arrow/scalar/scalar_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/arrow/scalar/scalar.go b/arrow/scalar/scalar.go index dff4c2ed..614de03e 100644 --- a/arrow/scalar/scalar.go +++ b/arrow/scalar/scalar.go @@ -679,6 +679,11 @@ func GetScalar(arr arrow.Array, idx int) (Scalar, error) { for i := range children { child, err := GetScalar(arr.Field(i), idx) if err != nil { + for _, child := range children[:i] { + if releasable, ok := child.(Releasable); ok { + releasable.Release() + } + } return nil, err } children[i] = child diff --git a/arrow/scalar/scalar_test.go b/arrow/scalar/scalar_test.go index 056da477..18a65362 100644 --- a/arrow/scalar/scalar_test.go +++ b/arrow/scalar/scalar_test.go @@ -1388,6 +1388,30 @@ func TestGetScalarIndexOutOfRange(t *testing.T) { assert.ErrorIs(t, err, arrow.ErrIndex) } +func TestGetScalarReleasesPartialStructChildrenOnError(t *testing.T) { + mem := memory.NewCheckedAllocator(memory.NewGoAllocator()) + defer mem.AssertSize(t, 0) + + dt := arrow.StructOf( + arrow.Field{Name: "values", Type: arrow.ListOf(arrow.PrimitiveTypes.Int32)}, + arrow.Field{Name: "view", Type: arrow.BinaryTypes.StringView}, + ) + builder := array.NewStructBuilder(mem, dt) + defer builder.Release() + + builder.Append(true) + listBuilder := builder.FieldBuilder(0).(*array.ListBuilder) + listBuilder.Append(true) + listBuilder.ValueBuilder().(*array.Int32Builder).Append(1) + builder.FieldBuilder(1).(*array.StringViewBuilder).Append("unsupported") + + arr := builder.NewStructArray() + defer arr.Release() + + _, err := scalar.GetScalar(arr, 0) + require.Error(t, err) +} + func TestDictionaryScalarValidateErrors(t *testing.T) { mem := memory.NewCheckedAllocator(memory.DefaultAllocator) defer mem.AssertSize(t, 0)