From 4ad70348d8fa0ef95052451aec88aa9e2076567e Mon Sep 17 00:00:00 2001 From: "dgrowley@gmail.com" Date: Thu, 27 Sep 2018 13:27:24 +1200 Subject: [PATCH v8 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 targetRelation which replaces 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. --- contrib/postgres_fdw/postgres_fdw.c | 2 +- src/backend/commands/explain.c | 6 +-- src/backend/commands/portalcmds.c | 2 +- src/backend/executor/execMain.c | 2 +- src/backend/executor/execParallel.c | 3 +- src/backend/executor/execPartition.c | 2 +- src/backend/executor/execUtils.c | 55 -------------------- src/backend/executor/nodeAppend.c | 6 --- src/backend/executor/nodeMergeAppend.c | 6 --- src/backend/executor/nodeModifyTable.c | 9 ++-- src/backend/executor/spi.c | 4 +- src/backend/nodes/copyfuncs.c | 9 ++-- src/backend/nodes/outfuncs.c | 15 ++---- src/backend/nodes/readfuncs.c | 9 ++-- src/backend/optimizer/plan/createplan.c | 46 ++++------------- src/backend/optimizer/plan/planner.c | 89 +++++++++------------------------ src/backend/optimizer/plan/setrefs.c | 49 ++---------------- src/backend/optimizer/util/pathnode.c | 12 ++--- src/backend/tcop/utility.c | 15 ++++-- src/include/executor/executor.h | 2 - src/include/nodes/plannodes.h | 30 ++++------- src/include/nodes/relation.h | 10 ++-- src/include/optimizer/pathnode.h | 2 +- 23 files changed, 95 insertions(+), 290 deletions(-) diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index 6cbba97c22..eeb053d5d8 100644 --- a/contrib/postgres_fdw/postgres_fdw.c +++ b/contrib/postgres_fdw/postgres_fdw.c @@ -2050,7 +2050,7 @@ postgresBeginForeignInsert(ModifyTableState *mtstate, * Vars contained in those expressions. */ if (plan && plan->operation == CMD_UPDATE && - resultRelation == plan->nominalRelation) + resultRelation == plan->targetRelation) resultRelation = mtstate->resultRelInfo[0].ri_RangeTableIndex; } diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index ed6afe79a9..5ca7f69830 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -929,7 +929,7 @@ ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used) break; case T_ModifyTable: *rels_used = bms_add_member(*rels_used, - ((ModifyTable *) plan)->nominalRelation); + ((ModifyTable *) plan)->targetRelation); if (((ModifyTable *) plan)->exclRelRTI) *rels_used = bms_add_member(*rels_used, ((ModifyTable *) plan)->exclRelRTI); @@ -2924,7 +2924,7 @@ ExplainScanTarget(Scan *plan, ExplainState *es) static void ExplainModifyTarget(ModifyTable *plan, ExplainState *es) { - ExplainTargetRel((Plan *) plan, plan->nominalRelation, es); + ExplainTargetRel((Plan *) plan, plan->targetRelation, es); } /* @@ -3088,7 +3088,7 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors, /* Should we explicitly label target relations? */ labeltargets = (mtstate->mt_nplans > 1 || (mtstate->mt_nplans == 1 && - mtstate->resultRelInfo->ri_RangeTableIndex != node->nominalRelation)); + mtstate->resultRelInfo->ri_RangeTableIndex != node->targetRelation)); if (labeltargets) ExplainOpenGroup("Target Tables", "Target Tables", false, es); 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 a9edc90a52..3c197c55f4 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -219,7 +219,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 7d8bd01994..15d8fcc352 100644 --- a/src/backend/executor/execParallel.c +++ b/src/backend/executor/execParallel.c @@ -176,6 +176,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; @@ -183,7 +184,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 @@ -203,7 +203,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/execPartition.c b/src/backend/executor/execPartition.c index 3be794b97d..1d2b3620ee 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -379,7 +379,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate, leaf_part_rri = makeNode(ResultRelInfo); InitResultRelInfo(leaf_part_rri, partrel, - node ? node->nominalRelation : 1, + node ? node->targetRelation : 1, rootrel, estate->es_instrument); 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 f81769ea85..b18f9e3164 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -2255,18 +2255,17 @@ 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); + rte = rt_fetch(node->targetRelation, 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->targetRelation, 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..da02b8961c 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); @@ -203,8 +202,8 @@ _copyModifyTable(const ModifyTable *from) */ COPY_SCALAR_FIELD(operation); COPY_SCALAR_FIELD(canSetTag); - COPY_SCALAR_FIELD(nominalRelation); - COPY_NODE_FIELD(partitioned_rels); + COPY_SCALAR_FIELD(targetRelation); + 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 03d84aa0cd..2e6a5a1b42 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -272,6 +272,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); @@ -280,11 +281,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); @@ -375,8 +374,8 @@ _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(targetRelation); + WRITE_BOOL_FIELD(partitionedTarget); WRITE_BOOL_FIELD(partColsUpdated); WRITE_NODE_FIELD(resultRelations); WRITE_INT_FIELD(resultRelIndex); @@ -405,7 +404,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); } @@ -418,7 +416,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); @@ -2178,8 +2175,8 @@ _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(targetRelation); + WRITE_BOOL_FIELD(partitionedTarget); WRITE_BOOL_FIELD(partColsUpdated); WRITE_NODE_FIELD(resultRelations); WRITE_NODE_FIELD(subpaths); @@ -2257,9 +2254,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 fc006e2830..aea5b0abc4 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -1496,6 +1496,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); @@ -1504,11 +1505,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); @@ -1597,8 +1596,8 @@ _readModifyTable(void) READ_ENUM_FIELD(operation, CmdType); READ_BOOL_FIELD(canSetTag); - READ_UINT_FIELD(nominalRelation); - READ_NODE_FIELD(partitioned_rels); + READ_UINT_FIELD(targetRelation); + READ_BOOL_FIELD(partitionedTarget); READ_BOOL_FIELD(partColsUpdated); READ_NODE_FIELD(resultRelations); READ_INT_FIELD(resultRelIndex); @@ -1632,7 +1631,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(); @@ -1648,7 +1646,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..8f20e54d9e 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 targetRelation, 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; @@ -2410,8 +2405,8 @@ create_modifytable_plan(PlannerInfo *root, ModifyTablePath *best_path) plan = make_modifytable(root, best_path->operation, best_path->canSetTag, - best_path->nominalRelation, - best_path->partitioned_rels, + best_path->targetRelation, + 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 targetRelation, bool partitionedTarget, bool partColsUpdated, List *resultRelations, List *subplans, List *subroots, List *withCheckOptionLists, List *returningLists, @@ -6537,8 +6509,8 @@ make_modifytable(PlannerInfo *root, node->operation = operation; node->canSetTag = canSetTag; - node->nominalRelation = nominalRelation; - node->partitioned_rels = flatten_partitioned_rels(partitioned_rels); + node->targetRelation = targetRelation; + 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 22c010c19e..a927c0a1db 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -287,6 +287,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 @@ -301,9 +302,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; @@ -501,9 +500,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) */ @@ -514,6 +511,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 */ @@ -523,6 +522,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; @@ -530,11 +530,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; @@ -1169,7 +1167,7 @@ inheritance_planner(PlannerInfo *root) int top_parentRTindex = parse->resultRelation; Bitmapset *subqueryRTindexes; Bitmapset *modifiableARIindexes; - int nominalRelation = -1; + int targetRelation = -1; List *final_rtable = NIL; int save_rel_array_size = 0; RelOptInfo **save_rel_array = NULL; @@ -1184,8 +1182,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); @@ -1248,25 +1245,14 @@ inheritance_planner(PlannerInfo *root) } /* - * If the parent RTE is a partitioned table, we should use that as the - * nominal relation, because the RTEs added for partitioned tables - * (including the root parent) as child members of the inheritance set do - * not appear anywhere else in the plan. The situation is exactly the - * opposite in the case of non-partitioned inheritance parent as described - * below. For the same reason, collect the list of descendant partitioned - * tables to be saved in ModifyTable node, so that executor can lock those - * as well. + * If the parent RTE is a partitioned table, set that as the target + * relation and mark that we're working with a partitioned target. */ 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); + targetRelation = top_parentRTindex; + partitionedTarget = true; } /* @@ -1338,7 +1324,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. @@ -1363,17 +1349,17 @@ inheritance_planner(PlannerInfo *root) } /* - * Set the nominal target relation of the ModifyTable node if not - * already done. We use the inheritance parent RTE as the nominal - * target relation if it's a partitioned table (see just above this - * loop). In the non-partitioned parent case, we'll use the first - * child relation (even if it's excluded) as the nominal target - * relation. Because of the way expand_inherited_rtentry works, the - * latter should be the RTE representing the parent table in its role - * as a simple member of the inheritance set. + * Set the target relation of the ModifyTable node if not already + * done. We use the inheritance parent RTE as the target relation + * if it's a partitioned table (see just above this loop). In the + * non-partitioned parent case, we'll use the first child relation + * (even if it's excluded) as the target relation. Because of the way + * expand_inherited_rtentry works, the latter should be the RTE + * representing the parent table in its role as a simple member of + * the inheritance set. * * It would be logically cleaner to *always* use the inheritance - * parent RTE as the nominal relation; but that RTE is not otherwise + * parent RTE as the target relation; but that RTE is not otherwise * referenced in the plan in the non-partitioned inheritance case. * Instead the duplicate child RTE created by expand_inherited_rtentry * is used elsewhere in the plan, so using the original parent RTE @@ -1383,8 +1369,8 @@ inheritance_planner(PlannerInfo *root) * duplicate child RTE added for the parent does not appear anywhere * else in the plan tree. */ - if (nominalRelation < 0) - nominalRelation = appinfo->child_relid; + if (targetRelation < 0) + targetRelation = appinfo->child_relid; /* * The rowMarks list might contain references to subquery RTEs, so @@ -1509,15 +1495,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. @@ -1620,29 +1597,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, + targetRelation, + partitionedTarget, root->partColsUpdated, resultRelations, subpaths, @@ -2219,7 +2180,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update, parse->commandType, parse->canSetTag, parse->resultRelation, - NIL, + false, 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..17d53f356c 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); } @@ -847,13 +827,9 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset) fix_scan_list(root, splan->exclRelTlist, rtoffset); } - splan->nominalRelation += rtoffset; + splan->targetRelation += 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->targetRelation); } } 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..73eca1d4d0 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -3291,10 +3291,8 @@ create_lockrows_path(PlannerInfo *root, RelOptInfo *rel, * 'rel' is the parent relation associated with the result * '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. + * 'targetRelation' is the target table's RT index + * 'partitionedTarget' true if 'targetRelation' is a 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 targetRelation, bool partitionedTarget, bool partColsUpdated, List *resultRelations, List *subpaths, List *subroots, @@ -3376,8 +3374,8 @@ create_modifytable_path(PlannerInfo *root, RelOptInfo *rel, pathnode->operation = operation; pathnode->canSetTag = canSetTag; - pathnode->nominalRelation = nominalRelation; - pathnode->partitioned_rels = list_copy(partitioned_rels); + pathnode->targetRelation = targetRelation; + 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..27ae73e3d4 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,10 @@ 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 targetRelation; /* RT index of the target table specified in + * the command or first child for inheritance + * tables */ + 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 +253,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 +265,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 +916,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..bcc2ba6db5 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,10 @@ 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 targetRelation; /* RT index of the target table specified in + * the command or first child for inheritance + * tables */ + 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..a45c2407d0 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 targetRelation, bool partitionedTarget, bool partColsUpdated, List *resultRelations, List *subpaths, List *subroots, -- 2.11.0