You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iceberg.apache.org by ze...@apache.org on 2026/06/08 19:13:55 UTC
(iceberg-go) branch main updated: fix: preserve nested field IDs when filling missing columns (#1168)
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/iceberg-go.git
The following commit(s) were added to refs/heads/main by this push:
new 8f4faf40 fix: preserve nested field IDs when filling missing columns (#1168)
8f4faf40 is described below
commit 8f4faf40adee28a63eb282378146e41df193dc6e
Author: Blue Li <10...@users.noreply.github.com>
AuthorDate: Tue Jun 9 03:13:49 2026 +0800
fix: preserve nested field IDs when filling missing columns (#1168)
Fixes a bug where generating a null array for a completely missing
nested column (e.g., during schema evolution) accidentally drops the
inner `PARQUET:field_id` metadata due to a hardcoded `false` flag. This
correctly propagates `includeFieldIDs` and resolves the `record schema
does not match writer's` error when writing to `pqarrow`.
---
table/arrow_utils.go | 2 +-
table/arrow_utils_test.go | 60 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/table/arrow_utils.go b/table/arrow_utils.go
index d490ad8e..375b6b94 100644
--- a/table/arrow_utils.go
+++ b/table/arrow_utils.go
@@ -1051,7 +1051,7 @@ func (a *arrowProjectionVisitor) Struct(st iceberg.StructType, structArr arrow.A
fieldArrs[i] = arr
fields[i] = a.constructField(field, arr.DataType())
} else {
- dt := retOrPanic(TypeToArrowType(field.Type, false, a.useLargeTypes))
+ dt := retOrPanic(TypeToArrowType(field.Type, a.includeFieldIDs, a.useLargeTypes))
alloc := compute.GetAllocator(a.ctx)
switch {
diff --git a/table/arrow_utils_test.go b/table/arrow_utils_test.go
index 1ecc5f1f..97a8a3fd 100644
--- a/table/arrow_utils_test.go
+++ b/table/arrow_utils_test.go
@@ -1845,3 +1845,63 @@ func TestToRequestedSchemaWriteDefaultJSONRoundTrip(t *testing.T) {
})
}
}
+
+func TestToRequestedSchemaMissingNestedFieldID(t *testing.T) {
+ mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
+ defer mem.AssertSize(t, 0)
+
+ // Create an Arrow schema that lacks the nested list completely
+ schemaWithoutMetadata := arrow.NewSchema([]arrow.Field{
+ {
+ Name: "other_field", Type: arrow.PrimitiveTypes.Int32,
+ },
+ }, nil)
+
+ bldr := array.NewRecordBuilder(mem, schemaWithoutMetadata)
+ defer bldr.Release()
+
+ const data = `{"other_field": 1}
+ {"other_field": 2}`
+
+ s := bufio.NewScanner(strings.NewReader(data))
+ for s.Scan() {
+ require.NoError(t, bldr.UnmarshalJSON(s.Bytes()))
+ }
+
+ rec := bldr.NewRecordBatch()
+ defer rec.Release()
+
+ // The file schema lacks the nested_list
+ fileIcesc := iceberg.NewSchema(1, iceberg.NestedField{
+ ID: 10, Name: "other_field", Type: iceberg.PrimitiveTypes.Int32, Required: false,
+ })
+
+ // The requested schema has the nested_list
+ reqIcesc := iceberg.NewSchema(1, iceberg.NestedField{
+ ID: 10, Name: "other_field", Type: iceberg.PrimitiveTypes.Int32, Required: false,
+ }, iceberg.NestedField{
+ ID: 11, Name: "nested_list", Type: &iceberg.ListType{
+ ElementID: 12, Element: iceberg.PrimitiveTypes.String, ElementRequired: false,
+ }, Required: false,
+ })
+
+ rec2, err := table.ToRequestedSchema(context.Background(), reqIcesc, fileIcesc, rec, table.SchemaOptions{IncludeFieldIDs: true})
+ require.NoError(t, err)
+ defer rec2.Release()
+
+ targetSchema := arrow.NewSchema([]arrow.Field{
+ {
+ Name: "other_field", Type: arrow.PrimitiveTypes.Int32, Nullable: true,
+ Metadata: arrow.MetadataFrom(map[string]string{table.ArrowParquetFieldIDKey: "10"}),
+ },
+ {
+ Name: "nested_list", Type: arrow.ListOfField(arrow.Field{
+ Name: "element", Type: arrow.BinaryTypes.String, Nullable: true,
+ Metadata: arrow.MetadataFrom(map[string]string{table.ArrowParquetFieldIDKey: "12"}),
+ }),
+ Metadata: arrow.MetadataFrom(map[string]string{table.ArrowParquetFieldIDKey: "11"}),
+ Nullable: true,
+ },
+ }, nil)
+ require.True(t, targetSchema.Equal(rec2.Schema()), "Schema is not perfectly equal")
+}