diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2011-11-03 00:51:06 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2011-11-03 00:51:06 -0400 |
commit | e4e60e7b6125e77f679861ebf43cc6b9f9dbf16d (patch) | |
tree | ab7bcfc64e6e78e81617bc93df631fbdbcd15c59 /src/include | |
parent | 5cd7b682427d0e912b3ddf7f4910d52089e0df71 (diff) |
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.
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/nodes/plannodes.h | 4 | ||||
-rw-r--r-- | src/include/nodes/relation.h | 21 | ||||
-rw-r--r-- | src/include/optimizer/subselect.h | 4 |
3 files changed, 18 insertions, 11 deletions
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 7c085b3f4f6..7ab0b34885c 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -488,7 +488,9 @@ typedef struct Join * The nestParams list identifies any executor Params that must be passed * into execution of the inner subplan carrying values from the current row * of the outer subplan. Currently we restrict these values to be simple - * Vars, but perhaps someday that'd be worth relaxing. + * Vars, but perhaps someday that'd be worth relaxing. (Note: during plan + * creation, the paramval can actually be a PlaceHolderVar expression; but it + * must be a Var with varno OUTER_VAR by the time it gets to the executor.) * ---------------- */ typedef struct NestLoop diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index 0aec1637c93..4a7178520fb 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -1432,13 +1432,16 @@ typedef struct MinMaxAggInfo * * Each paramlist item shows the absolute query level it is associated with, * where the outermost query is level 1 and nested subqueries have higher - * numbers. The item the parameter slot represents can be one of three kinds: + * numbers. The item the parameter slot represents can be one of four kinds: * * A Var: the slot represents a variable of that level that must be passed * down because subqueries have outer references to it, or must be passed * from a NestLoop node of that level to its inner scan. The varlevelsup * value in the Var will always be zero. * + * A PlaceHolderVar: this works much like the Var case. It is currently + * only needed for NestLoop parameters, not outer references. + * * An Aggref (with an expression tree representing its argument): the slot * represents an aggregate expression that is an outer reference for some * subquery. The Aggref itself has agglevelsup = 0, and its argument tree @@ -1448,20 +1451,20 @@ typedef struct MinMaxAggInfo * for that subplan). The absolute level shown for such items corresponds * to the parent query of the subplan. * - * Note: we detect duplicate Var parameters and coalesce them into one slot, - * but we do not bother to do this for Aggrefs, and it would be incorrect - * to do so for Param slots. Duplicate detection is actually *necessary* - * in the case of NestLoop parameters since it serves to match up the usage - * of a Param (in the inner scan) with the assignment of the value (in the - * NestLoop node). This might result in the same PARAM_EXEC slot being used - * by multiple NestLoop nodes or SubPlan nodes, but no harm is done since + * Note: we detect duplicate Var and PlaceHolderVar parameters and coalesce + * them into one slot, but we do not bother to do this for Aggrefs, and it + * would be incorrect to do so for Param slots. Duplicate detection is + * actually *necessary* for NestLoop parameters since it serves to match up + * the usage of a Param (in the inner scan) with the assignment of the value + * (in the NestLoop node). This might result in the same PARAM_EXEC slot being + * used by multiple NestLoop nodes or SubPlan nodes, but no harm is done since * the same value would be assigned anyway. */ typedef struct PlannerParamItem { NodeTag type; - Node *item; /* the Var, Aggref, or Param */ + Node *item; /* the Var, PlaceHolderVar, Aggref, or Param */ Index abslevel; /* its absolute query level */ } PlannerParamItem; diff --git a/src/include/optimizer/subselect.h b/src/include/optimizer/subselect.h index ff9e2b7f89f..564865ad68f 100644 --- a/src/include/optimizer/subselect.h +++ b/src/include/optimizer/subselect.h @@ -29,7 +29,9 @@ extern void SS_finalize_plan(PlannerInfo *root, Plan *plan, bool attach_initplans); extern Param *SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan, Oid resulttype, int32 resulttypmod, Oid resultcollation); -extern Param *assign_nestloop_param(PlannerInfo *root, Var *var); +extern Param *assign_nestloop_param_var(PlannerInfo *root, Var *var); +extern Param *assign_nestloop_param_placeholdervar(PlannerInfo *root, + PlaceHolderVar *phv); extern int SS_assign_special_param(PlannerInfo *root); #endif /* SUBSELECT_H */ |