agora inbox for pgsql-committers@postgresql.org  
help / color / mirror / Atom feed
pgsql: Strip removed-relation references from PlaceHolderVars at join r
5+ messages / 1 participants
[nested] [flat]

* pgsql: Strip removed-relation references from PlaceHolderVars at join r
@ 2026-06-22 01:44  Richard Guo <rguo@postgresql.org>
  0 siblings, 0 replies; 5+ messages in thread

From: Richard Guo @ 2026-06-22 01:44 UTC (permalink / raw)
  To: pgsql-committers@lists.postgresql.org

Strip removed-relation references from PlaceHolderVars at join removal

When left-join removal deletes a relation, remove_rel_from_query()
updates the relid sets attached to RestrictInfos and
EquivalenceMembers, and the canonical PlaceHolderVar held in each
PlaceHolderInfo, but it does not rewrite the PlaceHolderVars embedded
in clause and EquivalenceClass member expressions.  That has been
fine, because later processing consults those relid sets rather than
the embedded PlaceHolderVars.

However, such an expression may afterwards be translated for an
appendrel child and have its relids recomputed from scratch by
pull_varnos().  If the embedded PlaceHolderVar's phrels still mentions
the removed relation, pull_varnos() folds it back in, so the rebuilt
clause's relids reference a no-longer-existent relation.  That yields
a parameterized path keyed on the removed relation, tripping the
Assert on root->outer_join_rels in get_eclass_indexes_for_relids().

Fix by stripping the removed relids from the PlaceHolderVars in
surviving rels' baserestrictinfo and in EquivalenceClass member
expressions, keeping them consistent with the canonical
PlaceHolderVars.

This is only reachable on v18 and later, where
match_index_to_operand() began ignoring PlaceHolderVars; before that,
the wrapping PlaceHolderVar prevented the index match that exposes the
stale relids.

Reported-by: Alexander Kuzmenkov <akuzmenkov@tigerdata.com>
Author: Richard Guo <guofenglinux@gmail.com>
Reviewed-by: Tender Wang <tndrwang@gmail.com>
Discussion: https://postgr.es/m/CALzhyqwryL2QywgO03VQr_237Sq3MEVgTTT2_A9G3nGT5-SRZg@mail.gmail.com
Backpatch-through: 18

Branch
------
master

Details
-------
https://git.postgresql.org/pg/commitdiff/9a60f295bcb186a729d04e76377b7f122b2a1dd9

Modified Files
--------------
src/backend/optimizer/plan/analyzejoins.c | 119 +++++++++++++++++++++++++++---
src/test/regress/expected/join.out        |  22 ++++++
src/test/regress/sql/join.sql             |  12 +++
3 files changed, 143 insertions(+), 10 deletions(-)



^ permalink  raw  reply  [nested|flat] 5+ messages in thread

* pgsql: Strip removed-relation references from PlaceHolderVars at join r
@ 2026-06-22 01:44  Richard Guo <rguo@postgresql.org>
  0 siblings, 0 replies; 5+ messages in thread

From: Richard Guo @ 2026-06-22 01:44 UTC (permalink / raw)
  To: pgsql-committers@lists.postgresql.org

Strip removed-relation references from PlaceHolderVars at join removal

When left-join removal deletes a relation, remove_rel_from_query()
updates the relid sets attached to RestrictInfos and
EquivalenceMembers, and the canonical PlaceHolderVar held in each
PlaceHolderInfo, but it does not rewrite the PlaceHolderVars embedded
in clause and EquivalenceClass member expressions.  That has been
fine, because later processing consults those relid sets rather than
the embedded PlaceHolderVars.

However, such an expression may afterwards be translated for an
appendrel child and have its relids recomputed from scratch by
pull_varnos().  If the embedded PlaceHolderVar's phrels still mentions
the removed relation, pull_varnos() folds it back in, so the rebuilt
clause's relids reference a no-longer-existent relation.  That yields
a parameterized path keyed on the removed relation, tripping the
Assert on root->outer_join_rels in get_eclass_indexes_for_relids().

Fix by stripping the removed relids from the PlaceHolderVars in
surviving rels' baserestrictinfo and in EquivalenceClass member
expressions, keeping them consistent with the canonical
PlaceHolderVars.

This is only reachable on v18 and later, where
match_index_to_operand() began ignoring PlaceHolderVars; before that,
the wrapping PlaceHolderVar prevented the index match that exposes the
stale relids.

