[REVIEW ONLY, DO NOT MERGE] feat(core): port the merge-on-read file group reader (#639-#673 squashed) - #660
Open
linliu-code wants to merge 1 commit into
Open
Conversation
linliu-code
force-pushed
the
review/mor-reader-squashed
branch
3 times, most recently
from
August 7, 2026 17:26
83554db to
a4773cc
Compare
linliu-code
force-pushed
the
review/mor-reader-squashed
branch
2 times, most recently
from
August 8, 2026 05:44
44039fd to
be86639
Compare
Squash of apache#639-apache#673 for review. The reviewable increments are those PRs; merging should happen there. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
linliu-code
force-pushed
the
review/mor-reader-squashed
branch
from
August 8, 2026 06:59
be86639 to
cce7c72
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.
What this is
The merge-on-read file group reader ported from
onehouseinc/hudi-rs-internalintohudi-core, the switch that reaches it, its end-to-end test harness, and the correctness work that followed once the ported reader was run against real fixtures.75 files, +38,143 / −1,373.
Nothing changes for existing users. The ported reader is
pub(crate)and reachable only viahoodie.read.merge.engine = v2, which defaults tolegacy— the reader that has always served reads.Table, DataFusion, the Python binding and the cxx bridge are untouched.New since this PR was last opened
The first version of this PR was the port itself (#639–#659). Everything below landed after, and most of it is not refactoring — it is bugs the fixtures found once the reader could actually run.
Correctness against real files
Dictionary(Utf8, V), which is not a valid Arrow maphoodie.table.create.schema, which records the table as created, not as it iswrite-old-list-structure=truefiles were rejected outright by parquet-rsRobustness and cost
arrow-avroinstead of the hand-rolled converter, deleting 1,073 lines ofavro_to_arrow/arrow_array_reader.rs.Observability
reader_v2::gaps), warning on the ones that would otherwise differ silently.The switch
The one thing worth understanding first, because it explains the shape of everything else.
FileGroupReaderkeeps its exact public API and becomes a dispatcher, with one decision point insideread_file_slice_from_paths:The engine is read from the raw config rather than through
get_or_default, which falls back to the default when a value fails to parse. A typo in the engine name would otherwise silently read with the other engine — the one outcome this switch must not produce.Metadata tables (HFile) have no v2 path and always take the existing reader. That is a decision, not a gap.
What this engine refuses
A table that needs something the port does not do gets an error naming it, rather than plausible wrong rows:
CUSTOMmerge mode or a table's own merger, schema-on-read (InternalSchema, renames),skip_merge, and sorted output.reader_v2::gapscarries the list; only position-based merge is silent, and it now warns.Testing
1,211 unit tests plus the end-to-end harness, integration tests and gold fixtures; 3 ignored (a memory benchmark that must run one mode per process, an unread-fixture inventory, and one harness expectation still being re-derived).
Please read the test state with this caveat: CI has never run on any of these PRs. Every
CIandCoderun on this repository since 2026-06-05 has ended instartup_failure— silently, for every contributor — because three action refs are not on the ASF allowlist. #674 fixes that and adds the guard. Until it merges, everything here is verified locally only, and on a Rust toolchain newer than the pinned one.🤖 Generated with Claude Code