Skip to content

Commit 2a55e71

Browse files
committed
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
1 parent 2a63434 commit 2a55e71

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

contrib/pg_upgrade/check.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ static void check_locale_and_encoding(ControlData *oldctrl,
2020
static bool equivalent_locale(int category, const char *loca, const char *locb);
2121
static bool equivalent_encoding(const char *chara, const char *charb);
2222
static void check_is_super_user(ClusterInfo *cluster);
23+
static void check_proper_datallowconn(ClusterInfo *cluster);
2324
static void check_for_prepared_transactions(ClusterInfo *cluster);
2425
static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster);
2526
static void check_for_reg_data_type_usage(ClusterInfo *cluster);
@@ -98,6 +99,7 @@ check_old_cluster(bool live_check, char **sequence_script_file_name)
9899
* Check for various failure cases
99100
*/
100101
check_is_super_user(&old_cluster);
102+
check_proper_datallowconn(&old_cluster);
101103
check_for_prepared_transactions(&old_cluster);
102104
check_for_reg_data_type_usage(&old_cluster);
103105
check_for_isn_and_int8_passing_mismatch(&old_cluster);
@@ -628,6 +630,58 @@ create_script_for_cluster_analyze(char **analyze_script_file_name)
628630
}
629631

630632

633+
static void
634+
check_proper_datallowconn(ClusterInfo *cluster)
635+
{
636+
int dbnum;
637+
PGconn *conn_template1;
638+
PGresult *dbres;
639+
int ntups;
640+
int i_datname;
641+
int i_datallowconn;
642+
643+
prep_status("Checking database connection settings");
644+
645+
conn_template1 = connectToServer(cluster, "template1");
646+
647+
/* get database names */
648+
dbres = executeQueryOrDie(conn_template1,
649+
"SELECT datname, datallowconn "
650+
"FROM pg_catalog.pg_database");
651+
652+
i_datname = PQfnumber(dbres, "datname");
653+
i_datallowconn = PQfnumber(dbres, "datallowconn");
654+
655+
ntups = PQntuples(dbres);
656+
for (dbnum = 0; dbnum < ntups; dbnum++)
657+
{
658+
char *datname = PQgetvalue(dbres, dbnum, i_datname);
659+
char *datallowconn = PQgetvalue(dbres, dbnum, i_datallowconn);
660+
661+
if (strcmp(datname, "template0") == 0)
662+
{
663+
/* avoid restore failure when pg_dumpall tries to create template0 */
664+
if (strcmp(datallowconn, "t") == 0)
665+
pg_log(PG_FATAL, "template0 must not allow connections, "
666+
"i.e. its pg_database.datallowconn must be false\n");
667+
}
668+
else
669+
{
670+
/* avoid datallowconn == false databases from being skipped on restore */
671+
if (strcmp(datallowconn, "f") == 0)
672+
pg_log(PG_FATAL, "All non-template0 databases must allow connections, "
673+
"i.e. their pg_database.datallowconn must be true\n");
674+
}
675+
}
676+
677+
PQclear(dbres);
678+
679+
PQfinish(conn_template1);
680+
681+
check_ok();
682+
}
683+
684+
631685
/*
632686
* create_script_for_old_cluster_deletion()
633687
*

0 commit comments

Comments
 (0)