Список грантов и привилегий для материализованного представления в 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
);