37.1. Обзор поведения триггеров событий#
37.1. Обзор поведения триггеров событий #
Событийный триггер срабатывает каждый раз, когда в базе данных, в которой он определён, происходит связанное с ним событие. В настоящее время поддерживаются следующие события: login, ddl_command_start, ddl_command_end, table_rewrite и sql_drop. Поддержка дополнительных событий может быть добавлена в будущих версиях.
37.1.1. вход #
Событие login происходит, когда аутентифицированный пользователь входит в систему. Любая ошибка в процедуре триггера для этого события может предотвратить успешный вход в систему. Такие ошибки можно обойти, установив event_triggers в false либо в строке подключения, либо в файле конфигурации. В качестве альтернативы, вы можете перезапустить систему в однопользовательском режиме (так как триггеры событий отключены в этом режиме). Подробности о использовании однопользовательского режима смотрите на справочной странице postgres. Событие login также будет срабатывать на резервных серверах. Чтобы предотвратить недоступность серверов, такие триггеры должны избегать записи чего-либо в базу данных при работе на резервном сервере. Также рекомендуется избегать длительных запросов в триггерах события login. Обратите внимание, что, например, отмена соединения в psql не отменит выполняющийся триггер login.
Пример использования событийного триггера login приведен в Раздел 37.5.
37.1.2. ddl_command_start #
Событие ddl_command_start происходит непосредственно перед выполнением DDL-команды. В данном контексте DDL-команды это:
CREATEALTERDROPCOMMENTGRANTIMPORT FOREIGN SCHEMAREINDEXREFRESH MATERIALIZED VIEWREVOKESECURITY LABEL
ddl_command_start также возникает непосредственно перед выполнением команды SELECT INTO, поскольку она эквивалентна CREATE TABLE AS.
В качестве исключения, это событие не срабатывает для DDL-команд, направленных на общие объекты:
базы данных
роли (определения ролей и членство в ролях)
табличные пространства
права на параметры
ALTER SYSTEM
Это событие также не срабатывает для команд, направленных на сами событийные триггеры.
Проверка существования целевого объекта перед срабатыванием событийного триггера не выполняется.
37.1.3. ddl_command_end #
Событие ddl_command_end происходит сразу после выполнения того же набора команд, что и ddl_command_start. Чтобы получить более подробную информацию об операциях DDL, вызвавших событие, используйте функцию pg_event_trigger_ddl_commands(), возвращающую набор строк, из кода обработчика события ddl_command_end (см. Раздел 9.30). Обратите внимание, что триггер срабатывает после того, как действия уже были выполнены (но до фиксации транзакции), и, таким образом, в системных каталогах видны уже изменённые состояния.
37.1.4. sql_drop #
Событие sql_drop происходит непосредственно перед событийным триггером ddl_command_end для любой операции, которая удаляет объекты базы данных. Обратите внимание, что помимо очевидных команд DROP, некоторые команды ALTER также могут вызывать событие sql_drop.
Чтобы получить список удаленных объектов, используйте функцию, возвращающую набор строк, pg_event_trigger_dropped_objects() из кода обработчика события sql_drop (см. Раздел 9.30). Обратите внимание, что триггер выполняется после того, как объекты были удалены из системных каталогов, поэтому их больше невозможно найти.
37.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).
37.1.6. Событийные триггеры в прерванных транзакциях #
Триггеры событий (как и другие функции) не могут быть выполнены в аннулированной транзакции. Таким образом, если команда DDL завершается с ошибкой, триггеры ddl_command_end не будут выполнены. Напротив, если триггер ddl_command_start завершается с ошибкой, дальнейшие триггеры событий не будут запущены, и попытка выполнить саму команду не будет предпринята. Аналогично, если триггер ddl_command_end завершается с ошибкой, эффекты оператора DDL будут отменены, как и в любом другом случае, когда транзакция прерывается.
37.1.7. Создание событийных триггеров #
Создание триггеров событий выполняется с помощью команды CREATE EVENT TRIGGER.
Для создания триггера событий необходимо сначала создать функцию с особым типом возвращаемого значения event_trigger. Эта функция не обязана (и не может) возвращать значение; тип возвращаемого значения служит только сигналом о том, что функция должна быть вызвана как триггер событий.
Если для определенного события определено более одного триггера, они будут запускаться в алфавитном порядке по имени триггера.
Определение триггера также может указывать условие WHEN,
чтобы, например, триггер ddl_command_start мог быть запущен только для определенных команд, которые пользователь хочет перехватить. Обычное использование таких триггеров - ограничение диапазона DDL-операций, которые пользователи могут выполнять.