From: Bruce Momjian Date: Sat, 16 May 2015 04:10:03 +0000 (-0400) Subject: pg_upgrade: only allow template0 to be non-connectable X-Git-Tag: REL9_0_20~17 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2194aa92b7a65561c109875d8b904198c3cd0743;p=postgresql pg_upgrade: only allow template0 to be non-connectable This patch causes pg_upgrade to error out during its check phase if: (1) template0 is marked connectable or (2) any other database is marked non-connectable This is done because, in the first case, pg_upgrade would fail because the pg_dumpall --globals restore would fail, and in the second case, the database would not be restored, leading to data loss. Report by Matt Landry (1), Stephen Frost (2) Backpatch through 9.0 --- diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c index 05c46a5ec7..dc737efff8 100644 --- a/contrib/pg_upgrade/check.c +++ b/contrib/pg_upgrade/check.c @@ -14,6 +14,7 @@ static void set_locale_and_encoding(migratorContext *ctx, Cluster whichCluster); static void check_new_db_is_empty(migratorContext *ctx); static void check_locale_and_encoding(migratorContext *ctx, ControlData *oldctrl, ControlData *newctrl); +static void check_proper_datallowconn(migratorContext *ctx, Cluster whichCluster); static void check_for_isn_and_int8_passing_mismatch(migratorContext *ctx, Cluster whichCluster); static void check_for_reg_data_type_usage(migratorContext *ctx, Cluster whichCluster); @@ -94,6 +95,7 @@ check_old_cluster(migratorContext *ctx, bool live_check, * Check for various failure cases */ + check_proper_datallowconn(ctx, CLUSTER_OLD); check_for_reg_data_type_usage(ctx, CLUSTER_OLD); check_for_isn_and_int8_passing_mismatch(ctx, CLUSTER_OLD); @@ -485,6 +487,58 @@ create_script_for_old_cluster_deletion(migratorContext *ctx, } +static void +check_proper_datallowconn(migratorContext *ctx, Cluster whichCluster) +{ + int dbnum; + PGconn *conn_template1; + PGresult *dbres; + int ntups; + int i_datname; + int i_datallowconn; + + prep_status(ctx, "Checking database connection settings"); + + conn_template1 = connectToServer(ctx, "template1", whichCluster); + + /* 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); + + if (strcmp(datname, "template0") == 0) + { + /* avoid restore failure when pg_dumpall tries to create template0 */ + if (strcmp(datallowconn, "t") == 0) + pg_log(ctx, PG_FATAL, "template0 must not allow connections, " + "i.e. its pg_database.datallowconn must be false\n"); + } + else + { + /* avoid datallowconn == false databases from being skipped on restore */ + if (strcmp(datallowconn, "f") == 0) + pg_log(ctx, PG_FATAL, "All non-template0 databases must allow connections, " + "i.e. their pg_database.datallowconn must be true\n"); + } + } + + PQclear(dbres); + + PQfinish(conn_template1); + + check_ok(ctx); +} + + /* * check_for_isn_and_int8_passing_mismatch() *