确定触发器功能内的更新是否导致触发另一个触发器

时间:2015-05-10 02:28:23

标签: postgresql postgresql-9.4

我想知道是否从另一个触发器函数内部调用了插入/更新/删除操作,这样我就可以在表X上应用一个不允许插入/更新/删除操作的触发器,除非该操作是从表Y上的触发器功能。

换句话说,我希望在发出插入/更新/删除操作时在表Y上有一个触发器,检查是否从表X触发器调用了操作,如果是,则继续 - 否则,拒绝行动。

我还认为,触发器功能可用的“请求源”信息可能有助于调试,具体取决于触发器的层次结构。

1 个答案:

答案 0 :(得分:2)

您在此提出的建议违背了启用或拒绝访问数据库中数据的标准方法。通常,您可以通过GRANT对表和函数的权限来解决此问题。您的案例可以这样解决:

首先,创建具有特定角色(= user,group)的表,例如“admin”。

CREATE TABLE x (...);
ALTER TABLE x OWNER to admin; -- Not necessary if "admin" created the table

CREATE TABLE y (...);
ALTER TABLE y OWNER to admin;

此时只有角色“admin”可以访问这些表。如果您希望其他用户(例如,角色“app_user”)从表x中进行选择并从表y中选择,插入,更新和删除,那么您应该明确GRANT这些权限:< / p>

GRANT SELECT ON x TO app_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON y TO app_user;

然后在表y上定义触发器,并在触发器功能中将更改级联到表x;我想你已经解决了这个问题。这里的诀窍是让“admin”用户作为触发器函数的所有者(这是合乎逻辑的,因为只有“admin”可以CREATE TRIGGER在表y上),然后使用SECURITY DEFINER。这意味着即使“app_user”执行调用触发器的INSERT INTO y ...,也会使用用户“admin”的权限执行级联表x上的操作的触发器函数:

CREATE FUNCTION my_trigger_func RETURNS trigger AS $$
BEGIN
  -- Perform some operation on x
  RETURN NEW; -- or OLD
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

ALTER FUNCTION my_trigger_func OWNER TO admin; -- If needed
REVOKE ALL ON FUNCTION my_trigger_func FROM public;

CREATE TRIGGER my_trigger
  BEFORE INSERT, UPDATE, DELETE ON y -- or AFTER, depending on your needs
  FOR EACH ROW EXECUTE PROCEDURE my_trigger_func();

请注意,触发器函数不需要GRANT EXECUTE:因为“app_user”具有调用触发器运行触发器功能的表y的权限,所以允许“app_user”执行触发功能。

遵循此过程,“app_user”可以修改表x的唯一方法是通过表y。使用“admin”可以直接修改表x,但作为表和触发器所有者,此角色应该知道比直接修改表x更好。