PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
trigger.h File Reference
Include dependency graph for trigger.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  TriggerData
 

Macros

#define CALLED_AS_TRIGGER(fcinfo)   ((fcinfo)->context != NULL && IsA((fcinfo)->context, TriggerData))
 
#define TRIGGER_EVENT_INSERT   0x00000000
 
#define TRIGGER_EVENT_DELETE   0x00000001
 
#define TRIGGER_EVENT_UPDATE   0x00000002
 
#define TRIGGER_EVENT_TRUNCATE   0x00000003
 
#define TRIGGER_EVENT_OPMASK   0x00000003
 
#define TRIGGER_EVENT_ROW   0x00000004
 
#define TRIGGER_EVENT_BEFORE   0x00000008
 
#define TRIGGER_EVENT_AFTER   0x00000000
 
#define TRIGGER_EVENT_INSTEAD   0x00000010
 
#define TRIGGER_EVENT_TIMINGMASK   0x00000018
 
#define AFTER_TRIGGER_DEFERRABLE   0x00000020
 
#define AFTER_TRIGGER_INITDEFERRED   0x00000040
 
#define TRIGGER_FIRED_BY_INSERT(event)   (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_INSERT)
 
#define TRIGGER_FIRED_BY_DELETE(event)   (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_DELETE)
 
#define TRIGGER_FIRED_BY_UPDATE(event)   (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_UPDATE)
 
#define TRIGGER_FIRED_BY_TRUNCATE(event)   (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_TRUNCATE)
 
#define TRIGGER_FIRED_FOR_ROW(event)   ((event) & TRIGGER_EVENT_ROW)
 
#define TRIGGER_FIRED_FOR_STATEMENT(event)   (!TRIGGER_FIRED_FOR_ROW(event))
 
#define TRIGGER_FIRED_BEFORE(event)   (((event) & TRIGGER_EVENT_TIMINGMASK) == TRIGGER_EVENT_BEFORE)
 
#define TRIGGER_FIRED_AFTER(event)   (((event) & TRIGGER_EVENT_TIMINGMASK) == TRIGGER_EVENT_AFTER)
 
#define TRIGGER_FIRED_INSTEAD(event)   (((event) & TRIGGER_EVENT_TIMINGMASK) == TRIGGER_EVENT_INSTEAD)
 
#define SESSION_REPLICATION_ROLE_ORIGIN   0
 
#define SESSION_REPLICATION_ROLE_REPLICA   1
 
#define SESSION_REPLICATION_ROLE_LOCAL   2
 
#define TRIGGER_FIRES_ON_ORIGIN   'O'
 
#define TRIGGER_FIRES_ALWAYS   'A'
 
#define TRIGGER_FIRES_ON_REPLICA   'R'
 
#define TRIGGER_DISABLED   'D'
 
#define RI_TRIGGER_PK   1 /* is a trigger on the PK relation */
 
#define RI_TRIGGER_FK   2 /* is a trigger on the FK relation */
 
#define RI_TRIGGER_NONE   0 /* is not an RI trigger function */
 

Typedefs

typedef uint32 TriggerEvent
 
typedef struct TriggerData TriggerData
 

Functions

ObjectAddress CreateTrigger (CreateTrigStmt *stmt, const char *queryString, Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid, bool isInternal)
 
void RemoveTriggerById (Oid trigOid)
 
Oid get_trigger_oid (Oid relid, const char *name, bool missing_ok)
 
ObjectAddress renametrig (RenameStmt *stmt)
 
void EnableDisableTrigger (Relation rel, const char *tgname, char fires_when, bool skip_system)
 
void RelationBuildTriggers (Relation relation)
 
TriggerDescCopyTriggerDesc (TriggerDesc *trigdesc)
 
void FreeTriggerDesc (TriggerDesc *trigdesc)
 
void ExecBSInsertTriggers (EState *estate, ResultRelInfo *relinfo)
 
void ExecASInsertTriggers (EState *estate, ResultRelInfo *relinfo)
 
TupleTableSlotExecBRInsertTriggers (EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
 
void ExecARInsertTriggers (EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple, List *recheckIndexes)
 
TupleTableSlotExecIRInsertTriggers (EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
 
void ExecBSDeleteTriggers (EState *estate, ResultRelInfo *relinfo)
 
void ExecASDeleteTriggers (EState *estate, ResultRelInfo *relinfo)
 
bool ExecBRDeleteTriggers (EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple)
 
void ExecARDeleteTriggers (EState *estate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple)
 
bool ExecIRDeleteTriggers (EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple)
 
void ExecBSUpdateTriggers (EState *estate, ResultRelInfo *relinfo)
 
void ExecASUpdateTriggers (EState *estate, ResultRelInfo *relinfo)
 
TupleTableSlotExecBRUpdateTriggers (EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot *slot)
 
void ExecARUpdateTriggers (EState *estate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, HeapTuple newtuple, List *recheckIndexes)
 
TupleTableSlotExecIRUpdateTriggers (EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple, TupleTableSlot *slot)
 
void ExecBSTruncateTriggers (EState *estate, ResultRelInfo *relinfo)
 
void ExecASTruncateTriggers (EState *estate, ResultRelInfo *relinfo)
 
void AfterTriggerBeginXact (void)
 
void AfterTriggerBeginQuery (void)
 
void AfterTriggerEndQuery (EState *estate)
 
void AfterTriggerFireDeferred (void)
 
void AfterTriggerEndXact (bool isCommit)
 
void AfterTriggerBeginSubXact (void)
 
void AfterTriggerEndSubXact (bool isCommit)
 
void AfterTriggerSetState (ConstraintsSetStmt *stmt)
 
bool AfterTriggerPendingOnRel (Oid relid)
 
bool RI_FKey_pk_upd_check_required (Trigger *trigger, Relation pk_rel, HeapTuple old_row, HeapTuple new_row)
 
bool RI_FKey_fk_upd_check_required (Trigger *trigger, Relation fk_rel, HeapTuple old_row, HeapTuple new_row)
 
bool RI_Initial_Check (Trigger *trigger, Relation fk_rel, Relation pk_rel)
 
int RI_FKey_trigger_type (Oid tgfoid)
 

Variables

PGDLLIMPORT int SessionReplicationRole
 

Macro Definition Documentation

#define AFTER_TRIGGER_DEFERRABLE   0x00000020

Definition at line 67 of file trigger.h.

Referenced by afterTriggerCheckState(), AfterTriggerSaveEvent(), and ExecCallTriggerFunc().

#define AFTER_TRIGGER_INITDEFERRED   0x00000040

Definition at line 68 of file trigger.h.

Referenced by afterTriggerCheckState(), AfterTriggerSaveEvent(), and ExecCallTriggerFunc().

#define RI_TRIGGER_FK   2 /* is a trigger on the FK relation */

Definition at line 210 of file trigger.h.

Referenced by AfterTriggerSaveEvent(), and RI_FKey_trigger_type().

#define RI_TRIGGER_NONE   0 /* is not an RI trigger function */

Definition at line 211 of file trigger.h.

Referenced by AfterTriggerSaveEvent(), CreateTrigger(), and RI_FKey_trigger_type().

#define RI_TRIGGER_PK   1 /* is a trigger on the PK relation */

Definition at line 209 of file trigger.h.

Referenced by AfterTriggerSaveEvent(), and RI_FKey_trigger_type().

#define SESSION_REPLICATION_ROLE_LOCAL   2

Definition at line 102 of file trigger.h.

#define SESSION_REPLICATION_ROLE_ORIGIN   0

Definition at line 100 of file trigger.h.

#define SESSION_REPLICATION_ROLE_REPLICA   1

Definition at line 101 of file trigger.h.

Referenced by filter_event_trigger(), matchLocks(), and TriggerEnabled().

#define TRIGGER_DISABLED   'D'

Definition at line 112 of file trigger.h.

Referenced by ATExecCmd(), BuildEventTriggerCache(), and TriggerEnabled().

#define TRIGGER_EVENT_AFTER   0x00000000

Definition at line 61 of file trigger.h.

#define TRIGGER_EVENT_DELETE   0x00000001
#define TRIGGER_EVENT_INSTEAD   0x00000010

Definition at line 62 of file trigger.h.

Referenced by ExecIRDeleteTriggers(), ExecIRInsertTriggers(), and ExecIRUpdateTriggers().

#define TRIGGER_EVENT_OPMASK   0x00000003

Definition at line 56 of file trigger.h.

Referenced by AfterTriggerExecute(), and AfterTriggerSaveEvent().

#define TRIGGER_EVENT_TIMINGMASK   0x00000018

Definition at line 63 of file trigger.h.

#define TRIGGER_EVENT_TRUNCATE   0x00000003

Definition at line 55 of file trigger.h.

Referenced by AfterTriggerSaveEvent(), ExecASTruncateTriggers(), and ExecBSTruncateTriggers().

#define TRIGGER_FIRED_BY_TRUNCATE (   event)    (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_TRUNCATE)
#define TRIGGER_FIRED_FOR_STATEMENT (   event)    (!TRIGGER_FIRED_FOR_ROW(event))
#define TRIGGER_FIRED_INSTEAD (   event)    (((event) & TRIGGER_EVENT_TIMINGMASK) == TRIGGER_EVENT_INSTEAD)
#define TRIGGER_FIRES_ALWAYS   'A'

Definition at line 110 of file trigger.h.

Referenced by ATExecCmd().

#define TRIGGER_FIRES_ON_ORIGIN   'O'
#define TRIGGER_FIRES_ON_REPLICA   'R'

Definition at line 111 of file trigger.h.

Referenced by ATExecCmd(), filter_event_trigger(), and TriggerEnabled().

Typedef Documentation

Definition at line 28 of file trigger.h.

Function Documentation

void AfterTriggerBeginQuery ( void  )

Definition at line 4150 of file trigger.c.

References AfterTriggersData::query_depth.

Referenced by CopyFrom(), ExecuteTruncate(), and standard_ExecutorStart().

4151 {
4152  /* Increase the query stack depth */
4154 }
static AfterTriggersData afterTriggers
Definition: trigger.c:3404
void AfterTriggerBeginSubXact ( void  )

Definition at line 4374 of file trigger.c.

References DEFTRIG_INITALLOC, AfterTriggersData::depth_stack, AfterTriggersData::events, AfterTriggersData::events_stack, AfterTriggersData::firing_counter, AfterTriggersData::firing_stack, GetCurrentTransactionNestLevel(), AfterTriggersData::maxtransdepth, MemoryContextSwitchTo(), NULL, palloc(), AfterTriggersData::query_depth, repalloc(), AfterTriggersData::state_stack, and TopTransactionContext.

Referenced by StartSubTransaction().

4375 {
4376  int my_level = GetCurrentTransactionNestLevel();
4377 
4378  /*
4379  * Allocate more space in the stacks if needed. (Note: because the
4380  * minimum nest level of a subtransaction is 2, we waste the first couple
4381  * entries of each array; not worth the notational effort to avoid it.)
4382  */
4383  while (my_level >= afterTriggers.maxtransdepth)
4384  {
4385  if (afterTriggers.maxtransdepth == 0)
4386  {
4387  MemoryContext old_cxt;
4388 
4390 
4391 #define DEFTRIG_INITALLOC 8
4396  afterTriggers.depth_stack = (int *)
4397  palloc(DEFTRIG_INITALLOC * sizeof(int));
4399  palloc(DEFTRIG_INITALLOC * sizeof(CommandId));
4401 
4402  MemoryContextSwitchTo(old_cxt);
4403  }
4404  else
4405  {
4406  /* repalloc will keep the stacks in the same context */
4407  int new_alloc = afterTriggers.maxtransdepth * 2;
4408 
4411  new_alloc * sizeof(SetConstraintState));
4414  new_alloc * sizeof(AfterTriggerEventList));
4415  afterTriggers.depth_stack = (int *)
4417  new_alloc * sizeof(int));
4420  new_alloc * sizeof(CommandId));
4421  afterTriggers.maxtransdepth = new_alloc;
4422  }
4423  }
4424 
4425  /*
4426  * Push the current information into the stack. The SET CONSTRAINTS state
4427  * is not saved until/unless changed. Likewise, we don't make a
4428  * per-subtransaction event context until needed.
4429  */
4430  afterTriggers.state_stack[my_level] = NULL;
4434 }
uint32 CommandId
Definition: c.h:408
MemoryContext TopTransactionContext
Definition: mcxt.c:48
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define DEFTRIG_INITALLOC
CommandId * firing_stack
Definition: trigger.c:3400
SetConstraintState * state_stack
Definition: trigger.c:3397
CommandId firing_counter
Definition: trigger.c:3384
AfterTriggerEventList * events_stack
Definition: trigger.c:3398
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:760
#define NULL
Definition: c.h:226
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1021
void * palloc(Size size)
Definition: mcxt.c:891
AfterTriggerEventList events
Definition: trigger.c:3386
static AfterTriggersData afterTriggers
Definition: trigger.c:3404
void AfterTriggerBeginXact ( void  )

Definition at line 4112 of file trigger.c.

References Assert, AfterTriggersData::depth_stack, AfterTriggersData::event_cxt, AfterTriggersData::events, AfterTriggersData::events_stack, AfterTriggersData::fdw_tuplestores, AfterTriggersData::firing_counter, AfterTriggersData::firing_stack, AfterTriggerEventList::head, AfterTriggersData::maxquerydepth, AfterTriggersData::maxtransdepth, AfterTriggersData::new_tuplestores, NULL, AfterTriggersData::old_tuplestores, AfterTriggersData::query_depth, AfterTriggersData::query_stack, AfterTriggersData::state, and AfterTriggersData::state_stack.

Referenced by StartTransaction().

4113 {
4114  /*
4115  * Initialize after-trigger state structure to empty
4116  */
4117  afterTriggers.firing_counter = (CommandId) 1; /* mustn't be 0 */
4119 
4120  /*
4121  * Verify that there is no leftover state remaining. If these assertions
4122  * trip, it means that AfterTriggerEndXact wasn't called or didn't clean
4123  * up properly.
4124  */
4138 }
uint32 CommandId
Definition: c.h:408
Tuplestorestate ** old_tuplestores
Definition: trigger.c:3390
CommandId * firing_stack
Definition: trigger.c:3400
SetConstraintState * state_stack
Definition: trigger.c:3397
SetConstraintState state
Definition: trigger.c:3385
CommandId firing_counter
Definition: trigger.c:3384
AfterTriggerEventList * events_stack
Definition: trigger.c:3398
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
AfterTriggerEventChunk * head
Definition: trigger.c:3306
MemoryContext event_cxt
Definition: trigger.c:3393
Tuplestorestate ** fdw_tuplestores
Definition: trigger.c:3389
AfterTriggerEventList events
Definition: trigger.c:3386
AfterTriggerEventList * query_stack
Definition: trigger.c:3388
static AfterTriggersData afterTriggers
Definition: trigger.c:3404
Tuplestorestate ** new_tuplestores
Definition: trigger.c:3391
void AfterTriggerEndQuery ( EState estate)

Definition at line 4170 of file trigger.c.

References afterTriggerFreeEventList(), afterTriggerInvokeEvents(), afterTriggerMarkEvents(), Assert, AfterTriggersData::events, AfterTriggersData::fdw_tuplestores, AfterTriggersData::firing_counter, AfterTriggersData::maxquerydepth, AfterTriggersData::new_tuplestores, NULL, AfterTriggersData::old_tuplestores, AfterTriggersData::query_depth, AfterTriggersData::query_stack, and tuplestore_end().

Referenced by CopyFrom(), ExecuteTruncate(), and standard_ExecutorFinish().

4171 {
4172  AfterTriggerEventList *events;
4173  Tuplestorestate *fdw_tuplestore;
4174  Tuplestorestate *old_tuplestore;
4175  Tuplestorestate *new_tuplestore;
4176 
4177  /* Must be inside a query, too */
4179 
4180  /*
4181  * If we never even got as far as initializing the event stack, there
4182  * certainly won't be any events, so exit quickly.
4183  */
4185  {
4187  return;
4188  }
4189 
4190  /*
4191  * Process all immediate-mode triggers queued by the query, and move the
4192  * deferred ones to the main list of deferred events.
4193  *
4194  * Notice that we decide which ones will be fired, and put the deferred
4195  * ones on the main list, before anything is actually fired. This ensures
4196  * reasonably sane behavior if a trigger function does SET CONSTRAINTS ...
4197  * IMMEDIATE: all events we have decided to defer will be available for it
4198  * to fire.
4199  *
4200  * We loop in case a trigger queues more events at the same query level.
4201  * Ordinary trigger functions, including all PL/pgSQL trigger functions,
4202  * will instead fire any triggers in a dedicated query level. Foreign key
4203  * enforcement triggers do add to the current query level, thanks to their
4204  * passing fire_triggers = false to SPI_execute_snapshot(). Other
4205  * C-language triggers might do likewise. Be careful here: firing a
4206  * trigger could result in query_stack being repalloc'd, so we can't save
4207  * its address across afterTriggerInvokeEvents calls.
4208  *
4209  * If we find no firable events, we don't have to increment
4210  * firing_counter.
4211  */
4212  for (;;)
4213  {
4215  if (afterTriggerMarkEvents(events, &afterTriggers.events, true))
4216  {
4217  CommandId firing_id = afterTriggers.firing_counter++;
4218 
4219  /* OK to delete the immediate events after processing them */
4220  if (afterTriggerInvokeEvents(events, firing_id, estate, true))
4221  break; /* all fired */
4222  }
4223  else
4224  break;
4225  }
4226 
4227  /* Release query-local storage for events, including tuplestore if any */
4229  if (fdw_tuplestore)
4230  {
4231  tuplestore_end(fdw_tuplestore);
4233  }
4235  if (old_tuplestore)
4236  {
4237  tuplestore_end(old_tuplestore);
4239  }
4241  if (new_tuplestore)
4242  {
4243  tuplestore_end(new_tuplestore);
4245  }
4247 
4249 }
uint32 CommandId
Definition: c.h:408
Tuplestorestate ** old_tuplestores
Definition: trigger.c:3390
static bool afterTriggerInvokeEvents(AfterTriggerEventList *events, CommandId firing_id, EState *estate, bool delete_ok)
Definition: trigger.c:3967
static void afterTriggerFreeEventList(AfterTriggerEventList *events)
Definition: trigger.c:3630
CommandId firing_counter
Definition: trigger.c:3384
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
void tuplestore_end(Tuplestorestate *state)
Definition: tuplestore.c:450
static bool afterTriggerMarkEvents(AfterTriggerEventList *events, AfterTriggerEventList *move_list, bool immediate_only)
Definition: trigger.c:3895
Tuplestorestate ** fdw_tuplestores
Definition: trigger.c:3389
AfterTriggerEventList events
Definition: trigger.c:3386
AfterTriggerEventList * query_stack
Definition: trigger.c:3388
static AfterTriggersData afterTriggers
Definition: trigger.c:3404
Tuplestorestate ** new_tuplestores
Definition: trigger.c:3391
void AfterTriggerEndSubXact ( bool  isCommit)

Definition at line 4442 of file trigger.c.

References AFTER_TRIGGER_DONE, AFTER_TRIGGER_IN_PROGRESS, afterTriggerFreeEventList(), afterTriggerRestoreEventList(), Assert, AfterTriggerEventData::ate_flags, AfterTriggerSharedData::ats_firing_id, AfterTriggersData::depth_stack, AfterTriggersData::events, AfterTriggersData::events_stack, AfterTriggersData::fdw_tuplestores, AfterTriggersData::firing_stack, for_each_event_chunk, GetCurrentTransactionNestLevel(), GetTriggerSharedData, AfterTriggersData::maxquerydepth, AfterTriggersData::maxtransdepth, AfterTriggersData::new_tuplestores, NULL, AfterTriggersData::old_tuplestores, pfree(), AfterTriggersData::query_depth, AfterTriggersData::query_stack, AfterTriggersData::state, AfterTriggersData::state_stack, and tuplestore_end().

Referenced by AbortSubTransaction(), and CommitSubTransaction().

