mirror of
https://github.com/postgres/postgres.git
synced 2025-05-01 01:04:50 +03:00
Fix pull_varnos to cope with translated PlaceHolderVars.
Commit 55dc86eca changed pull_varnos to use (if possible) the associated ph_eval_at for a PlaceHolderVar. I missed a fine point though: we might be looking at a PHV in the quals or tlist of a child appendrel, in which case we need to compute a ph_eval_at value that's been translated in the same way that the PHV itself has been (cf. adjust_appendrel_attrs). Fortunately, enough info is available in the PlaceHolderInfo to make such translation possible without additional outside data, so we don't need another round of uglification of planner APIs. This is a little bit complicated, but since it's a hard-to-hit corner case, I'm not much worried about adding cycles here. Per report from Jaime Casanova. Back-patch to v12, like the previous commit. Discussion: https://postgr.es/m/20210915230959.GB17635@ahch-to
This commit is contained in:
parent
24c57aa629
commit
febe013cad
@ -200,6 +200,16 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
|
|||||||
* join that forces delay of evaluation of a given qual clause
|
* join that forces delay of evaluation of a given qual clause
|
||||||
* will be processed before we examine that clause here, so the
|
* will be processed before we examine that clause here, so the
|
||||||
* ph_eval_at value should have been updated to include it.
|
* ph_eval_at value should have been updated to include it.
|
||||||
|
*
|
||||||
|
* Another problem is that a PlaceHolderVar can appear in quals or
|
||||||
|
* tlists that have been translated for use in a child appendrel.
|
||||||
|
* Typically such a PHV is a parameter expression sourced by some
|
||||||
|
* other relation, so that the translation from parent appendrel
|
||||||
|
* to child doesn't change its phrels, and we should still take
|
||||||
|
* ph_eval_at at face value. But in corner cases, the PHV's
|
||||||
|
* original phrels can include the parent appendrel itself, in
|
||||||
|
* which case the translated PHV will have the child appendrel in
|
||||||
|
* phrels, and we must translate ph_eval_at to match.
|
||||||
*/
|
*/
|
||||||
PlaceHolderInfo *phinfo = NULL;
|
PlaceHolderInfo *phinfo = NULL;
|
||||||
|
|
||||||
@ -215,12 +225,37 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
|
|||||||
phinfo = NULL;
|
phinfo = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (phinfo != NULL)
|
if (phinfo == NULL)
|
||||||
context->varnos = bms_add_members(context->varnos,
|
{
|
||||||
phinfo->ph_eval_at);
|
/* No PlaceHolderInfo yet, use phrels */
|
||||||
else
|
|
||||||
context->varnos = bms_add_members(context->varnos,
|
context->varnos = bms_add_members(context->varnos,
|
||||||
phv->phrels);
|
phv->phrels);
|
||||||
|
}
|
||||||
|
else if (bms_equal(phv->phrels, phinfo->ph_var->phrels))
|
||||||
|
{
|
||||||
|
/* Normal case: use ph_eval_at */
|
||||||
|
context->varnos = bms_add_members(context->varnos,
|
||||||
|
phinfo->ph_eval_at);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Translated PlaceHolderVar: translate ph_eval_at to match */
|
||||||
|
Relids newevalat,
|
||||||
|
delta;
|
||||||
|
|
||||||
|
/* remove what was removed from phv->phrels ... */
|
||||||
|
delta = bms_difference(phinfo->ph_var->phrels, phv->phrels);
|
||||||
|
newevalat = bms_difference(phinfo->ph_eval_at, delta);
|
||||||
|
/* ... then if that was in fact part of ph_eval_at ... */
|
||||||
|
if (!bms_equal(newevalat, phinfo->ph_eval_at))
|
||||||
|
{
|
||||||
|
/* ... add what was added */
|
||||||
|
delta = bms_difference(phv->phrels, phinfo->ph_var->phrels);
|
||||||
|
newevalat = bms_join(newevalat, delta);
|
||||||
|
}
|
||||||
|
context->varnos = bms_join(context->varnos,
|
||||||
|
newevalat);
|
||||||
|
}
|
||||||
return false; /* don't recurse into expression */
|
return false; /* don't recurse into expression */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4629,6 +4629,34 @@ where q2 = 456;
|
|||||||
123 | 456 | |
|
123 | 456 | |
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
-- and check a related issue where we miscompute required relids for
|
||||||
|
-- a PHV that's been translated to a child rel
|
||||||
|
create temp table parttbl (a integer primary key) partition by range (a);
|
||||||
|
create temp table parttbl1 partition of parttbl for values from (1) to (100);
|
||||||
|
insert into parttbl values (11), (12);
|
||||||
|
explain (costs off)
|
||||||
|
select * from
|
||||||
|
(select *, 12 as phv from parttbl) as ss
|
||||||
|
right join int4_tbl on true
|
||||||
|
where ss.a = ss.phv and f1 = 0;
|
||||||
|
QUERY PLAN
|
||||||
|
----------------------------
|
||||||
|
Nested Loop
|
||||||
|
-> Seq Scan on int4_tbl
|
||||||
|
Filter: (f1 = 0)
|
||||||
|
-> Seq Scan on parttbl1
|
||||||
|
Filter: (a = 12)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
select * from
|
||||||
|
(select *, 12 as phv from parttbl) as ss
|
||||||
|
right join int4_tbl on true
|
||||||
|
where ss.a = ss.phv and f1 = 0;
|
||||||
|
a | phv | f1
|
||||||
|
----+-----+----
|
||||||
|
12 | 12 | 0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- bug #8444: we've historically allowed duplicate aliases within aliased JOINs
|
-- bug #8444: we've historically allowed duplicate aliases within aliased JOINs
|
||||||
select * from
|
select * from
|
||||||
int8_tbl x join (int4_tbl x cross join int4_tbl y) j on q1 = f1; -- error
|
int8_tbl x join (int4_tbl x cross join int4_tbl y) j on q1 = f1; -- error
|
||||||
|
@ -1635,6 +1635,22 @@ select i8.*, ss.v, t.unique2
|
|||||||
left join tenk1 t on t.unique2 = ss.v
|
left join tenk1 t on t.unique2 = ss.v
|
||||||
where q2 = 456;
|
where q2 = 456;
|
||||||
|
|
||||||
|
-- and check a related issue where we miscompute required relids for
|
||||||
|
-- a PHV that's been translated to a child rel
|
||||||
|
create temp table parttbl (a integer primary key) partition by range (a);
|
||||||
|
create temp table parttbl1 partition of parttbl for values from (1) to (100);
|
||||||
|
insert into parttbl values (11), (12);
|
||||||
|
explain (costs off)
|
||||||
|
select * from
|
||||||
|
(select *, 12 as phv from parttbl) as ss
|
||||||
|
right join int4_tbl on true
|
||||||
|
where ss.a = ss.phv and f1 = 0;
|
||||||
|
|
||||||
|
select * from
|
||||||
|
(select *, 12 as phv from parttbl) as ss
|
||||||
|
right join int4_tbl on true
|
||||||
|
where ss.a = ss.phv and f1 = 0;
|
||||||
|
|
||||||
-- bug #8444: we've historically allowed duplicate aliases within aliased JOINs
|
-- bug #8444: we've historically allowed duplicate aliases within aliased JOINs
|
||||||
|
|
||||||
select * from
|
select * from
|
||||||
|
Loading…
x
Reference in New Issue
Block a user