| From: | Richard Guo <rguo(at)postgresql(dot)org> |
|---|---|
| To: | pgsql-committers(at)lists(dot)postgresql(dot)org |
| Subject: | pgsql: Don't replace clone clauses with constant TRUE |
| Date: | 2026-10-29 02:30:05 |
| Message-ID: | E1xMFu1-00000001CJe-0LAP@gemulon.postgresql.org |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-committers |
Don't replace clone clauses with constant TRUE
When reconsider_outer_join_clauses() finds an outer-join clause
OUTERVAR = INNERVAR whose OUTERVAR is known to equal a constant, it
pushes INNERVAR = CONSTANT into the inner side and replaces the clause
with constant TRUE. The replacement assumes that OUTERVAR cannot have
gone to NULL where the clause is evaluated.
That assumption fails for a clone made for outer join identity 3.
When an outer join is pushed into the RHS of a lower outer join, its
relid is not added to the joinrel until the commuted pair is complete,
so a version of a clause that lacks that join's nulling bit can be
applied above it, after it has null-extended OUTERVAR. This is fine
for the original clause, because it is strict, which is what allowed
the commutation in the first place; but it is not fine for constant
TRUE. As a result, inner rows could be joined to null-extended outer
rows, producing wrong query results.
To fix, throw back a clone as-is rather than the TRUE replacement, as
v15 and earlier did. The derived INNERVAR = CONSTANT clause remains
valid and is still pushed down. This can leave a redundant join
filter in some plans, as seen in an existing regression test.
To keep the thrown-back clause from affecting selectivity estimates,
including for parameterized scans, where the cached selectivity is not
used, restore the redundancy marker removed by b448f1c8d: a norm_selec
greater than 1 marks a redundant clause, for which
clause_selectivity_ext() always returns 1.0.
Back-patch to v16, where clone clauses were introduced.
Bug: #19765
Reported-by: Viktor Leis <leis(at)in(dot)tum(dot)de>
Diagnosed-by: Tender Wang <tndrwang(at)gmail(dot)com>
Author: Richard Guo <guofenglinux(at)gmail(dot)com>
Co-authored-by: Nitin Motiani <nitinmotiani(at)google(dot)com>
Reviewed-by: Tender Wang <tndrwang(at)gmail(dot)com>
Discussion: https://postgr.es/m/19765-5778b18918040583@postgresql.org
Backpatch-through: 16
Branch
------
master
Details
-------
https://git.postgresql.org/pg/commitdiff/f400289946f7d0e66a4169cf4aa56079f1422a2b
Modified Files
--------------
src/backend/optimizer/path/clausesel.c | 6 +++
src/backend/optimizer/path/equivclass.c | 24 ++++++++++++
src/include/nodes/pathnodes.h | 5 ++-
src/test/regress/expected/join.out | 68 ++++++++++++++++++++++++++++++++-
src/test/regress/sql/join.sql | 24 ++++++++++++
5 files changed, 125 insertions(+), 2 deletions(-)
| From | Date | Subject | |
|---|---|---|---|
| Next Message | David Rowley | 2026-10-29 03:20:14 | pgsql: Empty partial_pathlist when unsetting consider_parallel flag |
| Previous Message | Michael Paquier | 2026-10-29 02:15:12 | pgsql: Do not take a full-page image for REGBUF_NO_CHANGE buffers |