summaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2012-03-24 16:21:54 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2012-03-24 16:21:54 -0400
commit29e0b4cb772c0089007f795655136e1dd3d48f93 (patch)
tree04c2c88cbd2cdd67b45da78202c616e12f7fe01e /src/include
parent7bdf9b863f57f13fe73b3bed1c456aa905068272 (diff)
Fix planner's handling of outer PlaceHolderVars within subqueries.
For some reason, in the original coding of the PlaceHolderVar mechanism I had supposed that PlaceHolderVars couldn't propagate into subqueries. That is of course entirely possible. When it happens, we need to treat an outer-level PlaceHolderVar much like an outer Var or Aggref, that is SS_replace_correlation_vars() needs to replace the PlaceHolderVar with a Param, and then when building the finished SubPlan we have to provide the PlaceHolderVar expression as an actual parameter for the SubPlan. The handling of the contained expression is a bit delicate but it can be treated exactly like an Aggref's expression. In addition to the missing logic in subselect.c, prepjointree.c was failing to search subqueries for PlaceHolderVars that need their relids adjusted during subquery pullup. It looks like everyplace else that touches PlaceHolderVars got it right, though. Per report from Mark Murawski. In 9.1 and HEAD, queries affected by this oversight would fail with "ERROR: Upper-level PlaceHolderVar found where not expected". But in 9.0 and 8.4, you'd silently get possibly-wrong answers, since the value transmitted into the subquery wouldn't go to null when it should.
Diffstat (limited to 'src/include')
-rw-r--r--src/include/nodes/relation.h13
1 files changed, 9 insertions, 4 deletions
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index dc3a37eae95..b6c598ff7cc 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -1357,12 +1357,17 @@ typedef struct PlaceHolderInfo
*
* 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. The varlevelsup
* value in the Var will always be zero.
*
+ * A PlaceHolderVar: this works much like the Var case, except that the
+ * entry is a PlaceHolderVar node with a contained expression. The PHV
+ * will have phlevelsup = 0, and the contained expression is adjusted
+ * to match in level.
+ *
* 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
@@ -1372,14 +1377,14 @@ typedef struct PlaceHolderInfo
* 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 do this for Aggref or Param slots.
+ * Note: we detect duplicate Var and PlaceHolderVar parameters and coalesce
+ * them into one slot, but we do not do this for Aggref or Param slots.
*/
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;