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


##########
native/core/src/execution/planner.rs:
##########
@@ -1254,13 +1257,83 @@ impl PhysicalPlanner {
         }
     }
 
+    /// Merge compatible nested types by ordinal, retaining the left field 
names and physical
+    /// leaf types. Return None when a metadata-only Spark cast cannot safely 
align the layouts.
+    fn positional_nullability_union(left: &DataType, right: &DataType) -> 
Option<DataType> {

Review Comment:
   This is the same positional merge that #6458 added for `IF` as 
`if_common_type` and `coerce_branch` in 
`spark-expr/src/conditional_funcs/case_when.rs`, and the two copies already 
disagree. This one refuses dictionaries because Comet's cast rejects a 
dictionary target, but `if_common_type` passes them to `type_union_coercion`, 
so an `IF` over the same structs would still hit that cast error. They also 
differ on the map sort flag (equal here, AND there), only `if_common_type` 
widens differing leaf types through `type_union_coercion`, and the cast here 
has no timezone while `coerce_branch` passes `"UTC"` and explains that Comet's 
cast needs one for timestamps. Could we keep one helper in `case_when.rs` and 
use it for `IF`, for `CASE` inside `create_case_when`, and for 
`reconcile_nested_comparison_types`? Then `create_case_expr` could go away, so 
`CASE` isn't coerced in two layers, and the comment that refers to "main's" 
evaluator goes with it.



##########
spark/src/test/resources/sql-tests/expressions/struct/create_named_struct_positional_comparison.sql:
##########
@@ -0,0 +1,38 @@
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements.  See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership.  The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License.  You may obtain a copy of the License at
+--
+--   http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied.  See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+
+-- MinSparkVersion: 4.0
+
+-- Config: spark.comet.exec.range.enabled=true
+-- Config: spark.comet.sparkToColumnar.enabled=true
+-- Config: spark.comet.sparkToColumnar.supportedOperatorList=Range
+-- Config: spark.sql.caseSensitive=false
+
+-- Spark 4.x compares struct fields by position, irrespective of field names.
+query
+SELECT named_struct('x', CAST(id AS DOUBLE), 'y', CAST(NULL AS DOUBLE)) =
+       named_struct('y', CAST(NULL AS DOUBLE), 'x', CAST(id AS DOUBLE))
+FROM range(8)
+
+-- Equal nullability must not bypass field-name alignment. Native Range makes 
every field
+-- non-nullable; id=1 compares equal, while id=2 detects an accidental 
name-based reorder.
+query expect_native(equalto)

Review Comment:
   The reconcile change covers all eight comparison operators, but this file 
only exercises `=`. Since #6447, `=` and `<>` on float fields go through 
`NestedPredicate`, while `<`, `<=`, `>`, `>=` and `<=>` compare normalized 
operands in a `BinaryExpr`, so they take a different path after the cast. Could 
we add a `<` and a `<=>` query with the same swapped names? On main today 
`named_struct('x', CAST(id AS DOUBLE), 'y', 1D) < named_struct('y', 1D, 'x', 
CAST(id AS DOUBLE))` returns false for id=0 where Spark returns true, and with 
this PR it matches.



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