1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Fix handling of PlaceHolderVars in nestloop parameter management.

If we use a PlaceHolderVar from the outer relation in an inner indexscan,
we need to reference the PlaceHolderVar as such as the value to be passed
in from the outer relation.  The previous code effectively tried to
reconstruct the PHV from its component expression, which doesn't work since
(a) the Vars therein aren't necessarily bubbled up far enough, and (b) it
would be the wrong semantics anyway because of the possibility that the PHV
is supposed to have gone to null at some point before the current join.
Point (a) led to "variable not found in subplan target list" planner
errors, but point (b) would have led to silently wrong answers.
Per report from Roger Niederland.
This commit is contained in:
Tom Lane
2011-11-03 00:50:58 -04:00
parent 1a77f8b63d
commit 7e3bf99baa
9 changed files with 208 additions and 19 deletions

View File

@ -170,7 +170,7 @@ replace_outer_var(PlannerInfo *root, Var *var)
* the Var to be local to the current query level.
*/
Param *
assign_nestloop_param(PlannerInfo *root, Var *var)
assign_nestloop_param_var(PlannerInfo *root, Var *var)
{
Param *retval;
int i;
@ -190,6 +190,65 @@ assign_nestloop_param(PlannerInfo *root, Var *var)
return retval;
}
/*
* Generate a Param node to replace the given PlaceHolderVar, which will be
* supplied from an upper NestLoop join node.
*
* This is just like assign_nestloop_param_var, except for PlaceHolderVars.
*/
Param *
assign_nestloop_param_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
{
Param *retval;
ListCell *ppl;
PlannerParamItem *pitem;
Index abslevel;
int i;
Assert(phv->phlevelsup == 0);
abslevel = root->query_level;
/* If there's already a paramlist entry for this same PHV, just use it */
/* We assume comparing the PHIDs is sufficient */
i = 0;
foreach(ppl, root->glob->paramlist)
{
pitem = (PlannerParamItem *) lfirst(ppl);
if (pitem->abslevel == abslevel && IsA(pitem->item, PlaceHolderVar))
{
PlaceHolderVar *pphv = (PlaceHolderVar *) pitem->item;
if (pphv->phid == phv->phid)
break;
}
i++;
}
if (ppl == NULL)
{
/* Nope, so make a new one */
phv = (PlaceHolderVar *) copyObject(phv);
pitem = makeNode(PlannerParamItem);
pitem->item = (Node *) phv;
pitem->abslevel = abslevel;
root->glob->paramlist = lappend(root->glob->paramlist, pitem);
/* i is already the correct list index for the new item */
}
retval = makeNode(Param);
retval->paramkind = PARAM_EXEC;
retval->paramid = i;
retval->paramtype = exprType((Node *) phv->phexpr);
retval->paramtypmod = exprTypmod((Node *) phv->phexpr);
retval->paramcollid = exprCollation((Node *) phv->phexpr);
retval->location = -1;
return retval;
}
/*
* Generate a Param node to replace the given Aggref
* which is expected to have agglevelsup > 0 (ie, it is not local).