43.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');Заметьте, что сама триггерная функция не знает имени столбца; оно передаётся в аргументах триггера. Это позволяет применять эту функцию для различных таблиц.