Add new function BackgroundWorkerInitializeConnectionByOid.
Sometimes it's useful for a background worker to be able to initialize its database connection by OID rather than by name, so provide a way to do that.
This commit is contained in:
parent
2488eff889
commit
5d2f957f3f
|
@ -146,14 +146,17 @@ typedef struct BackgroundWorker
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>Once running, the process can connect to a database by calling
|
<para>Once running, the process can connect to a database by calling
|
||||||
<function>BackgroundWorkerInitializeConnection(<parameter>char *dbname</parameter>, <parameter>char *username</parameter>)</function>.
|
<function>BackgroundWorkerInitializeConnection(<parameter>char *dbname</parameter>, <parameter>char *username</parameter>)</function> or
|
||||||
|
<function>BackgroundWorkerInitializeConnectionByOid(<parameter>Oid dboid</parameter>, <parameter>Oid useroid</parameter>)</function>.
|
||||||
This allows the process to run transactions and queries using the
|
This allows the process to run transactions and queries using the
|
||||||
<literal>SPI</literal> interface. If <varname>dbname</> is NULL,
|
<literal>SPI</literal> interface. If <varname>dbname</> is NULL or
|
||||||
the session is not connected to any particular database, but shared catalogs
|
<varname>dboid</> is <literal>InvalidOid</>, the session is not connected
|
||||||
can be accessed. If <varname>username</> is NULL, the process will run as
|
to any particular database, but shared catalogs can be accessed.
|
||||||
the superuser created during <command>initdb</>.
|
If <varname>username</> is NULL or <varname>useroid</> is
|
||||||
BackgroundWorkerInitializeConnection can only be called once per background
|
<literal>InvalidOid</>, the process will run as the superuser created
|
||||||
process, it is not possible to switch databases.
|
during <command>initdb</>.
|
||||||
|
A background worker can only call one of these two functions, and only
|
||||||
|
once. It is not possible to switch databases.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
|
|
@ -467,7 +467,7 @@ BootstrapModeMain(void)
|
||||||
*/
|
*/
|
||||||
InitProcess();
|
InitProcess();
|
||||||
|
|
||||||
InitPostgres(NULL, InvalidOid, NULL, NULL);
|
InitPostgres(NULL, InvalidOid, NULL, InvalidOid, NULL);
|
||||||
|
|
||||||
/* Initialize stuff for bootstrap-file processing */
|
/* Initialize stuff for bootstrap-file processing */
|
||||||
for (i = 0; i < MAXATTR; i++)
|
for (i = 0; i < MAXATTR; i++)
|
||||||
|
|
|
@ -450,7 +450,7 @@ AutoVacLauncherMain(int argc, char *argv[])
|
||||||
InitProcess();
|
InitProcess();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
InitPostgres(NULL, InvalidOid, NULL, NULL);
|
InitPostgres(NULL, InvalidOid, NULL, InvalidOid, NULL);
|
||||||
|
|
||||||
SetProcessingMode(NormalProcessing);
|
SetProcessingMode(NormalProcessing);
|
||||||
|
|
||||||
|
@ -1620,7 +1620,7 @@ AutoVacWorkerMain(int argc, char *argv[])
|
||||||
* Note: if we have selected a just-deleted database (due to using
|
* Note: if we have selected a just-deleted database (due to using
|
||||||
* stale stats info), we'll fail and exit here.
|
* stale stats info), we'll fail and exit here.
|
||||||
*/
|
*/
|
||||||
InitPostgres(NULL, dbid, NULL, dbname);
|
InitPostgres(NULL, dbid, NULL, InvalidOid, dbname);
|
||||||
SetProcessingMode(NormalProcessing);
|
SetProcessingMode(NormalProcessing);
|
||||||
set_ps_display(dbname, false);
|
set_ps_display(dbname, false);
|
||||||
ereport(DEBUG1,
|
ereport(DEBUG1,
|
||||||
|
|
|
@ -5313,7 +5313,30 @@ BackgroundWorkerInitializeConnection(char *dbname, char *username)
|
||||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||||
errmsg("database connection requirement not indicated during registration")));
|
errmsg("database connection requirement not indicated during registration")));
|
||||||
|
|
||||||
InitPostgres(dbname, InvalidOid, username, NULL);
|
InitPostgres(dbname, InvalidOid, username, InvalidOid, NULL);
|
||||||
|
|
||||||
|
/* it had better not gotten out of "init" mode yet */
|
||||||
|
if (!IsInitProcessingMode())
|
||||||
|
ereport(ERROR,
|
||||||
|
(errmsg("invalid processing mode in background worker")));
|
||||||
|
SetProcessingMode(NormalProcessing);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Connect background worker to a database using OIDs.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid)
|
||||||
|
{
|
||||||
|
BackgroundWorker *worker = MyBgworkerEntry;
|
||||||
|
|
||||||
|
/* XXX is this the right errcode? */
|
||||||
|
if (!(worker->bgw_flags & BGWORKER_BACKEND_DATABASE_CONNECTION))
|
||||||
|
ereport(FATAL,
|
||||||
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||||
|
errmsg("database connection requirement not indicated during registration")));
|
||||||
|
|
||||||
|
InitPostgres(NULL, dboid, NULL, useroid, NULL);
|
||||||
|
|
||||||
/* it had better not gotten out of "init" mode yet */
|
/* it had better not gotten out of "init" mode yet */
|
||||||
if (!IsInitProcessingMode())
|
if (!IsInitProcessingMode())
|
||||||
|
|
|
@ -3714,7 +3714,7 @@ PostgresMain(int argc, char *argv[],
|
||||||
* it inside InitPostgres() instead. In particular, anything that
|
* it inside InitPostgres() instead. In particular, anything that
|
||||||
* involves database access should be there, not here.
|
* involves database access should be there, not here.
|
||||||
*/
|
*/
|
||||||
InitPostgres(dbname, InvalidOid, username, NULL);
|
InitPostgres(dbname, InvalidOid, username, InvalidOid, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the PostmasterContext is still around, recycle the space; we don't
|
* If the PostmasterContext is still around, recycle the space; we don't
|
||||||
|
|
|
@ -453,11 +453,10 @@ has_rolreplication(Oid roleid)
|
||||||
* Initialize user identity during normal backend startup
|
* Initialize user identity during normal backend startup
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
InitializeSessionUserId(const char *rolename)
|
InitializeSessionUserId(const char *rolename, Oid roleid)
|
||||||
{
|
{
|
||||||
HeapTuple roleTup;
|
HeapTuple roleTup;
|
||||||
Form_pg_authid rform;
|
Form_pg_authid rform;
|
||||||
Oid roleid;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Don't do scans if we're bootstrapping, none of the system catalogs
|
* Don't do scans if we're bootstrapping, none of the system catalogs
|
||||||
|
@ -468,7 +467,10 @@ InitializeSessionUserId(const char *rolename)
|
||||||
/* call only once */
|
/* call only once */
|
||||||
AssertState(!OidIsValid(AuthenticatedUserId));
|
AssertState(!OidIsValid(AuthenticatedUserId));
|
||||||
|
|
||||||
roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(rolename));
|
if (rolename != NULL)
|
||||||
|
roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(rolename));
|
||||||
|
else
|
||||||
|
roleTup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
|
||||||
if (!HeapTupleIsValid(roleTup))
|
if (!HeapTupleIsValid(roleTup))
|
||||||
ereport(FATAL,
|
ereport(FATAL,
|
||||||
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
|
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
|
||||||
|
|
|
@ -523,6 +523,9 @@ BaseInit(void)
|
||||||
* name can be returned to the caller in out_dbname. If out_dbname isn't
|
* name can be returned to the caller in out_dbname. If out_dbname isn't
|
||||||
* NULL, it must point to a buffer of size NAMEDATALEN.
|
* NULL, it must point to a buffer of size NAMEDATALEN.
|
||||||
*
|
*
|
||||||
|
* Similarly, the username can be passed by name, using the username parameter,
|
||||||
|
* or by OID using the useroid parameter.
|
||||||
|
*
|
||||||
* In bootstrap mode no parameters are used. The autovacuum launcher process
|
* In bootstrap mode no parameters are used. The autovacuum launcher process
|
||||||
* doesn't use any parameters either, because it only goes far enough to be
|
* doesn't use any parameters either, because it only goes far enough to be
|
||||||
* able to read pg_database; it doesn't connect to any particular database.
|
* able to read pg_database; it doesn't connect to any particular database.
|
||||||
|
@ -537,7 +540,7 @@ BaseInit(void)
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
InitPostgres(const char *in_dbname, Oid dboid, const char *username,
|
InitPostgres(const char *in_dbname, Oid dboid, const char *username,
|
||||||
char *out_dbname)
|
Oid useroid, char *out_dbname)
|
||||||
{
|
{
|
||||||
bool bootstrap = IsBootstrapProcessingMode();
|
bool bootstrap = IsBootstrapProcessingMode();
|
||||||
bool am_superuser;
|
bool am_superuser;
|
||||||
|
@ -692,18 +695,18 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
|
||||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||||
errmsg("no roles are defined in this database system"),
|
errmsg("no roles are defined in this database system"),
|
||||||
errhint("You should immediately run CREATE USER \"%s\" SUPERUSER;.",
|
errhint("You should immediately run CREATE USER \"%s\" SUPERUSER;.",
|
||||||
username)));
|
username != NULL ? username : "postgres")));
|
||||||
}
|
}
|
||||||
else if (IsBackgroundWorker)
|
else if (IsBackgroundWorker)
|
||||||
{
|
{
|
||||||
if (username == NULL)
|
if (username == NULL && !OidIsValid(useroid))
|
||||||
{
|
{
|
||||||
InitializeSessionUserIdStandalone();
|
InitializeSessionUserIdStandalone();
|
||||||
am_superuser = true;
|
am_superuser = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
InitializeSessionUserId(username);
|
InitializeSessionUserId(username, useroid);
|
||||||
am_superuser = superuser();
|
am_superuser = superuser();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -712,7 +715,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
|
||||||
/* normal multiuser case */
|
/* normal multiuser case */
|
||||||
Assert(MyProcPort != NULL);
|
Assert(MyProcPort != NULL);
|
||||||
PerformAuthentication(MyProcPort);
|
PerformAuthentication(MyProcPort);
|
||||||
InitializeSessionUserId(username);
|
InitializeSessionUserId(username, useroid);
|
||||||
am_superuser = superuser();
|
am_superuser = superuser();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -307,7 +307,7 @@ extern bool InLocalUserIdChange(void);
|
||||||
extern bool InSecurityRestrictedOperation(void);
|
extern bool InSecurityRestrictedOperation(void);
|
||||||
extern void GetUserIdAndContext(Oid *userid, bool *sec_def_context);
|
extern void GetUserIdAndContext(Oid *userid, bool *sec_def_context);
|
||||||
extern void SetUserIdAndContext(Oid userid, bool sec_def_context);
|
extern void SetUserIdAndContext(Oid userid, bool sec_def_context);
|
||||||
extern void InitializeSessionUserId(const char *rolename);
|
extern void InitializeSessionUserId(const char *rolename, Oid useroid);
|
||||||
extern void InitializeSessionUserIdStandalone(void);
|
extern void InitializeSessionUserIdStandalone(void);
|
||||||
extern void SetSessionAuthorization(Oid userid, bool is_superuser);
|
extern void SetSessionAuthorization(Oid userid, bool is_superuser);
|
||||||
extern Oid GetCurrentRoleId(void);
|
extern Oid GetCurrentRoleId(void);
|
||||||
|
@ -411,7 +411,7 @@ extern AuxProcType MyAuxProcType;
|
||||||
extern void pg_split_opts(char **argv, int *argcp, char *optstr);
|
extern void pg_split_opts(char **argv, int *argcp, char *optstr);
|
||||||
extern void InitializeMaxBackends(void);
|
extern void InitializeMaxBackends(void);
|
||||||
extern void InitPostgres(const char *in_dbname, Oid dboid, const char *username,
|
extern void InitPostgres(const char *in_dbname, Oid dboid, const char *username,
|
||||||
char *out_dbname);
|
Oid useroid, char *out_dbname);
|
||||||
extern void BaseInit(void);
|
extern void BaseInit(void);
|
||||||
|
|
||||||
/* in utils/init/miscinit.c */
|
/* in utils/init/miscinit.c */
|
||||||
|
|
|
@ -130,6 +130,9 @@ extern PGDLLIMPORT BackgroundWorker *MyBgworkerEntry;
|
||||||
*/
|
*/
|
||||||
extern void BackgroundWorkerInitializeConnection(char *dbname, char *username);
|
extern void BackgroundWorkerInitializeConnection(char *dbname, char *username);
|
||||||
|
|
||||||
|
/* Just like the above, but specifying database and user by OID. */
|
||||||
|
extern void BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid);
|
||||||
|
|
||||||
/* Block/unblock signals in a background worker process */
|
/* Block/unblock signals in a background worker process */
|
||||||
extern void BackgroundWorkerBlockSignals(void);
|
extern void BackgroundWorkerBlockSignals(void);
|
||||||
extern void BackgroundWorkerUnblockSignals(void);
|
extern void BackgroundWorkerUnblockSignals(void);
|
||||||
|
|
Loading…
Reference in New Issue