diff options
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 5 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 22 | ||||
-rw-r--r-- | src/backend/optimizer/plan/setrefs.c | 16 | ||||
-rw-r--r-- | src/backend/optimizer/plan/subselect.c | 11 |
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 || |