andygrove commented on code in PR #5853:
URL: https://github.com/apache/datafusion-comet/pull/5853#discussion_r3991434033


##########
native/proto/src/proto/operator.proto:
##########
@@ -407,14 +414,24 @@ message IcebergDeleteFile {
   // Equality field IDs (empty for positional deletes)
   repeated int32 equality_ids = 4;
 
-  // Fields 5-7 are reserved for the deletion-vector coordinates on the 
dv-read branch
-  // (referenced_data_file / content_offset / content_size_in_bytes) so the 
two features can merge
-  // in either order without a tag collision.
-  reserved 5, 6, 7;
+  // Deletion vector coordinates, set only for V3 deletion vectors. 
referenced_data_file is the
+  // data file the vector applies to; content_offset and content_size_in_bytes 
locate the
+  // deletion-vector-v1 blob within its Puffin file.
+  optional string referenced_data_file = 5;

Review Comment:
   This comment (and the matching ones in `CometIcebergNativeScan.scala` and 
`planner.rs`) says `referenced_data_file` is set only for V3 deletion vectors, 
but Iceberg also populates `DeleteFile.referencedDataFile()` for file-scoped 
Parquet position deletes. The javadoc calls this out, and `BaseFile` stores it 
from the manifest entry on 1.7+. So V2 tables will carry it on Parquet delete 
files too.
   
   iceberg-rust ignores it on the Parquet path so nothing breaks, but could we 
either clear it when the format is not Puffin, or reword the comments so nobody 
later keys DV detection on this field? The format field is the discriminator 
and it would be good for the comments to say so. Fine as a follow-up.



##########
spark/src/test/scala/org/apache/comet/CometIcebergNativeSuite.scala:
##########
@@ -598,6 +598,182 @@ class CometIcebergNativeSuite
     }
   }
 
+  // V3 tables store positional deletes as deletion vectors (Puffin blobs) 
instead of position
+  // delete files. This verifies Comet reads a V3 table's deletion vectors 
natively and applies
+  // them, matching Spark.
+  test("MOR V3 table with DELETION VECTORS - verify deletes are applied") {
+    assume(icebergAvailable, "Iceberg not available in classpath")
+    // Format version 3 (and its deletion vectors) requires Iceberg 1.11+. 
Older Iceberg
+    // rejects `format-version=3` at table creation.
+    assume(icebergVersionAtLeast(1, 11), "Iceberg V3 tables require Iceberg 
1.11+")
+
+    withTempIcebergDir { warehouseDir =>
+      withSQLConf(
+        "spark.sql.catalog.test_cat" -> 
"org.apache.iceberg.spark.SparkCatalog",
+        "spark.sql.catalog.test_cat.type" -> "hadoop",
+        "spark.sql.catalog.test_cat.warehouse" -> warehouseDir.getAbsolutePath,
+        CometConf.COMET_ENABLED.key -> "true",
+        CometConf.COMET_EXEC_ENABLED.key -> "true",
+        CometConf.COMET_ICEBERG_NATIVE_ENABLED.key -> "true") {
+
+        spark.sql("""
+          CREATE TABLE test_cat.db.dv_delete_test (
+            id INT,
+            name STRING,
+            value DOUBLE
+          ) USING iceberg
+          TBLPROPERTIES (
+            'format-version' = '3',
+            'write.delete.mode' = 'merge-on-read',
+            'write.merge.mode' = 'merge-on-read'
+          )
+        """)
+
+        spark.sql("""
+          INSERT INTO test_cat.db.dv_delete_test
+          VALUES
+            (1, 'Alice', 10.5), (2, 'Bob', 20.3), (3, 'Charlie', 30.7),
+            (4, 'Diana', 15.2), (5, 'Eve', 25.8), (6, 'Frank', 35.0),
+            (7, 'Grace', 12.1), (8, 'Hank', 22.5)
+        """)
+
+        spark.sql("DELETE FROM test_cat.db.dv_delete_test WHERE id IN (2, 4, 
6)")
+
+        // Confirm the delete produced a deletion vector (a Puffin delete 
file), not a parquet
+        // position-delete file or a copy-on-write rewrite, so this test 
actually exercises the
+        // deletion-vector read path.
+        val deleteFormats = spark
+          .sql("SELECT file_format FROM test_cat.db.dv_delete_test.files WHERE 
content = 1")
+          .collect()
+          .map(_.getString(0))
+          .toSet
+        assert(
+          deleteFormats.contains("PUFFIN"),
+          s"expected a deletion vector (PUFFIN delete file) but found: 
$deleteFormats")
+
+        checkIcebergNativeScan("SELECT * FROM test_cat.db.dv_delete_test ORDER 
BY id")
+
+        spark.sql("DROP TABLE test_cat.db.dv_delete_test")
+      }
+    }
+  }
+
+  // A DELETE writes one deletion vector per data file it touches, and 
Iceberg's DV writer packs
+  // every vector produced by one write task into a single Puffin file. 
Vectors that apply to
+  // different data files therefore share a delete-file path and differ only 
by their content
+  // offset, which is what makes the delete-file pool's identity key 
load-bearing: keyed on the
+  // path alone (as the pool was before deletion vectors), the second and 
later vectors dedup into
+  // the first and their data files come back with the deleted rows still in 
them. Keyed on the
+  // whole message they stay distinct, and the path they share is interned 
separately so it is
+  // still serialized once.
+  test("V3 deletion vectors sharing one Puffin file are interned but not 
collapsed") {

Review Comment:
   Two coverage ideas for a follow-up:
   
   1. A test where one scan sees both delete formats: create a V2 table with 
file-scoped position deletes, `ALTER TABLE ... SET TBLPROPERTIES 
('format-version'='3')`, then DELETE from a data file that had no prior 
deletes. That exercises the per-delete-file `file_format` in one plan and 
confirms Java's planning hands Comet the DV rather than both for a file that 
gets rewritten.
   
   2. An encrypted V3 table DV case. iceberg-rust has a separate decrypt branch 
in `load_deletion_vector` that reads `content_offset` over the plaintext file 
view, and forwarding `key_metadata` on a Puffin entry is the one thing the 
existing encryption tests do not cover.



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