diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index 62785f98243..10f5622c050 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -553,7 +553,9 @@ offset_relid_set(Relids relids, int offset) * 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 @@ -586,11 +588,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 a5e0efa3313..63d0e99b512 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -6265,6 +6265,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 1) + SubPlan 1 + -> Result + Output: a.b_id +(5 rows) + CREATE TEMP TABLE parted_b (id int PRIMARY KEY) partition by range(id); CREATE TEMP TABLE parted_b1 partition of parted_b for values from (0) to (10); -- test join removals on a partitioned table diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql index 0a1476a3348..5848979630d 100644 --- a/src/test/regress/sql/join.sql +++ b/src/test/regress/sql/join.sql @@ -2287,6 +2287,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; + CREATE TEMP TABLE parted_b (id int PRIMARY KEY) partition by range(id); CREATE TEMP TABLE parted_b1 partition of parted_b for values from (0) to (10);