From 6b934cf39c05fc0f3720bb8817e0489cf7e0c339 Mon Sep 17 00:00:00 2001 From: amit Date: Mon, 13 Aug 2018 16:10:19 +0900 Subject: [PATCH v1 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 single Index field called 'rootRelation', because we still need to refer to root partitioned table for constructing a ResultRelInfo needed for processing its statement triggers. * '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 | 7 ++--- 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 | 39 +++-------------------- src/backend/optimizer/plan/setrefs.c | 49 ++++------------------------- src/backend/optimizer/util/pathnode.c | 8 ++--- src/backend/tcop/utility.c | 15 +++++++-- src/include/executor/executor.h | 2 -- src/include/nodes/plannodes.h | 26 ++++------------ src/include/nodes/relation.h | 6 +--- src/include/optimizer/pathnode.h | 2 +- 20 files changed, 56 insertions(+), 243 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 298bf43fce..5e0c2b8e67 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..fd3966d489 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -2255,17 +2255,16 @@ 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->rootRelation > 0); + rte = rt_fetch(node->rootRelation, estate->es_range_table); rel = heap_open(rte->relid, NoLock); - InitResultRelInfo(mtstate->rootResultRelInfo, rel, root_rt_index, + InitResultRelInfo(mtstate->rootResultRelInfo, rel, node->rootRelation, NULL, estate->es_instrument); } diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index 5756365c8f..b3664e2f3f 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -1334,7 +1334,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 @@ -1350,7 +1350,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..29abe56b70 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(rootRelation); 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 b4d2a4aa4c..f5fd9e6345 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_UINT_FIELD(rootRelation); 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_UINT_FIELD(rootRelation); 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..780d261edf 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_UINT_FIELD(rootRelation); 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..ae46b0140e 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, Index rootRelation, 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->rootRelation, 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, Index rootRelation, 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->rootRelation = rootRelation; 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..34fbc37702 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -290,9 +290,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 +488,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) */ @@ -512,6 +508,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) result->queryId = parse->queryId; result->hasReturning = (parse->returningList != NIL); result->hasModifyingCTE = parse->hasModifyingCTE; + result->hasRowMarks = (parse->rowMarks != NIL); result->canSetTag = parse->canSetTag; result->transientPlan = glob->transientPlan; result->dependsOnRole = glob->dependsOnRole; @@ -519,11 +516,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; @@ -1174,7 +1169,7 @@ inheritance_planner(PlannerInfo *root) Index rti; RangeTblEntry *parent_rte; Relids partitioned_relids = NULL; - List *partitioned_rels = NIL; + Index rootRelation = 0; PlannerInfo *parent_root; Query *parent_parse; Bitmapset *parent_relids = bms_make_singleton(top_parentRTindex); @@ -1248,15 +1243,7 @@ inheritance_planner(PlannerInfo *root) */ parent_rte = rt_fetch(top_parentRTindex, root->parse->rtable); 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); - } + nominalRelation = rootRelation = top_parentRTindex; /* * The PlannerInfo for each child is obtained by translating the relevant @@ -1609,29 +1596,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, + rootRelation, root->partColsUpdated, resultRelations, subpaths, @@ -2208,7 +2179,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 69dd327f0c..7db9d0f1d4 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -215,7 +215,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 @@ -224,25 +223,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); } @@ -852,12 +832,10 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset) } splan->nominalRelation += rtoffset; + if (splan->rootRelation > 0) + splan->rootRelation += rtoffset; splan->exclRelRTI += rtoffset; - foreach(l, splan->partitioned_rels) - { - lfirst_int(l) += rtoffset; - } foreach(l, splan->resultRelations) { lfirst_int(l) += rtoffset; @@ -888,24 +866,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->rootRelation > 0) { - 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->rootRelation); } } break; @@ -919,10 +890,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, @@ -941,10 +908,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..4983e500ac 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, Index rootRelation, 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->rootRelation = rootRelation; 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..72cf99c79e 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 if (IsA(stmt->planTree, ModifyTable)) + 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..a342edf49c 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 */ @@ -220,8 +213,7 @@ typedef struct ModifyTable 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 rootRelation; /* RT index of root partitioned table */ 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 +251,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 +263,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 +914,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 41caf873fb..10d9327b8b 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 */ @@ -1713,8 +1710,7 @@ typedef struct ModifyTablePath 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 rootRelation; /* RT index of root partitioned table */ 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..81abcf53a8 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, Index rootRelation, bool partColsUpdated, List *resultRelations, List *subpaths, List *subroots, -- 2.11.0