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

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

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

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

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

Событие ddl_command_start происходит непосредственно перед выполнением команды CREATE, ALTER, DROP, SECURITY LABEL, COMMENT, GRANT или REVOKE. Перед срабатыванием триггера события не выполняется проверка наличия или отсутствия затронутого объекта. Однако, существует исключение: данное событие не происходит для команд DDL, направленных на общие объекты - базы данных, роли и табличные пространства имен, а также для команд, направленных на сами триггеры событий. Механизм триггеров событий не поддерживает эти типы объектов. Событие ddl_command_start также происходит непосредственно перед выполнением команды SELECT INTO, так как она эквивалентна команде CREATE TABLE AS.

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

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

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

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

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

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

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

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