38.1. Обзор механизма работы триггеров событий #

Триггер события срабатывает всякий раз, когда в базе данных, в которой он определён, происходит связанное с ним событие. В настоящий момент поддерживаются следующие события: login, ddl_command_start, ddl_command_end, table_rewrite и sql_drop. Поддержка дополнительных событий может быть добавлена в будущих выпусках.

38.1.1. login #

Событие login происходит, когда аутентифицированный пользователь входит в систему. Любые ошибки в процедуре триггера для этого события могут помешать успешному входу в систему. Таких ошибок можно избежать, задав для параметра event_triggers значение false в строке подключения или файле конфигурации. Кроме того, можно перезапустить сервер в однопользовательском режиме (поскольку триггеры событий в этом режиме отключены). За дополнительными сведениями об однопользовательском режиме обратитесь к справке по postgres. Событийный триггер login также срабатывает на резервных серверах. Во избежание проблем с подключением к серверам, работающие на них триггеры login не должны ничего записывать в базу данных. Кроме того, рекомендуется избегать длительных запросов в событийных триггерах login. Обратите внимание, что отмена подключения в psql не отменит текущий триггер login.

Пример использования триггера события login приведён в Разделе 38.5.

38.1.2. ddl_command_start #

Событие ddl_command_start происходит непосредственно перед выполнением команды DDL. В данном контексте командами DDL считаются:

  • CREATE

  • ALTER

  • DROP

  • COMMENT

  • GRANT

  • IMPORT FOREIGN SCHEMA

  • REINDEX

  • REFRESH MATERIALIZED VIEW

  • REVOKE

  • SECURITY LABEL

Событие ddl_command_start также происходит перед выполнением команды SELECT INTO, так как она равнозначна CREATE TABLE AS.

В качестве исключения это событие не срабатывает для команд DDL, направленных на общие объекты:

  • базы данных

  • роли (определения ролей и членство в ролях)

  • табличные пространства

  • права на параметры

  • ALTER SYSTEM

Оно также не срабатывает для команд, направленных на сами триггеры событий.

Проверка существования целевого объекта до срабатывания событийного триггера не выполняется.

38.1.3. ddl_command_end #

Событие ddl_command_end происходит непосредственно после выполнения того же набора команд, что и для ddl_command_start. Чтобы получить дополнительную информацию об операциях DDL, повлёкших произошедшее событие, вызовите функцию pg_event_trigger_ddl_commands(), возвращающую множество, из кода обработчика события ddl_command_end (см. Раздел 9.30). Заметьте, что этот триггер срабатывает после того, как эти действия имели место (но до фиксации транзакции), так что в системных каталогах можно увидеть уже изменённое состояние.

38.1.4. sql_drop #

Событие sql_drop происходит непосредственно перед событием ddl_command_end для любой операции, которая удаляет объекты базы данных. Обратите внимание, что кроме очевидных команд DROP некоторые команды ALTER также могут вызывать событие sql_drop.

Для получения списка удалённых объектов используйте возвращающую набор строк функцию pg_event_trigger_dropped_objects() в триггере события sql_drop (см. Раздел 9.30). Обратите внимание, что триггер выполняется после удаления объектов из таблиц системного каталога, поэтому их невозможно больше увидеть.

38.1.5. table_rewrite #

Событие table_rewrite происходит непосредственно перед тем, как таблица будет перезаписана в результате определённых действий команд ALTER TABLE и ALTER TYPE. Хотя перезапись таблицы может быть вызвана и другими управляющими операторами, в частности CLUSTER и VACUUM, событие table_rewrite для них не вызывается. Найти OID таблицы, которая была перезаписана, можно с помощью функции pg_event_trigger_table_rewrite_oid(). Чтобы узнать причину (причины) перезаписи, используйте функцию pg_event_trigger_table_rewrite_reason() (см. Раздел 9.30).

38.1.6. Событийные триггеры в прерванных транзакциях #

Триггеры событий (как и прочие функции) не могут выполняться в прерванной транзакции. Поэтому, если команда DDL завершается ошибкой, соответствующие триггеры ddl_command_end не сработают. И наоборот, если триггер ddl_command_end завершился с ошибкой, последующие триггеры событий не сработают, так же как и сама команда не будет выполняться. Похожим образом, если триггер ddl_command_end завершится ошибкой, действие команды DDL будет отменено, как это происходит при возникновении ошибки внутри транзакции.

38.1.7. Создание событийных триггеров #

Для создания триггера события используется команда CREATE EVENT TRIGGER. Предварительно нужно создать функцию, со специальным возвращаемым типом event_trigger. Данная функция не обязана возвращать значение (и может не возвращать). Возвращаемый тип служит лишь указанием на то, что функция будет вызываться из триггера события.

Если есть несколько триггеров на одно и то же событие, то они будут вызываться в алфавитном порядке по имени триггера.

В определении триггера можно использовать условие WHEN, чтобы, например, триггер ddl_command_start срабатывал только для отдельных команд, которые нужно перехватить. Триггеры событий часто используются для ограничения диапазона DDL-команд, доступных пользователям.