andygrove opened a new issue, #6782:
URL: https://github.com/apache/datafusion-comet/issues/6782

   ### Describe the bug
   
   When a table has an equality delete keyed on a field nested in a struct, 
every query the native Iceberg scan runs on that table fails with `Iceberg scan 
error: Unexpected => file scan task generate failed, source: Unexpected => 
field not found`. It fails even when the query projects the key, where Spark 
returns the right answer.
   
   iceberg-rust applies an equality delete by evolving the delete file's 
batches to the equality field ids (`BasicDeleteFileLoader::evolve_schema`, 
which builds a `RecordBatchTransformer`). The transformer looks up each id 
among the delete file's top-level columns only 
(`build_field_id_to_arrow_schema_map`), so a nested id such as `s.k` is never 
found. The check in `CometScanRule` (`deleteFileTypesSupported`) rejects struct 
and variant equality keys, but it lets a primitive nested inside a struct 
through. The iceberg-rust code is the same at Comet's current pin, at bb1e4a4 
(the 1.1 pin), and on iceberg-rust's main.
   
   ### Steps to reproduce
   
   Spark SQL can't write equality deletes, so the delete file is written 
through Iceberg's API, the way Comet's `CometEqualityDeletes` test helper does, 
but with the nested field id passed explicitly.
   
   ```scala
   spark.sql("""CREATE TABLE cat.db.t (id INT, s STRUCT<k: INT, a: INT>) USING 
iceberg
     TBLPROPERTIES ('format-version' = '2')""")
   spark.sql("""INSERT INTO cat.db.t SELECT CAST(id AS INT),
     named_struct('k', CAST(id % 10 AS INT), 'a', CAST(id AS INT)) FROM 
range(100)""")
   
   // In package org.apache.iceberg.data, because 
GenericFileWriterFactory.builderFor is package-private.
   val deleteRowSchema = table.schema().select("s.k")
   val s = 
GenericRecord.create(deleteRowSchema.findField("s").`type`().asStructType())
   s.setField("k", Integer.valueOf(3))
   val row = GenericRecord.create(deleteRowSchema)
   row.setField("s", s)
   val writer = GenericFileWriterFactory
     .builderFor(table)
     .equalityDeleteRowSchema(deleteRowSchema)
     .equalityFieldIds(Array(table.schema().findField("s.k").fieldId()))
     .build()
     .newEqualityDeleteWriter(
       EncryptedFiles.encryptedOutput(table.io().newOutputFile(path), 
EncryptionKeyMetadata.EMPTY),
       table.spec(),
       null)
   try writer.write(java.util.Collections.singletonList[Record](row)) finally 
writer.close()
   table.newRowDelta().addDeletes(writer.toDeleteFile()).commit()
   ```
   
   On main at 7d294535e8 (Spark 4.1, Iceberg 1.11):
   
   | Query | Spark | Comet |
   | --- | --- | --- |
   | `SELECT count(*), sum(s.k), sum(s.a) FROM t` | `[90,420,4470]` | `field 
not found` |
   | `SELECT count(*), sum(s.a) FROM t` | `[0,null]` | `field not found` |
   | `SELECT count(*), sum(id) FROM t` | `[0,null]` | `field not found` |
   
   The native scan fails the same way on Spark 3.4 with Iceberg 1.5.2.
   
   ### Expected behavior
   
   Comet falls back to Spark when an equality delete's field ids include a 
field nested below the top level, until iceberg-rust can apply such a delete.
   
   A test can compare against Spark only for a query that projects the key. 
When the query doesn't project it, Spark is wrong too. Iceberg's 
`DeleteFilter.fileProjection` can add a missing equality column only at the top 
level. Iceberg 1.5.2 then throws `Cannot find required field for ID`, and 
Iceberg 1.11 deletes every row, which is where the two `[0,null]` results above 
come from.
   
   ### Additional context
   
   Found while reviewing #6725. It predates that PR, and fails the same way 
with that PR's nested schema pruning on or off.
   


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