Fix ClassCastException for single-server colocated aggregations in the multi-stage engine#18835
Open
yashmayya wants to merge 1 commit into
Open
Fix ClassCastException for single-server colocated aggregations in the multi-stage engine#18835yashmayya wants to merge 1 commit into
yashmayya wants to merge 1 commit into
Conversation
…tRows() for server-return-final A no-group-by aggregate whose data is colocated on a single server (e.g. partition-pruned to one partition on a strictReplicaGroup table) is planned by the v2 physical optimizer as a single-stage AGGREGATE_DIRECT that returns final results (SERVER_RETURN_FINAL_RESULT). For aggregations whose intermediate type differs from their final type (DISTINCTCOUNTHLLPLUS, DISTINCTCOUNT, ...), the leaf crashed during serialization with e.g. 'HyperLogLogPlus cannot be cast to Long'. AggregationResultsBlock.getDataSchema() reports the final column types when isServerReturnFinalResult() is true, but getRows() returned the raw intermediate results without finalizing (only getDataTable() finalized). The MSE LeafOperator consumes getRows() + getDataSchema(), so an intermediate object was left in a column typed as its final type and failed on MAILBOX_SEND serialization. getRows() now finalizes via extractFinalResult() when isServerReturnFinalResult() is true, consistent with getDataTable() and the group-by path (GroupByCombineOperator already finalizes the table). The default (v1) MSE planner always splits no-group-by aggregates into LEAF+FINAL and is unaffected; group-by DIRECT aggregates already finalize in the combine operator.
Jackie-Jiang
approved these changes
Jun 22, 2026
| public List<Object[]> getRows() { | ||
| return Collections.singletonList(_results.toArray()); | ||
| if (!_queryContext.isServerReturnFinalResult()) { | ||
| return Collections.singletonList(_results.toArray()); |
Contributor
There was a problem hiding this comment.
(nit, not introduced in this PR) We prefer List.of(x) over Collections.singletonList(x)
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #18835 +/- ##
============================================
+ Coverage 64.78% 64.81% +0.02%
Complexity 1319 1319
============================================
Files 3392 3392
Lines 210988 210994 +6
Branches 33127 33128 +1
============================================
+ Hits 136687 136748 +61
+ Misses 63283 63229 -54
+ Partials 11018 11017 -1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
With the multi-stage engine and
usePhysicalOptimizer=true, a no-GROUP-BY aggregate whose data is colocated on a single server is planned as a single-stageAGGREGATE_DIRECTleaf that returns final results (SERVER_RETURN_FINAL_RESULT). This happens, for example, when a query filters on a single partition value of a partitioned,strictReplicaGrouptable so routing prunes to one server.For aggregation functions whose intermediate type differs from their final type — e.g.
DISTINCTCOUNTHLLPLUS(HyperLogLogPlus→LONG),DISTINCTCOUNT(Set→INT) — the leaf crashes while serializing its output:Root cause
AggregationResultsBlockis inconsistent between the two methods the multi-stage leaf relies on:getDataSchema()reports the final column types (e.g.LONG) whenisServerReturnFinalResult()is true.getRows()returned the raw intermediate_results(theHyperLogLogPlusobject) without finalizing. OnlygetDataTable()finalized viaextractFinalResult().LeafOperator.composeDirectMseBlockconsumesgetRows()+getDataSchema(). Because the schema already claims the final type, no type conversion is applied, and the intermediate object is left in a column typed as its final type. It then fails onMAILBOX_SENDwhen the block is serialized.Fix
AggregationResultsBlock.getRows()now finalizes viaextractFinalResult()whenisServerReturnFinalResult()is true, so the rows are consistent with the schema it already advertises. This mirrorsgetDataTable()and the group-by path, whereGroupByCombineOperatoralready finalizes the indexed table for server-return-final.Scope
DIRECTaggregate. The default (v1) multi-stage planner always splits no-GROUP-BY aggregates into LEAF + FINAL (intermediateOBJECTon the leaf, finalized in the FINAL stage), so it is not affected.DIRECTaggregates were already safe becauseGroupByCombineOperatorfinalizes the table.ClassCastException, so there is no behavior change for any query that previously succeeded.Testing
Added
DirectAggregateObjectIntermediate.json(areplicatedtable forces single-server colocation →AGGREGATE_DIRECT), covering:SUM+DISTINCTCOUNTHLLPLUS ... FILTER(the reported shape),DISTINCTCOUNTHLLPLUSandDISTINCTCOUNT,NULL.The legacy planner passes and the physical optimizer fails before / passes after the fix. The full
ResourceBasedQueriesTest(3589 cases) and the relevantpinot-coreaggregation tests are green.