46.6. Триггерные функции на PL/Tcl
На PL/Tcl можно написать триггерные функции. Postgres Pro требует, чтобы функция, которая будет вызываться как триггерная, была объявлена как функция без аргументов и возвращала тип trigger
.
Информация от менеджера триггеров передаётся в тело функции в следующих переменных:
$TG_name
Имя триггера из оператора
CREATE TRIGGER
.$TG_relid
Идентификатор объекта таблицы, для которой будет вызываться триггерная функция.
$TG_table_name
Имя таблицы, для которой будет вызываться триггерная функция.
$TG_table_schema
Схема таблицы, для которой будет вызываться триггерная функция.
$TG_relatts
Список языка Tcl, содержащий имена столбцов таблицы. В начало списка добавлен пустой элемент, поэтому при поиске в этом списке имени столбца с помощью стандартной в Tcl команды
lsearch
будет возвращён номер элемента, начиная с 1, так же, как нумеруются столбцы в Postgres Pro. (В позициях удалённых столбцов также содержатся пустые элементы, так что нумерация следующих за ними атрибутов не нарушается.)$TG_when
Строка
BEFORE
,AFTER
илиINSTEAD OF
, в зависимости от типа события триггера.$TG_level
Строка
ROW
илиSTATEMENT
, в зависимости от уровня события триггера.$TG_op
Строка
INSERT
,UPDATE
,DELETE
илиTRUNCATE
, в зависимости от действия события триггера.$NEW
Ассоциативный массив, содержащий значения новой строки таблицы для действий
INSERT
илиUPDATE
, либо пустой массив дляDELETE
. Индексами в массиве являются имена столбцов. Столбцы со значениями NULL в нём отсутствуют. Для триггеров уровня оператора этот массив не определяется.$OLD
Ассоциативный массив, содержащий значения старой строки таблицы для действий
UPDATE
илиDELETE
, либо пустой массив дляINSERT
. Индексами в массиве являются имена столбцов. Столбцы со значениями NULL в нём отсутствуют. Для триггеров уровня оператора этот массив не определяется.$args
Список на языке Tcl аргументов функции, заданных в операторе
CREATE TRIGGER
. Эти аргументы также доступны под обозначениями$1
...$
в теле функции.n
Возвращаемым значением триггерной функции может быть строка OK
или SKIP
либо список пар имя столбца/значение. Если возвращается значение OK
, операция (INSERT
/UPDATE
/DELETE
), которая привела к срабатыванию триггера, выполняется нормально. Значение SKIP
указывает менеджеру триггеров просто пропустить эту операцию с текущей строкой данных. Если возвращается список, через него PL/Tcl передаёт менеджеру триггеров изменённую строку; содержимое изменённой строки задаётся именами и значениями столбцов в списке. Все столбцы, не перечисленные в этом списке, получают значения NULL. Возвращать изменённую строку имеет смысл только для триггеров уровня строки с порядком BEFORE
команд INSERT
и UPDATE
, в которых вместо заданной в $NEW
будет записываться изменённая строка; либо с порядком INSTEAD OF
команд INSERT
и UPDATE
, в которых возвращаемая строка служит исходными данными для предложений INSERT RETURNING
или UPDATE RETURNING
. В триггерах уровня строки с порядком BEFORE
или INSTEAD OF
команды DELETE
возврат изменённой строки воспринимается так же, как и возврат значения OK
, то есть операция выполняется. Для всех остальных типов триггеров возвращаемое значение игнорируется.
Подсказка
Список результатов можно создать из изменённого кортежа, представленного в виде массива, с помощью команды array get
языка Tcl.
Следующий небольшой пример показывает триггерную функцию, которая ведёт в таблице целочисленный счётчик числа изменений, выполненных в строке. Для новых строк счётчик инициализируется нулевым значением, а затем увеличивается на единицу при каждом изменении.
CREATE FUNCTION trigfunc_modcount() RETURNS trigger AS $$ switch $TG_op { INSERT { set NEW($1) 0 } UPDATE { set NEW($1) $OLD($1) incr NEW($1) } default { return OK } } return [array get NEW] $$ LANGUAGE pltcl; CREATE TABLE mytab (num integer, description text, modcnt integer); CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab FOR EACH ROW EXECUTE FUNCTION trigfunc_modcount('modcnt');
Заметьте, что сама триггерная функция не знает имени столбца; оно передаётся в аргументах триггера. Это позволяет применять эту функцию для различных таблиц.