40.1. Обзор механизма работы триггеров событий
Триггер события срабатывает всякий раз, когда в базе данных, в которой он определён, происходит связанное с ним событие. В настоящий момент поддерживаются следующие события: ddl_command_start
, ddl_command_end
, table_rewrite
и sql_drop
. Поддержка дополнительных событий может быть добавлена в будущих выпусках.
Событие ddl_command_start
происходит непосредственно перед выполнением команд CREATE
, ALTER
, DROP
, SECURITY LABEL
, COMMENT
, GRANT
и REVOKE
. Проверка на существование объекта перед срабатыванием триггера не производится. В качестве исключения, однако, это событие не происходит для команд DDL, обращающихся к общим объектам кластера базы данных — базам данных, табличным пространствам, ролям, а также к самим триггерам событий. Событие ddl_command_start
также происходит непосредственно перед выполнением команды SELECT INTO
, так как она равнозначна команде CREATE TABLE AS
.
Событие ddl_command_end
происходит непосредственно после выполнения команд из того же набора. Чтобы получить дополнительную информацию об операциях DDL, повлёкших произошедшее событие, вызовите функцию pg_event_trigger_ddl_commands()
, возвращающую множество, из кода обработчика события ddl_command_end
(см. Раздел 9.29). Заметьте, что этот триггер срабатывает после того, как эти действия имели место (но до фиксации транзакции), так что в системных каталогах можно увидеть уже изменённое состояние.
Событие sql_drop
происходит непосредственно перед событием ddl_command_end
для команд, которые удаляют объекты базы данных. Для получения списка удалённых объектов используйте возвращающую набор строк функцию pg_event_trigger_dropped_objects()
в триггере события sql_drop
(см. Раздел 9.29). Обратите внимание, что триггер выполняется после удаления объектов из таблиц системного каталога, поэтому их невозможно больше увидеть.
Событие table_rewrite
происходит непосредственно перед тем, как таблица будет перезаписана в результате определённых действий команд ALTER TABLE
и ALTER TYPE
. Хотя перезапись таблицы может быть вызвана и другими управляющими операторами, в частности CLUSTER
и VACUUM
, событие table_rewrite
для них не вызывается. Найти OID таблицы, которая была перезаписана, можно с помощью функции pg_event_trigger_table_rewrite_oid()
(см. Раздел 9.29). Причину (причины) перезаписи можно посмотреть с помощью функции pg_event_trigger_table_rewrite_reason()
.
Триггеры событий (как и прочие функции) не могут выполняться в прерванной транзакции. Поэтому, если команда DDL завершается ошибкой, соответствующие триггеры ddl_command_end
не сработают. И наоборот, если триггер ddl_command_end
завершился с ошибкой, последующие триггеры событий не сработают, так же как и сама команда не будет выполняться. Похожим образом, если триггер ddl_command_end
завершится ошибкой, действие команды DDL будет отменено, как это происходит при возникновении ошибки внутри транзакции.
Полный список команд, которые поддерживаются триггерами событий, можно найти в Разделе 40.2.
Для создания триггера события используется команда CREATE EVENT TRIGGER. Предварительно нужно создать функцию, со специальным возвращаемым типом event_trigger
. Данная функция не обязана возвращать значение (и может не возвращать). Возвращаемый тип служит лишь указанием на то, что функция будет вызываться из триггера события.
Если есть несколько триггеров на одно и то же событие, то они будут вызываться в алфавитном порядке по имени триггера.
В определении триггера можно использовать условие WHEN
, чтобы, например, триггер ddl_command_start
срабатывал только для отдельных команд, которые нужно перехватить. Триггеры событий часто используются для ограничения диапазона DDL-команд, доступных пользователям.