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.c91
1 files changed, 51 insertions, 40 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 64f77a5c71e..4b06c823b6c 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.257 2009/10/08 02:39:21 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.258 2009/10/10 01:43:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -217,6 +217,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
result = makeNode(PlannedStmt);
result->commandType = parse->commandType;
+ result->hasReturning = (parse->returningList != NIL);
result->canSetTag = parse->canSetTag;
result->transientPlan = glob->transientPlan;
result->planTree = top_plan;
@@ -226,7 +227,6 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
result->intoClause = parse->intoClause;
result->subplans = glob->subplans;
result->rewindPlanIDs = glob->rewindPlanIDs;
- result->returningLists = root->returningLists;
result->rowMarks = parse->rowMarks;
result->relationOids = glob->relationOids;
result->invalItems = glob->invalItems;
@@ -478,7 +478,39 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
rt_fetch(parse->resultRelation, parse->rtable)->inh)
plan = inheritance_planner(root);
else
+ {
plan = grouping_planner(root, tuple_fraction);
+ /* If it's not SELECT, we need a ModifyTable node */
+ if (parse->commandType != CMD_SELECT)
+ {
+ /*
+ * Deal with the RETURNING clause if any. It's convenient to pass
+ * the returningList through setrefs.c now rather than at top
+ * level (if we waited, handling inherited UPDATE/DELETE would be
+ * much harder).
+ */
+ List *returningLists;
+
+ if (parse->returningList)
+ {
+ List *rlist;
+
+ Assert(parse->resultRelation);
+ rlist = set_returning_clause_references(root->glob,
+ parse->returningList,
+ plan,
+ parse->resultRelation);
+ returningLists = list_make1(rlist);
+ }
+ else
+ returningLists = NIL;
+
+ plan = (Plan *) make_modifytable(parse->commandType,
+ copyObject(root->resultRelations),
+ list_make1(plan),
+ returningLists);
+ }
+ }
/*
* If any subplans were generated, or if we're inside a subplan, build
@@ -625,9 +657,7 @@ preprocess_qual_conditions(PlannerInfo *root, Node *jtnode)
* is an inheritance set. Source inheritance is expanded at the bottom of the
* plan tree (see allpaths.c), but target inheritance has to be expanded at
* the top. The reason is that for UPDATE, each target relation needs a
- * different targetlist matching its own column set. Also, for both UPDATE
- * and DELETE, the executor needs the Append plan node at the top, else it
- * can't keep track of which table is the current target table. Fortunately,
+ * different targetlist matching its own column set. Fortunately,
* the UPDATE/DELETE target can never be the nullable side of an outer join,
* so it's OK to generate the plan this way.
*
@@ -642,7 +672,7 @@ inheritance_planner(PlannerInfo *root)
List *resultRelations = NIL;
List *returningLists = NIL;
List *rtable = NIL;
- List *tlist = NIL;
+ List *tlist;
PlannerInfo subroot;
ListCell *l;
@@ -662,7 +692,6 @@ inheritance_planner(PlannerInfo *root)
subroot.parse = (Query *)
adjust_appendrel_attrs((Node *) parse,
appinfo);
- subroot.returningLists = NIL;
subroot.init_plans = NIL;
/* We needn't modify the child's append_rel_list */
/* There shouldn't be any OJ info to translate, as yet */
@@ -680,12 +709,9 @@ inheritance_planner(PlannerInfo *root)
if (is_dummy_plan(subplan))
continue;
- /* Save rtable and tlist from first rel for use below */
+ /* Save rtable from first rel for use below */
if (subplans == NIL)
- {
rtable = subroot.parse->rtable;
- tlist = subplan->targetlist;
- }
subplans = lappend(subplans, subplan);
@@ -698,20 +724,24 @@ inheritance_planner(PlannerInfo *root)
/* Build list of per-relation RETURNING targetlists */
if (parse->returningList)
{
- Assert(list_length(subroot.returningLists) == 1);
- returningLists = list_concat(returningLists,
- subroot.returningLists);
+ List *rlist;
+
+ rlist = set_returning_clause_references(root->glob,
+ subroot.parse->returningList,
+ subplan,
+ appinfo->child_relid);
+ returningLists = lappend(returningLists, rlist);
}
}
root->resultRelations = resultRelations;
- root->returningLists = returningLists;
/* Mark result as unordered (probably unnecessary) */
root->query_pathkeys = NIL;
/*
- * If we managed to exclude every child rel, return a dummy plan
+ * If we managed to exclude every child rel, return a dummy plan;
+ * it doesn't even need a ModifyTable node.
*/
if (subplans == NIL)
{
@@ -738,11 +768,11 @@ inheritance_planner(PlannerInfo *root)
*/
parse->rtable = rtable;
- /* Suppress Append if there's only one surviving child rel */
- if (list_length(subplans) == 1)
- return (Plan *) linitial(subplans);
-
- return (Plan *) make_append(subplans, true, tlist);
+ /* And last, tack on a ModifyTable node to do the UPDATE/DELETE work */
+ return (Plan *) make_modifytable(parse->commandType,
+ copyObject(root->resultRelations),
+ subplans,
+ returningLists);
}
/*--------------------
@@ -1569,25 +1599,6 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
count_est);
}
- /*
- * Deal with the RETURNING clause if any. It's convenient to pass the
- * returningList through setrefs.c now rather than at top level (if we
- * waited, handling inherited UPDATE/DELETE would be much harder).
- */
- if (parse->returningList)
- {
- List *rlist;
-
- Assert(parse->resultRelation);
- rlist = set_returning_clause_references(root->glob,
- parse->returningList,
- result_plan,
- parse->resultRelation);
- root->returningLists = list_make1(rlist);
- }
- else
- root->returningLists = NIL;
-
/* Compute result-relations list if needed */
if (parse->resultRelation)
root->resultRelations = list_make1_int(parse->resultRelation);