diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index ed1c07bb5e7..ddc222d6913 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -549,7 +549,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 @@ -582,11 +584,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 37ac979e74e..4b31d9e6957 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -6266,6 +6266,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 fc984fff672..90023903077 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);