2222#include "catalog/pg_auth_members.h"
2323#include "catalog/pg_authid.h"
2424#include "catalog/pg_class.h"
25+ #include "catalog/pg_database.h"
2526#include "catalog/pg_type.h"
2627#include "commands/dbcommands.h"
2728#include "commands/proclang.h"
@@ -68,6 +69,7 @@ enum RoleRecurseType
6869};
6970static Oid cached_role []= {InvalidOid ,InvalidOid };
7071static List * cached_roles []= {NIL ,NIL };
72+ static uint32 cached_db_hash ;
7173
7274
7375static const char * getid (const char * s ,char * n );
@@ -4665,17 +4667,24 @@ initialize_acl(void)
46654667{
46664668if (!IsBootstrapProcessingMode ())
46674669{
4670+ cached_db_hash =
4671+ GetSysCacheHashValue1 (DATABASEOID ,
4672+ ObjectIdGetDatum (MyDatabaseId ));
4673+
46684674/*
46694675 * 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())
46724678 */
46734679CacheRegisterSyscacheCallback (AUTHMEMROLEMEM ,
46744680RoleMembershipCacheCallback ,
46754681 (Datum )0 );
46764682CacheRegisterSyscacheCallback (AUTHOID ,
46774683RoleMembershipCacheCallback ,
46784684 (Datum )0 );
4685+ CacheRegisterSyscacheCallback (DATABASEOID ,
4686+ RoleMembershipCacheCallback ,
4687+ (Datum )0 );
46794688}
46804689}
46814690
@@ -4686,6 +4695,13 @@ initialize_acl(void)
46864695static void
46874696RoleMembershipCacheCallback (Datum arg ,int cacheid ,uint32 hashvalue )
46884697{
4698+ if (cacheid == DATABASEOID &&
4699+ hashvalue != cached_db_hash &&
4700+ hashvalue != 0 )
4701+ {
4702+ return ;/* ignore pg_database changes for other DBs */
4703+ }
4704+
46894705/* Force membership caches to be recomputed on next use */
46904706cached_role [ROLERECURSE_PRIVS ]= InvalidOid ;
46914707cached_role [ROLERECURSE_MEMBERS ]= InvalidOid ;
@@ -4728,6 +4744,7 @@ static List *
47284744roles_is_member_of (Oid roleid ,enum RoleRecurseType type ,
47294745Oid admin_of ,bool * is_admin )
47304746{
4747+ Oid dba ;
47314748List * roles_list ;
47324749ListCell * l ;
47334750List * new_cached_roles ;
@@ -4740,6 +4757,24 @@ roles_is_member_of(Oid roleid, enum RoleRecurseType type,
47404757OidIsValid (cached_role [type ]))
47414758return cached_roles [type ];
47424759
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+
47434778/*
47444779 * Find all the roles that roleid is a member of, including multi-level
47454780 * 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,
47874822roles_list = list_append_unique_oid (roles_list ,otherid );
47884823}
47894824ReleaseSysCacheList (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 );
47904830}
47914831
47924832/*