Re: Thoughts on pg_hba.conf rejection - Mailing list pgsql-hackers

From Tom Lane
Subject Re: Thoughts on pg_hba.conf rejection
Date
Msg-id 1695.1271799794@sss.pgh.pa.us
Whole thread Raw
In response to Re: Thoughts on pg_hba.conf rejection  (Alvaro Herrera <alvherre@commandprompt.com>)
List pgsql-hackers
Alvaro Herrera <alvherre@commandprompt.com> writes:
> Tom Lane escribió:
>> 2. We don't have infrastructure that would allow access to out-of-line
>> toasted fields during startup.  Rather than try to add such, I propose
>> removing pg_authid's toast table, with the consequence that rolpassword
>> cannot be long enough to require out-of-line storage (note it could
>> still be compressed in-line).  I cannot imagine any real situation where
>> this would be an issue --- does anyone else?  (BTW, I'm fairly sure that
>> we couldn't support an out-of-line rolpassword in the past anyway,
>> because of restrictions in the old flatfiles code.)

> In the past rolconfig could have been a problem too, but fortunately we
> got that moved out.  I really doubt that a password of "only" about 2kB
> compressed is going to be a limitation to anyone on this planet.  (Hmm,
> isn't it really 8kB in row length that's the hard limit?)

Actually, rolconfig would be OK because it doesn't have to be accessed
until after we've completed authentication.  However there's no really
nice way to ensure that rolpassword doesn't get toasted if another
column can be.  I suppose we could have initdb force its attstorage to
PLAIN or some such.

> This could perhaps be an issue if we were to store an SSL certificate in
> rolpassword or something like that, but I don't think we support that.

Nope, not that I know of.  Anyway we could solve the problem if it ever
came up --- I don't think there's anything insurmountable about
accessing shared toast tables here, we'd just need some support to allow
them to be nailed-in-cache.

>> 3. We'd have to nail pg_authid, pg_auth_members, and their indexes into
>> relcache, because relcache.c isn't prepared to cope otherwise.  I doubt
>> this would affect performance in any material way, but it would eat a
>> few more kbytes of storage per backend.

> This doesn't limit that VACUUM FULL or other commands are applied to
> those catalogs, right?

Nope, it's no different from pg_database.

Attached is a draft patch --- it looks pretty reasonable, but I've not
tested the impact on walsender yet.

            regards, tom lane

Index: src/backend/catalog/catalog.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/catalog/catalog.c,v
retrieving revision 1.89
diff -c -r1.89 catalog.c
*** src/backend/catalog/catalog.c    26 Feb 2010 02:00:36 -0000    1.89
--- src/backend/catalog/catalog.c    20 Apr 2010 21:28:40 -0000
***************
*** 327,335 ****
          relationId == DbRoleSettingDatidRolidIndexId)
          return true;
      /* These are their toast tables and toast indexes (see toasting.h) */
!     if (relationId == PgAuthidToastTable ||
!         relationId == PgAuthidToastIndex ||
!         relationId == PgDatabaseToastTable ||
          relationId == PgDatabaseToastIndex ||
          relationId == PgShdescriptionToastTable ||
          relationId == PgShdescriptionToastIndex ||
--- 327,333 ----
          relationId == DbRoleSettingDatidRolidIndexId)
          return true;
      /* These are their toast tables and toast indexes (see toasting.h) */
