*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/catalog.c,v 1.89 2010/02/26 02:00:36 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/catalog.c,v 1.90 2010/04/20 23:48:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
relationId == DbRoleSettingDatidRolidIndexId)
return true;
/* These are their toast tables and toast indexes (see toasting.h) */
- if (relationId == PgAuthidToastTable ||
- relationId == PgAuthidToastIndex ||
- relationId == PgDatabaseToastTable ||
+ if (relationId == PgDatabaseToastTable ||
relationId == PgDatabaseToastIndex ||
relationId == PgShdescriptionToastTable ||
relationId == PgShdescriptionToastIndex ||
# Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California
#
-# $PostgreSQL: pgsql/src/backend/catalog/genbki.pl,v 1.7 2010/01/22 16:40:18 rhaas Exp $
+# $PostgreSQL: pgsql/src/backend/catalog/genbki.pl,v 1.8 2010/04/20 23:48:47 tgl Exp $
#
#----------------------------------------------------------------------
# Generate entries for user attributes.
my $attnum = 0;
+ my $priornotnull = 1;
my @user_attrs = @{ $table->{columns} };
foreach my $attr (@user_attrs)
{
$attnum++;
- my $row = emit_pgattr_row($table_name, $attr);
+ my $row = emit_pgattr_row($table_name, $attr, $priornotnull);
$row->{attnum} = $attnum;
$row->{attstattarget} = '-1';
+ $priornotnull &= ($row->{attnotnull} eq 't');
# If it's bootstrapped, put an entry in postgres.bki.
if ($is_bootstrap eq ' bootstrap')
foreach my $attr (@SYS_ATTRS)
{
$attnum--;
- my $row = emit_pgattr_row($table_name, $attr);
+ my $row = emit_pgattr_row($table_name, $attr, 1);
$row->{attnum} = $attnum;
$row->{attstattarget} = '0';
# Given a system catalog name and a reference to a key-value pair corresponding
# to the name and type of a column, generate a reference to a hash that
-# represents a pg_attribute entry
+# represents a pg_attribute entry. We must also be told whether preceding
+# columns were all not-null.
sub emit_pgattr_row
{
- my ($table_name, $attr) = @_;
+ my ($table_name, $attr, $priornotnull) = @_;
my ($attname, $atttype) = %$attr;
my %row;
$row{attalign} = $type->{typalign};
# set attndims if it's an array type
$row{attndims} = $type->{typcategory} eq 'A' ? '1' : '0';
- # This approach to attnotnull is not really good enough;
- # we need to know about prior column types too. Look at
- # DefineAttr in bootstrap.c. For the moment it's okay for
- # the column orders appearing in bootstrapped catalogs.
- $row{attnotnull} =
- $type->{typname} eq 'oidvector' ? 't'
- : $type->{typname} eq 'int2vector' ? 't'
- : $type->{typlen} eq 'NAMEDATALEN' ? 't'
- : $type->{typlen} > 0 ? 't' : 'f';
+ # attnotnull must be set true if the type is fixed-width and
+ # prior columns are too --- compare DefineAttr in bootstrap.c.
+ # oidvector and int2vector are also treated as not-nullable.
+ if ($priornotnull)
+ {
+ $row{attnotnull} =
+ $type->{typname} eq 'oidvector' ? 't'
+ : $type->{typname} eq 'int2vector' ? 't'
+ : $type->{typlen} eq 'NAMEDATALEN' ? 't'
+ : $type->{typlen} > 0 ? 't' : 'f';
+ }
+ else
+ {
+ $row{attnotnull} = 'f';
+ }
last;
}
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/cache/catcache.c,v 1.151 2010/02/14 18:42:17 rhaas Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/catcache.c,v 1.152 2010/04/20 23:48:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* certain system indexes that support critical syscaches.
* We can't use an indexscan to fetch these, else we'll get into
* infinite recursion. A plain heap scan will work, however.
- *
* Once we have completed relcache initialization (signaled by
* criticalRelcachesBuilt), we don't have to worry anymore.
+ *
+ * Similarly, during backend startup we have to be able to use the
+ * pg_authid and pg_auth_members syscaches for authentication even if
+ * we don't yet have relcache entries for those catalogs' indexes.
*/
static bool
IndexScanOK(CatCache *cache, ScanKey cur_skey)
{
- if (cache->id == INDEXRELID)
+ switch (cache->id)
{
- /*
- * Rather than tracking exactly which indexes have to be loaded before
- * we can use indexscans (which changes from time to time), just force
- * all pg_index searches to be heap scans until we've built the
- * critical relcaches.
- */
- if (!criticalRelcachesBuilt)
+ case INDEXRELID:
+ /*
+ * Rather than tracking exactly which indexes have to be loaded
+ * before we can use indexscans (which changes from time to time),
+ * just force all pg_index searches to be heap scans until we've
+ * built the critical relcaches.
+ */
+ if (!criticalRelcachesBuilt)
+ return false;
+ break;
+
+ case AMOID:
+ case AMNAME:
+ /*
+ * Always do heap scans in pg_am, because it's so small there's
+ * not much point in an indexscan anyway. We *must* do this when
+ * initially building critical relcache entries, but we might as
+ * well just always do it.
+ */
return false;
- }
- else if (cache->id == AMOID ||
- cache->id == AMNAME)
- {
- /*
- * Always do heap scans in pg_am, because it's so small there's not
- * much point in an indexscan anyway. We *must* do this when
- * initially building critical relcache entries, but we might as well
- * just always do it.
- */
- return false;
+
+ case AUTHNAME:
+ case AUTHOID:
+ case AUTHMEMMEMROLE:
+ /*
+ * Protect authentication lookups occurring before relcache has
+ * collected entries for shared indexes.
+ */
+ if (!criticalSharedRelcachesBuilt)
+ return false;
+ break;
+
+ default:
+ break;
}
/* Normal case, allow index scan */
scandesc = systable_beginscan(relation,
cache->cc_indexoid,
- true,
+ IndexScanOK(cache, cur_skey),
SnapshotNow,
nkeys,
cur_skey);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.309 2010/04/14 21:31:11 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.310 2010/04/20 23:48:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "catalog/pg_amproc.h"
#include "catalog/pg_attrdef.h"
#include "catalog/pg_authid.h"
+#include "catalog/pg_auth_members.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_database.h"
#include "catalog/pg_namespace.h"
#define RELCACHE_INIT_FILEMAGIC 0x573265 /* version ID value */
/*
- * hardcoded tuple descriptors. see include/catalog/pg_attribute.h
+ * hardcoded tuple descriptors, generated by genbki.pl
*/
static const FormData_pg_attribute Desc_pg_class[Natts_pg_class] = {Schema_pg_class};
static const FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute] = {Schema_pg_attribute};
static const FormData_pg_attribute Desc_pg_proc[Natts_pg_proc] = {Schema_pg_proc};
static const FormData_pg_attribute Desc_pg_type[Natts_pg_type] = {Schema_pg_type};
static const FormData_pg_attribute Desc_pg_database[Natts_pg_database] = {Schema_pg_database};
+static const FormData_pg_attribute Desc_pg_authid[Natts_pg_authid] = {Schema_pg_authid};
+static const FormData_pg_attribute Desc_pg_auth_members[Natts_pg_auth_members] = {Schema_pg_auth_members};
static const FormData_pg_attribute Desc_pg_index[Natts_pg_index] = {Schema_pg_index};
/*
/*
* This flag is false until we have prepared the critical relcache entries
- * for shared catalogs (specifically, pg_database and its indexes).
+ * for shared catalogs (which are the tables needed for login).
*/
bool criticalSharedRelcachesBuilt = false;
* quite a lot since we only need to work for a few basic system
* catalogs.
*
- * formrdesc is currently used for: pg_database, pg_class, pg_attribute,
- * pg_proc, and pg_type (see RelationCacheInitializePhase2/3).
+ * formrdesc is currently used for: pg_database, pg_authid, pg_auth_members,
+ * pg_class, pg_attribute, pg_proc, and pg_type
+ * (see RelationCacheInitializePhase2/3).
*
* Note that these catalogs can't have constraints (except attnotnull),
* default values, rules, or triggers, since we don't cope with any of that.
* initialize attribute tuple form
*
* Unlike the case with the relation tuple, this data had better be right
- * because it will never be replaced. The input values must be correctly
- * defined by macros in src/include/catalog/ headers.
+ * because it will never be replaced. The data comes from
+ * src/include/catalog/ headers via genbki.pl.
*/
relation->rd_att = CreateTemplateTupleDesc(natts, hasoids);
relation->rd_att->tdrefcount = 1; /* mark as refcounted */
switch (relid)
{
case DatabaseRelationId:
+ case AuthIdRelationId:
+ case AuthMemRelationId:
case RelationRelationId:
case AttributeRelationId:
case ProcedureRelationId:
/*
* RelationCacheInitializePhase2
*
- * This is called to prepare for access to pg_database during startup.
- * We must at least set up a nailed reldesc for pg_database. Ideally
- * we'd like to have reldescs for its indexes, too. We attempt to
- * load this information from the shared relcache init file. If that's
- * missing or broken, just make a phony entry for pg_database.
- * RelationCacheInitializePhase3 will clean up as needed.
+ * This is called to prepare for access to shared catalogs during startup.
+ * We must at least set up nailed reldescs for pg_database, pg_authid,
+ * and pg_auth_members. Ideally we'd like to have reldescs for their
+ * indexes, too. We attempt to load this information from the shared
+ * relcache init file. If that's missing or broken, just make phony
+ * entries for the catalogs themselves. RelationCacheInitializePhase3
+ * will clean up as needed.
*/
void
RelationCacheInitializePhase2(void)
RelationMapInitializePhase2();
/*
- * In bootstrap mode, pg_database isn't there yet anyway, so do nothing.
+ * In bootstrap mode, the shared catalogs aren't there yet anyway,
+ * so do nothing.
*/
if (IsBootstrapProcessingMode())
return;
/*
* Try to load the shared relcache cache file. If unsuccessful, bootstrap
- * the cache with a pre-made descriptor for pg_database.
+ * the cache with pre-made descriptors for the critical shared catalogs.
*/
if (!load_relcache_init_file(true))
{
formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
true, Natts_pg_database, Desc_pg_database);
+ formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
+ true, Natts_pg_authid, Desc_pg_authid);
+ formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
+ false, Natts_pg_auth_members, Desc_pg_auth_members);
-#define NUM_CRITICAL_SHARED_RELS 1 /* fix if you change list above */
+#define NUM_CRITICAL_SHARED_RELS 3 /* fix if you change list above */
}
MemoryContextSwitchTo(oldcxt);
* DatabaseNameIndexId isn't critical for relcache loading, but rather for
* initial lookup of MyDatabaseId, without which we'll never find any
* non-shared catalogs at all. Autovacuum calls InitPostgres with a
- * database OID, so it instead depends on DatabaseOidIndexId.
+ * database OID, so it instead depends on DatabaseOidIndexId. We also
+ * need to nail up some indexes on pg_authid and pg_auth_members for use
+ * during client authentication.
*/
if (!criticalSharedRelcachesBuilt)
{
DatabaseRelationId);
load_critical_index(DatabaseOidIndexId,
DatabaseRelationId);
-
-#define NUM_CRITICAL_SHARED_INDEXES 2 /* fix if you change list above */
+ load_critical_index(AuthIdRolnameIndexId,
+ AuthIdRelationId);
+ load_critical_index(AuthIdOidIndexId,
+ AuthIdRelationId);
+ load_critical_index(AuthMemMemRoleIndexId,
+ AuthMemRelationId);
+
+#define NUM_CRITICAL_SHARED_INDEXES 5 /* fix if you change list above */
criticalSharedRelcachesBuilt = true;
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.183 2010/02/26 02:01:13 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.184 2010/04/20 23:48:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* These next checks are not enforced when in standalone mode, so that
* there is a way to recover from sillinesses like "UPDATE pg_authid SET
* rolcanlogin = false;".
- *
- * We do not enforce them for the autovacuum process either.
*/
- if (IsUnderPostmaster && !IsAutoVacuumWorkerProcess())
+ if (IsUnderPostmaster)
{
/*
* Is role allowed to login at all?
void
InitializeSessionUserIdStandalone(void)
{
- /* This function should only be called in a single-user backend. */
+ /*
+ * This function should only be called in single-user mode and in
+ * autovacuum workers.
+ */
AssertState(!IsUnderPostmaster || IsAutoVacuumWorkerProcess());
/* call only once */
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.209 2010/04/20 01:38:52 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.210 2010/04/20 23:48:47 tgl Exp $
*
*
*-------------------------------------------------------------------------
/*
* Load relcache entries for the shared system catalogs. This must create
- * at least an entry for pg_database.
+ * at least entries for pg_database and catalogs used for authentication.
*/
RelationCacheInitializePhase2();
(void) GetTransactionSnapshot();
}
+ /*
+ * Perform client authentication if necessary, then figure out our
+ * postgres user ID, and see if we are a superuser.
+ *
+ * In standalone mode and in autovacuum worker processes, we use a fixed
+ * ID, otherwise we figure it out from the authenticated user name.
+ */
+ if (bootstrap || IsAutoVacuumWorkerProcess())
+ {
+ InitializeSessionUserIdStandalone();
+ am_superuser = true;
+ }
+ else if (!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)));
+ }
+ else
+ {
+ /* normal multiuser case */
+ Assert(MyProcPort != NULL);
+ PerformAuthentication(MyProcPort);
+ InitializeSessionUserId(username);
+ am_superuser = superuser();
+ }
+
+ /*
+ * If walsender, we're done here --- we don't want to connect to any
+ * particular database.
+ */
+ if (am_walsender)
+ {
+ Assert(!bootstrap);
+ /* report this backend in the PgBackendStatus array */
+ pgstat_bestart();
+ /* close the transaction we started above */
+ CommitTransactionCommand();
+ return;
+ }
+
/*
* Set up the global variables holding database id and default tablespace.
* But note we won't actually try to touch the database just yet.
*
- * We take a shortcut in the bootstrap and walsender case, otherwise we
- * have to look up the db's entry in pg_database.
+ * We take a shortcut in the bootstrap case, otherwise we have to look up
+ * the db's entry in pg_database.
*/
- if (bootstrap || am_walsender)
+ if (bootstrap)
{
MyDatabaseId = TemplateDbOid;
MyDatabaseTableSpace = DEFAULTTABLESPACE_OID;
* AccessShareLock for such sessions and thereby not conflict against
* CREATE DATABASE.
*/
- if (!bootstrap && !am_walsender)
+ if (!bootstrap)
LockSharedObject(DatabaseRelationId, MyDatabaseId, 0,
RowExclusiveLock);
* If there was a concurrent DROP DATABASE, this ensures we will die
* cleanly without creating a mess.
*/
- if (!bootstrap && !am_walsender)
+ if (!bootstrap)
{
HeapTuple tuple;
*/
fullpath = GetDatabasePath(MyDatabaseId, MyDatabaseTableSpace);
- if (!bootstrap && !am_walsender)
+ if (!bootstrap)
{
if (access(fullpath, F_OK) == -1)
{
*/
RelationCacheInitializePhase3();
- /*
- * Perform client authentication if necessary, then figure out our
- * postgres user ID, and see if we are a superuser.
- *
- * In standalone mode and in autovacuum worker processes, we use a fixed
- * ID, otherwise we figure it out from the authenticated user name.
- */
- if (bootstrap || IsAutoVacuumWorkerProcess())
- {
- InitializeSessionUserIdStandalone();
- am_superuser = true;
- }
- else if (!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)));
- }
- else
- {
- /* normal multiuser case */
- Assert(MyProcPort != NULL);
- PerformAuthentication(MyProcPort);
- InitializeSessionUserId(username);
- am_superuser = superuser();
- }
-
/* set up ACL framework (so CheckMyDatabase can check permissions) */
initialize_acl();
- /* Process pg_db_role_setting options */
- process_settings(MyDatabaseId, GetSessionUserId());
-
/*
* Re-read the pg_database row for our database, check permissions and set
* up database-specific GUC settings. We can't do this until all the
* database-access infrastructure is up. (Also, it wants to know if the
* user is a superuser, so the above stuff has to happen first.)
*/
- if (!bootstrap && !am_walsender)
+ if (!bootstrap)
CheckMyDatabase(dbname, am_superuser);
/*
}
}
+ /* Process pg_db_role_setting options */
+ process_settings(MyDatabaseId, GetSessionUserId());
+
/* Apply PostAuthDelay as soon as we've read all options */
if (PostAuthDelay > 0)
pg_usleep(PostAuthDelay * 1000000L);
/* initialize client encoding */
InitializeClientEncoding();
- /* reset the database for walsender */
- if (am_walsender)
- MyProc->databaseId = MyDatabaseId = InvalidOid;
-
/* report this backend in the PgBackendStatus array */
if (!bootstrap)
pgstat_bestart();
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.585 2010/02/16 22:34:54 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.586 2010/04/20 23:48:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201002161
+#define CATALOG_VERSION_NO 201004201
#endif
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_auth_members.h,v 1.8 2010/01/05 01:06:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_auth_members.h,v 1.9 2010/04/20 23:48:47 tgl Exp $
*
* NOTES
* the genbki.pl script reads this file and generates .bki
* ----------------
*/
#define AuthMemRelationId 1261
+#define AuthMemRelation_Rowtype_Id 2843
-CATALOG(pg_auth_members,1261) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
+CATALOG(pg_auth_members,1261) BKI_SHARED_RELATION BKI_WITHOUT_OIDS BKI_ROWTYPE_OID(2843) BKI_SCHEMA_MACRO
{
Oid roleid; /* ID of a role */
Oid member; /* ID of a member of that role */
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_authid.h,v 1.12 2010/01/05 01:06:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_authid.h,v 1.13 2010/04/20 23:48:47 tgl Exp $
*
* NOTES
* the genbki.pl script reads this file and generates .bki
* ----------------
*/
#define AuthIdRelationId 1260
+#define AuthIdRelation_Rowtype_Id 2842
-CATALOG(pg_authid,1260) BKI_SHARED_RELATION
+CATALOG(pg_authid,1260) BKI_SHARED_RELATION BKI_ROWTYPE_OID(2842) BKI_SCHEMA_MACRO
{
NameData rolname; /* name of role */
bool rolsuper; /* read this field via superuser() only! */
* compiler constants for pg_authid
* ----------------
*/
-#define Natts_pg_authid 11
+#define Natts_pg_authid 10
#define Anum_pg_authid_rolname 1
#define Anum_pg_authid_rolsuper 2
#define Anum_pg_authid_rolinherit 3
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/toasting.h,v 1.13 2010/01/06 03:04:03 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/toasting.h,v 1.14 2010/04/20 23:48:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
DECLARE_TOAST(pg_trigger, 2336, 2337);
/* shared catalogs */
-DECLARE_TOAST(pg_authid, 2842, 2843);
-#define PgAuthidToastTable 2842
-#define PgAuthidToastIndex 2843
DECLARE_TOAST(pg_database, 2844, 2845);
#define PgDatabaseToastTable 2844
#define PgDatabaseToastIndex 2845