4443 {
4444  int my_level = GetCurrentTransactionNestLevel();
4446  AfterTriggerEvent event;
4447  AfterTriggerEventChunk *chunk;
4448  CommandId subxact_firing_id;
4449 
4450  /*
4451  * Pop the prior state if needed.
4452  */
4453  if (isCommit)
4454  {
4455  Assert(my_level < afterTriggers.maxtransdepth);
4456  /* If we saved a prior state, we don't need it anymore */
4457  state = afterTriggers.state_stack[my_level];
4458  if (state != NULL)
4459  pfree(state);
4460  /* this avoids double pfree if error later: */
4461  afterTriggers.state_stack[my_level] = NULL;
4463  afterTriggers.depth_stack[my_level]);
4464  }
4465  else
4466  {
4467  /*
4468  * Aborting. It is possible subxact start failed before calling
4469  * AfterTriggerBeginSubXact, in which case we mustn't risk touching
4470  * stack levels that aren't there.
4471  */
4472  if (my_level >= afterTriggers.maxtransdepth)
4473  return;
4474 
4475  /*
4476  * Release any event lists from queries being aborted, and restore
4477  * query_depth to its pre-subxact value. This assumes that a
4478  * subtransaction will not add events to query levels started in a
4479  * earlier transaction state.
4480  */
4482  {
4484  {
4485  Tuplestorestate *ts;
4486 
4488  if (ts)
4489  {
4490  tuplestore_end(ts);
4492  }
4494  if (ts)
4495  {
4496  tuplestore_end(ts);
4498  }
4500  if (ts)
4501  {
4502  tuplestore_end(ts);
4504  }
4505 
4507  }
4508 
4510  }
4512  afterTriggers.depth_stack[my_level]);
4513 
4514  /*
4515  * Restore the global deferred-event list to its former length,
4516  * discarding any events queued by the subxact.
4517  */
4519  &afterTriggers.events_stack[my_level]);
4520 
4521  /*
4522  * Restore the trigger state. If the saved state is NULL, then this
4523  * subxact didn't save it, so it doesn't need restoring.
4524  */
4525  state = afterTriggers.state_stack[my_level];
4526  if (state != NULL)
4527  {
4529  afterTriggers.state = state;
4530  }
4531  /* this avoids double pfree if error later: */
4532  afterTriggers.state_stack[my_level] = NULL;
4533 
4534  /*
4535  * Scan for any remaining deferred events that were marked DONE or IN
4536  * PROGRESS by this subxact or a child, and un-mark them. We can
4537  * recognize such events because they have a firing ID greater than or
4538  * equal to the firing_counter value we saved at subtransaction start.
4539  * (This essentially assumes that the current subxact includes all
4540  * subxacts started after it.)
4541  */
4542  subxact_firing_id = afterTriggers.firing_stack[my_level];
4544  {
4545  AfterTriggerShared evtshared = GetTriggerSharedData(event);
4546 
4547  if (event->ate_flags &
4549  {
4550  if (evtshared->ats_firing_id >= subxact_firing_id)
4551  event->ate_flags &=
4553  }
4554  }
4555  }
4556 }
uint32 CommandId
Definition: c.h:408
Tuplestorestate ** old_tuplestores
Definition: trigger.c:3390
TriggerFlags ate_flags
Definition: trigger.c:3257
#define AFTER_TRIGGER_DONE
Definition: trigger.c:3234
#define for_each_event_chunk(eptr, cptr, evtlist)
Definition: trigger.c:3319
CommandId * firing_stack
Definition: trigger.c:3400
#define GetTriggerSharedData(evt)
Definition: trigger.c:3282
void pfree(void *pointer)
Definition: mcxt.c:992
SetConstraintState * state_stack
Definition: trigger.c:3397
SetConstraintState state
Definition: trigger.c:3385
static void afterTriggerFreeEventList(AfterTriggerEventList *events)
Definition: trigger.c:3630
AfterTriggerEventList * events_stack
Definition: trigger.c:3398
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:760
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
Definition: regguts.h:298
void tuplestore_end(Tuplestorestate *state)
Definition: tuplestore.c:450
static void afterTriggerRestoreEventList(AfterTriggerEventList *events, const AfterTriggerEventList *old_events)
Definition: trigger.c:3653
CommandId ats_firing_id
Definition: trigger.c:3250
#define AFTER_TRIGGER_IN_PROGRESS
Definition: trigger.c:3235
Tuplestorestate ** fdw_tuplestores
Definition: trigger.c:3389
AfterTriggerEventList events
Definition: trigger.c:3386
AfterTriggerEventList * query_stack
Definition: trigger.c:3388
static AfterTriggersData afterTriggers
Definition: trigger.c:3404
Tuplestorestate ** new_tuplestores
Definition: trigger.c:3391
void AfterTriggerEndXact ( bool  isCommit)

Definition at line 4320 of file trigger.c.

References AfterTriggersData::depth_stack, AfterTriggersData::event_cxt, AfterTriggersData::events, AfterTriggersData::events_stack, AfterTriggersData::fdw_tuplestores, AfterTriggersData::firing_stack, AfterTriggerEventList::head, AfterTriggersData::maxquerydepth, AfterTriggersData::maxtransdepth, MemoryContextDelete(), AfterTriggersData::new_tuplestores, NULL, AfterTriggersData::old_tuplestores, AfterTriggersData::query_depth, AfterTriggersData::query_stack, AfterTriggersData::state, AfterTriggersData::state_stack, AfterTriggerEventList::tail, and AfterTriggerEventList::tailfree.

Referenced by AbortTransaction(), CommitTransaction(), and PrepareTransaction().

4321 {
4322  /*
4323  * Forget the pending-events list.
4324  *
4325  * Since all the info is in TopTransactionContext or children thereof, we
4326  * don't really need to do anything to reclaim memory. However, the
4327  * pending-events list could be large, and so it's useful to discard it as
4328  * soon as possible --- especially if we are aborting because we ran out
4329  * of memory for the list!
4330  */
4332  {
4338  }
4339 
4340  /*
4341  * Forget any subtransaction state as well. Since this can't be very
4342  * large, we let the eventual reset of TopTransactionContext free the
4343  * memory instead of doing it here.
4344  */
4350 
4351 
4352  /*
4353  * Forget the query stack and constraint-related state information. As
4354  * with the subtransaction state information, we don't bother freeing the
4355  * memory here.
4356  */
4363 
4364  /* No more afterTriggers manipulation until next transaction starts. */
4366 }
Tuplestorestate ** old_tuplestores
Definition: trigger.c:3390
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
AfterTriggerEventChunk * tail
Definition: trigger.c:3307
CommandId * firing_stack
Definition: trigger.c:3400
SetConstraintState * state_stack
Definition: trigger.c:3397
SetConstraintState state
Definition: trigger.c:3385
AfterTriggerEventList * events_stack
Definition: trigger.c:3398
#define NULL
Definition: c.h:226
AfterTriggerEventChunk * head
Definition: trigger.c:3306
MemoryContext event_cxt
Definition: trigger.c:3393
Tuplestorestate ** fdw_tuplestores
Definition: trigger.c:3389
AfterTriggerEventList events
Definition: trigger.c:3386
AfterTriggerEventList * query_stack
Definition: trigger.c:3388
static AfterTriggersData afterTriggers
Definition: trigger.c:3404
Tuplestorestate ** new_tuplestores
Definition: trigger.c:3391
void AfterTriggerFireDeferred ( void  )

Definition at line 4264 of file trigger.c.

References afterTriggerInvokeEvents(), afterTriggerMarkEvents(), Assert, AfterTriggersData::events, AfterTriggersData::firing_counter, GetTransactionSnapshot(), AfterTriggerEventList::head, NULL, PopActiveSnapshot(), PushActiveSnapshot(), and AfterTriggersData::query_depth.

Referenced by CommitTransaction(), and PrepareTransaction().

4265 {
4266  AfterTriggerEventList *events;
4267  bool snap_pushed = false;
4268 
4269  /* Must not be inside a query */
4271 
4272  /*
4273  * If there are any triggers to fire, make sure we have set a snapshot for
4274  * them to use. (Since PortalRunUtility doesn't set a snap for COMMIT, we
4275  * can't assume ActiveSnapshot is valid on entry.)
4276  */
4277  events = &afterTriggers.events;
4278  if (events->head != NULL)
4279  {
4281  snap_pushed = true;
4282  }
4283 
4284  /*
4285  * Run all the remaining triggers. Loop until they are all gone, in case
4286  * some trigger queues more for us to do.
4287  */
4288  while (afterTriggerMarkEvents(events, NULL, false))
4289  {
4290  CommandId firing_id = afterTriggers.firing_counter++;
4291 
4292  if (afterTriggerInvokeEvents(events, firing_id, NULL, true))
4293  break; /* all fired */
4294  }
4295 
4296  /*
4297  * We don't bother freeing the event list, since it will go away anyway
4298  * (and more efficiently than via pfree) in AfterTriggerEndXact.
4299  */
4300 
4301  if (snap_pushed)
4303 }
uint32 CommandId
Definition: c.h:408
static bool afterTriggerInvokeEvents(AfterTriggerEventList *events, CommandId firing_id, EState *estate, bool delete_ok)
Definition: trigger.c:3967
void PopActiveSnapshot(void)
Definition: snapmgr.c:807
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:300
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:728
CommandId firing_counter
Definition: trigger.c:3384
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
AfterTriggerEventChunk * head
Definition: trigger.c:3306
static bool afterTriggerMarkEvents(AfterTriggerEventList *events, AfterTriggerEventList *move_list, bool immediate_only)
Definition: trigger.c:3895
AfterTriggerEventList events
Definition: trigger.c:3386
static AfterTriggersData afterTriggers
Definition: trigger.c:3404
bool AfterTriggerPendingOnRel ( Oid  relid)

Definition at line 5008 of file trigger.c.

References AFTER_TRIGGER_DONE, AfterTriggerEventData::ate_flags, AfterTriggerSharedData::ats_relid, AfterTriggersData::events, for_each_event_chunk, GetTriggerSharedData, AfterTriggersData::maxquerydepth, AfterTriggersData::query_depth, and AfterTriggersData::query_stack.

Referenced by CheckTableNotInUse().

5009 {
5010  AfterTriggerEvent event;
5011  AfterTriggerEventChunk *chunk;
5012  int depth;
5013 
5014  /* Scan queued events */
5016  {
5017  AfterTriggerShared evtshared = GetTriggerSharedData(event);
5018 
5019  /*
5020  * We can ignore completed events. (Even if a DONE flag is rolled
5021  * back by subxact abort, it's OK because the effects of the TRUNCATE
5022  * or whatever must get rolled back too.)
5023  */
5024  if (event->ate_flags & AFTER_TRIGGER_DONE)
5025  continue;
5026 
5027  if (evtshared->ats_relid == relid)
5028  return true;
5029  }
5030 
5031  /*
5032  * Also scan events queued by incomplete queries. This could only matter
5033  * if TRUNCATE/etc is executed by a function or trigger within an updating
5034  * query on the same relation, which is pretty perverse, but let's check.
5035  */
5036  for (depth = 0; depth <= afterTriggers.query_depth && depth < afterTriggers.maxquerydepth; depth++)
5037  {
5038  for_each_event_chunk(event, chunk, afterTriggers.query_stack[depth])
5039  {
5040  AfterTriggerShared evtshared = GetTriggerSharedData(event);
5041 
5042  if (event->ate_flags & AFTER_TRIGGER_DONE)
5043  continue;
5044 
5045  if (evtshared->ats_relid == relid)
5046  return true;
5047  }
5048  }
5049 
5050  return false;
5051 }
TriggerFlags ate_flags
Definition: trigger.c:3257
#define AFTER_TRIGGER_DONE
Definition: trigger.c:3234
#define for_each_event_chunk(eptr, cptr, evtlist)
Definition: trigger.c:3319
#define GetTriggerSharedData(evt)
Definition: trigger.c:3282
AfterTriggerEventList events
Definition: trigger.c:3386
AfterTriggerEventList * query_stack
Definition: trigger.c:3388
static AfterTriggersData afterTriggers
Definition: trigger.c:3404
void AfterTriggerSetState ( ConstraintsSetStmt stmt)

Definition at line 4714 of file trigger.c.

References AccessShareLock, afterTriggerInvokeEvents(), afterTriggerMarkEvents(), SetConstraintStateData::all_isdeferred, SetConstraintStateData::all_isset, Anum_pg_constraint_conname, Anum_pg_constraint_connamespace, Anum_pg_trigger_tgconstraint, BTEqualStrategyNumber, RangeVar::catalogname, ConstraintNameNspIndexId, ConstraintRelationId, ConstraintsSetStmt::constraints, CStringGetDatum, ConstraintsSetStmt::deferred, elog, ereport, errcode(), errmsg(), ERROR, AfterTriggersData::events, fetch_search_path(), AfterTriggersData::firing_counter, get_database_name(), GetCurrentTransactionNestLevel(), GETSTRUCT, GetTransactionSnapshot(), heap_close, heap_open(), HeapTupleGetOid, HeapTupleIsValid, i, IsSubTransaction(), lappend_oid(), lfirst, lfirst_oid, list_free(), list_make1_oid, LookupExplicitNamespace(), MyDatabaseId, NIL, NULL, SetConstraintStateData::numstates, ObjectIdGetDatum, PopActiveSnapshot(), PushActiveSnapshot(), RangeVar::relname, ScanKeyInit(), RangeVar::schemaname, SetConstraintTriggerData::sct_tgisdeferred, SetConstraintTriggerData::sct_tgoid, SetConstraintStateAddItem(), SetConstraintStateCopy(), SetConstraintStateCreate(), AfterTriggersData::state, AfterTriggersData::state_stack, systable_beginscan(), systable_endscan(), systable_getnext(), TriggerConstraintIndexId, TriggerRelationId, and SetConstraintStateData::trigstates.

Referenced by standard_ProcessUtility().

4715 {
4716  int my_level = GetCurrentTransactionNestLevel();
4717 
4718  /* If we haven't already done so, initialize our state. */
4719  if (afterTriggers.state == NULL)
4721 
4722  /*
4723  * If in a subtransaction, and we didn't save the current state already,
4724  * save it so it can be restored if the subtransaction aborts.
4725  */
4726  if (my_level > 1 &&
4727  afterTriggers.state_stack[my_level] == NULL)
4728  {
4729  afterTriggers.state_stack[my_level] =
4731  }
4732 
4733  /*
4734  * Handle SET CONSTRAINTS ALL ...
4735  */
4736  if (stmt->constraints == NIL)
4737  {
4738  /*
4739  * Forget any previous SET CONSTRAINTS commands in this transaction.
4740  */
4742 
4743  /*
4744  * Set the per-transaction ALL state to known.
4745  */
4746  afterTriggers.state->all_isset = true;
4748  }
4749  else
4750  {
4751  Relation conrel;
4752  Relation tgrel;
4753  List *conoidlist = NIL;
4754  List *tgoidlist = NIL;
4755  ListCell *lc;
4756 
4757  /*
4758  * Handle SET CONSTRAINTS constraint-name [, ...]
4759  *
4760  * First, identify all the named constraints and make a list of their
4761  * OIDs. Since, unlike the SQL spec, we allow multiple constraints of
4762  * the same name within a schema, the specifications are not
4763  * necessarily unique. Our strategy is to target all matching
4764  * constraints within the first search-path schema that has any
4765  * matches, but disregard matches in schemas beyond the first match.
4766  * (This is a bit odd but it's the historical behavior.)
4767  */
4769 
4770  foreach(lc, stmt->constraints)
4771  {
4772  RangeVar *constraint = lfirst(lc);
4773  bool found;
4774  List *namespacelist;
4775  ListCell *nslc;
4776 
4777  if (constraint->catalogname)
4778  {
4779  if (strcmp(constraint->catalogname, get_database_name(MyDatabaseId)) != 0)
4780  ereport(ERROR,
4781  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4782  errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
4783  constraint->catalogname, constraint->schemaname,
4784  constraint->relname)));
4785  }
4786 
4787  /*
4788  * If we're given the schema name with the constraint, look only
4789  * in that schema. If given a bare constraint name, use the
4790  * search path to find the first matching constraint.
4791  */
4792  if (constraint->schemaname)
4793  {
4794  Oid namespaceId = LookupExplicitNamespace(constraint->schemaname,
4795  false);
4796 
4797  namespacelist = list_make1_oid(namespaceId);
4798  }
4799  else
4800  {
4801  namespacelist = fetch_search_path(true);
4802  }
4803 
4804  found = false;
4805  foreach(nslc, namespacelist)
4806  {
4807  Oid namespaceId = lfirst_oid(nslc);
4808  SysScanDesc conscan;
4809  ScanKeyData skey[2];
4810  HeapTuple tup;
4811 
4812  ScanKeyInit(&skey[0],
4814  BTEqualStrategyNumber, F_NAMEEQ,
4815  CStringGetDatum(constraint->relname));
4816  ScanKeyInit(&skey[1],
4818  BTEqualStrategyNumber, F_OIDEQ,
4819  ObjectIdGetDatum(namespaceId));
4820 
4821  conscan = systable_beginscan(conrel, ConstraintNameNspIndexId,
4822  true, NULL, 2, skey);
4823 
4824  while (HeapTupleIsValid(tup = systable_getnext(conscan)))
4825  {
4827 
4828  if (con->condeferrable)
4829  conoidlist = lappend_oid(conoidlist,
4830  HeapTupleGetOid(tup));
4831  else if (stmt->deferred)
4832  ereport(ERROR,
4833  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
4834  errmsg("constraint \"%s\" is not deferrable",
4835  constraint->relname)));
4836  found = true;
4837  }
4838 
4839  systable_endscan(conscan);
4840 
4841  /*
4842  * Once we've found a matching constraint we do not search
4843  * later parts of the search path.
4844  */
4845  if (found)
4846  break;
4847  }
4848 
4849  list_free(namespacelist);
4850 
4851  /*
4852  * Not found ?
4853  */
4854  if (!found)
4855  ereport(ERROR,
4856  (errcode(ERRCODE_UNDEFINED_OBJECT),
4857  errmsg("constraint \"%s\" does not exist",
4858  constraint->relname)));
4859  }
4860 
4861  heap_close(conrel, AccessShareLock);
4862 
4863  /*
4864  * Now, locate the trigger(s) implementing each of these constraints,
4865  * and make a list of their OIDs.
4866  */
4868 
4869  foreach(lc, conoidlist)
4870  {
4871  Oid conoid = lfirst_oid(lc);
4872  bool found;
4873  ScanKeyData skey;
4874  SysScanDesc tgscan;
4875  HeapTuple htup;
4876 
4877  found = false;
4878 
4879  ScanKeyInit(&skey,
4881  BTEqualStrategyNumber, F_OIDEQ,
4882  ObjectIdGetDatum(conoid));
4883 
4884  tgscan = systable_beginscan(tgrel, TriggerConstraintIndexId, true,
4885  NULL, 1, &skey);
4886 
4887  while (HeapTupleIsValid(htup = systable_getnext(tgscan)))
4888  {
4889  Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
4890 
4891  /*
4892  * Silently skip triggers that are marked as non-deferrable in
4893  * pg_trigger. This is not an error condition, since a
4894  * deferrable RI constraint may have some non-deferrable
4895  * actions.
4896  */
4897  if (pg_trigger->tgdeferrable)
4898  tgoidlist = lappend_oid(tgoidlist,
4899  HeapTupleGetOid(htup));
4900 
4901  found = true;
4902  }
4903 
4904  systable_endscan(tgscan);
4905 
4906  /* Safety check: a deferrable constraint should have triggers */
4907  if (!found)
4908  elog(ERROR, "no triggers found for constraint with OID %u",
4909  conoid);
4910  }
4911 
4912  heap_close(tgrel, AccessShareLock);
4913 
4914  /*
4915  * Now we can set the trigger states of individual triggers for this
4916  * xact.
4917  */
4918  foreach(lc, tgoidlist)
4919  {
4920  Oid tgoid = lfirst_oid(lc);
4922  bool found = false;
4923  int i;
4924 
4925  for (i = 0; i < state->numstates; i++)
4926  {
4927  if (state->trigstates[i].sct_tgoid == tgoid)
4928  {
4929  state->trigstates[i].sct_tgisdeferred = stmt->deferred;
4930  found = true;
4931  break;
4932  }
4933  }
4934  if (!found)
4935  {
4937  SetConstraintStateAddItem(state, tgoid, stmt->deferred);
4938  }
4939  }
4940  }
4941 
4942  /*
4943  * SQL99 requires that when a constraint is set to IMMEDIATE, any deferred
4944  * checks against that constraint must be made when the SET CONSTRAINTS
4945  * command is executed -- i.e. the effects of the SET CONSTRAINTS command
4946  * apply retroactively. We've updated the constraints state, so scan the
4947  * list of previously deferred events to fire any that have now become
4948  * immediate.
4949  *
4950  * Obviously, if this was SET ... DEFERRED then it can't have converted
4951  * any unfired events to immediate, so we need do nothing in that case.
4952  */
4953  if (!stmt->deferred)
4954  {
4956  bool snapshot_set = false;
4957 
4958  while (afterTriggerMarkEvents(events, NULL, true))
4959  {
4960  CommandId firing_id = afterTriggers.firing_counter++;
4961 
4962  /*
4963  * Make sure a snapshot has been established in case trigger
4964  * functions need one. Note that we avoid setting a snapshot if
4965  * we don't find at least one trigger that has to be fired now.
4966  * This is so that BEGIN; SET CONSTRAINTS ...; SET TRANSACTION
4967  * ISOLATION LEVEL SERIALIZABLE; ... works properly. (If we are
4968  * at the start of a transaction it's not possible for any trigger
4969  * events to be queued yet.)
4970  */
4971  if (!snapshot_set)
4972  {
4974  snapshot_set = true;
4975  }
4976 
4977  /*
4978  * We can delete fired events if we are at top transaction level,
4979  * but we'd better not if inside a subtransaction, since the
4980  * subtransaction could later get rolled back.
4981  */
4982  if (afterTriggerInvokeEvents(events, firing_id, NULL,
4983  !IsSubTransaction()))
4984  break; /* all fired */
4985  }
4986 
4987  if (snapshot_set)
4989  }
4990 }
#define NIL
Definition: pg_list.h:69
uint32 CommandId
Definition: c.h:408
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:2687
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define Anum_pg_trigger_tgconstraint
Definition: pg_trigger.h:87
SetConstraintTriggerData trigstates[FLEXIBLE_ARRAY_MEMBER]
Definition: trigger.c:3194
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
static SetConstraintState SetConstraintStateAddItem(SetConstraintState state, Oid tgoid, bool tgisdeferred)
Definition: trigger.c:4684
static bool afterTriggerInvokeEvents(AfterTriggerEventList *events, CommandId firing_id, EState *estate, bool delete_ok)
Definition: trigger.c:3967
void PopActiveSnapshot(void)
Definition: snapmgr.c:807
#define heap_close(r, l)
Definition: heapam.h:97
#define Anum_pg_constraint_conname
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:300
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:322
char * schemaname
Definition: primnodes.h:66
char * relname
Definition: primnodes.h:67
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
SetConstraintState * state_stack
Definition: trigger.c:3397
SetConstraintState state
Definition: trigger.c:3385
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2049
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:728
#define CStringGetDatum(X)
Definition: postgres.h:586
#define TriggerConstraintIndexId
Definition: indexing.h:240
#define ereport(elevel, rest)
Definition: elog.h:122
static SetConstraintState SetConstraintStateCreate(int numalloc)
Definition: trigger.c:4639
#define list_make1_oid(x1)
Definition: pg_list.h:145
Oid MyDatabaseId
Definition: globals.c:76
#define Anum_pg_constraint_connamespace
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
CommandId firing_counter
Definition: trigger.c:3384
#define ConstraintNameNspIndexId
Definition: indexing.h:124
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:760
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
Definition: regguts.h:298
#define TriggerRelationId
Definition: pg_trigger.h:34
FormData_pg_trigger * Form_pg_trigger
Definition: pg_trigger.h:72
bool IsSubTransaction(void)
Definition: xact.c:4374
int errmsg(const char *fmt,...)
Definition: elog.c:797
void list_free(List *list)
Definition: list.c:1133
int i
static bool afterTriggerMarkEvents(AfterTriggerEventList *events, AfterTriggerEventList *move_list, bool immediate_only)
Definition: trigger.c:3895
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
AfterTriggerEventList events
Definition: trigger.c:3386
#define ConstraintRelationId
Definition: pg_constraint.h:29
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
Definition: pg_list.h:45
List * fetch_search_path(bool includeImplicit)
Definition: namespace.c:4018
static AfterTriggersData afterTriggers
Definition: trigger.c:3404
char * catalogname
Definition: primnodes.h:65
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define lfirst_oid(lc)
Definition: pg_list.h:108
static SetConstraintState SetConstraintStateCopy(SetConstraintState state)
Definition: trigger.c:4664
TriggerDesc* CopyTriggerDesc ( TriggerDesc trigdesc)

