| From: | Tender Wang <tndrwang(at)gmail(dot)com> |
|---|---|
| To: | PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org> |
| Cc: | Richard Guo <guofenglinux(at)gmail(dot)com> |
| Subject: | Eliminate redundant outer-join clone clauses after constant propagation |
| Date: | 2026-11-09 13:49:15 |
| Message-ID: | CAHewXNk8Xpn7RTZFK2EeqTxe10Nmg8eQz3qj3i2FSmNFce1y_Q@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Hi,
When I proposed v3 for the original wrong-result issue [1], it
recorded the relevant deferred outer joins in a new RestrictInfo
field. As noted in the review:
> However, your v3 adds a new field to RestrictInfo, which breaks ABI
> and can't be back-patched.
That concern prevented us from using the v3 approach.
Commit f4002899 instead fixed the correctness issue conservatively by
retaining every constant-propagated clone clause and marking it with
norm_selec greater than 1 so that it contributes no additional
selectivity.
The attached patch revisits the optimization without adding any field
to RestrictInfo.
Consider an outer-join clause:
OUTERVAR = INNERVAR
If OUTERVAR is known to equal a constant,
reconsider_outer_join_clauses() derives:
INNERVAR = CONSTANT
The original equality is then redundant as long as OUTERVAR has not
been null-extended before the clause is evaluated.
If a lower outer join has already null-extended OUTERVAR, however, the
original strict clause is still required to prevent an inner row
satisfying INNERVAR = CONSTANT from matching the null-extended row.
Normally, incompatible_relids is sufficient to reject a clone at such
an evaluation level, because the lower outer join's relid appears in
the available relids.
The exception is a pushed-down outer join that has already been
physically performed but whose OJ relid is still deferred until its
commuting lower outer join completes.
This is the case addressed by f4002899.
The patch uses the existing norm_selec marker to identify clone
clauses made redundant by constant propagation.
When selecting clauses for a particular join or parameterized path, it
checks whether such a deferred outer join may already have
null-extended the clause's outer operand.
It derives this entirely from the existing RestrictInfo and
SpecialJoinInfo fields, including incompatible_relids, outer_relids,
min_lefthand, min_righthand, syn_righthand, and commute_below_l.
If such an outer join may have been performed, the original clause is
retained. Otherwise, it is omitted as redundant.
The clause is not removed during reconsider_outer_join_clauses(). It
is still distributed to the relations and remains available during
join-order search.
It is omitted only later, when constructing the restriction list for a
specific join or parameterized path, after it has served its
join-search purpose.
At that point, omitting it is equivalent to using the constant-TRUE
replacement for that particular placement.
The regression test changes are plan-only changes. The new plans
choose join orders in which the propagated constant restrictions make
the clone clauses redundant, while clauses needed to reject
null-extended rows remain in place.
Thus, this patch restores the elimination of redundant outer-join
clone clauses while preserving the correctness fix from f4002899 and
without changing the RestrictInfo ABI.
[1] https://www.postgresql.org/message-id/19765-5778b18918040583%40postgresql.org
--
Thanks,
Tender Wang
| Attachment | Content-Type | Size |
|---|---|---|
| 0001-Remove-redundant-constant-propagated-outer-join-clau.patch | text/plain | 9.4 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | shihao zhong | 2026-11-09 13:50:51 | Re: [PATCH] Cover get_json_table_plan() with tests |
| Previous Message | Jakub Wartak | 2026-11-09 13:49:11 | Re: aio tests failing on newer Linux kernels |