Reported-by: Alexander Kuzmenkov <akuzmenkov@tigerdata.com>
Author: Richard Guo <guofenglinux@gmail.com>
Reviewed-by: Tender Wang <tndrwang@gmail.com>
Discussion: https://postgr.es/m/CALzhyqwryL2QywgO03VQr_237Sq3MEVgTTT2_A9G3nGT5-SRZg@mail.gmail.com
Backpatch-through: 18

Branch
------
REL_18_STABLE

Details
-------
https://git.postgresql.org/pg/commitdiff/e0252679559adaeee16a7924430f542a1cad3ab7

Modified Files
--------------
src/backend/optimizer/plan/analyzejoins.c | 121 +++++++++++++++++++++++++++---
src/test/regress/expected/join.out        |  20 +++++
src/test/regress/sql/join.sql             |  12 +++
3 files changed, 143 insertions(+), 10 deletions(-)



^ permalink  raw  reply  [nested|flat] 5+ messages in thread

* pgsql: Strip removed-relation references from PHVs in join clauses
@ 2026-07-15 00:23  Richard Guo <rguo@postgresql.org>
  0 siblings, 0 replies; 5+ messages in thread

From: Richard Guo @ 2026-07-15 00:23 UTC (permalink / raw)
  To: pgsql-committers@lists.postgresql.org

Strip removed-relation references from PHVs in join clauses

Commit 9a60f295b stripped the stale PlaceHolderVars left behind by
left-join removal from the surviving rels' baserestrictinfo and from
EquivalenceClass member expressions, but it overlooked join clauses.
A PlaceHolderVar embedded in a join clause can likewise retain the
removed rel and join in its phrels, since remove_rel_from_query()
fixes up the RestrictInfo's own relid sets but not the PHVs inside its
expression.

As before, this is normally harmless, because later processing
consults those relid sets rather than the embedded PHVs.  However, a
restriction clause derived from such an OR join clause inherits the
stale PlaceHolderVar, and when the derived clause is translated for an
appendrel child, pull_varnos() recomputes its relids and folds the
removed relation back in.  The rebuilt clause then references a
no-longer-existent relation, tripping an assertion during path
generation.

Fix by also stripping the removed relation from the PlaceHolderVars in
the surviving rels' join clauses, including the sub-clauses of any OR
clause.

Like 9a60f295b, this is only reachable on v18 and later, where
match_index_to_operand() began ignoring PlaceHolderVars.

Author: Arne Roland <arne.roland@malkut.net>
Reviewed-by: Tender Wang <tndrwang@gmail.com>
Reviewed-by: Richard Guo <guofenglinux@gmail.com>
Discussion: https://postgr.es/m/27a44087-3d65-473e-8d88-7c12228e0d7e@malkut.net
Backpatch-through: 18

Branch
------
master

Details
-------
https://git.postgresql.org/pg/commitdiff/d68576bcfc7227d94c4391a3c34aadb8dbf8a3c7

Modified Files
--------------
src/backend/optimizer/plan/analyzejoins.c | 78 +++++++++++++++++++++++++++++--
src/test/regress/expected/join.out        | 12 +++++
src/test/regress/sql/join.sql             |  7 +++
3 files changed, 92 insertions(+), 5 deletions(-)



^ permalink  raw  reply  [nested|flat] 5+ messages in thread

* pgsql: Strip removed-relation references from PHVs in join clauses
@ 2026-07-15 00:23  Richard Guo <rguo@postgresql.org>
  0 siblings, 0 replies; 5+ messages in thread

From: Richard Guo @ 2026-07-15 00:23 UTC (permalink / raw)
  To: pgsql-committers@lists.postgresql.org

Strip removed-relation references from PHVs in join clauses

Commit 9a60f295b stripped the stale PlaceHolderVars left behind by
left-join removal from the surviving rels' baserestrictinfo and from
EquivalenceClass member expressions, but it overlooked join clauses.
A PlaceHolderVar embedded in a join clause can likewise retain the
removed rel and join in its phrels, since remove_rel_from_query()
fixes up the RestrictInfo's own relid sets but not the PHVs inside its
expression.

As before, this is normally harmless, because later processing
consults those relid sets rather than the embedded PHVs.  However, a
restriction clause derived from such an OR join clause inherits the
stale PlaceHolderVar, and when the derived clause is translated for an
appendrel child, pull_varnos() recomputes its relids and folds the
removed relation back in.  The rebuilt clause then references a
no-longer-existent relation, tripping an assertion during path
generation.

