Каскадное обновление всегда запускается в контексте безопасности владельца ссылочной таблицы (test.table
в вашем примере).
См. ri_PerformCheck
в src/backend/utils/adt/ri_triggers.c
:
/*
* Use the query type code to determine whether the query is run against
* the PK or FK table; we'll do the check as that table's owner
*/
if (qkey->constr_queryno <= RI_PLAN_LAST_ON_PK)
query_rel = pk_rel;
else
query_rel = fk_rel;
...
/* Switch to proper UID to perform check as */
GetUserIdAndSecContext(&save_userid, &save_sec_context);
SetUserIdAndSecContext(RelationGetForm(query_rel)->relowner,
save_sec_context | SECURITY_LOCAL_USERID_CHANGE |
SECURITY_NOFORCE_RLS);
Я пытался следовать коду до его источника, и поведение, кажется, происходит из commit 465cf168eb6151275016486fe2d2c629fed967ca .
При поиске в архивах хакеров соответствующих обсуждений я обнаружил это .
Итак, насколько я могу сказать, поведение пытается избежать следующего:
Пользователь A
владеет atable
и предоставляет REFERENCES
в этой таблице пользователю B
.
Пользователь B
владеет btable
и добавляет внешний ключ к atable
с помощью ON UPDATE OR DELETE CASCADE
.Пользователь A
не имеет разрешений на btable
.
Пользователь A
пытается обновить или удалить строку в atable
, которая может каскадно перейти к btable
, и завершается неудачно сОшибка «отказано в разрешении».
Лично я не уверен, является ли данное поведение хорошим или нет, но я вижу, что было бы удивительно, если бы A
'небыть в состоянии изменить таблицу, которой она владеет.