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


##########
spark/src/test/resources/sql-tests/expressions/conditional/case_when_field_names.sql:
##########
@@ -65,3 +65,68 @@ query expect_native(casewhen)
 SELECT to_json(CASE WHEN p THEN named_struct('x', i, 'X', CAST(5.5 AS DOUBLE))
   ELSE named_struct('X', 0, 'x', d) END)
 FROM test_case_field_names
+
+-- Case-distinct names repeat across positions in the opposite order. Spark 
aligns fields by
+-- position, so x stays an INT. Pairing fields by name would widen it to 
DOUBLE, and to_json would
+-- emit 7.0. Each INSERT writes its own files, and a batch never spans files, 
so the first has
+-- every row take THEN, the second every row take ELSE, and the third mixes 
them.
+-- https://github.com/apache/datafusion-comet/issues/6532
+statement
+CREATE TABLE test_case_positional(q boolean, i int, d double) USING parquet
+
+statement
+INSERT INTO test_case_positional VALUES (true, 7, 9.5), (true, NULL, NULL)
+
+statement
+INSERT INTO test_case_positional VALUES (false, 7, 9.5), (false, NULL, NULL)
+
+statement
+INSERT INTO test_case_positional VALUES (true, 7, 9.5), (false, 8, 10.5), 
(NULL, NULL, NULL), (false, 3, NULL)
+
+-- Both branch orders
+query expect_native(casewhen)
+SELECT
+  to_json(CASE WHEN q THEN named_struct('x', i, 'X', CAST(5.5 AS DOUBLE))
+    ELSE named_struct('X', 0, 'x', d) END),
+  to_json(CASE WHEN q THEN named_struct('X', 0, 'x', d)
+    ELSE named_struct('x', i, 'X', CAST(5.5 AS DOUBLE)) END)
+FROM test_case_positional
+
+-- Several branches, none of which has the others' names
+query expect_native(casewhen)
+SELECT
+  to_json(CASE WHEN q THEN named_struct('x', i, 'X', CAST(5.5 AS DOUBLE))
+    WHEN i > 7 THEN named_struct('X', 1, 'x', d)
+    ELSE named_struct('x', 2, 'X', d) END),
+  to_json(CASE WHEN q THEN named_struct('X', 1, 'x', d)
+    WHEN i > 7 THEN named_struct('x', i, 'X', CAST(5.5 AS DOUBLE))
+    ELSE named_struct('X', 2, 'x', d) END)
+FROM test_case_positional
+
+-- Native to_json supports structs, so extract the struct after reconciling 
the array or map.

Review Comment:
   Nit, optional: I don't think the top-level array queries can tell positional 
pairing from pairing by name. `CometCreateArray` casts every element to a 
deeply nullable type, so the two branches differ only in field names. 
DataFusion's `type_union_coercion` then returns the left type unchanged, 
because `equals_datatype` ignores names. I made the `List` arm of 
`merge_branch_types` fall through to `type_union_coercion`, and then did the 
same with the `Struct` arm. The array queries in both files passed under both 
mutants. Only the map-of-array query caught the `List` one. Building the arrays 
with `array_repeat(named_struct(...), 1)` keeps each field's nullability. A 
CASE WHEN version of the query built that way passes at this head and fails 
under both mutants. Could these queries (here and at 
`coalesce_field_names.sql:79`) use it?



##########
spark/src/test/resources/sql-tests/expressions/conditional/case_when_field_names.sql:
##########
@@ -65,3 +65,68 @@ query expect_native(casewhen)
 SELECT to_json(CASE WHEN p THEN named_struct('x', i, 'X', CAST(5.5 AS DOUBLE))
   ELSE named_struct('X', 0, 'x', d) END)
 FROM test_case_field_names
+
+-- Case-distinct names repeat across positions in the opposite order. Spark 
aligns fields by
+-- position, so x stays an INT. Pairing fields by name would widen it to 
DOUBLE, and to_json would
+-- emit 7.0. Each INSERT writes its own files, and a batch never spans files, 
so the first has
+-- every row take THEN, the second every row take ELSE, and the third mixes 
them.
+-- https://github.com/apache/datafusion-comet/issues/6532
+statement
+CREATE TABLE test_case_positional(q boolean, i int, d double) USING parquet
+
+statement
+INSERT INTO test_case_positional VALUES (true, 7, 9.5), (true, NULL, NULL)
+
+statement
+INSERT INTO test_case_positional VALUES (false, 7, 9.5), (false, NULL, NULL)
+
+statement
+INSERT INTO test_case_positional VALUES (true, 7, 9.5), (false, 8, 10.5), 
(NULL, NULL, NULL), (false, 3, NULL)

Review Comment:
   Nit, optional: The comment above says the third INSERT mixes THEN and ELSE 
rows, but I don't think any batch here does. `CometTestBase` runs `local[5]`, 
so a four-row `INSERT ... VALUES` runs as four tasks and writes four one-row 
files. I checked with a probe at this head. `test_case_positional` ends up as 8 
files of one row each, and every batch the native project sees has one row. 
`coalesce_field_names.sql:53` has the same problem. Could the third INSERT use 
the `SELECT /*+ COALESCE(1) */ * FROM VALUES ... AS v(q, i, d)` form that 
`array_null_short_circuit.sql` uses? With that change the four rows reach CASE 
WHEN as one mixed batch, and both files still pass.



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