This is an automated email from the ASF dual-hosted git repository.

Jackie-Jiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new 2e9f31bdfed Add CombinePlanNode extension points for substituting 
combine operators (#19438)
2e9f31bdfed is described below

commit 2e9f31bdfedaa1122795f97412baa91e5d7091a8
Author: scottlan0113 <[email protected]>
AuthorDate: Thu Sep 3 02:06:38 2026 -0500

    Add CombinePlanNode extension points for substituting combine operators 
(#19438)
---
 .../apache/pinot/core/plan/CombinePlanNode.java    | 106 ++++++++++++++-------
 1 file changed, 74 insertions(+), 32 deletions(-)

diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/plan/CombinePlanNode.java 
b/pinot-core/src/main/java/org/apache/pinot/core/plan/CombinePlanNode.java
index b753fa74d26..71539035f53 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/plan/CombinePlanNode.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/plan/CombinePlanNode.java
@@ -56,10 +56,10 @@ public class CombinePlanNode implements PlanNode {
   // Try to schedule 10 plans for each thread, or evenly distribute plans to 
all MAX_NUM_THREADS_PER_QUERY threads
   private static final int TARGET_NUM_PLANS_PER_THREAD = 10;
 
-  private final List<PlanNode> _planNodes;
-  private final QueryContext _queryContext;
-  private final ExecutorService _executorService;
-  private final ResultsBlockStreamer _streamer;
+  protected final List<PlanNode> _planNodes;
+  protected final QueryContext _queryContext;
+  protected final ExecutorService _executorService;
+  protected final ResultsBlockStreamer _streamer;
 
   /// Constructor for the class.
   ///
@@ -129,7 +129,7 @@ public class CombinePlanNode implements PlanNode {
     if (_streamer != null) {
       if (QueryContextUtils.isSelectionOnlyQuery(_queryContext) && 
_queryContext.getLimit() != 0) {
         // Use streaming operator only for non-empty selection-only query
-        return new StreamingSelectionOnlyCombineOperator(operators, 
_queryContext, _executorService);
+        return createStreamingSelectionOnlyCombineOperator(operators);
       }
       // Streaming flushes partial results, so it needs an aggregation above 
to merge them back together.
       // Leaves that must return final results are excluded, see 
StreamingGroupByCombineOperator.
@@ -140,7 +140,7 @@ public class CombinePlanNode implements PlanNode {
           && QueryContextUtils.isAggregationQuery(_queryContext)
           && _queryContext.getGroupByExpressions() != null
           && !leafReturnsFinalResult) {
-        return new StreamingGroupByCombineOperator(operators, _queryContext, 
_executorService, groupByFlushThreshold);
+        return createStreamingGroupByCombineOperator(operators);
       }
       int distinctFlushThreshold = 
_queryContext.getStreamingDistinctFlushThreshold();
       if (distinctFlushThreshold > 0 && 
QueryContextUtils.isDistinctQuery(_queryContext)
@@ -158,42 +158,84 @@ public class CombinePlanNode implements PlanNode {
           // LIMIT is at or below the threshold there is no memory to save, so 
the short-circuit wins instead.
           && _queryContext.getLimit() > distinctFlushThreshold
           && !leafReturnsFinalResult) {
-        return new StreamingDistinctCombineOperator(operators, _queryContext, 
_executorService,
-            distinctFlushThreshold);
+        return createStreamingDistinctCombineOperator(operators);
       }
     }
     if (QueryContextUtils.isAggregationQuery(_queryContext)) {
       if (_queryContext.getGroupByExpressions() == null) {
         // Aggregation only
-        return new AggregationCombineOperator(operators, _queryContext, 
_executorService);
+        return createAggregationCombineOperator(operators);
       } else {
-        // Sorted aggregation group-by, when safeTrim and limit is not too 
large
-        if (_queryContext.shouldSortAggregateUnderSafeTrim()) {
-          if (operators.size() < 
_queryContext.getSortAggregateSequentialCombineNumSegmentsThreshold()) {
-            return new SequentialSortedGroupByCombineOperator(operators, 
_queryContext, _executorService);
-          }
-          return new SortedGroupByCombineOperator(operators, _queryContext, 
_executorService);
-        }
-        // Aggregation group-by
-        return new GroupByCombineOperator(operators, _queryContext, 
_executorService);
+        return createGroupByCombineOperator(operators);
       }
     } else if (QueryContextUtils.isSelectionQuery(_queryContext)) {
-      if (_queryContext.getLimit() == 0 || 
_queryContext.getOrderByExpressions() == null) {
-        // Selection only
-        return new SelectionOnlyCombineOperator(operators, _queryContext, 
_executorService);
-      } else {
-        // Selection order-by
-        List<OrderByExpressionContext> orderByExpressions = 
_queryContext.getOrderByExpressions();
-        assert orderByExpressions != null;
-        if (orderByExpressions.get(0).getExpression().getType() == 
ExpressionContext.Type.IDENTIFIER) {
-          return new 
MinMaxValueBasedSelectionOrderByCombineOperator(operators, _queryContext, 
_executorService);
-        } else {
-          return new SelectionOrderByCombineOperator(operators, _queryContext, 
_executorService);
-        }
-      }
+      return createSelectionCombineOperator(operators);
     } else {
       assert QueryContextUtils.isDistinctQuery(_queryContext);
-      return new DistinctCombineOperator(operators, _queryContext, 
_executorService);
+      return createDistinctCombineOperator(operators);
+    }
+  }
+
+  /// Returns the combine operator for a selection query, with or without 
ORDER BY.
+  protected BaseCombineOperator createSelectionCombineOperator(List<Operator> 
operators) {
+    if (_queryContext.getLimit() == 0 || _queryContext.getOrderByExpressions() 
== null) {
+      // Selection only
+      return new SelectionOnlyCombineOperator(operators, _queryContext, 
_executorService);
+    }
+    // Selection order-by
+    List<OrderByExpressionContext> orderByExpressions = 
_queryContext.getOrderByExpressions();
+    assert orderByExpressions != null;
+    if (orderByExpressions.get(0).getExpression().getType() == 
ExpressionContext.Type.IDENTIFIER) {
+      return new MinMaxValueBasedSelectionOrderByCombineOperator(operators, 
_queryContext, _executorService);
     }
+    return new SelectionOrderByCombineOperator(operators, _queryContext, 
_executorService);
+  }
+
+  /// Returns the combine operator for an aggregation query with no GROUP BY.
+  protected BaseCombineOperator 
createAggregationCombineOperator(List<Operator> operators) {
+    return new AggregationCombineOperator(operators, _queryContext, 
_executorService);
+  }
+
+  /// Returns the combine operator for an aggregation query with GROUP BY.
+  ///
+  /// Covers the sorted variants as well as the general one. An implementation 
that substitutes only the
+  /// general operator must still delegate the 
`shouldSortAggregateUnderSafeTrim()` branch to `super`,
+  /// since those operators carry the safe-trim semantics the query was 
planned with.
+  protected BaseCombineOperator createGroupByCombineOperator(List<Operator> 
operators) {
+    // Sorted aggregation group-by, when safeTrim and limit is not too large
+    if (_queryContext.shouldSortAggregateUnderSafeTrim()) {
+      if (operators.size() < 
_queryContext.getSortAggregateSequentialCombineNumSegmentsThreshold()) {
+        return new SequentialSortedGroupByCombineOperator(operators, 
_queryContext, _executorService);
+      }
+      return new SortedGroupByCombineOperator(operators, _queryContext, 
_executorService);
+    }
+    // Aggregation group-by
+    return new GroupByCombineOperator(operators, _queryContext, 
_executorService);
+  }
+
+  /// Returns the combine operator for a distinct query.
+  protected BaseCombineOperator createDistinctCombineOperator(List<Operator> 
operators) {
+    return new DistinctCombineOperator(operators, _queryContext, 
_executorService);
+  }
+
+  /// Returns the streaming combine operator for a selection-only query.
+  protected BaseCombineOperator 
createStreamingSelectionOnlyCombineOperator(List<Operator> operators) {
+    return new StreamingSelectionOnlyCombineOperator(operators, _queryContext, 
_executorService);
+  }
+
+  /// Returns the streaming combine operator for a group-by query. This is a 
different path from
+  /// [#createGroupByCombineOperator()]: it flushes partial results and relies 
on an aggregation above to
+  /// merge them, so an implementation substituting one is not obliged to 
substitute the other.
+  protected BaseCombineOperator 
createStreamingGroupByCombineOperator(List<Operator> operators) {
+    return new StreamingGroupByCombineOperator(operators, _queryContext, 
_executorService,
+        _queryContext.getStreamingGroupByFlushThreshold());
+  }
+
+  /// Returns the streaming combine operator for a distinct query. See
+  /// [#createStreamingGroupByCombineOperator()] for why this is separate from
+  /// [#createDistinctCombineOperator()].
+  protected BaseCombineOperator 
createStreamingDistinctCombineOperator(List<Operator> operators) {
+    return new StreamingDistinctCombineOperator(operators, _queryContext, 
_executorService,
+        _queryContext.getStreamingDistinctFlushThreshold());
   }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to