From 573e446f6f5963a0edad575130743eb75887d087 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Wed, 19 May 2010 18:27:43 +0000
Subject: [PATCH] For pg_upgrade, update template0's datfrozenxid and its
 relfrozenxids to match the behavior of autovacuum, which does this as the xid
 advances even if autovacuum is turned off.

---
 contrib/pg_upgrade/pg_upgrade.c | 57 ++++++++++++++++++++++++---------
 1 file changed, 42 insertions(+), 15 deletions(-)

diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c
index fc692fc96a1..7d7abe6c23c 100644
--- a/contrib/pg_upgrade/pg_upgrade.c
+++ b/contrib/pg_upgrade/pg_upgrade.c
@@ -164,7 +164,10 @@ prepare_new_cluster(migratorContext *ctx)
 	check_ok(ctx);
 
 	/*
-	 * We do freeze after analyze so pg_statistic is also frozen
+	 * We do freeze after analyze so pg_statistic is also frozen.
+	 * template0 is not frozen here, but data rows were frozen by initdb,
+	 * and we set its datfrozenxid and relfrozenxids later to match the
+	 * new xid counter later.
 	 */
 	prep_status(ctx, "Freezing all rows on the new cluster");
 	exec_prog(ctx, true,
@@ -292,48 +295,72 @@ void
 set_frozenxids(migratorContext *ctx)
 {
 	int			dbnum;
-	PGconn	   *conn;
+	PGconn	   *conn, *conn_template1;
 	PGresult   *dbres;
 	int			ntups;
+	int			i_datname;
+	int			i_datallowconn;
 
 	prep_status(ctx, "Setting frozenxid counters in new cluster");
 
-	conn = connectToServer(ctx, "template1", CLUSTER_NEW);
+	conn_template1 = connectToServer(ctx, "template1", CLUSTER_NEW);
 
 	/* set pg_database.datfrozenxid */
-	PQclear(executeQueryOrDie(ctx, conn,
+	PQclear(executeQueryOrDie(ctx, conn_template1,
 							  "UPDATE pg_catalog.pg_database "
-							  "SET	datfrozenxid = '%u' "
-							  "WHERE datallowconn = true",
+							  "SET	datfrozenxid = '%u'",
 							  ctx->old.controldata.chkpnt_nxtxid));
 
 	/* get database names */
-	dbres = executeQueryOrDie(ctx, conn,
-							  "SELECT	datname "
-							  "FROM	pg_catalog.pg_database "
-							  "WHERE datallowconn = true");
+	dbres = executeQueryOrDie(ctx, conn_template1,
+							  "SELECT	datname, datallowconn "
+							  "FROM	pg_catalog.pg_database");
 
-	/* free dbres below */
-	PQfinish(conn);
+	i_datname = PQfnumber(dbres, "datname");
+	i_datallowconn = PQfnumber(dbres, "datallowconn");
 
 	ntups = PQntuples(dbres);
 	for (dbnum = 0; dbnum < ntups; dbnum++)
 	{
-		conn = connectToServer(ctx, PQgetvalue(dbres, dbnum, 0), CLUSTER_NEW);
+		char *datname = PQgetvalue(dbres, dbnum, i_datname);
+		char *datallowconn= PQgetvalue(dbres, dbnum, i_datallowconn);
+
+		/*
+		 *	We must update databases where datallowconn = false, e.g.
+		 *	template0, because autovacuum increments their datfrozenxids and
+		 *	relfrozenxids even if autovacuum is turned off, and even though
+		 *	all the data rows are already frozen  To enable this, we
+		 *	temporarily change datallowconn.
+		 */
+		if (strcmp(datallowconn, "f") == 0)
+			PQclear(executeQueryOrDie(ctx, conn_template1,
+								  "UPDATE pg_catalog.pg_database "
+								  "SET	datallowconn = true "
+								  "WHERE datname = '%s'", datname));
+
+		conn = connectToServer(ctx, datname, CLUSTER_NEW);
 
 		/* set pg_class.relfrozenxid */
 		PQclear(executeQueryOrDie(ctx, conn,
 								  "UPDATE	pg_catalog.pg_class "
 								  "SET	relfrozenxid = '%u' "
 		/* only heap and TOAST are vacuumed */
-								  "WHERE	relkind = 'r' OR "
-								  "		relkind = 't'",
+								  "WHERE	relkind IN ('r', 't')",
 								  ctx->old.controldata.chkpnt_nxtxid));
 		PQfinish(conn);
+
+		/* Reset datallowconn flag */
+		if (strcmp(datallowconn, "f") == 0)
+			PQclear(executeQueryOrDie(ctx, conn_template1,
+								  "UPDATE pg_catalog.pg_database "
+								  "SET	datallowconn = false "
+								  "WHERE datname = '%s'", datname));
 	}
 
 	PQclear(dbres);
 
+	PQfinish(conn_template1);
+
 	check_ok(ctx);
 }
 
-- 
GitLab