無料スクリプト配布のPHP.TO   PHPの実用的なtips PHPマニュアル MySQLマニュアル Apacheマニュアル PostgreSQLマニュアル マニュアル検索    

36.3. Cによるトリガ関数の作成

本節ではトリガ関数とのインタフェースについて低レベルな詳細を説明します。 この情報はC言語でトリガ関数を作成する時にのみ必要です。 高レベルな言語で作成すれば、こうした詳細は代わりに扱ってもらえます。 たいていの場合、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;
    Buffer        tg_trigtuplebuf;
    Buffer        tg_newtuplebuf;
} TriggerData;

メンバは下記のように定義されています。

type

常に T_TriggerData です。

tg_event

その関数が呼び出されたイベントを記述します。 tg_event を調べるためには下記のマクロを使うことができます。

TRIGGER_FIRED_BEFORE(tg_event)

トリガがBEFOREで発行された場合真を返します。

TRIGGER_FIRED_AFTER(tg_event)

トリガがAFTERで発行された場合真を返します。

TRIGGER_FIRED_INSTEAD(tg_event)

トリガがINSTEAD OFで発行された場合真を返します。

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 です。 名前のコピーが必要な場合は、 char* を得るために SPI_getrelname(tg_relation) を使用してください)。

tg_trigtuple

トリガが発行された行へのポインタです。 これは挿入される、削除される、あるいは更新される行です。 もし INSERT / DELETE でこのトリガが発行された時、この行を別のもので置き換えたくない( INSERT の場合)場合や、その操作を飛ばしたくない場合は、これをこの関数から返してください。

tg_newtuple

トリガが UPDATE で発行された場合は、行の新しいバージョンへのポインタです。 INSERT もしくは DELETE の場合は、 NULL です。 UPDATE イベントの時、この行を別のもので置き換えたくない場合や操作を飛ばしたくない場合は、これをこの関数から返してください。

tg_trigger

以下のように utils/reltrigger.h で定義された、 Trigger 構造体へのポインタです。

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;

ここで、 tgname がトリガの名前、 tgnargs tgargs 内の引数の数、 tgargs CREATE TRIGGER 文で指定された引数へのポインタの配列です。 他のメンバは内部でのみ使用されます。

tg_trigtuplebuf

tg_trigtuple を含むバッファです。 そうしたタプルが存在しない場合やディスクバッファ内に格納されていない場合は InvalidBuffer です。

tg_newtuplebuf

tg_newtuple を含むバッファです。 そうしたタプルが存在しない場合やディスクバッファ内に格納されていない場合は InvalidBuffer です。

トリガ関数は HeapTuple ポインタもしくは NULL ポインタ(SQLのNULLでは ありません 。 したがって、 isNull は真にはなりません)のどちらかを返さなければなりません。 操作対象の行を変更したくない場合は、注意して、 tg_trigtuple tg_newtuple の適切な方を返してください。


powered by SEO.CUG.NET