szehon-ho commented on code in PR #16977:
URL: https://github.com/apache/iceberg/pull/16977#discussion_r3920236895


##########
spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/SparkTableUtil.java:
##########
@@ -664,6 +680,35 @@ public static void importSparkPartitions(
     }
   }
 
+  private static void verifyRequiredFields(
+      Schema schema, Set<Integer> requiredFieldIds, DataFile dataFile) {
+    if (requiredFieldIds.isEmpty()) {
+      return;
+    }
+
+    Map<Integer, Long> nullValueCounts = dataFile.nullValueCounts();
+    if (nullValueCounts == null) {
+      return;
+    }
+
+    for (int fieldId : requiredFieldIds) {
+      Long nullCount = nullValueCounts.getOrDefault(fieldId, 0L);

Review Comment:
   Please avoid treating an absent null-count entry as proof of zero nulls. The 
entry may be absent because the physical file omits the target field. If that 
field is required without an initial default, reads later fail with `Missing 
required field`; omission is valid when an initial default exists. Please 
distinguish these cases using the physical file schema.



##########
spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/SparkTableUtil.java:
##########
@@ -664,6 +680,35 @@ public static void importSparkPartitions(
     }
   }
 
+  private static void verifyRequiredFields(
+      Schema schema, Set<Integer> requiredFieldIds, DataFile dataFile) {
+    if (requiredFieldIds.isEmpty()) {
+      return;
+    }
+
+    Map<Integer, Long> nullValueCounts = dataFile.nullValueCounts();

Review Comment:
   Please also validate required partition columns using the file’s partition 
data. Spark removes partition columns from the physical file, so their null 
counts are absent and a null identity-partition value currently passes this 
check.



##########
spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/SparkTableUtil.java:
##########
@@ -229,8 +233,14 @@ private static Iterator<ManifestFile> buildManifest(
       ManifestWriter<DataFile> writer =
           ManifestFiles.write(formatVersion, spec, outputFile, snapshotId);
 
+      Set<Integer> requiredFieldIds = requiredFieldIds(schema);
       try (ManifestWriter<DataFile> writerRef = writer) {
-        fileTuples.forEachRemaining(fileTuple -> writerRef.add(fileTuple._2));
+        fileTuples.forEachRemaining(
+            fileTuple -> {
+              DataFile dataFile = fileTuple._2;
+              verifyRequiredFields(schema, requiredFieldIds, dataFile);

Review Comment:
   Please delete the staging manifest if validation aborts, or validate before 
opening the writer. A validation failure closes but does not delete the 
manifest, and retries can leave multiple orphan files.



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


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to