37.1. Обзор поведения триггеров событий#

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-команды это:

  • 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

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

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

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-операций, которые пользователи могут выполнять.