Не удается получить раздел сведений об ошибке уникального ограничения, когда действует безопасность на уровне строки

TL; DR: в Postgres 10.6 Когда действует защита на уровне строк - я не получаю раздел «ПОДРОБНЕЕ» об ошибке нарушения уникального ограничения, хотя эта роль может видеть / вставлять все строки.

У меня две роли: admin (владелец таблиц) и app_role, на которых действует безопасность на уровне строк.

Вот как воспроизвести:

--using the admin role
create table parents(
    parent_id int primary key, 
    parent_name text unique
);
create table childs(
    child_id int primary key, 
    child_name text, 
    parent_id int references parents (parent_id), 
    constraint childs_uq unique (parent_id, child_name)
);

insert into parents values(1,'aaa');
insert into childs values(1,'bbb',1);
insert into childs values(2,'bbb',1);
--SQL Error [23505]: ERROR: duplicate key value violates unique constraint "childs_uq"
--  Detail: Key (parent_id, child_name)=(1, bbb) already exists.

Обратите внимание на «Сведения: ключ (parent_id, child_name) = (1, bbb) уже существует».

Роль app_role получила следующие гранты и политики RLS:

GRANT SELECT, UPDATE, INSERT, DELETE ON parents TO app_role;
GRANT SELECT, UPDATE, INSERT, DELETE ON childs TO app_role;

CREATE POLICY parents_select
ON parents 
AS permissive
FOR SELECT
TO app_role
USING (true);

alter table parents enable row level security;

CREATE POLICY childs_select
ON childs 
AS permissive
FOR SELECT
TO app_role
USING (true);

CREATE POLICY childs_insert
ON childs 
AS permissive
FOR INSERT
TO app_role
WITH CHECK (true);

alter table childs enable row level security;

Теперь о проблеме:

--using `app_role`
insert into childs values(3,'ccc',1); -- works

insert into childs values(2,'bbb',1);
--SQL Error [23505]: ERROR: duplicate key value violates unique constraint "childs_uq"

Ошибка не содержит раздела «Подробности».

Это ошибка? Ожидаемое поведение (хотелось бы увидеть ссылку на документацию)?


person Pyrocks    schedule 27.03.2019    source источник


Ответы (1)


Это работает так, как реализовано design и задокументировано в _ 1_, в комментариях к функции BuildIndexValueDescription:

char *
BuildIndexValueDescription(Relation indexRelation,
                           Datum *values, bool *isnull)
{
[...]
    /*
     * Check permissions- if the user does not have access to view all of the
     * key columns then return NULL to avoid leaking data.
     *
     * First check if RLS is enabled for the relation.  If so, return NULL to
     * avoid leaking data.
     *
     * Next we need to check table-level SELECT access and then, if there is
     * no access there, check column-level permissions.
     */
[...]
    /* RLS check- if RLS is enabled then we don't return anything. */
    if (check_enable_rls(indrelid, InvalidOid, true) == RLS_ENABLED)
        return NULL;

Проблема с отображением деталей очевидна:

Если вы знаете, с каким ключом конфликтует ваша запись, вы можете получить некоторую информацию о строках в базе данных, которую вы не видите.

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

Также может быть проверка, видите ли вы конфликтующую строку или нет, и вы могли бы получить подробное сообщение в первом случае, но похоже, что это никого не беспокоило.

person Laurenz Albe    schedule 27.03.2019
comment
Спасибо за ссылку на источник. Думаю, я ожидал, что может быть реализовано. Было бы неплохо, если бы он работал так же. - person Pyrocks; 27.03.2019
comment
Вы можете попробовать написать патч для этого, но я не знаю, насколько это будет сложно. Все, что увеличивает время выполнения неконфликтного случая, имеет хорошие шансы быть отклоненным. - person Laurenz Albe; 27.03.2019