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


##########
native/core/src/execution/operators/expand.rs:
##########
@@ -65,6 +66,47 @@ impl ExpandExec {
             cache,
         }
     }
+
+    /// Derives the operator's output schema from *every* projection, not just 
the first.
+    ///
+    /// Each projection produces the same output columns, so their types agree 
except where a
+    /// native kernel drifts on nested field nullability. Widening each 
column's nested `nullable`
+    /// flags across all projections gives a schema that is valid for all of 
them; deriving it from
+    /// `projections[0]` alone yields a schema that the remaining projections 
cannot be stamped
+    /// with. See <https://github.com/apache/datafusion-comet/issues/5137>.
+    pub fn build_schema(
+        projections: &[Vec<Arc<dyn PhysicalExpr>>],
+        input_schema: &SchemaRef,
+    ) -> Result<SchemaRef, DataFusionError> {
+        let mut data_types = projections
+            .first()
+            .ok_or_else(|| {
+                DataFusionError::Internal("Expand should have at least one 
projection".to_string())
+            })?
+            .iter()
+            .map(|expr| expr.data_type(input_schema))
+            .collect::<Result<Vec<_>, _>>()?;
+
+        for projection in &projections[1..] {
+            if projection.len() != data_types.len() {
+                return Err(DataFusionError::Internal(format!(
+                    "Expand projections produce differing column counts: {} 
and {}",
+                    data_types.len(),
+                    projection.len()
+                )));
+            }
+            for (data_type, expr) in data_types.iter_mut().zip(projection) {
+                *data_type = widen_nested_nullability(data_type, 
&expr.data_type(input_schema)?);
+            }
+        }
+
+        let fields: Vec<Field> = data_types
+            .into_iter()
+            .enumerate()
+            .map(|(idx, dt)| Field::new(format!("col_{idx}"), dt, true))

Review Comment:
   Not strictly required for correctness, but I kept it deliberately.
   
   `col_{idx}` is exactly what the planner produced before this logic moved 
into `build_schema`, so keeping it means the only behavior change here is the 
nullability derivation. There is also no better name available: an Expand 
projection is an arbitrary `PhysicalExpr` (including literals like the grouping 
ID), so there is nothing to inherit — and parent operators bind to these 
columns by index, with a bound reference taking its name from the child schema 
(`planner.rs`, `ExprStruct::Bound`), so the name is positional either way. It 
is only visible in explain output.
   
   Added a comment at the call site recording that.



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