Definition at line 1826 of file trigger.c.

References i, NULL, TriggerDesc::numtriggers, palloc(), pstrdup(), Trigger::tgargs, Trigger::tgattr, Trigger::tgname, Trigger::tgnargs, Trigger::tgnattr, Trigger::tgnewtable, Trigger::tgoldtable, Trigger::tgqual, and TriggerDesc::triggers.

Referenced by InitResultRelInfo(), and RelationBuildTriggers().

1827 {
1828  TriggerDesc *newdesc;
1829  Trigger *trigger;
1830  int i;
1831 
1832  if (trigdesc == NULL || trigdesc->numtriggers <= 0)
1833  return NULL;
1834 
1835  newdesc = (TriggerDesc *) palloc(sizeof(TriggerDesc));
1836  memcpy(newdesc, trigdesc, sizeof(TriggerDesc));
1837 
1838  trigger = (Trigger *) palloc(trigdesc->numtriggers * sizeof(Trigger));
1839  memcpy(trigger, trigdesc->triggers,
1840  trigdesc->numtriggers * sizeof(Trigger));
1841  newdesc->triggers = trigger;
1842 
1843  for (i = 0; i < trigdesc->numtriggers; i++)
1844  {
1845  trigger->tgname = pstrdup(trigger->tgname);
1846  if (trigger->tgnattr > 0)
1847  {
1848  int16 *newattr;
1849 
1850  newattr = (int16 *) palloc(trigger->tgnattr * sizeof(int16));
1851  memcpy(newattr, trigger->tgattr,
1852  trigger->tgnattr * sizeof(int16));
1853  trigger->tgattr = newattr;
1854  }
1855  if (trigger->tgnargs > 0)
1856  {
1857  char **newargs;
1858  int16 j;
1859 
1860  newargs = (char **) palloc(trigger->tgnargs * sizeof(char *));
1861  for (j = 0; j < trigger->tgnargs; j++)
1862  newargs[j] = pstrdup(trigger->tgargs[j]);
1863  trigger->tgargs = newargs;
1864  }
1865  if (trigger->tgqual)
1866  trigger->tgqual = pstrdup(trigger->tgqual);
1867  if (trigger->tgoldtable)
1868  trigger->tgoldtable = pstrdup(trigger->tgoldtable);
1869  if (trigger->tgnewtable)
1870  trigger->tgnewtable = pstrdup(trigger->tgnewtable);
1871  trigger++;
1872  }
1873 
1874  return newdesc;
1875 }
signed short int16
Definition: c.h:252
char * pstrdup(const char *in)
Definition: mcxt.c:1165
char * tgqual
Definition: reltrigger.h:41
char * tgname
Definition: reltrigger.h:27
Trigger * triggers
Definition: reltrigger.h:48
int numtriggers
Definition: reltrigger.h:49
char ** tgargs
Definition: reltrigger.h:40
int16 * tgattr
Definition: reltrigger.h:39
char * tgnewtable
Definition: reltrigger.h:43
#define NULL
Definition: c.h:226
int16 tgnattr
Definition: reltrigger.h:38
void * palloc(Size size)
Definition: mcxt.c:891
int i
int16 tgnargs
Definition: reltrigger.h:37
char * tgoldtable
Definition: reltrigger.h:42
ObjectAddress CreateTrigger ( CreateTrigStmt stmt,
const char *  queryString,
Oid  relOid,
Oid  refRelOid,
Oid  constraintOid,
Oid  indexOid,
bool  isInternal 
)

Definition at line 138 of file trigger.c.

References AccessShareLock, ACL_EXECUTE, ACL_KIND_CLASS, ACL_KIND_PROC, ACL_TRIGGER, aclcheck_error(), ACLCHECK_OK, addRangeTableEntryForRelation(), addRTEtoQuery(), allowSystemTableMods, Anum_pg_trigger_tgargs, Anum_pg_trigger_tgattr, Anum_pg_trigger_tgconstraint, Anum_pg_trigger_tgconstrindid, Anum_pg_trigger_tgconstrrelid, Anum_pg_trigger_tgdeferrable, Anum_pg_trigger_tgenabled, Anum_pg_trigger_tgfoid, Anum_pg_trigger_tginitdeferred, Anum_pg_trigger_tgisinternal, Anum_pg_trigger_tgname, Anum_pg_trigger_tgnargs, Anum_pg_trigger_tgnewtable, Anum_pg_trigger_tgoldtable, Anum_pg_trigger_tgqual, Anum_pg_trigger_tgrelid, Anum_pg_trigger_tgtype, generate_unaccent_rules::args, CreateTrigStmt::args, Assert, assign_expr_collations(), attnameAttNum(), BoolGetDatum, BTEqualStrategyNumber, buildint2vector(), byteain(), castNode, CatalogTupleInsert(), CatalogTupleUpdate(), CharGetDatum, ObjectAddress::classId, CreateTrigStmt::columns, CONSTRAINT_TRIGGER, ConstraintRelationId, CreateTrigStmt::constrrel, ConvertTriggerToFK(), copyObject(), CreateConstraintEntry(), CStringGetDatum, CStringGetTextDatum, DatumGetPointer, CreateTrigStmt::deferrable, DEPENDENCY_AUTO, DEPENDENCY_INTERNAL, DEPENDENCY_NORMAL, DirectFunctionCall1, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errdetail(), errhint(), errmsg(), ERROR, CreateTrigStmt::events, EXPR_KIND_TRIGGER_WHEN, free_parsestate(), CreateTrigStmt::funcname, get_func_rettype(), get_rel_name(), GetNewOid(), GETSTRUCT, GetUserId(), heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), heap_openrv(), HeapTupleIsValid, HeapTupleSetOid, i, CreateTrigStmt::initdeferred, Int16GetDatum, InvalidAttrNumber, InvalidObjectAddress, InvalidOid, InvokeObjectPostCreateHookArg, CreateTrigStmt::isconstraint, TriggerTransition::isNew, IsSystemRelation(), TriggerTransition::isTable, lfirst, list_length(), Var::location, LockRelationOid(), LookupFuncName(), make_parsestate(), makeAlias(), name, TriggerTransition::name, NAMEDATALEN, namein(), NameListToString(), namestrcmp(), Natts_pg_trigger, NIL, nodeToString(), NoLock, NULL, ObjectAddress::objectId, ObjectIdGetDatum, ObjectAddress::objectSubId, OidIsValid, OPAQUEOID, ParseState::p_rtable, ParseState::p_sourcetext, palloc(), parser_errposition(), pfree(), pg_class_aclcheck(), pg_proc_aclcheck(), PointerGetDatum, ProcedureRelationId, PRS2_NEW_VARNO, PRS2_OLD_VARNO, pull_var_clause(), RangeVarGetRelid, RelationData::rd_att, RelationData::rd_rel, recordDependencyOn(), recordDependencyOnExpr(), CreateTrigStmt::relation, RelationGetNamespace, RelationGetRelationName, RelationGetRelid, RelationRelationId, RELKIND_FOREIGN_TABLE, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, RELKIND_VIEW, RELOID, RI_FKey_trigger_type(), RI_TRIGGER_NONE, CreateTrigStmt::row, RowExclusiveLock, ScanKeyInit(), SearchSysCacheCopy1, SetFunctionReturnType(), ShareRowExclusiveLock, snprintf(), strVal, systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, CreateTrigStmt::timing, transformWhereClause(), CreateTrigStmt::transitionRels, TRIGGER_CLEAR_TYPE, TRIGGER_FIRES_ON_ORIGIN, TRIGGER_FOR_BEFORE, TRIGGER_FOR_DELETE, TRIGGER_FOR_INSERT, TRIGGER_FOR_INSTEAD, TRIGGER_FOR_ROW, TRIGGER_FOR_TRUNCATE, TRIGGER_FOR_UPDATE, TRIGGER_SETT_ROW, TRIGGER_TYPE_AFTER, TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSTEAD, TRIGGEROID, TriggerRelationId, TriggerRelidNameIndexId, CreateTrigStmt::trigname, values, Var::varattno, Var::varno, WARNING, and CreateTrigStmt::whenClause.

Referenced by CreateFKCheckTrigger(), createForeignKeyTriggers(), index_constraint_create(), and ProcessUtilitySlow().

