| From: | Narayanan Venkateswaran <narayananvpostgres(at)gmail(dot)com> |
|---|---|
| To: | Tender Wang <tndrwang(at)gmail(dot)com> |
| Cc: | 303677365(at)qq(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Subject: | Re: BUG #19800: Wrong results: self-join elimination drops an ORDER BY sort key with GROUPING SETS / CUBE / ROLLUP |
| Date: | 2026-11-12 21:34:49 |
| Message-ID: | CAFjuD9eaikD3Tg9khh_tcYbGdKp2+3AZOFrAh898_cGbRtHGRA@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
Hi Tender,
On Wed, Nov 11, 2026 at 12:08 PM Tender Wang <tndrwang(at)gmail(dot)com> wrote:
>
> Skipping SJE query-wide seems too strict; I'm also thinking about
> approach 2. As in the attached v2.
>
> In the attached v2, I collect the relids referenced by the grouping
> expressions and skip only an SJE candidate whose toRemove or toKeep
> relation overlaps that set. The relid set is computed once in
> remove_useless_self_joins(), so the per-candidate check only requires
> bitmap overlap tests.
Thanks for the v2 patch! I like this approach much better than skipping
SJE for the entire query.
While testing it further, I noticed a couple of small things,
1. In remove_useless_self_joins(), I passed NULL as the root to
pull_varnos(NULL, (Node *) tle->expr). When a grouping set contains a
constant (like GROUP BY ROLLUP(1)), mark_nullable_by_grouping() wraps the
constant in a PlaceHolderVar whose phrels includes all relations in the
jointree. Passing NULL tells pull_varnos() to look inside the
PlaceHolderVar's expression rather than returning ph_eval_at, so SJE can
still optimize self-joins in those queries.
2. In remove_self_joins_one_group(), since r and k are base relation IDs,
I moved the check for r to the outer loop using bms_is_member(r,
grouping_relids) and used bms_is_member(k, grouping_relids) in the inner
loop.
3. I also noticed that the underlying issue can cause wrong results even
without ORDER BY: if the second grouping column is used in HAVING (e.g.,
HAVING t2.a IS NULL) or in an expression like COALESCE(t2.a, -1), SJE
rewrites t1.a and t2.a to the same Var and setrefs.c ends up binding both
to the first column. Skipping SJE for relations in grouping_relids fixes
this case as well.
4. Added the commit message and regression tests in join.sql covering
both cases where SJE should be skipped and cases where SJE should still
apply.
Please find the patch with the above changes attached.
Thank you,
Narayanan
| Attachment | Content-Type | Size |
|---|---|---|
| v3-0001-Skip-self-join-elimination-for-relations-in-group.patch | application/octet-stream | 19.0 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Andrey Rachitskiy | 2026-11-12 21:45:43 | Re: BUG #19884: pg_publication_tables omits a detach-pending partition in root mode |
| Previous Message | Tom Lane | 2026-11-12 21:32:19 | Re: BUG #19851: Adding a tautological CHECK(true) to a domain changes JSON_VALUE's result (silent NULL, value/type c |