В данном разделе описываются низкоуровневые детали интерфейса триггерной функции. Данная информация необходима только при написании триггерных функций на языке 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 можно использовать
следующие макросы: 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)
Возвращает true, если триггер был вызван INSERT командой.
TRIGGER_FIRED_BY_UPDATE(tg_event)
Возвращает true, если триггер был вызван UPDATE командой.
TRIGGER_FIRED_BY_DELETE(tg_event)
Возвращает true, если триггер был вызван DELETE командой.
TRIGGER_FIRED_BY_TRUNCATE(tg_event)
Возвращает true, если триггер был вызван TRUNCATE командой.
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, и NULL если
это триггер для INSERT или
DELETE. Данное значение необходимо вернуть
из функции, если событием является UPDATE
и не требуется замена этой строки другой или
пропустить операцию. Для триггеров на сторонних таблицах значения системных
столбцов в данном контексте не определены.
tg_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, или NULL указатель
при отсутствии OLD TABLE переходное отношение.
tg_newtable
Указатель на структуру типа Tuplestorestate
содержащий ноль или более строк в формате, определенном
tg_relation, или NULL указатель
при отсутствии NEW TABLE переходное отношение.
tg_updatedcols
Для UPDATE триггеров предусмотрено битовое множество, указывающее на
столбцы, обновленные вызвавшей триггер командой. Универсальные триггерные
функции могут использовать это для оптимизации, исключая необходимость обработки
неизмененных столбцов.
Например, для проверки того, является ли столбец с номером атрибута
attnum (начиная с 1) элементом данного битового множества,
следует вызвать 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,
соответствующим образом, если не требуется изменять обрабатываемую строку.