# 39.3.用C语言编写触发器函数

本节介绍触发函数接口的低级细节。只有在用C编写触发器函数时才需要这些信息。如果您使用的是更高级的语言,那么这些细节将为您处理。在大多数情况下,在编写C.的触发器之前,您应该考虑使用过程语言。每个过程语言的文档解释了如何在该语言中编写触发器。

触发器功能必须使用“版本1”功能管理器界面。

触发器管理器调用函数时,不会向其传递任何常规参数,但会向其传递一个指向触发数据结构C函数可以通过执行宏来检查它们是否是从触发器管理器调用的:

CALLED_AS_TRIGGER(fcinfo)

扩展到:

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

如果返回true,则可以安全地进行强制转换fcinfo->context打字触发数据*并利用指向触发数据结构函数必须改变触发数据结构或它指向的任何数据。

结构触发器数据定义在命令/触发器。H:

typedef struct TriggerData
{
    NodeTag          type;
    TriggerEvent     tg_event;
    Relation         tg_relation;
    HeapTuple        tg_trigtuple;
    HeapTuple        tg_newtuple;
    Trigger         *tg_trigger;
    TupleTableSlot  *tg_trigslot;
    TupleTableSlot  *tg_newslot;
    Tuplestorestate *tg_oldtable;
    Tuplestorestate *tg_newtable;
    const Bitmapset *tg_updatedcols;
} TriggerData;

成员定义如下:

类型

总是触发数据.

tg_事件

描述为其调用函数的事件。您可以使用以下宏来检查tg_事件:

触发前触发(tg事件)

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

触发器在(tg事件)后触发

如果操作后触发触发器,则返回true。

触发触发触发(tg事件)

如果触发了触发器而不是操作,则返回true。

触发行触发行(tg事件)

如果为行级事件触发触发器,则返回true。

触发器为语句触发(tg事件)

如果为语句级事件触发触发器,则返回true。

触发器由插入触发(tg事件)

如果触发器是由插入命令

触发由更新触发(tg事件)

如果触发器是由使现代化命令

触发由删除触发(tg事件)

如果触发器是由删去命令

触发器由截断触发(tg事件)

如果触发器是由截断命令

tg_关系

指向描述触发器触发的关系的结构的指针。看看utils/rel。H有关此结构的详细信息。最有趣的事情是tg_关系->rd_附件(关系元组的描述符)和tg_关系->rd_关系->关系名称(关系名称;类型不是炭*但是名称数据; 使用SPI_getrelname(tg_关系)得到一个炭*如果您需要该名称的副本)。

三元组

指向为其触发触发器的行的指针。这是正在插入、更新或删除的行。如果这个扳机是为了插入删去如果不想用其他行替换该行(在插入)或者跳过操作。对于外部表上的触发器,此处未指定系统列的值。

tg_新偶

一个指向行的新版本的指针,如果触发器是为使现代化无效的如果是为了插入或者删去.如果事件是一个使现代化您不想用另一行替换这一行,也不想跳过该操作。对于外部表上的触发器,此处未指定系统列的值。

tg_触发器

指向类型结构的指针触发,定义于utils/reltrigger。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;
    char       *tgoldtable;
    char       *tgnewtable;
} Trigger;

哪里tgname是扳机的名字,特格纳格斯是中的参数数tgargstgargs是指向创建触发器陈述其他成员仅供内部使用。

三角槽

包含三元组,或无效的指针,如果没有这样的元组。

tg_新闻特辑

包含tg_新偶,或无效的指针,如果没有这样的元组。

老桌子

指向类型结构的指针树酯包含零行或多行,格式为tg_关系,或无效的指针,如果没有旧桌子过渡关系。

新表

指向类型结构的指针树酯包含零行或多行,格式为tg_关系,或无效的指针,如果没有新桌子过渡关系。

tg_更新的cols

对于使现代化触发器,一个位图集,指示由触发命令更新的列。通用触发器函数可以使用它来优化操作,不必处理未更改的列。

例如,要确定属性号为的列阿特纳姆(基于1)是此位图集的成员,请调用bms_是_成员(attnum-FirstLowInvalidHeapAttributeNumber,trigdata->tg_updatedcols)).

对于触发器,而不是使现代化触发器,这将是无效的.

要允许通过SPI发出的查询引用转换表,请参阅SPI_登记_触发_数据.

触发器函数必须返回一堆指针还是指针无效的指针(SQL空值,即不设置*isNull*是的)。小心返回三元组tg_新偶,如果不想修改正在操作的行,请视情况而定。