Postgres行级安全(RLS)插入策略中查询值引用问题排查
解决Postgres RLS插入策略的字段引用问题
你遇到的核心问题是子查询中对插入字段的引用歧义:Postgres会把你写的owner_id和contact_id默认解析为子查询里connection c表的字段,而不是你要插入的新行的字段。这就导致只要目标用户在connection表的任何行存在,就会触发冲突,完全偏离了你的预期逻辑。
修正后的RLS策略
你需要用Postgres的NEW关键字来明确引用待插入的新行数据,修正后的策略如下:
CREATE POLICY "Participants INSERT" ON public.connection FOR INSERT WITH CHECK ( auth.uid() = NEW.owner_id AND NOT EXISTS( SELECT * FROM public.connection c WHERE ( (c.owner_id = NEW.owner_id AND c.contact_id = NEW.contact_id) OR (c.contact_id = NEW.owner_id AND c.owner_id = NEW.contact_id) ) ) AND EXISTS( SELECT * FROM public.request r WHERE ( r.sender_id = NEW.contact_id AND r.recipient_id = NEW.owner_id ) ) );
关键修正点解释
- 用
NEW指代插入行:NEW是Postgres触发器和RLS策略中的特殊变量,专门用来引用即将插入的新行的字段值。通过NEW.owner_id和NEW.contact_id,你明确告诉数据库:我要对比的是这次插入的owner和contact,而不是子查询表中的任意行。 - 逻辑验证:
- 确保当前用户是插入连接的
owner_id(auth.uid() = NEW.owner_id) - 检查双方不存在任何形式的双向连接(无论是我加他还是他加我)
- 确认存在对应的请求记录(对方发送给当前用户的请求)
- 确保当前用户是插入连接的
测试建议
你可以用以下语句测试策略是否生效:
-- 替换为实际的用户UUID INSERT INTO connection (owner_id, contact_id) VALUES ('你的用户UUID', '请求方用户UUID');
如果满足所有条件(存在对应请求、无现有连接),插入会成功;否则会触发RLS违规错误,符合你的预期逻辑。
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

