aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/planner.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/planner.c')
-rw-r--r--src/backend/optimizer/plan/planner.c54
1 files changed, 46 insertions, 8 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 4b06c823b6c..c17fe5f63f6 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.258 2009/10/10 01:43:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.259 2009/10/12 18:10:48 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -132,7 +132,8 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
PlannerInfo *root;
Plan *top_plan;
ListCell *lp,
- *lr;
+ *lrt,
+ *lrm;
/* Cursor options may come from caller or from DECLARE CURSOR stmt */
if (parse->utilityStmt &&
@@ -151,11 +152,14 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
glob->paramlist = NIL;
glob->subplans = NIL;
glob->subrtables = NIL;
+ glob->subrowmarks = NIL;
glob->rewindPlanIDs = NULL;
glob->finalrtable = NIL;
+ glob->finalrowmarks = NIL;
glob->relationOids = NIL;
glob->invalItems = NIL;
glob->lastPHId = 0;
+ glob->lastRowmarkId = 0;
glob->transientPlan = false;
/* Determine what fraction of the plan is likely to be scanned */
@@ -202,15 +206,25 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
/* final cleanup of the plan */
Assert(glob->finalrtable == NIL);
- top_plan = set_plan_references(glob, top_plan, root->parse->rtable);
+ Assert(glob->finalrowmarks == NIL);
+ top_plan = set_plan_references(glob, top_plan,
+ root->parse->rtable,
+ root->parse->rowMarks);
/* ... and the subplans (both regular subplans and initplans) */
Assert(list_length(glob->subplans) == list_length(glob->subrtables));
- forboth(lp, glob->subplans, lr, glob->subrtables)
+ Assert(list_length(glob->subplans) == list_length(glob->subrowmarks));
+ lrt = list_head(glob->subrtables);
+ lrm = list_head(glob->subrowmarks);
+ foreach(lp, glob->subplans)
{
Plan *subplan = (Plan *) lfirst(lp);
- List *subrtable = (List *) lfirst(lr);
+ List *subrtable = (List *) lfirst(lrt);
+ List *subrowmark = (List *) lfirst(lrm);
- lfirst(lp) = set_plan_references(glob, subplan, subrtable);
+ lfirst(lp) = set_plan_references(glob, subplan,
+ subrtable, subrowmark);
+ lrt = lnext(lrt);
+ lrm = lnext(lrm);
}
/* build the PlannedStmt result */
@@ -227,7 +241,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
result->intoClause = parse->intoClause;
result->subplans = glob->subplans;
result->rewindPlanIDs = glob->rewindPlanIDs;
- result->rowMarks = parse->rowMarks;
+ result->rowMarks = glob->finalrowmarks;
result->relationOids = glob->relationOids;
result->invalItems = glob->invalItems;
result->nParamExec = list_length(glob->paramlist);
@@ -350,6 +364,21 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
}
/*
+ * Assign unique IDs (unique within this planner run) to RowMarkClauses.
+ * We can't identify them just by RT index because that will change
+ * during final rtable flattening, and we don't want to have to go back
+ * and change the resnames assigned to junk CTID tlist entries at that
+ * point. Do it now before expanding inheritance sets, because child
+ * relations should inherit their parents' rowmarkId.
+ */
+ foreach(l, parse->rowMarks)
+ {
+ RowMarkClause *rc = (RowMarkClause *) lfirst(l);
+
+ rc->rowmarkId = ++(root->glob->lastRowmarkId);
+ }
+
+ /*
* Expand any rangetable entries that are inheritance sets into "append
* relations". This can add entries to the rangetable, but they must be
* plain base relations not joins, so it's OK (and marginally more
@@ -1588,7 +1617,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
}
/*
- * Finally, if there is a LIMIT/OFFSET clause, add the LIMIT node.
+ * If there is a LIMIT/OFFSET clause, add the LIMIT node.
*/
if (parse->limitCount || parse->limitOffset)
{
@@ -1599,6 +1628,15 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
count_est);
}
+ /*
+ * Finally, if there is a FOR UPDATE/SHARE clause, add the LockRows node.
+ */
+ if (parse->rowMarks)
+ {
+ result_plan = (Plan *) make_lockrows(result_plan,
+ parse->rowMarks);
+ }
+
/* Compute result-relations list if needed */
if (parse->resultRelation)
root->resultRelations = list_make1_int(parse->resultRelation);