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


##########
pinot-query-planner/src/main/java/org/apache/pinot/query/planner/physical/v2/opt/rules/AggregatePushdownRule.java:
##########
@@ -94,6 +98,33 @@ public PRelNode onMatch(PRelOptRuleCall call) {
       hintOptions = Map.of();
     }
     boolean isInputExchange = call._currentNode.unwrap().getInput(0) 
instanceof Exchange;
+    if (aggRel.getGroupType() != Aggregate.Group.SIMPLE) {

Review Comment:
   Good catch — the v2 grouping-set branch now checks `withinGroupCollation` 
before the split, matching the default planner's `createPlan`. Since the DIRECT 
fallback does not preserve the ORDER BY across the per-set expansion either, 
the v2 planner now rejects `WITHIN GROUP` ordered aggregates under `GROUPING 
SETS` / `ROLLUP` / `CUBE` with an explicit error (run on the single-stage 
engine) instead of silently producing a wrong list. Added 
`testV2PhysicalPlannerRejectsWithinGroupRollup` (4091cff).
   
   _🤖 Addressed by [Claude Code](https://claude.com/claude-code)_



##########
pinot-query-planner/src/main/java/org/apache/pinot/calcite/rel/logical/PinotLogicalAggregate.java:
##########
@@ -92,6 +97,35 @@ public PinotLogicalAggregate copy(RelTraitSet traitSet, 
RelNode input, Immutable
         _leafReturnFinalResult, _collations, _limit);
   }
 
+  /// Whether this LEAF aggregate must synthesize the {@code $groupingId} 
discriminator column. Only a LEAF
+  /// grouping-set aggregate does: it is converted to a single-stage query 
that expands each row across the
+  /// grouping sets and appends {@code $groupingId}; the multi-stage final 
stage then groups on it.
+  public boolean emitsGroupingId() {
+    return _aggType == AggType.LEAF && getGroupType() != Group.SIMPLE;
+  }
+
+  @Override
+  protected RelDataType deriveRowType() {
+    RelDataType rowType = super.deriveRowType();
+    if (!emitsGroupingId()) {
+      return rowType;
+    }
+    // Insert the synthetic $groupingId INT column right after the union 
group-by columns (before the aggregate
+    // columns), matching the single-stage leaf output layout: [group keys..., 
$groupingId, aggregates...].
+    RelDataTypeFactory typeFactory = getCluster().getTypeFactory();
+    RelDataTypeFactory.Builder builder = typeFactory.builder();
+    List<RelDataTypeField> fields = rowType.getFieldList();
+    int groupCount = getGroupCount();
+    for (int i = 0; i < groupCount; i++) {
+      builder.add(fields.get(i));
+    }
+    builder.add(GroupingSets.GROUPING_ID_COLUMN, 
typeFactory.createSqlType(SqlTypeName.INTEGER));

Review Comment:
   The grouping-set feature ships entirely within a single release, so brokers 
and servers are upgraded together — there is no mixed-version window where an 
older server would see `AggregateNode.groupingSets` from a newer broker. MSE 
has no per-feature capability gate today and relies on lockstep upgrades for 
plan-shape changes (e.g. unknown plan-node types fail fast at deserialization); 
the upgrade ordering is also noted on the proto field as a backstop.
   
   _🤖 Addressed by [Claude Code](https://claude.com/claude-code)_



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