@@ -13489,9 +13489,20 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
13489
13489
/*
13490
13490
* Prevent circularity by seeing if rel is a partition of attachrel. (In
13491
13491
* 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.
13492
13503
*/
13493
13504
attachrel_children = find_all_inheritors (RelationGetRelid (attachrel ),
13494
- AccessShareLock , NULL );
13505
+ AccessExclusiveLock , NULL );
13495
13506
if (list_member_oid (attachrel_children , RelationGetRelid (rel )))
13496
13507
ereport (ERROR ,
13497
13508
(errcode (ERRCODE_DUPLICATE_TABLE ),
@@ -13694,17 +13705,9 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
13694
13705
else
13695
13706
{
13696
13707
/* Constraints proved insufficient, so we need to scan the table. */
13697
- List * all_parts ;
13698
13708
ListCell * lc ;
13699
13709
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 )
13708
13711
{
13709
13712
AlteredTableInfo * tab ;
13710
13713
Oid part_relid = lfirst_oid (lc );
0 commit comments