Skip to content

Commit 972b6ec

Browse files
committed
Fix lock upgrade hazard in ATExecAttachPartition.
Amit Langote Discussion: http://postgr.es/m/CAFjFpReT_kq_uwU_B8aWDxR7jNGE=P0iELycdq5oupi=xSQTOw@mail.gmail.com
1 parent 583df3b commit 972b6ec

File tree

1 file changed

+13
-10
lines changed

1 file changed

+13
-10
lines changed

src/backend/commands/tablecmds.c

+13-10
Original file line numberDiff line numberDiff line change
@@ -13489,9 +13489,20 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
1348913489
/*
1349013490
* Prevent circularity by seeing if rel is a partition of attachrel. (In
1349113491
* particular, this disallows making a rel a partition of itself.)
13492+
*
13493+
* We do that by checking if rel is a member of the list of attachRel's
13494+
* partitions provided the latter is partitioned at all. We want to avoid
13495+
* having to construct this list again, so we request the strongest lock
13496+
* on all partitions. We need the strongest lock, because we may decide
13497+
* to scan them if we find out that the table being attached (or its leaf
13498+
* partitions) may contain rows that violate the partition constraint.
13499+
* If the table has a constraint that would prevent such rows, which by
13500+
* definition is present in all the partitions, we need not scan the
13501+
* table, nor its partitions. But we cannot risk a deadlock by taking a
13502+
* weaker lock now and the stronger one only when needed.
1349213503
*/
1349313504
attachrel_children = find_all_inheritors(RelationGetRelid(attachrel),
13494-
AccessShareLock, NULL);
13505+
AccessExclusiveLock, NULL);
1349513506
if (list_member_oid(attachrel_children, RelationGetRelid(rel)))
1349613507
ereport(ERROR,
1349713508
(errcode(ERRCODE_DUPLICATE_TABLE),
@@ -13694,17 +13705,9 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
1369413705
else
1369513706
{
1369613707
/* Constraints proved insufficient, so we need to scan the table. */
13697-
List *all_parts;
1369813708
ListCell *lc;
1369913709

13700-
/* Take an exclusive lock on the partitions to be checked */
13701-
if (attachrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
13702-
all_parts = find_all_inheritors(RelationGetRelid(attachrel),
13703-
AccessExclusiveLock, NULL);
13704-
else
13705-
all_parts = list_make1_oid(RelationGetRelid(attachrel));
13706-
13707-
foreach(lc, all_parts)
13710+
foreach(lc, attachrel_children)
1370813711
{
1370913712
AlteredTableInfo *tab;
1371013713
Oid part_relid = lfirst_oid(lc);

0 commit comments

Comments
 (0)