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 0cd79a04 fix(parquet/pqarrow): require Variant value field when
writing (#1242)
0cd79a04 is described below
commit 0cd79a04549ca614df10bc529bba611ed6d0fcfa
Author: Digvijay <[email protected]>
AuthorDate: Mon Aug 31 10:06:33 2026 -0500
fix(parquet/pqarrow): require Variant value field when writing (#1242)
### Rationale for this change
Consensus in apache/parquet-format#591 is that the Variant `value` field
is mandatory for writers. arrow-go currently omits it when a shredded
schema has only `metadata` + `typed_value`.
Reading files that already omit `value` should still work.
Fixes #1204
### What changes are included in this PR?
- `ToParquet` errors if a Variant extension type has no `value` field
- `FromParquet` still accepts Variant groups without `value`
### Are these changes tested?
- `go test ./parquet/pqarrow -run
'TestVariantValueRequiredOnWrite|TestReadVariantWithoutValueField|TestConvertSchemaParquetVariant|TestShreddedVariantSchema'`
### Are there any user-facing changes?
Yes — writing a Variant schema without a `value` field now returns
`arrow.ErrInvalid`. Reading such files is unchanged.
Signed-off-by: Digvijay <[email protected]>
---
parquet/pqarrow/schema.go | 15 +++++++++------
parquet/pqarrow/schema_test.go | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 43 insertions(+), 6 deletions(-)
diff --git a/parquet/pqarrow/schema.go b/parquet/pqarrow/schema.go
index d2a97559..2a13ea33 100644
--- a/parquet/pqarrow/schema.go
+++ b/parquet/pqarrow/schema.go
@@ -265,13 +265,16 @@ func variantToNode(t *extensions.VariantType, field
arrow.Field, props *parquet.
return nil, err
}
- if value := t.Value(); value.Type != nil {
- valueField, err := fieldToNode("value", value, props, arrProps)
- if err != nil {
- return nil, err
- }
- fields = append(fields, valueField)
+ value := t.Value()
+ if value.Type == nil {
+ return nil, fmt.Errorf("%w: variant 'value' field is required
when writing Parquet", arrow.ErrInvalid)
+ }
+
+ valueField, err := fieldToNode("value", value, props, arrProps)
+ if err != nil {
+ return nil, err
}
+ fields = append(fields, valueField)
if typed := t.TypedValue(); typed.Type != nil {
typedValue, err := fieldToNode("typed_value", typed, props,
arrProps)
diff --git a/parquet/pqarrow/schema_test.go b/parquet/pqarrow/schema_test.go
index db72c22a..6d9465cb 100644
--- a/parquet/pqarrow/schema_test.go
+++ b/parquet/pqarrow/schema_test.go
@@ -1334,3 +1334,37 @@ func TestShreddedVariantSchema(t *testing.T) {
assert.True(t, arrSchema.Equal(arrsc), "expected: %s\ngot: %s",
arrSchema, arrsc)
}
+
+func TestVariantValueRequiredOnWrite(t *testing.T) {
+ vt, err := extensions.NewVariantType(arrow.StructOf(
+ arrow.Field{Name: "metadata", Type: arrow.BinaryTypes.Binary,
Nullable: false},
+ arrow.Field{Name: "typed_value", Type:
arrow.PrimitiveTypes.Int32, Nullable: true},
+ ))
+ require.NoError(t, err)
+
+ arrSchema := arrow.NewSchema([]arrow.Field{
+ {Name: "variant_col", Type: vt, Nullable: true},
+ }, nil)
+ _, err = pqarrow.ToParquet(arrSchema, nil, pqarrow.DefaultWriterProps())
+ require.Error(t, err)
+ assert.ErrorIs(t, err, arrow.ErrInvalid)
+ assert.ErrorContains(t, err, "variant 'value' field is required when
writing Parquet")
+}
+
+func TestReadVariantWithoutValueField(t *testing.T) {
+ metadata := schema.NewByteArrayNode("metadata",
parquet.Repetitions.Required, -1)
+ typed :=
schema.MustPrimitive(schema.NewPrimitiveNodeLogical("typed_value",
parquet.Repetitions.Optional,
+ schema.NewIntLogicalType(32, true), parquet.Types.Int32, 0, -1))
+ variant, err := schema.NewGroupNodeLogical("var",
parquet.Repetitions.Optional,
+ schema.FieldList{metadata, typed}, schema.VariantLogicalType{},
-1)
+ require.NoError(t, err)
+
+ pqschema :=
schema.NewSchema(schema.MustGroup(schema.NewGroupNode("schema",
parquet.Repetitions.Required, schema.FieldList{variant}, -1)))
+ outSchema, err := pqarrow.FromParquet(pqschema, nil, nil)
+ require.NoError(t, err)
+
+ vt, ok := outSchema.Field(0).Type.(*extensions.VariantType)
+ require.True(t, ok)
+ assert.Nil(t, vt.Value().Type)
+ assert.Equal(t, arrow.PrimitiveTypes.Int32, vt.TypedValue().Type)
+}