FrankChen021 commented on code in PR #20093:
URL: https://github.com/apache/druid/pull/20093#discussion_r4111370300


##########
sql/src/main/java/org/apache/druid/sql/calcite/aggregation/builtin/SumZeroSqlAggregator.java:
##########
@@ -29,4 +37,42 @@ public SqlAggFunction calciteFunction()
   {
     return SqlStdOperatorTable.SUM0;
   }
+
+  @Override
+  Aggregation getAggregation(
+      final String name,
+      final AggregateCall aggregateCall,
+      final ExprMacroTable macroTable,
+      final String fieldName
+  )
+  {
+    final ColumnType valueType = 
Calcites.getColumnTypeForRelDataType(aggregateCall.getType());
+    if (valueType == null) {
+      return null;
+    }
+
+    if (aggregateCall.filterArg >= 0) {

Review Comment:
   [P2] Keep filtered SUM0 supported in window aggregates
   
   **Finding:** The filtered branch now always returns an Aggregation with an 
ExpressionPostAggregator. Windowing.fromCalciteStuff rejects any translated 
window aggregation with a post-aggregator, so a filtered SUM0 window 
call—SUM0(value) FILTER (WHERE cond) OVER (...), which is registered in 
DruidOperatorTable and previously translated to one 
FilteredAggregatorFactory—now fails planning instead of executing.
   
   **Suggestion:** Use a window-compatible aggregation for filtered SUM0 or 
move the null-to-zero handling into window processing; cover a filtered SUM0 
window query so this path remains translatable.



##########
sql/src/main/java/org/apache/druid/sql/calcite/aggregation/builtin/SumZeroSqlAggregator.java:
##########
@@ -29,4 +37,42 @@ public SqlAggFunction calciteFunction()
   {
     return SqlStdOperatorTable.SUM0;
   }
+
+  @Override
+  Aggregation getAggregation(
+      final String name,
+      final AggregateCall aggregateCall,
+      final ExprMacroTable macroTable,
+      final String fieldName
+  )
+  {
+    final ColumnType valueType = 
Calcites.getColumnTypeForRelDataType(aggregateCall.getType());
+    if (valueType == null) {
+      return null;
+    }
+
+    if (aggregateCall.filterArg >= 0) {
+      // SQL SUM0 semantics require 0 when the filter matches nothing, but the 
native
+      // FilteredAggregatorFactory chain outputs null for empty input. Wrap 
the sum in
+      // an expression post-aggregator that replaces null with 0. This keeps 
the
+      // D1 rewrite of DruidAggregateCaseToFilterRule semantically consistent 
with the
+      // original SUM(CASE WHEN ... THEN ... ELSE 0 END).
+      // Unfiltered SUM0 keeps the plain factory path to avoid widening this 
fix.
+      final String innerName = name + ":sum";
+      final AggregatorFactory innerFactory =
+          createSumAggregatorFactory(valueType, innerName, fieldName, 
macroTable);
+      return Aggregation.create(
+          ImmutableList.of(innerFactory),
+          new ExpressionPostAggregator(
+              name,
+              "nvl(\"" + innerName + "\", 0)",

Review Comment:
   [P2] Preserve NULL for all-null matching rows
   
   **Finding:** The unconditional nvl converts every null result from the 
filtered sum to 0. For SUM(CASE WHEN cond THEN value ELSE 0 END), rows that 
satisfy cond with a null value still contribute NULL, so when all input rows 
match and every value is null the original expression returns NULL; the 
rewritten SUM0/filter now returns 0. This changes SQL results for the existing 
7=7,null case whenever extendedFilteredSumRewrite is enabled.
   
   **Suggestion:** Keep enough information to distinguish no matching rows from 
matching rows with only null values (for example, a filtered count alongside 
the sum) and coalesce only the former; add a regression case for the all-null 
state.



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