pg_init_privs
Эта страница переведена при помощи нейросети GigaChat.
В каталоге pg_init_privs
хранится информация о начальных привилегиях объектов в системе. Для каждого объекта в базе данных, имеющего начальный набор привилегий не по умолчанию (не NULL), существует одна запись.
Объекты могут иметь начальные привилегии либо путем установки этих привилегий при инициализации системы (с помощью initdb
), либо когда объект создается в процессе CREATE EXTENSION и сценарий расширения устанавливает начальные привилегии с помощью системы GRANT. Обратите внимание, что система автоматически обрабатывает запись привилегий во время сценария расширения, и авторам расширений нужно только использовать операторы GRANT
и REVOKE
в своем сценарии, чтобы записать привилегии. Столбец privtype
указывает, была ли начальная привилегия установлена initdb
или во время команды CREATE EXTENSION
.
Объекты с начальными привилегиями, установленными initdb
, будут иметь записи с privtype 'i'
, а объекты с начальными привилегиями, установленными CREATE EXTENSION
, будут иметь записи с privtype 'e'
.
Столбцы pg_init_privs
:
Столбец | Тип данных | Описание |
---|---|---|
objoid | oid ссылается на pg_class.oid | OID определенного объекта |
classoid | oid ссылается на (pg_class.oid) | OID системного каталога, в котором находится объект |
objsubid | int4 | Для столбца таблицы это номер столбца (objoid и classoid относятся к самой таблице). Для всех остальных типов объектов этот столбец равен нулю |
privtype | char | Код, определяющий тип начальной привилегии этого объекта; см. текст |
initprivs | aclitem[] | Начальные права доступа |
До версии PostgreSQL 15.8 существовала проблема с удалением записей в каталоге pg_init_privs
. Когда таблица удалялась вместе с соответствующим ей расширением, такие привилегии могли оставаться незадействованными, поскольку отсутствовал механизм автоматического удаления связанных записей. Поведение изменено с версии 15.8, но оставшиеся ранее лишние записи, связь которых с таблицами когда-то удаленных расширений потеряна, могут при переиспользовании OID таблицы негативно проявить себя. Стоит их обнаружить и предупредить пользователя или удалить вместе с общей автоматической или ручной логикой.
Пример запроса на выборку оставшихся записей о правах с примером результата выполнения запроса:
SELECT p.objoid, p.classoid, p.objsubid, p.privtype,
pg_catalog.format('delete from pg_init_privs pd where pd.objoid = %s and pd.classoid = %s and pd.objsubid = %s and pd.privtype= ''e'';', p.objoid, p.classoid, p.objsubid) sqlcommand
FROM pg_init_privs p
WHERE
p.privtype = 'e' AND
classoid = 'pg_class'::regclass AND
NOT EXISTS (SELECT 1 FROM pg_class cl WHERE cl.oid = p.objoid);
objoid | classoid | objsubid | privtype | sqlcommand
--------+----------+----------+----------+-----------------------------------------------------------------------------------------------------------------------
78724 | 1259 | 1 | e | delete from pg_init_privs pd where pd.objoid = 78724 and pd.classoid = 1259 and pd.objsubid = 1 and pd.privtype= 'e';
(1 row)
Пример удаления найденной лишней записи:
delete from pg_init_privs pd where pd.objoid = 78724 and pd.classoid = 1259 and pd.objsubid = 1 and pd.privtype= 'e';
Повторный запрос проверки наличия устаревших записей:
SELECT p.objoid, p.classoid, p.objsubid, p.privtype,
pg_catalog.format('delete from pg_init_privs pd where pd.objoid = %s and pd.classoid = %s and pd.objsubid = %s and pd.privtype= ''e'';', p.objoid, p.classoid, p.objsubid) sqlcommand
FROM pg_init_privs p
WHERE
p.privtype = 'e' AND
classoid = 'pg_class'::regclass AND
NOT EXISTS (SELECT 1 FROM pg_class cl WHERE cl.oid = p.objoid);
objoid | classoid | objsubid | privtype | sqlcommand
--------+----------+----------+----------+------------
(0 rows)