linliu-code opened a new pull request, #659:
URL: https://github.com/apache/hudi-rs/pull/659
**Stacked on #639–#658** — their commits appear here until they merge.
**Review only the last commit.**
## What
`hoodie.read.merge.engine = legacy | v2`, defaulting to `legacy`, dispatched
inside the file group reader. **Nothing changes for anyone** — the default is
the reader that has always served reads.
## Why land it now, before parity
The ported reader has been unreferenced across sixteen changes. This is the
first one that shows **how it is meant to be reached, and from where** — which
is the part of the replacement worth reviewing as architecture rather than as
sixteen file moves.
```
read_file_slice_from_paths(..)
├─ is_metadata_table() → existing reader (always, regardless of
setting)
├─ engine == legacy → existing reader (default)
└─ engine == v2 → adapter → ported reader
```
One seam. `Table`, DataFusion, the Python binding and the cxx bridge are
untouched — the ported reader was given a matching operation set precisely so
the switch could live here.
## Design points worth review
**Filters and projection are not in the adapter.** Both engines' results run
through the same `apply_eager_options`, so they cannot drift on what a filter
means or which columns come back. That also closes three of the parity gaps for
free.
**Two refusals rather than fallbacks:**
- A **metadata table** always uses the existing reader, whatever the setting
says — its base files and log blocks are HFile, which the ported reader has no
support for. This is permanent, not transitional (see #658, which separates
that path).
- A read with **no resolvable table schema** is refused. The existing reader
derives its schema from the data; the ported one needs it up front, and
guessing would be worse than saying so. The schema comes from
`hoodie.table.create.schema`, which `OptionResolver` already loads, so this
costs no extra I/O.
**An unparseable engine name is an error, not a fallback.** `get_or_default`
would have silently swallowed a typo — leaving a caller convinced they were
exercising one engine while actually reading with the other. That is the one
outcome a switch like this must not produce, so the value is read raw and
parsed strictly.
## Not yet
`v2` stays opt-in. It is not at parity — the gap list lives in the fixture
tests (#657), and the outstanding items are tracked separately. This PR is the
plumbing and the decision points, not the cutover.
## Tests
Four, asserting what the rest of the suite cannot say because no other test
names an engine:
- the default is `legacy`
- a metadata table stays on `legacy` even when `v2` is asked for
- asking for `v2` actually selects it — without this the switch could be
wired to nothing and everything would still pass
- an unknown value errors
Full workspace suite green (1113 lib + 79 table-read); build warning-free.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]