andygrove opened a new issue, #5536:
URL: https://github.com/apache/datafusion-comet/issues/5536

   Discovered during post-merge review of #5531.
   
   **Component**: `native/shuffle/src/remote_schema.rs:47`
   
   `validate_remote_schema` unwraps exactly one wire shape, a **top-level**
   `Dictionary(Int32, Utf8 | Binary)`. Every other dictionary is a hard 
mismatch, including
   `Dictionary(Int32, Int32)`, `Dictionary(Int8, Utf8)`, and any dictionary 
nested inside a list, map,
   or struct.
   
   The local reader is far more permissive. `unpack_dictionary` 
(`shuffle_scan.rs:254`) casts _any_
   top-level dictionary to its value type, and `cast_and_stamp_schema` absorbs 
nested ones. So the two
   readers disagree about what a valid frame is, and the disagreement is 
asymmetric: a frame that reads
   fine locally becomes, on Celeborn, a `validate_remote_schema` error, which 
the reader converts into
   a `FetchFailedException`, which triggers a map-stage rerun that reproduces 
the same frame, ending in
   job failure at `spark.stage.maxConsecutiveAttempts`.
   
   ## This is not reachable today
   
   I instrumented `read_ipc_compressed_impl` to log any decoded wire schema 
containing a `Dictionary`
   at any nesting depth and ran 125 tests across `CometFuzzTestSuite`, 
`CometShuffleSuite`, and
   `CometNativeShuffleSuite`. Zero hits. `SchemaAlignExec` aligns the writer 
input to the
   catalyst-declared schema and `ScanExec::unpack_dictionary_type` strips 
top-level dictionaries before
   that, so nothing dictionary-encoded currently reaches the wire.
   
   ## Why it is still worth fixing
   
   `ShuffleBlockWriter` demonstrably encodes nested dictionaries. Both frames 
below were produced by
   `ShuffleBlockWriter::write_batch`, not hand-built:
   
   ```
   wire type      = List(Dictionary(Int32, Utf8))
   spark declares = List(Utf8)
   validate       = Err(Execution("Shuffle block type mismatch at column 0:
                    got List(Dictionary(Int32, Utf8)) but expected List(Utf8)"))
   local cast ok  = 3 rows
   
   Dictionary(Int32,Int32) vs Int32
                  = Err(Execution("Shuffle block type mismatch at column 0:
                    got Dictionary(Int32, Int32) but expected Int32"))
   ```
   
   Nothing pins the "no dictionaries on the wire" invariant. The day something 
upstream stops stripping
   them, local shuffle keeps working and Celeborn shuffle starts failing jobs, 
with no compile error
   and no failing test in between.
   
   ## Suggested fix
   
   Either:
   
   1. Recurse the dictionary unwrap through the nested `List` / `LargeList` / 
`FixedSizeList` / `Map` /
      `Struct` arms of `same_logical_type`, so the validator accepts whatever 
the encoder can emit; or
   2. Add a test asserting the writer never emits a dictionary shape the reader 
would reject, so a
      drift in either direction breaks the build.
   
   Option 1 alone still leaves `Dictionary(Int8, Utf8)` and `Dictionary(Int32, 
Int32)` rejected, so
   option 2 is the one that actually closes the gap.
   
   Verified at merge commit `98cd8c967`.
   


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