141 {
142  int16 tgtype;
143  int ncolumns;
144  int16 *columns;
145  int2vector *tgattr;
146  Node *whenClause;
147  List *whenRtable;
148  char *qual;
150  bool nulls[Natts_pg_trigger];
151  Relation rel;
152  AclResult aclresult;
153  Relation tgrel;
154  SysScanDesc tgscan;
155  ScanKeyData key;
156  Relation pgrel;
157  HeapTuple tuple;
158  Oid fargtypes[1]; /* dummy */
159  Oid funcoid;
160  Oid funcrettype;
161  Oid trigoid;
162  char internaltrigname[NAMEDATALEN];
163  char *trigname;
164  Oid constrrelid = InvalidOid;
165  ObjectAddress myself,
166  referenced;
167  char *oldtablename = NULL;
168  char *newtablename = NULL;
169 
170  if (OidIsValid(relOid))
171  rel = heap_open(relOid, ShareRowExclusiveLock);
172  else
174 
175  /*
176  * Triggers must be on tables or views, and there are additional
177  * relation-type-specific restrictions.
178  */
179  if (rel->rd_rel->relkind == RELKIND_RELATION ||
180  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
181  {
182  /* Tables can't have INSTEAD OF triggers */
183  if (stmt->timing != TRIGGER_TYPE_BEFORE &&
184  stmt->timing != TRIGGER_TYPE_AFTER)
185  ereport(ERROR,
186  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
187  errmsg("\"%s\" is a table",
189  errdetail("Tables cannot have INSTEAD OF triggers.")));
190  /* Disallow ROW triggers on partitioned tables */
191  if (stmt->row && rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
192  ereport(ERROR,
193  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
194  errmsg("\"%s\" is a partitioned table",
196  errdetail("Partitioned tables cannot have ROW triggers.")));
197  }
198  else if (rel->rd_rel->relkind == RELKIND_VIEW)
199  {
200  /*
201  * Views can have INSTEAD OF triggers (which we check below are
202  * row-level), or statement-level BEFORE/AFTER triggers.
203  */
204  if (stmt->timing != TRIGGER_TYPE_INSTEAD && stmt->row)
205  ereport(ERROR,
206  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
207  errmsg("\"%s\" is a view",
209  errdetail("Views cannot have row-level BEFORE or AFTER triggers.")));
210  /* Disallow TRUNCATE triggers on VIEWs */
211  if (TRIGGER_FOR_TRUNCATE(stmt->events))
212  ereport(ERROR,
213  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
214  errmsg("\"%s\" is a view",
216  errdetail("Views cannot have TRUNCATE triggers.")));
217  }
218  else if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
219  {
220  if (stmt->timing != TRIGGER_TYPE_BEFORE &&
221  stmt->timing != TRIGGER_TYPE_AFTER)
222  ereport(ERROR,
223  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
224  errmsg("\"%s\" is a foreign table",
226  errdetail("Foreign tables cannot have INSTEAD OF triggers.")));
227 
228  if (TRIGGER_FOR_TRUNCATE(stmt->events))
229  ereport(ERROR,
230  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
231  errmsg("\"%s\" is a foreign table",
233  errdetail("Foreign tables cannot have TRUNCATE triggers.")));
234 
235  if (stmt->isconstraint)
236  ereport(ERROR,
237  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
238  errmsg("\"%s\" is a foreign table",
240  errdetail("Foreign tables cannot have constraint triggers.")));
241  }
242  else
243  ereport(ERROR,
244  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
245  errmsg("\"%s\" is not a table or view",
246  RelationGetRelationName(rel))));
247 
249  ereport(ERROR,
250  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
251  errmsg("permission denied: \"%s\" is a system catalog",
252  RelationGetRelationName(rel))));
253 
254  if (stmt->isconstraint)
255  {
256  /*
257  * We must take a lock on the target relation to protect against
258  * concurrent drop. It's not clear that AccessShareLock is strong
259  * enough, but we certainly need at least that much... otherwise, we
260  * might end up creating a pg_constraint entry referencing a
261  * nonexistent table.
262  */
263  if (OidIsValid(refRelOid))
264  {
265  LockRelationOid(refRelOid, AccessShareLock);
266  constrrelid = refRelOid;
267  }
268  else if (stmt->constrrel != NULL)
269  constrrelid = RangeVarGetRelid(stmt->constrrel, AccessShareLock,
270  false);
271  }
272 
273  /* permission checks */
274  if (!isInternal)
275  {
276  aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
277  ACL_TRIGGER);
278  if (aclresult != ACLCHECK_OK)
279  aclcheck_error(aclresult, ACL_KIND_CLASS,
281 
282  if (OidIsValid(constrrelid))
283  {
284  aclresult = pg_class_aclcheck(constrrelid, GetUserId(),
285  ACL_TRIGGER);
286  if (aclresult != ACLCHECK_OK)
287  aclcheck_error(aclresult, ACL_KIND_CLASS,
288  get_rel_name(constrrelid));
289  }
290  }
291 
292  /* Compute tgtype */
293  TRIGGER_CLEAR_TYPE(tgtype);
294  if (stmt->row)
295  TRIGGER_SETT_ROW(tgtype);
296  tgtype |= stmt->timing;
297  tgtype |= stmt->events;
298 
299  /* Disallow ROW-level TRUNCATE triggers */
300  if (TRIGGER_FOR_ROW(tgtype) && TRIGGER_FOR_TRUNCATE(tgtype))
301  ereport(ERROR,
302  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
303  errmsg("TRUNCATE FOR EACH ROW triggers are not supported")));
304 
305  /* INSTEAD triggers must be row-level, and can't have WHEN or columns */
306  if (TRIGGER_FOR_INSTEAD(tgtype))
307  {
308  if (!TRIGGER_FOR_ROW(tgtype))
309  ereport(ERROR,
310  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
311  errmsg("INSTEAD OF triggers must be FOR EACH ROW")));
312  if (stmt->whenClause)
313  ereport(ERROR,
314  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
315  errmsg("INSTEAD OF triggers cannot have WHEN conditions")));
316  if (stmt->columns != NIL)
317  ereport(ERROR,
318  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
319  errmsg("INSTEAD OF triggers cannot have column lists")));
320  }
321 
322  /*
323  * We don't yet support naming ROW transition variables, but the parser
324  * recognizes the syntax so we can give a nicer message here.
325  *
326  * Per standard, REFERENCING TABLE names are only allowed on AFTER
327  * triggers. Per standard, REFERENCING ROW names are not allowed with FOR
328  * EACH STATEMENT. Per standard, each OLD/NEW, ROW/TABLE permutation is
329  * only allowed once. Per standard, OLD may not be specified when
330  * creating a trigger only for INSERT, and NEW may not be specified when
331  * creating a trigger only for DELETE.
332  *
333  * Notice that the standard allows an AFTER ... FOR EACH ROW trigger to
334  * reference both ROW and TABLE transition data.
335  */
336  if (stmt->transitionRels != NIL)
337  {
338  List *varList = stmt->transitionRels;
339  ListCell *lc;
340 
341  foreach(lc, varList)
342  {
344 
345  if (!(tt->isTable))
346  ereport(ERROR,
347  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
348  errmsg("ROW variable naming in the REFERENCING clause is not supported"),
349  errhint("Use OLD TABLE or NEW TABLE for naming transition tables.")));
350 
351  /*
352  * Because of the above test, we omit further ROW-related testing
353  * below. If we later allow naming OLD and NEW ROW variables,
354  * adjustments will be needed below.
355  */
356 
357  if (stmt->timing != TRIGGER_TYPE_AFTER)
358  ereport(ERROR,
359  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
360  errmsg("transition table name can only be specified for an AFTER trigger")));
361 
362  if (tt->isNew)
363  {
364  if (!(TRIGGER_FOR_INSERT(tgtype) ||
365  TRIGGER_FOR_UPDATE(tgtype)))
366  ereport(ERROR,
367  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
368  errmsg("NEW TABLE can only be specified for an INSERT or UPDATE trigger")));
369 
370  if (newtablename != NULL)
371  ereport(ERROR,
372  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
373  errmsg("NEW TABLE cannot be specified multiple times")));
374 
375  newtablename = tt->name;
376  }
377  else
378  {
379  if (!(TRIGGER_FOR_DELETE(tgtype) ||
380  TRIGGER_FOR_UPDATE(tgtype)))
381  ereport(ERROR,
382  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
383  errmsg("OLD TABLE can only be specified for a DELETE or UPDATE trigger")));
384 
385  if (oldtablename != NULL)
386  ereport(ERROR,
387  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
388  errmsg("OLD TABLE cannot be specified multiple times")));
389 
390  oldtablename = tt->name;
391  }
392  }
393 
394  if (newtablename != NULL && oldtablename != NULL &&
395  strcmp(newtablename, oldtablename) == 0)
396  ereport(ERROR,
397  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
398  errmsg("OLD TABLE name and NEW TABLE name cannot be the same")));
399  }
400 
401  /*
402  * Parse the WHEN clause, if any
403  */
404  if (stmt->whenClause)
405  {
406  ParseState *pstate;
407  RangeTblEntry *rte;
408  List *varList;
409  ListCell *lc;
410 
411  /* Set up a pstate to parse with */
412  pstate = make_parsestate(NULL);
413  pstate->p_sourcetext = queryString;
414 
415  /*
416  * Set up RTEs for OLD and NEW references.
417  *
418  * 'OLD' must always have varno equal to 1 and 'NEW' equal to 2.
419  */
420  rte = addRangeTableEntryForRelation(pstate, rel,
421  makeAlias("old", NIL),
422  false, false);
423  addRTEtoQuery(pstate, rte, false, true, true);
424  rte = addRangeTableEntryForRelation(pstate, rel,
425  makeAlias("new", NIL),
426  false, false);
427  addRTEtoQuery(pstate, rte, false, true, true);
428 
429  /* Transform expression. Copy to be sure we don't modify original */
430  whenClause = transformWhereClause(pstate,
431  copyObject(stmt->whenClause),
433  "WHEN");
434  /* we have to fix its collations too */
435  assign_expr_collations(pstate, whenClause);
436 
437  /*
438  * Check for disallowed references to OLD/NEW.
439  *
440  * NB: pull_var_clause is okay here only because we don't allow
441  * subselects in WHEN clauses; it would fail to examine the contents
442  * of subselects.
443  */
444  varList = pull_var_clause(whenClause, 0);
445  foreach(lc, varList)
446  {
447  Var *var = (Var *) lfirst(lc);
448 
449  switch (var->varno)
450  {
451  case PRS2_OLD_VARNO:
452  if (!TRIGGER_FOR_ROW(tgtype))
453  ereport(ERROR,
454  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
455  errmsg("statement trigger's WHEN condition cannot reference column values"),
456  parser_errposition(pstate, var->location)));
457  if (TRIGGER_FOR_INSERT(tgtype))
458  ereport(ERROR,
459  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
460  errmsg("INSERT trigger's WHEN condition cannot reference OLD values"),
461  parser_errposition(pstate, var->location)));
462  /* system columns are okay here */
463  break;
464  case PRS2_NEW_VARNO:
465  if (!TRIGGER_FOR_ROW(tgtype))
466  ereport(ERROR,
467  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
468  errmsg("statement trigger's WHEN condition cannot reference column values"),
469  parser_errposition(pstate, var->location)));
470  if (TRIGGER_FOR_DELETE(tgtype))
471  ereport(ERROR,
472  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
473  errmsg("DELETE trigger's WHEN condition cannot reference NEW values"),
474  parser_errposition(pstate, var->location)));
475  if (var->varattno < 0 && TRIGGER_FOR_BEFORE(tgtype))
476  ereport(ERROR,
477  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
478  errmsg("BEFORE trigger's WHEN condition cannot reference NEW system columns"),
479  parser_errposition(pstate, var->location)));
480  break;
481  default:
482  /* can't happen without add_missing_from, so just elog */
483  elog(ERROR, "trigger WHEN condition cannot contain references to other relations");
484  break;
485  }
486  }
487 
488  /* we'll need the rtable for recordDependencyOnExpr */
489  whenRtable = pstate->p_rtable;
490 
491  qual = nodeToString(whenClause);
492 
493  free_parsestate(pstate);
494  }
495  else
496  {
497  whenClause = NULL;
498  whenRtable = NIL;
499  qual = NULL;
500  }
501 
502  /*
503  * Find and validate the trigger function.
504  */
505  funcoid = LookupFuncName(stmt->funcname, 0, fargtypes, false);
506  if (!isInternal)
507  {
508  aclresult = pg_proc_aclcheck(funcoid, GetUserId(), ACL_EXECUTE);
509  if (aclresult != ACLCHECK_OK)
510  aclcheck_error(aclresult, ACL_KIND_PROC,
511  NameListToString(stmt->funcname));
512  }
513  funcrettype = get_func_rettype(funcoid);
514  if (funcrettype != TRIGGEROID)
515  {
516  /*
517  * We allow OPAQUE just so we can load old dump files. When we see a
518  * trigger function declared OPAQUE, change it to TRIGGER.
519  */
520  if (funcrettype == OPAQUEOID)
521  {
523  (errmsg("changing return type of function %s from %s to %s",
524  NameListToString(stmt->funcname),
525  "opaque", "trigger")));
527  }
528  else
529  ereport(ERROR,
530  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
531  errmsg("function %s must return type %s",
532  NameListToString(stmt->funcname), "trigger")));
533  }
534 
535  /*
536  * If the command is a user-entered CREATE CONSTRAINT TRIGGER command that
537  * references one of the built-in RI_FKey trigger functions, assume it is
538  * from a dump of a pre-7.3 foreign key constraint, and take steps to
539  * convert this legacy representation into a regular foreign key
540  * constraint. Ugly, but necessary for loading old dump files.
541  */
542  if (stmt->isconstraint && !isInternal &&
543  list_length(stmt->args) >= 6 &&
544  (list_length(stmt->args) % 2) == 0 &&
546  {
547  /* Keep lock on target rel until end of xact */
548  heap_close(rel, NoLock);
549 
550  ConvertTriggerToFK(stmt, funcoid);
551 
552  return InvalidObjectAddress;
553  }
554 
555  /*
556  * If it's a user-entered CREATE CONSTRAINT TRIGGER command, make a
557  * corresponding pg_constraint entry.
558  */
559  if (stmt->isconstraint && !OidIsValid(constraintOid))
560  {
561  /* Internal callers should have made their own constraints */
562  Assert(!isInternal);
563  constraintOid = CreateConstraintEntry(stmt->trigname,
566  stmt->deferrable,
567  stmt->initdeferred,
568  true,
569  RelationGetRelid(rel),
570  NULL, /* no conkey */
571  0,
572  InvalidOid, /* no domain */
573  InvalidOid, /* no index */
574  InvalidOid, /* no foreign key */
575  NULL,
576  NULL,
577  NULL,
578  NULL,
579  0,
580  ' ',
581  ' ',
582  ' ',
583  NULL, /* no exclusion */
584  NULL, /* no check constraint */
585  NULL,
586  NULL,
587  true, /* islocal */
588  0, /* inhcount */
589  true, /* isnoinherit */
590  isInternal); /* is_internal */
591  }
592 
593  /*
594  * Generate the trigger's OID now, so that we can use it in the name if
595  * needed.
596  */
598 
599  trigoid = GetNewOid(tgrel);
600 
601  /*
602  * If trigger is internally generated, modify the provided trigger name to
603  * ensure uniqueness by appending the trigger OID. (Callers will usually
604  * supply a simple constant trigger name in these cases.)
605  */
606  if (isInternal)
607  {
608  snprintf(internaltrigname, sizeof(internaltrigname),
609  "%s_%u", stmt->trigname, trigoid);
610  trigname = internaltrigname;
611  }
612  else
613  {
614  /* user-defined trigger; use the specified trigger name as-is */
615  trigname = stmt->trigname;
616  }
617 
618  /*
619  * Scan pg_trigger for existing triggers on relation. We do this only to
620  * give a nice error message if there's already a trigger of the same
621  * name. (The unique index on tgrelid/tgname would complain anyway.) We
622  * can skip this for internally generated triggers, since the name
623  * modification above should be sufficient.
624  *
625  * NOTE that this is cool only because we have ShareRowExclusiveLock on
626  * the relation, so the trigger set won't be changing underneath us.
627  */
628  if (!isInternal)
629  {
630  ScanKeyInit(&key,
632  BTEqualStrategyNumber, F_OIDEQ,
634  tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
635  NULL, 1, &key);
636  while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
637  {
638  Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
639 
640  if (namestrcmp(&(pg_trigger->tgname), trigname) == 0)
641  ereport(ERROR,
643  errmsg("trigger \"%s\" for relation \"%s\" already exists",
644  trigname, RelationGetRelationName(rel))));
645  }
646  systable_endscan(tgscan);
647  }
648 
649  /*
650  * Build the new pg_trigger tuple.
651  */
652  memset(nulls, false, sizeof(nulls));
653 
656  CStringGetDatum(trigname));
657  values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid);
658  values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype);
660  values[Anum_pg_trigger_tgisinternal - 1] = BoolGetDatum(isInternal);
661  values[Anum_pg_trigger_tgconstrrelid - 1] = ObjectIdGetDatum(constrrelid);
662  values[Anum_pg_trigger_tgconstrindid - 1] = ObjectIdGetDatum(indexOid);
663  values[Anum_pg_trigger_tgconstraint - 1] = ObjectIdGetDatum(constraintOid);
666 
667  if (stmt->args)
668  {
669  ListCell *le;
670  char *args;
671  int16 nargs = list_length(stmt->args);
672  int len = 0;
673 
674  foreach(le, stmt->args)
675  {
676  char *ar = strVal(lfirst(le));
677 
678  len += strlen(ar) + 4;
679  for (; *ar; ar++)
680  {
681  if (*ar == '\\')
682  len++;
683  }
684  }
685  args = (char *) palloc(len + 1);
686  args[0] = '\0';
687  foreach(le, stmt->args)
688  {
689  char *s = strVal(lfirst(le));
690  char *d = args + strlen(args);
691 
692  while (*s)
693  {
694  if (*s == '\\')
695  *d++ = '\\';
696  *d++ = *s++;
697  }
698  strcpy(d, "\\000");
699  }
700  values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(nargs);
702  CStringGetDatum(args));
703  }
704  else
705  {
706  values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(0);
708  CStringGetDatum(""));
709  }
710 
711  /* build column number array if it's a column-specific trigger */
712  ncolumns = list_length(stmt->columns);
713  if (ncolumns == 0)
714  columns = NULL;
715  else
716  {
717  ListCell *cell;
718  int i = 0;
719 
720  columns = (int16 *) palloc(ncolumns * sizeof(int16));
721  foreach(cell, stmt->columns)
722  {
723  char *name = strVal(lfirst(cell));
724  int16 attnum;
725  int j;
726 
727  /* Lookup column name. System columns are not allowed */
728  attnum = attnameAttNum(rel, name, false);
729  if (attnum == InvalidAttrNumber)
730  ereport(ERROR,
731  (errcode(ERRCODE_UNDEFINED_COLUMN),
732  errmsg("column \"%s\" of relation \"%s\" does not exist",
733  name, RelationGetRelationName(rel))));
734 
735  /* Check for duplicates */
736  for (j = i - 1; j >= 0; j--)
737  {
738  if (columns[j] == attnum)
739  ereport(ERROR,
740  (errcode(ERRCODE_DUPLICATE_COLUMN),
741  errmsg("column \"%s\" specified more than once",
742  name)));
743  }
744 
745  columns[i++] = attnum;
746  }
747  }
748  tgattr = buildint2vector(columns, ncolumns);
749  values[Anum_pg_trigger_tgattr - 1] = PointerGetDatum(tgattr);
750 
751  /* set tgqual if trigger has WHEN clause */
752  if (qual)
753  values[Anum_pg_trigger_tgqual - 1] = CStringGetTextDatum(qual);
754  else
755  nulls[Anum_pg_trigger_tgqual - 1] = true;
756 
757  if (oldtablename)
759  CStringGetDatum(oldtablename));
760  else
761  nulls[Anum_pg_trigger_tgoldtable - 1] = true;
762  if (newtablename)
764  CStringGetDatum(newtablename));
765  else
766  nulls[Anum_pg_trigger_tgnewtable - 1] = true;
767 
768  tuple = heap_form_tuple(tgrel->rd_att, values, nulls);
769 
770  /* force tuple to have the desired OID */
771  HeapTupleSetOid(tuple, trigoid);
772 
773  /*
774  * Insert tuple into pg_trigger.
775  */
776  CatalogTupleInsert(tgrel, tuple);
777 
778  heap_freetuple(tuple);
780 
784  if (oldtablename)
786  if (newtablename)
788 
789  /*
790  * Update relation's pg_class entry. Crucial side-effect: other backends
791  * (and this one too!) are sent SI message to make them rebuild relcache
792  * entries.
793  */
795  tuple = SearchSysCacheCopy1(RELOID,
797  if (!HeapTupleIsValid(tuple))
798  elog(ERROR, "cache lookup failed for relation %u",
799  RelationGetRelid(rel));
800 
801  ((Form_pg_class) GETSTRUCT(tuple))->relhastriggers = true;
802 
803  CatalogTupleUpdate(pgrel, &tuple->t_self, tuple);
804 
805  heap_freetuple(tuple);
807 
808  /*
809  * We used to try to update the rel's relcache entry here, but that's
810  * fairly pointless since it will happen as a byproduct of the upcoming
811  * CommandCounterIncrement...
812  */
813 
814  /*
815  * Record dependencies for trigger. Always place a normal dependency on
816  * the function.
817  */
818  myself.classId = TriggerRelationId;
819  myself.objectId = trigoid;
820  myself.objectSubId = 0;
821 
822  referenced.classId = ProcedureRelationId;
823  referenced.objectId = funcoid;
824  referenced.objectSubId = 0;
825  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
826 
827  if (isInternal && OidIsValid(constraintOid))
828  {
829  /*
830  * Internally-generated trigger for a constraint, so make it an
831  * internal dependency of the constraint. We can skip depending on
832  * the relation(s), as there'll be an indirect dependency via the
833  * constraint.
834  */
835  referenced.classId = ConstraintRelationId;
836  referenced.objectId = constraintOid;
837  referenced.objectSubId = 0;
838  recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
839  }
840  else
841  {
842  /*
843  * User CREATE TRIGGER, so place dependencies. We make trigger be
844  * auto-dropped if its relation is dropped or if the FK relation is
845  * dropped. (Auto drop is compatible with our pre-7.3 behavior.)
846  */
847  referenced.classId = RelationRelationId;
848  referenced.objectId = RelationGetRelid(rel);
849  referenced.objectSubId = 0;
850  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
851  if (OidIsValid(constrrelid))
852  {
853  referenced.classId = RelationRelationId;
854  referenced.objectId = constrrelid;
855  referenced.objectSubId = 0;
856  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
857  }
858  /* Not possible to have an index dependency in this case */
859  Assert(!OidIsValid(indexOid));
860 
861  /*
862  * If it's a user-specified constraint trigger, make the constraint
863  * internally dependent on the trigger instead of vice versa.
864  */
865  if (OidIsValid(constraintOid))
866  {
867  referenced.classId = ConstraintRelationId;
868  referenced.objectId = constraintOid;
869  referenced.objectSubId = 0;
870  recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
871  }
872  }
873 
874  /* If column-specific trigger, add normal dependencies on columns */
875  if (columns != NULL)
876  {
877  int i;
878 
879  referenced.classId = RelationRelationId;
880  referenced.objectId = RelationGetRelid(rel);
881  for (i = 0; i < ncolumns; i++)
882  {
883  referenced.objectSubId = columns[i];
884  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
885  }
886  }
887 
888  /*
889  * If it has a WHEN clause, add dependencies on objects mentioned in the
890  * expression (eg, functions, as well as any columns used).
891  */
892  if (whenClause != NULL)
893  recordDependencyOnExpr(&myself, whenClause, whenRtable,
895 
896  /* Post creation hook for new trigger */
898  isInternal);
899 
900  /* Keep lock on target rel until end of xact */
901  heap_close(rel, NoLock);
902 
903  return myself;
904 }
signed short int16
Definition: c.h:252
#define NIL
Definition: pg_list.h:69
#define Anum_pg_trigger_tgdeferrable
Definition: pg_trigger.h:88
#define TRIGGER_FOR_DELETE(type)
Definition: pg_trigger.h:135
int RI_FKey_trigger_type(Oid tgfoid)
Definition: ri_triggers.c:3704
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:46
int errhint(const char *fmt,...)
Definition: elog.c:987
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
bool IsSystemRelation(Relation relation)
Definition: catalog.c:62
Oid GetUserId(void)
Definition: miscinit.c:283
#define castNode(_type_, nodeptr)
Definition: nodes.h:577
#define PointerGetDatum(X)
Definition: postgres.h:564
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:53
#define Anum_pg_trigger_tgconstraint
Definition: pg_trigger.h:87
#define ProcedureRelationId
Definition: pg_proc.h:33
Node * whenClause
Definition: parsenodes.h:2251
#define RelationRelationId
Definition: pg_class.h:29
int2vector * buildint2vector(const int16 *int2s, int n)
Definition: int.c:112
#define Anum_pg_trigger_tgqual
Definition: pg_trigger.h:93
#define TRIGGER_CLEAR_TYPE(type)
Definition: pg_trigger.h:118
#define Int16GetDatum(X)
Definition: postgres.h:459
#define Anum_pg_trigger_tgtype
Definition: pg_trigger.h:82
#define AccessShareLock
Definition: lockdefs.h:36
#define Anum_pg_trigger_tgnargs
Definition: pg_trigger.h:90
Definition: nodes.h:508
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
int namestrcmp(Name name, const char *str)
Definition: name.c:248
#define TRIGGER_FOR_UPDATE(type)
Definition: pg_trigger.h:136
AttrNumber varattno
Definition: primnodes.h:146
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
#define heap_close(r, l)
Definition: heapam.h:97
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:555
Form_pg_class rd_rel
Definition: rel.h:113
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:141
#define Anum_pg_trigger_tgisinternal
Definition: pg_trigger.h:84
#define OidIsValid(objectId)
Definition: c.h:534
#define TRIGGER_FIRES_ON_ORIGIN
Definition: trigger.h:109
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:322
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1427
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
void * copyObject(const void *from)
Definition: copyfuncs.c:4475
#define TriggerRelidNameIndexId
Definition: indexing.h:242
#define HeapTupleSetOid(tuple, oid)
Definition: htup_details.h:698
#define NAMEDATALEN
void assign_expr_collations(ParseState *pstate, Node *expr)
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:384
RangeVar * constrrel
Definition: parsenodes.h:2258
#define TRIGGER_TYPE_INSTEAD
Definition: pg_trigger.h:104
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define TRIGGER_FOR_ROW(type)
Definition: pg_trigger.h:130
void pfree(void *pointer)
Definition: mcxt.c:992
#define OPAQUEOID
Definition: pg_type.h:688
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
#define TRIGGER_TYPE_AFTER
Definition: pg_trigger.h:112
#define TRIGGEROID
Definition: pg_type.h:680
ItemPointerData t_self
Definition: htup.h:65
Datum byteain(PG_FUNCTION_ARGS)
Definition: varlena.c:257
#define ACL_TRIGGER
Definition: parsenodes.h:71
int location
Definition: primnodes.h:156
#define NoLock
Definition: lockdefs.h:34
#define TRIGGER_SETT_ROW(type)
Definition: pg_trigger.h:120
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3378
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define CStringGetDatum(X)
Definition: postgres.h:586
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1332
#define RelationGetRelationName(relation)
Definition: rel.h:433
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:166
const char * p_sourcetext
Definition: parse_node.h:167
#define TRIGGER_FOR_BEFORE(type)
Definition: pg_trigger.h:131
static void ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
Definition: trigger.c:934
List * transitionRels
Definition: parsenodes.h:2254
#define ereport(elevel, rest)
Definition: elog.h:122
void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
#define PRS2_OLD_VARNO
Definition: primnodes.h:138
#define Anum_pg_trigger_tgrelid
Definition: pg_trigger.h:79
#define WARNING
Definition: elog.h:40
Index varno
Definition: primnodes.h:144
char * NameListToString(List *names)
Definition: namespace.c:2897
#define Anum_pg_trigger_tgnewtable
Definition: pg_trigger.h:95
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
Definition: c.h:463
#define Anum_pg_trigger_tgconstrindid
Definition: pg_trigger.h:86
AclResult
Definition: acl.h:170
uintptr_t Datum
Definition: postgres.h:374
#define Anum_pg_trigger_tgenabled
Definition: pg_trigger.h:83
Oid GetNewOid(Relation relation)
Definition: catalog.c:288
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
void SetFunctionReturnType(Oid funcOid, Oid newRetType)
#define TRIGGER_FOR_TRUNCATE(type)
Definition: pg_trigger.h:137
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
Definition: objectaccess.h:147
TupleDesc rd_att
Definition: rel.h:114
#define BoolGetDatum(X)
Definition: postgres.h:410
Relation heap_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: heapam.c:1315
bool allowSystemTableMods
Definition: globals.c:111
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
int attnameAttNum(Relation rd, const char *attname, bool sysColOK)
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
#define Anum_pg_trigger_tgargs
Definition: pg_trigger.h:92
#define ShareRowExclusiveLock
Definition: lockdefs.h:42
#define Anum_pg_trigger_tgconstrrelid
Definition: pg_trigger.h:85
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
#define Anum_pg_trigger_tgname
Definition: pg_trigger.h:80
#define TriggerRelationId
Definition: pg_trigger.h:34
#define TRIGGER_FOR_INSERT(type)
Definition: pg_trigger.h:134
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
static int list_length(const List *l)
Definition: pg_list.h:89
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:109
FormData_pg_trigger * Form_pg_trigger
Definition: pg_trigger.h:72
RangeTblEntry * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, Alias *alias, bool inh, bool inFromCl)
const char * name
Definition: encode.c:521
#define InvalidAttrNumber
Definition: attnum.h:23
#define CharGetDatum(X)
Definition: postgres.h:424
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4397
#define DatumGetPointer(X)
Definition: postgres.h:557
#define TRIGGER_TYPE_BEFORE
Definition: pg_trigger.h:99
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:1908
#define Anum_pg_trigger_tgoldtable
Definition: pg_trigger.h:94
static Datum values[MAXATTR]
Definition: bootstrap.c:162
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:158
const ObjectAddress InvalidObjectAddress
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ACL_EXECUTE
Definition: parsenodes.h:72
#define RELKIND_VIEW
Definition: pg_class.h:164
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4421
int i
RangeVar * relation
Definition: parsenodes.h:2242
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define CStringGetTextDatum(s)
Definition: builtins.h:90
char * nodeToString(const void *obj)
Definition: outfuncs.c:3981
#define ConstraintRelationId
Definition: pg_constraint.h:29
#define elog
Definition: elog.h:219
#define CONSTRAINT_TRIGGER
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:75
#define RELKIND_RELATION
Definition: pg_class.h:160
#define RI_TRIGGER_NONE
Definition: trigger.h:211
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:34
Definition: pg_list.h:45
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1694
#define RelationGetRelid(relation)
Definition: rel.h:413
Oid CreateConstraintEntry(const char *constraintName, Oid constraintNamespace, char constraintType, bool isDeferrable, bool isDeferred, bool isValidated, Oid relId, const int16 *constraintKey, int constraintNKeys, Oid domainId, Oid indexRelId, Oid foreignRelId, const int16 *foreignKey, const Oid *pfEqOp, const Oid *ppEqOp, const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, char foreignMatchType, const Oid *exclOp, Node *conExpr, const char *conBin, const char *conSrc, bool conIsLocal, int conInhCount, bool conNoInherit, bool is_internal)
Definition: pg_constraint.c:49
#define PRS2_NEW_VARNO
Definition: primnodes.h:139
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define Anum_pg_trigger_tgfoid
Definition: pg_trigger.h:81
#define Anum_pg_trigger_tginitdeferred
Definition: pg_trigger.h:89
#define Anum_pg_trigger_tgattr
Definition: pg_trigger.h:91
#define Natts_pg_trigger
Definition: pg_trigger.h:78
#define TRIGGER_FOR_INSTEAD(type)
Definition: pg_trigger.h:133
#define RelationGetNamespace(relation)
Definition: rel.h:440
List * p_rtable
Definition: parse_node.h:168
void EnableDisableTrigger ( Relation  rel,
const char *  tgname,
char  fires_when,
bool  skip_system 
)

