ORC: fill initial defaults for missing id-bound fields - #263
Open
cbb330 wants to merge 1 commit into
Open
Conversation
This was referenced Jul 23, 2026
cbb330
force-pushed
the
chbush/oh120-orc-default-fill
branch
from
July 25, 2026 01:04
a888bee to
4db9002
Compare
4 tasks
cbb330
changed the base branch from
openhouse-1.2.0
to
chbush/oh120-orc-id-binding
July 25, 2026 01:05
cbb330
force-pushed
the
chbush/oh120-orc-id-binding
branch
from
July 28, 2026 02:35
bd16f75 to
d39cbfd
Compare
cbb330
force-pushed
the
chbush/oh120-orc-default-fill
branch
from
July 28, 2026 02:35
4db9002 to
cac8ff0
Compare
cbb330
force-pushed
the
chbush/oh120-orc-default-fill
branch
from
July 28, 2026 03:11
cac8ff0 to
1115244
Compare
cbb330
force-pushed
the
chbush/oh120-orc-id-binding
branch
from
July 28, 2026 03:11
d39cbfd to
4ca1b1e
Compare
Fill a field's initial-default when it is absent from an id-bearing ORC file, mirroring how the Parquet reader resolves defaults. buildOrcProjection omits an absent field that declares a default when the file's embedded ids are trustworthy, so the id-binding StructReader finds no column for it and materializes the declared default as a per-file constant. This reuses the reader's existing constant path, so a defaulted field consumes no column vector. A present column always wins, including one holding an explicit null. Id-less and name-mapped files keep legacy null synthesis, so a default is never name-matched onto a legacy or migrated file. Engines that have not opted into id binding are unaffected: default filling is enabled only by passing a constant converter, and the positional path keeps its strict missing-reader failure. Co-authored-by: Cursor <cursoragent@cursor.com>
cbb330
force-pushed
the
chbush/oh120-orc-default-fill
branch
from
July 28, 2026 07:13
1115244 to
0e7b860
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fills a field's
initial-defaultwhen it is absent from an id-bearing ORC file, using the same shape as the Parquet reader's default resolution.buildOrcProjectionomits an absent field that declares a default, but only when the file's embedded ids are trustworthy.StructReaderfrom ORC: bind struct fields by Iceberg field id in generic and Spark 3.1 readers #265 then finds no column for that field and materializes the declared default as a per-file constant, consuming no column vector.Provenance: this is net new, not a backport
Unlike #265, this has no upstream counterpart.
apache/main's ORC reader refuses to read defaults outright:Upstream has the schema model for defaults (#9502, merged here as #250) but never wired the ORC reader to honor them. So we are not diverging from working upstream behavior — we are implementing something upstream declined to implement.
The design deliberately mirrors the Parquet reader, which is the engine upstream did implement defaults for.
BaseParquetReaders.defaultReaderresolves per field: file reader → declared default → null → fail. This PR adds the same fallback chain to the ORCStructReader, keyed offfileReader == null.How it works
Two phases of one read, communicating through the projection:
ORCSchemaUtil.buildOrcProjection(schema planning) —isOmittableDefaultskips a field when it declares a default and is absent from the file andhasTrustedIds.OrcIterablepassestrueonly on the id-bearing path; the name-mapped path keeps the 2-arg overload, which defaults tofalse.OrcValueReaders.StructReader(reader assembly) — for a field with no file reader, suppliesconstants(convertConstant.apply(field.type(), field.initialDefault())).Default filling is opt-in per engine: it activates only when a constant converter is supplied.
GenericOrcReaders.StructReaderpassesIdentityPartitionConverters::convertConstantin its own constructor, so the visitor call site inGenericOrcReaderis unchanged and byte-identical to upstream. Engines that have not opted in keep the strict missing-reader failure, and the deprecated positional path is untouched.Supported scope
Generic ORC row reader; scalar defaults at any struct nesting level, including structs inside list elements and map values.
Vectorized ORC and predicate pushdown on omitted default columns remain deferred. Restricting which engines may read a defaults-declaring table is handled outside this change.
Stack
StructReaderbackport (base:openhouse-1.2.0)Testing Done
testReadDoesNotApplyDefaultToIdLessFile,testReadDoesNotOverridePresentColumniceberg-orc66,iceberg-data393, Spark 3.1 ORC 22)iceberg-orc:revapipassTests generated with unit-tests plugin
Made with Cursor