Fix join removal when Vars reference the removed join via its alias

When a join has an alias, the parser marks every Var referenced
through that alias with the join's RT index as its syntactic referent
(varnosyn), even though varno points at the underlying base relation.
Since commit 2ebf25e7d, join removal strips the removed relids from
the query tree using ChangeVarNodes() with INVALID_VAR, which asserts
that the relid doesn't appear in any field identifying a single
relation.  A varnosyn that names the removed join violates that, so a
query like

    SELECT j.x FROM (t1 s(x) LEFT JOIN t2 ON s.x = t2.a) j;

with t2.a unique fails an assertion.  In non-assert builds, varnosyn
is silently set to INVALID_VAR.

Such syntactic references are still valid after the removal: the join
is only taken out of the jointree, and its RTE remains in the
rangetable through to the finished plan.  So, when deleting a relid,
leave varnosyn unchanged, as join removal did before 2ebf25e7d.

Back-patch to v16, as with commit 2ebf25e7d.

Author: Richard Guo <[email protected]>
Reviewed-by: Tom Lane <[email protected]>
Discussion: 
https://postgr.es/m/cambws484sqsdzwtgzykvwtuc6j4m7acw0lfbjp3awpvav7g...@mail.gmail.com
Backpatch-through: 16

Branch
------
REL_18_STABLE

Details
-------
https://git.postgresql.org/pg/commitdiff/051db7737c18b1c5d25cdc4ad508608c4b53fafc

Modified Files
--------------
src/backend/rewrite/rewriteManip.c | 11 ++++++-----
src/test/regress/expected/join.out | 12 ++++++++++++
src/test/regress/sql/join.sql      |  4 ++++
3 files changed, 22 insertions(+), 5 deletions(-)

Reply via email to