rmahindra123 opened a new pull request, #19660:
URL: https://github.com/apache/hudi/pull/19660

   ### Describe the issue this Pull Request addresses
   
   The Debezium payloads order records with two different mechanisms. 
`preCombine` (intra-batch dedup) compares `orderingVal` — the value of the 
configured precombine field captured at payload construction — while 
`combineAndGetUpdateValue` (incoming vs stored record) drops the payload 
`Properties` and always compares the connector-hardcoded column (`_event_lsn` 
for Postgres, `_event_seq` for MySQL) via `shouldPickCurrentRecord`: the 3-arg 
`combineAndGetUpdateValue(current, schema, properties)` funnels into the 
props-less template, so `Properties` never reaches the ordering decision.
   
   The two agree only by convention (precombine set to the connector column). 
Any table where precombine differs silently orders against storage by a column 
the user never configured.
   
   ### Summary and Changelog
   
   Debezium payloads now honor the configured ordering field(s) when merging 
against storage, matching what `preCombine` already does within a batch.
   
   - `AbstractDebeziumAvroPayload` keeps `OverwriteWithLatestAvroPayload` as 
its parent and adds a `Properties`-aware `combineAndGetUpdateValue` template 
(the 2-arg overload delegates with `CollectionUtils.emptyProps()`) which 
dispatches the ordering decision:
     - ordering fields absent → the connector-specific 
`shouldPickCurrentRecord` (unchanged, original 3-arg signature);
     - any configured ordering is used as-is, single or composite (multi-field, 
element-wise: the first non-equal field decides, ties go to the incoming 
record) via `needUpdatingPersistedRecord`, implemented in the abstract class 
mirroring `DefaultHoodieRecordPayload`'s comparison (kept local rather than 
reusing `OrderingValues` because a null persisted element after a tied element 
must take the incoming record instead of throwing; keeping the parent unchanged 
also avoids inheriting `Default`'s per-record-deserializing `isDeleted` and its 
`DELETE_KEY` handling — `isDeleted`/`getInsertValue` behavior is byte-identical 
to before this PR).
   - One compatibility carve-out, owned by `MySqlDebeziumAvroPayload`: the 
single legacy ordering field `_event_seq` (what v8 tables carry until the v9 
upgrade rewrites it to `_event_bin_file,_event_pos`) routes to the connector's 
segment-wise numeric seq parser — a plain `Comparable` compare of the encoded 
`"file.pos"` string is lexicographic (`"9.1" > "10.1"`) and flips merge winners 
for unpadded positions (caught by `TestPayloadDeprecationFlow`).
   - `preCombine(oldValue, properties)` applies the same dispatch, so 
intra-batch dedup (`hoodie.combine.before.upsert`) and the against-storage 
merge order by the same column(s) — a configured non-connector field previously 
crashed MySQL's seq parser on the first repeated key in a batch (NFE for 
non-numerics, AIOOBE for equal plain values). The props-less `preCombine` 
overrides (MySQL seq compare, delete natural-order) are untouched; Postgres 
toast-column merging is unchanged and covered by a test through the 
configured-ordering path.
   - A null incoming ordering value on the configured path throws 
`HoodieDebeziumAvroPayloadException` naming the field and record; a null 
persisted value (e.g. bootstrapped rows) takes the incoming record; ties go to 
the incoming record in every path, matching the legacy strict comparisons. 
Configured values are trimmed. No code was copied from external sources.
   
   ### Impact
   
   | Table config | Before | After |
   |---|---|---|
   | precombine = connector column | connector ordering | identical (numeric 
seq compare preserved for MySQL via the carve-out; plain `Comparable` on the 
LSN is the same ordering for Postgres) |
   | precombine = other field | `preCombine` by config field, 
`combineAndGetUpdateValue` by connector column | both by config field |
   | composite ordering (e.g. `_event_bin_file,_event_pos`) | connector column 
only | element-wise composite |
   | no ordering props passed | connector ordering | identical |
   
   No public API change; behavior-preserving for the conventional 
configurations.
   
   ### Risk Level
   
   low
   
   Behavior-preserving for the common configuration (precombine = connector 
column) and for callers that pass no ordering properties. Verification: 
`TestPostgresDebeziumAvroPayload` 16/16 and `TestMySqlDebeziumAvroPayload` 
31/31, including tests where the configured field contradicts the connector 
ordering, tie/null-persisted/null-incoming cases, whitespace-trim 
discriminators, mixed-type composite tests bound to 
`MySqlDebeziumAvroPayload.ORDERING_FIELDS` with real binlog shapes, 
unpadded-seq discriminators where lexicographic ordering inverts the winner, 
and toast-column merging through the configured-ordering path. 
`TestPayloadDeprecationFlow` covers the v8→v9 upgrade flow for every built-in 
payload.
   
   ### Documentation Update
   
   none — the payloads honor `hoodie.payload.ordering.field` / precombine as 
already documented for `DefaultHoodieRecordPayload`.
   
   ### Contributor's checklist
   
   - [x] Read through [contributor's 
guide](https://hudi.apache.org/contribute/how-to-contribute)
   - [x] Enough context is provided in the sections above
   - [x] Adequate tests were added if applicable
   


-- 
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