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)
+}

Reply via email to