↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4
历史版本。 PostgreSQL 9.1 已结束支持。 2016-10-27. 请参阅 当前版本手册.

36.3. 用 C 编写触发器函数 #

本节说明触发器函数接口的底层细节。这些信息仅在用 C 编写触发器函数时才需要。如果你使用更高层语言,这些细节会由系统代为处理。在多数情况下,在用 C 编写触发器之前,应先考虑使用过程语言。每种过程语言的文档都会说明如何用该语言编写触发器。

触发器函数必须使用“版本 1” 函数管理器接口。

当函数由触发器管理器调用时,不会向它传递任何普通参数,但会传递一个指向 TriggerData 结构体的“上下文”指针。C 函数可以通过执行下列宏来检查自己是否由触发器管理器调用:

CALLED_AS_TRIGGER(fcinfo)

它会展开为:

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

如果该宏返回真,就可以安全地把 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;
    Buffer        tg_trigtuplebuf;
    Buffer        tg_newtuplebuf;
} TriggerData;

其中各成员的定义如下:

type

始终是 T_TriggerData。

tg_event

描述调用函数的事件。可以使用以下宏检查 tg_event:

TRIGGER_FIRED_BEFORE(tg_event)

如果触发器在操作之前触发,则返回真。

TRIGGER_FIRED_AFTER(tg_event)

如果触发器在操作之后触发,则返回真。

TRIGGER_FIRED_INSTEAD(tg_event)

如果触发器是取代该操作而触发,则返回真。

TRIGGER_FIRED_FOR_ROW(tg_event)

如果触发器是因行级事件触发,则返回真。

TRIGGER_FIRED_FOR_STATEMENT(tg_event)

如果触发器是因语句级事件触发,则返回真。

TRIGGER_FIRED_BY_INSERT(tg_event)

如果触发器是由 INSERT 命令触发,则返回真。

TRIGGER_FIRED_BY_UPDATE(tg_event)

如果触发器是由 UPDATE 命令触发,则返回真。

TRIGGER_FIRED_BY_DELETE(tg_event)

如果触发器是由 DELETE 命令触发,则返回真。

TRIGGER_FIRED_BY_TRUNCATE(tg_event)

如果触发器是由 TRUNCATE 命令触发,则返回真。

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 而触发,那么如果你不想用另一行替换该行(在 INSERT 的情形下)或跳过该操作,就应从函数中返回它。

tg_newtuple

如果触发器因 UPDATE 而触发,则指向该行的新版本;如果因 INSERT 或 DELETE 而触发,则为 NULL。如果事件是 UPDATE,而你不想用另一行替换该行或跳过该操作,就必须从函数中返回它。

tg_trigger

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

typedef struct Trigger
{
    Oid         tgoid;
    char       *tgname;
    Oid         tgfoid;
    int16       tgtype;
    char        tgenabled;
    bool        tgisinternal;
    Oid         tgconstrrelid;
    Oid         tgconstrindid;
    Oid         tgconstraint;
    bool        tgdeferrable;
    bool        tginitdeferred;
    int16       tgnargs;
    int16       tgnattr;
    int16      *tgattr;
    char      **tgargs;
    char       *tgqual;
} Trigger;

where tgname is the trigger's name, tgnargs is the number of arguments in tgargs, and tgargs is an array of pointers to the arguments specified in the CREATE TRIGGER statement. The other members are for internal use only.

tg_trigtuplebuf

包含 tg_trigtuple 的缓冲区;如果没有这样的元组,或它没有存储在磁盘缓冲区中,则为 InvalidBuffer。

tg_newtuplebuf

包含 tg_newtuple 的缓冲区;如果没有这样的元组,或它没有存储在磁盘缓冲区中,则为 InvalidBuffer。

触发器函数必须返回一个 HeapTuple 指针或一个 NULL 指针(不是 SQL 空值,也就是说不要把 isNull 设为真)。如果你不想修改正在处理的行,就要小心地根据情况返回适当的 tg_trigtuple 或 tg_newtuple。

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.