Skip to content

Commit 5d2f957

Browse files
committed
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.
1 parent 2488eff commit 5d2f957

File tree

9 files changed

+56
-22
lines changed

9 files changed

+56
-22
lines changed

doc/src/sgml/bgworker.sgml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -146,14 +146,17 @@ typedef struct BackgroundWorker
146146
</para>
147147

148148
<para>Once running, the process can connect to a database by calling
149-
<function>BackgroundWorkerInitializeConnection(<parameter>char *dbname</parameter>, <parameter>char *username</parameter>)</function>.
149+
<function>BackgroundWorkerInitializeConnection(<parameter>char *dbname</parameter>, <parameter>char *username</parameter>)</function> or
150+
<function>BackgroundWorkerInitializeConnectionByOid(<parameter>Oid dboid</parameter>, <parameter>Oid useroid</parameter>)</function>.
150151
This allows the process to run transactions and queries using the
151-
<literal>SPI</literal> interface. If <varname>dbname</> is NULL,
152-
the session is not connected to any particular database, but shared catalogs
153-
can be accessed. If <varname>username</> is NULL, the process will run as
154-
the superuser created during <command>initdb</>.
155-
BackgroundWorkerInitializeConnection can only be called once per background
156-
process, it is not possible to switch databases.
152+
<literal>SPI</literal> interface. If <varname>dbname</> is NULL or
153+
<varname>dboid</> is <literal>InvalidOid</>, the session is not connected
154+
to any particular database, but shared catalogs can be accessed.
155+
If <varname>username</> is NULL or <varname>useroid</> is
156+
<literal>InvalidOid</>, the process will run as the superuser created
157+
during <command>initdb</>.
158+
A background worker can only call one of these two functions, and only
159+
once. It is not possible to switch databases.
157160
</para>
158161

159162
<para>

src/backend/bootstrap/bootstrap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ BootstrapModeMain(void)
467467
*/
468468
InitProcess();
469469

470-
InitPostgres(NULL, InvalidOid, NULL, NULL);
470+
InitPostgres(NULL, InvalidOid, NULL, InvalidOid, NULL);
471471

472472
/* Initialize stuff for bootstrap-file processing */
473473
for (i = 0; i < MAXATTR; i++)

src/backend/postmaster/autovacuum.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ AutoVacLauncherMain(int argc, char *argv[])
450450
InitProcess();
451451
#endif
452452

453-
InitPostgres(NULL, InvalidOid, NULL, NULL);
453+
InitPostgres(NULL, InvalidOid, NULL, InvalidOid, NULL);
454454

455455
SetProcessingMode(NormalProcessing);
456456

@@ -1620,7 +1620,7 @@ AutoVacWorkerMain(int argc, char *argv[])
16201620
* Note: if we have selected a just-deleted database (due to using
16211621
* stale stats info), we'll fail and exit here.
16221622
*/
1623-
InitPostgres(NULL, dbid, NULL, dbname);
1623+
InitPostgres(NULL, dbid, NULL, InvalidOid, dbname);
16241624
SetProcessingMode(NormalProcessing);
16251625
set_ps_display(dbname, false);
16261626
ereport(DEBUG1,

src/backend/postmaster/postmaster.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5313,7 +5313,30 @@ BackgroundWorkerInitializeConnection(char *dbname, char *username)
53135313
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
53145314
errmsg("database connection requirement not indicated during registration")));
53155315

5316-
InitPostgres(dbname, InvalidOid, username, NULL);
5316+
InitPostgres(dbname, InvalidOid, username, InvalidOid, NULL);
5317+
5318+
/* it had better not gotten out of "init" mode yet */
5319+
if (!IsInitProcessingMode())
5320+
ereport(ERROR,
5321+
(errmsg("invalid processing mode in background worker")));
5322+
SetProcessingMode(NormalProcessing);
5323+
}
5324+
5325+
/*
5326+
* Connect background worker to a database using OIDs.
5327+
*/
5328+
void
5329+
BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid)
5330+
{
5331+
BackgroundWorker *worker = MyBgworkerEntry;
5332+
5333+
/* XXX is this the right errcode? */
5334+
if (!(worker->bgw_flags & BGWORKER_BACKEND_DATABASE_CONNECTION))
5335+
ereport(FATAL,
5336+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5337+
errmsg("database connection requirement not indicated during registration")));
5338+
5339+
InitPostgres(NULL, dboid, NULL, useroid, NULL);
53175340

53185341
/* it had better not gotten out of "init" mode yet */
53195342
if (!IsInitProcessingMode())

