summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/subselect.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/subselect.c')
-rw-r--r--src/backend/optimizer/plan/subselect.c114
1 files changed, 86 insertions, 28 deletions
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 7b0dd75e7fe..6c6122e1485 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.155 2009/10/12 18:10:48 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.156 2009/10/26 02:26:35 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -77,7 +77,8 @@ static Node *process_sublinks_mutator(Node *node,
process_sublinks_context *context);
static Bitmapset *finalize_plan(PlannerInfo *root,
Plan *plan,
- Bitmapset *valid_params);
+ Bitmapset *valid_params,
+ Bitmapset *scan_params);
static bool finalize_primnode(Node *node, finalize_primnode_context *context);
@@ -215,10 +216,14 @@ generate_new_param(PlannerInfo *root, Oid paramtype, int32 paramtypmod)
}
/*
- * Assign a (nonnegative) PARAM_EXEC ID for a recursive query's worktable.
+ * Assign a (nonnegative) PARAM_EXEC ID for a special parameter (one that
+ * is not actually used to carry a value at runtime). Such parameters are
+ * used for special runtime signaling purposes, such as connecting a
+ * recursive union node to its worktable scan node or forcing plan
+ * re-evaluation within the EvalPlanQual mechanism.
*/
int
-SS_assign_worktable_param(PlannerInfo *root)
+SS_assign_special_param(PlannerInfo *root)
{
Param *param;
@@ -335,7 +340,7 @@ make_subplan(PlannerInfo *root, Query *orig_subquery, SubLinkType subLinkType,
/* And convert to SubPlan or InitPlan format. */
result = build_subplan(root, plan,
- subroot->parse->rtable, subroot->parse->rowMarks,
+ subroot->parse->rtable, subroot->rowMarks,
subLinkType, testexpr, true, isTopQual);
/*
@@ -377,7 +382,7 @@ make_subplan(PlannerInfo *root, Query *orig_subquery, SubLinkType subLinkType,
/* OK, convert to SubPlan format. */
hashplan = (SubPlan *) build_subplan(root, plan,
subroot->parse->rtable,
- subroot->parse->rowMarks,
+ subroot->rowMarks,
ANY_SUBLINK, newtestexpr,
false, true);
/* Check we got what we expected */
@@ -949,7 +954,7 @@ SS_process_ctes(PlannerInfo *root)
root->glob->subrtables = lappend(root->glob->subrtables,
subroot->parse->rtable);
root->glob->subrowmarks = lappend(root->glob->subrowmarks,
- subroot->parse->rowMarks);
+ subroot->rowMarks);
splan->plan_id = list_length(root->glob->subplans);
root->init_plans = lappend(root->init_plans, splan);
@@ -1702,7 +1707,8 @@ process_sublinks_mutator(Node *node, process_sublinks_context *context)
}
/*
- * SS_finalize_plan - do final sublink processing for a completed Plan.
+ * SS_finalize_plan - do final sublink and parameter processing for a
+ * completed Plan.
*
* This recursively computes the extParam and allParam sets for every Plan
* node in the given plan tree. It also optionally attaches any previously
@@ -1751,7 +1757,8 @@ SS_finalize_plan(PlannerInfo *root, Plan *plan, bool attach_initplans)
* output parameters of any initPlans. (We do not include output
* parameters of regular subplans. Those should only appear within the
* testexpr of SubPlan nodes, and are taken care of locally within
- * finalize_primnode.)
+ * finalize_primnode. Likewise, special parameters that are generated
+ * by nodes such as ModifyTable are handled within finalize_plan.)
*
* Note: this is a bit overly generous since some parameters of upper
* query levels might belong to query subtrees that don't include this
@@ -1772,14 +1779,11 @@ SS_finalize_plan(PlannerInfo *root, Plan *plan, bool attach_initplans)
paramid++;
}
- /* Also include the recursion working table, if any */
- if (root->wt_param_id >= 0)
- valid_params = bms_add_member(valid_params, root->wt_param_id);
/*
* Now recurse through plan tree.
*/
- (void) finalize_plan(root, plan, valid_params);
+ (void) finalize_plan(root, plan, valid_params, NULL);
bms_free(valid_params);
@@ -1819,19 +1823,28 @@ SS_finalize_plan(PlannerInfo *root, Plan *plan, bool attach_initplans)
/*
* Recursive processing of all nodes in the plan tree
*
+ * valid_params is the set of param IDs considered valid to reference in
+ * this plan node or its children.
+ * scan_params is a set of param IDs to force scan plan nodes to reference.
+ * This is for EvalPlanQual support, and is always NULL at the top of the
+ * recursion.
+ *
* The return value is the computed allParam set for the given Plan node.
* This is just an internal notational convenience.
*/
static Bitmapset *
-finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params)
+finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params,
+ Bitmapset *scan_params)
{
finalize_primnode_context context;
+ int locally_added_param;
if (plan == NULL)
return NULL;
context.root = root;
context.paramids = NULL; /* initialize set to empty */
+ locally_added_param = -1; /* there isn't one */
/*
* When we call finalize_primnode, context.paramids sets are automatically
@@ -1852,6 +1865,10 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params)
&context);
break;
+ case T_SeqScan:
+ context.paramids = bms_add_members(context.paramids, scan_params);
+ break;
+
case T_IndexScan:
finalize_primnode((Node *) ((IndexScan *) plan)->indexqual,
&context);
@@ -1860,6 +1877,7 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params)
* we need not look at indexqualorig, since it will have the same
* param references as indexqual.
*/
+ context.paramids = bms_add_members(context.paramids, scan_params);
break;
case T_BitmapIndexScan:
@@ -1875,11 +1893,13 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params)
case T_BitmapHeapScan:
finalize_primnode((Node *) ((BitmapHeapScan *) plan)->bitmapqualorig,
&context);
+ context.paramids = bms_add_members(context.paramids, scan_params);
break;
case T_TidScan:
finalize_primnode((Node *) ((TidScan *) plan)->tidquals,
&context);
+ context.paramids = bms_add_members(context.paramids, scan_params);
break;
case T_SubqueryScan:
@@ -1893,16 +1913,20 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params)
*/
context.paramids = bms_add_members(context.paramids,
((SubqueryScan *) plan)->subplan->extParam);
+ /* We need scan_params too, though */
+ context.paramids = bms_add_members(context.paramids, scan_params);
break;
case T_FunctionScan:
finalize_primnode(((FunctionScan *) plan)->funcexpr,
&context);
+ context.paramids = bms_add_members(context.paramids, scan_params);
break;
case T_ValuesScan:
finalize_primnode((Node *) ((ValuesScan *) plan)->values_lists,
&context);
+ context.paramids = bms_add_members(context.paramids, scan_params);
break;
case T_CteScan:
@@ -1934,6 +1958,9 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params)
bms_add_member(context.paramids,
((CteScan *) plan)->cteParam);
#endif
+
+ context.paramids = bms_add_members(context.paramids,
+ scan_params);
}
break;
@@ -1941,21 +1968,30 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params)
context.paramids =
bms_add_member(context.paramids,
((WorkTableScan *) plan)->wtParam);
+ context.paramids = bms_add_members(context.paramids, scan_params);
break;
case T_ModifyTable:
{
+ ModifyTable *mtplan = (ModifyTable *) plan;
ListCell *l;
- finalize_primnode((Node *) ((ModifyTable *) plan)->returningLists,
+ /* Force descendant scan nodes to reference epqParam */
+ locally_added_param = mtplan->epqParam;
+ valid_params = bms_add_member(bms_copy(valid_params),
+ locally_added_param);
+ scan_params = bms_add_member(bms_copy(scan_params),
+ locally_added_param);
+ finalize_primnode((Node *) mtplan->returningLists,
&context);
- foreach(l, ((ModifyTable *) plan)->plans)
+ foreach(l, mtplan->plans)
{
context.paramids =
bms_add_members(context.paramids,
finalize_plan(root,
(Plan *) lfirst(l),
- valid_params));
+ valid_params,
+ scan_params));
}
}
break;
@@ -1970,7 +2006,8 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params)
bms_add_members(context.paramids,
finalize_plan(root,
(Plan *) lfirst(l),
- valid_params));
+ valid_params,
+ scan_params));
}
}
break;
@@ -1985,7 +2022,8 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params)
bms_add_members(context.paramids,
finalize_plan(root,
(Plan *) lfirst(l),
- valid_params));
+ valid_params,
+ scan_params));
}
}
break;
@@ -2000,7 +2038,8 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params)
bms_add_members(context.paramids,
finalize_plan(root,
(Plan *) lfirst(l),
- valid_params));
+ valid_params,
+ scan_params));
}
}
break;
@@ -2032,16 +2071,30 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params)
break;
case T_RecursiveUnion:
+ /* child nodes are allowed to reference wtParam */
+ locally_added_param = ((RecursiveUnion *) plan)->wtParam;
+ valid_params = bms_add_member(bms_copy(valid_params),
+ locally_added_param);
+ /* wtParam does *not* get added to scan_params */
+ break;
+
+ case T_LockRows:
+ /* Force descendant scan nodes to reference epqParam */
+ locally_added_param = ((LockRows *) plan)->epqParam;
+ valid_params = bms_add_member(bms_copy(valid_params),
+ locally_added_param);
+ scan_params = bms_add_member(bms_copy(scan_params),
+ locally_added_param);
+ break;
+
case T_Hash:
case T_Agg:
case T_WindowAgg:
- case T_SeqScan:
case T_Material:
case T_Sort:
case T_Unique:
case T_SetOp:
case T_Group:
- case T_LockRows:
break;
default:
@@ -2053,20 +2106,25 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params)
context.paramids = bms_add_members(context.paramids,
finalize_plan(root,
plan->lefttree,
- valid_params));
+ valid_params,
+ scan_params));
context.paramids = bms_add_members(context.paramids,
finalize_plan(root,
plan->righttree,
- valid_params));
+ valid_params,
+ scan_params));
/*
- * RecursiveUnion *generates* its worktable param, so don't bubble that up
+ * Any locally generated parameter doesn't count towards its generating
+ * plan node's external dependencies. (Note: if we changed valid_params
+ * and/or scan_params, we leak those bitmapsets; not worth the notational
+ * trouble to clean them up.)
*/
- if (IsA(plan, RecursiveUnion))
+ if (locally_added_param >= 0)
{
context.paramids = bms_del_member(context.paramids,
- ((RecursiveUnion *) plan)->wtParam);
+ locally_added_param);
}
/* Now we have all the paramids */
@@ -2199,7 +2257,7 @@ SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
root->glob->subrtables = lappend(root->glob->subrtables,
root->parse->rtable);
root->glob->subrowmarks = lappend(root->glob->subrowmarks,
- root->parse->rowMarks);
+ root->rowMarks);
/*
* Create a SubPlan node and add it to the outer list of InitPlans. Note