Copilot commented on code in PR #18842:
URL: https://github.com/apache/pinot/pull/18842#discussion_r3531450092


##########
pinot-core/src/test/java/org/apache/pinot/core/query/reduce/MergeDataTablesOnlyTest.java:
##########
@@ -118,6 +118,50 @@ public void testGroupByRoundTrip() {
     assertRoundTrip(query, serverTables);
   }
 
+  /**
+   * Regression for the merge-only-reducer GROUP BY + DISTINCTCOUNT defect: 
prior to the fix,
+   * {@code mergeDataTablesOnly} called {@code getIndexedTable} which 
unconditionally finished the
+   * IndexedTable with {@code storeFinalResult=true} — finalizing each row's 
aggregate (Set → Integer).
+   * The subsequent {@code buildIntermediateDataTable} then read {@code 
_storedColumnDataTypes} (still
+   * OBJECT), took the OBJECT branch, and handed the now-Integer value into
+   * {@code 
BaseDistinctAggregateAggregationFunction.serializeIntermediateResult(Set)} →
+   * {@link ClassCastException}. This test fails without the fix and passes 
with it.
+   *
+   * <p>Builds fresh per-server DataTables for the {@code reduce(...)} 
baseline and the
+   * {@code merge(...)} call separately. The regular reduce path mutates the 
input DataTable's
+   * schema's column-data-types array in place via {@code 
IndexedTable.finish(_, true)} — that's
+   * pre-existing OSS behavior and is fine in production where no caller 
re-reads the input after
+   * a reduce. Reusing the same DataTable list across both calls would falsely 
surface that
+   * mutation as an apparent merge-only bug.
+   */
+  @Test
+  public void testGroupByDistinctCountObjectRoundTrip()
+      throws IOException {
+    String query = "SELECT col1, DISTINCTCOUNT(col2) FROM testTable GROUP BY 
col1";
+    BrokerRequest brokerRequest = 
CalciteSqlCompiler.compileToBrokerRequest(query);
+    BrokerResponseNative baseline = reduce(brokerRequest, 
toMap(buildDistinctCountServerTables(query)));
+    DataTable merged = merge(brokerRequest, 
toMap(buildDistinctCountServerTables(query)));
+    assertNotNull(merged, "merge produced null");
+    BrokerResponseNative viaMerge = reduce(brokerRequest, 
singletonMap(merged));
+    assertResultTablesEquivalent(baseline.getResultTable(), 
viaMerge.getResultTable());
+  }
+
+  /** Two per-server intermediate DataTables for {@code GROUP BY col1, 
DISTINCTCOUNT(col2)} with one
+   * overlapping group across servers so the OBJECT-path per-group Set merge 
actually runs. */

Review Comment:
   This Javadoc says "GROUP BY col1, DISTINCTCOUNT(col2)", which reads like 
`DISTINCTCOUNT(col2)` is part of the GROUP BY clause. It’s actually a `GROUP BY 
col1` query selecting `DISTINCTCOUNT(col2)`, so rephrasing avoids confusion for 
future readers.



##########
pinot-core/src/main/java/org/apache/pinot/core/query/reduce/GroupByDataTableReducer.java:
##########
@@ -148,6 +148,13 @@ public DataTable mergeDataTablesOnly(String tableName, 
DataSchema dataSchema,
       Collection<DataTable> dataTables = dataTableMap.values();
       // Reuse the regular reduce's merge: builds the IndexedTable of group 
keys + intermediate agg state.
       IndexedTable indexedTable = getIndexedTable(dataSchema, dataTables, 
reducerContext);

Review Comment:
   `mergeDataTablesOnly()` rejects `isServerReturnFinalResult()`, but it does 
not reject `isServerReturnFinalResultKeyUnpartitioned()`. That option also 
makes servers return final (not intermediate) aggregate values, so merge-only 
cannot safely produce a re-mergeable intermediate DataTable and should fail 
fast the same way.



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