Repository navigation
Support fully-native multi-stage (distinct-combined) collect_list / collect_set #4724
Description
Describe the bug
collect_list / collect_set declare their aggregate buffer as BinaryType in Spark (serialized TypedImperativeAggregate state) but produce a native ArrayType (Arrow List) state in Comet. Comet bridges this only for the simple two-stage shape: CometObjectHashAggregateExec.adjustOutputForNativeState rewrites the buffer column of a pure-Partial aggregate to ArrayType, so Partial -> Final runs natively and correctly.
It does not handle multi-stage aggregates that contain a PartialMerge stage, which Spark introduces for the distinct-aggregate rewrite, e.g.:
SELECT x, count(DISTINCT y), collect_list(z) FROM t GROUP BY xThis plans as Partial(x,y) -> PartialMerge(x,y) -> [PartialMerge, Partial](x) -> Final(x). The intermediate PartialMerge outputs are still declared BinaryType, so a fully-native pipeline crashes at runtime:
CometNativeException: Cast error: Cannot cast LIST to non-list data type Binary
(and a related nullability drift List(non-null T) vs List(nullable T) for nested element types). This is a facet of the broader Arrow-type-drift tracked in #4515.
This affects both collect_list (added in #4720) and the already-shipped collect_set — collect_set has the same latent crash on this shape.
Current behavior (workaround in #4720)
To avoid the crash, multi-stage collect_list/collect_set aggregates now fall back to Spark consistently:
CometExecRule.tagUnsafePartialAggregatestags the feeding pure-Partialwhen aPartialMergestage of aCollectList/CollectSetaggregate is present.CometBaseAggregate.doConvertfalls back aPartialMerge/Finalstage of these functions when no Comet partial produced the buffer (the cross-engineLocalTableScancase).
The simple two-stage collect_list/collect_set cases continue to run natively.
Expected behavior
Enable fully-native multi-stage execution by correcting the intermediate buffer schema for PartialMerge (and multi-mode) stages of CollectList/CollectSet (extend adjustOutputForNativeState beyond pure-Partial, and fix the element-nullability drift), so the ArrayType buffer round-trips across all stages. Then remove the fallback guards added in #4720.
Additional context
- Related: DataFusion / DataFusion-Spark functions whose Arrow return type drifts from Spark catalyst's declared type #4515 (DataFusion / datafusion-spark functions whose Arrow return type drifts from Spark catalyst's declared type)
- Introduced alongside: feat: native collect_list / array_agg aggregate #4720 (native
collect_list/array_agg)
Activity
fix: fall back collect_list/collect_set in multi-stage distinct aggre…
peterxcli commentedon Jun 25, 2026
take
feat: native collect_list / array_agg aggregate (#4720)
chetan-habu commentedon Aug 10, 2026
above Issue reproducible with v0.17.0 using below sample queries and data.
SELECT imp_campaign_id, imp_adgroup_id, ARRAY_JOIN(COLLECT_SET(STRING(imp_creative_id)), ',') AS creatives, COUNT(DISTINCT imp_impression_id) AS imp_count FROM impressions GROUP BY imp_campaign_id, imp_adgroup_idSELECT imp_campaign_id, COUNT(DISTINCT imp_user_id) AS users, COLLECT_SET(imp_creative_id) AS creatives FROM impressions GROUP BY imp_campaign_idimpressions.csv
peterxcli commentedon Aug 10, 2026
@chetan-habu thanks for reporting this.
#4727 should fix this.
you can
4724.scalacurl -L https://github.com/user-attachments/files/30888137/impressions.csv -o impressions.csvspark-shell \ --jars $COMET_JAR \ --conf spark.driver.extraClassPath=$COMET_JAR \ --conf spark.executor.extraClassPath=$COMET_JAR \ --conf spark.plugins=org.apache.spark.CometPlugin \ --conf spark.shuffle.manager=org.apache.spark.sql.comet.execution.shuffle.CometShuffleManager \ --conf spark.comet.explainFallback.enabled=true \ --conf spark.memory.offHeap.enabled=true \ --conf spark.memory.offHeap.size=4g:load 4724.scala4724.scala:feat: native collect_list / array_agg aggregate (apache#4720)
fix: walk through sorts when pairing sort aggregate buffers
test: expect the distinct collect_list sort aggregate chain to run na…
feat: support SortAggregateExec (apache#4565)