22
22
#include "catalog/pg_auth_members.h"
23
23
#include "catalog/pg_authid.h"
24
24
#include "catalog/pg_class.h"
25
+ #include "catalog/pg_database.h"
25
26
#include "catalog/pg_type.h"
26
27
#include "commands/dbcommands.h"
27
28
#include "commands/proclang.h"
@@ -68,6 +69,7 @@ enum RoleRecurseType
68
69
};
69
70
static Oid cached_role [] = {InvalidOid , InvalidOid };
70
71
static List * cached_roles [] = {NIL , NIL };
72
+ static uint32 cached_db_hash ;
71
73
72
74
73
75
static const char * getid (const char * s , char * n );
@@ -4665,17 +4667,24 @@ initialize_acl(void)
4665
4667
{
4666
4668
if (!IsBootstrapProcessingMode ())
4667
4669
{
4670
+ cached_db_hash =
4671
+ GetSysCacheHashValue1 (DATABASEOID ,
4672
+ ObjectIdGetDatum (MyDatabaseId ));
4673
+
4668
4674
/*
4669
4675
* In normal mode, set a callback on any syscache invalidation of rows
4670
- * of pg_auth_members (for roles_is_member_of()) or pg_authid (for
4671
- * has_rolinherit())
4676
+ * of pg_auth_members (for roles_is_member_of()), pg_authid (for
4677
+ * has_rolinherit()), or pg_database (for roles_is_member_of())
4672
4678
*/
4673
4679
CacheRegisterSyscacheCallback (AUTHMEMROLEMEM ,
4674
4680
RoleMembershipCacheCallback ,
4675
4681
(Datum ) 0 );
4676
4682
CacheRegisterSyscacheCallback (AUTHOID ,
4677
4683
RoleMembershipCacheCallback ,
4678
4684
(Datum ) 0 );
4685
+ CacheRegisterSyscacheCallback (DATABASEOID ,
4686
+ RoleMembershipCacheCallback ,
4687
+ (Datum ) 0 );
4679
4688
}
4680
4689
}
4681
4690
@@ -4686,6 +4695,13 @@ initialize_acl(void)
4686
4695
static void
4687
4696
RoleMembershipCacheCallback (Datum arg , int cacheid , uint32 hashvalue )
4688
4697
{
4698
+ if (cacheid == DATABASEOID &&
4699
+ hashvalue != cached_db_hash &&
4700
+ hashvalue != 0 )
4701
+ {
4702
+ return ; /* ignore pg_database changes for other DBs */
4703
+ }
4704
+
4689
4705
/* Force membership caches to be recomputed on next use */
4690
4706
cached_role [ROLERECURSE_PRIVS ] = InvalidOid ;
4691
4707
cached_role [ROLERECURSE_MEMBERS ] = InvalidOid ;
@@ -4728,6 +4744,7 @@ static List *
4728
4744
roles_is_member_of (Oid roleid , enum RoleRecurseType type ,
4729
4745
Oid admin_of , bool * is_admin )
4730
4746
{
4747
+ Oid dba ;
4731
4748
List * roles_list ;
4732
4749
ListCell * l ;
4733
4750
List * new_cached_roles ;
@@ -4740,6 +4757,24 @@ roles_is_member_of(Oid roleid, enum RoleRecurseType type,
4740
4757
OidIsValid (cached_role [type ]))
4741
4758
return cached_roles [type ];
4742
4759
4760
+ /*
4761
+ * Role expansion happens in a non-database backend when guc.c checks
4762
+ * DEFAULT_ROLE_READ_ALL_SETTINGS for a physical walsender SHOW command.
4763
+ * In that case, no role gets pg_database_owner.
4764
+ */
4765
+ if (!OidIsValid (MyDatabaseId ))
4766
+ dba = InvalidOid ;
4767
+ else
4768
+ {
4769
+ HeapTuple dbtup ;
4770
+
4771
+ dbtup = SearchSysCache1 (DATABASEOID , ObjectIdGetDatum (MyDatabaseId ));
4772
+ if (!HeapTupleIsValid (dbtup ))
4773
+ elog (ERROR , "cache lookup failed for database %u" , MyDatabaseId );
4774
+ dba = ((Form_pg_database ) GETSTRUCT (dbtup ))-> datdba ;
4775
+ ReleaseSysCache (dbtup );
4776
+ }
4777
+
4743
4778
/*
4744
4779
* Find all the roles that roleid is a member of, including multi-level
4745
4780
* recursion. The role itself will always be the first element of the
@@ -4787,6 +4822,11 @@ roles_is_member_of(Oid roleid, enum RoleRecurseType type,
4787
4822
roles_list = list_append_unique_oid (roles_list , otherid );
4788
4823
}
4789
4824
ReleaseSysCacheList (memlist );
4825
+
4826
+ /* implement pg_database_owner implicit membership */
4827
+ if (memberid == dba && OidIsValid (dba ))
4828
+ roles_list = list_append_unique_oid (roles_list ,
4829
+ DEFAULT_ROLE_DATABASE_OWNER );
4790
4830
}
4791
4831
4792
4832
/*
0 commit comments