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
Message: Re: Add SPLIT PARTITION/MERGE PARTITIONS commands
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