src/backend/tcop/postgres.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3714,7 +3714,7 @@ PostgresMain(int argc, char *argv[],
37143714
* it inside InitPostgres() instead. In particular, anything that
37153715
* involves database access should be there, not here.
37163716
*/
3717-
InitPostgres(dbname, InvalidOid, username, NULL);
3717+
InitPostgres(dbname, InvalidOid, username, InvalidOid, NULL);
37183718

37193719
/*
37203720
* If the PostmasterContext is still around, recycle the space; we don't

src/backend/utils/init/miscinit.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -453,11 +453,10 @@ has_rolreplication(Oid roleid)
453453
* Initialize user identity during normal backend startup
454454
*/
455455
void
456-
InitializeSessionUserId(const char *rolename)
456+
InitializeSessionUserId(const char *rolename, Oid roleid)
457457
{
458458
HeapTuple roleTup;
459459
Form_pg_authid rform;
460-
Oid roleid;
461460

462461
/*
463462
* Don't do scans if we're bootstrapping, none of the system catalogs
@@ -468,7 +467,10 @@ InitializeSessionUserId(const char *rolename)
468467
/* call only once */
469468
AssertState(!OidIsValid(AuthenticatedUserId));
470469

471-
roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(rolename));
470+
if (rolename != NULL)
471+
roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(rolename));
472+
else
473+
roleTup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
472474
if (!HeapTupleIsValid(roleTup))
473475
ereport(FATAL,
474476
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),

src/backend/utils/init/postinit.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,9 @@ BaseInit(void)
523523
* name can be returned to the caller in out_dbname. If out_dbname isn't
524524
* NULL, it must point to a buffer of size NAMEDATALEN.
525525
*
526+
* Similarly, the username can be passed by name, using the username parameter,
527+
* or by OID using the useroid parameter.
528+
*
526529
* In bootstrap mode no parameters are used. The autovacuum launcher process
527530
* doesn't use any parameters either, because it only goes far enough to be
528531
* able to read pg_database; it doesn't connect to any particular database.
@@ -537,7 +540,7 @@ BaseInit(void)
537540
*/
538541
void
539542
InitPostgres(const char *in_dbname, Oid dboid, const char *username,
540-
char *out_dbname)
543+
Oid useroid, char *out_dbname)
541544
{
542545
bool bootstrap = IsBootstrapProcessingMode();
543546
bool am_superuser;
@@ -692,18 +695,18 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
692695
(errcode(ERRCODE_UNDEFINED_OBJECT),
693696
errmsg("no roles are defined in this database system"),
694697
errhint("You should immediately run CREATE USER \"%s\" SUPERUSER;.",
695-
username)));
698+
username != NULL ? username : "postgres")));
696699
}
697700
else if (IsBackgroundWorker)
698701
{
699-
if (username == NULL)
702+
if (username == NULL && !OidIsValid(useroid))
700703
{
701704
InitializeSessionUserIdStandalone();
702705
am_superuser = true;
703706
}
704707
else
705708
{
706-
InitializeSessionUserId(username);
709+
InitializeSessionUserId(username, useroid);
707710
am_superuser = superuser();
708711
}
709712
}
@@ -712,7 +715,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
712715
/* normal multiuser case */
713716
Assert(MyProcPort != NULL);
714717
PerformAuthentication(MyProcPort);
715-
InitializeSessionUserId(username);
718+
InitializeSessionUserId(username, useroid);
716719
am_superuser = superuser();
717720
}
718721

src/include/miscadmin.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ extern bool InLocalUserIdChange(void);
307307
extern bool InSecurityRestrictedOperation(void);
308308
extern void GetUserIdAndContext(Oid *userid, bool *sec_def_context);
309309
extern void SetUserIdAndContext(Oid userid, bool sec_def_context);
310-
extern void InitializeSessionUserId(const char *rolename);
310+
extern void InitializeSessionUserId(const char *rolename, Oid useroid);
311311
extern void InitializeSessionUserIdStandalone(void);
312312
extern void SetSessionAuthorization(Oid userid, bool is_superuser);
313313
extern Oid GetCurrentRoleId(void);
@@ -411,7 +411,7 @@ extern AuxProcType MyAuxProcType;
411411
extern void pg_split_opts(char **argv, int *argcp, char *optstr);
412412
extern void InitializeMaxBackends(void);
413413
extern void InitPostgres(const char *in_dbname, Oid dboid, const char *username,
414-
char *out_dbname);
414+
Oid useroid, char *out_dbname);
415415
extern void BaseInit(void);
416416

417417
/* in utils/init/miscinit.c */

src/include/postmaster/bgworker.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ extern PGDLLIMPORT BackgroundWorker *MyBgworkerEntry;
130130
*/
131131
extern void BackgroundWorkerInitializeConnection(char *dbname, char *username);
132132

133+
/* Just like the above, but specifying database and user by OID. */
134+
extern void BackgroundWorkerInitializeConnectionByOid(Oid dboid, Oid useroid);
135+
133136
/* Block/unblock signals in a background worker process */
134137
extern void BackgroundWorkerBlockSignals(void);
135138
extern void BackgroundWorkerUnblockSignals(void);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy