Esta seção descreve detalhes de baixo nível da interface para uma função de gatilho. Estas informações são necessárias apenas quando se escreve funções de gatilho em C. Se estiver sendo usada uma linguagem de alto nível, estes detalhes serão tratados pela própria linguagem. Geralmente, deve-se considerar o uso de uma linguagem procedural antes de escrever gatilhos em C. A documentação de cada linguagem procedural explica como escrever gatilho nesta linguagem.
As funções de gatilho devem usar a interface do gerenciador de função “versão 1”.
Quando uma função é chamada pelo gerenciador de gatilhos, ela não
recebe nenhum argumento normal, mas é passado um ponteiro
“context” apontando para uma estrutura
TriggerData.
As funções em C podem verificar se foram chamadas
pelo gerenciador de gatilhos ou não, executando a macro:
CALLED_AS_TRIGGER(fcinfo)
que se expande para:
((fcinfo)->context != NULL && IsA((fcinfo)->context, TriggerData))
Se retornar o valor verdade, então é seguro converter
fcinfo->context para o tipo
TriggerData *, e usar a estrutura apontada
por TriggerData.
A função não deve alterar a estrutura de
TriggerData, ou qualquer um dos dados para
os quais ela aponta.
A estrutura struct TriggerData é definida
no arquivo de cabeçalho 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;
const Bitmapset *tg_updatedcols;
} TriggerData;
onde os campos são definidos da seguinte forma:
type
Sempre T_TriggerData.
tg_event
Descreve o evento para o qual a função é chamada.
Podem ser usadas as seguintes macros para examinar
tg_event:
TRIGGER_FIRED_BEFORE(tg_event)Retorna verdade se o gatilho foi disparado antes da operação.
TRIGGER_FIRED_AFTER(tg_event)Retorna verdade se o gatilho foi disparado após a operação.
TRIGGER_FIRED_INSTEAD(tg_event)Retorna verdade se o gatilho foi disparado em vez da operação.
TRIGGER_FIRED_FOR_ROW(tg_event)Retorna verdade se o gatilho foi disparado para um evento no nível de linha.
TRIGGER_FIRED_FOR_STATEMENT(tg_event)Retorna verdade se o gatilho foi disparado para um evento no nível de instrução.
TRIGGER_FIRED_BY_INSERT(tg_event)
Retorna verdade se o gatilho foi disparado por um comando
INSERT.
TRIGGER_FIRED_BY_UPDATE(tg_event)
Retorna verdade se o gatilho foi disparado por um comando
UPDATE.
TRIGGER_FIRED_BY_DELETE(tg_event)
Retorna verdade se o gatilho foi disparado por um comando
DELETE.
TRIGGER_FIRED_BY_TRUNCATE(tg_event)
Retorna verdade se o gatilho foi disparado por um comando
TRUNCATE.
tg_relation
Ponteiro para uma estrutura que descreve a relação para a qual
o gatilho foi disparado.
Deve ser consultado o arquivo de cabeçalho
utils/rel.h para obter detalhes sobre esta
estrutura.
As informações de maior interesse são
tg_relation->rd_att
(descritor das tuplas da relação) e
tg_relation->rd_rel->relname
(nome da relação; o tipo não é char*, mas sim
NameData; deve ser usado
SPI_getrelname(tg_relation) para obter
char*, se for necessário obter uma cópia do nome).
tg_trigtuple
Ponteiro para a linha para a qual o gatilho foi disparado.
Esta é a linha que está sendo inserida, atualizada ou excluída.
Se o gatilho foi disparado para um comando
INSERT ou DELETE, então é
isto que a função deve retornar se não quiser substituir a linha
por uma linha diferente (no caso de INSERT),
ou saltar a operação.
Para os gatilhos em tabelas estrangeiras, os valores das colunas
do sistema não são especificados aqui.
tg_newtuple
Ponteiro para a nova versão da linha, se o gatilho foi
disparado por um comando UPDATE, ou
NULL se foi por um INSERT
ou DELETE.
É isto que a função deve retornar, se o evento for um
UPDATE e não se deseja substituir a linha
por uma linha diferente ou saltar a operação.
Para os gatilhos em tabelas estrangeiras, os valores das colunas
do sistema não são especificados aqui.
tg_trigger
Ponteiro para uma estrutura do tipo Trigger,
definida mo arquivo de cabeçalho utils/reltrigger.h:
typedef struct Trigger
{
Oid tgoid;
char *tgname;
Oid tgfoid;
int16 tgtype;
char tgenabled;
bool tgisinternal;
bool tgisclone;
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;
onde tgname é o nome do gatilho,
tgnargs é o número de argumentos em
tgargs, e
tgargs é uma matriz de ponteiros para
os argumentos especificados na instrução
CREATE TRIGGER.
Os demais campos são apenas para uso interno.
tg_trigslot
O encaixe contendo tg_trigtuple,
ou um ponteiro NULL, caso não haja esta tupla.
tg_newslot
O encaixe contendo tg_newtuple,
ou um ponteiro NULL, caso não haja esta tupla.
tg_oldtable
Um ponteiro para uma estrutura do tipo
Tuplestorestate,
contendo zero ou mais linhas no formato especificado por
tg_relation,
ou um ponteiro NULL, caso não haja a
relação de transição OLD TABLE.
tg_newtable
Um ponteiro para uma estrutura do tipo
Tuplestorestate,
contendo zero ou mais linhas no formato especificado por
tg_relation,
ou um ponteiro NULL, caso não haja a
relação de transição NEW TABLE.
tg_updatedcols
Para os gatilhos de UPDATE, um conjunto de
bitmap indicando as colunas
atualizadas pelo comando disparador.
As funções de gatilho genéricas podem usar esta informação para
otimizar ações, por não ter que lidar com colunas que não foram
modificadas.
Por exemplo, para determinar se a coluna com número de atributo
attnum (com base em 1) é membro desse conjunto
de bitmap, deve-se chamar
bms_is_member(attnum -
FirstLowInvalidHeapAttributeNumber,
trigdata->tg_updatedcols)).
Para os gatilhos diferentes dos gatilhos de
UPDATE, será NULL.
Para permitir que consultas chamadas por meio de SPI façam referência a tabelas de transição, veja SPI_register_trigger_data.
Uma função de gatilho deve retornar um ponteiro
HeapTuple ou um ponteiro NULL
(e não um valor SQL nulo,
ou seja, não se deve definir isNull como
verdade).
Deve-se tomar o cuidado de retornar
tg_trigtuple ou
tg_newtuple,
conforme apropriado, se não for desejado modificar a linha que
está sendo operada.