From be7ff5eb7b962efd53fa6a22b6ec8329910de0eb Mon Sep 17 00:00:00 2001
From: Peter Smith <peter.b.smith@fujitsu.com>
Date: Fri, 5 Feb 2021 14:57:33 +1100
Subject: [PATCH v2] replorigin_drop_by_name.

Drop the origin by name as a single operation.
The whole function is locked to prevent concurrent drops.

Discussion: https://www.postgresql.org/message-id/CAHut%2BPuW8DWV5fskkMWWMqzt-x7RPcNQOtJQBp6SdwyRghCk7A%40mail.gmail.com
---
 src/backend/replication/logical/origin.c | 72 +++++++++++++++++++++++---------
 src/include/replication/origin.h         |  1 +
 2 files changed, 54 insertions(+), 19 deletions(-)

diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c
index 9bd761a..2cd226b 100644
--- a/src/backend/replication/logical/origin.c
+++ b/src/backend/replication/logical/origin.c
@@ -324,25 +324,14 @@ replorigin_create(char *roname)
 
 
 /*
- * Drop replication origin.
- *
- * Needs to be called in a transaction.
+ * Common code to drop a replication origin.
  */
-void
-replorigin_drop(RepOriginId roident, bool nowait)
+static void
+replorigin_drop_guts(Relation rel, RepOriginId roident, bool nowait)
 {
 	HeapTuple	tuple;
-	Relation	rel;
 	int			i;
 
-	Assert(IsTransactionState());
-
-	/*
-	 * To interlock against concurrent drops, we hold ExclusiveLock on
-	 * pg_replication_origin throughout this function.
-	 */
-	rel = table_open(ReplicationOriginRelationId, ExclusiveLock);
-
 	/*
 	 * First, clean up the slot state info, if there is any matching slot.
 	 */
@@ -415,6 +404,55 @@ restart:
 	ReleaseSysCache(tuple);
 
 	CommandCounterIncrement();
+}
+
+/*
+ * Drop replication origin (by name).
+ *
+ * Needs to be called in a transaction.
+ */
+void
+replorigin_drop_by_name(char *name, bool missing_ok, bool nowait)
+{
+	RepOriginId	roident;
+	Relation	rel;
+
+	Assert(IsTransactionState());
+
+	/*
+	 * To interlock against concurrent drops, we hold ExclusiveLock on
+	 * pg_replication_origin throughout this function.
+	 */
+	rel = table_open(ReplicationOriginRelationId, ExclusiveLock);
+
+	roident = replorigin_by_name(name, missing_ok);
+
+	if (OidIsValid(roident))
+		replorigin_drop_guts(rel, roident, nowait);
+
+	/* now release lock again */
+	table_close(rel, ExclusiveLock);
+}
+
+/*
+ * Drop replication origin (by id).
+ *
+ * Needs to be called in a transaction.
+ */
+void
+replorigin_drop(RepOriginId roident, bool nowait)
+{
+	Relation	rel;
+
+	Assert(IsTransactionState());
+
+	/*
+	 * To interlock against concurrent drops, we hold ExclusiveLock on
+	 * pg_replication_origin throughout this function.
+	 */
+	rel = table_open(ReplicationOriginRelationId, ExclusiveLock);
+
+	replorigin_drop_guts(rel, roident, nowait);
 
 	/* now release lock again */
 	table_close(rel, ExclusiveLock);
@@ -1256,16 +1294,12 @@ Datum
 pg_replication_origin_drop(PG_FUNCTION_ARGS)
 {
 	char	   *name;
-	RepOriginId roident;
 
 	replorigin_check_prerequisites(false, false);
 
 	name = text_to_cstring((text *) DatumGetPointer(PG_GETARG_DATUM(0)));
 
-	roident = replorigin_by_name(name, false);
-	Assert(OidIsValid(roident));
-
-	replorigin_drop(roident, true);
+	replorigin_drop_by_name(name, false /* missing_ok */, true /* nowait */);
 
 	pfree(name);
 
diff --git a/src/include/replication/origin.h b/src/include/replication/origin.h
index 731445a..e13c238 100644
--- a/src/include/replication/origin.h
+++ b/src/include/replication/origin.h
@@ -41,6 +41,7 @@ extern PGDLLIMPORT TimestampTz replorigin_session_origin_timestamp;
 extern RepOriginId replorigin_by_name(char *name, bool missing_ok);
 extern RepOriginId replorigin_create(char *name);
 extern void replorigin_drop(RepOriginId roident, bool nowait);
+extern void replorigin_drop_by_name(char *name, bool missing_ok, bool nowait);
 extern bool replorigin_by_oid(RepOriginId roident, bool missing_ok,
 							  char **roname);
 
-- 
1.8.3.1

