aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execMain.c
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2017-03-21 09:48:04 -0400
committerRobert Haas <rhaas@postgresql.org>2017-03-21 09:48:04 -0400
commitd3cc37f1d801a6b5cad9bf179274a8d767f1ee50 (patch)
tree88dd5a0133f46b2eb015b4fd2ce69f1b3c30bb56 /src/backend/executor/execMain.c
parentd5286aa905c9173b3fc4f911682089149bd3caef (diff)
downloadpostgresql-d3cc37f1d801a6b5cad9bf179274a8d767f1ee50.tar.gz
postgresql-d3cc37f1d801a6b5cad9bf179274a8d767f1ee50.zip
Don't scan partitioned tables.
Partitioned tables do not contain any data; only their unpartitioned descendents need to be scanned. However, the partitioned tables still need to be locked, even though they're not scanned. To make that work, Append and MergeAppend relations now need to carry a list of (unscanned) partitioned relations that must be locked, and InitPlan must lock all partitioned result relations. Aside from the obvious advantage of avoiding some work at execution time, this has two other advantages. First, it may improve the planner's decision-making in some cases since the empty relation might throw things off. Second, it paves the way to getting rid of the storage for partitioned tables altogether. Amit Langote, reviewed by me. Discussion: http://postgr.es/m/6837c359-45c4-8044-34d1-736756335a15@lab.ntt.co.jp
Diffstat (limited to 'src/backend/executor/execMain.c')
-rw-r--r--src/backend/executor/execMain.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index f5cd65d8a0d..023ea0081a0 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -844,6 +844,22 @@ InitPlan(QueryDesc *queryDesc, int eflags)
estate->es_num_result_relations = numResultRelations;
/* es_result_relation_info is NULL except when within ModifyTable */
estate->es_result_relation_info = NULL;
+
+ /*
+ * In the partitioned result relation case, lock the non-leaf result
+ * relations too. We don't however need ResultRelInfos for them.
+ */
+ if (plannedstmt->nonleafResultRelations)
+ {
+ foreach(l, plannedstmt->nonleafResultRelations)
+ {
+ Index resultRelationIndex = lfirst_int(l);
+ Oid resultRelationOid;
+
+ resultRelationOid = getrelid(resultRelationIndex, rangeTable);
+ LockRelationOid(resultRelationOid, RowExclusiveLock);
+ }
+ }
}
else
{
@@ -858,7 +874,11 @@ InitPlan(QueryDesc *queryDesc, int eflags)
/*
* Similarly, we have to lock relations selected FOR [KEY] UPDATE/SHARE
* before we initialize the plan tree, else we'd be risking lock upgrades.
- * While we are at it, build the ExecRowMark list.
+ * While we are at it, build the ExecRowMark list. Any partitioned child
+ * tables are ignored here (because isParent=true) and will be locked by
+ * the first Append or MergeAppend node that references them. (Note that
+ * the RowMarks corresponding to partitioned child tables are present in
+ * the same list as the rest, i.e., plannedstmt->rowMarks.)
*/
estate->es_rowMarks = NIL;
foreach(l, plannedstmt->rowMarks)