PostgreSQL的Event triggers


PostgreSQL中,常規觸發器依附於單個表並捕獲dml事件。而Event triggers是數據庫全局性的,可以捕獲ddl事件。與常規觸發器一樣,Event triggers可以用任何包含事件觸發器支持的過程語言編寫,也可以用C編寫,但不能用純SQL編寫。

當與事件關聯的事件在定義它的數據庫中發生時,就會觸發Event triggers。在11版本中,僅支持的事件是ddl_command_start,ddl_command_end,table_rewrite和sql_drop。在將來的版本中可能會添加對其他事件的支持。

ddl_command_start事件在執行CREATE,ALTER,DROP,SECURITY LABEL,COMMENT,GRANT或REVOKE命令之前發生。在觸發事件觸發器之前,不檢查受影響的對象是否存在。但是,作為例外,針對共享對象(數據庫,角色和表空間)的DDL命令或針對Event triggers本身的命令不會發生此事件。事件觸發機制不支持這些對象類型。ddl_command_start也將在執行SELECT INTO命令之前發生,因為它等效於CREATE TABLE AS。

ddl_command_end事件在執行以上命令后立即發生。要獲得有關已發生的DDL操作的更多詳細信息,請使用ddl_command_end事件觸發代碼中的設置返回函數pg_event_trigger_ddl_commands()。請注意,觸發器在執行操作之后(但在事務提交之前)觸發,因此可以將系統目錄讀取為已更改。

對於任何刪除數據庫對象的操作,sql_drop事件就在ddl_command_end事件觸發器之前發生。要列出已刪除的對象,請使用sql_drop事件觸發代碼中的返回設置函數pg_event_trigger_dropped_objects()。請注意,觸發器是在從系統目錄中刪除對象后執行的,因此無法再查找它們。

table_rewrite事件僅在通過命令ALTER TABLE和ALTER TYPE的某些操作重寫表之前發生。盡管其他控制語句(例如CLUSTER和VACUUM)可用於重寫表,但table_rewrite事件不會由它們觸發。

事件觸發器(與其他函數一樣)無法在異常終止的事務中執行。因此,如果DDL命令由於錯誤而失敗,則將不執行任何關聯的ddl_command_end觸發器。相反,如果ddl_command_start觸發器因錯誤而失敗,則不會觸發其他事件觸發器,也不會嘗試執行命令本身。同樣,如果ddl_command_end觸發器因錯誤而失敗,則DDL語句的效果將回滾,就像在其他任何情況下包含事務中止的情況一樣。

使用命令CREATE EVENT TRIGGER創建事件觸發器。為了創建事件觸發器,必須首先創建具有特殊返回類型event_trigger的函數。此函數不需要(也可以不)返回值;返回類型僅用作將函數作為事件觸發器調用的信號。

如果為一個特定事件定義了多個事件觸發器,則它們將按觸發器名稱的字母順序觸發。

觸發器定義還可以指定WHEN條件,例如,僅可以為用戶希望攔截的特定命令觸發ddl_command_start觸發器。這種觸發器的常見用法是限制用戶可以執行的DDL操作的范圍。

事件觸發觸發矩陣

 

