| From: | Tender Wang <tndrwang(at)gmail(dot)com> |
|---|---|
| To: | leis(at)in(dot)tum(dot)de, pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Subject: | Re: BUG #19765: Wrong result from a chain of LEFT JOINs since v16 |
| Date: | 2026-10-16 13:11:03 |
| Message-ID: | CAHewXNmEhGQj1o4_rKuS5GOoTB8iD=4zvatVi2+y+J-pV+qjxA@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
PG Bug reporting form <noreply(at)postgresql(dot)org> 于2026年10月16日周五 17:50写道:
>
> EXPLAIN shows that all three join conditions have disappeared, leaving
> three unqualified nested-loop left joins:
>
> Nested Loop Left Join
> -> Values Scan on "*VALUES*"
> Filter: (column1 = 1)
> -> Nested Loop Left Join
> -> Nested Loop Left Join
> -> Values Scan on "*VALUES*_1"
> Filter: (column1 = 1)
> -> Values Scan on "*VALUES*_2"
> Filter: (column1 = 1)
> -> Values Scan on "*VALUES*_3"
> Filter: (column1 = 1)
I think the problem is in the interaction between constant propagation
in reconsider_outer_join_clauses() and outer-join identity 3.
To support join reordering, deconstruct_distribute_oj_quals()
generates variants of the join quals with different nullingrels
markings.
The least-nulled variants allow reconsider_outer_join_clause() to
propagate the constant through the chain: a=1 implies a restriction
b=1, then c=1, and finally d=1.
The corresponding join quals are replaced with constant-TRUE dummy clauses.
However, a restriction on the scan of C does not guarantee that c=1
still holds after C has been null-extended. In the chosen join order,
A LEFT JOIN ((B LEFT JOIN C) LEFT JOIN D)
the B/C join produces a row with c=NULL, since no C row passes c=1.
The original c=d qual would reject a match with D, whereas its TRUE
replacement allows d=1 to match.
Thus, deriving the inner-side restriction is not sufficient to
establish that the join qual is redundant.
In particular, replacing a strict qual with TRUE can invalidate the
reasoning that allowed the outer joins to commute.
I am considering guarding this optimization when a commuting lower
outer join could null-extend the outer operand.
Specifically, I would examine the joins in sjinfo->commute_below_l and
retain the original qual if one of their syn_righthand sets overlaps
the outer operand's relids.
It might also be possible to retain constant propagation while keeping
the original join qual, but that would require separating the
deduction from the decision to discard the qual.
--
Thanks,
Tender Wang
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Nitin Motiani | 2026-10-16 14:43:59 | Re: BUG #19765: Wrong result from a chain of LEFT JOINs since v16 |
| Previous Message | Jan Nidzwetzki | 2026-10-16 13:03:59 | Re: START_REPLICATION silently truncates an overlong LSN component |