| From: | Richard Guo <guofenglinux(at)gmail(dot)com> |
|---|---|
| To: | Thom Brown <thom(at)linux(dot)com> |
| Cc: | pgsql-bugs <pgsql-bugs(at)postgresql(dot)org> |
| Subject: | Re: EXPLAIN (VERBOSE) fails with for JSON_ARRAYAGG/JSON_OBJECTAGG + window function |
| Date: | 2026-07-03 03:06:45 |
| Message-ID: | CAMbWs4-b2By5XFEn-_ZJKgN4-8SBhAoRZJrt4gwmM2ctOQzAyw@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
On Fri, Jul 3, 2026 at 7:10 AM Richard Guo <guofenglinux(at)gmail(dot)com> wrote:
> Reproduced here. get_json_agg_constructor() expects that ctor->func
> is Aggref or WindowFunc, but what it gets here is a Var.
>
> This is because the query has both window functions and grouped
> aggregates. make_window_input_target() flattens the final tlist using
> pull_var_clause, which pulls the Aggref out of its JsonConstructorExpr
> wrapper. Then fix_upper_expr() matches that inner Aggref against the
> Agg subplan's tlist and replaces it with an OUTER Var.
Here is the patch. It's a bit annoying that the original JSON agg
syntax then appears nowhere in the EXPLAIN output. All we get is the
bare jsonb_agg_strict Aggref.
WindowAgg
Output: g, (jsonb_agg_strict(name)), row_number() OVER w1
Window: w1 AS (ROWS UNBOUNDED PRECEDING)
-> HashAggregate
Output: g, jsonb_agg_strict(name)
The reason is that the JsonConstructorExpr wrapper and the Aggref it
wraps end up in different plan nodes, and neither alone suffices to
reconstruct the syntax.
I had an attempt to reconstruct the JSON syntax for the WindowAgg node
by leveraging resolve_special_varno(), and that works. But I don't
know how to do that for the HashAggregate node, because the
JsonConstructorExpr wrapper simply doesn't exist at that plan level.
Maybe we can hack the planner to make make_window_input_target() keep
the JsonConstructorExpr together with its Aggref. But I think that is
too invasive and it changes which node evaluates the wrapper.
So that attempt ended up with:
WindowAgg
Output: g, JSON_ARRAYAGG(name RETURNING jsonb), row_number() OVER w1
Window: w1 AS (ROWS UNBOUNDED PRECEDING)
-> HashAggregate
Output: g, jsonb_agg_strict(name)
But I don't think this is good. It fails to state the fact that the
WindowAgg doesn't compute a JSON aggregate; it passes through a value
that the HashAggregate computed. So I gave up this idea.
- Richard
| Attachment | Content-Type | Size |
|---|---|---|
| v1-0001-Fix-EXPLAIN-failure-when-deparsing-SQL-JSON-aggre.patch | application/octet-stream | 7.9 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | David Rowley | 2026-07-03 03:38:34 | Re: BUG #19533: Wrong results from WindowAgg run-condition pushdown on count() with EXCLUDE CURRENT ROW |
| Previous Message | Fujii Masao | 2026-07-03 02:25:54 | Re: BUG #18876: HINT messages for mxid wrap-around say "drop stale slots", but that may not be appropriate |