【openGauss如何通过pg_trigger.tgtype获取触发器的各种触发条件

前言

最近有客户反馈兼容的dba_triggers视图中,同一个触发器的trigger_event被拆成了多行,和ORACLE中表现不一致,于是我进行了一些分析,发现是在其引用的information_schema.triggers视图中就已经拆开成了INSERT/DELETE/UPDATE,但是这些属性都是通过tgtype这一个int2整型的字段获取的,甚至连before/after/instead of/row/statement 等都是通过这一个字段。一个值存多种信息,这在ORACLE的数据字典视图里很常见,无非就是按二进制位来判断,于是我尝试自己猜一猜,看能不能从这个数字中识别出规律。

测试和分析

先建一堆测试触发器

create schema test1; create schema test2; CREATE TABLE test1.test_trigger_src_tbl(id1 INT, id2 INT, id3 INT); CREATE OR REPLACE FUNCTION test1.tri_test_func() RETURNS TRIGGER AS $$ DECLARE BEGIN INSERT INTO test_trigger_des_tbl VALUES(NEW.id1, NEW.id2, NEW.id3); RETURN NEW; END $$ LANGUAGE PLPGSQL; --before insert/update row CREATE TRIGGER test_trigger BEFORE insert or update ON test1.test_trigger_src_tbl FOR EACH ROW EXECUTE PROCEDURE test1.tri_test_func(); CREATE TABLE test2.test_trigger_src_tbl(id1 INT, id2 INT, id3 INT); CREATE OR REPLACE FUNCTION test2.tri_test_func() RETURNS TRIGGER AS $$ DECLARE BEGIN INSERT INTO test_trigger_des_tbl VALUES(NEW.id1, NEW.id2, NEW.id3); RETURN NEW; END $$ LANGUAGE PLPGSQL; --不同schema下的同名触发器 CREATE TRIGGER test_trigger BEFORE insert or update ON test2.test_trigger_src_tbl FOR EACH ROW EXECUTE PROCEDURE test2.tri_test_func(); CREATE OR REPLACE FUNCTION test1.tri_test_func1() RETURNS TRIGGER AS $$ DECLARE BEGIN INSERT INTO test_trigger_des_tbl VALUES(NEW.id1, NEW.id2, NEW.id3); RETURN NEW; END $$ LANGUAGE PLPGSQL; -- before insert row CREATE TRIGGER test_trigger1 BEFORE insert ON test1.test_trigger_src_tbl FOR EACH ROW EXECUTE PROCEDURE test1.tri_test_func1(); CREATE OR REPLACE FUNCTION test1.tri_test_func2() RETURNS TRIGGER AS $$ DECLARE BEGIN INSERT INTO test_trigger_des_tbl VALUES(NEW.id1, NEW.id2, NEW.id3); RETURN NEW; END $$ LANGUAGE PLPGSQL; --before insert/delete row CREATE TRIGGER test_trigger2 BEFORE insert or DELETE ON test1.test_trigger_src_tbl FOR EACH ROW EXECUTE PROCEDURE test1.tri_test_func2(); CREATE OR REPLACE FUNCTION test1.tri_test_func3() RETURNS TRIGGER AS $$ DECLARE BEGIN INSERT INTO test_trigger_des_tbl VALUES(NEW.id1, NEW.id2, NEW.id3); RETURN NEW; END $$ LANGUAGE PLPGSQL; --after insert/delete/update row CREATE TRIGGER test_trigger3 AFTER insert or delete or UPDATE ON test1.test_trigger_src_tbl FOR EACH ROW EXECUTE PROCEDURE test1.tri_test_func3(); CREATE OR REPLACE FUNCTION test1.tri_test_func4() RETURNS TRIGGER AS $$ DECLARE BEGIN INSERT INTO test_trigger_des_tbl VALUES(NEW.id1, NEW.id2, NEW.id3); RETURN NEW; END $$ LANGUAGE PLPGSQL; create view test1.test_trigger_src_tbl_V as select * from test1.test_trigger_src_tbl; --instead delete row CREATE TRIGGER test_trigger4 instead OF DELETE ON test1.test_trigger_src_tbl_V FOR EACH ROW EXECUTE PROCEDURE test1.tri_test_func4(); CREATE OR REPLACE FUNCTION test1.tri_test_func5() RETURNS TRIGGER AS $$ DECLARE BEGIN INSERT INTO test_trigger_des_tbl VALUES(NEW.id1, NEW.id2, NEW.id3); RETURN NEW; END $$ LANGUAGE PLPGSQL; --before truncate statement CREATE TRIGGER test_trigger5 before truncate ON test1.test_trigger_src_tbl FOR EACH STATEMENT EXECUTE PROCEDURE test1.tri_test_func5(); CREATE OR REPLACE FUNCTION test1.tri_test_func6() RETURNS TRIGGER AS $$ DECLARE BEGIN INSERT INTO test_trigger_des_tbl VALUES(NEW.id1, NEW.id2, NEW.id3); RETURN NEW; END $$ LANGUAGE PLPGSQL; --after delete row CREATE TRIGGER test_trigger6 AFTER delete ON test1.test_trigger_src_tbl FOR EACH ROW EXECUTE PROCEDURE test1.tri_test_func6(); CREATE OR REPLACE FUNCTION test1.tri_test_func7() RETURNS TRIGGER AS $$ DECLARE BEGIN INSERT INTO test_trigger_des_tbl VALUES(NEW.id1, NEW.id2, NEW.id3); RETURN NEW; END $$ LANGUAGE PLPGSQL; --after truncate statement CREATE TRIGGER test_trigger7 AFTER truncate ON test1.test_trigger_src_tbl FOR EACH STATEMENT EXECUTE PROCEDURE test1.tri_test_func7(); CREATE OR REPLACE FUNCTION test1.tri_test_func8() RETURNS TRIGGER AS $$ DECLARE BEGIN INSERT INTO test_trigger_des_tbl VALUES(NEW.id1, NEW.id2, NEW.id3); RETURN NEW; END $$ LANGUAGE PLPGSQL; --after update/delete row CREATE TRIGGER test_trigger8 AFTER update or delete ON test1.test_trigger_src_tbl FOR EACH ROW EXECUTE PROCEDURE test1.tri_test_func8();