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

PostgreSQL 9.0.0文書
前のページ | 巻戻し | 第 36章トリガ | 早送り | 次のページ

# 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_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/rel.h`で定義された、`Trigger`構造体へのポインタです。

      typedef struct Trigger
      {
          Oid         tgoid;
          char       *tgname;
          Oid         tgfoid;
          int16       tgtype;
          bool        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`の適切な方を返してください。

前のページ | ホーム | 次のページ
データ変更の可視性 | 上に戻る | 完全なトリガの例