Short version:
SELECT a.oid
FROM pg_authid a
WHERE pg_has_role('maxwell', a.oid, 'member');
Here we use a version of pg_has_role
that takes a role name as the subject and role oid to test for membership, passing member
mode so we test for inherited memberships.
The advantage of using pg_has_role
is that it uses PostgreSQL's internal caches of role information to satisfy membership queries quickly.
You might want to wrap this in a SECURITY DEFINER
function, since pg_authid
has restricted access. Something like:
CREATE OR REPLACE FUNCTION user_role_memberships(text)
RETURNS SETOF oid
LANGUAGE sql
SECURITY DEFINER
SET search_path = 'pg_catalog'
AS $$
SELECT a.oid
FROM pg_authid a
WHERE pg_has_role($1, a.oid, 'member');
$$;
REVOKE EXECUTE ON FUNCTION user_role_memberships(text) FROM public;
GRANT EXECUTE ON FUNCTION user_role_memberships(text) TO ...whoever...;
You can use pg_get_userbyid(oid)
to get the role name from the oid without the need to query pg_authid
:
SELECT a.oid AS member_oid, pg_get_userbyid(oid) AS member_name
FROM pg_authid a
WHERE pg_has_role('maxwell', a.oid, 'member');