!     if (relationId == PgDatabaseToastTable ||
          relationId == PgDatabaseToastIndex ||
          relationId == PgShdescriptionToastTable ||
          relationId == PgShdescriptionToastIndex ||
Index: src/backend/catalog/genbki.pl
===================================================================
RCS file: /cvsroot/pgsql/src/backend/catalog/genbki.pl,v
retrieving revision 1.7
diff -c -r1.7 genbki.pl
*** src/backend/catalog/genbki.pl    22 Jan 2010 16:40:18 -0000    1.7
--- src/backend/catalog/genbki.pl    20 Apr 2010 21:28:40 -0000
***************
*** 183,195 ****

              # Generate entries for user attributes.
              my $attnum = 0;
              my @user_attrs = @{ $table->{columns} };
              foreach my $attr (@user_attrs)
              {
                  $attnum++;
!                 my $row = emit_pgattr_row($table_name, $attr);
                  $row->{attnum} = $attnum;
                  $row->{attstattarget} = '-1';

                  # If it's bootstrapped, put an entry in postgres.bki.
                  if ($is_bootstrap eq ' bootstrap')
--- 183,197 ----

              # 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, $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')
***************
*** 221,227 ****
                  foreach my $attr (@SYS_ATTRS)
                  {
                      $attnum--;
!                     my $row = emit_pgattr_row($table_name, $attr);
                      $row->{attnum} = $attnum;
                      $row->{attstattarget} = '0';

--- 223,229 ----
                  foreach my $attr (@SYS_ATTRS)
                  {
                      $attnum--;
!                     my $row = emit_pgattr_row($table_name, $attr, 1);
                      $row->{attnum} = $attnum;
                      $row->{attstattarget} = '0';

***************
*** 308,317 ****

  # 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
  sub emit_pgattr_row
  {
!     my ($table_name, $attr) = @_;
      my ($attname, $atttype) = %$attr;
      my %row;

--- 310,320 ----

  # 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.  We must also be told whether preceding
! # columns were all not-null.
  sub emit_pgattr_row
  {
!     my ($table_name, $attr, $priornotnull) = @_;
      my ($attname, $atttype) = %$attr;
      my %row;

***************
*** 337,351 ****
              $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';
              last;
          }
      }
--- 340,360 ----
              $row{attalign}    = $type->{typalign};
              # set attndims if it's an array type
              $row{attndims}    = $type->{typcategory} eq 'A' ? '1' : '0';
!             # 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;
          }
      }
Index: src/backend/utils/cache/catcache.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v
retrieving revision 1.151
diff -c -r1.151 catcache.c
*** src/backend/utils/cache/catcache.c    14 Feb 2010 18:42:17 -0000    1.151
--- src/backend/utils/cache/catcache.c    20 Apr 2010 21:28:40 -0000
***************
*** 981,1014 ****
   *        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.
   */
  static bool
  IndexScanOK(CatCache *cache, ScanKey cur_skey)
  {
!     if (cache->id == 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;
!     }
!     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;
      }

      /* Normal case, allow index scan */
--- 981,1032 ----
   *        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)
  {
!     switch (cache->id)
      {
!         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;
!
!         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 */
***************
*** 1397,1403 ****

          scandesc = systable_beginscan(relation,
                                        cache->cc_indexoid,
!                                       true,
                                        SnapshotNow,
                                        nkeys,
                                        cur_skey);
--- 1415,1421 ----

          scandesc = systable_beginscan(relation,
                                        cache->cc_indexoid,
!                                       IndexScanOK(cache, cur_skey),
                                        SnapshotNow,
                                        nkeys,
                                        cur_skey);
Index: src/backend/utils/cache/relcache.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v
retrieving revision 1.309
diff -c -r1.309 relcache.c
*** src/backend/utils/cache/relcache.c    14 Apr 2010 21:31:11 -0000    1.309
--- src/backend/utils/cache/relcache.c    20 Apr 2010 21:28:40 -0000
***************
*** 43,48 ****
--- 43,49 ----
  #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"
***************
*** 87,99 ****
  #define RELCACHE_INIT_FILEMAGIC        0x573265    /* version ID value */

  /*
!  *        hardcoded tuple descriptors.  see include/catalog/pg_attribute.h
   */
  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_index[Natts_pg_index] = {Schema_pg_index};

  /*
--- 88,102 ----
  #define RELCACHE_INIT_FILEMAGIC        0x573265    /* version ID value */

  /*
!  *        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};

  /*
***************
*** 118,124 ****

  /*
   * This flag is false until we have prepared the critical relcache entries
!  * for shared catalogs (specifically, pg_database and its indexes).
   */
  bool        criticalSharedRelcachesBuilt = false;

--- 121,127 ----

  /*
   * This flag is false until we have prepared the critical relcache entries
!  * for shared catalogs (which are the tables needed for login).
   */
  bool        criticalSharedRelcachesBuilt = false;

***************
*** 1379,1386 ****
   *        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).
   *
   * Note that these catalogs can't have constraints (except attnotnull),
   * default values, rules, or triggers, since we don't cope with any of that.
--- 1382,1390 ----
   *        quite a lot since we only need to work for a few basic system
   *        catalogs.
   *
!  * 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.
***************
*** 1461,1468 ****
       * 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.
       */
      relation->rd_att = CreateTemplateTupleDesc(natts, hasoids);
      relation->rd_att->tdrefcount = 1;    /* mark as refcounted */
--- 1465,1472 ----
       * initialize attribute tuple form
       *
       * Unlike the case with the relation tuple, this data had better be right
!      * 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 */
***************
*** 2455,2460 ****
--- 2459,2466 ----
      switch (relid)
      {
          case DatabaseRelationId:
+         case AuthIdRelationId:
+         case AuthMemRelationId:
          case RelationRelationId:
          case AttributeRelationId:
          case ProcedureRelationId:
***************
*** 2750,2761 ****
  /*
   *        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.
   */
  void
  RelationCacheInitializePhase2(void)
--- 2756,2768 ----
  /*
   *        RelationCacheInitializePhase2
   *
!  *        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)
***************
*** 2768,2774 ****
      RelationMapInitializePhase2();

      /*
!      * In bootstrap mode, pg_database isn't there yet anyway, so do nothing.
       */
      if (IsBootstrapProcessingMode())
          return;
--- 2775,2782 ----
      RelationMapInitializePhase2();

      /*
!      * In bootstrap mode, the shared catalogs aren't there yet anyway,
!      * so do nothing.
       */
      if (IsBootstrapProcessingMode())
          return;
***************
*** 2780,2793 ****

      /*
       * Try to load the shared relcache cache file.    If unsuccessful, bootstrap
!      * the cache with a pre-made descriptor for pg_database.
       */
      if (!load_relcache_init_file(true))
      {
          formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
                    true, Natts_pg_database, Desc_pg_database);

! #define NUM_CRITICAL_SHARED_RELS    1    /* fix if you change list above */
      }

      MemoryContextSwitchTo(oldcxt);
--- 2788,2805 ----

      /*
       * Try to load the shared relcache cache file.    If unsuccessful, bootstrap
!      * 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    3    /* fix if you change list above */
      }

      MemoryContextSwitchTo(oldcxt);
***************
*** 2910,2916 ****
       * 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.
       */
      if (!criticalSharedRelcachesBuilt)
      {
--- 2922,2930 ----
       * 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.  We also
!      * need to nail up some indexes on pg_authid and pg_auth_members for use
!      * during client authentication.
       */
      if (!criticalSharedRelcachesBuilt)
      {
***************
*** 2918,2925 ****
                              DatabaseRelationId);
          load_critical_index(DatabaseOidIndexId,
                              DatabaseRelationId);

! #define NUM_CRITICAL_SHARED_INDEXES 2    /* fix if you change list above */

          criticalSharedRelcachesBuilt = true;
      }
--- 2932,2945 ----
                              DatabaseRelationId);
          load_critical_index(DatabaseOidIndexId,
                              DatabaseRelationId);
