aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/cache/plancache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/cache/plancache.c')
-rw-r--r--src/backend/utils/cache/plancache.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 1a0950489d7..c1f4128445b 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -1735,6 +1735,23 @@ QueryListGetPrimaryStmt(List *stmts)
return NULL;
}
+static void
+AcquireExecutorLocksOnPartitions(List *partitionOids, int lockmode,
+ bool acquire)
+{
+ ListCell *lc;
+
+ foreach(lc, partitionOids)
+ {
+ Oid partOid = lfirst_oid(lc);
+
+ if (acquire)
+ LockRelationOid(partOid, lockmode);
+ else
+ UnlockRelationOid(partOid, lockmode);
+ }
+}
+
/*
* AcquireExecutorLocks: acquire locks needed for execution of a cached plan;
* or release them if acquire is false.
@@ -1748,6 +1765,8 @@ AcquireExecutorLocks(List *stmt_list, bool acquire)
{
PlannedStmt *plannedstmt = lfirst_node(PlannedStmt, lc1);
ListCell *lc2;
+ Index rti,
+ resultRelation = 0;
if (plannedstmt->commandType == CMD_UTILITY)
{
@@ -1765,6 +1784,9 @@ AcquireExecutorLocks(List *stmt_list, bool acquire)
continue;
}
+ rti = 1;
+ if (plannedstmt->resultRelations)
+ resultRelation = linitial_int(plannedstmt->resultRelations);
foreach(lc2, plannedstmt->rtable)
{
RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc2);
@@ -1782,6 +1804,14 @@ AcquireExecutorLocks(List *stmt_list, bool acquire)
LockRelationOid(rte->relid, rte->rellockmode);
else
UnlockRelationOid(rte->relid, rte->rellockmode);
+
+ /* Lock partitions ahead of modifying them in parallel mode. */
+ if (rti == resultRelation &&
+ plannedstmt->partitionOids != NIL)
+ AcquireExecutorLocksOnPartitions(plannedstmt->partitionOids,
+ rte->rellockmode, acquire);
+
+ rti++;
}
}
}
@@ -1990,7 +2020,8 @@ PlanCacheRelCallback(Datum arg, Oid relid)
if (plannedstmt->commandType == CMD_UTILITY)
continue; /* Ignore utility statements */
if ((relid == InvalidOid) ? plannedstmt->relationOids != NIL :
- list_member_oid(plannedstmt->relationOids, relid))
+ (list_member_oid(plannedstmt->relationOids, relid) ||
+ list_member_oid(plannedstmt->partitionOids, relid)))
{
/* Invalidate the generic plan only */
plansource->gplan->is_valid = false;