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

   ### Describe the bug
   
   On an Iceberg table whose data files have no Iceberg field ids and are read 
through a name mapping (`schema.name-mapping.default`, which the `migrate`, 
`snapshot` and `add_files` procedures set), the native Iceberg scan returns 
NULL for nested fields whenever the query also reads a top-level primitive 
column. That covers struct fields, list element fields and map value fields. 
Spark returns the values, and nothing fails, so the wrong results are silent.
   
   iceberg-rust applies the mapping in `apply_name_mapping_to_arrow_schema` 
(`crates/iceberg/src/arrow/reader/projection.rs`), which assigns field ids to 
the file's top-level Arrow fields only. Nested fields get no id, so the 
field-id projection never selects their leaves. When the query also reads a 
top-level primitive, the projection reads only that column, and 
`RecordBatchTransformer` fills the struct, list or map column with NULL as 
though the file didn't have it. When the query reads only nested fields, no 
leaf matches at all, the reader falls back to reading every column, and the 
values come out right. Iceberg Java's `ApplyNameMapping` visitor applies the 
mapping at every level of the schema.
   
   The iceberg-rust code is the same at Comet's current pin, at bb1e4a4 (the 
1.1 pin), and on iceberg-rust's main, so the 1.1.0 release has the bug too. 
apache/iceberg-rust#1845 tracks nested name mapping there as a missing feature.
   
   ### Steps to reproduce
   
   ```scala
   // Parquet files written without Iceberg field ids
   spark.sql("""SELECT CAST(id AS INT) AS id,
       named_struct('a', CAST(id AS INT), 'b', CAST(-id AS INT)) AS s,
       array(named_struct('x', CAST(id AS INT))) AS items,
       map('k', named_struct('v', CAST(id AS INT))) AS m
     FROM range(50)""").coalesce(1).write.parquet(dataPath)
   
   spark.sql("""CREATE TABLE cat.db.t (id INT, s STRUCT<a: INT, b: INT>,
     items ARRAY<STRUCT<x: INT>>, m MAP<STRING, STRUCT<v: INT>>) USING 
iceberg""")
   spark.sql(s"CREATE TABLE src USING parquet LOCATION '$dataPath'")
   SparkTableUtil.importSparkTable(spark, TableIdentifier("src"), table, 
stagingDir)
   
   // importSparkTable sets no mapping. migrate, snapshot and add_files set 
this one.
   table.updateProperties()
     .set("schema.name-mapping.default", 
NameMappingParser.toJson(MappingUtil.create(table.schema())))
     .commit()
   spark.sql("REFRESH TABLE cat.db.t")
   ```
   
   On main at 7d294535e8 (Spark 4.1, Iceberg 1.11):
   
   | Query | Spark | Comet |
   | --- | --- | --- |
   | `SELECT id, s.a, s.b FROM t WHERE id < 3 ORDER BY id` | `[0,0,0] [1,1,-1] 
[2,2,-2]` | `[0,null,null] [1,null,null] [2,null,null]` |
   | `SELECT id, items.x, m['k'].v FROM t WHERE id < 3 ORDER BY id` | 
`[0,[0],0] [1,[1],1] [2,[2],2]` | `[0,null,null] [1,null,null] [2,null,null]` |
   | `SELECT s.a, s.b FROM t ORDER BY s.a LIMIT 3` | `[0,0] [1,-1] [2,-2]` | 
`[0,0] [1,-1] [2,-2]` |
   
   Spark 3.4 with Iceberg 1.5.2 gives the same NULLs.
   
   ### Expected behavior
   
   The native scan returns the same values as Spark. The fix belongs in 
iceberg-rust, where `apply_name_mapping_to_arrow_schema` would apply the 
mapping to nested fields as Iceberg Java does. Until Comet's pin has that, 
`CometScanRule` could fall back when the table has a name mapping and the scan 
reads a struct, list or map column. Comet can't tell at planning time which 
data files lack field ids, so that guard would also catch tables whose files 
were all rewritten with ids after the migration.
   
   ### Additional context
   
   Found while reviewing #6725, which doesn't change it: the results are the 
same with its nested schema pruning on or off. Comet's existing migrated-table 
tests use `SparkTableUtil.importSparkTable`, which sets no name mapping, so no 
test reads a nested column through one.
   


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