xiangfu0 commented on code in PR #19800:
URL: https://github.com/apache/pinot/pull/19800#discussion_r4225331983


##########
pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/MultistageGroupByExecutor.java:
##########
@@ -230,6 +291,30 @@ public List<Object[]> getResult(Comparator<Object[]> 
comparator, int maxRows) {
     return result;
   }
 
+  private SortedRow getSortedRow(Object[] row, int[] columnsToFinalize) {
+    if (columnsToFinalize.length == 0) {
+      return new SortedRow(row, row);
+    }
+    // Extract each sort value once per group, retaining intermediate values 
for downstream aggregation.
+    Object[] sortKeys = row.clone();
+    for (int index : columnsToFinalize) {
+      AggregationFunction aggFunction = _aggFunctions[index - 
_groupKeyIds.length];
+      Object intermediateResult = row[index];
+      // Funnel finalization consumes the event queue, so extract from a copy.
+      if (intermediateResult instanceof PriorityQueue<?> queue) {

Review Comment:
   Re-review of 913f8c2: the reachable funnel bug is fixed (FUNNEL* now 
bypasses trim entirely), and the heap no longer finalizes live funnel state. 
One residual on this thread: the check is a fail-unsafe denylist. 
`cacheSortValue` finalizes the live intermediate that stays in the output row, 
and the only guard against a destructive finalizer is 
`getType().name().startsWith("FUNNEL")`. There is already a concrete non-FUNNEL 
counterexample in the codebase: 
`DistinctCountOffHeapAggregationFunction.extractFinalResult` calls 
`set.close()` (frees native memory) on an OBJECT intermediate with INT final 
type, so it passes every gate here. It is unreachable today only because its 
`aggregateGroupBySV`/`extractGroupByResult` throw 
`UnsupportedOperationException` — if group-by support lands (or any plugin adds 
a destructive numeric-final finalizer), ordered trim silently corrupts (here, 
use-after-free) with no compile error or test failure. Since the untrimmed 
fallback is always correct, cons
 ider failing safe at zero cost to current behavior: route unknown OBJECT 
intermediates to `getResult(Integer.MAX_VALUE)` unless the function is known 
safe to finalize (invert to an allowlist), or at minimum add 
DISTINCTCOUNTOFFHEAP next to the FUNNEL check with a comment naming the 
invariant.



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