Как сравнить старые и новые значения строки в политике postgres для обновления

#sql #postgresql #row-level-security

Вопрос:

У меня есть структура разрешений, так что конкретное разрешение позволяет редактировать только 2 из 5 полей в моей таблице. У меня есть RLS во всей моей системе, поэтому мне нужно выполнить вышеуказанное в политике.

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

Вот указанная функция:

 CREATE OR REPLACE FUNCTION is_user_updating_non_permitted_fields(id uuid, fieldA integer, fieldB text...)
.....
 DECLARE
  old_row MY_TABLE
 BEGIN
  SELECT * FROM MY_TABLE m WHERE id = m.id INTO old_row;
  IF (fieldA != old_row.fieldA OR fieldB != old_row.fieldB)
    THEN RETURN 1;
    ELSE RETURN 0;
  ENDIF;
 END;
....
 

И политика будет чем-то вроде:

 CREATE POLICY my_table_update ON MY_TABLE FOR UPDATE
WITH CHECK (
 (SELECT CASE WHEN (
    ''use function here''
   ) = 1 THEN false ELSE true END;
 )
)
 

В качестве последнего средства я подумал о том, чтобы сделать триггер перед обновлением и использованием ROLLBACK TRANSACTION , но я действительно не хочу идти этим путем.

Ответ №1:

Согласно документации, это невозможно:

Будут разрешены только строки, для которых выражение имеет значение true. Ошибка будет выдана, если выражение примет значение false или null для любой из вставленных записей или любых записей, полученных в результате обновления. Обратите внимание, что значение check_expression оценивается по предлагаемому новому содержимому строки, а не по исходному содержимому.

В конце концов, вам придется использовать триггер.