beliefer opened a new issue, #12708:
URL: https://github.com/apache/gluten/issues/12708

   ### Backend
   
   VL (Velox)
   
   ### Bug description
   
   For an **OUTER** generator, Velox's `Unnest` operator appends a trailing 
`BOOLEAN` marker column to its output (output column order: replicated columns 
→ unnest value columns → `[ordinality]` → `[marker]`). Gluten's 
`GenerateExecTransformer` must consume that marker in `pullOutPostProject` so 
the native output aligns positionally with the declared Spark schema.
   
   `pullOutPostProject` handles the OUTER marker for `PosExplode`, 
`Inline`/`JsonTupleExplode`, and `Explode` — but **not for `Stack`**. An OUTER 
`Stack` falls through to `case _ => generate`, so the marker column is never 
consumed. Because Velox binds columns **by position**, the unconsumed marker 
makes the native output one column wider than Gluten's declared schema, 
shifting every upstream column by one index.
   
   The shift is only observable when a **columnar hash exchange** consumes the 
Generate output. Under columnar shuffle, `VeloxShuffleWriter::getFirstColumn` 
requires field 0 of the shuffle `RowVector` to be the int32 
`hash_partition_key`. With the columns shifted, the boolean marker lands at 
field 0 and every task of the stage aborts deterministically:
   
   ```
   Partition id (field 0) should be integer, but got BOOLEAN
     (cpp/velox/shuffle/VeloxShuffleWriter.h — getFirstColumn)
   ```
   
   The same unconsumed-marker root cause can surface under different messages 
depending on the operator downstream of the shift:
   - **hash-partition shuffle → SortMergeJoin**: `Partition id (field 0) should 
be integer, but got BOOLEAN` (the case above).
   - **partial HashAggregate** (e.g. `GROUP BY` on the exploded columns): 
crashes earlier in the native input stream with `values_->capacity() >= 
byteSize` (`FlatVector.h`).
   - **BroadcastHashJoin** downstream: `Serialized encoding is not compatible 
... Expected INT_ARRAY. Got BYTE_ARRAY` (`checkTypeEncoding`).
   
   Inner (non-OUTER) `stack` emits no marker column and is unaffected. The 
existing `test stack function` only exercises inner `stack`, which is why the 
gap was not caught.
   
   Self-contained repro (crashes before the fix, returns correct rows after):
   
   ```sql
   CREATE OR REPLACE TEMPORARY VIEW t1_stack AS
     SELECT * FROM VALUES (1,'james',10,'lucy'),(2,'bond',20,'lily') AS 
tbl(id,name,id1,name1);
   CREATE OR REPLACE TEMPORARY VIEW t2_dim AS
     SELECT * FROM VALUES (1,'a'),(2,'b'),(10,'c'),(20,'d') AS tbl(k,tag);
   
   SET spark.sql.autoBroadcastJoinThreshold=-1;   -- force SortMergeJoin 
(hash-partition columnar exchange)
   
   SELECT j.eq_pos, t2.tag
   FROM (
     SELECT eq_pos, val
     FROM t1_stack
     LATERAL VIEW OUTER stack(2, id, name, id1, name1) v AS eq_pos, val
   ) j
   JOIN t2_dim t2 ON j.eq_pos = t2.k
   ORDER BY j.eq_pos, t2.tag;
   ```
   
   Expected (after fix): `(1,a) (2,b) (10,c) (20,d)`.
   
   Root cause is in `PullOutGenerateProjectHelper.pullOutPostProject`
   
(`backends-velox/src/main/scala/org/apache/gluten/execution/GenerateExecTransformer.scala`):
   `Stack` has no `if generate.outer` branch, unlike 
`Explode`/`PosExplode`/`Inline`.
   
   ### Gluten version
   
   main branch
   
   ### Spark version
   
   Spark-3.5.x
   
   ### Spark configurations
   
   Reproduces on the columnar shuffle path. Force a SortMergeJoin so the 
exploded key drives a hash-partition columnar exchange:
   
   ```
   spark.sql.autoBroadcastJoinThreshold = -1
   ```
   
   ### System information
   
   Velox backend. Not environment-specific — the crash is deterministic and 
data-independent (every task of the stage fails).
   
   ### Relevant logs
   
   ```bash
   
   ```


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