kosiew commented on code in PR #23327:
URL: https://github.com/apache/datafusion/pull/23327#discussion_r3549033535


##########
datafusion/sql/src/unparser/plan.rs:
##########


Review Comment:
   Nice work applying the new aggregate input normalization to SELECT and GROUP 
BY. 
   
   I think the same path is needed for HAVING predicates that come from a 
`Filter` over an `Aggregate`.
   
   For the same plan shape being fixed here, where `Aggregate` reads from an 
unnamed derived `Projection`, a query like `... GROUP BY 1 HAVING 
count(DISTINCT cs.customer_id) > 0` still unparses to `HAVING (count(DISTINCT 
\"cs\".\"customer_id\") > 0)`. The FROM item is `(SELECT 
\"cs\".\"customer_id\", ... FROM ...)`, so the `cs` qualifier is no longer in 
scope.
   
   Could we apply the same `normalize_agg_input_columns` path after 
`unproject_agg_exprs` here, and also in the QUALIFY branch when it unprojects 
aggregate expressions? That should make all expressions rendered in the 
aggregate SELECT resolve against the derived projection output.



##########
datafusion/core/tests/sql/unparser.rs:
##########
@@ -399,6 +402,118 @@ async fn 
optimized_duckdb_unparse_qualifies_nested_passthrough_column() -> Resul
     Ok(())
 }
 
+// https://github.com/apache/datafusion/issues/23317
+//
+// `SingleDistinctToGroupBy` can produce two stacked Aggregates where the inner
+// Aggregate defines intermediate fields such as `group_alias_0`, `alias1`, and
+// `alias2`. The unparser must preserve that inner Aggregate as a derived table
+// before the outer Aggregate references those fields.
+//
+// Without `SingleDistinctToGroupBy`, the Aggregate still sits over an unnamed
+// derived Projection. In that SQL scope, base table aliases `cs` and `c` are 
no
+// longer visible, so aggregate expressions must refer to the derived table's
+// output columns unqualified.
+const ISSUE_23317_QUERY: &str = r#"
+WITH cohort AS (
+    SELECT
+        signup_year,
+        sum(customers) AS customers,
+        sum(revenue) AS revenue
+    FROM
+        (
+            SELECT
+                date_part('year', c.signup_date) AS signup_year,
+                count(DISTINCT cs.customer_id) AS customers,
+                round(sum(cs.total_revenue), 2) AS revenue
+            FROM
+                "warehouse"."main"."sales" cs
+                JOIN "warehouse"."main"."customers" c USING (customer_id)
+            GROUP BY

Review Comment:
   Small suggestion for the regression coverage: it would be great if the 
`issue_23317` tests executed, or at least parsed, the unparsed SQL rather than 
only checking string fragments.
   
   The bug here is invalid SQL caused by out-of-scope aliases, so a parse or 
roundtrip execution assertion would be more likely to catch similar missed 
clauses like HAVING or ORDER BY even if the exact formatting changes later.



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