You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by ze...@apache.org on 2023/06/01 15:52:21 UTC
[arrow] branch main updated: GH-35866: [Go] Provide a copy in `arrow.NestedType.Fields()` implementations (#35867)
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.git
The following commit(s) were added to refs/heads/main by this push:
new e0fd7ef8f1 GH-35866: [Go] Provide a copy in `arrow.NestedType.Fields()` implementations (#35867)
e0fd7ef8f1 is described below
commit e0fd7ef8f16a913913bba706c396f424fba1583a
Author: Alex Shcherbakov <ca...@users.noreply.github.com>
AuthorDate: Thu Jun 1 18:52:13 2023 +0300
GH-35866: [Go] Provide a copy in `arrow.NestedType.Fields()` implementations (#35867)
### Rationale for this change
Data types should be left immutable after they've been constructed.
### What changes are included in this PR?
Provide a copy of fields in the following implementations:
* `*arrow.StructType.Fields()`
* `*arrow.unionType.Fields()`
### Are these changes tested?
`arrow.TestFieldsImmutability` was added to ensure the behavior.
### Are there any user-facing changes?
Now the fields for structs & unions will be immutable.
* Closes: #35866
Authored-by: candiduslynx <ca...@gmail.com>
Signed-off-by: Matt Topol <zo...@gmail.com>
---
go/arrow/datatype_nested.go | 21 +++++++++++++++--
go/arrow/datatype_nested_test.go | 50 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 69 insertions(+), 2 deletions(-)
diff --git a/go/arrow/datatype_nested.go b/go/arrow/datatype_nested.go
index de544251cc..368527b4b2 100644
--- a/go/arrow/datatype_nested.go
+++ b/go/arrow/datatype_nested.go
@@ -27,6 +27,9 @@ import (
type NestedType interface {
DataType
+
+ // Fields method provides a copy of NestedType fields
+ // (so it can be safely mutated and will not result in updating the NestedType).
Fields() []Field
}
@@ -288,7 +291,14 @@ func (t *StructType) String() string {
return o.String()
}
-func (t *StructType) Fields() []Field { return t.fields }
+// Fields method provides a copy of StructType fields
+// (so it can be safely mutated and will not result in updating the StructType).
+func (t *StructType) Fields() []Field {
+ fields := make([]Field, len(t.fields))
+ copy(fields, t.fields)
+ return fields
+}
+
func (t *StructType) Field(i int) Field { return t.fields[i] }
func (t *StructType) FieldByName(name string) (Field, bool) {
@@ -490,7 +500,14 @@ func (t *unionType) init(fields []Field, typeCodes []UnionTypeCode) {
}
}
-func (t unionType) Fields() []Field { return t.children }
+// Fields method provides a copy of union type fields
+// (so it can be safely mutated and will not result in updating the union type).
+func (t unionType) Fields() []Field {
+ fields := make([]Field, len(t.children))
+ copy(fields, t.children)
+ return fields
+}
+
func (t unionType) TypeCodes() []UnionTypeCode { return t.typeCodes }
func (t unionType) ChildIDs() []int { return t.childIDs[:] }
diff --git a/go/arrow/datatype_nested_test.go b/go/arrow/datatype_nested_test.go
index 0f4203b0da..15d7b2e0e3 100644
--- a/go/arrow/datatype_nested_test.go
+++ b/go/arrow/datatype_nested_test.go
@@ -19,6 +19,9 @@ package arrow
import (
"reflect"
"testing"
+
+ "github.com/google/uuid"
+ "github.com/stretchr/testify/assert"
)
func TestListOf(t *testing.T) {
@@ -491,3 +494,50 @@ func TestMapOfWithMetadata(t *testing.T) {
})
}
}
+
+func TestFieldsImmutability(t *testing.T) {
+ cases := []struct {
+ dt NestedType
+ expected []Field
+ }{
+ {
+ dt: ListOfField(Field{Name: "name", Type: PrimitiveTypes.Int64}),
+ expected: ListOfField(Field{Name: "name", Type: PrimitiveTypes.Int64}).Fields(),
+ },
+ {
+ dt: LargeListOfField(Field{Name: "name", Type: PrimitiveTypes.Int64}),
+ expected: LargeListOfField(Field{Name: "name", Type: PrimitiveTypes.Int64}).Fields(),
+ },
+ {
+ dt: FixedSizeListOfField(1, Field{Name: "name", Type: PrimitiveTypes.Int64}),
+ expected: FixedSizeListOfField(1, Field{Name: "name", Type: PrimitiveTypes.Int64}).Fields(),
+ },
+ {
+ dt: MapOf(BinaryTypes.String, PrimitiveTypes.Int64),
+ expected: MapOf(BinaryTypes.String, PrimitiveTypes.Int64).Fields(),
+ },
+ {
+ dt: StructOf(Field{Name: "name", Type: PrimitiveTypes.Int64}),
+ expected: StructOf(Field{Name: "name", Type: PrimitiveTypes.Int64}).Fields(),
+ },
+ {
+ dt: RunEndEncodedOf(BinaryTypes.String, PrimitiveTypes.Int64),
+ expected: RunEndEncodedOf(BinaryTypes.String, PrimitiveTypes.Int64).Fields(),
+ },
+ {
+ dt: UnionOf(DenseMode, []Field{{Name: "name", Type: PrimitiveTypes.Int64}}, []UnionTypeCode{0}),
+ expected: UnionOf(DenseMode, []Field{{Name: "name", Type: PrimitiveTypes.Int64}}, []UnionTypeCode{0}).Fields(),
+ },
+ }
+
+ for _, tc := range cases {
+ t.Run(tc.dt.String(), func(t *testing.T) {
+ fields := tc.dt.Fields()
+ fields[0].Nullable = !fields[0].Nullable
+ fields[0].Name = uuid.NewString()
+ fields[0].Type = nil
+
+ assert.Equal(t, tc.expected, tc.dt.Fields())
+ })
+ }
+}