Definition at line 1496 of file trigger.c.

References Anum_pg_trigger_tgname, Anum_pg_trigger_tgrelid, BTEqualStrategyNumber, CacheInvalidateRelcache(), CatalogTupleUpdate(), CStringGetDatum, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, heap_close, heap_copytuple(), heap_freetuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, InvokeObjectPostAlterHook, NameStr, NULL, ObjectIdGetDatum, RelationGetRelationName, RelationGetRelid, RowExclusiveLock, ScanKeyInit(), superuser(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, TriggerRelationId, and TriggerRelidNameIndexId.

Referenced by ATExecEnableDisableTrigger().

1498 {
1499  Relation tgrel;
1500  int nkeys;
1501  ScanKeyData keys[2];
1502  SysScanDesc tgscan;
1503  HeapTuple tuple;
1504  bool found;
1505  bool changed;
1506 
1507  /* Scan the relevant entries in pg_triggers */
1509 
1510  ScanKeyInit(&keys[0],
1512  BTEqualStrategyNumber, F_OIDEQ,
1514  if (tgname)
1515  {
1516  ScanKeyInit(&keys[1],
1518  BTEqualStrategyNumber, F_NAMEEQ,
1519  CStringGetDatum(tgname));
1520  nkeys = 2;
1521  }
1522  else
1523  nkeys = 1;
1524 
1525  tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1526  NULL, nkeys, keys);
1527 
1528  found = changed = false;
1529 
1530  while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1531  {
1532  Form_pg_trigger oldtrig = (Form_pg_trigger) GETSTRUCT(tuple);
1533 
1534  if (oldtrig->tgisinternal)
1535  {
1536  /* system trigger ... ok to process? */
1537  if (skip_system)
1538  continue;
1539  if (!superuser())
1540  ereport(ERROR,
1541  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1542  errmsg("permission denied: \"%s\" is a system trigger",
1543  NameStr(oldtrig->tgname))));
1544  }
1545 
1546  found = true;
1547 
1548  if (oldtrig->tgenabled != fires_when)
1549  {
1550  /* need to change this one ... make a copy to scribble on */
1551  HeapTuple newtup = heap_copytuple(tuple);
1552  Form_pg_trigger newtrig = (Form_pg_trigger) GETSTRUCT(newtup);
1553 
1554  newtrig->tgenabled = fires_when;
1555 
1556  CatalogTupleUpdate(tgrel, &newtup->t_self, newtup);
1557 
1558  heap_freetuple(newtup);
1559 
1560  changed = true;
1561  }
1562 
1564  HeapTupleGetOid(tuple), 0);
1565  }
1566 
1567  systable_endscan(tgscan);
1568 
1569  heap_close(tgrel, RowExclusiveLock);
1570 
1571  if (tgname && !found)
1572  ereport(ERROR,
1573  (errcode(ERRCODE_UNDEFINED_OBJECT),
1574  errmsg("trigger \"%s\" for table \"%s\" does not exist",
1575  tgname, RelationGetRelationName(rel))));
1576 
1577  /*
1578  * If we changed anything, broadcast a SI inval message to force each
1579  * backend (including our own!) to rebuild relation's relcache entry.
1580  * Otherwise they will fail to apply the change promptly.
1581  */
1582  if (changed)
1584 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:608
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:322
#define TriggerRelidNameIndexId
Definition: indexing.h:242
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:586
#define RelationGetRelationName(relation)
Definition: rel.h:433
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
#define Anum_pg_trigger_tgrelid
Definition: pg_trigger.h:79
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define Anum_pg_trigger_tgname
Definition: pg_trigger.h:80
#define TriggerRelationId
Definition: pg_trigger.h:34
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
FormData_pg_trigger * Form_pg_trigger
Definition: pg_trigger.h:72
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1225
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define NameStr(name)
Definition: c.h:495
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
#define RelationGetRelid(relation)
Definition: rel.h:413
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void ExecARDeleteTriggers ( EState estate,
ResultRelInfo relinfo,
ItemPointer  tupleid,
HeapTuple  fdw_trigtuple 
)

Definition at line 2448 of file trigger.c.

References AfterTriggerSaveEvent(), Assert, GetTupleForTrigger(), heap_freetuple(), HeapTupleIsValid, ItemPointerIsValid, LockTupleExclusive, NIL, NULL, ResultRelInfo::ri_TrigDesc, TriggerDesc::trig_delete_after_row, TriggerDesc::trig_delete_old_table, and TRIGGER_EVENT_DELETE.

Referenced by ExecDelete(), and ExecSimpleRelationDelete().

2451 {
2452  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2453 
2454  if (trigdesc &&
2455  (trigdesc->trig_delete_after_row || trigdesc->trig_delete_old_table))
2456  {
2457  HeapTuple trigtuple;
2458 
2459  Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2460  if (fdw_trigtuple == NULL)
2461  trigtuple = GetTupleForTrigger(estate,
2462  NULL,
2463  relinfo,
2464  tupleid,
2466  NULL);
2467  else
2468  trigtuple = fdw_trigtuple;
2469 
2471  true, trigtuple, NULL, NIL, NULL);
2472  if (trigtuple != fdw_trigtuple)
2473  heap_freetuple(trigtuple);
2474  }
2475 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:59
#define NIL
Definition: pg_list.h:69
#define TRIGGER_EVENT_DELETE
Definition: trigger.h:53
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
bool trig_delete_after_row
Definition: reltrigger.h:66
static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, int event, bool row_trigger, HeapTuple oldtup, HeapTuple newtup, List *recheckIndexes, Bitmapset *modifiedCols)
Definition: trigger.c:5073
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:339
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
static HeapTuple GetTupleForTrigger(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tid, LockTupleMode lockmode, TupleTableSlot **newSlot)
Definition: trigger.c:2870
bool trig_delete_old_table
Definition: reltrigger.h:77
void ExecARInsertTriggers ( EState estate,
ResultRelInfo relinfo,
HeapTuple  trigtuple,
List recheckIndexes 
)

Definition at line 2239 of file trigger.c.

References AfterTriggerSaveEvent(), NULL, ResultRelInfo::ri_TrigDesc, TriggerDesc::trig_insert_after_row, TriggerDesc::trig_insert_new_table, and TRIGGER_EVENT_INSERT.

Referenced by CopyFrom(), CopyFromInsertBatch(), ExecInsert(), and ExecSimpleRelationInsert().

2241 {
2242  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2243 
2244  if (trigdesc &&
2245  (trigdesc->trig_insert_after_row || trigdesc->trig_insert_new_table))
2247  true, NULL, trigtuple, recheckIndexes, NULL);
2248 }
bool trig_insert_new_table
Definition: reltrigger.h:74
bool trig_insert_after_row
Definition: reltrigger.h:56
static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, int event, bool row_trigger, HeapTuple oldtup, HeapTuple newtup, List *recheckIndexes, Bitmapset *modifiedCols)
Definition: trigger.c:5073
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:339
#define NULL
Definition: c.h:226
#define TRIGGER_EVENT_INSERT
Definition: trigger.h:52
void ExecARUpdateTriggers ( EState estate,
ResultRelInfo relinfo,
ItemPointer  tupleid,
HeapTuple  fdw_trigtuple,
HeapTuple  newtuple,
List recheckIndexes 
)

Definition at line 2708 of file trigger.c.

References AfterTriggerSaveEvent(), Assert, GetTupleForTrigger(), GetUpdatedColumns, heap_freetuple(), HeapTupleIsValid, ItemPointerIsValid, LockTupleExclusive, NULL, ResultRelInfo::ri_TrigDesc, TriggerDesc::trig_update_after_row, TriggerDesc::trig_update_new_table, TriggerDesc::trig_update_old_table, and TRIGGER_EVENT_UPDATE.

Referenced by ExecSimpleRelationUpdate(), and ExecUpdate().

2713 {
2714  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2715 
2716  if (trigdesc && (trigdesc->trig_update_after_row ||
2717  trigdesc->trig_update_old_table || trigdesc->trig_update_new_table))
2718  {
2719  HeapTuple trigtuple;
2720 
2721  Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2722  if (fdw_trigtuple == NULL)
2723  trigtuple = GetTupleForTrigger(estate,
2724  NULL,
2725  relinfo,
2726  tupleid,
2728  NULL);
2729  else
2730  trigtuple = fdw_trigtuple;
2731 
2733  true, trigtuple, newtuple, recheckIndexes,
2734  GetUpdatedColumns(relinfo, estate));
2735  if (trigtuple != fdw_trigtuple)
2736  heap_freetuple(trigtuple);
2737  }
2738 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:59
bool trig_update_new_table
Definition: reltrigger.h:76
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
bool trig_update_old_table
Definition: reltrigger.h:75
static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, int event, bool row_trigger, HeapTuple oldtup, HeapTuple newtup, List *recheckIndexes, Bitmapset *modifiedCols)
Definition: trigger.c:5073
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:339
bool trig_update_after_row
Definition: reltrigger.h:61
#define GetUpdatedColumns(relinfo, estate)
Definition: trigger.c:75
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define TRIGGER_EVENT_UPDATE
Definition: trigger.h:54
static HeapTuple GetTupleForTrigger(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tid, LockTupleMode lockmode, TupleTableSlot **newSlot)
Definition: trigger.c:2870
void ExecASDeleteTriggers ( EState estate,
ResultRelInfo relinfo 
)

Definition at line 2369 of file trigger.c.

References AfterTriggerSaveEvent(), NIL, NULL, ResultRelInfo::ri_TrigDesc, TriggerDesc::trig_delete_after_statement, and TRIGGER_EVENT_DELETE.

Referenced by fireASTriggers().

2370 {
2371  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2372 
2373  if (trigdesc && trigdesc->trig_delete_after_statement)
2375  false, NULL, NULL, NIL, NULL);
2376 }
#define NIL
Definition: pg_list.h:69
#define TRIGGER_EVENT_DELETE
Definition: trigger.h:53
static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, int event, bool row_trigger, HeapTuple oldtup, HeapTuple newtup, List *recheckIndexes, Bitmapset *modifiedCols)
Definition: trigger.c:5073
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:339
#define NULL
Definition: c.h:226
bool trig_delete_after_statement
Definition: reltrigger.h:69
void ExecASInsertTriggers ( EState estate,
ResultRelInfo relinfo 
)

Definition at line 2163 of file trigger.c.

References AfterTriggerSaveEvent(), NIL, NULL, ResultRelInfo::ri_TrigDesc, TriggerDesc::trig_insert_after_statement, and TRIGGER_EVENT_INSERT.

Referenced by CopyFrom(), and fireASTriggers().

2164 {
2165  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2166 
2167  if (trigdesc && trigdesc->trig_insert_after_statement)
2169  false, NULL, NULL, NIL, NULL);
2170 }
#define NIL
Definition: pg_list.h:69
bool trig_insert_after_statement
Definition: reltrigger.h:59
static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, int event, bool row_trigger, HeapTuple oldtup, HeapTuple newtup, List *recheckIndexes, Bitmapset *modifiedCols)
Definition: trigger.c:5073
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:339
#define NULL
Definition: c.h:226
#define TRIGGER_EVENT_INSERT
Definition: trigger.h:52
void ExecASTruncateTriggers ( EState estate,
ResultRelInfo relinfo 
)

Definition at line 2859 of file trigger.c.

References AfterTriggerSaveEvent(), NIL, NULL, ResultRelInfo::ri_TrigDesc, TriggerDesc::trig_truncate_after_statement, and TRIGGER_EVENT_TRUNCATE.

Referenced by ExecuteTruncate().

2860 {
2861  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2862 
2863  if (trigdesc && trigdesc->trig_truncate_after_statement)
2865  false, NULL, NULL, NIL, NULL);
2866 }
#define NIL
Definition: pg_list.h:69
bool trig_truncate_after_statement
Definition: reltrigger.h:72
static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, int event, bool row_trigger, HeapTuple oldtup, HeapTuple newtup, List *recheckIndexes, Bitmapset *modifiedCols)
Definition: trigger.c:5073
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:339
#define NULL
Definition: c.h:226
#define TRIGGER_EVENT_TRUNCATE
Definition: trigger.h:55
void ExecASUpdateTriggers ( EState estate,
ResultRelInfo relinfo 
)

Definition at line 2580 of file trigger.c.

References AfterTriggerSaveEvent(), GetUpdatedColumns, NIL, NULL, ResultRelInfo::ri_TrigDesc, TriggerDesc::trig_update_after_statement, and TRIGGER_EVENT_UPDATE.

Referenced by fireASTriggers().

2581 {
2582  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2583 
2584  if (trigdesc && trigdesc->trig_update_after_statement)
2586  false, NULL, NULL, NIL,
2587  GetUpdatedColumns(relinfo, estate));
2588 }
#define NIL
Definition: pg_list.h:69
bool trig_update_after_statement
Definition: reltrigger.h:64
static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, int event, bool row_trigger, HeapTuple oldtup, HeapTuple newtup, List *recheckIndexes, Bitmapset *modifiedCols)
Definition: trigger.c:5073
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:339
#define GetUpdatedColumns(relinfo, estate)
Definition: trigger.c:75
#define NULL
Definition: c.h:226
#define TRIGGER_EVENT_UPDATE
Definition: trigger.h:54
bool ExecBRDeleteTriggers ( EState estate,
EPQState epqstate,
ResultRelInfo relinfo,
ItemPointer  tupleid,
HeapTuple  fdw_trigtuple 
)

Definition at line 2379 of file trigger.c.

References Assert, ExecCallTriggerFunc(), GetPerTupleMemoryContext, GetTupleForTrigger(), heap_freetuple(), HeapTupleIsValid, i, InvalidBuffer, ItemPointerIsValid, LockTupleExclusive, NULL, TriggerDesc::numtriggers, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, ResultRelInfo::ri_TrigFunctions, ResultRelInfo::ri_TrigInstrument, T_TriggerData, TriggerData::tg_event, TriggerData::tg_newtable, TriggerData::tg_newtuple, TriggerData::tg_newtuplebuf, TriggerData::tg_oldtable, TriggerData::tg_relation, TriggerData::tg_trigger, TriggerData::tg_trigtuple, TriggerData::tg_trigtuplebuf, Trigger::tgtype, TRIGGER_EVENT_BEFORE, TRIGGER_EVENT_DELETE, TRIGGER_EVENT_ROW, TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE, TRIGGER_TYPE_MATCHES, TRIGGER_TYPE_ROW, TriggerEnabled(), TriggerDesc::triggers, and TriggerData::type.

Referenced by ExecDelete(), and ExecSimpleRelationDelete().

2383 {
2384  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2385  bool result = true;
2386  TriggerData LocTriggerData;
2387  HeapTuple trigtuple;
2388  HeapTuple newtuple;
2389  TupleTableSlot *newSlot;
2390  int i;
2391 
2392  Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2393  if (fdw_trigtuple == NULL)
2394  {
2395  trigtuple = GetTupleForTrigger(estate, epqstate, relinfo, tupleid,
2396  LockTupleExclusive, &newSlot);
2397  if (trigtuple == NULL)
2398  return false;
2399  }
2400  else
2401  trigtuple = fdw_trigtuple;
2402 
2403  LocTriggerData.type = T_TriggerData;
2404  LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
2407  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2408  LocTriggerData.tg_newtuple = NULL;
2409  LocTriggerData.tg_oldtable = NULL;
2410  LocTriggerData.tg_newtable = NULL;
2411  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2412  for (i = 0; i < trigdesc->numtriggers; i++)
2413  {
2414  Trigger *trigger = &trigdesc->triggers[i];
2415 
2416  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2420  continue;
2421  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2422  NULL, trigtuple, NULL))
2423  continue;
2424 
2425  LocTriggerData.tg_trigtuple = trigtuple;
2426  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2427  LocTriggerData.tg_trigger = trigger;
2428  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2429  i,
2430  relinfo->ri_TrigFunctions,
2431  relinfo->ri_TrigInstrument,
2432  GetPerTupleMemoryContext(estate));
2433  if (newtuple == NULL)
2434  {
2435  result = false; /* tell caller to suppress delete */
2436  break;
2437  }
2438  if (newtuple != trigtuple)
2439  heap_freetuple(newtuple);
2440  }
2441  if (trigtuple != fdw_trigtuple)
2442  heap_freetuple(trigtuple);
2443 
2444  return result;
2445 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:59
#define TRIGGER_EVENT_ROW
Definition: trigger.h:58
Relation ri_RelationDesc
Definition: execnodes.h:335
#define TRIGGER_TYPE_DELETE
Definition: pg_trigger.h:101
#define TRIGGER_EVENT_DELETE
Definition: trigger.h:53
Buffer tg_newtuplebuf
Definition: trigger.h:39
#define TRIGGER_TYPE_MATCHES(type, level, timing, event)
Definition: pg_trigger.h:146
Instrumentation * ri_TrigInstrument
Definition: execnodes.h:342
#define InvalidBuffer
Definition: buf.h:25
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
HeapTuple tg_trigtuple
Definition: trigger.h:35
int16 tgtype
Definition: reltrigger.h:29
#define TRIGGER_EVENT_BEFORE
Definition: trigger.h:60
Trigger * triggers
Definition: reltrigger.h:48
Buffer tg_trigtuplebuf
Definition: trigger.h:38
#define TRIGGER_TYPE_ROW
Definition: pg_trigger.h:98
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:339
int numtriggers
Definition: reltrigger.h:49
Trigger * tg_trigger
Definition: trigger.h:37
HeapTuple tg_newtuple
Definition: trigger.h:36
static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo, Trigger *trigger, TriggerEvent event, Bitmapset *modifiedCols, HeapTuple oldtup, HeapTuple newtup)
Definition: trigger.c:3014
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
TriggerEvent tg_event
Definition: trigger.h:33
Tuplestorestate * tg_oldtable
Definition: trigger.h:40
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:343
#define TRIGGER_TYPE_BEFORE
Definition: pg_trigger.h:99
static HeapTuple GetTupleForTrigger(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tid, LockTupleMode lockmode, TupleTableSlot **newSlot)
Definition: trigger.c:2870
NodeTag type
Definition: trigger.h:32
int i
Tuplestorestate * tg_newtable
Definition: trigger.h:41
static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata, int tgindx, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context)
Definition: trigger.c:2017
FmgrInfo * ri_TrigFunctions
Definition: execnodes.h:340
Relation tg_relation
Definition: trigger.h:34
TupleTableSlot* ExecBRInsertTriggers ( EState estate,
ResultRelInfo relinfo,
TupleTableSlot slot 
)

Definition at line 2173 of file trigger.c.

References EState::es_trig_tuple_slot, ExecCallTriggerFunc(), ExecMaterializeSlot(), ExecSetSlotDescriptor(), ExecStoreTuple(), GetPerTupleMemoryContext, heap_freetuple(), i, InvalidBuffer, NULL, TriggerDesc::numtriggers, RelationGetDescr, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, ResultRelInfo::ri_TrigFunctions, ResultRelInfo::ri_TrigInstrument, T_TriggerData, TriggerData::tg_event, TriggerData::tg_newtable, TriggerData::tg_newtuple, TriggerData::tg_newtuplebuf, TriggerData::tg_oldtable, TriggerData::tg_relation, TriggerData::tg_trigger, TriggerData::tg_trigtuple, TriggerData::tg_trigtuplebuf, Trigger::tgtype, TRIGGER_EVENT_BEFORE, TRIGGER_EVENT_INSERT, TRIGGER_EVENT_ROW, TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT, TRIGGER_TYPE_MATCHES, TRIGGER_TYPE_ROW, TriggerEnabled(), TriggerDesc::triggers, TupleTableSlot::tts_tupleDescriptor, and TriggerData::type.

Referenced by CopyFrom(), ExecInsert(), and ExecSimpleRelationInsert().

2175 {
2176  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2177  HeapTuple slottuple = ExecMaterializeSlot(slot);
2178  HeapTuple newtuple = slottuple;
2179  HeapTuple oldtuple;
2180  TriggerData LocTriggerData;
2181  int i;
2182 
2183  LocTriggerData.type = T_TriggerData;
2184  LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
2187  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2188  LocTriggerData.tg_newtuple = NULL;
2189  LocTriggerData.tg_oldtable = NULL;
2190  LocTriggerData.tg_newtable = NULL;
2191  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2192  for (i = 0; i < trigdesc->numtriggers; i++)
2193  {
2194  Trigger *trigger = &trigdesc->triggers[i];
2195 
2196  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2200  continue;
2201  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2202  NULL, NULL, newtuple))
2203  continue;
2204 
2205  LocTriggerData.tg_trigtuple = oldtuple = newtuple;
2206  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2207  LocTriggerData.tg_trigger = trigger;
2208  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2209  i,
2210  relinfo->ri_TrigFunctions,
2211  relinfo->ri_TrigInstrument,
2212  GetPerTupleMemoryContext(estate));
2213  if (oldtuple != newtuple && oldtuple != slottuple)
2214  heap_freetuple(oldtuple);
2215  if (newtuple == NULL)
2216  return NULL; /* "do nothing" */
2217  }
2218 
2219  if (newtuple != slottuple)
2220  {
2221  /*
2222  * Return the modified tuple using the es_trig_tuple_slot. We assume
2223  * the tuple was allocated in per-tuple memory context, and therefore
2224  * will go away by itself. The tuple table slot should not try to
2225  * clear it.
2226  */
2227  TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2228  TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2229 
2230  if (newslot->tts_tupleDescriptor != tupdesc)
2231  ExecSetSlotDescriptor(newslot, tupdesc);
2232  ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2233  slot = newslot;
2234  }
2235  return slot;
2236 }
#define TRIGGER_EVENT_ROW
Definition: trigger.h:58
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:320
Relation ri_RelationDesc
Definition: execnodes.h:335
#define RelationGetDescr(relation)
Definition: rel.h:425
Buffer tg_newtuplebuf
Definition: trigger.h:39
#define TRIGGER_TYPE_MATCHES(type, level, timing, event)
Definition: pg_trigger.h:146
Instrumentation * ri_TrigInstrument
Definition: execnodes.h:342
#define InvalidBuffer
Definition: buf.h:25
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
HeapTuple tg_trigtuple
Definition: trigger.h:35
int16 tgtype
Definition: reltrigger.h:29
#define TRIGGER_EVENT_BEFORE
Definition: trigger.h:60
Trigger * triggers
Definition: reltrigger.h:48
Buffer tg_trigtuplebuf
Definition: trigger.h:38
#define TRIGGER_TYPE_ROW
Definition: pg_trigger.h:98
TupleTableSlot * es_trig_tuple_slot
Definition: execnodes.h:388
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:339
int numtriggers
Definition: reltrigger.h:49
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:121
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:247
Trigger * tg_trigger
Definition: trigger.h:37
HeapTuple tg_newtuple
Definition: trigger.h:36
static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo, Trigger *trigger, TriggerEvent event, Bitmapset *modifiedCols, HeapTuple oldtup, HeapTuple newtup)
Definition: trigger.c:3014
#define NULL
Definition: c.h:226
TriggerEvent tg_event
Definition: trigger.h:33
#define TRIGGER_TYPE_INSERT
Definition: pg_trigger.h:100
HeapTuple ExecMaterializeSlot(TupleTableSlot *slot)
Definition: execTuples.c:725
Tuplestorestate * tg_oldtable
Definition: trigger.h:40
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:343
#define TRIGGER_TYPE_BEFORE
Definition: pg_trigger.h:99
#define TRIGGER_EVENT_INSERT
Definition: trigger.h:52
NodeTag type
Definition: trigger.h:32
int i
Tuplestorestate * tg_newtable
Definition: trigger.h:41
static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata, int tgindx, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context)
Definition: trigger.c:2017
FmgrInfo * ri_TrigFunctions
Definition: execnodes.h:340
Relation tg_relation
Definition: trigger.h:34
TupleTableSlot* ExecBRUpdateTriggers ( EState estate,
EPQState epqstate,
ResultRelInfo relinfo,
ItemPointer  tupleid,
HeapTuple  fdw_trigtuple,
TupleTableSlot slot 
)

Definition at line 2591 of file trigger.c.

References Assert, EState::es_trig_tuple_slot, ExecCallTriggerFunc(), ExecFilterJunk(), ExecMaterializeSlot(), ExecSetSlotDescriptor(), ExecStoreTuple(), ExecUpdateLockMode(), GetPerTupleMemoryContext, GetTupleForTrigger(), GetUpdatedColumns, heap_freetuple(), HeapTupleIsValid, i, InvalidBuffer, ItemPointerIsValid, NULL, TriggerDesc::numtriggers, RelationGetDescr, ResultRelInfo::ri_junkFilter, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, ResultRelInfo::ri_TrigFunctions, ResultRelInfo::ri_TrigInstrument, T_TriggerData, TriggerData::tg_event, TriggerData::tg_newtable, TriggerData::tg_newtuple, TriggerData::tg_newtuplebuf, TriggerData::tg_oldtable, TriggerData::tg_relation, TriggerData::tg_trigger, TriggerData::tg_trigtuple, TriggerData::tg_trigtuplebuf, Trigger::tgtype, TRIGGER_EVENT_BEFORE, TRIGGER_EVENT_ROW, TRIGGER_EVENT_UPDATE, TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_MATCHES, TRIGGER_TYPE_ROW, TRIGGER_TYPE_UPDATE, TriggerEnabled(), TriggerDesc::triggers, TupleTableSlot::tts_tupleDescriptor, and TriggerData::type.

Referenced by ExecSimpleRelationUpdate(), and ExecUpdate().

2596 {
2597  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2598  HeapTuple slottuple = ExecMaterializeSlot(slot);
2599  HeapTuple newtuple = slottuple;
2600  TriggerData LocTriggerData;
2601  HeapTuple trigtuple;
2602  HeapTuple oldtuple;
2603  TupleTableSlot *newSlot;
2604  int i;
2605  Bitmapset *updatedCols;
2606  LockTupleMode lockmode;
2607 
2608  /* Determine lock mode to use */
2609  lockmode = ExecUpdateLockMode(estate, relinfo);
2610 
2611  Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2612  if (fdw_trigtuple == NULL)
2613  {
2614  /* get a copy of the on-disk tuple we are planning to update */
2615  trigtuple = GetTupleForTrigger(estate, epqstate, relinfo, tupleid,
2616  lockmode, &newSlot);
2617  if (trigtuple == NULL)
2618  return NULL; /* cancel the update action */
2619  }
2620  else
2621  {
2622  trigtuple = fdw_trigtuple;
2623  newSlot = NULL;
2624  }
2625 
2626  /*
2627  * In READ COMMITTED isolation level it's possible that target tuple was
2628  * changed due to concurrent update. In that case we have a raw subplan
2629  * output tuple in newSlot, and need to run it through the junk filter to
2630  * produce an insertable tuple.
2631  *
2632  * Caution: more than likely, the passed-in slot is the same as the
2633  * junkfilter's output slot, so we are clobbering the original value of
2634  * slottuple by doing the filtering. This is OK since neither we nor our
2635  * caller have any more interest in the prior contents of that slot.
2636  */
2637  if (newSlot != NULL)
2638  {
2639  slot = ExecFilterJunk(relinfo->ri_junkFilter, newSlot);
2640  slottuple = ExecMaterializeSlot(slot);
2641  newtuple = slottuple;
2642  }
2643 
2644 
2645  LocTriggerData.type = T_TriggerData;
2646  LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
2649  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2650  LocTriggerData.tg_oldtable = NULL;
2651  LocTriggerData.tg_newtable = NULL;
2652  updatedCols = GetUpdatedColumns(relinfo, estate);
2653  for (i = 0; i < trigdesc->numtriggers; i++)
2654  {
2655  Trigger *trigger = &trigdesc->triggers[i];
2656 
2657  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2661  continue;
2662  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2663  updatedCols, trigtuple, newtuple))
2664  continue;
2665 
2666  LocTriggerData.tg_trigtuple = trigtuple;
2667  LocTriggerData.tg_newtuple = oldtuple = newtuple;
2668  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2669  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2670  LocTriggerData.tg_trigger = trigger;
2671  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2672  i,
2673  relinfo->ri_TrigFunctions,
2674  relinfo->ri_TrigInstrument,
2675  GetPerTupleMemoryContext(estate));
2676  if (oldtuple != newtuple && oldtuple != slottuple)
2677  heap_freetuple(oldtuple);
2678  if (newtuple == NULL)
2679  {
2680  if (trigtuple != fdw_trigtuple)
2681  heap_freetuple(trigtuple);
2682  return NULL; /* "do nothing" */
2683  }
2684  }
2685  if (trigtuple != fdw_trigtuple)
2686  heap_freetuple(trigtuple);
2687 
2688  if (newtuple != slottuple)
2689  {
2690  /*
2691  * Return the modified tuple using the es_trig_tuple_slot. We assume
2692  * the tuple was allocated in per-tuple memory context, and therefore
2693  * will go away by itself. The tuple table slot should not try to
2694  * clear it.
2695  */
2696  TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2697  TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2698 
2699  if (newslot->tts_tupleDescriptor != tupdesc)
2700  ExecSetSlotDescriptor(newslot, tupdesc);
2701  ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2702  slot = newslot;
2703  }
2704  return slot;
2705 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:59
#define TRIGGER_EVENT_ROW
Definition: trigger.h:58
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:320
JunkFilter * ri_junkFilter
Definition: execnodes.h:349
Relation ri_RelationDesc
Definition: execnodes.h:335
#define RelationGetDescr(relation)
Definition: rel.h:425
Buffer tg_newtuplebuf
Definition: trigger.h:39
#define TRIGGER_TYPE_MATCHES(type, level, timing, event)
Definition: pg_trigger.h:146
Instrumentation * ri_TrigInstrument
Definition: execnodes.h:342
#define InvalidBuffer
Definition: buf.h:25
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
HeapTuple tg_trigtuple
Definition: trigger.h:35
LockTupleMode
Definition: heapam.h:38
int16 tgtype
Definition: reltrigger.h:29
#define TRIGGER_EVENT_BEFORE
Definition: trigger.h:60
Trigger * triggers
Definition: reltrigger.h:48
Buffer tg_trigtuplebuf
Definition: trigger.h:38
#define TRIGGER_TYPE_ROW
Definition: pg_trigger.h:98
TupleTableSlot * es_trig_tuple_slot
Definition: execnodes.h:388
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:339
int numtriggers
Definition: reltrigger.h:49
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:121
TupleTableSlot * ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
Definition: execJunk.c:262
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:247
Trigger * tg_trigger
Definition: trigger.h:37
HeapTuple tg_newtuple
Definition: trigger.h:36
#define TRIGGER_TYPE_UPDATE
Definition: pg_trigger.h:102
static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo, Trigger *trigger, TriggerEvent event, Bitmapset *modifiedCols, HeapTuple oldtup, HeapTuple newtup)
Definition: trigger.c:3014
#define GetUpdatedColumns(relinfo, estate)
Definition: trigger.c:75
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
LockTupleMode ExecUpdateLockMode(EState *estate, ResultRelInfo *relinfo)
Definition: execMain.c:2182
TriggerEvent tg_event
Definition: trigger.h:33
HeapTuple ExecMaterializeSlot(TupleTableSlot *slot)
Definition: execTuples.c:725
#define TRIGGER_EVENT_UPDATE
Definition: trigger.h:54
Tuplestorestate * tg_oldtable
Definition: trigger.h:40
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:343
#define TRIGGER_TYPE_BEFORE
Definition: pg_trigger.h:99
static HeapTuple GetTupleForTrigger(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tid, LockTupleMode lockmode, TupleTableSlot **newSlot)
Definition: trigger.c:2870
NodeTag type
Definition: trigger.h:32
int i
Tuplestorestate * tg_newtable
Definition: trigger.h:41
static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata, int tgindx, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context)
Definition: trigger.c:2017
FmgrInfo * ri_TrigFunctions
Definition: execnodes.h:340
Relation tg_relation
Definition: trigger.h:34
void ExecBSDeleteTriggers ( EState estate,
ResultRelInfo relinfo 
)

Definition at line 2317 of file trigger.c.

References ereport, errcode(), errmsg(), ERROR, ExecCallTriggerFunc(), GetPerTupleMemoryContext, i, InvalidBuffer, NULL, TriggerDesc::numtriggers, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, ResultRelInfo::ri_TrigFunctions, ResultRelInfo::ri_TrigInstrument, T_TriggerData, TriggerData::tg_event, TriggerData::tg_newtable, TriggerData::tg_newtuple, TriggerData::tg_newtuplebuf, TriggerData::tg_oldtable, TriggerData::tg_relation, TriggerData::tg_trigger, TriggerData::tg_trigtuple, TriggerData::tg_trigtuplebuf, Trigger::tgtype, TriggerDesc::trig_delete_before_statement, TRIGGER_EVENT_BEFORE, TRIGGER_EVENT_DELETE, TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE, TRIGGER_TYPE_MATCHES, TRIGGER_TYPE_STATEMENT, TriggerEnabled(), TriggerDesc::triggers, and TriggerData::type.

Referenced by fireBSTriggers().

2318 {
2319  TriggerDesc *trigdesc;
2320  int i;
2321  TriggerData LocTriggerData;
2322 
2323  trigdesc = relinfo->ri_TrigDesc;
2324 
2325  if (trigdesc == NULL)
2326  return;
2327  if (!trigdesc->trig_delete_before_statement)
2328  return;
2329 
2330  LocTriggerData.type = T_TriggerData;
2331  LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
2333  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2334  LocTriggerData.tg_trigtuple = NULL;
2335  LocTriggerData.tg_newtuple = NULL;
2336  LocTriggerData.tg_oldtable = NULL;
2337  LocTriggerData.tg_newtable = NULL;
2338  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2339  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2340  for (i = 0; i < trigdesc->numtriggers; i++)
2341  {
2342  Trigger *trigger = &trigdesc->triggers[i];
2343  HeapTuple newtuple;
2344 
2345  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2349  continue;
2350  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2351  NULL, NULL, NULL))
2352  continue;
2353 
2354  LocTriggerData.tg_trigger = trigger;
2355  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2356  i,
2357  relinfo->ri_TrigFunctions,
2358  relinfo->ri_TrigInstrument,
2359  GetPerTupleMemoryContext(estate));
2360 
2361  if (newtuple)
2362  ereport(ERROR,
2363  (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2364  errmsg("BEFORE STATEMENT trigger cannot return a value")));
2365  }
2366 }
Relation ri_RelationDesc
Definition: execnodes.h:335
#define TRIGGER_TYPE_DELETE
Definition: pg_trigger.h:101
#define TRIGGER_EVENT_DELETE
Definition: trigger.h:53
Buffer tg_newtuplebuf
Definition: trigger.h:39
#define TRIGGER_TYPE_MATCHES(type, level, timing, event)
Definition: pg_trigger.h:146
Instrumentation * ri_TrigInstrument
Definition: execnodes.h:342
#define InvalidBuffer
Definition: buf.h:25
int errcode(int sqlerrcode)
Definition: elog.c:575
HeapTuple tg_trigtuple
Definition: trigger.h:35
#define ERROR
Definition: elog.h:43
int16 tgtype
Definition: reltrigger.h:29
#define TRIGGER_EVENT_BEFORE
Definition: trigger.h:60
Trigger * triggers
Definition: reltrigger.h:48
Buffer tg_trigtuplebuf
Definition: trigger.h:38
bool trig_delete_before_statement
Definition: reltrigger.h:68
#define ereport(elevel, rest)
Definition: elog.h:122
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:339
int numtriggers
Definition: reltrigger.h:49
Trigger * tg_trigger
Definition: trigger.h:37
HeapTuple tg_newtuple
Definition: trigger.h:36
static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo, Trigger *trigger, TriggerEvent event, Bitmapset *modifiedCols, HeapTuple oldtup, HeapTuple newtup)
Definition: trigger.c:3014
#define NULL
Definition: c.h:226
TriggerEvent tg_event
Definition: trigger.h:33
Tuplestorestate * tg_oldtable
Definition: trigger.h:40
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:343
#define TRIGGER_TYPE_BEFORE
Definition: pg_trigger.h:99
int errmsg(const char *fmt,...)
Definition: elog.c:797
NodeTag type
Definition: trigger.h:32
int i
Tuplestorestate * tg_newtable
Definition: trigger.h:41
static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata, int tgindx, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context)
Definition: trigger.c:2017
#define TRIGGER_TYPE_STATEMENT
Definition: pg_trigger.h:107
FmgrInfo * ri_TrigFunctions
Definition: execnodes.h:340
Relation tg_relation
Definition: trigger.h:34
void ExecBSInsertTriggers ( EState estate,
ResultRelInfo relinfo 
)

Definition at line 2111 of file trigger.c.

References ereport, errcode(), errmsg(), ERROR, ExecCallTriggerFunc(), GetPerTupleMemoryContext, i, InvalidBuffer, NULL, TriggerDesc::numtriggers, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, ResultRelInfo::ri_TrigFunctions, ResultRelInfo::ri_TrigInstrument, T_TriggerData, TriggerData::tg_event, TriggerData::tg_newtable, TriggerData::tg_newtuple, TriggerData::tg_newtuplebuf, TriggerData::tg_oldtable, TriggerData::tg_relation, TriggerData::tg_trigger, TriggerData::tg_trigtuple, TriggerData::tg_trigtuplebuf, Trigger::tgtype, TriggerDesc::trig_insert_before_statement, TRIGGER_EVENT_BEFORE, TRIGGER_EVENT_INSERT, TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT, TRIGGER_TYPE_MATCHES, TRIGGER_TYPE_STATEMENT, TriggerEnabled(), TriggerDesc::triggers, and TriggerData::type.

Referenced by CopyFrom(), and fireBSTriggers().

2112 {
2113  TriggerDesc *trigdesc;
2114  int i;
2115  TriggerData LocTriggerData;
2116 
2117  trigdesc = relinfo->ri_TrigDesc;
2118 
2119  if (trigdesc == NULL)
2120  return;
2121  if (!trigdesc->trig_insert_before_statement)
2122  return;
2123 
2124  LocTriggerData.type = T_TriggerData;
2125  LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
2127  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2128  LocTriggerData.tg_trigtuple = NULL;
2129  LocTriggerData.tg_newtuple = NULL;
2130  LocTriggerData.tg_oldtable = NULL;
2131  LocTriggerData.tg_newtable = NULL;
2132  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2133  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2134  for (i = 0; i < trigdesc->numtriggers; i++)
2135  {
2136  Trigger *trigger = &trigdesc->triggers[i];
2137  HeapTuple newtuple;
2138 
2139  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2143  continue;
2144  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2145  NULL, NULL, NULL))
2146  continue;
2147 
2148  LocTriggerData.tg_trigger = trigger;
2149  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2150  i,
2151  relinfo->ri_TrigFunctions,
2152  relinfo->ri_TrigInstrument,
2153  GetPerTupleMemoryContext(estate));
2154 
2155  if (newtuple)
2156  ereport(ERROR,
2157  (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2158  errmsg("BEFORE STATEMENT trigger cannot return a value")));
2159  }
2160 }
Relation ri_RelationDesc
Definition: execnodes.h:335
Buffer tg_newtuplebuf
Definition: trigger.h:39
#define TRIGGER_TYPE_MATCHES(type, level, timing, event)
Definition: pg_trigger.h:146
Instrumentation * ri_TrigInstrument
Definition: execnodes.h:342
#define InvalidBuffer
Definition: buf.h:25
int errcode(int sqlerrcode)
Definition: elog.c:575
HeapTuple tg_trigtuple
Definition: trigger.h:35
#define ERROR
Definition: elog.h:43
int16 tgtype
Definition: reltrigger.h:29
#define TRIGGER_EVENT_BEFORE
Definition: trigger.h:60
Trigger * triggers
Definition: reltrigger.h:48
Buffer tg_trigtuplebuf
Definition: trigger.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:339
int numtriggers
Definition: reltrigger.h:49
Trigger * tg_trigger
Definition: trigger.h:37
HeapTuple tg_newtuple
Definition: trigger.h:36
static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo, Trigger *trigger, TriggerEvent event, Bitmapset *modifiedCols, HeapTuple oldtup, HeapTuple newtup)
Definition: trigger.c:3014
#define NULL
Definition: c.h:226
TriggerEvent tg_event
Definition: trigger.h:33
bool trig_insert_before_statement
Definition: reltrigger.h:58
#define TRIGGER_TYPE_INSERT
Definition: pg_trigger.h:100
Tuplestorestate * tg_oldtable
Definition: trigger.h:40
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:343
#define TRIGGER_TYPE_BEFORE
Definition: pg_trigger.h:99
#define TRIGGER_EVENT_INSERT
Definition: trigger.h:52
int errmsg(const char *fmt,...)
Definition: elog.c:797
NodeTag type
Definition: trigger.h:32
int i
Tuplestorestate * tg_newtable
Definition: trigger.h:41
static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata, int tgindx, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context)
Definition: trigger.c:2017
#define TRIGGER_TYPE_STATEMENT
Definition: pg_trigger.h:107
FmgrInfo * ri_TrigFunctions
Definition: execnodes.h:340
Relation tg_relation
Definition: trigger.h:34
void ExecBSTruncateTriggers ( EState estate,
ResultRelInfo relinfo 
)

Definition at line 2807 of file trigger.c.

References ereport, errcode(), errmsg(), ERROR, ExecCallTriggerFunc(), GetPerTupleMemoryContext, i, InvalidBuffer, NULL, TriggerDesc::numtriggers, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, ResultRelInfo::ri_TrigFunctions, ResultRelInfo::ri_TrigInstrument, T_TriggerData, TriggerData::tg_event, TriggerData::tg_newtable, TriggerData::tg_newtuple, TriggerData::tg_newtuplebuf, TriggerData::tg_oldtable, TriggerData::tg_relation, TriggerData::tg_trigger, TriggerData::tg_trigtuple, TriggerData::tg_trigtuplebuf, Trigger::tgtype, TriggerDesc::trig_truncate_before_statement, TRIGGER_EVENT_BEFORE, TRIGGER_EVENT_TRUNCATE, TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_MATCHES, TRIGGER_TYPE_STATEMENT, TRIGGER_TYPE_TRUNCATE, TriggerEnabled(), TriggerDesc::triggers, and TriggerData::type.

Referenced by ExecuteTruncate().

2808 {
2809  TriggerDesc *trigdesc;
2810  int i;
2811  TriggerData LocTriggerData;
2812 
2813  trigdesc = relinfo->ri_TrigDesc;
2814 
2815  if (trigdesc == NULL)
2816  return;
2817  if (!trigdesc->trig_truncate_before_statement)
2818  return;
2819 
2820  LocTriggerData.type = T_TriggerData;
2821  LocTriggerData.tg_event = TRIGGER_EVENT_TRUNCATE |
2823  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2824  LocTriggerData.tg_trigtuple = NULL;
2825  LocTriggerData.tg_newtuple = NULL;
2826  LocTriggerData.tg_oldtable = NULL;
2827  LocTriggerData.tg_newtable = NULL;
2828  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2829  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2830  for (i = 0; i < trigdesc->numtriggers; i++)
2831  {
2832  Trigger *trigger = &trigdesc->triggers[i];
2833  HeapTuple newtuple;
2834 
2835  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2839  continue;
2840  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2841  NULL, NULL, NULL))
2842  continue;
2843 
2844  LocTriggerData.tg_trigger = trigger;
2845  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2846  i,
2847  relinfo->ri_TrigFunctions,
2848  relinfo->ri_TrigInstrument,
2849  GetPerTupleMemoryContext(estate));
2850 
2851  if (newtuple)
2852  ereport(ERROR,
2853  (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2854  errmsg("BEFORE STATEMENT trigger cannot return a value")));
2855  }
2856 }
Relation ri_RelationDesc
Definition: execnodes.h:335
Buffer tg_newtuplebuf
Definition: trigger.h:39
#define TRIGGER_TYPE_MATCHES(type, level, timing, event)
Definition: pg_trigger.h:146
Instrumentation * ri_TrigInstrument
Definition: execnodes.h:342
#define InvalidBuffer
Definition: buf.h:25
int errcode(int sqlerrcode)
Definition: elog.c:575
HeapTuple tg_trigtuple
Definition: trigger.h:35
#define ERROR
Definition: elog.h:43
int16 tgtype
Definition: reltrigger.h:29
#define TRIGGER_EVENT_BEFORE
Definition: trigger.h:60
Trigger * triggers
Definition: reltrigger.h:48
Buffer tg_trigtuplebuf
Definition: trigger.h:38
bool trig_truncate_before_statement
Definition: reltrigger.h:71
#define ereport(elevel, rest)
Definition: elog.h:122
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:339
int numtriggers
Definition: reltrigger.h:49
#define TRIGGER_TYPE_TRUNCATE
Definition: pg_trigger.h:103
Trigger * tg_trigger
Definition: trigger.h:37
HeapTuple tg_newtuple
Definition: trigger.h:36
static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo, Trigger *trigger, TriggerEvent event, Bitmapset *modifiedCols, HeapTuple oldtup, HeapTuple newtup)
Definition: trigger.c:3014
#define NULL
Definition: c.h:226
TriggerEvent tg_event
Definition: trigger.h:33
#define TRIGGER_EVENT_TRUNCATE
Definition: trigger.h:55
Tuplestorestate * tg_oldtable
Definition: trigger.h:40
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:343
#define TRIGGER_TYPE_BEFORE
Definition: pg_trigger.h:99
int errmsg(const char *fmt,...)
Definition: elog.c:797
NodeTag type
Definition: trigger.h:32
int i
Tuplestorestate * tg_newtable
Definition: trigger.h:41
static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata, int tgindx, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context)
Definition: trigger.c:2017
#define TRIGGER_TYPE_STATEMENT
Definition: pg_trigger.h:107
FmgrInfo * ri_TrigFunctions
Definition: execnodes.h:340
Relation tg_relation
Definition: trigger.h:34
void ExecBSUpdateTriggers ( EState estate,
ResultRelInfo relinfo 
)

Definition at line 2525 of file trigger.c.

References ereport, errcode(), errmsg(), ERROR, ExecCallTriggerFunc(), GetPerTupleMemoryContext, GetUpdatedColumns, i, InvalidBuffer, NULL, TriggerDesc::numtriggers, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, ResultRelInfo::ri_TrigFunctions, ResultRelInfo::ri_TrigInstrument, T_TriggerData, TriggerData::tg_event, TriggerData::tg_newtable, TriggerData::tg_newtuple, TriggerData::tg_newtuplebuf, TriggerData::tg_oldtable, TriggerData::tg_relation, TriggerData::tg_trigger, TriggerData::tg_trigtuple, TriggerData::tg_trigtuplebuf, Trigger::tgtype, TriggerDesc::trig_update_before_statement, TRIGGER_EVENT_BEFORE, TRIGGER_EVENT_UPDATE, TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_MATCHES, TRIGGER_TYPE_STATEMENT, TRIGGER_TYPE_UPDATE, TriggerEnabled(), TriggerDesc::triggers, and TriggerData::type.

Referenced by fireBSTriggers().

2526 {
2527  TriggerDesc *trigdesc;
2528  int i;
2529  TriggerData LocTriggerData;
2530  Bitmapset *updatedCols;
2531 
2532  trigdesc = relinfo->ri_TrigDesc;
2533 
2534  if (trigdesc == NULL)
2535  return;
2536  if (!trigdesc->trig_update_before_statement)
2537  return;
2538 
2539  updatedCols = GetUpdatedColumns(relinfo, estate);
2540 
2541  LocTriggerData.type = T_TriggerData;
2542  LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
2544  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2545  LocTriggerData.tg_trigtuple = NULL;
2546  LocTriggerData.tg_newtuple = NULL;
2547  LocTriggerData.tg_oldtable = NULL;
2548  LocTriggerData.tg_newtable = NULL;
2549  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2550  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2551  for (i = 0; i < trigdesc->numtriggers; i++)
2552  {
2553  Trigger *trigger = &trigdesc->triggers[i];
2554  HeapTuple newtuple;
2555 
2556  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2560  continue;
2561  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2562  updatedCols, NULL, NULL))
2563  continue;
2564 
2565  LocTriggerData.tg_trigger = trigger;
2566  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2567  i,
2568  relinfo->ri_TrigFunctions,
2569  relinfo->ri_TrigInstrument,
2570  GetPerTupleMemoryContext(estate));
2571 
2572  if (newtuple)
2573  ereport(ERROR,
2574  (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2575  errmsg("BEFORE STATEMENT trigger cannot return a value")));
2576  }
2577 }
Relation ri_RelationDesc
Definition: execnodes.h:335
Buffer tg_newtuplebuf
Definition: trigger.h:39
#define TRIGGER_TYPE_MATCHES(type, level, timing, event)
Definition: pg_trigger.h:146
Instrumentation * ri_TrigInstrument
Definition: execnodes.h:342
#define InvalidBuffer
Definition: buf.h:25
int errcode(int sqlerrcode)
Definition: elog.c:575
bool trig_update_before_statement
Definition: reltrigger.h:63
HeapTuple tg_trigtuple
Definition: trigger.h:35
#define ERROR
Definition: elog.h:43
int16 tgtype
Definition: reltrigger.h:29
#define TRIGGER_EVENT_BEFORE
Definition: trigger.h:60
Trigger * triggers
Definition: reltrigger.h:48
Buffer tg_trigtuplebuf
Definition: trigger.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:339
int numtriggers
Definition: reltrigger.h:49
Trigger * tg_trigger
Definition: trigger.h:37
HeapTuple tg_newtuple
Definition: trigger.h:36
#define TRIGGER_TYPE_UPDATE
Definition: pg_trigger.h:102
static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo, Trigger *trigger, TriggerEvent event, Bitmapset *modifiedCols, HeapTuple oldtup, HeapTuple newtup)
Definition: trigger.c:3014
#define GetUpdatedColumns(relinfo, estate)
Definition: trigger.c:75
#define NULL
Definition: c.h:226
TriggerEvent tg_event
Definition: trigger.h:33
#define TRIGGER_EVENT_UPDATE
Definition: trigger.h:54
Tuplestorestate * tg_oldtable
Definition: trigger.h:40
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:343
#define TRIGGER_TYPE_BEFORE
Definition: pg_trigger.h:99
int errmsg(const char *fmt,...)
Definition: elog.c:797
NodeTag type
Definition: trigger.h:32
int i
Tuplestorestate * tg_newtable
Definition: trigger.h:41
static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata, int tgindx, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context)
Definition: trigger.c:2017
#define TRIGGER_TYPE_STATEMENT
Definition: pg_trigger.h:107
FmgrInfo * ri_TrigFunctions
Definition: execnodes.h:340
Relation tg_relation
Definition: trigger.h:34
bool ExecIRDeleteTriggers ( EState estate,
ResultRelInfo relinfo,
HeapTuple  trigtuple 
)

Definition at line 2478 of file trigger.c.

References ExecCallTriggerFunc(), GetPerTupleMemoryContext, heap_freetuple(), i, InvalidBuffer, NULL, TriggerDesc::numtriggers, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, ResultRelInfo::ri_TrigFunctions, ResultRelInfo::ri_TrigInstrument, T_TriggerData, TriggerData::tg_event, TriggerData::tg_newtable, TriggerData::tg_newtuple, TriggerData::tg_newtuplebuf, TriggerData::tg_oldtable, TriggerData::tg_relation, TriggerData::tg_trigger, TriggerData::tg_trigtuple, TriggerData::tg_trigtuplebuf, Trigger::tgtype, TRIGGER_EVENT_DELETE, TRIGGER_EVENT_INSTEAD, TRIGGER_EVENT_ROW, TRIGGER_TYPE_DELETE, TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_MATCHES, TRIGGER_TYPE_ROW, TriggerEnabled(), TriggerDesc::triggers, and TriggerData::type.

Referenced by ExecDelete().

2480 {
2481  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2482  TriggerData LocTriggerData;
2483  HeapTuple rettuple;
2484  int i;
2485 
2486  LocTriggerData.type = T_TriggerData;
2487  LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
2490  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2491  LocTriggerData.tg_newtuple = NULL;
2492  LocTriggerData.tg_oldtable = NULL;
2493  LocTriggerData.tg_newtable = NULL;
2494  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2495  for (i = 0; i < trigdesc->numtriggers; i++)
2496  {
2497  Trigger *trigger = &trigdesc->triggers[i];
2498 
2499  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2503  continue;
2504  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2505  NULL, trigtuple, NULL))
2506  continue;
2507 
2508  LocTriggerData.tg_trigtuple = trigtuple;
2509  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2510  LocTriggerData.tg_trigger = trigger;
2511  rettuple = ExecCallTriggerFunc(&LocTriggerData,
2512  i,
2513  relinfo->ri_TrigFunctions,
2514  relinfo->ri_TrigInstrument,
2515  GetPerTupleMemoryContext(estate));
2516  if (rettuple == NULL)
2517  return false; /* Delete was suppressed */
2518  if (rettuple != trigtuple)
2519  heap_freetuple(rettuple);
2520  }
2521  return true;
2522 }
#define TRIGGER_EVENT_ROW
Definition: trigger.h:58
Relation ri_RelationDesc
Definition: execnodes.h:335
#define TRIGGER_TYPE_DELETE
Definition: pg_trigger.h:101
#define TRIGGER_EVENT_DELETE
Definition: trigger.h:53
Buffer tg_newtuplebuf
Definition: trigger.h:39
#define TRIGGER_TYPE_MATCHES(type, level, timing, event)
Definition: pg_trigger.h:146
Instrumentation * ri_TrigInstrument
Definition: execnodes.h:342
#define InvalidBuffer
Definition: buf.h:25
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
HeapTuple tg_trigtuple
Definition: trigger.h:35
#define TRIGGER_TYPE_INSTEAD
Definition: pg_trigger.h:104
#define TRIGGER_EVENT_INSTEAD
Definition: trigger.h:62
int16 tgtype
Definition: reltrigger.h:29
Trigger * triggers
Definition: reltrigger.h:48
Buffer tg_trigtuplebuf
Definition: trigger.h:38
#define TRIGGER_TYPE_ROW
Definition: pg_trigger.h:98
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:339
int numtriggers
Definition: reltrigger.h:49
Trigger * tg_trigger
Definition: trigger.h:37
HeapTuple tg_newtuple
Definition: trigger.h:36
static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo, Trigger *trigger, TriggerEvent event, Bitmapset *modifiedCols, HeapTuple oldtup, HeapTuple newtup)
Definition: trigger.c:3014
#define NULL
Definition: c.h:226
TriggerEvent tg_event
Definition: trigger.h:33
Tuplestorestate * tg_oldtable
Definition: trigger.h:40
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:343
NodeTag type
Definition: trigger.h:32
int i
Tuplestorestate * tg_newtable
Definition: trigger.h:41
static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata, int tgindx, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context)
Definition: trigger.c:2017
FmgrInfo * ri_TrigFunctions
Definition: execnodes.h:340
Relation tg_relation
Definition: trigger.h:34
TupleTableSlot* ExecIRInsertTriggers ( EState estate,
ResultRelInfo relinfo,
TupleTableSlot slot 
)

Definition at line 2251 of file trigger.c.

References EState::es_trig_tuple_slot, ExecCallTriggerFunc(), ExecMaterializeSlot(), ExecSetSlotDescriptor(), ExecStoreTuple(), GetPerTupleMemoryContext, heap_freetuple(), i, InvalidBuffer, NULL, TriggerDesc::numtriggers, RelationGetDescr, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, ResultRelInfo::ri_TrigFunctions, ResultRelInfo::ri_TrigInstrument, T_TriggerData, TriggerData::tg_event, TriggerData::tg_newtable, TriggerData::tg_newtuple, TriggerData::tg_newtuplebuf, TriggerData::tg_oldtable, TriggerData::tg_relation, TriggerData::tg_trigger, TriggerData::tg_trigtuple, TriggerData::tg_trigtuplebuf, Trigger::tgtype, TRIGGER_EVENT_INSERT, TRIGGER_EVENT_INSTEAD, TRIGGER_EVENT_ROW, TRIGGER_TYPE_INSERT, TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_MATCHES, TRIGGER_TYPE_ROW, TriggerEnabled(), TriggerDesc::triggers, TupleTableSlot::tts_tupleDescriptor, and TriggerData::type.

Referenced by CopyFrom(), and ExecInsert().

