42.6. Функции триггеров в PL/Tcl#

42.6. Функции триггеров в PL/Tcl

42.6. Функции триггеров в PL/Tcl

Функции триггеров могут быть написаны на PL/Tcl. Tantor SE требует, чтобы функция, которая должна быть вызвана как триггер, была объявлена как функция без аргументов и с типом возвращаемого значения trigger.

Информация от менеджера триггеров передается в тело функции в следующих переменных:

$TG_name

Имя триггера из оператора CREATE TRIGGER.

$TG_relid

Идентификатор объекта таблицы, вызвавшей функцию триггера.

$TG_table_name

Имя таблицы, вызвавшей функцию триггера.

$TG_table_schema

Схема таблицы, вызвавшей функцию триггера.

$TG_relatts

Список столбцов таблицы на языке Tcl, с префиксом пустого элемента списка. Таким образом, поиск имени столбца в списке с помощью команды Tcl lsearch возвращает номер элемента, начиная с 1 для первого столбца, так же, как принято нумеровать столбцы в Tantor SE. (Пустые элементы списка также появляются на позициях столбцов, которые были удалены, чтобы нумерация атрибутов была правильной для столбцов справа).

$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 DELETE или INSTEAD OF DELETE уровня строки возвращение измененной строки имеет тот же эффект, что и возвращение OK, то есть операция выполняется. Значение, возвращаемое триггером, игнорируется для всех остальных типов триггеров.

Подсказка

Список результатов может быть создан из массивного представления измененного кортежа с помощью команды Tcl array get.

Вот небольшой пример функции триггера, которая заставляет целочисленное значение в таблице отслеживать количество обновлений, выполняемых для строки. Для новых вставленных строк значение инициализируется нулем, а затем увеличивается при каждой операции обновления.

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');

Обратите внимание, что сама функция триггера не знает имя столбца; оно передается из аргументов триггера. Это позволяет повторно использовать функцию триггера с разными таблицами.