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 0d21f8e4 fix(arrow/scalar): release partial children after failed 
struct extraction (#1118)
0d21f8e4 is described below

commit 0d21f8e4ef2a21b0963356f935ed2b16e35bfbe4
Author: Minh Vu <[email protected]>
AuthorDate: Mon Aug 10 19:02:28 2026 +0200

    fix(arrow/scalar): release partial children after failed struct extraction 
(#1118)
    
    ### Rationale for this change
    
    GetScalar can create children before a later Struct child fails
    conversion. Returning immediately leaves the children already created on
    the error path unreleased.
    
    ### What changes are included in this PR?
    
    Release partial children when extraction fails while preserving
    ownership for a successfully built struct scalar. The regression test
    uses a list child followed by an unsupported view child.
    
    ### Are these changes tested?
    
    - `go test ./arrow/scalar`
    
    ### Are there any user-facing changes?
    
    No API changes. This corrects the reported behavior while preserving the
    existing ownership and compatibility contracts.
---
 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 535eb367..194b11b3 100644
--- a/arrow/scalar/scalar.go
+++ b/arrow/scalar/scalar.go
@@ -677,6 +677,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 36557f2f..24cb7ba0 100644
--- a/arrow/scalar/scalar_test.go
+++ b/arrow/scalar/scalar_test.go
@@ -1635,6 +1635,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)

Reply via email to