Skip to content

[VL] Validate parquet field ids on the Iceberg write path - #12956

Draft
malinjawi wants to merge 1 commit into
apache:mainfrom
malinjawi:split/parquet-field-id-resolver
Draft

[VL] Validate parquet field ids on the Iceberg write path#12956
malinjawi wants to merge 1 commit into
apache:mainfrom
malinjawi:split/parquet-field-id-resolver

Conversation

@malinjawi

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

IcebergWriter trusted the incoming field-id proto and indexed it positionally, so a proto that disagreed with the Velox row type was an out-of-bounds read rather than an error. Velox only checks arity shallowly and stops recursing at non-ROW array elements, so ARRAY<ARRAY<T>> and ARRAY<MAP<K,V>> reach an unguarded .at(0) inside Velox instead of a diagnostic.

This adds a shared resolver that validates a decoded field-id tree against the write schema at every depth — arity, kind, name, strictly positive ids, and ids unique across the whole tree — then lowers it to what ParquetWriterOptions expects. Call sites use .at(i), so a residual mismatch throws.

The uniqueness check is the one that matters beyond crash safety: Iceberg requires table-global unique ids, so two sibling structs each carrying id 5 would otherwise produce a well-formed footer that resolves to the wrong column.

How was this patch tested?

New ParquetFieldIdsTest.cc covers primitives, nested structs, arrays, maps, array-of-struct, nested arrays, name-less resolution, absent ids and the empty tree.

Notes

Draft — I haven't been able to run the C++ locally, so I'd like CI to build it first.

The ParquetFieldIdSchema decoder is currently only reached from tests; it's the intended entry point for the Delta write path and lands with the follow-up, so say the word if you'd rather it came later instead.

@github-actions github-actions Bot added the VELOX label Sep 2, 2026
IcebergWriter trusted the incoming field-id proto and indexed it positionally,
so a proto that disagreed with the Velox row type was an out-of-bounds read
rather than an error. Velox only checks arity shallowly and stops recursing at
non-ROW array elements, so ARRAY<ARRAY<T>> and ARRAY<MAP<K,V>> reach an
unguarded .at(0) inside Velox instead of a diagnostic.
Add a shared resolver that validates a decoded field-id tree against the write
schema at every depth -- arity, kind, name, strictly positive ids, and ids
unique across the whole tree -- then lowers it to what ParquetWriterOptions
expects. The uniqueness check is the one that matters beyond crash safety:
Iceberg requires table-global unique ids, so two sibling structs each carrying
id 5 would otherwise produce a well-formed footer that resolves to the wrong
column.
@malinjawi
malinjawi force-pushed the split/parquet-field-id-resolver branch from 0640b5b to 9a5bddc Compare September 2, 2026 12:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant