Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 触发器:允许更新到";除“foo”外,没有列;_Postgresql_Database Trigger_Row Level Security - Fatal编程技术网

Postgresql 触发器:允许更新到";除“foo”外,没有列;

Postgresql 触发器:允许更新到";除“foo”外,没有列;,postgresql,database-trigger,row-level-security,Postgresql,Database Trigger,Row Level Security,假设我们有一张这样的桌子: Table "someschema.todo" Column | Type | Nullable | Default --------------+--------------+----------+---------------------------------- id | integer | not null | nextval

假设我们有一张这样的桌子:

                         Table "someschema.todo"
    Column    |    Type      | Nullable |             Default
--------------+--------------+----------+----------------------------------
 id           | integer      | not null | nextval('todo_id_seq'::regclass)
 contract_id  | integer      | not null |
 title        | text         |          |
 description  | text         |          |
 status       | todo_status  |          | 'INCOMPLETE'::todo_status
Foreign-key constraints:
    "todo_contract_id_fkey" FOREIGN KEY (contract_id) REFERENCES contract(id)
行级安全性已启用,我们将假设规则已正确设置,但有一个例外:通常不允许更新此表中的
行的用户类型需要能够将
状态
列从一个
枚举
值切换到另一个。比如说,从
未完成
挂起
。该用户类型还需要能够在其他时间
更新表(取决于与
合同id相关的条件),因此我们不能只使用总括列授权

可以说,这可能会使该列成为新的
todo_status
表中的候选列,但我们暂时将其排除在外。现在我们可以编写一个触发器,按名称检查每一列,看它是否已被修改,只允许那些修改
状态的查询,而不允许其他任何查询。。。但这似乎是脆弱的(如果我们以后再增加一个专栏呢?)和痛苦的

触发器中是否有允许修改“除<代码>状态之外没有列”
?换句话说,“拒绝访问,除非唯一修改的列是
status


补充:是否有一种方法可以在
创建策略
中使用
检查表达式
使用表达式
来完成此操作?我一直在假设,因为我们在
使用
表达式中没有
新的
值,或者在
检查
表达式中没有
旧的
值,所以我不能使用RLS来实现我们所需要的

CREATE OR REPLACE FUNCTION validate_update()
RETURNS trigger AS
$BODY$
DECLARE
    v_key TEXT;
    v_value TEXT;
    valid_update boolean := true;
BEGIN
    FOR v_key, v_value IN select key, value from each(hstore(NEW))  each LOOP
        if (coalesce(v_value,'') != coalesce((hstore(OLD) -> v_key),'')) then
            if (v_key != 'status')  then
                valid_update := false;
            end if;
        end if;
    END LOOP;
    if (valid_update) then
        raise info 'good update';
        return NEW;
    else
        raise info 'bad update';
        return null;
    end if;
 END;
$BODY$
LANGUAGE plpgsql;

create trigger validate_update before update on someschema.todo 
for each row execute procedure validate_update();

谢谢,这是非常有趣的(并向我介绍了
hstore
!)