aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r--src/backend/optimizer/plan/createplan.c5
-rw-r--r--src/backend/optimizer/plan/planner.c22
-rw-r--r--src/backend/optimizer/plan/setrefs.c16
-rw-r--r--src/backend/optimizer/plan/subselect.c11
4 files changed, 34 insertions, 20 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 4895858df60..8a0135c9a74 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -4284,7 +4284,8 @@ make_result(PlannerInfo *root,
* to make it look better sometime.
*/
ModifyTable *
-make_modifytable(CmdType operation, List *resultRelations,
+make_modifytable(CmdType operation, bool canSetTag,
+ List *resultRelations,
List *subplans, List *returningLists,
List *rowMarks, int epqParam)
{
@@ -4334,7 +4335,9 @@ make_modifytable(CmdType operation, List *resultRelations,
node->plan.targetlist = NIL;
node->operation = operation;
+ node->canSetTag = canSetTag;
node->resultRelations = resultRelations;
+ node->resultRelIndex = -1; /* will be set correctly in setrefs.c */
node->plans = subplans;
node->returningLists = returningLists;
node->rowMarks = rowMarks;
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index ee09673051f..38112f1501b 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -163,6 +163,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
glob->rewindPlanIDs = NULL;
glob->finalrtable = NIL;
glob->finalrowmarks = NIL;
+ glob->resultRelations = NIL;
glob->relationOids = NIL;
glob->invalItems = NIL;
glob->lastPHId = 0;
@@ -214,6 +215,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
/* final cleanup of the plan */
Assert(glob->finalrtable == NIL);
Assert(glob->finalrowmarks == NIL);
+ Assert(glob->resultRelations == NIL);
top_plan = set_plan_references(glob, top_plan,
root->parse->rtable,
root->rowMarks);
@@ -239,11 +241,12 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
result->commandType = parse->commandType;
result->hasReturning = (parse->returningList != NIL);
+ result->hasModifyingCTE = parse->hasModifyingCTE;
result->canSetTag = parse->canSetTag;
result->transientPlan = glob->transientPlan;
result->planTree = top_plan;
result->rtable = glob->finalrtable;
- result->resultRelations = root->resultRelations;
+ result->resultRelations = glob->resultRelations;
result->utilityStmt = parse->utilityStmt;
result->intoClause = parse->intoClause;
result->subplans = glob->subplans;
@@ -571,7 +574,8 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
rowMarks = root->rowMarks;
plan = (Plan *) make_modifytable(parse->commandType,
- copyObject(root->resultRelations),
+ parse->canSetTag,
+ list_make1_int(parse->resultRelation),
list_make1(plan),
returningLists,
rowMarks,
@@ -787,7 +791,7 @@ inheritance_planner(PlannerInfo *root)
/* Make sure any initplans from this rel get into the outer list */
root->init_plans = list_concat(root->init_plans, subroot.init_plans);
- /* Build target-relations list for the executor */
+ /* Build list of target-relation RT indexes */
resultRelations = lappend_int(resultRelations, appinfo->child_relid);
/* Build list of per-relation RETURNING targetlists */
@@ -803,8 +807,6 @@ inheritance_planner(PlannerInfo *root)
}
}
- root->resultRelations = resultRelations;
-
/* Mark result as unordered (probably unnecessary) */
root->query_pathkeys = NIL;
@@ -814,7 +816,6 @@ inheritance_planner(PlannerInfo *root)
*/
if (subplans == NIL)
{
- root->resultRelations = list_make1_int(parentRTindex);
/* although dummy, it must have a valid tlist for executor */
tlist = preprocess_targetlist(root, parse->targetList);
return (Plan *) make_result(root,
@@ -849,7 +850,8 @@ inheritance_planner(PlannerInfo *root)
/* And last, tack on a ModifyTable node to do the UPDATE/DELETE work */
return (Plan *) make_modifytable(parse->commandType,
- copyObject(root->resultRelations),
+ parse->canSetTag,
+ resultRelations,
subplans,
returningLists,
rowMarks,
@@ -1725,12 +1727,6 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
count_est);
}
- /* Compute result-relations list if needed */
- if (parse->resultRelation)
- root->resultRelations = list_make1_int(parse->resultRelation);
- else
- root->resultRelations = NIL;
-
/*
* Return the actual output ordering in query_pathkeys for possible use by
* an outer query level.
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index b1c181a1cc5..432d6483be1 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -173,8 +173,9 @@ static bool extract_query_dependencies_walker(Node *node,
* The return value is normally the same Plan node passed in, but can be
* different when the passed-in Plan is a SubqueryScan we decide isn't needed.
*
- * The flattened rangetable entries are appended to glob->finalrtable,
- * and we also append rowmarks entries to glob->finalrowmarks.
+ * The flattened rangetable entries are appended to glob->finalrtable.
+ * Also, rowmarks entries are appended to glob->finalrowmarks, and the
+ * RT indexes of ModifyTable result relations to glob->resultRelations.
* Plan dependencies are appended to glob->relationOids (for relations)
* and glob->invalItems (for everything else).
*
@@ -552,6 +553,17 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
(Plan *) lfirst(l),
rtoffset);
}
+
+ /*
+ * Append this ModifyTable node's final result relation RT
+ * index(es) to the global list for the plan, and set its
+ * resultRelIndex to reflect their starting position in the
+ * global list.
+ */
+ splan->resultRelIndex = list_length(glob->resultRelations);
+ glob->resultRelations =
+ list_concat(glob->resultRelations,
+ list_copy(splan->resultRelations));
}
break;
case T_Append:
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 96a257f6afa..a9649212f20 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -930,6 +930,7 @@ SS_process_ctes(PlannerInfo *root)
foreach(lc, root->parse->cteList)
{
CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
+ CmdType cmdType = ((Query *) cte->ctequery)->commandType;
Query *subquery;
Plan *plan;
PlannerInfo *subroot;
@@ -939,9 +940,9 @@ SS_process_ctes(PlannerInfo *root)
Param *prm;
/*
- * Ignore CTEs that are not actually referenced anywhere.
+ * Ignore SELECT CTEs that are not actually referenced anywhere.
*/
- if (cte->cterefcount == 0)
+ if (cte->cterefcount == 0 && cmdType == CMD_SELECT)
{
/* Make a dummy entry in cte_plan_ids */
root->cte_plan_ids = lappend_int(root->cte_plan_ids, -1);
@@ -1332,14 +1333,16 @@ simplify_EXISTS_query(Query *query)
{
/*
* We don't try to simplify at all if the query uses set operations,
- * aggregates, HAVING, LIMIT/OFFSET, or FOR UPDATE/SHARE; none of these
- * seem likely in normal usage and their possible effects are complex.
+ * aggregates, modifying CTEs, HAVING, LIMIT/OFFSET, or FOR UPDATE/SHARE;
+ * none of these seem likely in normal usage and their possible effects
+ * are complex.
*/
if (query->commandType != CMD_SELECT ||
query->intoClause ||
query->setOperations ||
query->hasAggs ||
query->hasWindowFuncs ||
+ query->hasModifyingCTE ||
query->havingQual ||
query->limitOffset ||
query->limitCount ||