v43-0001-check-if-we-can-drop-merging-partition-before-actuall.no-cfbot
application/octet-stream
Filename: v43-0001-check-if-we-can-drop-merging-partition-before-actuall.no-cfbot
Type: application/octet-stream
Part: 0
From 96d2e0de87ee03a37aa0532484c75a370802bbe3 Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Wed, 11 Jun 2025 21:11:55 +0800
Subject: [PATCH v43 1/1] check if we can drop merging partition before
actually did it.
---
src/backend/catalog/dependency.c | 51 ++++++++++++++++++++++++++++++++
src/backend/commands/tablecmds.c | 21 +++++++++++++
src/include/catalog/dependency.h | 2 ++
3 files changed, 74 insertions(+)
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index 18316a3968b..add706b9f85 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -319,6 +319,57 @@ performDeletion(const ObjectAddress *object,
table_close(depRel, RowExclusiveLock);
}
+
+/*
+ * performDeletionCheck: Check whether a specific object can be safely deleted.
+ * This function does not perform any deletion; instead, it raises an error
+ * if the object cannot be deleted due to existing dependencies.
+ *
+ * It can be useful when you need delete some objects later. See comments in
+ * performDeletion too.
+ * The behavior must specified as DROP_RESTRICT.
+ */
+void
+performDeletionCheck(const ObjectAddress *object,
+ DropBehavior behavior, int flags)
+{
+ Relation depRel;
+ ObjectAddresses *targetObjects;
+
+ Assert(behavior == DROP_RESTRICT);
+
+ depRel = table_open(DependRelationId, RowExclusiveLock);
+
+ AcquireDeletionLock(object, 0);
+
+ /*
+ * Construct a list of objects we want delete later (ie, the given object plus
+ * everything directly or indirectly dependent on it).
+ */
+ targetObjects = new_object_addresses();
+
+ findDependentObjects(object,
+ DEPFLAG_ORIGINAL,
+ flags,
+ NULL, /* empty stack */
+ targetObjects,
+ NULL, /* no pendingObjects */
+ &depRel);
+
+ /*
+ * Check if deletion is allowed.
+ */
+ reportDependentObjects(targetObjects,
+ behavior,
+ flags,
+ object);
+
+ /* And clean up */
+ free_object_addresses(targetObjects);
+
+ table_close(depRel, RowExclusiveLock);
+}
+
/*
* performMultipleDeletions: Similar to performDeletion, but act on multiple
* objects at once.
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index d6ce87dd965..552db167854 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -22603,6 +22603,27 @@ ATExecMergePartitions(List **wqueue, AlteredTableInfo *tab, Relation rel,
Assert(OidIsValid(ownerId));
newPartRel = createPartitionTable(cmd->name, rel, ownerId);
+ /*
+ * Perform a preliminary check to determine whether it's safe to drop all
+ * merging partitions before we actually do so later. After merging rows
+ * into the new partitions via moveMergedTablesRows, all old partitions need
+ * be dropped. However, since the drop behavior is DROP_RESTRICT and the
+ * merge process (moveMergedTablesRows) can be time-consuming, performing an
+ * early check on the drop eligibility of old partitions is preferable.
+ */
+ foreach(listptr, mergingPartitionsList)
+ {
+ ObjectAddress object;
+ Relation mergingPartition = (Relation) lfirst(listptr);
+
+ /* Get oid of the later to be dropped relation */
+ object.objectId = RelationGetRelid(mergingPartition);
+ object.classId = RelationRelationId;
+ object.objectSubId = 0;
+
+ performDeletionCheck(&object, DROP_RESTRICT, PERFORM_DELETION_INTERNAL);
+ }
+
/*
* Switch to the table owner's userid, so that any index functions are run
* as that user. Also lock down security-restricted operations and
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
index 0ea7ccf5243..f54233499bf 100644
--- a/src/include/catalog/dependency.h
+++ b/src/include/catalog/dependency.h
@@ -107,6 +107,8 @@ extern void ReleaseDeletionLock(const ObjectAddress *object);
extern void performDeletion(const ObjectAddress *object,
DropBehavior behavior, int flags);
+extern void performDeletionCheck(const ObjectAddress *object,
+ DropBehavior behavior, int flags);
extern void performMultipleDeletions(const ObjectAddresses *objects,
DropBehavior behavior, int flags);
--
2.34.1