この節では、トリガ関数のインターフェイスの低レベルな詳細について説明します。この情報はトリガ関数をCで書く場合にのみ必要になります。 もしもっと高レベルな関数言語を使っている場合はこれらの問題はすでに解決されています。
Note: ここで説明されるインターフェイスはPostgreSQL 7.1以降に当てはまります。 それ以前のバージョンでは、TriggerData ポインタはグローバル変数 CurrentTriggerData の中で渡されていました。
関数がトリガマネージャから呼び出されるときは、通常のパラメータが渡されるのではなく、TriggerData 構造体を指す "context" ポインタが渡されます。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; } TriggerData;
メンバは下記のように定義されています。
もしこれがトリガイベントである場合、常にT_TriggerDataです。
その関数が呼び出されたイベントを説明します。tg_eventを調べるためには下記のマクロを使うことができます。
トリガがBEFOREで発行され場合TRUEを返します。
トリガがAFTERを発行した場合TRUEを返します。
トリガが行レベルのイベントを発行した場合TRUEを返します。
トリガがステートメントレベルのイベントを発行した場合TRUEを返します。
トリガがINSERTに発行された場合TRUEを返します。
トリガがDELETEに発行された場合TRUEを返します。
トリガがUPDATEに発行された場合TRUEを返します。
トリガされたリレーションを説明する構造体へのポインタです。 この構造体についての詳細は、utils/rel.h を参照してください。 最も興味深いのは、tg_relation->rd_att (リレーションタプルの記述子) と tg_relation->rd_rel->relname です (リレーション名、これは char* ではなく NameData です。 名前のコピーが必要な場合は、char* を得るために SPI_getrelname(tg_relation) を使用してください)。
トリガが発行されたタプルへのポインタです。これは挿入された(INSERTの場合)、削除された(DELETEの場合)、更新された(UPDATEの場合)タプルです。もしINSERT/DELETEの場合、タプルを別のもの(INSERT)で置き換えるか演算子を飛ばしたくなければ、これをエクゼキュータに返してください。
もしこれが INSERT か DELETE のためで、UPDATE か NULL ならば、タプルの新しいバージョンのためのポインタです。もしUPDATEだった場合で別のタプルで置き換えるか演算を飛ばしたくなければ、これをエクゼキュータに返してください。
utils/rel.h で定義された、構造体 Trigger へのポインタです。
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 文で指定された引数へのポインタの配列です。他のメンバは内部使用のみです。