Fix by also stripping the removed relation from the PlaceHolderVars in
the surviving rels' join clauses, including the sub-clauses of any OR
clause.

Like 9a60f295b, this is only reachable on v18 and later, where
match_index_to_operand() began ignoring PlaceHolderVars.

Author: Arne Roland <arne.roland@malkut.net>
Reviewed-by: Tender Wang <tndrwang@gmail.com>
Reviewed-by: Richard Guo <guofenglinux@gmail.com>
Discussion: https://postgr.es/m/27a44087-3d65-473e-8d88-7c12228e0d7e@malkut.net
Backpatch-through: 18

Branch
------
REL_19_STABLE

Details
-------
https://git.postgresql.org/pg/commitdiff/aae47813a14d1f5638469bda146d7839e39b7097

Modified Files
--------------
src/backend/optimizer/plan/analyzejoins.c | 78 +++++++++++++++++++++++++++++--
src/test/regress/expected/join.out        | 12 +++++
src/test/regress/sql/join.sql             |  7 +++
3 files changed, 92 insertions(+), 5 deletions(-)



^ permalink  raw  reply  [nested|flat] 5+ messages in thread

* pgsql: Strip removed-relation references from PHVs in join clauses
@ 2026-07-15 00:23  Richard Guo <rguo@postgresql.org>
  0 siblings, 0 replies; 5+ messages in thread

From: Richard Guo @ 2026-07-15 00:23 UTC (permalink / raw)
  To: pgsql-committers@lists.postgresql.org

Strip removed-relation references from PHVs in join clauses

Commit 9a60f295b stripped the stale PlaceHolderVars left behind by
left-join removal from the surviving rels' baserestrictinfo and from
EquivalenceClass member expressions, but it overlooked join clauses.
A PlaceHolderVar embedded in a join clause can likewise retain the
removed rel and join in its phrels, since remove_rel_from_query()
fixes up the RestrictInfo's own relid sets but not the PHVs inside its
expression.

As before, this is normally harmless, because later processing
consults those relid sets rather than the embedded PHVs.  However, a
restriction clause derived from such an OR join clause inherits the
stale PlaceHolderVar, and when the derived clause is translated for an
appendrel child, pull_varnos() recomputes its relids and folds the
removed relation back in.  The rebuilt clause then references a
no-longer-existent relation, tripping an assertion during path
generation.

Fix by also stripping the removed relation from the PlaceHolderVars in
the surviving rels' join clauses, including the sub-clauses of any OR
clause.

Like 9a60f295b, this is only reachable on v18 and later, where
match_index_to_operand() began ignoring PlaceHolderVars.

Author: Arne Roland <arne.roland@malkut.net>
Reviewed-by: Tender Wang <tndrwang@gmail.com>
Reviewed-by: Richard Guo <guofenglinux@gmail.com>
Discussion: https://postgr.es/m/27a44087-3d65-473e-8d88-7c12228e0d7e@malkut.net
Backpatch-through: 18

Branch
------
REL_18_STABLE

Details
-------
https://git.postgresql.org/pg/commitdiff/18105e6db5e5314a575fdb23a99cf4809d8ef062

Modified Files
--------------
src/backend/optimizer/plan/analyzejoins.c | 79 ++++++++++++++++++++++++++++---
src/test/regress/expected/join.out        | 11 +++++
src/test/regress/sql/join.sql             |  7 +++
3 files changed, 91 insertions(+), 6 deletions(-)



^ permalink  raw  reply  [nested|flat] 5+ messages in thread


end of thread, other threads:[~2026-07-15 00:23 UTC | newest]

Thread overview: 5+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2026-06-22 01:44 pgsql: Strip removed-relation references from PlaceHolderVars at join r Richard Guo <rguo@postgresql.org>
2026-06-22 01:44 pgsql: Strip removed-relation references from PlaceHolderVars at join r Richard Guo <rguo@postgresql.org>
2026-07-15 00:23 pgsql: Strip removed-relation references from PHVs in join clauses Richard Guo <rguo@postgresql.org>
2026-07-15 00:23 pgsql: Strip removed-relation references from PHVs in join clauses Richard Guo <rguo@postgresql.org>
2026-07-15 00:23 pgsql: Strip removed-relation references from PHVs in join clauses Richard Guo <rguo@postgresql.org>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox