37.3. Триггерные функции на языке C
В этом разделе описываются низкоуровневые детали интерфейса для триггерных функций. Эта информация необходима только при разработке триггерных функций на языке C. При использовании языка более высокого уровня эти детали обрабатываются не видны. В большинстве случаев стоит рассмотреть возможность использования процедурного языка, прежде чем начать разрабатывать триггеры на C. В документации по каждому процедурному языку объясняется, как создавать триггеры на этом языке.
Триггерные функции должны использовать интерфейс функций «версии 1».
Когда функция вызывается диспетчером триггеров, ей не передаются обычные аргументы, но передаётся указатель «context», ссылающийся на структуру TriggerData
. Функции на C могут проверить, вызваны ли они диспетчером триггеров или нет, выполнив макрос:
CALLED_AS_TRIGGER(fcinfo)
который разворачивается в:
((fcinfo)->context != NULL && IsA((fcinfo)->context, TriggerData))
Если возвращается истина, то fcinfo->context
можно безопасно привести к типу TriggerData *
и использовать указатель на структуру TriggerData
. Функция не должна изменять структуру TriggerData
или любые данные, которые на неё указывают.
struct TriggerData
определяется в commands/trigger.h
:
typedef struct TriggerData { NodeTag type; TriggerEvent tg_event; Relation tg_relation; HeapTuple tg_trigtuple; HeapTuple tg_newtuple; Trigger *tg_trigger; TupleTableSlot *tg_trigslot; TupleTableSlot *tg_newslot; Tuplestorestate *tg_oldtable; Tuplestorestate *tg_newtable; } TriggerData;
где элементы определяются следующим образом:
type
Всегда
T_TriggerData
.tg_event
Описывает событие, для которого вызывается функция. Можно использовать следующие макросы для получения информации о
tg_event
:TRIGGER_FIRED_BEFORE(tg_event)
Возвращает истину, если триггер сработал до операции.
TRIGGER_FIRED_AFTER(tg_event)
Возвращает истину, если триггер сработал после операции.
TRIGGER_FIRED_INSTEAD(tg_event)
Возвращает истину, если триггер сработал вместо операции.
TRIGGER_FIRED_FOR_ROW(tg_event)
Возвращает истину, если триггер сработал на уровне строки.
TRIGGER_FIRED_FOR_STATEMENT(tg_event)
Возвращает истину, если триггер сработал на уровне оператора.
TRIGGER_FIRED_BY_INSERT(tg_event)
Возвращает истину, если триггер сработал для операции
INSERT
.TRIGGER_FIRED_BY_UPDATE(tg_event)
Возвращает истину, если триггер сработал для операции
UPDATE
.TRIGGER_FIRED_BY_DELETE(tg_event)
Возвращает истину, если триггер сработал для операции
DELETE
.TRIGGER_FIRED_BY_TRUNCATE(tg_event)
Возвращает истину, если триггер сработал для операции
TRUNCATE
.
tg_relation
Указатель на структуру, описывающую таблицу, для которой сработал триггер. Подробнее об этой структуре в
utils/rel.h
. Самое интересное здесь этоtg_relation->rd_att
(дескриптор записей таблицы) иtg_relation->rd_rel->relname
(имя таблицы; имеет типNameData
, а неchar*
; используйтеSPI_getrelname(tg_relation)
, чтобы получить типchar*
если потребуется копия имени).tg_trigtuple
Указатель на строку, для которой сработал триггер. Это строка, которая вставляется, обновляется или удаляется. При срабатывании триггера для
INSERT
илиDELETE
это значение нужно вернуть из функции, только если не планируется изменять строку (в случаеINSERT
) или пропускать операцию для этой строки.tg_newtuple
Для триггера на
UPDATE
это указатель на новую версию строки либоNULL
, если триггер наINSERT
илиDELETE
. Это значение нужно вернуть из функции в случаеUPDATE
, если не планируется изменять строку или пропускать операцию для этой строки.tg_trigger
Указатель на структуру с типом
Trigger
, определённую вutils/reltrigger.h
:typedef struct Trigger { Oid tgoid; char *tgname; Oid tgfoid; int16 tgtype; char tgenabled; bool tgisinternal; Oid tgconstrrelid; Oid tgconstrindid; Oid tgconstraint; bool tgdeferrable; bool tginitdeferred; int16 tgnargs; int16 tgnattr; int16 *tgattr; char **tgargs; char *tgqual; char *tgoldtable; char *tgnewtable; } Trigger;
где
tgname
— имя триггера,tgnargs
— количество аргументов вtgargs
, иtgargs
— массив указателей на аргументы, указанные в командеCREATE TRIGGER
. Остальные члены структуры предназначены для внутреннего использования.tg_trigslot
Слот, содержащий
tg_trigtuple
, или указательNULL
, если такой строки нет.tg_newslot
Слот, содержащий
tg_newtuple
, или указательNULL
, если такой строки нет.tg_oldtable
Указатель на структуру типа
Tuplestorestate
, содержащую ноль или несколько строк в формате, определяемом содержимымtg_relation
, или указательNULL
, если переходное отношениеOLD TABLE
отсутствует.tg_newtable
Указатель на структуру типа
Tuplestorestate
, содержащую ноль или несколько строк в формате, определяемом содержимымtg_relation
, или указательNULL
, если переходное отношениеNEW TABLE
отсутствует.
Чтобы обращаться к переходным таблицам в запросах, выполняемых через SPI, используйте SPI_register_trigger_data.
Триггерная функция должна возвращать указатель HeapTuple
или указатель NULL
(но не SQL значение null
, то есть не нужно устанавливать isNull
в истину). Не забудьте, что если не планируете менять обрабатываемую триггером строку, то нужно вернуть либо tg_trigtuple
, либо tg_newtuple
.
ALTER MATERIALIZED VIEW
ALTER MATERIALIZED VIEW — change the definition of a materialized view
Synopsis
ALTER MATERIALIZED VIEW [ IF EXISTS ]name
action
[, ... ] ALTER MATERIALIZED VIEWname
[ NO ] DEPENDS ON EXTENSIONextension_name
ALTER MATERIALIZED VIEW [ IF EXISTS ]name
RENAME [ COLUMN ]column_name
TOnew_column_name
ALTER MATERIALIZED VIEW [ IF EXISTS ]name
RENAME TOnew_name
ALTER MATERIALIZED VIEW [ IF EXISTS ]name
SET SCHEMAnew_schema
ALTER MATERIALIZED VIEW ALL IN TABLESPACEname
[ OWNED BYrole_name
[, ... ] ] SET TABLESPACEnew_tablespace
[ NOWAIT ] whereaction
is one of: ALTER [ COLUMN ]column_name
SET STATISTICSinteger
ALTER [ COLUMN ]column_name
SET (attribute_option
=value
[, ... ] ) ALTER [ COLUMN ]column_name
RESET (attribute_option
[, ... ] ) ALTER [ COLUMN ]column_name
SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN } ALTER [ COLUMN ]column_name
SET COMPRESSIONcompression_method
CLUSTER ONindex_name
SET WITHOUT CLUSTER SET ACCESS METHODnew_access_method
SET TABLESPACEnew_tablespace
SET (storage_parameter
[=value
] [, ... ] ) RESET (storage_parameter
[, ... ] ) OWNER TO {new_owner
| CURRENT_ROLE | CURRENT_USER | SESSION_USER }
Description
ALTER MATERIALIZED VIEW
changes various auxiliary properties of an existing materialized view.
You must own the materialized view to use ALTER MATERIALIZED VIEW
. To change a materialized view's schema, you must also have CREATE
privilege on the new schema. To alter the owner, you must also be a direct or indirect member of the new owning role, and that role must have CREATE
privilege on the materialized view's schema. (These restrictions enforce that altering the owner doesn't do anything you couldn't do by dropping and recreating the materialized view. However, a superuser can alter ownership of any view anyway.)
The statement subforms and actions available for ALTER MATERIALIZED VIEW
are a subset of those available for ALTER TABLE
, and have the same meaning when used for materialized views. See the descriptions for ALTER TABLE
for details.
Parameters
name
The name (optionally schema-qualified) of an existing materialized view.
column_name
Name of an existing column.
extension_name
The name of the extension that the materialized view is to depend on (or no longer dependent on, if
NO
is specified). A materialized view that's marked as dependent on an extension is automatically dropped when the extension is dropped.new_column_name
New name for an existing column.
new_owner
The user name of the new owner of the materialized view.
new_name
The new name for the materialized view.
new_schema
The new schema for the materialized view.
Examples
To rename the materialized view foo
to bar
:
ALTER MATERIALIZED VIEW foo RENAME TO bar;
Compatibility
ALTER MATERIALIZED VIEW
is a Postgres Pro extension.