refactor(unparser): centralize aggregate-scope rendering in the SQL unparser#23789
Conversation
|
Hey @kosiew, can you please review this PR, when you get a chance? One small design note: I went with a small IMO, it reads a bit cleaner at the call sites and keeps the flag from being recomputed per clause. If you'd rather keep it consistent with the existing TIA! |
There was a problem hiding this comment.
@naman-modi
Nice fix overall. I like the direction of consolidating the aggregate scope handling into a small helper. I just have a couple of minor suggestions that could make the abstraction a little cleaner and the test coverage a bit clearer.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #23789 +/- ##
==========================================
- Coverage 80.65% 80.65% -0.01%
==========================================
Files 1091 1091
Lines 370692 370702 +10
Branches 370692 370702 +10
==========================================
+ Hits 298972 298974 +2
+ Misses 53885 53884 -1
- Partials 17835 17844 +9 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Thanks for reviewing @kosiew! I've addressed both review comments. It would be great, if you could trigger the CI. |
e4c275d to
d9e58ed
Compare
d9e58ed to
38cf748
Compare
Which issue does this PR close?
Rationale for this change
... FROM (SELECT ...)).csonly exist inside that subquery. Any clause outside it (SELECT, GROUP BY, HAVING, QUALIFY, ORDER BY) must use the subquery's output columns, not the aliases, so the unparser drops the alias.ORDER BY round(sum("cs"."total_revenue"), 2), while the SELECT list in the same query correctly printedsum("total_revenue").csis out of scope there.What changes are included in this PR?
I moved the rule into one helper,
UnparserAggScope, that checks once per aggregate whether the input is an inner subquery and then prepares expressions for each clause. SELECT, GROUP BY, HAVING, QUALIFY, and both ORDER BY paths now go through it, which fixes the ORDER BY case. The window-over-aggregate path is left as-is with a comment: it is only reachable from hand-built plans, since a window in SQL always sits inside a SELECT that already drops the alias. Only ORDER BY output changes; every already-correct case stays the same.Are these changes tested?
Yes. New tests in
datafusion/core/tests/sql/unparser.rscover the inner-subquery shape for a window sorting by an aggregate, ORDER BY on an unselected aggregate (the fixed case), and a top-level ORDER BY (the second sort path). Existing unparser tests and the TPC-H/Clickbench roundtrips still pass.Are there any user-facing changes?
ORDER BY over an aggregate is now printed without an out-of-scope table qualifier, so the generated SQL is valid for stricter databases. No API changes.