From 444bf4eb53c2fcb760e529004d31a68a1370c19f Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Wed, 12 Jul 2023 11:45:14 +0200
Subject: [PATCH v4 3/3] pg_upgrade: Extend check for database not allowing
 connections

Rather than failing to connect, also check for datconnlimit being
-2 indicating that the database is invalid and needs to be dropped
before the upgrade.
---
 src/bin/pg_upgrade/check.c             | 26 ++++++++++++++++++++------
 src/bin/pg_upgrade/t/002_pg_upgrade.pl |  5 +----
 2 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c
index 64024e3b9e..5255dee10c 100644
--- a/src/bin/pg_upgrade/check.c
+++ b/src/bin/pg_upgrade/check.c
@@ -595,6 +595,7 @@ check_proper_datallowconn(ClusterInfo *cluster)
 	int			ntups;
 	int			i_datname;
 	int			i_datallowconn;
+	int			i_datconnlimit;
 	FILE	   *script = NULL;
 	char		output_path[MAXPGPATH];
 
@@ -602,23 +603,25 @@ check_proper_datallowconn(ClusterInfo *cluster)
 
 	snprintf(output_path, sizeof(output_path), "%s/%s",
 			 log_opts.basedir,
-			 "databases_with_datallowconn_false.txt");
+			 "databases_disallowing_connections.txt");
 
 	conn_template1 = connectToServer(cluster, "template1");
 
 	/* get database names */
 	dbres = executeQueryOrDie(conn_template1,
-							  "SELECT	datname, datallowconn "
+							  "SELECT	datname, datallowconn, datconnlimit "
 							  "FROM	pg_catalog.pg_database");
 
 	i_datname = PQfnumber(dbres, "datname");
 	i_datallowconn = PQfnumber(dbres, "datallowconn");
+	i_datconnlimit = PQfnumber(dbres, "datconnlimit");
 
 	ntups = PQntuples(dbres);
 	for (dbnum = 0; dbnum < ntups; dbnum++)
 	{
 		char	   *datname = PQgetvalue(dbres, dbnum, i_datname);
 		char	   *datallowconn = PQgetvalue(dbres, dbnum, i_datallowconn);
+		char	   *datconnlimit = PQgetvalue(dbres, dbnum, i_datconnlimit);
 
 		if (strcmp(datname, "template0") == 0)
 		{
@@ -629,6 +632,15 @@ check_proper_datallowconn(ClusterInfo *cluster)
 		}
 		else
 		{
+			if (strcmp(datconnlimit, "-2") == 0)
+			{
+				if (script == NULL && (script = fopen_priv(output_path, "w")) == NULL)
+					pg_fatal("could not open file \"%s\": %s",
+							 output_path, strerror(errno));
+
+				fprintf(script, "invalid database: %s\n", datname);
+			}
+
 			/*
 			 * avoid datallowconn == false databases from being skipped on
 			 * restore
@@ -639,7 +651,7 @@ check_proper_datallowconn(ClusterInfo *cluster)
 					pg_fatal("could not open file \"%s\": %s",
 							 output_path, strerror(errno));
 
-				fprintf(script, "%s\n", datname);
+				fprintf(script, "connections not allowed: %s\n", datname);
 			}
 		}
 	}
@@ -653,9 +665,11 @@ check_proper_datallowconn(ClusterInfo *cluster)
 		fclose(script);
 		pg_log(PG_REPORT, "fatal");
 		pg_fatal("All non-template0 databases must allow connections, i.e. their\n"
-				 "pg_database.datallowconn must be true.  Your installation contains\n"
-				 "non-template0 databases with their pg_database.datallowconn set to\n"
-				 "false.  Consider allowing connection for all non-template0 databases\n"
+				 "pg_database.datallowconn must be true and they must not be marked\n"
+				 "as invalid, pg_database.datconnlimit must not be -2.\n"
+				 "Your installation contains non-template0 databases with their\n"
+				 "pg_database.datallowconn set to false or pg_database.datconnlimit to -2.\n"
+				 "Consider allowing connection for all non-template0 databases\n"
 				 "or drop the databases which do not allow connections.  A list of\n"
 				 "databases with the problem is in the file:\n"
 				 "    %s", output_path);
diff --git a/src/bin/pg_upgrade/t/002_pg_upgrade.pl b/src/bin/pg_upgrade/t/002_pg_upgrade.pl
index a5688a1cf2..41ad310434 100644
--- a/src/bin/pg_upgrade/t/002_pg_upgrade.pl
+++ b/src/bin/pg_upgrade/t/002_pg_upgrade.pl
@@ -352,7 +352,7 @@ ok(-d $newnode->data_dir . "/pg_upgrade_output.d",
 rmtree($newnode->data_dir . "/pg_upgrade_output.d");
 
 # Check that pg_upgrade aborts when encountering an invalid database
-command_checks_all(
+command_fails(
 	[
 		'pg_upgrade', '--no-sync', '-d', $oldnode->data_dir,
 		'-D', $newnode->data_dir, '-b', $oldbindir,
@@ -360,9 +360,6 @@ command_checks_all(
 		'-p', $oldnode->port, '-P', $newnode->port,
 		$mode, '--check',
 	],
-	1,
-	[qr/invalid/], # pg_upgrade prints errors on stdout :(
-	[qr//],
 	'invalid database causes failure');
 rmtree($newnode->data_dir . "/pg_upgrade_output.d");
 
-- 
2.32.1 (Apple Git-133)

