16.2. 与触发器管理器交互

本章描述触发器函数的低层细节.只有当你用C书写触发器函数的时候 才需要这些信息.如果你用某种高级语言写触发器,那么系统就会为你处理 这些细节.

注意: 这里描述的接口适用于 PostgreSQL 7.1 及以后版本. 早期的版本把TriggerData指针放在全局量 CurrentTriggerData里 传递.

当一个函数被触发器管理器调用时,它不会收到任何普通参数,而是收到一个 指向TriggerData结构的"环境"指针.C程序可以通过执行 实际上被扩展为

	((fcinfo)->context != NULL && IsA((fcinfo)->context, TriggerData))
    

的宏 CALLED_AS_TRIGGER(fcinfo), 来判断自己是否从触发器管理器中调用的. 如果此宏返回真(TRUE),则可以安全地把fcinfo->context转换成类型 TriggerData * 然后使用这个指向 TriggerData的结构. 函数本身绝不能更改 TriggerData 结构 或者它指向的任何数据.

struct TriggerData 是在 commands/trigger.h 里面定义的:

typedef struct TriggerData
{
    NodeTag       type;
    TriggerEvent  tg_event;
    Relation      tg_relation;
    HeapTuple     tg_trigtuple;
    HeapTuple     tg_newtuple;
    Trigger      *tg_trigger;
} TriggerData;

这些成员的定义如下:

type

如果是触发器事件则总是 T_TriggerData

tg_event

描述调用函数的事件.你可以用下面的宏检查 tg_event

TRIGGER_FIRED_BEFORE(tg_event)

如果触发器是BEFORE类触发,返回真.

TRIGGER_FIRED_AFTER(tg_event)

如果触发器是AFTER类触发,返回真.

TRIGGER_FIRED_FOR_ROW(event)

如果触发器是行级别(ROW-level)事件触发,返回真.

TRIGGER_FIRED_FOR_STATEMENT(event)

如果触发器是语句级别(STATEMENT-level)事件触发,返回真.

TRIGGER_FIRED_BY_INSERT(event)

如果触发器是INSERT触发,返回真.

TRIGGER_FIRED_BY_DELETE(event)

如果触发器是DELETE触发,返回真.

TRIGGER_FIRED_BY_UPDATE(event)

如果触发器是UPDATE触发,返回真.

tg_relation

是一个指向描述被触发的关系的结构的指针. 请参考utils/rel.h获取关于此结构的详细信息. 最让人感兴趣的事情是 tg_relation->rd_att(关系元组的描述) 和tg_relation->rd_rel->relname(关系名.这个变量的类型不是 char*, 而是NameData. 如果你需要一份名字的拷贝,用 SPI_getrelname(tg_relation)获取char* ).

tg_trigtuple

是一个指向触发触发器的元组的指针.这是一个正在被 插入(INSERT), 删除(DELETE)或更新(UPDATE)的元组.如果是 INSERTDELETE, 那么这就是你将返回给执行者的东西--如果你不想用另一 条元组覆盖此元组(INSERT)或忽略操作(在DELETE的时候).

tg_newtuple

如果是UPDATE,这是一个指向新版本的元组的指针,如果是INSERTDELETE, 就是NULL.这就是你将返回给执行者的东西 -- 如果你是UPDATE 并且你不想用另一条元组替换这条元组或忽略操作.

tg_trigger

是一个指向结构Trigger的指针,该结构在utils/rel.h里定义:

typedef struct Trigger
{
    Oid	 tgoid;
    char       *tgname;
    Oid	 tgfoid;
    int16       tgtype;
    bool	tgenabled;
    bool	tgisconstraint;
    Oid	 tgconstrrelid;
    bool	tgdeferrable;
    bool	tginitdeferred;
    int16       tgnargs;
    int16       tgattr[FUNC_MAX_ARGS];
    char      **tgargs;
} Trigger;

tgname是触发器的名称,tgnargs 是在tgargs里参数的数量, tgargs是一个指针数组,数组里每个指针指向在 CREATE TRIGGER语句里声明的参数.其他成员只在内部使用.