35.3. Escrita de funções de gatilho em C

Esta seção descreve os detalhes de baixo nível da interface com a função de gatilho. Estas informações somente são necessárias para se escrever funções de gatilho em C. Se estiver sendo utilizada uma linguagem de nível mais alto, então estes detalhes são tratados para você. A documentação de cada linguagem procedural explica como escrever gatilhos nesta linguagem.

A função de gatilho deve utilizar a interface de gerência de função "versão 1".

Quando uma função é chamada pelo gerenciador de gatilho não é passado nenhum argumento normal, mas é passado um ponteiro de "contexto" apontando para a estrutura TriggerData. As funções em C podem verificar se foram chamadas pelo gerenciador de gatilhos executando a macro

CALLED_AS_TRIGGER(fcinfo)

que expande para

((fcinfo)->context != NULL && IsA((fcinfo)->context, TriggerData))

Se retornar verdade, então é seguro converter fcinfo->context no tipo TriggerData * e fazer uso da estrutura TriggerData apontada. A função não deve alterar a estrutura de TriggerData ou de qualquer dado apontado por esta.

A struct TriggerData está definida em commands/trigger.h:

typedef struct TriggerData
{
    NodeTag       type;
    TriggerEvent  tg_event;
    Relation      tg_relation;
    HeapTuple     tg_trigtuple;
    HeapTuple     tg_newtuple;
    Trigger      *tg_trigger;
} TriggerData;

onde os membros estão definidos conforme mostrado abaixo:

type
Sempre T_TriggerData.
tg_event
Descreve o evento para o qual a função foi chamada. Podem ser utilizadas as seguintes macros para examinar tg_event:
TRIGGER_FIRED_BEFORE(tg_event)
Retorna verdade se o gatilho disparou antes da operação.
TRIGGER_FIRED_AFTER(tg_event)
Retorna verdade se o gatilho disparou depois da operação.
TRIGGER_FIRED_FOR_ROW(tg_event)
Retorna verdade se o gatilho disparou para um evento no nível-de-linha.
TRIGGER_FIRED_FOR_STATEMENT(tg_event)
Retorna verdade se o gatilho disparou 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.

tg_relation
Um ponteiro para a estrutura que descreve a relação para a qual o gatilho foi disparado. Os detalhes sobre esta estrutura devem ser procurados no arquivo utils/rel.h. Os itens mais interessantes 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*, e sim NameData; deve ser utilizado SPI_getrelname(tg_relation) para obter char* se for necessário copiar o nome).
tg_trigtuple
Ponteiro para a linha para a qual o gatilho foi disparado. Esta é a linha sendo inserida, atualizada ou excluída. Se este gatilho foi disparado por um INSERT ou DELETE, então é o que deve ser retornado pela função se não for desejado substituir a linha por outra diferente (no caso do INSERT) ou saltar a operação.
tg_newtuple
Ponteiro para a nova versão da linha, se o gatilho foi disparado por um UPDATE, ou NULL, se foi disparado por um INSERT ou DELETE. É o que deve ser retornado pela função se o evento for um UPDATE e não for desejado substituir a linha por outra diferente ou saltar a operação.
tg_trigger
Um ponteiro para a estrutura do tipo Trigger, definida no arquivo utils/rel.h:
typedef struct Trigger
{
    Oid         tgoid;
    char       *tgname;
    Oid         tgfoid;
    int16       tgtype;
    bool        tgenabled;
    bool        tgisconstraint;
    Oid         tgconstrrelid;
    bool        tgdeferrable;
    bool        tginitdeferred;
    int16       tgnargs;
    int16       tgattr[FUNC_MAX_ARGS];
    char      **tgargs;
} 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 declaração CREATE TRIGGER. Os outros membros são para uso interno apenas.

Uma função de gatilho deve retornar um ponteiro para HeapTuple ou um ponteiro NULL. Deve-se tomar o cuidado de retornar tg_trigtuple ou tg_newtuple, conforme seja apropriado, se não for desejado modificar a linha onde está sendo realizada a operação.

SourceForge.net Logo