From a50d860ae1dfca56148dd41692b963bb859bf1d6 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Tue, 1 Nov 2011 13:49:03 -0400
Subject: [PATCH] Allow pg_upgrade to upgrade an old cluster that doesn't have
 a 'postgres' database.

---
 contrib/pg_upgrade/check.c       | 37 +-------------------------------
 contrib/pg_upgrade/function.c    |  3 +--
 contrib/pg_upgrade/relfilenode.c | 22 +++++++++++++------
 3 files changed, 17 insertions(+), 45 deletions(-)

diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c
index e400814617b..d32a84c6354 100644
--- a/contrib/pg_upgrade/check.c
+++ b/contrib/pg_upgrade/check.c
@@ -14,7 +14,6 @@
 
 static void set_locale_and_encoding(ClusterInfo *cluster);
 static void check_new_cluster_is_empty(void);
-static void check_old_cluster_has_new_cluster_dbs(void);
 static void check_locale_and_encoding(ControlData *oldctrl,
 						  ControlData *newctrl);
 static void check_is_super_user(ClusterInfo *cluster);
@@ -127,7 +126,6 @@ check_new_cluster(void)
 
 	check_new_cluster_is_empty();
 	check_for_prepared_transactions(&new_cluster);
-	check_old_cluster_has_new_cluster_dbs();
 
 	check_loadable_libraries();
 
@@ -381,39 +379,6 @@ check_new_cluster_is_empty(void)
 }
 
 
-/*
- *	If someone removes the 'postgres' database from the old cluster and
- *	the new cluster has a 'postgres' database, the number of databases
- *	will not match.  We actually could upgrade such a setup, but it would
- *	violate the 1-to-1 mapping of database counts, so we throw an error
- *	instead.  We would detect this as a database count mismatch during
- *	upgrade, but we want to detect it during the check phase and report
- *	the database name.
- */
-static void
-check_old_cluster_has_new_cluster_dbs(void)
-{
-	int			old_dbnum,
-				new_dbnum;
-
-	for (new_dbnum = 0; new_dbnum < new_cluster.dbarr.ndbs; new_dbnum++)
-	{
-		for (old_dbnum = 0; old_dbnum < old_cluster.dbarr.ndbs; old_dbnum++)
-			if (strcmp(old_cluster.dbarr.dbs[old_dbnum].db_name,
-					   new_cluster.dbarr.dbs[new_dbnum].db_name) == 0)
-				break;
-		if (old_dbnum == old_cluster.dbarr.ndbs)
-		{
-			if (strcmp(new_cluster.dbarr.dbs[new_dbnum].db_name, "postgres") == 0)
-				pg_log(PG_FATAL, "The \"postgres\" database must exist in the old cluster\n");
-			else
-				pg_log(PG_FATAL, "New cluster database \"%s\" does not exist in the old cluster\n",
-					   new_cluster.dbarr.dbs[new_dbnum].db_name);
-		}
-	}
-}
-
-
 /*
  * create_script_for_old_cluster_deletion()
  *
@@ -462,7 +427,7 @@ create_script_for_old_cluster_deletion(char **deletion_script_file_name)
 				fprintf(script, RM_CMD " %s%s/PG_VERSION\n",
 				 os_info.tablespaces[tblnum], old_cluster.tablespace_suffix);
 
-			for (dbnum = 0; dbnum < new_cluster.dbarr.ndbs; dbnum++)
+			for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
 			{
 				fprintf(script, RMDIR_CMD " %s%s/%d\n",
 				  os_info.tablespaces[tblnum], old_cluster.tablespace_suffix,
diff --git a/contrib/pg_upgrade/function.c b/contrib/pg_upgrade/function.c
index 0f8008951ab..b154f033e6e 100644
--- a/contrib/pg_upgrade/function.c
+++ b/contrib/pg_upgrade/function.c
@@ -132,8 +132,7 @@ get_loadable_libraries(void)
 	int			totaltups;
 	int			dbnum;
 
-	ress = (PGresult **)
-		pg_malloc(old_cluster.dbarr.ndbs * sizeof(PGresult *));
+	ress = (PGresult **) pg_malloc(old_cluster.dbarr.ndbs * sizeof(PGresult *));
 	totaltups = 0;
 
 	/* Fetch all library names, removing duplicates within each DB */
diff --git a/contrib/pg_upgrade/relfilenode.c b/contrib/pg_upgrade/relfilenode.c
index 1aefd337f1f..ad893be1c7f 100644
--- a/contrib/pg_upgrade/relfilenode.c
+++ b/contrib/pg_upgrade/relfilenode.c
@@ -34,22 +34,30 @@ const char *
 transfer_all_new_dbs(DbInfoArr *old_db_arr,
 				   DbInfoArr *new_db_arr, char *old_pgdata, char *new_pgdata)
 {
-	int			dbnum;
+	int			old_dbnum, new_dbnum;
 	const char *msg = NULL;
 
 	prep_status("Restoring user relation files\n");
 
-	if (old_db_arr->ndbs != new_db_arr->ndbs)
-		pg_log(PG_FATAL, "old and new clusters have a different number of databases\n");
-
-	for (dbnum = 0; dbnum < old_db_arr->ndbs; dbnum++)
+	/* Scan the old cluster databases and transfer their files */
+	for (old_dbnum = new_dbnum = 0;
+		 old_dbnum < old_db_arr->ndbs && new_dbnum < new_db_arr->ndbs;
+		 old_dbnum++, new_dbnum++)
 	{
-		DbInfo	   *old_db = &old_db_arr->dbs[dbnum];
-		DbInfo	   *new_db = &new_db_arr->dbs[dbnum];
+		DbInfo	   *old_db = &old_db_arr->dbs[old_dbnum];
+		DbInfo	   *new_db = &new_db_arr->dbs[new_dbnum];
 		FileNameMap *mappings;
 		int			n_maps;
 		pageCnvCtx *pageConverter = NULL;
 
+		/*
+		 *	Advance past any databases that exist in the new cluster
+		 *	but not in the old, e.g. "postgres".
+		 */
+		while (strcmp(old_db->db_name, new_db->db_name) != 0 &&
+			   new_dbnum < new_db_arr->ndbs)
+			new_db = &new_db_arr->dbs[++new_dbnum];
+
 		if (strcmp(old_db->db_name, new_db->db_name) != 0)
 			pg_log(PG_FATAL, "old and new databases have different names: old \"%s\", new \"%s\"\n",
 				   old_db->db_name, new_db->db_name);
-- 
GitLab