Repository navigation
feat: apply write defaults in Parquet and Avro writers - #942
huan233usc wants to merge 12 commits into
Conversation
b824448 to
ddb87cc
Compare
Extend Project with ProjectionOptions so the same field-id matching serves both paths: reads fill missing fields with initial-default and allow type promotion, writes fill with write-default and require exact types.
Add arrow::AlignBatchForWrite which projects an input batch onto the write schema via Project with write-default options: present columns are reordered by field id (recursively for structs), missing columns are materialized from write-default or null, and unknown input columns are rejected rather than silently dropped.
DataWriter aligns batches to the write schema when the input schema differs, via a new Write(data, input_schema) overload; schemas that already match keep the zero-conversion Write(data) path. Adds Parquet and Avro end-to-end tests where a column added with write-default reads back the default for rows written without it.
ddb87cc to
8e01c0e
Compare
|
Is this ready for review? |
|
I plan to do some final passes and then will send for review -- thanks |
- Preserve sliced struct offsets and align collection children by field id. - Materialize unknown inputs as typed nulls. - Configure optional input schemas without extending the writer interface.
- Always align batches while retaining the declared or default input schema. - Forward equal-schema batches without importing or exporting Arrow C Data.
| projection, | ||
| ProjectNested(*expected_field.type(), *source_field.type(), prune_source)); | ||
| ProjectNested(*expected_field.type(), *source_field.type(), prune_source, mode)); | ||
| } else if (mode == ProjectionMode::kWrite) { |
There was a problem hiding this comment.
The kWrite branch checks types but never compares source_field.optional() against expected_field.optional(), so an optional input column projects onto a required write column and its nulls get written straight into it. Java rejects that at CheckCompatibility.java:184, "should be required, but is optional", reached from TypeUtil.validateWriteSchema at TypeUtil.java:498.
| } | ||
|
|
||
| Status Write(ArrowArray* data) { | ||
| internal::ArrowArrayGuard data_guard(data); |
There was a problem hiding this comment.
'AlignBatchForWrite' consumes and releases 'data' even when it returns an error, but this outer guard still owns the same array. A missing required field or unknown input field therefore releases it in the helper and again here.
Writing an Arrow batch with an older schema currently requires callers to fill columns added by schema evolution. This PR adds optional
input_schematoDataWriterOptionsandWriterOptions, so Parquet and Avro writers can align batches to the target schema and populate omitted columns with Icebergwrite-defaultvalues.For a required column with
initial-default = 42andwrite-default = 7, an input batch containing onlyidwrites[[1, 7], [2, 7]]. Explicit nulls stay null; missing optional fields become null. Missing required fields without a write-default and unknown input field IDs are rejected.The shared alignment helper matches fields by ID and handles structs, lists, and maps recursively, preserving existing buffers, offsets, and validity. Matching schemas forward the original Arrow C Data batch.
Projectaccepts a read/write mode: reading uses initial-default and allows type promotion; writing uses write-default and requires matching types.Addresses the write-path portion of #637 and includes #941.
Validation: the complete
data_test(188 passed) andschema_test(564 passed) suites completed with no failures. Coverage includes Parquet and both Avro backends, identical-schema ownership transfer, sliced nested collections, field reordering, typed nulls, and rejected incompatible schemas.clang-format,clang-tidyon the changed implementations and tests, andgit diff --checkpassed.