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

39.1.1. имя_пользователя
39.1.2. ddl_command_start
39.1.3. ddl_command_end
39.1.4. sql_drop
39.1.5. table_rewrite
39.1.6. Событийные триггеры в прерванных транзакциях
39.1.7. Создание событийных триггеров

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

39.1.1. имя_пользователя #

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

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

39.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

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

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

39.1.3. ddl_command_end #

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

39.1.4. sql_drop #

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

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

39.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).

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

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

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

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

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

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