postgresql - Postgres - 创建可以存在于多个模式中的触发器
问题描述
我有一个我写的 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;
然后将其正确添加到“开发”模式中。只要我在我的数据库查询控制台中,我就可以验证这个触发器是否正常工作。
但是,当我的应用程序尝试写入表时,触发器失败,说它尝试执行的选择的关系(角色、client_users)不存在。我可以通过修改函数代码以显式引用每个表的“dev”模式来解决这个问题。不过,我不想这样做。我更喜欢可以作为 dev/qa/prod 的 DDL 语句执行的代码,而无需替换所有模式引用或保留它的多个副本。
我希望有人可以解释是否有某种方法可以做到这一点。显然,触发器不是从我执行它时分配给它的架构继承的。但是,如果有一些我不知道的 postgres 技巧来完成这项工作,我将不胜感激。谢谢你。
解决方案
您可以使用TG_TABLE_SCHEMA
变量和set_config()
withIS_LOCAL = true
来完成此操作:
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;
PERFORM set_config('search_path', TG_TABLE_SCHEMA, true); -- <-- This line
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;
推荐阅读
- node.js - 在 Node.js 中使用 WriteStream 和 replace-in-file 写入时出现问题
- javascript - 将事件开始时间放在开始选项中时出现 FullCalendar 错误
- django - 引导日期选择器在 django 中不起作用
- odoo - Odoo12:如何在不弹出的情况下从 tree_view 显示 form_view?
- javascript - 当单击javascript中的复选框时,动态字符限制长度上的textarea的字符数?
- html - 如何从 WordPress 项目中编码的图像 html 标记中删除通用 css 属性?
- javascript - 在 Javascript 中为循环中生成的每个值创建一个按钮
- html - 限制文件输入类型控制只选择文本文件
- android - 如何将视图模型变量与自定义类类型绑定
- mysql - SQL中的存储过程具有不同语句的计数