v4-0002-Remove-useless-fields-from-planner-nodes.patch

text/plain

Filename: v4-0002-Remove-useless-fields-from-planner-nodes.patch
Type: text/plain
Part: 1
Message: Re: executor relation handling

Patch

Format: format-patch
Series: patch v4-0002
Subject: Remove useless fields from planner nodes
File+
src/backend/commands/portalcmds.c 1 1
src/backend/executor/execMain.c 1 1
src/backend/executor/execParallel.c 1 2
src/backend/executor/execUtils.c 0 55
src/backend/executor/nodeAppend.c 0 6
src/backend/executor/nodeMergeAppend.c 0 6
src/backend/executor/nodeModifyTable.c 5 5
src/backend/executor/spi.c 2 2
src/backend/nodes/copyfuncs.c 2 5
src/backend/nodes/outfuncs.c 3 8
src/backend/nodes/readfuncs.c 2 5
src/backend/optimizer/plan/createplan.c 7 35
src/backend/optimizer/plan/planner.c 9 42
src/backend/optimizer/plan/setrefs.c 4 43
src/backend/optimizer/util/pathnode.c 3 5
src/backend/tcop/utility.c 12 3
src/include/executor/executor.h 0 2
src/include/nodes/plannodes.h 8 21
src/include/nodes/relation.h 3 6
src/include/optimizer/pathnode.h 1 1
From 5fef352b9ce73c9ffbfa4b49e5c7e425c2e4da75 Mon Sep 17 00:00:00 2001
From: amit <amitlangote09@gmail.com>
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