linliu-code opened a new pull request, #672:
URL: https://github.com/apache/hudi-rs/pull/672

   **Stacked on #639–#671** — review only the last commit. **Merge-on-read 
reader only; the existing reader is untouched.**
   
   ## The bug
   
   A table from version 9 on records how it merges in 
`hoodie.record.merge.mode`. Older ones do not, and this reader guessed — from 
`hoodie.table.record.merge.strategy`, a key **no Hudi table writes** (zero 
occurrences across every fixture). It always fell through to a derivation that 
returns `append_only` whenever meta fields are off or no ordering field is set.
   
   `append_only` has no merge-mode counterpart, so the read was **refused**.
   
   ## What Hudi does
   
   `HoodieTableConfig.inferMergingConfigsForPreV9Table` — three inputs, in 
precedence order:
   
   ```
   payload class or strategy id set?
     DefaultHoodieRecordPayload | EventTimeAvroPayload  → EVENT_TIME_ORDERING
     OverwriteWithLatestAvroPayload                     → COMMIT_TIME_ORDERING
     strategy eeb8d96f-…  → EVENT_TIME    ce9acb64-… → COMMIT_TIME
     anything else                                      → CUSTOM
     (v8+: strategy id wins;  before: payload class wins)
   otherwise
     ordering field set ? EVENT_TIME_ORDERING : COMMIT_TIME_ORDERING
   ```
   
   **The inputs were always present.** The strategy ids in our fixtures match 
Hudi's constants exactly (`eeb8d96f-…`, `ce9acb64-…`, and the payload-based 
sentinel `00000000-…`), and 37 fixtures carry a payload class. This reader 
consulted none of them.
   
   I confirmed the same rule is what the engine integration applies: gluten's 
`Hudi1xMergeConfigResolver.resolveMergeConfigs` delegates straight to 
`inferMergingConfigsForPreV9Table`, gated on `tableVersion < NINE` — which is 
why a v9 table passes through untouched.
   
   ## Two consequences worth naming
   
   **Tables that were refused now read.** `v6_empty` and 
`v6_simplekeygen_hivestyle_no_metafields` are the fixtures that hit the old 
fallback; both now merge by commit time.
   
   **A v6 `OverwriteWithLatestAvroPayload` table now merges by commit time, not 
event time.** Its payload class says so, and it outranks the ordering-field 
guess. That is a semantics change for those tables — and the correct one: 
"overwrite with latest" means latest by commit, not by ordering field.
   
   ## Why `CUSTOM` is still refused
   
   A table with a merger of its own is rejected rather than merged as if it had 
none.
   
   Gluten *does* remap one case — a Debezium payload becomes 
`EVENT_TIME_ORDERING` so it can offload — **but only after injecting the delete 
marker and, for MySQL, substituting the ordering field with the composite 
`(_event_bin_file, _event_pos)` this reader can actually compare.** Those 
configs are not persisted on the table. Inferring the same remap here would 
read such a table without them and drop its deletes silently.
   
   An engine that has done that work says so by setting 
`hoodie.record.merge.mode` outright, which is read before any inference. That 
is the right seam.
   
   ## Scope
   
   **The existing reader is untouched**, per the constraint on this change. It 
still derives its own strategy, so the two readers now disagree on these tables 
— the merge-on-read one being correct. A differential comparison between them 
still has to wait for the legacy path to be brought across.
   
   ## Tests
   
   An 11-case matrix mirroring the cases Java's own inference is tested 
against: the ordering-field fallback both ways, each built-in payload class, 
each built-in strategy id, the payload-based sentinel, and the version-8 
tie-break in both directions.
   
   Plus: a real fixture that was refused before and now resolves to commit-time 
ordering, and a table with its own merger still refused with a reason.
   
   The two tests that asserted the old behavior are replaced — they encoded the 
bug.
   
   Full workspace green: 1208 lib + 79 table-read + 39 datafusion + 21 + 12. 
Clippy clean in the changed file.
   
   🤖 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]

Reply via email to