From af7b37d2eff942e4a3a9563a9340fd3d7853e5ba Mon Sep 17 00:00:00 2001
From: Vaibhav Dalvi <vaibhav.dalvi@enterprisedb.com>
Date: Tue, 11 Nov 2025 04:58:59 +0000
Subject: [PATCH v4 1/2] Use list of C strings for publications

Currently, the structure Subscription has member
publications and it is list of String node rather
than a list of C strings. Subscription is not a
not a node, so this seems wasteful and pointless.

This patch tries to get rid of the String node
around Subscription->publications.

Vaibhav Dalvi
---
 src/backend/catalog/pg_subscription.c         | 15 ++++++++-----
 src/backend/commands/subscriptioncmds.c       | 21 +++++++++++++++----
 .../libpqwalreceiver/libpqwalreceiver.c       |  4 ++--
 3 files changed, 29 insertions(+), 11 deletions(-)

diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c
index 1945627ed88..09e9dc98167 100644
--- a/src/backend/catalog/pg_subscription.c
+++ b/src/backend/catalog/pg_subscription.c
@@ -32,7 +32,7 @@
 #include "utils/rel.h"
 #include "utils/syscache.h"
 
-static List *textarray_to_stringlist(ArrayType *textarray);
+static List *textarray_to_cstringlist(ArrayType *textarray);
 
 /*
  * Add a comma-separated list of publication names to the 'dest' string.
@@ -47,7 +47,12 @@ GetPublicationsStr(List *publications, StringInfo dest, bool quote_literal)
 
 	foreach(lc, publications)
 	{
-		char	   *pubname = strVal(lfirst(lc));
+		char	   *pubname;
+
+		if (IsA((Node *) lfirst(lc), String))
+			pubname = strVal(lfirst(lc));
+		else
+			pubname = (char *) lfirst(lc);
 
 		if (first)
 			first = false;
@@ -133,7 +138,7 @@ GetSubscription(Oid subid, bool missing_ok)
 	datum = SysCacheGetAttrNotNull(SUBSCRIPTIONOID,
 								   tup,
 								   Anum_pg_subscription_subpublications);
-	sub->publications = textarray_to_stringlist(DatumGetArrayTypeP(datum));
+	sub->publications = textarray_to_cstringlist(DatumGetArrayTypeP(datum));
 
 	/* Get origin */
 	datum = SysCacheGetAttrNotNull(SUBSCRIPTIONOID,
@@ -241,7 +246,7 @@ DisableSubscription(Oid subid)
  * Note: the resulting list of strings is pallocated here.
  */
 static List *
-textarray_to_stringlist(ArrayType *textarray)
+textarray_to_cstringlist(ArrayType *textarray)
 {
 	Datum	   *elems;
 	int			nelems,
@@ -254,7 +259,7 @@ textarray_to_stringlist(ArrayType *textarray)
 		return NIL;
 
 	for (i = 0; i < nelems; i++)
-		res = lappend(res, makeString(TextDatumGetCString(elems[i])));
+		res = lappend(res, TextDatumGetCString(elems[i]));
 
 	return res;
 }
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 3d29818badd..f55230292a6 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -3043,6 +3043,9 @@ ReportSlotConnectionError(List *rstates, Oid subid, char *slotname, char *err)
  * Check for duplicates in the given list of publications and error out if
  * found one.  Add publications to datums as text datums, if datums is not
  * NULL.
+ *
+ * Note that publications can be either list of string nodes or list of the
+ * C strings.
  */
 static void
 check_duplicates_in_publist(List *publist, Datum *datums)
@@ -3052,12 +3055,22 @@ check_duplicates_in_publist(List *publist, Datum *datums)
 
 	foreach(cell, publist)
 	{
-		char	   *name = strVal(lfirst(cell));
+		char	   *name;
 		ListCell   *pcell;
 
+		if (IsA((Node *) lfirst(cell), String))
+			name = strVal(lfirst(cell));
+		else
+			name = (char *) lfirst(cell);
+
 		foreach(pcell, publist)
 		{
-			char	   *pname = strVal(lfirst(pcell));
+			char	   *pname;
+
+			if (IsA((Node *) lfirst(pcell), String))
+				pname = strVal(lfirst(pcell));
+			else
+				pname = (char *) lfirst(pcell);
 
 			if (pcell == cell)
 				break;
@@ -3101,7 +3114,7 @@ merge_publications(List *oldpublist, List *newpublist, bool addpub, const char *
 
 		foreach(lc2, oldpublist)
 		{
-			char	   *pubname = strVal(lfirst(lc2));
+			char	   *pubname = (char *) (lfirst(lc2));
 
 			if (strcmp(name, pubname) == 0)
 			{
@@ -3119,7 +3132,7 @@ merge_publications(List *oldpublist, List *newpublist, bool addpub, const char *
 		}
 
 		if (addpub && !found)
-			oldpublist = lappend(oldpublist, makeString(name));
+			oldpublist = lappend(oldpublist, name);
 		else if (!addpub && !found)
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 239641bfbb6..8b97619db5c 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -1172,7 +1172,7 @@ libpqrcv_exec(WalReceiverConn *conn, const char *query,
 }
 
 /*
- * Given a List of strings, return it as single comma separated
+ * Given a List of C strings, return it as single comma separated
  * string, quoting identifiers as needed.
  *
  * This is essentially the reverse of SplitIdentifierString.
@@ -1190,7 +1190,7 @@ stringlist_to_identifierstr(PGconn *conn, List *strings)
 
 	foreach(lc, strings)
 	{
-		char	   *val = strVal(lfirst(lc));
+		char	   *val = (char *) (lfirst(lc));
 		char	   *val_escaped;
 
 		if (first)
-- 
2.43.0