+         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;
      }
Index: src/backend/utils/init/miscinit.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v
retrieving revision 1.183
diff -c -r1.183 miscinit.c
*** src/backend/utils/init/miscinit.c    26 Feb 2010 02:01:13 -0000    1.183
--- src/backend/utils/init/miscinit.c    20 Apr 2010 21:28:40 -0000
***************
*** 429,438 ****
       * 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())
      {
          /*
           * Is role allowed to login at all?
--- 429,436 ----
       * 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;".
       */
!     if (IsUnderPostmaster)
      {
          /*
           * Is role allowed to login at all?
***************
*** 479,485 ****
  void
  InitializeSessionUserIdStandalone(void)
  {
!     /* This function should only be called in a single-user backend. */
      AssertState(!IsUnderPostmaster || IsAutoVacuumWorkerProcess());

      /* call only once */
--- 477,486 ----
  void
  InitializeSessionUserIdStandalone(void)
  {
!     /*
!      * This function should only be called in single-user mode and in
!      * autovacuum workers.
!      */
      AssertState(!IsUnderPostmaster || IsAutoVacuumWorkerProcess());

      /* call only once */
Index: src/backend/utils/init/postinit.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v
retrieving revision 1.209
diff -c -r1.209 postinit.c
*** src/backend/utils/init/postinit.c    20 Apr 2010 01:38:52 -0000    1.209
--- src/backend/utils/init/postinit.c    20 Apr 2010 21:28:40 -0000
***************
*** 552,558 ****

      /*
       * Load relcache entries for the shared system catalogs.  This must create
!      * at least an entry for pg_database.
       */
      RelationCacheInitializePhase2();

--- 552,558 ----

      /*
       * Load relcache entries for the shared system catalogs.  This must create
!      * at least entries for pg_database and catalogs used for authentication.
       */
      RelationCacheInitializePhase2();

***************
*** 586,598 ****
      }

      /*
       * 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.
       */
!     if (bootstrap || am_walsender)
      {
          MyDatabaseId = TemplateDbOid;
          MyDatabaseTableSpace = DEFAULTTABLESPACE_OID;
--- 586,644 ----
      }

      /*
+      * 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 case, otherwise we have to look up
!      * the db's entry in pg_database.
       */
!     if (bootstrap)
      {
          MyDatabaseId = TemplateDbOid;
          MyDatabaseTableSpace = DEFAULTTABLESPACE_OID;
***************
*** 655,661 ****
       * AccessShareLock for such sessions and thereby not conflict against
       * CREATE DATABASE.
       */
!     if (!bootstrap && !am_walsender)
          LockSharedObject(DatabaseRelationId, MyDatabaseId, 0,
                           RowExclusiveLock);

--- 701,707 ----
       * AccessShareLock for such sessions and thereby not conflict against
       * CREATE DATABASE.
       */
!     if (!bootstrap)
          LockSharedObject(DatabaseRelationId, MyDatabaseId, 0,
                           RowExclusiveLock);

***************
*** 664,670 ****
       * If there was a concurrent DROP DATABASE, this ensures we will die
       * cleanly without creating a mess.
       */
!     if (!bootstrap && !am_walsender)
      {
          HeapTuple    tuple;

--- 710,716 ----
       * If there was a concurrent DROP DATABASE, this ensures we will die
       * cleanly without creating a mess.
       */
!     if (!bootstrap)
      {
          HeapTuple    tuple;

***************
*** 684,690 ****
       */
      fullpath = GetDatabasePath(MyDatabaseId, MyDatabaseTableSpace);

!     if (!bootstrap && !am_walsender)
      {
          if (access(fullpath, F_OK) == -1)
          {
--- 730,736 ----
       */
      fullpath = GetDatabasePath(MyDatabaseId, MyDatabaseTableSpace);

!     if (!bootstrap)
      {
          if (access(fullpath, F_OK) == -1)
          {
***************
*** 715,765 ****
       */
      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)
          CheckMyDatabase(dbname, am_superuser);

      /*
--- 761,776 ----
       */
      RelationCacheInitializePhase3();

      /* set up ACL framework (so CheckMyDatabase can check permissions) */
      initialize_acl();

      /*
       * 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)
          CheckMyDatabase(dbname, am_superuser);

      /*
***************
*** 841,846 ****
--- 852,860 ----
          }
      }

+     /* 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);
***************
*** 856,865 ****
      /* 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();
--- 870,875 ----
Index: src/include/catalog/catversion.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/catversion.h,v
retrieving revision 1.585
diff -c -r1.585 catversion.h
*** src/include/catalog/catversion.h    16 Feb 2010 22:34:54 -0000    1.585
--- src/include/catalog/catversion.h    20 Apr 2010 21:28:40 -0000
***************
*** 53,58 ****
   */

  /*                            yyyymmddN */
! #define CATALOG_VERSION_NO    201002161

  #endif
--- 53,58 ----
   */

  /*                            yyyymmddN */
! #define CATALOG_VERSION_NO    201004201

  #endif
Index: src/include/catalog/pg_auth_members.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/pg_auth_members.h,v
retrieving revision 1.8
diff -c -r1.8 pg_auth_members.h
*** src/include/catalog/pg_auth_members.h    5 Jan 2010 01:06:56 -0000    1.8
--- src/include/catalog/pg_auth_members.h    20 Apr 2010 21:28:40 -0000
***************
*** 27,34 ****
   * ----------------
   */
  #define AuthMemRelationId    1261

! CATALOG(pg_auth_members,1261) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
  {
      Oid            roleid;            /* ID of a role */
      Oid            member;            /* ID of a member of that role */
--- 27,35 ----
   * ----------------
   */
  #define AuthMemRelationId    1261
+ #define AuthMemRelation_Rowtype_Id    2843

! 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 */
Index: src/include/catalog/pg_authid.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/pg_authid.h,v
retrieving revision 1.12
diff -c -r1.12 pg_authid.h
*** src/include/catalog/pg_authid.h    5 Jan 2010 01:06:56 -0000    1.12
--- src/include/catalog/pg_authid.h    20 Apr 2010 21:28:40 -0000
***************
*** 40,47 ****
   * ----------------
   */
  #define AuthIdRelationId    1260

! CATALOG(pg_authid,1260) BKI_SHARED_RELATION
  {
      NameData    rolname;        /* name of role */
      bool        rolsuper;        /* read this field via superuser() only! */
--- 40,48 ----
   * ----------------
   */
  #define AuthIdRelationId    1260
+ #define AuthIdRelation_Rowtype_Id    2842

! 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! */
***************
*** 71,77 ****
   *        compiler constants for pg_authid
   * ----------------
   */
! #define Natts_pg_authid                    11
  #define Anum_pg_authid_rolname            1
  #define Anum_pg_authid_rolsuper            2
  #define Anum_pg_authid_rolinherit        3
--- 72,78 ----
   *        compiler constants for pg_authid
   * ----------------
   */
! #define Natts_pg_authid                    10
  #define Anum_pg_authid_rolname            1
  #define Anum_pg_authid_rolsuper            2
  #define Anum_pg_authid_rolinherit        3
Index: src/include/catalog/toasting.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/toasting.h,v
retrieving revision 1.13
diff -c -r1.13 toasting.h
*** src/include/catalog/toasting.h    6 Jan 2010 03:04:03 -0000    1.13
--- src/include/catalog/toasting.h    20 Apr 2010 21:28:40 -0000
***************
*** 49,57 ****
  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
--- 49,54 ----

pgsql-hackers by date:

Previous
From: Josh Berkus
Date:
Subject: Re: Vacuum cancels autovacuum error message confusing?
Next
From: Robert Haas
Date:
Subject: Re: Thoughts on pg_hba.conf rejection