diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 28ff2f0979..1430894ad2 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -498,7 +498,7 @@ BootstrapModeMain(void) */ InitProcess(); - InitPostgres(NULL, InvalidOid, NULL, InvalidOid, NULL); + InitPostgres(NULL, InvalidOid, NULL, InvalidOid, NULL, false); /* Initialize stuff for bootstrap-file processing */ for (i = 0; i < MAXATTR; i++) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 702f8d8188..a52178f7d3 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -477,7 +477,7 @@ AutoVacLauncherMain(int argc, char *argv[]) InitProcess(); #endif - InitPostgres(NULL, InvalidOid, NULL, InvalidOid, NULL); + InitPostgres(NULL, InvalidOid, NULL, InvalidOid, NULL, false); SetProcessingMode(NormalProcessing); @@ -1679,7 +1679,7 @@ AutoVacWorkerMain(int argc, char *argv[]) * Note: if we have selected a just-deleted database (due to using * stale stats info), we'll fail and exit here. */ - InitPostgres(NULL, dbid, NULL, InvalidOid, dbname); + InitPostgres(NULL, dbid, NULL, InvalidOid, dbname, false); SetProcessingMode(NormalProcessing); set_ps_display(dbname, false); ereport(DEBUG1, diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index f3ddf828bb..1ded418960 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -434,6 +434,9 @@ static void StartAutovacuumWorker(void); static void MaybeStartWalReceiver(void); static void InitPostmasterDeathWatchHandle(void); +static void BackgroundWorkerInitializeConnectionByOidInternal(Oid dboid, Oid useroid, bool override_allow_connections); +static void BackgroundWorkerInitializeConnectionInternal(const char *dbname, const char *username, bool override_allow_connections); + /* * Archiver is allowed to start up at the current postmaster state? * @@ -5587,6 +5590,18 @@ MaxLivePostmasterChildren(void) void BackgroundWorkerInitializeConnection(const char *dbname, const char *username) { + BackgroundWorkerInitializeConnectionInternal(dbname, username, false); +} + +void +BackgroundWorkerInitializeConnectionOverride(const char *dbname, const char *username) +{ + BackgroundWorkerInitializeConnectionInternal(dbname, username, true); +} + +static void +BackgroundWorkerInitializeConnectionInternal(const char *dbname, const char *username, bool override_allow_connections) +{ BackgroundWorker *worker = MyBgworkerEntry; /* XXX is this the right errcode? */ @@ -5595,7 +5610,7 @@ BackgroundWorkerInitializeConnection(const char *dbname, const char *username) (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("database connection requirement not indicated during registration"))); - InitPostgres(dbname, InvalidOid, username, InvalidOid, NULL); + InitPostgres(dbname, InvalidOid, username, InvalidOid, NULL, override_allow_connections); /* it had better not gotten out of "init" mode yet */ if (!IsInitProcessingMode()) @@ -5610,6 +5625,18 @@ BackgroundWorkerInitializeConnection(const char *dbname, const char *username) void BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid) { + BackgroundWorkerInitializeConnectionByOidInternal(dboid, useroid, false); +} + +void +BackgroundWorkerInitializeConnectionByOidOverride(Oid dboid, Oid useroid) +{ + BackgroundWorkerInitializeConnectionByOidInternal(dboid, useroid, true); +} + +void +BackgroundWorkerInitializeConnectionByOidInternal(Oid dboid, Oid useroid, bool override_allow_connections) +{ BackgroundWorker *worker = MyBgworkerEntry; /* XXX is this the right errcode? */ @@ -5618,7 +5645,7 @@ BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid) (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("database connection requirement not indicated during registration"))); - InitPostgres(NULL, dboid, NULL, useroid, NULL); + InitPostgres(NULL, dboid, NULL, useroid, NULL, override_allow_connections); /* it had better not gotten out of "init" mode yet */ if (!IsInitProcessingMode()) diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 6dc2095b9a..6b5a32b25b 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -3774,7 +3774,7 @@ PostgresMain(int argc, char *argv[], * it inside InitPostgres() instead. In particular, anything that * involves database access should be there, not here. */ - InitPostgres(dbname, InvalidOid, username, InvalidOid, NULL); + InitPostgres(dbname, InvalidOid, username, InvalidOid, NULL, false); /* * If the PostmasterContext is still around, recycle the space; we don't diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 484628987f..83640e3159 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -66,7 +66,7 @@ static HeapTuple GetDatabaseTuple(const char *dbname); static HeapTuple GetDatabaseTupleByOid(Oid dboid); static void PerformAuthentication(Port *port); -static void CheckMyDatabase(const char *name, bool am_superuser); +static void CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connections); static void InitCommunication(void); static void ShutdownPostgres(int code, Datum arg); static void StatementTimeoutHandler(void); @@ -290,7 +290,7 @@ PerformAuthentication(Port *port) * CheckMyDatabase -- fetch information from the pg_database entry for our DB */ static void -CheckMyDatabase(const char *name, bool am_superuser) +CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connections) { HeapTuple tup; Form_pg_database dbform; @@ -326,7 +326,7 @@ CheckMyDatabase(const char *name, bool am_superuser) /* * Check that the database is currently allowing connections. */ - if (!dbform->datallowconn) + if (!dbform->datallowconn && !override_allow_connections) ereport(FATAL, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("database \"%s\" is not currently accepting connections", @@ -563,7 +563,7 @@ BaseInit(void) */ void InitPostgres(const char *in_dbname, Oid dboid, const char *username, - Oid useroid, char *out_dbname) + Oid useroid, char *out_dbname, bool override_allow_connections) { bool bootstrap = IsBootstrapProcessingMode(); bool am_superuser; @@ -1006,7 +1006,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, * user is a superuser, so the above stuff has to happen first.) */ if (!bootstrap) - CheckMyDatabase(dbname, am_superuser); + CheckMyDatabase(dbname, am_superuser, override_allow_connections); /* * Now process any command-line switches and any additional GUC variable diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index a4574cd533..d06f71aceb 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -419,7 +419,7 @@ extern AuxProcType MyAuxProcType; extern void pg_split_opts(char **argv, int *argcp, const char *optstr); extern void InitializeMaxBackends(void); extern void InitPostgres(const char *in_dbname, Oid dboid, const char *username, - Oid useroid, char *out_dbname); + Oid useroid, char *out_dbname, bool override_allow_connections); extern void BaseInit(void); /* in utils/init/miscinit.c */ diff --git a/src/include/postmaster/bgworker.h b/src/include/postmaster/bgworker.h index 0c04529f47..83e15c1311 100644 --- a/src/include/postmaster/bgworker.h +++ b/src/include/postmaster/bgworker.h @@ -141,9 +141,11 @@ extern PGDLLIMPORT BackgroundWorker *MyBgworkerEntry; * only shared catalogs can be accessed. */ extern void BackgroundWorkerInitializeConnection(const char *dbname, const char *username); +extern void BackgroundWorkerInitializeConnectionOverride(const char *dbname, const char *username); /* Just like the above, but specifying database and user by OID. */ extern void BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid); +extern void BackgroundWorkerInitializeConnectionByOidOverride(Oid dboid, Oid useroid); /* Block/unblock signals in a background worker process */ extern void BackgroundWorkerBlockSignals(void);