本節では、トリガ関数とのインタフェースについて低レベルな詳細を説明します。 この情報は、Cでトリガ関数を作成する時にのみ必要です。 高レベルな言語で作成すれば、こうした詳細は代わりに扱ってもらえます。 各手続き言語の文書で、その言語を使用したトリガ言語の作成方法を説明します。
トリガ関数は"version 1"関数マネージャインタフェースを使わなくてはいけません。
関数がトリガマネージャから呼び出される時は、通常のパラメータが渡されるのではなく、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で発行された場合真を返します。
トリガがAFTERで発行された場合真を返します。
トリガが行レベルのイベントを発行した場合真を返します。
トリガが文レベルのイベントを発行した場合真を返します。
トリガがINSERTコマンドで発行された場合真を返します。
トリガがUPDATEコマンドで発行された場合真を返します。
トリガがDELETEコマンドで発行された場合真を返します。
トリガの発行元のリレーションを記述する構造体へのポインタです。 この構造体についての詳細は、utils/rel.hを参照してください。 最も興味深いのは、tg_relation->rd_att(リレーションタプルの記述子)とtg_relation->rd_rel->relnameです(リレーション名、これはchar*ではなくNameDataです。 名前のコピーが必要な場合は、char*を得るためにSPI_getrelname(tg_relation)を使用してください)。
トリガが発行された行へのポインタです。 これは挿入される、削除される、あるいは更新されるタプルです。 もしINSERT/DELETEでこのトリガが発行された時、 この行を別のもので置き換えたくない(INSERTの場合)場合や、演算子を飛ばしたくない場合は、これをこの関数から返してください。
トリガがUPDATEで発行された場合は、行の新しいバージョンへのポインタです。 INSERTもしくはDELETEの場合は、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文で指定された引数へのポインタの配列です。 他のメンバは内部でのみ使用されます。
トリガ関数はNULLもしくはHeapTupleポインタのどちらかを返さなければなりません。 操作対象の行を変更したくない場合は、注意して、tg_trigtupleかtg_newtupleの適切な方を返してください。