Список грантов и привилегий для материализованного представления в PostgreSQL

Мне нужно определить, какие привилегии в настоящее время предоставляются для некоторых материализованных представлений в моей базе данных.

запрос, чтобы сделать это на столе или стандартный вид является довольно прямо вперед:

SELECT grantee, string_agg(privilege_type, ', ') AS privileges
FROM information_schema.table_privileges
WHERE table_schema = 'some_schema' AND table_name = 'some_table'
GROUP by grantee;

тем не менее, похоже, нет аналогичной таблицы для материализованных представлений. Где PostgreSQL хранит эту информацию?

2 ответов


В Postgres система каталогов являются базовым набором полной информации об установке и базах данных. Системные каталоги являются наиболее надежным источником информации. информация-схемы как вспомогательная функция основана на системных каталогах и предоставляется для совместимости с другими СУБД:

схема информации определена в стандарте SQL и поэтому можно ожидать, что она будет переносимой и останется стабильной - в отличие от системные каталоги, которые специфичны для PostgreSQL и моделируются после проблем реализации. Однако представления информационной схемы не содержат сведений о функциях, специфичных для PostgreSQL; чтобы узнать о них, необходимо запросить системные каталоги или другие представления, специфичные для PostgreSQL.

материализованные представления не являются объектами SQL-стандарта, поэтому информационная схема не содержит информации о них.

системный каталог pg_class содержит вся информация о привилегиях в графе relacl.

если колонки null тогда владелец имеет все привилегии.

пустая строка в качестве имени пользователя в acl строка означает public.

create materialized view test_view as select 1;
grant select on test_view to public;
grant delete on test_view to a_user;

select 
    coalesce(nullif(s[1], ''), 'public') as grantee, 
    s[2] as privileges
from 
    pg_class c
    join pg_namespace n on n.oid = relnamespace
    join pg_roles r on r.oid = relowner,
    unnest(coalesce(relacl::text[], format('{%s=arwdDxt/%s}', rolname, rolname)::text[])) acl, 
    regexp_split_to_array(acl, '=|/') s
where nspname = 'public' and relname = 'test_view';

 grantee  | privileges 
----------+------------
 postgres | arwdDxt
 public   | r
 a_user   | d
(3 rows)

вам нужна функция для отображения привилегий в читабельный:

create or replace function priviliges_from_acl(text)
returns text language sql as $$
    select string_agg(privilege, ', ')
    from (
        select 
            case ch
                when 'r' then 'SELECT'
                when 'w' then 'UPDATE'
                when 'a' then 'INSERT'
                when 'd' then 'DELETE'
                when 'D' then 'TRUNCATE'
                when 'x' then 'REFERENCES'
                when 't' then 'TRIGGER'
            end privilege
        from
            regexp_split_to_table(, '') ch
    ) s 
$$;

использование:

select 
    coalesce(nullif(s[1], ''), 'public') as grantee, 
    priviliges_from_acl(s[2]) as privileges
from 
    pg_class c
    join pg_namespace n on n.oid = relnamespace
    join pg_roles r on r.oid = relowner,
    unnest(coalesce(relacl::text[], format('{%s=arwdDxt/%s}', rolname, rolname)::text[])) acl, 
    regexp_split_to_array(acl, '=|/') s
where nspname = 'public' and relname = 'test_view';

 grantee  |                          privileges                           
----------+---------------------------------------------------------------
 postgres | INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER
 public   | SELECT
 a_user   | DELETE
(3 rows)

следуя полезному ответу клина, я придумал представление, в котором перечислены все привилегии для всех отношений, которые появляются в pg_class (таблицы, представления, м. представления, индексы, последовательности, внешние таблицы, составные типы) для всех ролей:

CREATE VIEW show_privileges AS (
    SELECT
        grantee,
        string_agg(relname, ', ' ORDER BY relname) AS rel_names,
        privileges
    FROM (
        SELECT 
            relname,
            coalesce(nullif(s[1], ''), 'public') grantee, 
            (SELECT string_agg(privilege, ', ' ORDER BY privilege ASC)
                FROM (SELECT
                    CASE ch
                        WHEN 'r' THEN 'SELECT'
                        WHEN 'w' THEN 'UPDATE'
                        WHEN 'a' THEN 'INSERT'
                        WHEN 'd' THEN 'DELETE'
                        WHEN 'D' THEN 'TRUNCATE'
                        WHEN 'x' THEN 'REFERENCES'
                        WHEN 't' THEN 'TRIGGER'
                    END AS privilege
                    FROM regexp_split_to_table(s[2], '') ch
                ) s
            ) AS privileges
        FROM 
            pg_class
            JOIN pg_namespace ON pg_namespace.oid = relnamespace
            JOIN pg_roles ON pg_roles.oid = relowner,
            unnest(coalesce(relacl::text[], format('{%s=arwdDxt/%s}', rolname, rolname)::text[])) AS acl,
            regexp_split_to_array(acl, '=|/') AS s
        WHERE nspname = 'public'
    ) AS t
    GROUP BY grantee, privileges
    ORDER BY grantee, privileges, rel_names
);