Я хочу создать новые схемы и перенести таблицу из общедоступной схемы в эти схемы, но всякий раз, когда я перемещаю таблицу из общедоступной схемы в другую схему, пользователь / роль, имеющий доступ к использованию в новой схеме, а также на его таблицы (включая будущие таблицы) не могут получить доступ к недавно перемещенной таблице.

Таблица (в схеме public ):

CREATE TABLE atable(ID INT);
INSERT INTO atable VALUES(1);
INSERT INTO atable VALUES(2);

Новый пользователь:

create user x_user with login password 'x_user';

Новая схема:

create schema dw;  

Затем я предоставляю ему полный доступ к новой схеме и ее таблицам:

GRANT USAGE ON SCHEMA dw TO x_user;
GRANT USAGE ON ALL SEQUENCES IN SCHEMA dw to x_user;
GRANT SELECT ON ALL TABLES IN SCHEMA dw TO x_user;  

Для таблиц, добавленных в схему в будущем

ALTER DEFAULT PRIVILEGES IN SCHEMA dw GRANT SELECT ON TABLES TO x_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA dw GRANT USAGE ON SEQUENCES TO x_user;  

Теперь я меняю схему atable на dw :

ALTER TABLE atable SET SCHEMA dw;  

Кроме того, я создаю еще одну таблицу в схеме dw :

CREATE TABLE dw.btable(id int);
INSERT INTO dw.btable VALUES(3);
INSERT INTO dw.btable VALUES(4);  

Теперь, когда я подключаюсь к базе данных, используя новые учетные данные пользователя, и запускаю:

SELECT * FROM dw.atable;

Я получаю: ERROR: permission denied for relation atable 1 statement failed.

Если я запустил тот же запрос для btable, который был создан в схеме dw , он сработает.

SELECT * FROM dw.btable;
id
---
3
4

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

Что я здесь делаю не так?

1
Yankee 14 Фев 2018 в 14:11

1 ответ

Лучший ответ

GRANT ... ON ALL TABLES IN SCHEMA влияет только на текущее содержимое схемы.

ALTER DEFAULT PRIVILEGES IN SCHEMA влияет на таблицы, созданные в схеме.

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

Это можно сделать, создав триггер события. который запускается по любой команде ALTER TABLE и применяет соответствующий GRANT. К сожалению, хотя вы можете написать эти триггерные функции в PL / pgSQL, я не думаю, что (в настоящее время) он предоставляет какой-либо способ узнать, что это была за команда; вам нужно либо:

  • Напишите функцию C для проверки структуры pg_ddl_command, возвращаемой pg_event_trigger_ddl_commands() или
  • Слепо запускайте GRANT после каждого ALTER TABLE, независимо от того, была ли это команда SET SCHEMA.

Гораздо более простой вариант - при условии, что он соответствует вашему варианту использования - это написать функцию move_table(), которая объединяет команды ALTER и GRANT.

1
Nick Barnes 15 Фев 2018 в 01:14