/* Must copy tuple before releasing buffer */ if (HeapTupleIsValid(tuple))
tuple = heap_copytuple(tuple);
/* all done */
systable_endscan(scan);
table_close(relation, AccessShareLock);
return tuple;
}
/* *PerformAuthentication--authenticatearemoteclient * *returns:nothing.Willnotreturnatallifthere'sanyfailure.
*/ staticvoid
PerformAuthentication(Port *port)
{ /* This should be set already, but let's make sure */
ClientAuthInProgress = true; /* limit visibility of log messages */
/* Fetch our pg_database row normally, via syscache */
tup = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(MyDatabaseId)); if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
dbform = (Form_pg_database) GETSTRUCT(tup);
/* This recheck is strictly paranoia */ if (strcmp(name, NameStr(dbform->datname)) != 0)
ereport(FATAL,
(errcode(ERRCODE_UNDEFINED_DATABASE),
errmsg("database \"%s\" has disappeared from pg_database",
name),
errdetail("Database OID %u now seems to belong to \"%s\".",
MyDatabaseId, NameStr(dbform->datname))));
/* *Checkpermissionstoconnecttothedatabase. * *Thesechecksarenotenforcedwheninstandalonemode,sothatthereis *awaytorecoverfromdisablingallaccesstoalldatabases,for *example"UPDATEpg_databaseSETdatallowconn=false;".
*/ if (IsUnderPostmaster)
{ /* *Checkthatthedatabaseiscurrentlyallowingconnections. *(Backgroundprocessescanoverridethistestandthenextoneby *settingoverride_allow_connections.)
*/ if (!dbform->datallowconn && !override_allow_connections)
ereport(FATAL,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("database \"%s\" is not currently accepting connections",
name)));
/* *Checkprivilegetoconnecttothedatabase.(Theam_superusertest *isredundant,butsincewehavetheflag,mightaswellcheckit *andsaveafewcycles.)
*/ if (!am_superuser && !override_allow_connections &&
object_aclcheck(DatabaseRelationId, MyDatabaseId, GetUserId(),
ACL_CONNECT) != ACLCHECK_OK)
ereport(FATAL,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied for database \"%s\"", name),
errdetail("User does not have CONNECT privilege.")));
/* *OK,we'regolden.Nextto-doitemistosavetheencodinginfooutof *thepg_databasetuple.
*/
SetDatabaseEncoding(dbform->encoding); /* Record it as a GUC internal option, too */
SetConfigOption("server_encoding", GetDatabaseEncodingName(),
PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT); /* If we have no other source of client_encoding, use server encoding */
SetConfigOption("client_encoding", GetDatabaseEncodingName(),
PGC_BACKEND, PGC_S_DYNAMIC_DEFAULT);
if (pg_perm_setlocale(LC_COLLATE, collate) == NULL)
ereport(FATAL,
(errmsg("database locale is incompatible with operating system"),
errdetail("The database was initialized with LC_COLLATE \"%s\", " " which is not recognized by setlocale().", collate),
errhint("Recreate the database with another locale or install the missing locale.")));
if (pg_perm_setlocale(LC_CTYPE, ctype) == NULL)
ereport(FATAL,
(errmsg("database locale is incompatible with operating system"),
errdetail("The database was initialized with LC_CTYPE \"%s\", " " which is not recognized by setlocale().", ctype),
errhint("Recreate the database with another locale or install the missing locale.")));
/* *Checkcollationversion.Seesimilarcodein *pg_newlocale_from_collation().Notethatherewewarninsteadoferror *inanycase,sothatwedon'tpreventconnecting.
*/
datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_datcollversion,
&isnull); if (!isnull)
{ char *actual_versionstr; char *collversionstr; char *locale;
collversionstr = TextDatumGetCString(datum);
if (dbform->datlocprovider == COLLPROVIDER_LIBC)
locale = collate; else
{
datum = SysCacheGetAttrNotNull(DATABASEOID, tup, Anum_pg_database_datlocale);
locale = TextDatumGetCString(datum);
}
actual_versionstr = get_collation_actual_version(dbform->datlocprovider, locale); if (!actual_versionstr) /* should not happen */
elog(WARNING, "database \"%s\" has no actual collation version, but a version was recorded",
name); elseif (strcmp(actual_versionstr, collversionstr) != 0)
ereport(WARNING,
(errmsg("database \"%s\" has a collation version mismatch",
name),
errdetail("The database was created using collation version %s, " "but the operating system provides version %s.",
collversionstr, actual_versionstr),
errhint("Rebuild all objects in this database that use the default collation and run " "ALTER DATABASE %s REFRESH COLLATION VERSION, " "or build PostgreSQL with the right library version.",
quote_identifier(name))));
}
/* Note that this does not include "auxiliary" processes */
MaxBackends = MaxConnections + autovacuum_worker_slots +
max_worker_processes + max_wal_senders + NUM_SPECIAL_WORKER_PROCS;
if (MaxBackends > MAX_BACKENDS)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("too many server processes configured"),
errdetail("\"max_connections\" (%d) plus \"autovacuum_worker_slots\" (%d) plus \"max_worker_processes\" (%d) plus \"max_wal_senders\" (%d) must be less than %d.",
MaxConnections, autovacuum_worker_slots,
max_worker_processes, max_wal_senders,
MAX_BACKENDS - (NUM_SPECIAL_WORKER_PROCS - 1))));
}
/* *Initializethenumberoffast-pathlockslotsinPGPROC. * *ThismustbecalledaftermoduleshavehadthechancetoalterGUCsin *shared_preload_librariesandbeforesharedmemorysizeisdetermined.
*/ void
InitializeFastPathLocks(void)
{ /* Should be initialized only once. */
Assert(FastPathLockGroupsPerBackend == 0);
StartupXLOG(); /* Release (and warn about) any buffer pins leaked in StartupXLOG */
ReleaseAuxProcessResources(true); /* Reset CurrentResourceOwner to nothing for the moment */
CurrentResourceOwner = NULL;
/* The autovacuum launcher is done here */ if (AmAutoVacuumLauncherProcess())
{ /* fill in the remainder of this entry in the PgBackendStatus array */
pgstat_bestart_final();
return;
}
/* *Startanewtransactionherebeforefirstaccesstodb.
*/ if (!bootstrap)
{ /* statement_timestamp must be set for timeouts to work correctly */
SetCurrentStatementStartTimestamp();
StartTransactionCommand();
/* *Performclientauthenticationifnecessary,thenfigureoutour *postgresuserID,andseeifweareasuperuser. * *Instandalonemode,autovacuumworkerprocessesandslotsyncworker *process,weuseafixedID,otherwisewefigureitoutfromthe *authenticatedusername.
*/ if (bootstrap || AmAutoVacuumWorkerProcess() || AmLogicalSlotSyncWorkerProcess())
{
InitializeSessionUserIdStandalone();
am_superuser = true;
} elseif (!IsUnderPostmaster)
{
InitializeSessionUserIdStandalone();
am_superuser = true; if (!ThereIsAtLeastOneRole())
ereport(WARNING,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("no roles are defined in this database system"),
errhint("You should immediately run CREATE USER \"%s\" SUPERUSER;.",
username != NULL ? username : "postgres")));
} elseif (AmBackgroundWorkerProcess())
{ if (username == NULL && !OidIsValid(useroid))
{
InitializeSessionUserIdStandalone();
am_superuser = true;
} else
{
InitializeSessionUserId(username, useroid,
(flags & INIT_PG_OVERRIDE_ROLE_LOGIN) != 0);
am_superuser = superuser();
}
} else
{ /* normal multiuser case */
Assert(MyProcPort != NULL);
PerformAuthentication(MyProcPort);
InitializeSessionUserId(username, useroid, false); /* ensure that auth_method is actually valid, aka authn_id is not NULL */ if (MyClientConnectionInfo.authn_id)
InitializeSystemUser(MyClientConnectionInfo.authn_id,
hba_authname(MyClientConnectionInfo.auth_method));
am_superuser = superuser();
}
/* Report any SSL/GSS details for the session. */ if (MyProcPort != NULL)
{
Assert(!bootstrap);
pgstat_bestart_security();
}
/* *Binaryupgradesonlyallowedsuper-userconnections
*/ if (IsBinaryUpgrade && !am_superuser)
{
ereport(FATAL,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to connect in binary upgrade mode")));
}
/* *Thelastfewregularconnectionslotsarereservedforsuperusersand *roleswithprivilegesofpg_use_reserved_connections.Wedonotapply *theselimitstobackgroundprocesses,sincetheyallhavetheirown *poolsofPGPROCslots. * *Note:Atthispoint,thenewbackendhasalreadyclaimedaprocstruct, *sowemustcheckwhetherthenumberoffreeslotsisstrictlylessthan *thereservedconnectionlimits.
*/ if (AmRegularBackendProcess() && !am_superuser &&
(SuperuserReservedConnections + ReservedConnections) > 0 &&
!HaveNFreeProcs(SuperuserReservedConnections + ReservedConnections, &nfree))
{ if (nfree < SuperuserReservedConnections)
ereport(FATAL,
(errcode(ERRCODE_TOO_MANY_CONNECTIONS),
errmsg("remaining connection slots are reserved for roles with the %s attribute", "SUPERUSER")));
if (!has_privs_of_role(GetUserId(), ROLE_PG_USE_RESERVED_CONNECTIONS))
ereport(FATAL,
(errcode(ERRCODE_TOO_MANY_CONNECTIONS),
errmsg("remaining connection slots are reserved for roles with privileges of the \"%s\" role", "pg_use_reserved_connections")));
}
/* Check replication permissions needed for walsender processes. */ if (am_walsender)
{
Assert(!bootstrap);
if (!has_rolreplication(GetUserId()))
ereport(FATAL,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to start WAL sender"),
errdetail("Only roles with the %s attribute may start a WAL sender process.", "REPLICATION")));
}
/* *Ifthisisaplainwalsenderonlysupportingphysicalreplication,we *don'twanttoconnecttoanyparticulardatabase.Justfinishthe *backendstartupbyprocessinganyoptionsfromthestartuppacket,and *we'redone.
*/ if (am_walsender && !am_db_walsender)
{ /* process any options passed in the startup packet */ if (MyProcPort != NULL)
process_startup_options(MyProcPort, am_superuser);
/* Apply PostAuthDelay as soon as we've read all options */ if (PostAuthDelay > 0)
pg_usleep(PostAuthDelay * 1000000L);
tuple = GetDatabaseTupleByOid(dboid); if (HeapTupleIsValid(tuple))
datform = (Form_pg_database) GETSTRUCT(tuple);
if (!HeapTupleIsValid(tuple) ||
(in_dbname && namestrcmp(&datform->datname, in_dbname)))
{ if (in_dbname)
ereport(FATAL,
(errcode(ERRCODE_UNDEFINED_DATABASE),
errmsg("database \"%s\" does not exist", in_dbname),
errdetail("It seems to have just been dropped or renamed."))); else
ereport(FATAL,
(errcode(ERRCODE_UNDEFINED_DATABASE),
errmsg("database %u does not exist", dboid)));
}
if (database_is_invalid_form(datform))
{
ereport(FATAL,
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("cannot connect to invalid database \"%s\"", dbname),
errhint("Use DROP DATABASE to drop invalid databases."));
}
MyDatabaseTableSpace = datform->dattablespace;
MyDatabaseHasLoginEventTriggers = datform->dathasloginevt; /* pass the database name back to the caller */ if (out_dbname)
strcpy(out_dbname, dbname);
}
/* *STATEMENT_TIMEOUThandler:triggeraquery-cancelinterrupt.
*/ staticvoid
StatementTimeoutHandler(void)
{ int sig = SIGINT;
/* *Duringauthenticationthetimeoutisusedtodealwith *authentication_timeout-wewanttoquitinresponsetosuchtimeouts.
*/ if (ClientAuthInProgress)
sig = SIGTERM;
#ifdef HAVE_SETSID /* try to signal whole process group */
kill(-MyProcPid, sig); #endif
kill(MyProcPid, sig);
}
/* *LOCK_TIMEOUThandler:triggeraquery-cancelinterrupt.
*/ staticvoid
LockTimeoutHandler(void)
{ #ifdef HAVE_SETSID /* try to signal whole process group */
kill(-MyProcPid, SIGINT); #endif
kill(MyProcPid, SIGINT);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.