ziting-openai commented on code in PR #5262:
URL: https://github.com/apache/datafusion-comet/pull/5262#discussion_r3929822788


##########
native/Cargo.toml:
##########
@@ -62,8 +62,8 @@ object_store = { version = "0.13.2", features = ["gcp", 
"azure", "aws", "http"]
 url = "2.2"
 aws-config = "1.8.18"
 aws-credential-types = "1.2.13"
-iceberg = { git = "https://github.com/apache/iceberg-rust";, rev = 
"8adaa872f31549dd5ad8255848715758228038bc" }
-iceberg-storage-opendal = { git = "https://github.com/apache/iceberg-rust";, 
rev = "8adaa872f31549dd5ad8255848715758228038bc", features = ["opendal-memory", 
"opendal-fs", "opendal-s3", "opendal-gcs", "opendal-oss", "opendal-azdls"] }
+iceberg = { git = "https://github.com/apache/iceberg-rust";, rev = 
"665c64e48e8d33797ecb1a421f327edd9b024879" }

Review Comment:
   [P2] Adapt Comet to the newly pinned Iceberg task API
   
   At this revision, `FileScanTask` fields are private and 
`FileScanTaskDeleteFile` requires `file_format`, but Comet still reads/mutates 
`task.deletes` in `iceberg_scan.rs:270,323`, constructs `FileScanTask` with a 
struct literal in `planner.rs`, and omits `file_format` from the delete-task 
initializer. Iceberg is a nonoptional dependency and these modules are 
unconditional, so this blocks native compilation even when no Iceberg query is 
used. The [current-head Rust CI 
job](https://github.com/apache/datafusion-comet/actions/runs/33820438498/job/100862299933)
 reports E0616/E0063 for these call sites. Please migrate task 
construction/access to the pinned builder/getter APIs and supply the 
delete-file format, including the affected tests.



##########
native/core/src/parquet/schema_adapter.rs:
##########
@@ -77,6 +78,91 @@ fn schema_has_field_ids(schema: &SchemaRef) -> bool {
     schema.fields().iter().any(|f| parse_field_id(f).is_some())
 }
 
+/// Returns true when casting `physical_type` to `target_type` is a *pure* 
structural
+/// narrowing (dropping unrequested struct/list fields, no leaf-level value 
reinterpretation)
+/// that DataFusion's own `datafusion_common::nested_struct::cast_column` 
already computes
+/// identically to Comet's `spark_parquet_convert`. `ColumnarValue::cast_to` 
(the function a
+/// plain, un-swapped `CastExpr` runs at execution time; see
+/// datafusion/expr-common/src/columnar_value.rs) routes to that same function 
whenever
+/// `datafusion_common::nested_struct::requires_nested_struct_cast` holds, 
matching arbitrary
+/// struct/list fields by name, null-filling missing target fields, and 
dropping extra source
+/// fields, exactly the shape apache/datafusion-comet#4859 needs pruned. 
Confirmed
+/// byte-identical to `spark_parquet_convert` for the covered shapes by
+/// `test::nested_struct_narrowing_cast_matches_datafusion_generic_cast`.
+///
+/// When this returns `true`, `replace_with_spark_cast` leaves DataFusion's 
`CastExpr` in
+/// place instead of swapping in `CometCastColumnExpr`, so DataFusion's 
leaf-pruning
+/// (`build_projection_read_plan`'s cast-clipping, apache/datafusion#24090) 
can see the cast
+/// and read only the requested Parquet leaves, instead of falling back to a 
full-column read
+/// because it can't recognize `CometCastColumnExpr`.
+///
+/// This is deliberately an allow list, not a deny list: it only recurses 
through the two
+/// container shapes `nested_struct::cast_column` actually implements (Struct, 
List /
+/// LargeList), and requires every leaf it bottoms out at to be an *exact* 
type match. Pruning
+/// (the only case this predicate needs to cover, see 
apache/datafusion-comet#4859) only
+/// changes which struct/list fields are kept, never a leaf's type, so 
exact-match leaves are
+/// sufficient. A deny list here (enumerate every case where Comet's nested 
cast differs from
+/// Arrow's, allow everything else) would fail open: a future addition to
+/// `parquet_convert_array` that this predicate does not know to also exclude 
would silently
+/// start producing wrong results instead of just missing an optimization.
+fn is_pure_structural_narrowing(
+    physical_type: &DataType,
+    target_type: &DataType,
+    parquet_options: &SparkParquetOptions,
+) -> bool {
+    match (physical_type, target_type) {
+        (DataType::Struct(source_fields), DataType::Struct(target_fields)) => {
+            // Comet matches by Parquet field id first when the target carries 
one;
+            // DataFusion's generic cast has no field-id concept, so any 
field-id-bearing
+            // target field is a potential divergence.
+            if parquet_options.use_field_id
+                && target_fields.iter().any(|f| parse_field_id(f).is_some())
+            {
+                return false;
+            }
+            target_fields.iter().all(|target_field| {
+                // Require an *exact* (case-sensitive) name match for every 
target field.
+                // `nested_struct::cast_column` always matches by exact name; 
Comet
+                // additionally matches case-insensitively when 
`case_sensitive` is false,
+                // which could resolve a field DataFusion would instead treat 
as missing (and
+                // null-fill). Requiring an exact match sidesteps that 
divergence regardless
+                // of the `case_sensitive` setting, and also sidesteps the 
missing-field
+                // nullability divergence: DataFusion errors when a 
non-nullable target field
+                // is missing from the source, whereas Comet null-fills 
unconditionally.
+                source_fields
+                    .iter()
+                    .find(|f| f.name() == target_field.name())
+                    .is_some_and(|source_field| {

Review Comment:
   [P2] Reject ambiguous nested names before retaining the generic cast
   
   With `spark.sql.caseSensitive=false`, a Parquet column 
`s:struct<ID:bigint,id:bigint>` read through the explicit schema 
`s:struct<id:bigint>` passes this exact-name lookup. I traced the adapter 
retaining `CastExpr`, which can prune `ID` and bypass the duplicate-field check 
in `spark_parquet_convert`; Spark and the previous Comet path reject this 
ambiguous match instead of returning one field. The existing `CAFÉ`/`café` 
native-reader regression requests `Café`, so it misses the case where one 
sibling matches exactly. Please require uniqueness under the configured 
case-insensitive resolver at each nested struct level before allowing this 
cast, and add the same native-scan regression requesting `café` (or `id`) 
exactly.



##########
native/Cargo.toml:
##########
@@ -35,18 +35,18 @@ license = "Apache-2.0"
 edition = "2021"
 
 # Comet uses the same minimum Rust version as DataFusion
-rust-version = "1.88"
+rust-version = "1.94.0"
 
 [workspace.dependencies]
-arrow = { version = "58.4.0", features = ["prettyprint", "ffi", "chrono-tz"] }
-arrow-select = { version = "58.4.0" }
+arrow = { version = "59.2.0", features = ["prettyprint", "ffi", "chrono-tz"] }
+arrow-select = { version = "59.2.0" }
 async-trait = { version = "0.1" }
 bytes = { version = "1.11.1" }
-parquet = { version = "58.4.0", default-features = false, features = 
["experimental"] }
-datafusion = { version = "54.1.0", default-features = false, features = 
["unicode_expressions", "crypto_expressions", "nested_expressions", "parquet"] }
-datafusion-datasource = { version = "54.1.0" }
-datafusion-physical-expr-adapter = { version = "54.1.0" }
-datafusion-spark = { version = "54.1.0", features = ["core"] }
+parquet = { version = "59.2.0", default-features = false, features = 
["experimental"] }
+datafusion = { version = "55.0.0", default-features = false, features = 
["unicode_expressions", "crypto_expressions", "nested_expressions", "parquet"] }

Review Comment:
   [P2] Finish migrating the remaining DF55/Arrow consumers
   
   The native library no longer compiles with this version: `ExplodeExec` and 
`IcebergWriteExec` still omit the now-required 
`ExecutionPlan::apply_expressions`, and `explode.rs:898` still accesses 
`UnnestOptions::preserve_nulls` as a field. Both operators are compiled 
unconditionally. The [current-head Rust CI 
job](https://github.com/apache/datafusion-comet/actions/runs/33820438498/job/100862299933)
 confirms E0046/E0615, plus stale `preserve_nulls` test initializers and 
`CompressionContext` in the shuffle-scan test. Please port these remaining 
consumers and test helpers to the new APIs; updating the other execution plans 
is not enough to make this dependency bump build.



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