Postgresql

PostgreSQL 事件觸發器強制將擴展安裝到特定模式中

  • August 9, 2017

我有一個專用架構extensions(PostgreSQL v 9.6.3),我打算在其中為我的數據庫安裝所有擴展。我想以某種方式禁止(或至少提醒)使用者在未指定特定架構的情況下安裝擴展。

所以這應該失敗

CREATE EXTENSION tablefunc;

但這應該成功:

CREATE EXTENSION tablefunc SCHEMA extensions;

為此,我嘗試創建事件觸發器:

CREATE EVENT TRIGGER e010_verify_extension_schema_et
 ON ddl_command_end
 WHEN TAG IN ('CREATE EXTENSION')
 EXECUTE PROCEDURE verify_extension_schema();

verify_extension_schema()功能上我試圖利用pg_catalog.pg_event_trigger_ddl_commands(). 但是,該函式不會返回任何我可以用來檢查是否已指定架構或與此相關的架構…

有誰知道我如何做到這一點?

確保您正在使用ddl_command_end,它仍然會失敗或提醒使用者您想要什麼。從文件中,

類似地,如果**ddl_command_end觸發器因錯誤而失敗,則 DDL 語句的效果將被回滾**,就像在包含事務中止的任何其他情況下一樣。

不幸的是,在那之後你有兩個選擇

  1. 處理它可能會做出假設,但只知道安裝擴展的位置。例如,CREATE EXTENSION x WITH SCHEMA CURRENT_SCHEMACREATE EXTENSION x將被混為一談。無法簡單訪問執行的命令,因為一些簡單的命令發出多個命令(例如,serial作為宏)。
  2. pg_ddl_command使用 C 函式處理內部。

因為第二個選項聽起來不那麼快樂,所以讓我們選擇第一個。

查看Capturing Changes at Command End下的列表,該列表支持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();

現在你可以

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

如果您只想要一個通知,您可以將其更改為RAISE NOTICE

引用自:https://dba.stackexchange.com/questions/183098