Postgres pg_trigger的触发器类型字段(tgtype)中的位的含义

时间:2014-05-13 14:47:06

标签: postgresql triggers

我在哪里可以找到有关POSTGRES tgtype的文档,例如:

SELECT * FROM pg_trigger;
===>
 tgtype = 23; 

这是什么意思?

3 个答案:

答案 0 :(得分:14)

tgtype是(per documentation):

  

位掩码识别触发器触发条件

但是那里没有识别出个别位 source code says

41  int16  tgtype;  /* BEFORE/AFTER/INSTEAD, UPDATE/DELETE/INSERT,
42                                   * ROW/STATEMENT; see below */

...

93  /* Bits within tgtype */
94  #define TRIGGER_TYPE_ROW         (1 << 0)
95  #define TRIGGER_TYPE_BEFORE      (1 << 1)
96  #define TRIGGER_TYPE_INSERT      (1 << 2)
97  #define TRIGGER_TYPE_DELETE      (1 << 3)
98  #define TRIGGER_TYPE_UPDATE      (1 << 4)
99  #define TRIGGER_TYPE_TRUNCATE    (1 << 5)
100 #define TRIGGER_TYPE_INSTEAD     (1 << 6)
101
102 #define TRIGGER_TYPE_LEVEL_MASK  (TRIGGER_TYPE_ROW)
103 #define TRIGGER_TYPE_STATEMENT   0

23 在最低8位中转换为 00010111 ,这应该代表:

CREATE TRIGGER trigger_name
BEFORE INSERT OR UPDATE ON table_name
FOR EACH ROW
EXECUTE PROCEDURE func_name();

我现有的数据库中的一些快速测试似乎证实了这一点。

答案 1 :(得分:0)

感谢rlib和Erwin。 这正是我想要的。

我对此进行了查询。如果其他人需要,我会把它留在这里。

SELECT 
  n.nspname as schema_name, 
  c.relname as table_name, 
  t.tgname as trigger_name, 
  proname as function_name,
  tgtype::int::bit(7) as condition_bits,
  CASE WHEN (tgtype::int::bit(7) & b'0000001')::int = 0 THEN 'STATEMENT' ELSE 'EACH ROW' END as cond_row,
  COALESCE(
    CASE WHEN (tgtype::int::bit(7) & b'0000010')::int = 0 THEN NULL ELSE 'BEFORE' END,
    CASE WHEN (tgtype::int::bit(7) & b'0000010')::int = 0 THEN 'AFTER' ELSE NULL END,
    CASE WHEN (tgtype::int::bit(7) & b'1000000')::int = 0 THEN NULL ELSE 'INSTEAD' END,
    ''
  )::text as cond_timing, 
    (CASE WHEN (tgtype::int::bit(7) & b'0000100')::int = 0 THEN '' ELSE ' INSERT' END) ||
    (CASE WHEN (tgtype::int::bit(7) & b'0001000')::int = 0 THEN '' ELSE ' DELETE' END) ||
    (CASE WHEN (tgtype::int::bit(7) & b'0010000')::int = 0 THEN '' ELSE ' UPDATE' END) ||
    (CASE WHEN (tgtype::int::bit(7) & b'0100000')::int = 0 THEN '' ELSE ' TRUNCATE' END)
  as cond_event
FROM pg_trigger t
JOIN pg_proc p ON t.tgfoid = p.oid
JOIN pg_class c ON c.oid = t.tgrelid
JOIN pg_namespace n ON n.oid = c.relnamespace;

编辑:

嗯,那太过分了。事实证明,以上工作已在triggers模式的information_schema视图中完成。

更容易:SELECT * FROM information_schema.triggers

答案 2 :(得分:0)

谢谢大家,这些答案为我节省了一些时间。关于最后一个答案,如果您有 TRUNCATE 触发器,它不是 矫枉过正。前几天我刚刚注意到,information_schema.triggers包含此类触发器。正如我记得的,或推测的……,这是一个有意识的选择。 TRUNCATE 是非标准的,我认为 Postgres 的核心人员严格要求根本不让 information_schema 成为非标准。

我为自己对发布的代码做了一个小小的修改,发布在这里供任何想要这样东西的人使用。

SELECT 
  c.relnamespace::regnamespace::text as schema_name, 
  tgrelid::regclass                  as table_name,
  t.tgname                           as trigger_name, 
  proname                            as function_name,
  tgtype::int::bit(7)                as condition_bits,
  CASE WHEN (tgtype::int::bit(7) & b'0000001')::int = 0 THEN 'STATEMENT' ELSE 'EACH ROW' END
                                     as trigger_scope,
  COALESCE(
    CASE WHEN (tgtype::int::bit(7) & b'0000010')::int = 0 THEN NULL ELSE 'BEFORE' END,
    CASE WHEN (tgtype::int::bit(7) & b'0000010')::int = 0 THEN 'AFTER' ELSE NULL END,
    CASE WHEN (tgtype::int::bit(7) & b'1000000')::int = 0 THEN NULL ELSE 'INSTEAD' END,
    ''
  )::text                           as trigger_timing, 
    (CASE WHEN (tgtype::int::bit(7) & b'0000100')::int = 0 THEN '' ELSE ' INSERT' END) ||
    (CASE WHEN (tgtype::int::bit(7) & b'0001000')::int = 0 THEN '' ELSE ' DELETE' END) ||
    (CASE WHEN (tgtype::int::bit(7) & b'0010000')::int = 0 THEN '' ELSE ' UPDATE' END) ||
    (CASE WHEN (tgtype::int::bit(7) & b'0100000')::int = 0 THEN '' ELSE ' TRUNCATE' END)
                                     as trigger_action,
pg_get_triggerdef(t.oid)             as trigger_definition
  
FROM pg_trigger t
JOIN pg_proc p      ON t.tgfoid = p.oid
JOIN pg_class c     ON c.oid    = t.tgrelid