39.4. Полный пример триггера события
Вот очень простой пример функции для триггера события, написанной на C. (Примеры триггеров для процедурных языков могут быть найдены в документации на процедурные языки.)
Функция noddl
выдаёт ошибку при каждом вызове. Триггер с этой функцией определяется для события ddl_command_start
. Это предотвращает работу любых DDL-команд (за исключением тех, о которых говорилось в Разделе 39.1).
Теперь исходный код триггерной функции:
#include "postgres.h" #include "commands/event_trigger.h" PG_MODULE_MAGIC; PG_FUNCTION_INFO_V1(noddl); Datum noddl(PG_FUNCTION_ARGS) { EventTriggerData *trigdata; if (!CALLED_AS_EVENT_TRIGGER(fcinfo)) /* internal error */ elog(ERROR, "not fired by event trigger manager"); trigdata = (EventTriggerData *) fcinfo->context; ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("command \"%s\" denied", trigdata->tag))); PG_RETURN_NULL(); }
После компиляции исходного кода (см. Подраздел 37.9.5) объявляем функцию и триггеры:
CREATE FUNCTION noddl() RETURNS event_trigger AS 'noddl' LANGUAGE C; CREATE EVENT TRIGGER noddl ON ddl_command_start EXECUTE PROCEDURE noddl();
Теперь проверим работу триггера:
=# \dy List of event triggers Name | Event | Owner | Enabled | Procedure | Tags -------+-------------------+-------+---------+-----------+------ noddl | ddl_command_start | dim | enabled | noddl | (1 row) =# CREATE TABLE foo(id serial); ERROR: Команда "CREATE TABLE" отменена
В этой ситуации, для запуска DDL-команд, нужно либо удалить триггер события, либо отключить его. Может быть удобным отключить триггер на время выполнения транзакции:
BEGIN; ALTER EVENT TRIGGER noddl DISABLE; CREATE TABLE foo (id serial); ALTER EVENT TRIGGER noddl ENABLE; COMMIT;
(Вспомним, что триггеры событий не обрабатывают DDL-команды для самих триггеров событий.)
SPI_freetuptable
SPI_freetuptable — free a row set created by SPI_execute
or a similar function
Synopsis
void SPI_freetuptable(SPITupleTable * tuptable
)
Description
SPI_freetuptable
frees a row set created by a prior SPI command execution function, such as SPI_execute
. Therefore, this function is often called with the global variable SPI_tuptable
as argument.
This function is useful if an SPI-using C function needs to execute multiple commands and does not want to keep the results of earlier commands around until it ends. Note that any unfreed row sets will be freed anyway at SPI_finish
. Also, if a subtransaction is started and then aborted within execution of an SPI-using C function, SPI automatically frees any row sets created while the subtransaction was running.
Beginning in PostgreSQL 9.3, SPI_freetuptable
contains guard logic to protect against duplicate deletion requests for the same row set. In previous releases, duplicate deletions would lead to crashes.
Arguments
SPITupleTable *
tuptable
pointer to row set to free, or NULL to do nothing