From 5fef352b9ce73c9ffbfa4b49e5c7e425c2e4da75 Mon Sep 17 00:00:00 2001 From: amit Date: Mon, 13 Aug 2018 16:10:19 +0900 Subject: [PATCH v4 2/4] Remove useless fields from planner nodes They were added so that executor could identify range table entries entries to lock them or to impose order on locking during executor initialization, but turns out that executor doesn't take any locks of its own on the relations, so these fields are redundant. Following fields are removed: * 'partitioned_rels' from Append, MergeAppend, and ModifyTable. Actually, in ModifyTable, it is replaced by a bool field called 'partitionedTarget', which is set if the target is a partitioned table. The table itself is identified by nominalRelation. * 'nonleafResultRelations' from PlannedStmt and PlannerGlobal. * 'rowMarks' from PlannedStmt and 'finalrowmarks' from PlannerGlobal. In PlannedStmt, it is replaced by a bool hasRowMarks that stores if query->rowMarks != NIL. --- src/backend/commands/portalcmds.c | 2 +- src/backend/executor/execMain.c | 2 +- src/backend/executor/execParallel.c | 3 +- src/backend/executor/execUtils.c | 55 --------------------------------- src/backend/executor/nodeAppend.c | 6 ---- src/backend/executor/nodeMergeAppend.c | 6 ---- src/backend/executor/nodeModifyTable.c | 10 +++--- src/backend/executor/spi.c | 4 +-- src/backend/nodes/copyfuncs.c | 7 ++--- src/backend/nodes/outfuncs.c | 11 ++----- src/backend/nodes/readfuncs.c | 7 ++--- src/backend/optimizer/plan/createplan.c | 42 +++++-------------------- src/backend/optimizer/plan/planner.c | 51 ++++++------------------------ src/backend/optimizer/plan/setrefs.c | 47 +++------------------------- src/backend/optimizer/util/pathnode.c | 8 ++--- src/backend/tcop/utility.c | 15 +++++++-- src/include/executor/executor.h | 2 -- src/include/nodes/plannodes.h | 29 +++++------------ src/include/nodes/relation.h | 9 ++---- src/include/optimizer/pathnode.h | 2 +- 20 files changed, 64 insertions(+), 254 deletions(-) diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c index 568499761f..4b213a8db7 100644 --- a/src/backend/commands/portalcmds.c +++ b/src/backend/commands/portalcmds.c @@ -133,7 +133,7 @@ PerformCursorOpen(DeclareCursorStmt *cstmt, ParamListInfo params, portal->cursorOptions = cstmt->options; if (!(portal->cursorOptions & (CURSOR_OPT_SCROLL | CURSOR_OPT_NO_SCROLL))) { - if (plan->rowMarks == NIL && + if (!plan->hasRowMarks && ExecSupportsBackwardScan(plan->planTree)) portal->cursorOptions |= CURSOR_OPT_SCROLL; else diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index f797cdfe7c..e84ebe0c87 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -217,7 +217,7 @@ standard_ExecutorStart(QueryDesc *queryDesc, int eflags) * SELECT FOR [KEY] UPDATE/SHARE and modifying CTEs need to mark * tuples */ - if (queryDesc->plannedstmt->rowMarks != NIL || + if (queryDesc->plannedstmt->hasRowMarks || queryDesc->plannedstmt->hasModifyingCTE) estate->es_output_cid = GetCurrentCommandId(true); diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c index ee0f07a81e..7afcd5b6c0 100644 --- a/src/backend/executor/execParallel.c +++ b/src/backend/executor/execParallel.c @@ -174,6 +174,7 @@ ExecSerializePlan(Plan *plan, EState *estate) pstmt->queryId = UINT64CONST(0); pstmt->hasReturning = false; pstmt->hasModifyingCTE = false; + pstmt->hasRowMarks = false; pstmt->canSetTag = true; pstmt->transientPlan = false; pstmt->dependsOnRole = false; @@ -181,7 +182,6 @@ ExecSerializePlan(Plan *plan, EState *estate) pstmt->planTree = plan; pstmt->rtable = estate->es_range_table; pstmt->resultRelations = NIL; - pstmt->nonleafResultRelations = NIL; /* * Transfer only parallel-safe subplans, leaving a NULL "hole" in the list @@ -201,7 +201,6 @@ ExecSerializePlan(Plan *plan, EState *estate) } pstmt->rewindPlanIDs = NULL; - pstmt->rowMarks = NIL; pstmt->relationOids = NIL; pstmt->invalItems = NIL; /* workers can't replan anyway... */ pstmt->paramExecTypes = estate->es_plannedstmt->paramExecTypes; diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index 09942b34fb..d32796aac3 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -848,61 +848,6 @@ ShutdownExprContext(ExprContext *econtext, bool isCommit) } /* - * ExecLockNonLeafAppendTables - * - * Locks, if necessary, the tables indicated by the RT indexes contained in - * the partitioned_rels list. These are the non-leaf tables in the partition - * tree controlled by a given Append or MergeAppend node. - */ -void -ExecLockNonLeafAppendTables(List *partitioned_rels, EState *estate) -{ - PlannedStmt *stmt = estate->es_plannedstmt; - ListCell *lc; - - foreach(lc, partitioned_rels) - { - ListCell *l; - Index rti = lfirst_int(lc); - bool is_result_rel = false; - Oid relid = getrelid(rti, estate->es_range_table); - - /* If this is a result relation, already locked in InitPlan */ - foreach(l, stmt->nonleafResultRelations) - { - if (rti == lfirst_int(l)) - { - is_result_rel = true; - break; - } - } - - /* - * Not a result relation; check if there is a RowMark that requires - * taking a RowShareLock on this rel. - */ - if (!is_result_rel) - { - PlanRowMark *rc = NULL; - - foreach(l, stmt->rowMarks) - { - if (((PlanRowMark *) lfirst(l))->rti == rti) - { - rc = lfirst(l); - break; - } - } - - if (rc && RowMarkRequiresRowShareLock(rc->markType)) - LockRelationOid(relid, RowShareLock); - else - LockRelationOid(relid, AccessShareLock); - } - } -} - -/* * GetAttributeByName * GetAttributeByNum * diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index f08dfcbcf0..eb587be221 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -113,12 +113,6 @@ ExecInitAppend(Append *node, EState *estate, int eflags) Assert(!(eflags & EXEC_FLAG_MARK)); /* - * Lock the non-leaf tables in the partition tree controlled by this node. - * It's a no-op for non-partitioned parent tables. - */ - ExecLockNonLeafAppendTables(node->partitioned_rels, estate); - - /* * create new AppendState for our append node */ appendstate->ps.plan = (Plan *) node; diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c index 9a72d3a0ac..d8e0978966 100644 --- a/src/backend/executor/nodeMergeAppend.c +++ b/src/backend/executor/nodeMergeAppend.c @@ -76,12 +76,6 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags) Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); /* - * Lock the non-leaf tables in the partition tree controlled by this node. - * It's a no-op for non-partitioned parent tables. - */ - ExecLockNonLeafAppendTables(node->partitioned_rels, estate); - - /* * create new MergeAppendState for our node */ mergestate->ps.plan = (Plan *) node; diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 93e5bf7af6..ab4ec575fc 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -2255,18 +2255,18 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) /* If modifying a partitioned table, initialize the root table info */ if (node->rootResultRelIndex >= 0) { - Index root_rt_index = linitial_int(node->partitioned_rels); RangeTblEntry *rte; Relation rel; mtstate->rootResultRelInfo = estate->es_root_result_relations + node->rootResultRelIndex; - Assert(root_rt_index > 0); - rte = rt_fetch(root_rt_index, estate->es_range_table); + Assert(node->partitionedTarget); + /* nominalRelation is the index of the target partitioned table. */ + rte = rt_fetch(node->nominalRelation, estate->es_range_table); rel = heap_open(rte->relid, NoLock); - InitResultRelInfo(mtstate->rootResultRelInfo, rel, root_rt_index, - NULL, estate->es_instrument); + InitResultRelInfo(mtstate->rootResultRelInfo, rel, + node->nominalRelation, NULL, estate->es_instrument); } mtstate->mt_arowmarks = (List **) palloc0(sizeof(List *) * nplans); diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index 11ca800e4c..1bee240e72 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -1358,7 +1358,7 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, { if (list_length(stmt_list) == 1 && linitial_node(PlannedStmt, stmt_list)->commandType != CMD_UTILITY && - linitial_node(PlannedStmt, stmt_list)->rowMarks == NIL && + !linitial_node(PlannedStmt, stmt_list)->hasRowMarks && ExecSupportsBackwardScan(linitial_node(PlannedStmt, stmt_list)->planTree)) portal->cursorOptions |= CURSOR_OPT_SCROLL; else @@ -1374,7 +1374,7 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, { if (list_length(stmt_list) == 1 && linitial_node(PlannedStmt, stmt_list)->commandType != CMD_UTILITY && - linitial_node(PlannedStmt, stmt_list)->rowMarks != NIL) + linitial_node(PlannedStmt, stmt_list)->hasRowMarks) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported"), diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 6d685db0ea..b0193a94a9 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -83,6 +83,7 @@ _copyPlannedStmt(const PlannedStmt *from) COPY_SCALAR_FIELD(queryId); COPY_SCALAR_FIELD(hasReturning); COPY_SCALAR_FIELD(hasModifyingCTE); + COPY_SCALAR_FIELD(hasRowMarks); COPY_SCALAR_FIELD(canSetTag); COPY_SCALAR_FIELD(transientPlan); COPY_SCALAR_FIELD(dependsOnRole); @@ -91,11 +92,9 @@ _copyPlannedStmt(const PlannedStmt *from) COPY_NODE_FIELD(planTree); COPY_NODE_FIELD(rtable); COPY_NODE_FIELD(resultRelations); - COPY_NODE_FIELD(nonleafResultRelations); COPY_NODE_FIELD(rootResultRelations); COPY_NODE_FIELD(subplans); COPY_BITMAPSET_FIELD(rewindPlanIDs); - COPY_NODE_FIELD(rowMarks); COPY_NODE_FIELD(relationOids); COPY_NODE_FIELD(invalItems); COPY_NODE_FIELD(paramExecTypes); @@ -204,7 +203,7 @@ _copyModifyTable(const ModifyTable *from) COPY_SCALAR_FIELD(operation); COPY_SCALAR_FIELD(canSetTag); COPY_SCALAR_FIELD(nominalRelation); - COPY_NODE_FIELD(partitioned_rels); + COPY_SCALAR_FIELD(partitionedTarget); COPY_SCALAR_FIELD(partColsUpdated); COPY_NODE_FIELD(resultRelations); COPY_SCALAR_FIELD(resultRelIndex); @@ -244,7 +243,6 @@ _copyAppend(const Append *from) */ COPY_NODE_FIELD(appendplans); COPY_SCALAR_FIELD(first_partial_plan); - COPY_NODE_FIELD(partitioned_rels); COPY_NODE_FIELD(part_prune_info); return newnode; @@ -266,7 +264,6 @@ _copyMergeAppend(const MergeAppend *from) /* * copy remainder of node */ - COPY_NODE_FIELD(partitioned_rels); COPY_NODE_FIELD(mergeplans); COPY_SCALAR_FIELD(numCols); COPY_POINTER_FIELD(sortColIdx, from->numCols * sizeof(AttrNumber)); diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 53f209e170..36d46f5d8f 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -268,6 +268,7 @@ _outPlannedStmt(StringInfo str, const PlannedStmt *node) WRITE_UINT64_FIELD(queryId); WRITE_BOOL_FIELD(hasReturning); WRITE_BOOL_FIELD(hasModifyingCTE); + WRITE_BOOL_FIELD(hasRowMarks); WRITE_BOOL_FIELD(canSetTag); WRITE_BOOL_FIELD(transientPlan); WRITE_BOOL_FIELD(dependsOnRole); @@ -276,11 +277,9 @@ _outPlannedStmt(StringInfo str, const PlannedStmt *node) WRITE_NODE_FIELD(planTree); WRITE_NODE_FIELD(rtable); WRITE_NODE_FIELD(resultRelations); - WRITE_NODE_FIELD(nonleafResultRelations); WRITE_NODE_FIELD(rootResultRelations); WRITE_NODE_FIELD(subplans); WRITE_BITMAPSET_FIELD(rewindPlanIDs); - WRITE_NODE_FIELD(rowMarks); WRITE_NODE_FIELD(relationOids); WRITE_NODE_FIELD(invalItems); WRITE_NODE_FIELD(paramExecTypes); @@ -372,7 +371,7 @@ _outModifyTable(StringInfo str, const ModifyTable *node) WRITE_ENUM_FIELD(operation, CmdType); WRITE_BOOL_FIELD(canSetTag); WRITE_UINT_FIELD(nominalRelation); - WRITE_NODE_FIELD(partitioned_rels); + WRITE_BOOL_FIELD(partitionedTarget); WRITE_BOOL_FIELD(partColsUpdated); WRITE_NODE_FIELD(resultRelations); WRITE_INT_FIELD(resultRelIndex); @@ -401,7 +400,6 @@ _outAppend(StringInfo str, const Append *node) WRITE_NODE_FIELD(appendplans); WRITE_INT_FIELD(first_partial_plan); - WRITE_NODE_FIELD(partitioned_rels); WRITE_NODE_FIELD(part_prune_info); } @@ -414,7 +412,6 @@ _outMergeAppend(StringInfo str, const MergeAppend *node) _outPlanInfo(str, (const Plan *) node); - WRITE_NODE_FIELD(partitioned_rels); WRITE_NODE_FIELD(mergeplans); WRITE_INT_FIELD(numCols); @@ -2175,7 +2172,7 @@ _outModifyTablePath(StringInfo str, const ModifyTablePath *node) WRITE_ENUM_FIELD(operation, CmdType); WRITE_BOOL_FIELD(canSetTag); WRITE_UINT_FIELD(nominalRelation); - WRITE_NODE_FIELD(partitioned_rels); + WRITE_BOOL_FIELD(partitionedTarget); WRITE_BOOL_FIELD(partColsUpdated); WRITE_NODE_FIELD(resultRelations); WRITE_NODE_FIELD(subpaths); @@ -2253,9 +2250,7 @@ _outPlannerGlobal(StringInfo str, const PlannerGlobal *node) WRITE_NODE_FIELD(subplans); WRITE_BITMAPSET_FIELD(rewindPlanIDs); WRITE_NODE_FIELD(finalrtable); - WRITE_NODE_FIELD(finalrowmarks); WRITE_NODE_FIELD(resultRelations); - WRITE_NODE_FIELD(nonleafResultRelations); WRITE_NODE_FIELD(rootResultRelations); WRITE_NODE_FIELD(relationOids); WRITE_NODE_FIELD(invalItems); diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 7a1e839ef4..4d1317e339 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -1476,6 +1476,7 @@ _readPlannedStmt(void) READ_UINT64_FIELD(queryId); READ_BOOL_FIELD(hasReturning); READ_BOOL_FIELD(hasModifyingCTE); + READ_BOOL_FIELD(hasRowMarks); READ_BOOL_FIELD(canSetTag); READ_BOOL_FIELD(transientPlan); READ_BOOL_FIELD(dependsOnRole); @@ -1484,11 +1485,9 @@ _readPlannedStmt(void) READ_NODE_FIELD(planTree); READ_NODE_FIELD(rtable); READ_NODE_FIELD(resultRelations); - READ_NODE_FIELD(nonleafResultRelations); READ_NODE_FIELD(rootResultRelations); READ_NODE_FIELD(subplans); READ_BITMAPSET_FIELD(rewindPlanIDs); - READ_NODE_FIELD(rowMarks); READ_NODE_FIELD(relationOids); READ_NODE_FIELD(invalItems); READ_NODE_FIELD(paramExecTypes); @@ -1578,7 +1577,7 @@ _readModifyTable(void) READ_ENUM_FIELD(operation, CmdType); READ_BOOL_FIELD(canSetTag); READ_UINT_FIELD(nominalRelation); - READ_NODE_FIELD(partitioned_rels); + READ_BOOL_FIELD(partitionedTarget); READ_BOOL_FIELD(partColsUpdated); READ_NODE_FIELD(resultRelations); READ_INT_FIELD(resultRelIndex); @@ -1612,7 +1611,6 @@ _readAppend(void) READ_NODE_FIELD(appendplans); READ_INT_FIELD(first_partial_plan); - READ_NODE_FIELD(partitioned_rels); READ_NODE_FIELD(part_prune_info); READ_DONE(); @@ -1628,7 +1626,6 @@ _readMergeAppend(void) ReadCommonPlan(&local_node->plan); - READ_NODE_FIELD(partitioned_rels); READ_NODE_FIELD(mergeplans); READ_INT_FIELD(numCols); READ_ATTRNUMBER_ARRAY(sortColIdx, local_node->numCols); diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index ae41c9efa0..becc5ef75d 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -124,7 +124,6 @@ static BitmapHeapScan *create_bitmap_scan_plan(PlannerInfo *root, static Plan *create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual, List **qual, List **indexqual, List **indexECs); static void bitmap_subplan_mark_shared(Plan *plan); -static List *flatten_partitioned_rels(List *partitioned_rels); static TidScan *create_tidscan_plan(PlannerInfo *root, TidPath *best_path, List *tlist, List *scan_clauses); static SubqueryScan *create_subqueryscan_plan(PlannerInfo *root, @@ -203,8 +202,7 @@ static NamedTuplestoreScan *make_namedtuplestorescan(List *qptlist, List *qpqual static WorkTableScan *make_worktablescan(List *qptlist, List *qpqual, Index scanrelid, int wtParam); static Append *make_append(List *appendplans, int first_partial_plan, - List *tlist, List *partitioned_rels, - PartitionPruneInfo *partpruneinfo); + List *tlist, PartitionPruneInfo *partpruneinfo); static RecursiveUnion *make_recursive_union(List *tlist, Plan *lefttree, Plan *righttree, @@ -280,7 +278,7 @@ static Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan); static ProjectSet *make_project_set(List *tlist, Plan *subplan); static ModifyTable *make_modifytable(PlannerInfo *root, CmdType operation, bool canSetTag, - Index nominalRelation, List *partitioned_rels, + Index nominalRelation, bool partitionedTarget, bool partColsUpdated, List *resultRelations, List *subplans, List *subroots, List *withCheckOptionLists, List *returningLists, @@ -1110,8 +1108,7 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path) */ plan = make_append(subplans, best_path->first_partial_path, - tlist, best_path->partitioned_rels, - partpruneinfo); + tlist, partpruneinfo); copy_generic_path_info(&plan->plan, (Path *) best_path); @@ -1253,8 +1250,6 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path) prunequal); } - node->partitioned_rels = - flatten_partitioned_rels(best_path->partitioned_rels); node->mergeplans = subplans; node->part_prune_info = partpruneinfo; @@ -2411,7 +2406,7 @@ create_modifytable_plan(PlannerInfo *root, ModifyTablePath *best_path) best_path->operation, best_path->canSetTag, best_path->nominalRelation, - best_path->partitioned_rels, + best_path->partitionedTarget, best_path->partColsUpdated, best_path->resultRelations, subplans, @@ -5005,27 +5000,6 @@ bitmap_subplan_mark_shared(Plan *plan) elog(ERROR, "unrecognized node type: %d", nodeTag(plan)); } -/* - * flatten_partitioned_rels - * Convert List of Lists into a single List with all elements from the - * sub-lists. - */ -static List * -flatten_partitioned_rels(List *partitioned_rels) -{ - List *newlist = NIL; - ListCell *lc; - - foreach(lc, partitioned_rels) - { - List *sublist = lfirst(lc); - - newlist = list_concat(newlist, list_copy(sublist)); - } - - return newlist; -} - /***************************************************************************** * * PLAN NODE BUILDING ROUTINES @@ -5368,8 +5342,7 @@ make_foreignscan(List *qptlist, static Append * make_append(List *appendplans, int first_partial_plan, - List *tlist, List *partitioned_rels, - PartitionPruneInfo *partpruneinfo) + List *tlist, PartitionPruneInfo *partpruneinfo) { Append *node = makeNode(Append); Plan *plan = &node->plan; @@ -5380,7 +5353,6 @@ make_append(List *appendplans, int first_partial_plan, plan->righttree = NULL; node->appendplans = appendplans; node->first_partial_plan = first_partial_plan; - node->partitioned_rels = flatten_partitioned_rels(partitioned_rels); node->part_prune_info = partpruneinfo; return node; } @@ -6509,7 +6481,7 @@ make_project_set(List *tlist, static ModifyTable * make_modifytable(PlannerInfo *root, CmdType operation, bool canSetTag, - Index nominalRelation, List *partitioned_rels, + Index nominalRelation, bool partitionedTarget, bool partColsUpdated, List *resultRelations, List *subplans, List *subroots, List *withCheckOptionLists, List *returningLists, @@ -6538,7 +6510,7 @@ make_modifytable(PlannerInfo *root, node->operation = operation; node->canSetTag = canSetTag; node->nominalRelation = nominalRelation; - node->partitioned_rels = flatten_partitioned_rels(partitioned_rels); + node->partitionedTarget = partitionedTarget; node->partColsUpdated = partColsUpdated; node->resultRelations = resultRelations; node->resultRelIndex = -1; /* will be set correctly in setrefs.c */ diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 96bf0601a8..44884c29c6 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -276,6 +276,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) Plan *top_plan; ListCell *lp, *lr; + bool hasRowMarks = (parse->rowMarks != NIL); /* * Set up global state for this planner invocation. This data is needed @@ -290,9 +291,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) glob->subroots = NIL; glob->rewindPlanIDs = NULL; glob->finalrtable = NIL; - glob->finalrowmarks = NIL; glob->resultRelations = NIL; - glob->nonleafResultRelations = NIL; glob->rootResultRelations = NIL; glob->relationOids = NIL; glob->invalItems = NIL; @@ -490,9 +489,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); - Assert(glob->nonleafResultRelations == NIL); Assert(glob->rootResultRelations == NIL); top_plan = set_plan_references(root, top_plan); /* ... and the subplans (both regular subplans and initplans) */ @@ -503,6 +500,8 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) PlannerInfo *subroot = lfirst_node(PlannerInfo, lr); lfirst(lp) = set_plan_references(subroot, subplan); + if (subroot->rowMarks != NIL) + hasRowMarks = true; } /* build the PlannedStmt result */ @@ -512,6 +511,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) result->queryId = parse->queryId; result->hasReturning = (parse->returningList != NIL); result->hasModifyingCTE = parse->hasModifyingCTE; + result->hasRowMarks = hasRowMarks; result->canSetTag = parse->canSetTag; result->transientPlan = glob->transientPlan; result->dependsOnRole = glob->dependsOnRole; @@ -519,11 +519,9 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) result->planTree = top_plan; result->rtable = glob->finalrtable; result->resultRelations = glob->resultRelations; - result->nonleafResultRelations = glob->nonleafResultRelations; result->rootResultRelations = glob->rootResultRelations; result->subplans = glob->subplans; result->rewindPlanIDs = glob->rewindPlanIDs; - result->rowMarks = glob->finalrowmarks; result->relationOids = glob->relationOids; result->invalItems = glob->invalItems; result->paramExecTypes = glob->paramExecTypes; @@ -1173,8 +1171,7 @@ inheritance_planner(PlannerInfo *root) ListCell *lc; Index rti; RangeTblEntry *parent_rte; - Relids partitioned_relids = NULL; - List *partitioned_rels = NIL; + bool partitionedTarget = false; PlannerInfo *parent_root; Query *parent_parse; Bitmapset *parent_relids = bms_make_singleton(top_parentRTindex); @@ -1250,12 +1247,7 @@ inheritance_planner(PlannerInfo *root) if (parent_rte->relkind == RELKIND_PARTITIONED_TABLE) { nominalRelation = top_parentRTindex; - - /* - * Root parent's RT index is always present in the partitioned_rels of - * the ModifyTable node, if one is needed at all. - */ - partitioned_relids = bms_make_singleton(top_parentRTindex); + partitionedTarget = true; } /* @@ -1327,7 +1319,7 @@ inheritance_planner(PlannerInfo *root) * inheritance parent. */ subroot->inhTargetKind = - partitioned_relids ? INHKIND_PARTITIONED : INHKIND_INHERITED; + partitionedTarget ? INHKIND_PARTITIONED : INHKIND_INHERITED; /* * If this child is further partitioned, remember it as a parent. @@ -1498,15 +1490,6 @@ inheritance_planner(PlannerInfo *root) continue; /* - * Add the current parent's RT index to the partitioned_relids set if - * we're creating the ModifyTable path for a partitioned root table. - * (We only care about parents of non-excluded children.) - */ - if (partitioned_relids) - partitioned_relids = bms_add_member(partitioned_relids, - appinfo->parent_relid); - - /* * If this is the first non-excluded child, its post-planning rtable * becomes the initial contents of final_rtable; otherwise, append * just its modified subquery RTEs to final_rtable. @@ -1609,29 +1592,13 @@ inheritance_planner(PlannerInfo *root) else rowMarks = root->rowMarks; - if (partitioned_relids) - { - int i; - - i = -1; - while ((i = bms_next_member(partitioned_relids, i)) >= 0) - partitioned_rels = lappend_int(partitioned_rels, i); - - /* - * If we're going to create ModifyTable at all, the list should - * contain at least one member, that is, the root parent's index. - */ - Assert(list_length(partitioned_rels) >= 1); - partitioned_rels = list_make1(partitioned_rels); - } - /* Create Path representing a ModifyTable to do the UPDATE/DELETE work */ add_path(final_rel, (Path *) create_modifytable_path(root, final_rel, parse->commandType, parse->canSetTag, nominalRelation, - partitioned_rels, + partitionedTarget, root->partColsUpdated, resultRelations, subpaths, @@ -2208,7 +2175,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update, parse->commandType, parse->canSetTag, parse->resultRelation, - NIL, + 0, false, list_make1_int(parse->resultRelation), list_make1(path), diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index f66f39d8c6..a8ec0be83a 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -211,7 +211,6 @@ set_plan_references(PlannerInfo *root, Plan *plan) { PlannerGlobal *glob = root->glob; int rtoffset = list_length(glob->finalrtable); - ListCell *lc; /* * Add all the query's RTEs to the flattened rangetable. The live ones @@ -220,25 +219,6 @@ set_plan_references(PlannerInfo *root, Plan *plan) */ add_rtes_to_flat_rtable(root, false); - /* - * Adjust RT indexes of PlanRowMarks and add to final rowmarks list - */ - foreach(lc, root->rowMarks) - { - PlanRowMark *rc = lfirst_node(PlanRowMark, lc); - PlanRowMark *newrc; - - /* flat copy is enough since all fields are scalars */ - newrc = (PlanRowMark *) palloc(sizeof(PlanRowMark)); - memcpy(newrc, rc, sizeof(PlanRowMark)); - - /* adjust indexes ... but *not* the rowmarkId */ - newrc->rti += rtoffset; - newrc->prti += rtoffset; - - glob->finalrowmarks = lappend(glob->finalrowmarks, newrc); - } - /* Now fix the Plan tree */ return set_plan_refs(root, plan, rtoffset); } @@ -850,10 +830,6 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset) splan->nominalRelation += rtoffset; splan->exclRelRTI += rtoffset; - foreach(l, splan->partitioned_rels) - { - lfirst_int(l) += rtoffset; - } foreach(l, splan->resultRelations) { lfirst_int(l) += rtoffset; @@ -884,24 +860,17 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset) list_copy(splan->resultRelations)); /* - * If the main target relation is a partitioned table, the - * following list contains the RT indexes of partitioned child - * relations including the root, which are not included in the - * above list. We also keep RT indexes of the roots - * separately to be identified as such during the executor - * initialization. + * If the main target relation is a partitioned table, remember + * the root table's RT index. */ - if (splan->partitioned_rels != NIL) + if (splan->partitionedTarget) { - root->glob->nonleafResultRelations = - list_concat(root->glob->nonleafResultRelations, - list_copy(splan->partitioned_rels)); /* Remember where this root will be in the global list. */ splan->rootResultRelIndex = list_length(root->glob->rootResultRelations); root->glob->rootResultRelations = lappend_int(root->glob->rootResultRelations, - linitial_int(splan->partitioned_rels)); + splan->nominalRelation); } } break; @@ -915,10 +884,6 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset) */ set_dummy_tlist_references(plan, rtoffset); Assert(splan->plan.qual == NIL); - foreach(l, splan->partitioned_rels) - { - lfirst_int(l) += rtoffset; - } foreach(l, splan->appendplans) { lfirst(l) = set_plan_refs(root, @@ -937,10 +902,6 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset) */ set_dummy_tlist_references(plan, rtoffset); Assert(splan->plan.qual == NIL); - foreach(l, splan->partitioned_rels) - { - lfirst_int(l) += rtoffset; - } foreach(l, splan->mergeplans) { lfirst(l) = set_plan_refs(root, diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index c5aaaf5c22..28f90a2a04 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -3292,9 +3292,7 @@ create_lockrows_path(PlannerInfo *root, RelOptInfo *rel, * 'operation' is the operation type * 'canSetTag' is true if we set the command tag/es_processed * 'nominalRelation' is the parent RT index for use of EXPLAIN - * 'partitioned_rels' is an integer list of RT indexes of non-leaf tables in - * the partition tree, if this is an UPDATE/DELETE to a partitioned table. - * Otherwise NIL. + * 'rootRelation' is the RT index of the root partitioned table * 'partColsUpdated' is true if any partitioning columns are being updated, * either from the target relation or a descendent partitioned table. * 'resultRelations' is an integer list of actual RT indexes of target rel(s) @@ -3309,7 +3307,7 @@ create_lockrows_path(PlannerInfo *root, RelOptInfo *rel, ModifyTablePath * create_modifytable_path(PlannerInfo *root, RelOptInfo *rel, CmdType operation, bool canSetTag, - Index nominalRelation, List *partitioned_rels, + Index nominalRelation, bool partitionedTarget, bool partColsUpdated, List *resultRelations, List *subpaths, List *subroots, @@ -3377,7 +3375,7 @@ create_modifytable_path(PlannerInfo *root, RelOptInfo *rel, pathnode->operation = operation; pathnode->canSetTag = canSetTag; pathnode->nominalRelation = nominalRelation; - pathnode->partitioned_rels = list_copy(partitioned_rels); + pathnode->partitionedTarget = partitionedTarget; pathnode->partColsUpdated = partColsUpdated; pathnode->resultRelations = resultRelations; pathnode->subpaths = subpaths; diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index b5804f64ad..d0427c64ba 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -103,7 +103,7 @@ CommandIsReadOnly(PlannedStmt *pstmt) switch (pstmt->commandType) { case CMD_SELECT: - if (pstmt->rowMarks != NIL) + if (pstmt->hasRowMarks) return false; /* SELECT FOR [KEY] UPDATE/SHARE */ else if (pstmt->hasModifyingCTE) return false; /* data-modifying CTE */ @@ -2809,10 +2809,19 @@ CreateCommandTag(Node *parsetree) * will be useful for complaints about read-only * statements */ - if (stmt->rowMarks != NIL) + if (stmt->hasRowMarks) { + List *rowMarks; + + /* Top-level Plan must be LockRows or ModifyTable */ + Assert(IsA(stmt->planTree, LockRows) || + IsA(stmt->planTree, ModifyTable)); + if (IsA(stmt->planTree, LockRows)) + rowMarks = ((LockRows *) stmt->planTree)->rowMarks; + else + rowMarks = ((ModifyTable *) stmt->planTree)->rowMarks; /* not 100% but probably close enough */ - switch (((PlanRowMark *) linitial(stmt->rowMarks))->strength) + switch (((PlanRowMark *) linitial(rowMarks))->strength) { case LCS_FORKEYSHARE: tag = "SELECT FOR KEY SHARE"; diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 4425b978f9..1d2b48fe09 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -524,8 +524,6 @@ extern void UnregisterExprContextCallback(ExprContext *econtext, ExprContextCallbackFunction function, Datum arg); -extern void ExecLockNonLeafAppendTables(List *partitioned_rels, EState *estate); - extern Datum GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull); extern Datum GetAttributeByNum(HeapTupleHeader tuple, AttrNumber attrno, diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 7c2abbd03a..ceec266a21 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -51,6 +51,8 @@ typedef struct PlannedStmt bool hasModifyingCTE; /* has insert|update|delete in WITH? */ + bool hasRowMarks; /* has FOR UPDATE/SHARE? */ + bool canSetTag; /* do I set the command result tag? */ bool transientPlan; /* redo plan when TransactionXmin changes? */ @@ -69,15 +71,8 @@ typedef struct PlannedStmt List *resultRelations; /* integer list of RT indexes, or NIL */ /* - * rtable indexes of non-leaf target relations for UPDATE/DELETE on all - * the partitioned tables mentioned in the query. - */ - List *nonleafResultRelations; - - /* - * rtable indexes of root target relations for UPDATE/DELETE; this list - * maintains a subset of the RT indexes in nonleafResultRelations, - * indicating the roots of the respective partition hierarchies. + * rtable indexes of root partitioned tables that are UPDATE/DELETE + * targets */ List *rootResultRelations; @@ -86,8 +81,6 @@ typedef struct PlannedStmt Bitmapset *rewindPlanIDs; /* indices of subplans that require REWIND */ - List *rowMarks; /* a list of PlanRowMark's */ - List *relationOids; /* OIDs of relations the plan depends on */ List *invalItems; /* other dependencies, as PlanInvalItems */ @@ -219,9 +212,9 @@ typedef struct ModifyTable Plan plan; CmdType operation; /* INSERT, UPDATE, or DELETE */ bool canSetTag; /* do we set the command tag/es_processed? */ - Index nominalRelation; /* Parent RT index for use of EXPLAIN */ - /* RT indexes of non-leaf tables in a partition tree */ - List *partitioned_rels; + Index nominalRelation; /* RT index of the target table specified + * in the command */ + bool partitionedTarget; /* is the target table partitioned? */ bool partColsUpdated; /* some part key in hierarchy updated */ List *resultRelations; /* integer list of RT indexes */ int resultRelIndex; /* index of first resultRel in plan's list */ @@ -259,9 +252,6 @@ typedef struct Append */ int first_partial_plan; - /* RT indexes of non-leaf tables in a partition tree */ - List *partitioned_rels; - /* Info for run-time subplan pruning; NULL if we're not doing that */ struct PartitionPruneInfo *part_prune_info; } Append; @@ -274,8 +264,6 @@ typedef struct Append typedef struct MergeAppend { Plan plan; - /* RT indexes of non-leaf tables in a partition tree */ - List *partitioned_rels; List *mergeplans; /* remaining fields are just like the sort-key info in struct Sort */ int numCols; /* number of sort-key columns */ @@ -927,8 +915,7 @@ typedef struct SetOp /* ---------------- * lock-rows node * - * rowMarks identifies the rels to be locked by this node; it should be - * a subset of the rowMarks listed in the top-level PlannedStmt. + * rowMarks identifies the rels to be locked by this node. * epqParam is a Param that all scan nodes below this one must depend on. * It is used to force re-evaluation of the plan during EvalPlanQual. * ---------------- diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index adb4265047..c9f288c24d 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -117,11 +117,8 @@ typedef struct PlannerGlobal List *finalrtable; /* "flat" rangetable for executor */ - List *finalrowmarks; /* "flat" list of PlanRowMarks */ - List *resultRelations; /* "flat" list of integer RT indexes */ - List *nonleafResultRelations; /* "flat" list of integer RT indexes */ List *rootResultRelations; /* "flat" list of integer RT indexes */ List *relationOids; /* OIDs of relations the plan depends on */ @@ -1716,9 +1713,9 @@ typedef struct ModifyTablePath Path path; CmdType operation; /* INSERT, UPDATE, or DELETE */ bool canSetTag; /* do we set the command tag/es_processed? */ - Index nominalRelation; /* Parent RT index for use of EXPLAIN */ - /* RT indexes of non-leaf tables in a partition tree */ - List *partitioned_rels; + Index nominalRelation; /* RT index of the target table specified + * in the command */ + bool partitionedTarget; /* is the target table partitioned? */ bool partColsUpdated; /* some part key in hierarchy updated */ List *resultRelations; /* integer list of RT indexes */ List *subpaths; /* Path(s) producing source data */ diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h index 7c5ff22650..d826e3cc55 100644 --- a/src/include/optimizer/pathnode.h +++ b/src/include/optimizer/pathnode.h @@ -238,7 +238,7 @@ extern LockRowsPath *create_lockrows_path(PlannerInfo *root, RelOptInfo *rel, extern ModifyTablePath *create_modifytable_path(PlannerInfo *root, RelOptInfo *rel, CmdType operation, bool canSetTag, - Index nominalRelation, List *partitioned_rels, + Index nominalRelation, bool partitionedTarget, bool partColsUpdated, List *resultRelations, List *subpaths, List *subroots, -- 2.11.0