选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0
历史版本PostgreSQL 9.1 已于 2016 年 10 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本

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

指向触发该触发器的那一行。这是正在被插入、更新或删除的行。如果该触发器因 INSERTDELETE 而触发,那么如果你不想用另一行替换该行(在 INSERT 的情形下)或跳过该操作,就应从函数中返回它。

tg_newtuple

如果触发器因 UPDATE 而触发,则指向该行的新版本;如果因 INSERTDELETE 而触发,则为 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_trigtupletg_newtuple

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。