Index: contrib/pg_upgrade/pg_upgrade.c
===================================================================
RCS file: /cvsroot/pgsql/contrib/pg_upgrade/pg_upgrade.c,v
retrieving revision 1.3
diff -c -c -r1.3 pg_upgrade.c
*** contrib/pg_upgrade/pg_upgrade.c	18 May 2010 18:40:51 -0000	1.3
--- contrib/pg_upgrade/pg_upgrade.c	19 May 2010 18:20:03 -0000
***************
*** 164,170 ****
  	check_ok(ctx);
  
  	/*
! 	 * We do freeze after analyze so pg_statistic is also frozen
  	 */
  	prep_status(ctx, "Freezing all rows on the new cluster");
  	exec_prog(ctx, true,
--- 164,173 ----
  	check_ok(ctx);
  
  	/*
! 	 * 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,339 ****
  set_frozenxids(migratorContext *ctx)
  {
  	int			dbnum;
! 	PGconn	   *conn;
  	PGresult   *dbres;
  	int			ntups;
  
  	prep_status(ctx, "Setting frozenxid counters in new cluster");
  
! 	conn = connectToServer(ctx, "template1", CLUSTER_NEW);
  
  	/* set pg_database.datfrozenxid */
! 	PQclear(executeQueryOrDie(ctx, conn,
  							  "UPDATE pg_catalog.pg_database "
! 							  "SET	datfrozenxid = '%u' "
! 							  "WHERE datallowconn = true",
  							  ctx->old.controldata.chkpnt_nxtxid));
  
  	/* get database names */
! 	dbres = executeQueryOrDie(ctx, conn,
! 							  "SELECT	datname "
! 							  "FROM	pg_catalog.pg_database "
! 							  "WHERE datallowconn = true");
  
! 	/* free dbres below */
! 	PQfinish(conn);
  
  	ntups = PQntuples(dbres);
  	for (dbnum = 0; dbnum < ntups; dbnum++)
  	{
! 		conn = connectToServer(ctx, PQgetvalue(dbres, dbnum, 0), 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'",
  								  ctx->old.controldata.chkpnt_nxtxid));
  		PQfinish(conn);
  	}
  
  	PQclear(dbres);
  
  	check_ok(ctx);
  }
  
--- 295,366 ----
  set_frozenxids(migratorContext *ctx)
  {
  	int			dbnum;
! 	PGconn	   *conn, *conn_template1;
  	PGresult   *dbres;
  	int			ntups;
+ 	int			i_datname;
+ 	int			i_datallowconn;
  
  	prep_status(ctx, "Setting frozenxid counters in new cluster");
  
! 	conn_template1 = connectToServer(ctx, "template1", CLUSTER_NEW);
  
  	/* set pg_database.datfrozenxid */
! 	PQclear(executeQueryOrDie(ctx, conn_template1,
  							  "UPDATE pg_catalog.pg_database "
! 							  "SET	datfrozenxid = '%u'",
  							  ctx->old.controldata.chkpnt_nxtxid));
  
  	/* get database names */
! 	dbres = executeQueryOrDie(ctx, conn_template1,
! 							  "SELECT	datname, datallowconn "
! 							  "FROM	pg_catalog.pg_database");
  
! 	i_datname = PQfnumber(dbres, "datname");
! 	i_datallowconn = PQfnumber(dbres, "datallowconn");
  
  	ntups = PQntuples(dbres);
  	for (dbnum = 0; dbnum < ntups; dbnum++)
  	{
! 		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 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);
  }
  
