Перейти к основному содержимому

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:

СтолбецТип данныхОписание
objoidoid ссылается на pg_class.oidOID определенного объекта
classoidoid ссылается на (pg_class.oid)OID системного каталога, в котором находится объект
objsubidint4Для столбца таблицы это номер столбца (objoid и classoid относятся к самой таблице). Для всех остальных типов объектов этот столбец равен нулю
privtypecharКод, определяющий тип начальной привилегии этого объекта; см. текст
initprivsaclitem[]Начальные права доступа

До версии 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)