我正在使用AWS Aurora Postgres 14(14.5),并设置了此表(在铁 rust 中的柴油的帮助下)->

create table contacts (
    email TEXT NOT NULL,
    user_id TEXT NOT NULL,
    contact_data JSONB,
    user_groups TEXT[],
    tenant_groups TEXT[],
    tags TEXT[],
    PRIMARY KEY (email, user_id)
);

使用政策->

ALTER TABLE contacts FORCE ROW LEVEL SECURITY;
CREATE POLICY select_contacts_policy ON contacts 
FOR SELECT
USING (user_id = current_setting('myapp.user_id'));
ALTER TABLE contacts ENABLE ROW LEVEL SECURITY;

CREATE POLICY insert_contacts_policy ON contacts 
FOR INSERT
WITH CHECK (true);
ALTER TABLE contacts ENABLE ROW LEVEL SECURITY;

在向该表插入新数据时,我首先设置了一个名为user_id(字符串)的会话参数(使用迪塞尔的sql_query函数)->

sql_query(format!("SET SESSION myapp.user_id = '{user_id}';")).execute(pg_conn)?;

然后我插入使用柴油->

diesel::insert_into(contacts::table)
    .values(&contacts) # a custom struct
    .on_conflict((contacts::email, contacts::user_id))
    .do_update()
    .set(&contacts)
    .execute(pg_conn)?;

在此查询之后,user_id将恢复为默认的->

sql_query("SET SESSION myapp.user_id = -1;").execute(pg_conn)?;

DIESEL函数调用转换为以下SQL查询(从Postgres日志(log)中获取)->

INSERT INTO "contacts" ("email", "user_id", "contact_data", "user_groups", "tenant_groups", "tags") VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT ("email", "user_id") DO UPDATE SET "email" = $7, "user_id" = $8, "contact_data" = $9, "user_groups" = $10, "tenant_groups" = $11, "tags" = $12

在运行此查询时,当发生冲突并触发更新分支时,我会收到以下错误消息->

new row violates row-level security policy (USING expression) for table "contacts"

我在本地有一个有点类似的postgres安装(没有多个用户,但是有相同的模式)(v14.8),它能够毫无问题地升级.

其他信息->

在此操作的用户是另一个名为backend User的用户

访问权限->Snapshot of access privileges for the contacts table

我试图运行一个EXPLAIN ANALYZE查询并将其记录下来,以查看错误发生在哪里,但该查询在完成之前就导致了违反策略.如果我在没有ANALYZE标志的情况下运行,它只会打印查询计划(但我想知道在哪里以及是什么导致了该违规)

推荐答案

这里的问题是ON CONFLICT ... DO UPDATE.普通的INSERTINSERT ... ON CONFLICT DO NOTHING将会成功.

您只能更新可以看到的行,即您具有FOR SELECT策略的行,如the documentation所述:

[.]需要SELECT个权限的查询(如UPDATE)也将仅看到SELECT策略允许的那些记录.

因此,是FOR SELECT政策和(缺失)FOR UPDATE政策在这里给你带来了麻烦.这有点令人惊讶,因为有人可能会争辩说,只有在INSERT期间发生冲突时才应该得到该错误.然而,要确定是否存在冲突,您已经需要能够从表中提取SELECT.如果没有冲突,添加FOR SELECT策略将使语句成功.如果存在is个冲突,则需要额外的FOR UPDATE个策略.

您必须添加允许插入角色无条件更新和 Select 的策略:

CREATE POLICY inserter_may_select ON contacts FOR SELECT TO inserter
   USING (TRUE);
CREATE POLICY inserter_may_update ON contacts FOR UPDATE TO inserter
   USING (TRUE);

Postgresql相关问答推荐

Postgres:如何优化在多个表上搜索列的相似性查询?(Pg_Trgm)

PostgreSQL:重新创建主键值以匹配记录计数

ANTLR4 PostgreSQL语法被 destruct 了吗?

忽略 split_part 的第 n 个分隔符之后

为什么我的唯一索引在 Postgresql 中不起作用?

安装age-installation时出错

使用Helm设置PostgreSQL配置

从单选插入到多个表

Upper() 不会大写重音字符

如何在postgres中查询多行

Postgis 不只使用索引扫描

在postgresql中按经纬度查找最近的位置

Rails:安装 pg gem 时出错

Postgres COPY FROM csv file-No such file or directory

更新列或列或列时触发触发

如何通过我在 PostgreSQL 中的数据库获取列大小和类型

如何从 WSL 连接到 windows postgres 数据库

如何检索 PostgreSQL 数据库的 comments ?

'active' 标志与否?

PostgreSQL 不区分大小写的 SELECT 数组