diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index 3653f00d383..7011275f8c6 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -536,7 +536,9 @@ OffsetVarNodes(Node *node, int offset, int sublevels_up) * Also, new_index can be INVALID_VAR to indicate that we are deleting the * given relid from the tree. In this case we expect to find rt_index only * in Relids fields (varnullingrels, phnullingrels, phrels), never in any - * field that identifies a single relation. + * field that identifies a single relation. The exception is varnosyn, + * which may name an aliased join being removed; the join's RTE remains in + * the rangetable, so we leave such syntactic references unchanged. * * NOTE: although this has the form of a walker, we cheat and modify the * nodes in-place. The given expression tree should have been copied @@ -569,11 +571,10 @@ ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context) var->varnullingrels = adjust_relid_set(var->varnullingrels, context->rt_index, context->new_index); - if (var->varnosyn == context->rt_index) - { - Assert(context->new_index != INVALID_VAR); + /* when deleting, leave syntactic refs to a removed join alone */ + if (var->varnosyn == context->rt_index && + context->new_index != INVALID_VAR) var->varnosyn = context->new_index; - } } return false; } diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out index 494ad20fef9..94e158d0dc6 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -7855,6 +7855,18 @@ select c.id, ss.a from c -> Seq Scan on c (7 rows) +-- check join removal when Vars reference the removed join via its alias +explain (verbose, costs off) +select j.b_id, (select j.b_id) from (a left join b on a.b_id = b.id) j; + QUERY PLAN +------------------------------------ + Seq Scan on pg_temp.a + Output: a.b_id, (SubPlan expr_1) + SubPlan expr_1 + -> Result + Output: a.b_id +(5 rows) + -- check the case when the placeholder relates to an outer join and its -- inner in the press field but actually uses only the outer side of the join explain (costs off) diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql index f068aec0a68..576a90dfc1b 100644 --- a/src/test/regress/sql/join.sql +++ b/src/test/regress/sql/join.sql @@ -2901,6 +2901,10 @@ select c.id, ss.a from c left join (select d.a from onerow, d left join b on d.a = b.id) ss on c.id = ss.a; +-- check join removal when Vars reference the removed join via its alias +explain (verbose, costs off) +select j.b_id, (select j.b_id) from (a left join b on a.b_id = b.id) j; + -- check the case when the placeholder relates to an outer join and its -- inner in the press field but actually uses only the outer side of the join explain (costs off)