You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Struct-valued expressions other than column() emit a single output name #312
ExpressionReference.output_names holds field names in depth-first order, so a struct-valued expression needs one name for itself plus one per nested field. Apart from column(), the expression builders in src/substrait/builders/extended_expression.py always produce a single name, whatever the output type is. A projected struct-valued function, cast, literal or if_then therefore yields a RelRoot.names / inferred NamedStruct with too few names, and nothing raises an error:
Fixing this means deriving each builder's output type and padding output_names to type_num_names of it. The spec does not say what the nested fields of a computed struct should be called, so before picking a scheme, check what the sibling bindings (substrait-java, substrait-rs) generate and state the choice in the PR. alias() renames only output_names[0], which is correct once the nested names are present.
Follow-up to #311, which fixed select, project and aggregate to carry a struct column's full name list.
This also covers aggregate() measures. In #313, grouping expressions keep their full output_names list, but measures still take only output_names[0] (src/substrait/builders/plan.py, the measure half of the names list in aggregate()). A struct-returning aggregate function given a full alias list is therefore cut back to one name. When the builders here start emitting the nested names, switch measures to the full list as well. No standard extension has an aggregate that returns a struct, so this only shows up with a user-registered extension.
Activity
nielspardon commentedon Oct 13, 2026
This also covers
aggregate()measures. In #313, grouping expressions keep their fulloutput_nameslist, but measures still take onlyoutput_names[0](src/substrait/builders/plan.py, the measure half of thenameslist inaggregate()). A struct-returning aggregate function given a full alias list is therefore cut back to one name. When the builders here start emitting the nested names, switch measures to the full list as well. No standard extension has an aggregate that returns a struct, so this only shows up with a user-registered extension.