воскресенье, 27 марта 2016 г.

Наследование и права на дочерние таблицы

Неожиданный вопрос от слушателей нашего курса DBA1, прошедшего в Омске со 2-го по 4-е декабря 2015г.
Есть две таблицы: родительская и дочерняя. Пользователю выдали права на родительскую таблицу, но не выдали на дочернюю. Обращаясь к родительской таблице, сможет он увидеть строки дочерней?

Моделируем ситуацию

postgres=# create user u1 login;
CREATE ROLE
postgres=# create user u2 login;
CREATE ROLE
postgres=# \c - u1
You are now connected to database "postgres" as user "u1".
postgres=> create table tab (c text);
CREATE TABLE
postgres=> create table tab_child () inherits (tab);
CREATE TABLE
postgres=> insert into tab values ('parent table');
INSERT 0 1
postgres=> insert into tab_child values ('child table');
INSERT 0 1
postgres=> select * from tab;
      c      
--------------
 parent table
 child table
(2 rows)
postgres=> grant select, insert, update, delete on tab to u2;
GRANT
postgres=> \c - u2
You are now connected to database "postgres" as user "u2".
postgres=> select * from tab;
 
Каков будет результат запроса?
  • Только строки из родительской таблицы
  • Ошибка из-за отстутствия прав доступа к дочерней
  • Все записи из обеих таблиц
  • Другое

Проверяем

Итак результат:

postgres=> select * from tab;
      c      
--------------
 parent table
 child table
(2 rows)
 
Не смотря на то, что прав на дочернюю таблицу пользователь не имеет, запрос к родительской таблице вернет все записи, включая записи дочерней таблицы. По такому же принципу, права на update и delete для родительской таблицы, позволяют изменять и удалять записи в дочерней:

postgres=> update tab set c = c ||'!';
UPDATE 2
postgres=> select * from tab;
       c      
---------------
 parent table!
 child table!
(2 rows)
postgres=> delete from tab;
DELETE 2
postgres=> select * from tab;
 c
---
(0 rows)
 
При этом, прямой запрос к дочерней таблицы завершится ошибкой, из-за недостаточных прав:

postgres=> select * from tab_child;
ERROR:  permission denied for relation tab_child

Объяснение

Если результат оказался неожиданным, то не помешает внимательно [пере|про]читать документацию:
“Note how table access permissions are handled. Querying a parent table can automatically access data in child tables without further access privilege checking. This preserves the appearance that the data is (also) in the parent table. Accessing the child tables directly is, however, not automatically allowed and would require further privileges to be granted.”

Комментариев нет: