Repository navigation
Conversation
5fe8f8b to
1c51487
Compare
1c51487 to
008fa68
Compare
… evolution fallback Moves the iceberg-rust pin to b154603a, which matches a data file's nested fields by field id (apache/iceberg-rust#3255). The fallback added by apache#6543 now covers only a struct whose current fields were all added after a data file was written, the one shape where the native read still differs from Spark. That check runs on the task schema the scan reads. The fallback for nested columns of name-mapped tables (apache#6790) stays. With the bump, a pruned read of a map value whose projected leaves all differ from the file's physical names fails in iceberg-rust with "Map field must have exactly 2 fields". Closes apache#6934
1ced41c to
793e320
Compare
rich7420
left a comment
There was a problem hiding this comment.
A few compatibility questions inline.
| .flatMap { schema => | ||
| IcebergReflection.nestedFieldsAddedOrRenamed(metadata.table, schema, fieldIds) | ||
| } | ||
| val disjoint = metadata.taskSchema.toSeq |
There was a problem hiding this comment.
Please preserve fallback for evolved ID-less structs: adding s.b now throws, while renames can expose incorrectly matched values.
There was a problem hiding this comment.
You're right that this changes behavior. For files with neither field ids nor a name mapping, iceberg-rust now matches a struct's children by position only when the counts are equal, so a pruned read of such a struct fails with "cannot reconcile struct fields by id". Before the bump it returned the file's values. I don't think we can keep the old fallback for this case. Nothing at planning time tells us whether a file has ids, and the old guard only fired when the schema history showed a nested add or rename, so keeping it would put back most of what this PR removes. Spark reads every nested field of these files as NULL, so the native scan already differs there. That's tracked in #6794 and listed under "Reads that differ from Spark" in iceberg.md, and the upstream side is apache/iceberg-rust#3436. Does it work for you to leave this as a documented divergence?
| IcebergReflection.nestedFieldsAddedOrRenamed(metadata.table, schema, fieldIds) | ||
| } | ||
| val disjoint = metadata.taskSchema.toSeq | ||
| .flatMap(IcebergReflection.structsWithNoFieldsInCommon(metadata.table, _, fieldIds)) |
There was a problem hiding this comment.
Could default validation use the task schema? With pruning disabled, unprojected nested defaults now reach unsupported native reads.
There was a problem hiding this comment.
Good catch. With nested pruning off the task schema holds nested fields the query's schema doesn't, and iceberg-rust errors on a nested default the file lacks. The default check now also covers the projected columns of the task schema, with a test, in bc89e2c.
| # version requirement once a release ships on arrow 59. Bump policy: #5645. | ||
| iceberg = { git = "https://github.com/apache/iceberg-rust", rev = "1f3bc34058e3f3e45336bc5428f37b92649a608b" } | ||
| iceberg-storage-opendal = { git = "https://github.com/apache/iceberg-rust", rev = "1f3bc34058e3f3e45336bc5428f37b92649a608b", features = ["opendal-memory", "opendal-fs", "opendal-s3", "opendal-gcs", "opendal-oss", "opendal-azdls"] } | ||
| iceberg = { git = "https://github.com/apache/iceberg-rust", rev = "b154603a710d730d2f43f8af4db257cc137237ef" } |
There was a problem hiding this comment.
Could equality deletes bind case-sensitively? This pin rejects id/ID because Comet still sets case_sensitive=false.
There was a problem hiding this comment.
Agreed. Comet's native tasks were built case-insensitive, and the equality-delete predicate is the only thing that reads that flag. Its names come from the task schema, so they match exactly. Tasks are now case-sensitive in bc89e2c, with a test that fails without it.
| iceberg = { git = "https://github.com/apache/iceberg-rust", rev = "1f3bc34058e3f3e45336bc5428f37b92649a608b" } | ||
| iceberg-storage-opendal = { git = "https://github.com/apache/iceberg-rust", rev = "1f3bc34058e3f3e45336bc5428f37b92649a608b", features = ["opendal-memory", "opendal-fs", "opendal-s3", "opendal-gcs", "opendal-oss", "opendal-azdls"] } | ||
| iceberg = { git = "https://github.com/apache/iceberg-rust", rev = "b154603a710d730d2f43f8af4db257cc137237ef" } | ||
| iceberg-storage-opendal = { git = "https://github.com/apache/iceberg-rust", rev = "b154603a710d730d2f43f8af4db257cc137237ef", features = ["opendal-memory", "opendal-fs", "opendal-s3", "opendal-gcs", "opendal-oss", "opendal-azdls"] } |
There was a problem hiding this comment.
Please preserve FixedSizeList→List conversion; Parquet’s Arrow schema hint can expose this newly rejected input.
There was a problem hiding this comment.
This one is real. In the new pin, RecordBatchTransformer only converts List and LargeList file columns to a List target, so a FixedSizeList from a Parquet Arrow schema hint now errors with "cannot promote". It is tracked upstream as apache/iceberg-rust#3471, and a fix is in progress. It only affects files whose embedded Arrow schema uses FixedSizeList, which Spark and Iceberg writers don't produce, so I'd like to merge as is and pick up the fix with the next iceberg-rust bump. Does that work for you?
… on the task schema iceberg-rust now rejects a case-insensitive name that matches two columns when it binds an equality delete's predicate to the task schema, so a table with `id` and `ID` failed any scan whose task schema held both. The names come from that schema, so Comet marks its tasks case-sensitive. The check for V3 default values read only the query's schema. While nested schema pruning is off, the scan reads every nested field of a projected column, and iceberg-rust fails a nested field with a default that a data file lacks. The check now also covers the projected columns of the task schema.
Which issue does this PR close?
Closes #6934.
Rationale for this change
Since #6543, the native Iceberg scan falls back to Spark whenever a projected struct, list or map column has a nested field that some schema in the table's history lacks or names differently. That was needed because iceberg-rust matched a data file's nested fields to the table's by position (apache/iceberg-rust#2617). apache/iceberg-rust#3255 matches them by field id and fills absent optional fields with NULLs, so most of those fallbacks are no longer needed.
What changes are included in this PR?
icebergandiceberg-storage-opendalpin to iceberg-rustb154603a.Cargo.lockchanges only those three crates, and no Comet source change was needed to compile.IcebergReflection.nestedFieldsAddedOrRenamedwithstructsWithNoFieldsInCommon. The scan now falls back only when a projected struct, at any depth, shares no field id with the same struct in some schema in the table's history. That is the one shape where the native read still differs from Spark: it returns a struct of NULLs or NULL depending on what else the scan reads, where Spark returns NULL for a top-level struct and a struct of NULLs for a nested one.CometIcebergNativeScanMetadata.taskSchema, from perf: read only the nested fields Spark keeps in the native Iceberg scan #6725), instead of the table and scan schemas. With nested schema pruning on, that schema holds only the fields Spark keeps, so a read of onlys.bfalls back when a file predatess.b, while a read ofs.astays native.docs/source/user-guide/latest/iceberg.md.The name-mapping fallback from #7085 (#6790) stays. Removing it with this pin makes a pruned read of a map value fail in iceberg-rust with "Map field must have exactly 2 fields", when the table was imported and the files' physical names differ from the mapping, so every projected leaf under the map value is missing. Other reads of such tables match Spark. #6790 remains open.
How are these changes tested?
In
CometIcebergNativeSuite:VERSION AS OFtests added by perf: read only the nested fields Spark keeps in the native Iceberg scan #6725 now expect native scans too, with nested schema pruning on and off.s.bread. A struct that kept one of its fields stays native.On Spark 4.1 with Iceberg 1.11,
CometIcebergNativeSuitegives 134 passed, 0 failed, 2 canceled, on top of apache/main at 6fe73d9. I have not run the Spark matrix or the other Iceberg shards.