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-команд, доступных пользователям.