Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions arrow/extensions/variant.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,10 @@ func NewVariantType(storage arrow.DataType) (*VariantType, error) {
dt = dt.(arrow.ExtensionType).StorageType()
}

if dt.ID() == arrow.NULL {
return nil, fmt.Errorf("%w: typed_value field must not be null type", arrow.ErrInvalid)
}

if nt, ok := dt.(arrow.NestedType); ok {
if !validNestedType(nt) {
return nil, fmt.Errorf("%w: typed_value field must be a valid nested type, got %s", arrow.ErrInvalid, typedValueField.Type)
Expand Down Expand Up @@ -295,7 +299,10 @@ func validStruct(s *arrow.StructType) bool {
switch s.NumFields() {
case 1:
f := s.Field(0)
return (f.Name == "value" && isBinary(f.Type)) || f.Name == "typed_value"
if f.Name == "value" {
return isBinary(f.Type)
}
return f.Name == "typed_value" && f.Type.ID() != arrow.NULL
case 2:
valField, ok := s.FieldByName("value")
if !ok || !valField.Nullable || !isBinary(valField.Type) {
Expand All @@ -311,7 +318,7 @@ func validStruct(s *arrow.StructType) bool {
return validNestedType(nt)
}

return true
return typedField.Type.ID() != arrow.NULL
default:
return false
}
Expand Down
10 changes: 10 additions & 0 deletions arrow/extensions/variant_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ func TestVariantExtensionType(t *testing.T) {
arrow.Field{Name: "metadata", Type: arrow.BinaryTypes.String, Nullable: false},
arrow.Field{Name: "value", Type: arrow.BinaryTypes.Binary, Nullable: false}),
"metadata field must be non-nullable binary type, got utf8"},
{arrow.StructOf(
arrow.Field{Name: "metadata", Type: arrow.BinaryTypes.Binary, Nullable: false},
arrow.Field{Name: "value", Type: arrow.BinaryTypes.Binary, Nullable: true},
arrow.Field{Name: "typed_value", Type: arrow.Null, Nullable: true}),
"typed_value field must not be null type"},
}

for _, tt := range tests {
Expand Down Expand Up @@ -113,6 +118,11 @@ func TestVariantExtensionBadNestedTypes(t *testing.T) {
), Nullable: false})},
{"empty struct elem", arrow.StructOf(
arrow.Field{Name: "foobar", Type: arrow.StructOf(), Nullable: false})},
{"null typed_value in shredded field", arrow.StructOf(
arrow.Field{Name: "foobar", Type: arrow.StructOf(
arrow.Field{Name: "value", Type: arrow.BinaryTypes.Binary, Nullable: true},
arrow.Field{Name: "typed_value", Type: arrow.Null, Nullable: true},
), Nullable: false})},
{"non-nullable two elem struct", arrow.StructOf(
arrow.Field{Name: "foobar", Type: arrow.StructOf(
arrow.Field{Name: "value", Type: arrow.BinaryTypes.Binary, Nullable: true},
Expand Down