lokeshj1703 commented on code in PR #20049:
URL: https://github.com/apache/hudi/pull/20049#discussion_r4182897184


##########
hudi-utilities/src/main/java/org/apache/hudi/utilities/streamer/HoodieStreamerUtils.java:
##########
@@ -130,6 +135,13 @@ public static Option<JavaRDD<HoodieRecord>> 
createHoodieRecords(HoodieStreamer.C
                       ? OrderingValues.create(orderingFieldsStr.split(","),
                          field -> (Comparable) 
HoodieAvroUtils.getNestedFieldVal(gr, field, false, 
useConsistentLogicalTimestamp))
                       : null;
+                  if (requiresOrderingValue && 
OrderingValues.isMissing(orderingValue)) {
+                    throw new IllegalArgumentException(
+                        "Ordering fields '" + orderingFieldsStr + "' resolved 
to a null value for record key '"
+                            + hoodieKey.getRecordKey() + "'. Please ensure all 
records carry non-null values for "
+                            + "the ordering fields, or use a merge mode or 
payload class that does not order "
+                            + "(e.g., COMMIT_TIME_ORDERING or 
OverwriteWithLatestAvroPayload).");

Review Comment:
   Good question, and it deserved measurement rather than an argument, so I ran 
it on each line.
   
   | | 0.x | 1.x before | 1.x after |
   | --- | --- | --- | --- |
   | record creation, no error table | throws `HoodieException` | accepted | 
throws `IllegalArgumentException` |
   | record creation, with error table | quarantined `RECORD_CREATION` | 
accepted | quarantined `RECORD_CREATION` |
   | outcome at merge | never reached | live row silently deleted | never 
reached |
   | delete exempt? | no | n/a | no |
   
   On 1.x today a MOR delete carrying a null ordering value removes a live row 
with a higher ordering value, unconditionally, with nothing logged. I checked 
both the payload path and the file-group-reader path and they agree, and 
`master` (1.3.0-SNAPSHOT) and the 1.1 line agree too. I had expected the 
file-group-reader path to NPE in `shouldKeepNewerRecord` and it does not — the 
probe corrected me.
   
   So "deletes skip the check and carry `OrderingValues.getDefault()`" is what 
1.x effectively does today, and the result is the silent deletion above rather 
than a benign default. `isCommitTimeOrderingDelete()` is `isDelete() && 
OrderingValues.isDefault(orderingValue)`, so substituting the default is 
precisely what turns a stale delete into an unconditional one.
   
   0.x rejects it instead, deletes included: `HoodieRecordUtils.loadPayload` 
there has no null short-circuit, so `BaseAvroPayload` throws, with 
`isDeletedRecord` already set before the check. I ran all four combinations on 
0.14.1 to confirm. 1.x later added that short-circuit, which made the guard 
unreachable; this PR restores the 0.x behaviour.
   
   On your second point you are right and I have taken it: the body now carries 
this table and states the MOR impact explicitly.



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