Command Tag ddl_command_start ddl_command_end sql_drop table_rewrite Notes
ALTER AGGREGATE X X - -  
ALTER COLLATION X X - -  
ALTER CONVERSION X X - -  
ALTER DOMAIN X X - -  
ALTER DEFAULT PRIVILEGES X X - -  
ALTER EXTENSION X X - -  
ALTER FOREIGN DATA WRAPPER X X - -  
ALTER FOREIGN TABLE X X X -  
ALTER FUNCTION X X - -  
ALTER LANGUAGE X X - -  
ALTER LARGE OBJECT X X - -  
ALTER MATERIALIZED VIEW X X - -  
ALTER OPERATOR X X - -  
ALTER OPERATOR CLASS X X - -  
ALTER OPERATOR FAMILY X X - -  
ALTER POLICY X X - -  
ALTER PROCEDURE X X - -  
ALTER PUBLICATION X X - -  
ALTER SCHEMA X X - -  
ALTER SEQUENCE X X - -  
ALTER SERVER X X - -  
ALTER STATISTICS X X - -  
ALTER SUBSCRIPTION X X - -  
ALTER TABLE X X X X  
ALTER TEXT SEARCH CONFIGURATION X X - -  
ALTER TEXT SEARCH DICTIONARY X X - -  
ALTER TEXT SEARCH PARSER X X - -  
ALTER TEXT SEARCH TEMPLATE X X - -  
ALTER TRIGGER X X - -  
ALTER TYPE X X - X  
ALTER USER MAPPING X X - -  
ALTER VIEW X X - -  
COMMENT X X - - Only for local objects
CREATE ACCESS METHOD X X - -  
CREATE AGGREGATE X X - -  
CREATE CAST X X - -  
CREATE COLLATION X X - -  
CREATE CONVERSION X X - -  
CREATE DOMAIN X X - -  
CREATE EXTENSION X X - -  
CREATE FOREIGN DATA WRAPPER X X - -  
CREATE FOREIGN TABLE X X - -  
CREATE FUNCTION X X - -  
CREATE INDEX X X - -  
CREATE LANGUAGE X X - -  
CREATE MATERIALIZED VIEW X X - -  
CREATE OPERATOR X X - -  
CREATE OPERATOR CLASS X X - -  
CREATE OPERATOR FAMILY X X - -  
CREATE POLICY X X - -  
CREATE PROCEDURE X X - -  
CREATE PUBLICATION X X - -  
CREATE RULE X X - -  
CREATE SCHEMA X X - -  
CREATE SEQUENCE X X - -  
CREATE SERVER X X - -  
CREATE STATISTICS X X - -  
CREATE SUBSCRIPTION X X - -  
CREATE TABLE X X - -  
CREATE TABLE AS X X - -  
CREATE TEXT SEARCH CONFIGURATION X X - -  
CREATE TEXT SEARCH DICTIONARY X X - -  
CREATE TEXT SEARCH PARSER X X - -  
CREATE TEXT SEARCH TEMPLATE X X - -  
CREATE TRIGGER X X - -  
CREATE TYPE X X - -  
CREATE USER MAPPING X X - -  
CREATE VIEW X X - -  
DROP ACCESS METHOD X X X -  
DROP AGGREGATE X X X -  
DROP CAST X X X -  
DROP COLLATION X X X -  
DROP CONVERSION X X X -  
DROP DOMAIN X X X -  
DROP EXTENSION X X X -  
DROP FOREIGN DATA WRAPPER X X X -  
DROP FOREIGN TABLE X X X -  
DROP FUNCTION X X X -  
DROP INDEX X X X -  
DROP LANGUAGE X X X -  
DROP MATERIALIZED VIEW X X X -  
DROP OPERATOR X X X -  
DROP OPERATOR CLASS X X X -  
DROP OPERATOR FAMILY X X X -  
DROP OWNED X X X -  
DROP POLICY X X X -  
DROP PROCEDURE X X X -  
DROP PUBLICATION X X X -  
DROP RULE X X X -  
DROP SCHEMA X X X -  
DROP SEQUENCE X X X -  
DROP SERVER X X X -  
DROP STATISTICS X X X -  
DROP SUBSCRIPTION X X X -  
DROP TABLE X X X -  
DROP TEXT SEARCH CONFIGURATION X X X -  
DROP TEXT SEARCH DICTIONARY X X X -  
DROP TEXT SEARCH PARSER X X X -  
DROP TEXT SEARCH TEMPLATE X X X -  
DROP TRIGGER X X X -  
DROP TYPE X X X -  
DROP USER MAPPING X X X -  
DROP VIEW X X X -  
GRANT X X - - Only for local objects
IMPORT FOREIGN SCHEMA X X - -  
REFRESH MATERIALIZED VIEW X X - -  
REVOKE X X - - Only for local objects
SECURITY LABEL X X - - Only for local objects
SELECT INTO X X - -  

 

1.創建一張用於存放ddl記錄的表:

CREATE TABLE ddl_history ( ID serial PRIMARY KEY, ddl_date timestamptz, ddl_tag TEXT, object_name TEXT );

2.定義兩個函數:

一個用於跟蹤對象的創建和修改,一個用於跟蹤對象的刪除操作

CREATE 
   OR REPLACE FUNCTION log_ddl ( ) RETURNS event_trigger AS $$ 
DECLARE
   audit_query TEXT;
   r RECORD;
BEGIN
   IF
      tg_tag <> 'DROP TABLE' THEN
         r := pg_event_trigger_ddl_commands ( );
      INSERT INTO ddl_history ( ddl_date, ddl_tag, object_name )
      VALUES
         ( statement_timestamp( ), tg_tag, r.object_identity );
   END IF;
END;
$$ LANGUAGE plpgsql;



CREATE 
   OR REPLACE FUNCTION log_ddl_drop ( ) RETURNS event_trigger AS $$ 
DECLARE
   audit_query TEXT;
   r RECORD;
BEGIN
   IF
      tg_tag = 'DROP TABLE' THEN
         FOR r IN SELECT
         * 
      FROM
         pg_event_trigger_ddl_commands ( )
         LOOP
         INSERT INTO ddl_history ( ddl_date, ddl_tag, object_name )
      VALUES
         ( statement_timestamp( ), tg_tag, r.object_identity );
   END LOOP;
END IF;
END;
$$ LANGUAGE plpgsql;

3.創建兩個事件觸發器

CREATE EVENT TRIGGER log_ddl_info ON ddl_command_end EXECUTE PROCEDURE log_ddl();

CREATE EVENT TRIGGER log_ddl_drop_info ON sql_drop EXECUTE PROCEDURE log_ddl_drop();

4.執行ddl測試

CREATE TABLE testtable (id int, first_name text);
ALTER TABLE testtable ADD COLUMN last_name text;
ALTER TABLE testtable ADD COLUMN midlname text;
ALTER TABLE testtable RENAME COLUMN midlname TO middle_name;
ALTER TABLE testtable DROP COLUMN middle_name;
DROP TABLE testtable;
SELECT * FROM ddl_history;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM