From 22c4bcdde3f1c7f7d3122299f9aaf408a38f19f2 Mon Sep 17 00:00:00 2001
From: Masahiko Sawada <sawada.mshk@gmail.com>
Date: Wed, 29 Jan 2025 11:34:55 -0800
Subject: [PATCH v1] pg_rewind: Add dbname to primary_connifo with
 --write-recovery-conf.

Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch-through:
---
 src/bin/pg_basebackup/pg_basebackup.c |  2 +-
 src/bin/pg_basebackup/streamutil.c    | 69 ---------------------------
 src/bin/pg_basebackup/streamutil.h    |  2 -
 src/bin/pg_rewind/pg_rewind.c         |  6 ++-
 src/fe_utils/recovery_gen.c           | 65 +++++++++++++++++++++++++
 src/include/fe_utils/recovery_gen.h   |  1 +
 6 files changed, 71 insertions(+), 74 deletions(-)

diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c
index dc0c805137a..d4b4e334014 100644
--- a/src/bin/pg_basebackup/pg_basebackup.c
+++ b/src/bin/pg_basebackup/pg_basebackup.c
@@ -1818,7 +1818,7 @@ BaseBackup(char *compression_algorithm, char *compression_detail,
 	if (writerecoveryconf)
 		recoveryconfcontents = GenerateRecoveryConfig(conn,
 													  replication_slot,
-													  GetDbnameFromConnectionOptions());
+													  GetDbnameFromConnectionOptions(connection_string));
 
 	/*
 	 * Run IDENTIFY_SYSTEM so we can get the timeline
diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c
index 021ab61fcb0..8e605f43ffe 100644
--- a/src/bin/pg_basebackup/streamutil.c
+++ b/src/bin/pg_basebackup/streamutil.c
@@ -32,7 +32,6 @@
 int			WalSegSz;
 
 static bool RetrieveDataDirCreatePerm(PGconn *conn);
-static char *FindDbnameInConnParams(PQconninfoOption *conn_opts);
 
 /* SHOW command for replication connection was introduced in version 10 */
 #define MINIMUM_VERSION_FOR_SHOW_CMD 100000
@@ -269,74 +268,6 @@ GetConnection(void)
 	return tmpconn;
 }
 
-/*
- * FindDbnameInConnParams
- *
- * This is a helper function for GetDbnameFromConnectionOptions(). Extract
- * the value of dbname from PQconninfoOption parameters, if it's present.
- * Returns a strdup'd result or NULL.
- */
-static char *
-FindDbnameInConnParams(PQconninfoOption *conn_opts)
-{
-	PQconninfoOption *conn_opt;
-
-	for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
-	{
-		if (strcmp(conn_opt->keyword, "dbname") == 0 &&
-			conn_opt->val != NULL && conn_opt->val[0] != '\0')
-			return pg_strdup(conn_opt->val);
-	}
-	return NULL;
-}
-
-/*
- * GetDbnameFromConnectionOptions
- *
- * This is a special purpose function to retrieve the dbname from either the
- * connection_string specified by the user or from the environment variables.
- *
- * We follow GetConnection() to fetch the dbname from various connection
- * options.
- *
- * Returns NULL, if dbname is not specified by the user in the above
- * mentioned connection options.
- */
-char *
-GetDbnameFromConnectionOptions(void)
-{
-	PQconninfoOption *conn_opts;
-	char	   *err_msg = NULL;
-	char	   *dbname;
-
-	/* First try to get the dbname from connection string. */
-	if (connection_string)
-	{
-		conn_opts = PQconninfoParse(connection_string, &err_msg);
-		if (conn_opts == NULL)
-			pg_fatal("%s", err_msg);
-
-		dbname = FindDbnameInConnParams(conn_opts);
-
-		PQconninfoFree(conn_opts);
-		if (dbname)
-			return dbname;
-	}
-
-	/*
-	 * Next try to get the dbname from default values that are available from
-	 * the environment.
-	 */
-	conn_opts = PQconndefaults();
-	if (conn_opts == NULL)
-		pg_fatal("out of memory");
-
-	dbname = FindDbnameInConnParams(conn_opts);
-
-	PQconninfoFree(conn_opts);
-	return dbname;
-}
-
 /*
  * From version 10, explicitly set wal segment size using SHOW wal_segment_size
  * since ControlFile is not accessible here.
diff --git a/src/bin/pg_basebackup/streamutil.h b/src/bin/pg_basebackup/streamutil.h
index 472193e239f..f917c43517f 100644
--- a/src/bin/pg_basebackup/streamutil.h
+++ b/src/bin/pg_basebackup/streamutil.h
@@ -31,8 +31,6 @@ extern PGconn *conn;
 
 extern PGconn *GetConnection(void);
 
-extern char *GetDbnameFromConnectionOptions(void);
-
 /* Replication commands */
 extern bool CreateReplicationSlot(PGconn *conn, const char *slot_name,
 								  const char *plugin, bool is_temporary,
diff --git a/src/bin/pg_rewind/pg_rewind.c b/src/bin/pg_rewind/pg_rewind.c
index cae81cd6cb1..fbd29d81068 100644
--- a/src/bin/pg_rewind/pg_rewind.c
+++ b/src/bin/pg_rewind/pg_rewind.c
@@ -451,7 +451,8 @@ main(int argc, char **argv)
 		pg_log_info("no rewind required");
 		if (writerecoveryconf && !dry_run)
 			WriteRecoveryConfig(conn, datadir_target,
-								GenerateRecoveryConfig(conn, NULL, NULL));
+								GenerateRecoveryConfig(conn, NULL,
+													   GetDbnameFromConnectionOptions(connstr_source)));
 		exit(0);
 	}
 
@@ -528,7 +529,8 @@ main(int argc, char **argv)
 	/* Also update the standby configuration, if requested. */
 	if (writerecoveryconf && !dry_run)
 		WriteRecoveryConfig(conn, datadir_target,
-							GenerateRecoveryConfig(conn, NULL, NULL));
+							GenerateRecoveryConfig(conn, NULL,
+												   GetDbnameFromConnectionOptions(connstr_source)));
 
 	/* don't need the source connection anymore */
 	source->destroy(source);
diff --git a/src/fe_utils/recovery_gen.c b/src/fe_utils/recovery_gen.c
index 7c172f65a10..eaf2c125c16 100644
--- a/src/fe_utils/recovery_gen.c
+++ b/src/fe_utils/recovery_gen.c
@@ -168,3 +168,68 @@ escape_quotes(const char *src)
 		pg_fatal("out of memory");
 	return result;
 }
+
+/*
+ * FindDbnameInConnParams
+ *
+ * This is a helper function for GetDbnameFromConnectionOptions(). Extract
+ * the value of dbname from PQconninfoOption parameters, if it's present.
+ * Returns a strdup'd result or NULL.
+ */
+static char *
+FindDbnameInConnParams(PQconninfoOption *conn_opts)
+{
+	PQconninfoOption *conn_opt;
+
+	for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
+	{
+		if (strcmp(conn_opt->keyword, "dbname") == 0 &&
+			conn_opt->val != NULL && conn_opt->val[0] != '\0')
+			return pg_strdup(conn_opt->val);
+	}
+	return NULL;
+}
+
+/*
+ * GetDbnameFromConnectionOptions
+ *
+ * This is a special purpose function to retrieve the dbname from either the
+ * 'connstr' specified by the caller or from the environment variables.
+ *
+ * Returns NULL, if dbname is not specified by the user in the above
+ * mentioned connection options.
+ */
+char *
+GetDbnameFromConnectionOptions(const char *connstr)
+{
+	PQconninfoOption *conn_opts;
+	char	   *err_msg = NULL;
+	char	   *dbname;
+
+	/* First try to get the dbname from connection string. */
+	if (connstr)
+	{
+		conn_opts = PQconninfoParse(connstr, &err_msg);
+		if (conn_opts == NULL)
+			pg_fatal("%s", err_msg);
+
+		dbname = FindDbnameInConnParams(conn_opts);
+
+		PQconninfoFree(conn_opts);
+		if (dbname)
+			return dbname;
+	}
+
+	/*
+	 * Next try to get the dbname from default values that are available from
+	 * the environment.
+	 */
+	conn_opts = PQconndefaults();
+	if (conn_opts == NULL)
+		pg_fatal("out of memory");
+
+	dbname = FindDbnameInConnParams(conn_opts);
+
+	PQconninfoFree(conn_opts);
+	return dbname;
+}
diff --git a/src/include/fe_utils/recovery_gen.h b/src/include/fe_utils/recovery_gen.h
index 6412ffdaffa..c13f2263bcd 100644
--- a/src/include/fe_utils/recovery_gen.h
+++ b/src/include/fe_utils/recovery_gen.h
@@ -25,5 +25,6 @@ extern PQExpBuffer GenerateRecoveryConfig(PGconn *pgconn,
 										  char *dbname);
 extern void WriteRecoveryConfig(PGconn *pgconn, const char *target_dir,
 								PQExpBuffer contents);
+extern char *GetDbnameFromConnectionOptions(const char *connstr);
 
 #endif							/* RECOVERY_GEN_H */
-- 
2.43.5