2253 {
2254  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2255  HeapTuple slottuple = ExecMaterializeSlot(slot);
2256  HeapTuple newtuple = slottuple;
2257  HeapTuple oldtuple;
2258  TriggerData LocTriggerData;
2259  int i;
2260 
2261  LocTriggerData.type = T_TriggerData;
2262  LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
2265  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2266  LocTriggerData.tg_newtuple = NULL;
2267  LocTriggerData.tg_oldtable = NULL;
2268  LocTriggerData.tg_newtable = NULL;
2269  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2270  for (i = 0; i < trigdesc->numtriggers; i++)
2271  {
2272  Trigger *trigger = &trigdesc->triggers[i];
2273 
2274  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2278  continue;
2279  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2280  NULL, NULL, newtuple))
2281  continue;
2282 
2283  LocTriggerData.tg_trigtuple = oldtuple = newtuple;
2284  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2285  LocTriggerData.tg_trigger = trigger;
2286  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2287  i,
2288  relinfo->ri_TrigFunctions,
2289  relinfo->ri_TrigInstrument,
2290  GetPerTupleMemoryContext(estate));
2291  if (oldtuple != newtuple && oldtuple != slottuple)
2292  heap_freetuple(oldtuple);
2293  if (newtuple == NULL)
2294  return NULL; /* "do nothing" */
2295  }
2296 
2297  if (newtuple != slottuple)
2298  {
2299  /*
2300  * Return the modified tuple using the es_trig_tuple_slot. We assume
2301  * the tuple was allocated in per-tuple memory context, and therefore
2302  * will go away by itself. The tuple table slot should not try to
2303  * clear it.
2304  */
2305  TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2306  TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2307 
2308  if (newslot->tts_tupleDescriptor != tupdesc)
2309  ExecSetSlotDescriptor(newslot, tupdesc);
2310  ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2311  slot = newslot;
2312  }
2313  return slot;
2314 }
#define TRIGGER_EVENT_ROW
Definition: trigger.h:58
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:320
Relation ri_RelationDesc
Definition: execnodes.h:335
#define RelationGetDescr(relation)
Definition: rel.h:425
Buffer tg_newtuplebuf
Definition: trigger.h:39
#define TRIGGER_TYPE_MATCHES(type, level, timing, event)
Definition: pg_trigger.h:146
Instrumentation * ri_TrigInstrument
Definition: execnodes.h:342
#define InvalidBuffer
Definition: buf.h:25
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
HeapTuple tg_trigtuple
Definition: trigger.h:35
#define TRIGGER_TYPE_INSTEAD
Definition: pg_trigger.h:104
#define TRIGGER_EVENT_INSTEAD
Definition: trigger.h:62
int16 tgtype
Definition: reltrigger.h:29
Trigger * triggers
Definition: reltrigger.h:48
Buffer tg_trigtuplebuf
Definition: trigger.h:38
#define TRIGGER_TYPE_ROW
Definition: pg_trigger.h:98
TupleTableSlot * es_trig_tuple_slot
Definition: execnodes.h:388
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:339
int numtriggers
Definition: reltrigger.h:49
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:121
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:247
Trigger * tg_trigger
Definition: trigger.h:37
HeapTuple tg_newtuple
Definition: trigger.h:36
static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo, Trigger *trigger, TriggerEvent event, Bitmapset *modifiedCols, HeapTuple oldtup, HeapTuple newtup)
Definition: trigger.c:3014
#define NULL
Definition: c.h:226
TriggerEvent tg_event
Definition: trigger.h:33
#define TRIGGER_TYPE_INSERT
Definition: pg_trigger.h:100
HeapTuple ExecMaterializeSlot(TupleTableSlot *slot)
Definition: execTuples.c:725
Tuplestorestate * tg_oldtable
Definition: trigger.h:40
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:343
#define TRIGGER_EVENT_INSERT
Definition: trigger.h:52
NodeTag type
Definition: trigger.h:32
int i
Tuplestorestate * tg_newtable
Definition: trigger.h:41
static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata, int tgindx, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context)
Definition: trigger.c:2017
FmgrInfo * ri_TrigFunctions
Definition: execnodes.h:340
Relation tg_relation
Definition: trigger.h:34
TupleTableSlot* ExecIRUpdateTriggers ( EState estate,
ResultRelInfo relinfo,
HeapTuple  trigtuple,
TupleTableSlot slot 
)

Definition at line 2741 of file trigger.c.

References EState::es_trig_tuple_slot, ExecCallTriggerFunc(), ExecMaterializeSlot(), ExecSetSlotDescriptor(), ExecStoreTuple(), GetPerTupleMemoryContext, heap_freetuple(), i, InvalidBuffer, NULL, TriggerDesc::numtriggers, RelationGetDescr, ResultRelInfo::ri_RelationDesc, ResultRelInfo::ri_TrigDesc, ResultRelInfo::ri_TrigFunctions, ResultRelInfo::ri_TrigInstrument, T_TriggerData, TriggerData::tg_event, TriggerData::tg_newtable, TriggerData::tg_newtuple, TriggerData::tg_newtuplebuf, TriggerData::tg_oldtable, TriggerData::tg_relation, TriggerData::tg_trigger, TriggerData::tg_trigtuple, TriggerData::tg_trigtuplebuf, Trigger::tgtype, TRIGGER_EVENT_INSTEAD, TRIGGER_EVENT_ROW, TRIGGER_EVENT_UPDATE, TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_MATCHES, TRIGGER_TYPE_ROW, TRIGGER_TYPE_UPDATE, TriggerEnabled(), TriggerDesc::triggers, TupleTableSlot::tts_tupleDescriptor, and TriggerData::type.

Referenced by ExecUpdate().

2743 {
2744  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2745  HeapTuple slottuple = ExecMaterializeSlot(slot);
2746  HeapTuple newtuple = slottuple;
2747  TriggerData LocTriggerData;
2748  HeapTuple oldtuple;
2749  int i;
2750 
2751  LocTriggerData.type = T_TriggerData;
2752  LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
2755  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2756  LocTriggerData.tg_oldtable = NULL;
2757  LocTriggerData.tg_newtable = NULL;
2758  for (i = 0; i < trigdesc->numtriggers; i++)
2759  {
2760  Trigger *trigger = &trigdesc->triggers[i];
2761 
2762  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2766  continue;
2767  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2768  NULL, trigtuple, newtuple))
2769  continue;
2770 
2771  LocTriggerData.tg_trigtuple = trigtuple;
2772  LocTriggerData.tg_newtuple = oldtuple = newtuple;
2773  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2774  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2775  LocTriggerData.tg_trigger = trigger;
2776  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2777  i,
2778  relinfo->ri_TrigFunctions,
2779  relinfo->ri_TrigInstrument,
2780  GetPerTupleMemoryContext(estate));
2781  if (oldtuple != newtuple && oldtuple != slottuple)
2782  heap_freetuple(oldtuple);
2783  if (newtuple == NULL)
2784  return NULL; /* "do nothing" */
2785  }
2786 
2787  if (newtuple != slottuple)
2788  {
2789  /*
2790  * Return the modified tuple using the es_trig_tuple_slot. We assume
2791  * the tuple was allocated in per-tuple memory context, and therefore
2792  * will go away by itself. The tuple table slot should not try to
2793  * clear it.
2794  */
2795  TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2796  TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2797 
2798  if (newslot->tts_tupleDescriptor != tupdesc)
2799  ExecSetSlotDescriptor(newslot, tupdesc);
2800  ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2801  slot = newslot;
2802  }
2803  return slot;
2804 }
#define TRIGGER_EVENT_ROW
Definition: trigger.h:58
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:320
Relation ri_RelationDesc
Definition: execnodes.h:335
#define RelationGetDescr(relation)
Definition: rel.h:425
Buffer tg_newtuplebuf
Definition: trigger.h:39
#define TRIGGER_TYPE_MATCHES(type, level, timing, event)
Definition: pg_trigger.h:146
Instrumentation * ri_TrigInstrument
Definition: execnodes.h:342
#define InvalidBuffer
Definition: buf.h:25
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
HeapTuple tg_trigtuple
Definition: trigger.h:35
#define TRIGGER_TYPE_INSTEAD
Definition: pg_trigger.h:104
#define TRIGGER_EVENT_INSTEAD
Definition: trigger.h:62
int16 tgtype
Definition: reltrigger.h:29
Trigger * triggers
Definition: reltrigger.h:48
Buffer tg_trigtuplebuf
Definition: trigger.h:38
#define TRIGGER_TYPE_ROW
Definition: pg_trigger.h:98
TupleTableSlot * es_trig_tuple_slot
Definition: execnodes.h:388
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:339
int numtriggers
Definition: reltrigger.h:49
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:121
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:247
Trigger * tg_trigger
Definition: trigger.h:37
HeapTuple tg_newtuple
Definition: trigger.h:36
#define TRIGGER_TYPE_UPDATE
Definition: pg_trigger.h:102
static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo, Trigger *trigger, TriggerEvent event, Bitmapset *modifiedCols, HeapTuple oldtup, HeapTuple newtup)
Definition: trigger.c:3014
#define NULL
Definition: c.h:226
TriggerEvent tg_event
Definition: trigger.h:33
HeapTuple ExecMaterializeSlot(TupleTableSlot *slot)
Definition: execTuples.c:725
#define TRIGGER_EVENT_UPDATE
Definition: trigger.h:54
Tuplestorestate * tg_oldtable
Definition: trigger.h:40
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:343
NodeTag type
Definition: trigger.h:32
int i
Tuplestorestate * tg_newtable
Definition: trigger.h:41
static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata, int tgindx, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context)
Definition: trigger.c:2017
FmgrInfo * ri_TrigFunctions
Definition: execnodes.h:340
Relation tg_relation
Definition: trigger.h:34
void FreeTriggerDesc ( TriggerDesc trigdesc)

Definition at line 1881 of file trigger.c.

References i, NULL, TriggerDesc::numtriggers, pfree(), Trigger::tgargs, Trigger::tgattr, Trigger::tgname, Trigger::tgnargs, Trigger::tgnattr, Trigger::tgnewtable, Trigger::tgoldtable, Trigger::tgqual, and TriggerDesc::triggers.

Referenced by RelationBuildTriggers(), and RelationDestroyRelation().

1882 {
1883  Trigger *trigger;
1884  int i;
1885 
1886  if (trigdesc == NULL)
1887  return;
1888 
1889  trigger = trigdesc->triggers;
1890  for (i = 0; i < trigdesc->numtriggers; i++)
1891  {
1892  pfree(trigger->tgname);
1893  if (trigger->tgnattr > 0)
1894  pfree(trigger->tgattr);
1895  if (trigger->tgnargs > 0)
1896  {
1897  while (--(trigger->tgnargs) >= 0)
1898  pfree(trigger->tgargs[trigger->tgnargs]);
1899  pfree(trigger->tgargs);
1900  }
1901  if (trigger->tgqual)
1902  pfree(trigger->tgqual);
1903  if (trigger->tgoldtable)
1904  pfree(trigger->tgoldtable);
1905  if (trigger->tgnewtable)
1906  pfree(trigger->tgnewtable);
1907  trigger++;
1908  }
1909  pfree(trigdesc->triggers);
1910  pfree(trigdesc);
1911 }
void pfree(void *pointer)
Definition: mcxt.c:992
char * tgqual
Definition: reltrigger.h:41
char * tgname
Definition: reltrigger.h:27
Trigger * triggers
Definition: reltrigger.h:48
int numtriggers
Definition: reltrigger.h:49
char ** tgargs
Definition: reltrigger.h:40
int16 * tgattr
Definition: reltrigger.h:39
char * tgnewtable
Definition: reltrigger.h:43
#define NULL
Definition: c.h:226
int16 tgnattr
Definition: reltrigger.h:38
int i
int16 tgnargs
Definition: reltrigger.h:37
char * tgoldtable
Definition: reltrigger.h:42
Oid get_trigger_oid ( Oid  relid,
const char *  name,
bool  missing_ok 
)

Definition at line 1268 of file trigger.c.

References AccessShareLock, Anum_pg_trigger_tgname, Anum_pg_trigger_tgrelid, BTEqualStrategyNumber, CStringGetDatum, ereport, errcode(), errmsg(), ERROR, get_rel_name(), heap_close, heap_open(), HeapTupleGetOid, HeapTupleIsValid, InvalidOid, NULL, ObjectIdGetDatum, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), TriggerRelationId, and TriggerRelidNameIndexId.

Referenced by get_object_address_relobject().

1269 {
1270  Relation tgrel;
1271  ScanKeyData skey[2];
1272  SysScanDesc tgscan;
1273  HeapTuple tup;
1274  Oid oid;
1275 
1276  /*
1277  * Find the trigger, verify permissions, set up object address
1278  */
1280 
1281  ScanKeyInit(&skey[0],
1283  BTEqualStrategyNumber, F_OIDEQ,
1284  ObjectIdGetDatum(relid));
1285  ScanKeyInit(&skey[1],
1287  BTEqualStrategyNumber, F_NAMEEQ,
1288  CStringGetDatum(trigname));
1289 
1290  tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1291  NULL, 2, skey);
1292 
1293  tup = systable_getnext(tgscan);
1294 
1295  if (!HeapTupleIsValid(tup))
1296  {
1297  if (!missing_ok)
1298  ereport(ERROR,
1299  (errcode(ERRCODE_UNDEFINED_OBJECT),
1300  errmsg("trigger \"%s\" for table \"%s\" does not exist",
1301  trigname, get_rel_name(relid))));
1302  oid = InvalidOid;
1303  }
1304  else
1305  {
1306  oid = HeapTupleGetOid(tup);
1307  }
1308 
1309  systable_endscan(tgscan);
1310  heap_close(tgrel, AccessShareLock);
1311  return oid;
1312 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:322
#define TriggerRelidNameIndexId
Definition: indexing.h:242
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define CStringGetDatum(X)
Definition: postgres.h:586
#define ereport(elevel, rest)
Definition: elog.h:122
#define Anum_pg_trigger_tgrelid
Definition: pg_trigger.h:79
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define Anum_pg_trigger_tgname
Definition: pg_trigger.h:80
#define TriggerRelationId
Definition: pg_trigger.h:34
int errmsg(const char *fmt,...)
Definition: elog.c:797
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1694
#define BTEqualStrategyNumber
Definition: stratnum.h:31
void RelationBuildTriggers ( Relation  relation)

Definition at line 1598 of file trigger.c.

References AccessShareLock, Anum_pg_trigger_tgargs, Anum_pg_trigger_tgnewtable, Anum_pg_trigger_tgoldtable, Anum_pg_trigger_tgqual, Anum_pg_trigger_tgrelid, BTEqualStrategyNumber, CacheMemoryContext, CopyTriggerDesc(), DatumGetByteaP, DatumGetCString, DirectFunctionCall1, elog, ERROR, fastgetattr, FreeTriggerDesc(), GETSTRUCT, heap_close, heap_open(), HeapTupleGetOid, HeapTupleIsValid, i, MemoryContextSwitchTo(), NameGetDatum, nameout(), NULL, TriggerDesc::numtriggers, ObjectIdGetDatum, palloc(), palloc0(), pfree(), pstrdup(), RelationData::rd_att, RelationGetRelationName, RelationGetRelid, repalloc(), ScanKeyInit(), SetTriggerFlags(), systable_beginscan(), systable_endscan(), systable_getnext(), TextDatumGetCString, Trigger::tgargs, Trigger::tgattr, Trigger::tgconstraint, Trigger::tgconstrindid, Trigger::tgconstrrelid, Trigger::tgdeferrable, Trigger::tgenabled, Trigger::tgfoid, Trigger::tginitdeferred, Trigger::tgisinternal, Trigger::tgname, Trigger::tgnargs, Trigger::tgnattr, Trigger::tgnewtable, Trigger::tgoid, Trigger::tgoldtable, Trigger::tgqual, Trigger::tgtype, RelationData::trigdesc, TriggerRelationId, TriggerRelidNameIndexId, TriggerDesc::triggers, val, and VARDATA.

Referenced by RelationBuildDesc(), and RelationCacheInitializePhase3().

1599 {
1600  TriggerDesc *trigdesc;
1601  int numtrigs;
1602  int maxtrigs;
1603  Trigger *triggers;
1604  Relation tgrel;
1605  ScanKeyData skey;
1606  SysScanDesc tgscan;
1607  HeapTuple htup;
1608  MemoryContext oldContext;
1609  int i;
1610 
1611  /*
1612  * Allocate a working array to hold the triggers (the array is extended if
1613  * necessary)
1614  */
1615  maxtrigs = 16;
1616  triggers = (Trigger *) palloc(maxtrigs * sizeof(Trigger));
1617  numtrigs = 0;
1618 
1619  /*
1620  * Note: since we scan the triggers using TriggerRelidNameIndexId, we will
1621  * be reading the triggers in name order, except possibly during
1622  * emergency-recovery operations (ie, IgnoreSystemIndexes). This in turn
1623  * ensures that triggers will be fired in name order.
1624  */
1625  ScanKeyInit(&skey,
1627  BTEqualStrategyNumber, F_OIDEQ,
1628  ObjectIdGetDatum(RelationGetRelid(relation)));
1629 
1631  tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1632  NULL, 1, &skey);
1633 
1634  while (HeapTupleIsValid(htup = systable_getnext(tgscan)))
1635  {
1636  Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
1637  Trigger *build;
1638  Datum datum;
1639  bool isnull;
1640 
1641  if (numtrigs >= maxtrigs)
1642  {
1643  maxtrigs *= 2;
1644  triggers = (Trigger *) repalloc(triggers, maxtrigs * sizeof(Trigger));
1645  }
1646  build = &(triggers[numtrigs]);
1647 
1648  build->tgoid = HeapTupleGetOid(htup);
1650  NameGetDatum(&pg_trigger->tgname)));
1651  build->tgfoid = pg_trigger->tgfoid;
1652  build->tgtype = pg_trigger->tgtype;
1653  build->tgenabled = pg_trigger->tgenabled;
1654  build->tgisinternal = pg_trigger->tgisinternal;
1655  build->tgconstrrelid = pg_trigger->tgconstrrelid;
1656  build->tgconstrindid = pg_trigger->tgconstrindid;
1657  build->tgconstraint = pg_trigger->tgconstraint;
1658  build->tgdeferrable = pg_trigger->tgdeferrable;
1659  build->tginitdeferred = pg_trigger->tginitdeferred;
1660  build->tgnargs = pg_trigger->tgnargs;
1661  /* tgattr is first var-width field, so OK to access directly */
1662  build->tgnattr = pg_trigger->tgattr.dim1;
1663  if (build->tgnattr > 0)
1664  {
1665  build->tgattr = (int16 *) palloc(build->tgnattr * sizeof(int16));
1666  memcpy(build->tgattr, &(pg_trigger->tgattr.values),
1667  build->tgnattr * sizeof(int16));
1668  }
1669  else
1670  build->tgattr = NULL;
1671  if (build->tgnargs > 0)
1672  {
1673  bytea *val;
1674  char *p;
1675 
1676  val = DatumGetByteaP(fastgetattr(htup,
1678  tgrel->rd_att, &isnull));
1679  if (isnull)
1680  elog(ERROR, "tgargs is null in trigger for relation \"%s\"",
1681  RelationGetRelationName(relation));
1682  p = (char *) VARDATA(val);
1683  build->tgargs = (char **) palloc(build->tgnargs * sizeof(char *));
1684  for (i = 0; i < build->tgnargs; i++)
1685  {
1686  build->tgargs[i] = pstrdup(p);
1687  p += strlen(p) + 1;
1688  }
1689  }
1690  else
1691  build->tgargs = NULL;
1692 
1694  tgrel->rd_att, &isnull);
1695  if (!isnull)
1696  build->tgoldtable =
1698  else
1699  build->tgoldtable = NULL;
1700 
1702  tgrel->rd_att, &isnull);
1703  if (!isnull)
1704  build->tgnewtable =
1706  else
1707  build->tgnewtable = NULL;
1708 
1709  datum = fastgetattr(htup, Anum_pg_trigger_tgqual,
1710  tgrel->rd_att, &isnull);
1711  if (!isnull)
1712  build->tgqual = TextDatumGetCString(datum);
1713  else
1714  build->tgqual = NULL;
1715 
1716  numtrigs++;
1717  }
1718 
1719  systable_endscan(tgscan);
1720  heap_close(tgrel, AccessShareLock);
1721 
1722  /* There might not be any triggers */
1723  if (numtrigs == 0)
1724  {
1725  pfree(triggers);
1726  return;
1727  }
1728 
1729  /* Build trigdesc */
1730  trigdesc = (TriggerDesc *) palloc0(sizeof(TriggerDesc));
1731  trigdesc->triggers = triggers;
1732  trigdesc->numtriggers = numtrigs;
1733  for (i = 0; i < numtrigs; i++)
1734  SetTriggerFlags(trigdesc, &(triggers[i]));
1735 
1736  /* Copy completed trigdesc into cache storage */
1738  relation->trigdesc = CopyTriggerDesc(trigdesc);
1739  MemoryContextSwitchTo(oldContext);
1740 
1741  /* Release working memory */
1742  FreeTriggerDesc(trigdesc);
1743 }
signed short int16
Definition: c.h:252
#define NameGetDatum(X)
Definition: postgres.h:603
#define VARDATA(PTR)
Definition: postgres.h:305
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:719
Oid tgfoid
Definition: reltrigger.h:28
char * pstrdup(const char *in)
Definition: mcxt.c:1165
#define Anum_pg_trigger_tgqual
Definition: pg_trigger.h:93
Oid tgoid
Definition: reltrigger.h:25
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
bool tgisinternal
Definition: reltrigger.h:31
#define heap_close(r, l)
Definition: