PostgreSQL 事件触发器强制将扩展安装到特定模式

zam*_*6ak 5 postgresql trigger dml ddl ddl-trigger

我有一个专用架构extensions(PostgreSQL v 9.6.3),我打算在其中安装我的数据库的所有扩展。我想以某种方式禁止(或至少提醒)用户在没有指定特定架构的情况下安装扩展。

所以这应该失败

CREATE EXTENSION tablefunc;
Run Code Online (Sandbox Code Playgroud)

但这应该会成功:

CREATE EXTENSION tablefunc SCHEMA extensions;
Run Code Online (Sandbox Code Playgroud)

为此,我尝试创建事件触发器:

CREATE EVENT TRIGGER e010_verify_extension_schema_et
  ON ddl_command_end
  WHEN TAG IN ('CREATE EXTENSION')
  EXECUTE PROCEDURE verify_extension_schema();
Run Code Online (Sandbox Code Playgroud)

verify_extension_schema()功能上,我正在尝试使用pg_catalog.pg_event_trigger_ddl_commands(). 但是,该函数不会返回任何我可以用来检查是否已指定架构或与此相关的架构的任何内容...

有没有人有任何想法我怎么能做到这一点?

Eva*_*oll 3

确保您正在使用ddl_command_end,它仍然可能会失败或提醒用户这就是您想要的。从文档中

同样,如果ddl_command_end触发器因错误而失败,则 DDL 语句的效果将回滚,就像包含事务中止的任何其他情况一样。

不幸的是,之后你有两个选择

  1. 处理它可能会做出假设,但只知道扩展的安装位置。例如,CREATE EXTENSION x WITH SCHEMA CURRENT_SCHEMACREATE EXTENSION x会被合并。无法简单访问所执行的命令,因为某些简单命令会发出多个命令(例如,serial作为宏)。
  2. pg_ddl_command用C函数处理内部。

因为第二个选项听起来不太有趣,所以我们选择第一个。

查看在命令端捕获更改下的列表,该列表支持objid从 SRF 返回pg_event_trigger_ddl_commands()请注意,schema_name这不是您所追求的

CREATE OR REPLACE FUNCTION verify_extension_schema()
RETURNS event_trigger
AS $$
DECLARE
  schemafail bool;
BEGIN
  schemafail = (
    SELECT n.nspname = 'public'
    FROM pg_event_trigger_ddl_commands() AS ev
    INNER JOIN pg_catalog.pg_extension AS e
      ON ev.objid = e.oid
    INNER JOIN pg_catalog.pg_namespace AS n
      ON e.extnamespace = n.oid
  );
  IF schemafail THEN
    RAISE EXCEPTION 'Creating extensions into "public" is disabled';
  END IF;
END;
$$ LANGUAGE plpgsql;

CREATE EVENT TRIGGER nag_my_users
  ON ddl_command_end
  WHEN TAG IN ('CREATE EXTENSION')
  EXECUTE PROCEDURE verify_extension_schema();
Run Code Online (Sandbox Code Playgroud)

现在你可以

test=# CREATE EXTENSION intarray ;
ERROR:  Creating extensions into "public" is disabled
test=# CREATE EXTENSION intarray WITH SCHEMA public;
ERROR:  Creating extensions into "public" is disabled
test=# CREATE EXTENSION intarray WITH SCHEMA foo;
CREATE EXTENSION
Run Code Online (Sandbox Code Playgroud)

如果您只是想要通知,可以将其更改为RAISE NOTICE