本節介紹觸發器函式的介面的底層細節。這些資訊僅在用 C 編寫觸發器函式時需要。如果您使用的是更高階的語言,那麼這些細節將由語言本身處理。在大多數情況下,您應該考慮使用過程語言,然後再用 C 編寫觸發器。每種過程語言的文件都解釋瞭如何在該語言中編寫觸發器。
觸發器函式必須使用“版本 1”函式管理器介面。
當觸發器管理器呼叫函式時,不會向函式傳遞任何常規引數,而是會傳遞一個指向 TriggerData
結構的“上下文”指標。C 函式可以透過執行以下宏來檢查它們是否由觸發器管理器呼叫:
CALLED_AS_TRIGGER(fcinfo)
它會展開為
((fcinfo)->context != NULL && IsA((fcinfo)->context, TriggerData))
如果此宏返回 true,那麼將 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; TupleTableSlot *tg_trigslot; TupleTableSlot *tg_newslot; Tuplestorestate *tg_oldtable; Tuplestorestate *tg_newtable; const Bitmapset *tg_updatedcols; } TriggerData;
其成員定義如下:
type
始終為 T_TriggerData
。
tg_event
描述函式被呼叫的事件。您可以使用以下宏來檢查 tg_event
:
TRIGGER_FIRED_BEFORE(tg_event)
如果觸發器在操作之前觸發,則返回 true。
TRIGGER_FIRED_AFTER(tg_event)
如果觸發器在操作之後觸發,則返回 true。
TRIGGER_FIRED_INSTEAD(tg_event)
如果觸發器在操作的替代位置觸發,則返回 true。
TRIGGER_FIRED_FOR_ROW(tg_event)
如果觸發器因行級事件觸發,則返回 true。
TRIGGER_FIRED_FOR_STATEMENT(tg_event)
如果觸發器因語句級事件觸發,則返回 true。
TRIGGER_FIRED_BY_INSERT(tg_event)
如果觸發器是由 INSERT
命令觸發的,則返回 true。
TRIGGER_FIRED_BY_UPDATE(tg_event)
如果觸發器是由 UPDATE
命令觸發的,則返回 true。
TRIGGER_FIRED_BY_DELETE(tg_event)
如果觸發器是由 DELETE
命令觸發的,則返回 true。
TRIGGER_FIRED_BY_TRUNCATE(tg_event)
如果觸發器是由 TRUNCATE
命令觸發的,則返回 true。
tg_relation
指向描述觸發器觸發的關係的結構體。有關此結構體的詳細資訊,請參閱 utils/rel.h
。最值得關注的是 tg_relation->rd_att
(關係元組的描述符)和 tg_relation->rd_rel->relname
(關係名稱;其型別不是 char*
而是 NameData
;如果您需要關係的名稱副本,請使用 SPI_getrelname(tg_relation)
獲取 char*
)。
tg_trigtuple
指向觸發器觸發的行的指標。這是正在插入、更新或刪除的行。如果此觸發器是由 INSERT
或 DELETE
觸發的,並且您不希望替換該行(對於 INSERT
)或跳過操作,那麼您應該從函式返回此指標。對於外表上的觸發器,其中的系統列值是未指定的。
tg_newtuple
如果觸發器是由 UPDATE
觸發的,則指向行的新版本,如果是 INSERT
或 DELETE
,則為 NULL
。如果事件是 UPDATE
,並且您不希望用不同的行替換此行或跳過操作,那麼您必須從函式返回此指標。對於外表上的觸發器,其中的系統列值是未指定的。
tg_trigger
指向型別為 Trigger
的結構體的指標,該結構體定義在 utils/reltrigger.h
中。
typedef struct Trigger { Oid tgoid; char *tgname; Oid tgfoid; int16 tgtype; char tgenabled; bool tgisinternal; bool tgisclone; 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
是觸發器的名稱,tgnargs
是 tgargs
中引數的數量,而 tgargs
是指向 CREATE TRIGGER
語句中指定的引數的指標陣列。其他成員僅供內部使用。
tg_trigslot
包含 tg_trigtuple
的槽,如果沒有這樣的元組,則為 NULL
指標。
tg_newslot
包含 tg_newtuple
的槽,如果沒有這樣的元組,則為 NULL
指標。
tg_oldtable
指向型別為 Tuplestorestate
的結構體的指標,該結構體包含零個或多個行,格式由 tg_relation
指定,如果沒有 OLD TABLE
轉換表,則為 NULL
指標。
tg_newtable
指向型別為 Tuplestorestate
的結構體的指標,該結構體包含零個或多個行,格式由 tg_relation
指定,如果沒有 NEW TABLE
轉換表,則為 NULL
指標。
tg_updatedcols
對於 UPDATE
觸發器,這是一個位圖集,指示由觸發命令更新的列。通用的觸發器函式可以使用它來最佳化操作,而無需處理未更改的列。
例如,要確定具有屬性編號 attnum
(1-based)的列是否是此點陣圖集中的成員,請呼叫 bms_is_member(attnum - FirstLowInvalidHeapAttributeNumber, trigdata->tg_updatedcols))
。
對於 UPDATE
觸發器以外的觸發器,此欄位將為 NULL
。
要允許透過 SPI 發出的查詢引用轉換表,請參閱 SPI_register_trigger_data。
觸發器函式必須返回 HeapTuple
指標或 NULL
指標(不是 SQL null 值,即不要將 isNull
設定為 true)。如果您不希望修改正在操作的行,請務必根據情況返回 tg_trigtuple
或 tg_newtuple
。
如果您在文件中發現任何不正確的內容,與您對特定功能的體驗不符,或者需要進一步澄清,請使用 此表單 報告文件問題。