andygrove opened a new pull request, #4843:
URL: https://github.com/apache/datafusion-comet/pull/4843

   ## Which issue does this PR close?
   
   Closes #4789.
   
   ## Rationale for this change
   
   Several Comet array/map expressions crash natively when the input comes 
through `CometLocalTableScanExec` with a non-nullable child field. An in-memory 
`Seq[Int]` / `Map[Int, Int]` column encodes its array element / map value as 
non-null (`containsNull=false` / `valueContainsNull=false`), but Comet 
expression serdes promise nullable children. Feeding a non-null child into a 
native kernel disagrees with the planned output type:
   
   - `slice`: `Assertion failed: result_data_type == *expected_type: Function 
'spark_array_slice' returned value of type 'List(non-null Int32)' while ... 
expected: 'List(Int32)'`
   - `map_entries`: `ListArray expected data type Struct("key": non-null Int32, 
"value": Int32) got Struct("key": non-null Int32, "value": non-null Int32)`
   - `array_insert` / SPARK-41233 array prepend: analogous item-vs-array type 
mismatch
   
   It does not reproduce over a native Parquet scan (which normalizes children 
to nullable) or with a SQL `array(...)` / `map(...)` literal (literal children 
are nullable), so it is specific to the local scan path.
   
   ## What changes are included in this PR?
   
   The non-null child is carried in two places, so both must be reconciled:
   
   1. The Arrow batch produced by `CometLocalTableScanExec.mapToReaders` (built 
from `originalPlan.schema`).
   2. The native `ScanExec`'s declared schema, serialized from `op.output` in 
`CometSink.convert`. `scan.rs:build_record_batch` casts the imported batch back 
to this declared schema, so widening only the Arrow data is reverted by the 
cast.
   
   Changes:
   
   - Add `QueryPlanSerde.widenChildNullability`, which recursively widens array 
elements, map values, and struct fields to nullable while leaving top-level 
types and map keys unchanged (map keys stay non-null, matching Arrow, and their 
nullability is never serialized).
   - Add an overridable `scanFieldType` hook in `CometSink` (default identity) 
so the widening is scoped to the local table scan and does not affect 
Union/Coalesce/shuffle sinks, whose children come from already-normalized 
native execution.
   - `CometLocalTableScanExec` overrides the hook and applies the same widening 
to its Arrow schema, so the declared schema and the batch agree exactly and no 
per-batch cast is needed.
   
   This mirrors how the Parquet scan path already normalizes children to 
nullable. No native/Rust changes are required.
   
   ## How are these changes tested?
   
   Added regression tests that run through the local table scan with 
`ConvertToLocalRelation` disabled (so the expression executes natively rather 
than being folded at plan time):
   
   - `CometArrayExpressionSuite`: `slice` and `array_insert` on 
non-null-element arrays.
   - `CometMapExpressionSuite`: `map_entries` on a non-null-value map.
   
   All new tests pass, along with the existing `CometArrayExpressionSuite`, 
`CometMapExpressionSuite`, and the `LocalTableScan` tests in `CometExecSuite` 
(including nested `NullType` in struct/array/map).
   


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