nsivabalan commented on code in PR #19205:
URL: https://github.com/apache/hudi/pull/19205#discussion_r3767578471


##########
hudi-client/hudi-spark-client/src/main/java/org/apache/hudi/common/model/HoodieSparkRecord.java:
##########
@@ -296,9 +297,14 @@ public HoodieRecord 
wrapIntoHoodieRecordPayloadWithKeyGen(HoodieSchema recordSch
     StructType structType = 
HoodieInternalRowUtils.getCachedSchema(recordSchema);
     String key;
     String partition;
-    boolean populateMetaFields = 
Boolean.parseBoolean(props.getOrDefault(POPULATE_META_FIELDS.key(),
-        POPULATE_META_FIELDS.defaultValue().toString()).toString());
-    if (!populateMetaFields && keyGen.isPresent()) {
+    // Resolve via hoodie.meta.fields.mode — reading the deprecated boolean 
alone would report
+    // "populated" for a selective-mode table (whose _hoodie_record_key column 
is null), sending us
+    // down the meta-column branch below and NPE-ing on the null ordinal.
+    boolean recordKeyPopulated = MetaFieldsMode.resolve(
+        props.getProperty(HoodieTableConfig.META_FIELDS_MODE.key()),

Review Comment:
   Nearly — the catch is that this method does not receive a 
`HoodieTableConfig`. It is 
`HoodieRecordCompatibilityInterface#wrapIntoHoodieRecordPayloadWithKeyGen(HoodieSchema,
 Properties, Option<BaseKeyGenerator>)`, so what arrives is a raw `Properties` 
bag, and which bag depends on the caller — a write config in most paths, and 
nothing guarantees it carries the mode rather than only the legacy boolean.
   
   That is why it goes through `MetaFieldsMode.resolve(mode, boolean)`: it is 
the same resolution rule used on the table config, so it gets the right answer 
whether the props carry the mode, the boolean, or both. Reading 
`META_FIELDS_MODE` alone would resolve a props bag that has only 
`populate.meta.fields=false` to `ALL`, and then take the meta-column branch 
below and NPE on the null `_hoodie_record_key` ordinal — which is the exact bug 
this call site was fixed for.
   
   So the check is arguably in the wrong *place* rather than the wrong *shape*. 
If the interface took the table config, or the write config were guaranteed to 
carry the mode, one property would be enough. Making that guarantee real is the 
"thread the table config through" option — it also covers the three 
`getFileWriter` call sites that have no table config, and I would rather do it 
as its own PR than fold it in here, since the interface is implemented by 
Flink, Hive, and the Trino plugin.
   
   Worth noting the new validation gate makes the *write* path safe by a 
different route: a writer whose resolved mode disagrees with the table is now 
refused outright, so by the time records are being wrapped, the write config 
agrees with the table by construction. The `resolve` call here is then 
belt-and-braces for the paths that reach this method without going through 
`initTable` at all.
   



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