sunchao commented on code in PR #5889:
URL: https://github.com/apache/datafusion-comet/pull/5889#discussion_r4332877116


##########
native/spark-expr/src/struct_funcs/get_struct_field.rs:
##########
@@ -99,9 +99,15 @@ impl PhysicalExpr for GetStructField {
                     self.ordinal,
                 )?))
             }
-            ColumnarValue::Scalar(ScalarValue::Struct(struct_array)) => 
Ok(ColumnarValue::Array(
-                child_with_parent_nulls(&struct_array, self.ordinal)?,
-            )),
+            ColumnarValue::Scalar(ScalarValue::Struct(struct_array)) => {
+                let child = child_with_parent_nulls(&struct_array, 
self.ordinal)?;
+                // Match a struct column's batch-sized output so downstream 
expressions,
+                // including IF's whole-batch branch shortcut, never receive a 
scalar field.
+                Ok(ColumnarValue::Array(
+                    ScalarValue::try_from_array(child.as_ref(), 0)?
+                        .to_array_of_size(batch.num_rows())?,

Review Comment:
   [P2] Avoid eagerly expanding variable-width scalar fields before their 
consumers. With AQE disabled, subquery reuse enabled, two 256 KiB strings in 
Parquet table `src`, and an 8,192-row outer batch, `SELECT id, 
octet_length((SELECT max(s) FROM src)), octet_length((SELECT min(s) FROM src)) 
FROM outer_rows` produces merged struct subqueries. Spark returns `262144` for 
both lengths on every row. This expansion instead attempts a 2,147,483,648-byte 
`Utf8` value buffer and panics with `offset overflow` before `octet_length` 
runs. Smaller inputs still incur unnecessary copies proportional to batch size, 
even though the final result contains only integers. The base and release 
retain Spark fallback for this struct shape. Please preserve scalar evaluation 
for scalar-capable consumers or provide bounded expansion without duplicating 
the full value, while retaining the fixes for array-dependent consumers.
   
   Evidence: Reproduced at the reviewed SHA with `GetStructField` over 
`ScalarValue::Struct` containing a 262,144-byte `Utf8`, feeding DataFusion’s 
`OctetLengthFunc` on an 8,192-row batch. Evaluation panicked at 
`arrow-buffer-59.3.0/src/buffer/offset.rs:167` with `offset overflow`; the 
equivalent scalar consumer returned `Scalar(Int32(262144))`. Arrow checks the 
offset before allocating the repeated buffer, so this reproduction did not 
allocate 2 GiB. A separate 1,024-row test measured 33,554,432 value bytes from 
a 32,768-byte scalar. Spark 3.5.9 executed the SQL reference successfully, 
showed merged struct subqueries in its optimized plan, and returned 8,192 rows 
with `(262144, 262144)`. Native SQL admission and the prior fallback were 
verified from source.



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