我正在寻找确认和可能的解释。
在 PostgreSQL 中,我创建一个表 A,通过带有约束选项
ON DELETE UPDATE SET DEFAULT
的 FK 引用表 B。如果删除表 B 中引用的记录,则原始 FK 默认值的物理“更改”显然是由“系统角色”完成的(在我的例子中postgres)
现在,我在表 A 上设置了某些其他触发器,当我的“is_locked”列设置为
True
时,这些触发器会阻止编辑。根据所描述的角色切换,我期望我可以让改变发生(即使使用 is_locker==True
if current_role = 'postgres'
。
但是,只有当触发器是“更新之前”而不是“更新之后”时,这才起作用。换句话说,根据我的观察,当记录被物理更新时,数据库将执行角色更改回原始角色(删除表 B 中的记录的角色)。
这是预料之中的事情吗?如果是这样,您认为我应该如何处理“如果角色是 postgres 则允许编辑”,即使在插入记录之后?
复制和观察的代码:
BEGIN;
CREATE TABLE parent (id INT PRIMARY KEY, name VARCHAR(100));
CREATE TABLE child (
id INT PRIMARY KEY,
parent_id INT DEFAULT 0,
edited_by text,
CONSTRAINT fk_parent FOREIGN KEY (parent_id) REFERENCES parent (id) ON DELETE SET DEFAULT
);
CREATE TABLE logs ("text" text);
CREATE OR REPLACE FUNCTION react_on_child_update () RETURNS TRIGGER AS $$
BEGIN
INSERT INTO logs ("text") VALUES (CURRENT_role::text);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_before_react_on_child_update BEFORE
UPDATE ON child FOR EACH ROW
EXECUTE FUNCTION react_on_child_update();
CREATE TRIGGER trigger_after_react_on_child_update
AFTER UPDATE ON child FOR EACH ROW
EXECUTE FUNCTION react_on_child_update();
INSERT INTO parent (id, name) VALUES (0, 'ghost');
INSERT INTO parent (id, name) VALUES (1, 'Parent 1');
INSERT INTO parent (id, name) VALUES (2, 'Parent 2');
INSERT INTO child (id, parent_id) VALUES (1, 1);
INSERT INTO child (id, parent_id) VALUES (2, 2);
CREATE ROLE "user";
GRANT ALL ON TABLE parent,logs,child TO "user";
SET ROLE TO "user";
DELETE FROM parent
WHERE id = 1;
SELECT * FROM parent;
SELECT * FROM child;
-- See that first role was the admin one, second the caller ("user")
SELECT * FROM logs;
非常感谢!
postgres 作为更新中的凭据。但那是因为我已经登录到数据库了。不确定我是否理解此测试的目的。