【发布时间】:2020-08-02 22:30:34
【问题描述】:
我有一个我写的 postgres 触发器。它100%有效,我已经对其进行了彻底的测试。但是,当我的应用程序写入该数据库表时,它会失败。我把代码放在下面,然后我会解释失败的原因。
CREATE OR REPLACE FUNCTION validate_client_user_role()
RETURNS trigger AS
$BODY$
DECLARE role_has_client INT;
DECLARE user_has_client INT;
BEGIN
IF NEW.client_id IS NULL THEN
RAISE EXCEPTION 'client_id cannot be null';
END IF;
IF NEW.user_id IS NULL THEN
RAISE EXCEPTION 'user_id cannot be null';
END IF;
IF NEW.role_id IS NULL THEN
RAISE EXCEPTION 'role_id cannot be null';
END IF;
SELECT COUNT(*)
INTO role_has_client
FROM roles
WHERE id = NEW.role_id
AND client_id = NEW.client_id;
SELECT COUNT(*)
INTO user_has_client
FROM client_users
WHERE user_id = NEW.user_id
AND client_id = NEW.client_id;
IF role_has_client = 0 THEN
RAISE EXCEPTION 'Role is not allowed by client';
END IF;
IF user_has_client = 0 THEN
RAISE EXCEPTION 'User is not allowed by client';
END IF;
RETURN NEW;
END
$BODY$ LANGUAGE plpgsql;
CREATE TRIGGER client_user_role_validation
BEFORE INSERT OR UPDATE
ON client_user_roles
FOR EACH ROW
EXECUTE PROCEDURE validate_client_user_role();
所以,我的应用程序数据库有多个模式,一个用于 dev、qa、prod 等。当我第一次编写这个 DDL 语句时,我首先运行它:
set search_path to dev;
然后将其正确添加到“dev”架构中。只要我在我的数据库查询控制台中,我就可以验证这个触发器是否正常工作。
但是,当我的应用程序尝试写入表时,触发器失败,说它尝试从不存在选择的关系(角色、client_users)。我可以通过修改函数代码以显式引用每个表的“dev”模式来解决这个问题。不过,我不想这样做。我更喜欢可以作为 dev/qa/prod 的 DDL 语句执行的代码,而无需替换所有架构引用或保留它的多个副本。
我希望有人能解释一下是否有办法做到这一点。显然,触发器不是从我执行它时分配给它的架构继承的。但是,如果有一些我不知道的 postgres 技巧来完成这项工作,我将不胜感激。谢谢。
【问题讨论】:
标签: postgresql