1 /*-------------------------------------------------------------------------
4 * PostgreSQL TRIGGERs support code.
6 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.111 2002/04/01 22:36:10 tgl Exp $
12 *-------------------------------------------------------------------------
16 #include "access/genam.h"
17 #include "access/heapam.h"
18 #include "catalog/catalog.h"
19 #include "catalog/catname.h"
20 #include "catalog/indexing.h"
21 #include "catalog/namespace.h"
22 #include "catalog/pg_language.h"
23 #include "catalog/pg_proc.h"
24 #include "catalog/pg_trigger.h"
25 #include "commands/comment.h"
26 #include "commands/trigger.h"
27 #include "executor/executor.h"
28 #include "miscadmin.h"
29 #include "utils/acl.h"
30 #include "utils/builtins.h"
31 #include "utils/fmgroids.h"
32 #include "utils/inval.h"
33 #include "utils/lsyscache.h"
34 #include "utils/syscache.h"
37 static void InsertTrigger(TriggerDesc *trigdesc, Trigger *trigger, int indx);
38 static HeapTuple GetTupleForTrigger(EState *estate,
39 ResultRelInfo *relinfo,
41 TupleTableSlot **newSlot);
42 static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata,
44 MemoryContext per_tuple_context);
45 static void DeferredTriggerSaveEvent(ResultRelInfo *relinfo, int event,
46 HeapTuple oldtup, HeapTuple newtup);
47 static void DeferredTriggerExecute(DeferredTriggerEvent event, int itemno,
48 Relation rel, FmgrInfo *finfo,
49 MemoryContext per_tuple_context);
53 CreateTrigger(CreateTrigStmt *stmt)
56 int16 tgattr[FUNC_MAX_ARGS];
57 Datum values[Natts_pg_trigger];
58 char nulls[Natts_pg_trigger];
65 Relation idescs[Num_pg_trigger_indices];
66 Relation ridescs[Num_pg_class_indices];
67 Oid fargtypes[FUNC_MAX_ARGS];
72 char constrtrigname[NAMEDATALEN];
73 char *constrname = "";
74 Oid constrrelid = InvalidOid;
76 rel = heap_openrv(stmt->relation, AccessExclusiveLock);
78 if (rel->rd_rel->relkind != RELKIND_RELATION)
79 elog(ERROR, "CreateTrigger: relation \"%s\" is not a table",
80 stmt->relation->relname);
82 if (!allowSystemTableMods && IsSystemRelationName(stmt->relation->relname))
83 elog(ERROR, "CreateTrigger: can't create trigger for system relation %s",
84 stmt->relation->relname);
86 if (pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
87 stmt->isconstraint ? ACL_REFERENCES : ACL_TRIGGER)
89 elog(ERROR, "permission denied");
92 * If trigger is a constraint, user trigger name as constraint name
93 * and build a unique trigger name instead.
95 if (stmt->isconstraint)
97 constrname = stmt->trigname;
98 stmt->trigname = constrtrigname;
99 sprintf(constrtrigname, "RI_ConstraintTrigger_%u", newoid());
101 if (stmt->constrrel != NULL)
102 constrrelid = RangeVarGetRelid(stmt->constrrel, false);
104 constrrelid = InvalidOid;
107 TRIGGER_CLEAR_TYPE(tgtype);
109 TRIGGER_SETT_BEFORE(tgtype);
111 TRIGGER_SETT_ROW(tgtype);
113 elog(ERROR, "CreateTrigger: STATEMENT triggers are unimplemented, yet");
115 for (i = 0; i < 3 && stmt->actions[i]; i++)
117 switch (stmt->actions[i])
120 if (TRIGGER_FOR_INSERT(tgtype))
121 elog(ERROR, "CreateTrigger: double INSERT event specified");
122 TRIGGER_SETT_INSERT(tgtype);
125 if (TRIGGER_FOR_DELETE(tgtype))
126 elog(ERROR, "CreateTrigger: double DELETE event specified");
127 TRIGGER_SETT_DELETE(tgtype);
130 if (TRIGGER_FOR_UPDATE(tgtype))
131 elog(ERROR, "CreateTrigger: double UPDATE event specified");
132 TRIGGER_SETT_UPDATE(tgtype);
135 elog(ERROR, "CreateTrigger: unknown event specified");
141 * Scan pg_trigger for existing triggers on relation. NOTE that this
142 * is cool only because we have AccessExclusiveLock on the relation,
143 * so the trigger set won't be changing underneath us.
145 tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
146 ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
148 ObjectIdGetDatum(RelationGetRelid(rel)));
149 tgscan = systable_beginscan(tgrel, TriggerRelidIndex, true,
150 SnapshotNow, 1, &key);
151 while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
153 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
155 if (namestrcmp(&(pg_trigger->tgname), stmt->trigname) == 0)
156 elog(ERROR, "CreateTrigger: trigger %s already defined on relation %s",
157 stmt->trigname, stmt->relation->relname);
160 systable_endscan(tgscan);
163 * Find and validate the trigger function.
165 MemSet(fargtypes, 0, FUNC_MAX_ARGS * sizeof(Oid));
166 tuple = SearchSysCache(PROCNAME,
167 PointerGetDatum(stmt->funcname),
169 PointerGetDatum(fargtypes),
171 if (!HeapTupleIsValid(tuple))
172 elog(ERROR, "CreateTrigger: function %s() does not exist",
174 if (((Form_pg_proc) GETSTRUCT(tuple))->prorettype != 0)
175 elog(ERROR, "CreateTrigger: function %s() must return OPAQUE",
177 funcoid = tuple->t_data->t_oid;
178 funclang = ((Form_pg_proc) GETSTRUCT(tuple))->prolang;
179 ReleaseSysCache(tuple);
181 if (funclang != ClanguageId && funclang != INTERNALlanguageId)
185 langTup = SearchSysCache(LANGOID,
186 ObjectIdGetDatum(funclang),
188 if (!HeapTupleIsValid(langTup))
189 elog(ERROR, "CreateTrigger: cache lookup for language %u failed",
191 if (((Form_pg_language) GETSTRUCT(langTup))->lanispl == false)
192 elog(ERROR, "CreateTrigger: only internal, C and PL functions are supported");
193 ReleaseSysCache(langTup);
197 * Build the new pg_trigger tuple.
199 MemSet(nulls, ' ', Natts_pg_trigger * sizeof(char));
201 values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
202 values[Anum_pg_trigger_tgname - 1] = DirectFunctionCall1(namein,
203 CStringGetDatum(stmt->trigname));
204 values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid);
205 values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype);
206 values[Anum_pg_trigger_tgenabled - 1] = BoolGetDatum(true);
207 values[Anum_pg_trigger_tgisconstraint - 1] = BoolGetDatum(stmt->isconstraint);
208 values[Anum_pg_trigger_tgconstrname - 1] = PointerGetDatum(constrname);
209 values[Anum_pg_trigger_tgconstrrelid - 1] = ObjectIdGetDatum(constrrelid);
210 values[Anum_pg_trigger_tgdeferrable - 1] = BoolGetDatum(stmt->deferrable);
211 values[Anum_pg_trigger_tginitdeferred - 1] = BoolGetDatum(stmt->initdeferred);
217 int16 nargs = length(stmt->args);
220 foreach(le, stmt->args)
222 char *ar = ((Value *) lfirst(le))->val.str;
224 len += strlen(ar) + 4;
231 args = (char *) palloc(len + 1);
233 foreach(le, stmt->args)
235 char *s = ((Value *) lfirst(le))->val.str;
236 char *d = args + strlen(args);
246 values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(nargs);
247 values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
248 CStringGetDatum(args));
252 values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(0);
253 values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
254 CStringGetDatum(""));
256 MemSet(tgattr, 0, FUNC_MAX_ARGS * sizeof(int16));
257 values[Anum_pg_trigger_tgattr - 1] = PointerGetDatum(tgattr);
259 tuple = heap_formtuple(tgrel->rd_att, values, nulls);
262 * Insert tuple into pg_trigger.
264 heap_insert(tgrel, tuple);
265 CatalogOpenIndices(Num_pg_trigger_indices, Name_pg_trigger_indices, idescs);
266 CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple);
267 CatalogCloseIndices(Num_pg_trigger_indices, idescs);
268 heap_freetuple(tuple);
269 heap_close(tgrel, RowExclusiveLock);
271 pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
272 pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1]));
275 * Update relation's pg_class entry. Crucial side-effect: other
276 * backends (and this one too!) are sent SI message to make them
277 * rebuild relcache entries.
279 pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
280 tuple = SearchSysCacheCopy(RELOID,
281 ObjectIdGetDatum(RelationGetRelid(rel)),
283 if (!HeapTupleIsValid(tuple))
284 elog(ERROR, "CreateTrigger: relation %s not found in pg_class",
285 stmt->relation->relname);
287 ((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1;
288 simple_heap_update(pgrel, &tuple->t_self, tuple);
289 CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
290 CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
291 CatalogCloseIndices(Num_pg_class_indices, ridescs);
292 heap_freetuple(tuple);
293 heap_close(pgrel, RowExclusiveLock);
296 * We used to try to update the rel's relcache entry here, but that's
297 * fairly pointless since it will happen as a byproduct of the
298 * upcoming CommandCounterIncrement...
301 /* Keep lock on target rel until end of xact */
302 heap_close(rel, NoLock);
306 * DropTrigger - drop an individual trigger by name
309 DropTrigger(Oid relid, const char *trigname)
317 Relation ridescs[Num_pg_class_indices];
321 rel = heap_open(relid, AccessExclusiveLock);
323 if (rel->rd_rel->relkind != RELKIND_RELATION)
324 elog(ERROR, "DropTrigger: relation \"%s\" is not a table",
325 RelationGetRelationName(rel));
327 if (!allowSystemTableMods && IsSystemRelationName(RelationGetRelationName(rel)))
328 elog(ERROR, "DropTrigger: can't drop trigger for system relation %s",
329 RelationGetRelationName(rel));
331 if (!pg_class_ownercheck(relid, GetUserId()))
332 elog(ERROR, "%s: %s", RelationGetRelationName(rel),
333 aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
336 * Search pg_trigger, delete target trigger, count remaining triggers
337 * for relation. Note this is OK only because we have
338 * AccessExclusiveLock on the rel, so no one else is creating/deleting
339 * triggers on this rel at the same time.
341 tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
342 ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
344 ObjectIdGetDatum(relid));
345 tgscan = systable_beginscan(tgrel, TriggerRelidIndex, true,
346 SnapshotNow, 1, &key);
347 while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
349 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
351 if (namestrcmp(&(pg_trigger->tgname), trigname) == 0)
353 /* Delete any comments associated with this trigger */
354 DeleteComments(tuple->t_data->t_oid, RelationGetRelid(tgrel));
356 simple_heap_delete(tgrel, &tuple->t_self);
362 systable_endscan(tgscan);
363 heap_close(tgrel, RowExclusiveLock);
366 elog(ERROR, "DropTrigger: there is no trigger %s on relation %s",
367 trigname, RelationGetRelationName(rel));
368 if (found > 1) /* shouldn't happen */
369 elog(NOTICE, "DropTrigger: found (and deleted) %d triggers %s on relation %s",
370 found, trigname, RelationGetRelationName(rel));
373 * Update relation's pg_class entry. Crucial side-effect: other
374 * backends (and this one too!) are sent SI message to make them
375 * rebuild relcache entries.
377 pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
378 tuple = SearchSysCacheCopy(RELOID,
379 ObjectIdGetDatum(relid),
381 if (!HeapTupleIsValid(tuple))
382 elog(ERROR, "DropTrigger: relation %s not found in pg_class",
383 RelationGetRelationName(rel));
385 ((Form_pg_class) GETSTRUCT(tuple))->reltriggers = remaining;
386 simple_heap_update(pgrel, &tuple->t_self, tuple);
387 CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
388 CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
389 CatalogCloseIndices(Num_pg_class_indices, ridescs);
390 heap_freetuple(tuple);
391 heap_close(pgrel, RowExclusiveLock);
393 /* Keep lock on target rel until end of xact */
394 heap_close(rel, NoLock);
398 * Remove all triggers for a relation that's being deleted.
401 RelationRemoveTriggers(Relation rel)
409 tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
410 ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
412 ObjectIdGetDatum(RelationGetRelid(rel)));
413 tgscan = systable_beginscan(tgrel, TriggerRelidIndex, true,
414 SnapshotNow, 1, &key);
416 while (HeapTupleIsValid(tup = systable_getnext(tgscan)))
418 /* Delete any comments associated with this trigger */
419 DeleteComments(tup->t_data->t_oid, RelationGetRelid(tgrel));
421 simple_heap_delete(tgrel, &tup->t_self);
426 systable_endscan(tgscan);
429 * If we deleted any triggers, must update pg_class entry and advance
430 * command counter to make the updated entry visible. This is fairly
431 * annoying, since we'e just going to drop the durn thing later, but
432 * it's necessary to have a consistent state in case we do
433 * CommandCounterIncrement() below --- if RelationBuildTriggers()
434 * runs, it will complain otherwise. Perhaps RelationBuildTriggers()
435 * shouldn't be so picky...
440 Relation ridescs[Num_pg_class_indices];
442 pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
443 tup = SearchSysCacheCopy(RELOID,
444 ObjectIdGetDatum(RelationGetRelid(rel)),
446 if (!HeapTupleIsValid(tup))
447 elog(ERROR, "RelationRemoveTriggers: relation %u not found in pg_class",
448 RelationGetRelid(rel));
450 ((Form_pg_class) GETSTRUCT(tup))->reltriggers = 0;
451 simple_heap_update(pgrel, &tup->t_self, tup);
452 CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
453 CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tup);
454 CatalogCloseIndices(Num_pg_class_indices, ridescs);
456 heap_close(pgrel, RowExclusiveLock);
457 CommandCounterIncrement();
461 * Also drop all constraint triggers referencing this relation
463 ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgconstrrelid,
465 ObjectIdGetDatum(RelationGetRelid(rel)));
466 tgscan = systable_beginscan(tgrel, TriggerConstrRelidIndex, true,
467 SnapshotNow, 1, &key);
469 while (HeapTupleIsValid(tup = systable_getnext(tgscan)))
471 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tup);
473 elog(NOTICE, "DROP TABLE implicitly drops referential integrity trigger from table \"%s\"",
474 get_rel_name(pg_trigger->tgrelid));
476 DropTrigger(pg_trigger->tgrelid, NameStr(pg_trigger->tgname));
479 * Need to do a command counter increment here to show up new
480 * pg_class.reltriggers in the next loop iteration (in case there
481 * are multiple referential integrity action triggers for the same
482 * FK table defined on the PK table).
484 CommandCounterIncrement();
486 systable_endscan(tgscan);
488 heap_close(tgrel, RowExclusiveLock);
492 * Build trigger data to attach to the given relcache entry.
494 * Note that trigger data must be allocated in CacheMemoryContext
495 * to ensure it survives as long as the relcache entry. But we
496 * are probably running in a less long-lived working context.
499 RelationBuildTriggers(Relation relation)
501 TriggerDesc *trigdesc;
502 int ntrigs = relation->rd_rel->reltriggers;
503 Trigger *triggers = NULL;
512 ScanKeyEntryInitialize(&skey,
514 (AttrNumber) Anum_pg_trigger_tgrelid,
515 (RegProcedure) F_OIDEQ,
516 ObjectIdGetDatum(RelationGetRelid(relation)));
518 tgrel = heap_openr(TriggerRelationName, AccessShareLock);
519 tgscan = systable_beginscan(tgrel, TriggerRelidIndex, true,
520 SnapshotNow, 1, &skey);
522 while (HeapTupleIsValid(htup = systable_getnext(tgscan)))
524 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
528 elog(ERROR, "RelationBuildTriggers: unexpected record found for rel %s",
529 RelationGetRelationName(relation));
531 if (triggers == NULL)
532 triggers = (Trigger *) MemoryContextAlloc(CacheMemoryContext,
535 triggers = (Trigger *) repalloc(triggers,
536 (found + 1) * sizeof(Trigger));
537 build = &(triggers[found]);
539 build->tgoid = htup->t_data->t_oid;
540 build->tgname = MemoryContextStrdup(CacheMemoryContext,
541 DatumGetCString(DirectFunctionCall1(nameout,
542 NameGetDatum(&pg_trigger->tgname))));
543 build->tgfoid = pg_trigger->tgfoid;
544 build->tgtype = pg_trigger->tgtype;
545 build->tgenabled = pg_trigger->tgenabled;
546 build->tgisconstraint = pg_trigger->tgisconstraint;
547 build->tgconstrrelid = pg_trigger->tgconstrrelid;
548 build->tgdeferrable = pg_trigger->tgdeferrable;
549 build->tginitdeferred = pg_trigger->tginitdeferred;
550 build->tgnargs = pg_trigger->tgnargs;
551 memcpy(build->tgattr, &(pg_trigger->tgattr),
552 FUNC_MAX_ARGS * sizeof(int16));
553 if (build->tgnargs > 0)
558 val = (struct varlena *) fastgetattr(htup,
559 Anum_pg_trigger_tgargs,
560 tgrel->rd_att, &isnull);
562 elog(ERROR, "RelationBuildTriggers: tgargs IS NULL for rel %s",
563 RelationGetRelationName(relation));
564 p = (char *) VARDATA(val);
565 build->tgargs = (char **)
566 MemoryContextAlloc(CacheMemoryContext,
567 build->tgnargs * sizeof(char *));
568 for (i = 0; i < build->tgnargs; i++)
570 build->tgargs[i] = MemoryContextStrdup(CacheMemoryContext,
576 build->tgargs = NULL;
581 systable_endscan(tgscan);
582 heap_close(tgrel, AccessShareLock);
585 elog(ERROR, "RelationBuildTriggers: %d record(s) not found for rel %s",
587 RelationGetRelationName(relation));
590 trigdesc = (TriggerDesc *) MemoryContextAlloc(CacheMemoryContext,
591 sizeof(TriggerDesc));
592 MemSet(trigdesc, 0, sizeof(TriggerDesc));
593 trigdesc->triggers = triggers;
594 trigdesc->numtriggers = ntrigs;
595 for (found = 0; found < ntrigs; found++)
596 InsertTrigger(trigdesc, &(triggers[found]), found);
598 relation->trigdesc = trigdesc;
601 /* Insert the given trigger into the appropriate index list(s) for it */
603 InsertTrigger(TriggerDesc *trigdesc, Trigger *trigger, int indx)
609 if (TRIGGER_FOR_ROW(trigger->tgtype))
612 if (TRIGGER_FOR_BEFORE(trigger->tgtype))
614 n = trigdesc->n_before_row;
615 t = trigdesc->tg_before_row;
619 n = trigdesc->n_after_row;
620 t = trigdesc->tg_after_row;
625 /* STATEMENT trigger */
626 if (TRIGGER_FOR_BEFORE(trigger->tgtype))
628 n = trigdesc->n_before_statement;
629 t = trigdesc->tg_before_statement;
633 n = trigdesc->n_after_statement;
634 t = trigdesc->tg_after_statement;
638 if (TRIGGER_FOR_INSERT(trigger->tgtype))
640 tp = &(t[TRIGGER_EVENT_INSERT]);
642 *tp = (int *) MemoryContextAlloc(CacheMemoryContext,
645 *tp = (int *) repalloc(*tp, (n[TRIGGER_EVENT_INSERT] + 1) *
647 (*tp)[n[TRIGGER_EVENT_INSERT]] = indx;
648 (n[TRIGGER_EVENT_INSERT])++;
651 if (TRIGGER_FOR_DELETE(trigger->tgtype))
653 tp = &(t[TRIGGER_EVENT_DELETE]);
655 *tp = (int *) MemoryContextAlloc(CacheMemoryContext,
658 *tp = (int *) repalloc(*tp, (n[TRIGGER_EVENT_DELETE] + 1) *
660 (*tp)[n[TRIGGER_EVENT_DELETE]] = indx;
661 (n[TRIGGER_EVENT_DELETE])++;
664 if (TRIGGER_FOR_UPDATE(trigger->tgtype))
666 tp = &(t[TRIGGER_EVENT_UPDATE]);
668 *tp = (int *) MemoryContextAlloc(CacheMemoryContext,
671 *tp = (int *) repalloc(*tp, (n[TRIGGER_EVENT_UPDATE] + 1) *
673 (*tp)[n[TRIGGER_EVENT_UPDATE]] = indx;
674 (n[TRIGGER_EVENT_UPDATE])++;
679 FreeTriggerDesc(TriggerDesc *trigdesc)
685 if (trigdesc == NULL)
688 t = trigdesc->tg_before_statement;
689 for (i = 0; i < TRIGGER_NUM_EVENT_CLASSES; i++)
692 t = trigdesc->tg_before_row;
693 for (i = 0; i < TRIGGER_NUM_EVENT_CLASSES; i++)
696 t = trigdesc->tg_after_row;
697 for (i = 0; i < TRIGGER_NUM_EVENT_CLASSES; i++)
700 t = trigdesc->tg_after_statement;
701 for (i = 0; i < TRIGGER_NUM_EVENT_CLASSES; i++)
705 trigger = trigdesc->triggers;
706 for (i = 0; i < trigdesc->numtriggers; i++)
708 pfree(trigger->tgname);
709 if (trigger->tgnargs > 0)
711 while (--(trigger->tgnargs) >= 0)
712 pfree(trigger->tgargs[trigger->tgnargs]);
713 pfree(trigger->tgargs);
717 pfree(trigdesc->triggers);
722 equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
728 * We need not examine the "index" data, just the trigger array
729 * itself; if we have the same triggers with the same types, the
730 * derived index data should match.
732 if (trigdesc1 != NULL)
734 if (trigdesc2 == NULL)
736 if (trigdesc1->numtriggers != trigdesc2->numtriggers)
738 for (i = 0; i < trigdesc1->numtriggers; i++)
740 Trigger *trig1 = trigdesc1->triggers + i;
741 Trigger *trig2 = NULL;
744 * We can't assume that the triggers are always read from
745 * pg_trigger in the same order; so use the trigger OIDs to
746 * identify the triggers to compare. (We assume here that the
747 * same OID won't appear twice in either trigger set.)
749 for (j = 0; j < trigdesc2->numtriggers; j++)
751 trig2 = trigdesc2->triggers + j;
752 if (trig1->tgoid == trig2->tgoid)
755 if (j >= trigdesc2->numtriggers)
757 if (strcmp(trig1->tgname, trig2->tgname) != 0)
759 if (trig1->tgfoid != trig2->tgfoid)
761 if (trig1->tgtype != trig2->tgtype)
763 if (trig1->tgenabled != trig2->tgenabled)
765 if (trig1->tgisconstraint != trig2->tgisconstraint)
767 if (trig1->tgconstrrelid != trig2->tgconstrrelid)
769 if (trig1->tgdeferrable != trig2->tgdeferrable)
771 if (trig1->tginitdeferred != trig2->tginitdeferred)
773 if (trig1->tgnargs != trig2->tgnargs)
775 if (memcmp(trig1->tgattr, trig2->tgattr,
776 sizeof(trig1->tgattr)) != 0)
778 for (j = 0; j < trig1->tgnargs; j++)
779 if (strcmp(trig1->tgargs[j], trig2->tgargs[j]) != 0)
783 else if (trigdesc2 != NULL)
789 * Call a trigger function.
791 * trigdata: trigger descriptor.
792 * finfo: possibly-cached call info for the function.
793 * per_tuple_context: memory context to execute the function in.
795 * Returns the tuple (or NULL) as returned by the function.
798 ExecCallTriggerFunc(TriggerData *trigdata,
800 MemoryContext per_tuple_context)
802 FunctionCallInfoData fcinfo;
804 MemoryContext oldContext;
807 * We cache fmgr lookup info, to avoid making the lookup again on each
810 if (finfo->fn_oid == InvalidOid)
811 fmgr_info(trigdata->tg_trigger->tgfoid, finfo);
813 Assert(finfo->fn_oid == trigdata->tg_trigger->tgfoid);
816 * Do the function evaluation in the per-tuple memory context, so that
817 * leaked memory will be reclaimed once per tuple. Note in particular
818 * that any new tuple created by the trigger function will live till
819 * the end of the tuple cycle.
821 oldContext = MemoryContextSwitchTo(per_tuple_context);
824 * Call the function, passing no arguments but setting a context.
826 MemSet(&fcinfo, 0, sizeof(fcinfo));
828 fcinfo.flinfo = finfo;
829 fcinfo.context = (Node *) trigdata;
831 result = FunctionCallInvoke(&fcinfo);
833 MemoryContextSwitchTo(oldContext);
836 * Trigger protocol allows function to return a null pointer, but NOT
837 * to set the isnull result flag.
840 elog(ERROR, "ExecCallTriggerFunc: function %u returned NULL",
841 fcinfo.flinfo->fn_oid);
843 return (HeapTuple) DatumGetPointer(result);
847 ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
850 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
851 int ntrigs = trigdesc->n_before_row[TRIGGER_EVENT_INSERT];
852 int *tgindx = trigdesc->tg_before_row[TRIGGER_EVENT_INSERT];
853 HeapTuple newtuple = trigtuple;
855 TriggerData LocTriggerData;
858 /* Allocate cache space for fmgr lookup info, if not done yet */
859 if (relinfo->ri_TrigFunctions == NULL)
861 relinfo->ri_TrigFunctions = (FmgrInfo *)
862 palloc(trigdesc->numtriggers * sizeof(FmgrInfo));
863 MemSet(relinfo->ri_TrigFunctions, 0,
864 trigdesc->numtriggers * sizeof(FmgrInfo));
867 LocTriggerData.type = T_TriggerData;
868 LocTriggerData.tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE;
869 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
870 LocTriggerData.tg_newtuple = NULL;
871 for (i = 0; i < ntrigs; i++)
873 Trigger *trigger = &trigdesc->triggers[tgindx[i]];
875 if (!trigger->tgenabled)
877 LocTriggerData.tg_trigtuple = oldtuple = newtuple;
878 LocTriggerData.tg_trigger = trigger;
879 newtuple = ExecCallTriggerFunc(&LocTriggerData,
880 relinfo->ri_TrigFunctions + tgindx[i],
881 GetPerTupleMemoryContext(estate));
882 if (oldtuple != newtuple && oldtuple != trigtuple)
883 heap_freetuple(oldtuple);
884 if (newtuple == NULL)
891 ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo,
894 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
896 if (trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0)
897 DeferredTriggerSaveEvent(relinfo, TRIGGER_EVENT_INSERT,
902 ExecBRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
905 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
906 int ntrigs = trigdesc->n_before_row[TRIGGER_EVENT_DELETE];
907 int *tgindx = trigdesc->tg_before_row[TRIGGER_EVENT_DELETE];
908 TriggerData LocTriggerData;
910 HeapTuple newtuple = NULL;
911 TupleTableSlot *newSlot;
914 trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, &newSlot);
915 if (trigtuple == NULL)
918 /* Allocate cache space for fmgr lookup info, if not done yet */
919 if (relinfo->ri_TrigFunctions == NULL)
921 relinfo->ri_TrigFunctions = (FmgrInfo *)
922 palloc(trigdesc->numtriggers * sizeof(FmgrInfo));
923 MemSet(relinfo->ri_TrigFunctions, 0,
924 trigdesc->numtriggers * sizeof(FmgrInfo));
927 LocTriggerData.type = T_TriggerData;
928 LocTriggerData.tg_event = TRIGGER_EVENT_DELETE | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE;
929 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
930 LocTriggerData.tg_newtuple = NULL;
931 for (i = 0; i < ntrigs; i++)
933 Trigger *trigger = &trigdesc->triggers[tgindx[i]];
935 if (!trigger->tgenabled)
937 LocTriggerData.tg_trigtuple = trigtuple;
938 LocTriggerData.tg_trigger = trigger;
939 newtuple = ExecCallTriggerFunc(&LocTriggerData,
940 relinfo->ri_TrigFunctions + tgindx[i],
941 GetPerTupleMemoryContext(estate));
942 if (newtuple == NULL)
944 if (newtuple != trigtuple)
945 heap_freetuple(newtuple);
947 heap_freetuple(trigtuple);
949 return (newtuple == NULL) ? false : true;
953 ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
956 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
958 if (trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
960 HeapTuple trigtuple = GetTupleForTrigger(estate, relinfo,
963 DeferredTriggerSaveEvent(relinfo, TRIGGER_EVENT_DELETE,
965 heap_freetuple(trigtuple);
970 ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
971 ItemPointer tupleid, HeapTuple newtuple)
973 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
974 int ntrigs = trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
975 int *tgindx = trigdesc->tg_before_row[TRIGGER_EVENT_UPDATE];
976 TriggerData LocTriggerData;
979 HeapTuple intuple = newtuple;
980 TupleTableSlot *newSlot;
983 trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, &newSlot);
984 if (trigtuple == NULL)
988 * In READ COMMITTED isolevel it's possible that newtuple was changed
989 * due to concurrent update.
992 intuple = newtuple = ExecRemoveJunk(estate->es_junkFilter, newSlot);
994 /* Allocate cache space for fmgr lookup info, if not done yet */
995 if (relinfo->ri_TrigFunctions == NULL)
997 relinfo->ri_TrigFunctions = (FmgrInfo *)
998 palloc(trigdesc->numtriggers * sizeof(FmgrInfo));
999 MemSet(relinfo->ri_TrigFunctions, 0,
1000 trigdesc->numtriggers * sizeof(FmgrInfo));
1003 LocTriggerData.type = T_TriggerData;
1004 LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE;
1005 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
1006 for (i = 0; i < ntrigs; i++)
1008 Trigger *trigger = &trigdesc->triggers[tgindx[i]];
1010 if (!trigger->tgenabled)
1012 LocTriggerData.tg_trigtuple = trigtuple;
1013 LocTriggerData.tg_newtuple = oldtuple = newtuple;
1014 LocTriggerData.tg_trigger = trigger;
1015 newtuple = ExecCallTriggerFunc(&LocTriggerData,
1016 relinfo->ri_TrigFunctions + tgindx[i],
1017 GetPerTupleMemoryContext(estate));
1018 if (oldtuple != newtuple && oldtuple != intuple)
1019 heap_freetuple(oldtuple);
1020 if (newtuple == NULL)
1023 heap_freetuple(trigtuple);
1028 ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
1029 ItemPointer tupleid, HeapTuple newtuple)
1031 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
1033 if (trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0)
1035 HeapTuple trigtuple = GetTupleForTrigger(estate, relinfo,
1038 DeferredTriggerSaveEvent(relinfo, TRIGGER_EVENT_UPDATE,
1039 trigtuple, newtuple);
1040 heap_freetuple(trigtuple);
1046 GetTupleForTrigger(EState *estate, ResultRelInfo *relinfo,
1047 ItemPointer tid, TupleTableSlot **newSlot)
1049 Relation relation = relinfo->ri_RelationDesc;
1050 HeapTupleData tuple;
1054 if (newSlot != NULL)
1059 * mark tuple for update
1062 tuple.t_self = *tid;
1064 test = heap_mark4update(relation, &tuple, &buffer);
1067 case HeapTupleSelfUpdated:
1068 ReleaseBuffer(buffer);
1071 case HeapTupleMayBeUpdated:
1074 case HeapTupleUpdated:
1075 ReleaseBuffer(buffer);
1076 if (XactIsoLevel == XACT_SERIALIZABLE)
1077 elog(ERROR, "Can't serialize access due to concurrent update");
1078 else if (!(ItemPointerEquals(&(tuple.t_self), tid)))
1080 TupleTableSlot *epqslot = EvalPlanQual(estate,
1081 relinfo->ri_RangeTableIndex,
1084 if (!(TupIsNull(epqslot)))
1086 *tid = tuple.t_self;
1093 * if tuple was deleted or PlanQual failed for updated
1094 * tuple - we have not process this tuple!
1099 ReleaseBuffer(buffer);
1100 elog(ERROR, "Unknown status %u from heap_mark4update", test);
1109 buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
1111 if (!BufferIsValid(buffer))
1112 elog(ERROR, "GetTupleForTrigger: failed ReadBuffer");
1114 dp = (PageHeader) BufferGetPage(buffer);
1115 lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
1117 Assert(ItemIdIsUsed(lp));
1119 tuple.t_datamcxt = NULL;
1120 tuple.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
1121 tuple.t_len = ItemIdGetLength(lp);
1122 tuple.t_self = *tid;
1125 result = heap_copytuple(&tuple);
1126 ReleaseBuffer(buffer);
1133 * Deferred trigger stuff
1139 * Internal data to the deferred trigger mechanism is held
1140 * during entire session in a global context created at startup and
1141 * over statements/commands in a separate context which
1142 * is created at transaction start and destroyed at transaction end.
1145 static MemoryContext deftrig_gcxt = NULL;
1146 static MemoryContext deftrig_cxt = NULL;
1149 * Global data that tells which triggers are actually in
1150 * state IMMEDIATE or DEFERRED.
1153 static bool deftrig_dfl_all_isset = false;
1154 static bool deftrig_dfl_all_isdeferred = false;
1155 static List *deftrig_dfl_trigstates = NIL;
1157 static bool deftrig_all_isset;
1158 static bool deftrig_all_isdeferred;
1159 static List *deftrig_trigstates;
1162 * The list of pending deferred trigger events during the current transaction.
1164 * deftrig_events is the head, deftrig_event_tail is the last entry.
1165 * Because this can grow pretty large, we don't use separate List nodes,
1166 * but instead thread the list through the dte_next fields of the member
1167 * nodes. Saves just a few bytes per entry, but that adds up.
1169 * XXX Need to be able to shove this data out to a file if it grows too
1173 static DeferredTriggerEvent deftrig_events;
1174 static DeferredTriggerEvent deftrig_event_tail;
1178 * deferredTriggerCheckState()
1180 * Returns true if the trigger identified by tgoid is actually
1181 * in state DEFERRED.
1185 deferredTriggerCheckState(Oid tgoid, int32 itemstate)
1187 MemoryContext oldcxt;
1189 DeferredTriggerStatus trigstate;
1192 * Not deferrable triggers (i.e. normal AFTER ROW triggers and
1193 * constraints declared NOT DEFERRABLE, the state is allways false.
1195 if ((itemstate & TRIGGER_DEFERRED_DEFERRABLE) == 0)
1199 * Lookup if we know an individual state for this trigger
1201 foreach(sl, deftrig_trigstates)
1203 trigstate = (DeferredTriggerStatus) lfirst(sl);
1204 if (trigstate->dts_tgoid == tgoid)
1205 return trigstate->dts_tgisdeferred;
1209 * No individual state known - so if the user issued a SET CONSTRAINT
1210 * ALL ..., we return that instead of the triggers default state.
1212 if (deftrig_all_isset)
1213 return deftrig_all_isdeferred;
1216 * No ALL state known either, remember the default state as the
1217 * current and return that.
1219 oldcxt = MemoryContextSwitchTo(deftrig_cxt);
1221 trigstate = (DeferredTriggerStatus)
1222 palloc(sizeof(DeferredTriggerStatusData));
1223 trigstate->dts_tgoid = tgoid;
1224 trigstate->dts_tgisdeferred =
1225 ((itemstate & TRIGGER_DEFERRED_INITDEFERRED) != 0);
1226 deftrig_trigstates = lappend(deftrig_trigstates, trigstate);
1228 MemoryContextSwitchTo(oldcxt);
1230 return trigstate->dts_tgisdeferred;
1235 * deferredTriggerAddEvent()
1237 * Add a new trigger event to the queue.
1241 deferredTriggerAddEvent(DeferredTriggerEvent event)
1244 * Since the event list could grow quite long, we keep track of the
1245 * list tail and append there, rather than just doing a stupid
1246 * "lappend". This avoids O(N^2) behavior for large numbers of events.
1248 event->dte_next = NULL;
1249 if (deftrig_event_tail == NULL)
1251 /* first list entry */
1252 deftrig_events = event;
1253 deftrig_event_tail = event;
1257 deftrig_event_tail->dte_next = event;
1258 deftrig_event_tail = event;
1264 * DeferredTriggerExecute()
1266 * Fetch the required tuples back from the heap and fire one
1267 * single trigger function.
1269 * Frequently, this will be fired many times in a row for triggers of
1270 * a single relation. Therefore, we cache the open relation and provide
1271 * fmgr lookup cache space at the caller level.
1273 * event: event currently being fired.
1274 * itemno: item within event currently being fired.
1275 * rel: open relation for event.
1276 * finfo: array of fmgr lookup cache entries (one per trigger of relation).
1277 * per_tuple_context: memory context to call trigger function in.
1281 DeferredTriggerExecute(DeferredTriggerEvent event, int itemno,
1282 Relation rel, FmgrInfo *finfo,
1283 MemoryContext per_tuple_context)
1285 Oid tgoid = event->dte_item[itemno].dti_tgoid;
1286 TriggerDesc *trigdesc = rel->trigdesc;
1287 TriggerData LocTriggerData;
1288 HeapTupleData oldtuple;
1289 HeapTupleData newtuple;
1296 * Fetch the required OLD and NEW tuples.
1298 if (ItemPointerIsValid(&(event->dte_oldctid)))
1300 ItemPointerCopy(&(event->dte_oldctid), &(oldtuple.t_self));
1301 heap_fetch(rel, SnapshotAny, &oldtuple, &oldbuffer, NULL);
1302 if (!oldtuple.t_data)
1303 elog(ERROR, "DeferredTriggerExecute: failed to fetch old tuple");
1306 if (ItemPointerIsValid(&(event->dte_newctid)))
1308 ItemPointerCopy(&(event->dte_newctid), &(newtuple.t_self));
1309 heap_fetch(rel, SnapshotAny, &newtuple, &newbuffer, NULL);
1310 if (!newtuple.t_data)
1311 elog(ERROR, "DeferredTriggerExecute: failed to fetch new tuple");
1315 * Setup the trigger information
1317 LocTriggerData.type = T_TriggerData;
1318 LocTriggerData.tg_event = (event->dte_event & TRIGGER_EVENT_OPMASK) |
1320 LocTriggerData.tg_relation = rel;
1322 LocTriggerData.tg_trigger = NULL;
1323 for (tgindx = 0; tgindx < trigdesc->numtriggers; tgindx++)
1325 if (trigdesc->triggers[tgindx].tgoid == tgoid)
1327 LocTriggerData.tg_trigger = &(trigdesc->triggers[tgindx]);
1331 if (LocTriggerData.tg_trigger == NULL)
1332 elog(ERROR, "DeferredTriggerExecute: can't find trigger %u", tgoid);
1334 switch (event->dte_event & TRIGGER_EVENT_OPMASK)
1336 case TRIGGER_EVENT_INSERT:
1337 LocTriggerData.tg_trigtuple = &newtuple;
1338 LocTriggerData.tg_newtuple = NULL;
1341 case TRIGGER_EVENT_UPDATE:
1342 LocTriggerData.tg_trigtuple = &oldtuple;
1343 LocTriggerData.tg_newtuple = &newtuple;
1346 case TRIGGER_EVENT_DELETE:
1347 LocTriggerData.tg_trigtuple = &oldtuple;
1348 LocTriggerData.tg_newtuple = NULL;
1353 * Call the trigger and throw away an eventually returned updated
1356 rettuple = ExecCallTriggerFunc(&LocTriggerData,
1359 if (rettuple != NULL && rettuple != &oldtuple && rettuple != &newtuple)
1360 heap_freetuple(rettuple);
1363 * Might have been a referential integrity constraint trigger. Reset
1364 * the snapshot overriding flag.
1366 ReferentialIntegritySnapshotOverride = false;
1371 if (ItemPointerIsValid(&(event->dte_oldctid)))
1372 ReleaseBuffer(oldbuffer);
1373 if (ItemPointerIsValid(&(event->dte_newctid)))
1374 ReleaseBuffer(newbuffer);
1379 * deferredTriggerInvokeEvents()
1381 * Scan the event queue for not yet invoked triggers. Check if they
1382 * should be invoked now and do so.
1386 deferredTriggerInvokeEvents(bool immediate_only)
1388 DeferredTriggerEvent event,
1390 MemoryContext per_tuple_context;
1391 Relation rel = NULL;
1392 FmgrInfo *finfo = NULL;
1395 * If immediate_only is true, we remove fully-processed events from
1396 * the event queue to recycle space. If immediate_only is false,
1397 * we are going to discard the whole event queue on return anyway,
1398 * so no need to bother with "retail" pfree's.
1400 * In a scenario with many commands in a transaction and many
1401 * deferred-to-end-of-transaction triggers, it could get annoying
1402 * to rescan all the deferred triggers at each command end.
1403 * To speed this up, we could remember the actual end of the queue at
1404 * EndQuery and examine only events that are newer. On state changes
1405 * we simply reset the saved position to the beginning of the queue
1406 * and process all events once with the new states.
1409 /* Make a per-tuple memory context for trigger function calls */
1411 AllocSetContextCreate(CurrentMemoryContext,
1412 "DeferredTriggerTupleContext",
1413 ALLOCSET_DEFAULT_MINSIZE,
1414 ALLOCSET_DEFAULT_INITSIZE,
1415 ALLOCSET_DEFAULT_MAXSIZE);
1417 event = deftrig_events;
1418 while (event != NULL)
1420 bool still_deferred_ones = false;
1421 DeferredTriggerEvent next_event;
1425 * Check if event is already completely done.
1427 if (! (event->dte_event & (TRIGGER_DEFERRED_DONE |
1428 TRIGGER_DEFERRED_CANCELED)))
1430 MemoryContextReset(per_tuple_context);
1433 * Check each trigger item in the event.
1435 for (i = 0; i < event->dte_n_items; i++)
1437 if (event->dte_item[i].dti_state & TRIGGER_DEFERRED_DONE)
1441 * This trigger item hasn't been called yet. Check if we
1442 * should call it now.
1444 if (immediate_only &&
1445 deferredTriggerCheckState(event->dte_item[i].dti_tgoid,
1446 event->dte_item[i].dti_state))
1448 still_deferred_ones = true;
1453 * So let's fire it... but first, open the correct relation
1454 * if this is not the same relation as before.
1456 if (rel == NULL || rel->rd_id != event->dte_relid)
1459 heap_close(rel, NoLock);
1464 * We assume that an appropriate lock is still held by the
1465 * executor, so grab no new lock here.
1467 rel = heap_open(event->dte_relid, NoLock);
1470 * Allocate space to cache fmgr lookup info for triggers
1473 finfo = (FmgrInfo *)
1474 palloc(rel->trigdesc->numtriggers * sizeof(FmgrInfo));
1476 rel->trigdesc->numtriggers * sizeof(FmgrInfo));
1479 DeferredTriggerExecute(event, i, rel, finfo,
1482 event->dte_item[i].dti_state |= TRIGGER_DEFERRED_DONE;
1483 } /* end loop over items within event */
1487 * If it's now completely done, throw it away.
1489 * NB: it's possible the trigger calls above added more events to the
1490 * queue, or that calls we will do later will want to add more,
1491 * so we have to be careful about maintaining list validity here.
1493 next_event = event->dte_next;
1495 if (still_deferred_ones)
1497 /* Not done, keep in list */
1505 /* delink it from list and free it */
1507 prev_event->dte_next = next_event;
1509 deftrig_events = next_event;
1515 * We will clean up later, but just for paranoia's sake,
1516 * mark the event done.
1518 event->dte_event |= TRIGGER_DEFERRED_DONE;
1525 /* Update list tail pointer in case we just deleted tail event */
1526 deftrig_event_tail = prev_event;
1528 /* Release working resources */
1530 heap_close(rel, NoLock);
1533 MemoryContextDelete(per_tuple_context);
1538 * DeferredTriggerInit()
1540 * Initialize the deferred trigger mechanism. This is called during
1541 * backend startup and is guaranteed to be before the first of all
1546 DeferredTriggerInit(void)
1549 * Since this context will never be reset, give it a minsize of 0.
1550 * This avoids using any memory if the session never stores anything.
1552 deftrig_gcxt = AllocSetContextCreate(TopMemoryContext,
1553 "DeferredTriggerSession",
1555 ALLOCSET_DEFAULT_INITSIZE,
1556 ALLOCSET_DEFAULT_MAXSIZE);
1561 * DeferredTriggerBeginXact()
1563 * Called at transaction start (either BEGIN or implicit for single
1564 * statement outside of transaction block).
1568 DeferredTriggerBeginXact(void)
1570 MemoryContext oldcxt;
1572 DeferredTriggerStatus dflstat;
1573 DeferredTriggerStatus stat;
1575 if (deftrig_cxt != NULL)
1577 "DeferredTriggerBeginXact() called while inside transaction");
1580 * Create the per transaction memory context and copy all states from
1581 * the per session context to here. Set the minsize to 0 to avoid
1582 * wasting memory if there is no deferred trigger data.
1584 deftrig_cxt = AllocSetContextCreate(TopTransactionContext,
1585 "DeferredTriggerXact",
1587 ALLOCSET_DEFAULT_INITSIZE,
1588 ALLOCSET_DEFAULT_MAXSIZE);
1589 oldcxt = MemoryContextSwitchTo(deftrig_cxt);
1591 deftrig_all_isset = deftrig_dfl_all_isset;
1592 deftrig_all_isdeferred = deftrig_dfl_all_isdeferred;
1594 deftrig_trigstates = NIL;
1595 foreach(l, deftrig_dfl_trigstates)
1597 dflstat = (DeferredTriggerStatus) lfirst(l);
1598 stat = (DeferredTriggerStatus)
1599 palloc(sizeof(DeferredTriggerStatusData));
1601 stat->dts_tgoid = dflstat->dts_tgoid;
1602 stat->dts_tgisdeferred = dflstat->dts_tgisdeferred;
1604 deftrig_trigstates = lappend(deftrig_trigstates, stat);
1607 MemoryContextSwitchTo(oldcxt);
1609 deftrig_events = NULL;
1610 deftrig_event_tail = NULL;
1615 * DeferredTriggerEndQuery()
1617 * Called after one query sent down by the user has completely been
1618 * processed. At this time we invoke all outstanding IMMEDIATE triggers.
1622 DeferredTriggerEndQuery(void)
1625 * Ignore call if we aren't in a transaction.
1627 if (deftrig_cxt == NULL)
1630 deferredTriggerInvokeEvents(true);
1635 * DeferredTriggerEndXact()
1637 * Called just before the current transaction is committed. At this
1638 * time we invoke all DEFERRED triggers and tidy up.
1642 DeferredTriggerEndXact(void)
1645 * Ignore call if we aren't in a transaction.
1647 if (deftrig_cxt == NULL)
1650 deferredTriggerInvokeEvents(false);
1652 MemoryContextDelete(deftrig_cxt);
1658 * DeferredTriggerAbortXact()
1660 * The current transaction has entered the abort state.
1661 * All outstanding triggers are canceled so we simply throw
1662 * away anything we know.
1666 DeferredTriggerAbortXact(void)
1669 * Ignore call if we aren't in a transaction.
1671 if (deftrig_cxt == NULL)
1674 MemoryContextDelete(deftrig_cxt);
1680 * DeferredTriggerSetState()
1682 * Called for the users SET CONSTRAINTS ... utility command.
1686 DeferredTriggerSetState(ConstraintsSetStmt *stmt)
1692 MemoryContext oldcxt;
1694 DeferredTriggerStatus state;
1697 * Handle SET CONSTRAINTS ALL ...
1699 if (stmt->constraints == NIL)
1701 if (!IsTransactionBlock())
1704 * ... outside of a transaction block
1706 * Drop all information about individual trigger states per
1709 l = deftrig_dfl_trigstates;
1712 List *next = lnext(l);
1718 deftrig_dfl_trigstates = NIL;
1721 * Set the session ALL state to known.
1723 deftrig_dfl_all_isset = true;
1724 deftrig_dfl_all_isdeferred = stmt->deferred;
1731 * ... inside of a transaction block
1733 * Drop all information about individual trigger states per
1736 l = deftrig_trigstates;
1739 List *next = lnext(l);
1745 deftrig_trigstates = NIL;
1748 * Set the per transaction ALL state to known.
1750 deftrig_all_isset = true;
1751 deftrig_all_isdeferred = stmt->deferred;
1758 * Handle SET CONSTRAINTS constraint-name [, ...]
1759 * First lookup all trigger Oid's for the constraint names.
1762 tgrel = heap_openr(TriggerRelationName, AccessShareLock);
1764 foreach(l, stmt->constraints)
1766 char *cname = strVal(lfirst(l));
1772 * Check that only named constraints are set explicitly
1774 if (strlen(cname) == 0)
1775 elog(ERROR, "unnamed constraints cannot be set explicitly");
1778 * Setup to scan pg_trigger by tgconstrname ...
1780 ScanKeyEntryInitialize(&skey,
1782 (AttrNumber) Anum_pg_trigger_tgconstrname,
1783 (RegProcedure) F_NAMEEQ,
1784 PointerGetDatum(cname));
1786 tgscan = systable_beginscan(tgrel, TriggerConstrNameIndex, true,
1787 SnapshotNow, 1, &skey);
1790 * ... and search for the constraint trigger row
1794 while (HeapTupleIsValid(htup = systable_getnext(tgscan)))
1796 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
1800 * If we found some, check that they fit the deferrability but
1801 * skip ON <event> RESTRICT ones, since they are silently
1804 if (stmt->deferred && !pg_trigger->tgdeferrable &&
1805 pg_trigger->tgfoid != F_RI_FKEY_RESTRICT_UPD &&
1806 pg_trigger->tgfoid != F_RI_FKEY_RESTRICT_DEL)
1807 elog(ERROR, "Constraint '%s' is not deferrable",
1810 constr_oid = htup->t_data->t_oid;
1811 loid = lappendi(loid, constr_oid);
1815 systable_endscan(tgscan);
1821 elog(ERROR, "Constraint '%s' does not exist", cname);
1823 heap_close(tgrel, AccessShareLock);
1825 if (!IsTransactionBlock())
1828 * Outside of a transaction block set the trigger states of
1829 * individual triggers on session level.
1831 oldcxt = MemoryContextSwitchTo(deftrig_gcxt);
1836 foreach(ls, deftrig_dfl_trigstates)
1838 state = (DeferredTriggerStatus) lfirst(ls);
1839 if (state->dts_tgoid == (Oid) lfirsti(l))
1841 state->dts_tgisdeferred = stmt->deferred;
1848 state = (DeferredTriggerStatus)
1849 palloc(sizeof(DeferredTriggerStatusData));
1850 state->dts_tgoid = (Oid) lfirsti(l);
1851 state->dts_tgisdeferred = stmt->deferred;
1853 deftrig_dfl_trigstates =
1854 lappend(deftrig_dfl_trigstates, state);
1858 MemoryContextSwitchTo(oldcxt);
1865 * Inside of a transaction block set the trigger states of
1866 * individual triggers on transaction level.
1868 oldcxt = MemoryContextSwitchTo(deftrig_cxt);
1873 foreach(ls, deftrig_trigstates)
1875 state = (DeferredTriggerStatus) lfirst(ls);
1876 if (state->dts_tgoid == (Oid) lfirsti(l))
1878 state->dts_tgisdeferred = stmt->deferred;
1885 state = (DeferredTriggerStatus)
1886 palloc(sizeof(DeferredTriggerStatusData));
1887 state->dts_tgoid = (Oid) lfirsti(l);
1888 state->dts_tgisdeferred = stmt->deferred;
1890 deftrig_trigstates =
1891 lappend(deftrig_trigstates, state);
1895 MemoryContextSwitchTo(oldcxt);
1903 * DeferredTriggerSaveEvent()
1905 * Called by ExecAR...Triggers() to add the event to the queue.
1907 * NOTE: should be called only if we've determined that an event must
1908 * be added to the queue.
1912 DeferredTriggerSaveEvent(ResultRelInfo *relinfo, int event,
1913 HeapTuple oldtup, HeapTuple newtup)
1915 Relation rel = relinfo->ri_RelationDesc;
1916 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
1917 MemoryContext oldcxt;
1918 DeferredTriggerEvent new_event;
1923 ItemPointerData oldctid;
1924 ItemPointerData newctid;
1925 TriggerData LocTriggerData;
1927 if (deftrig_cxt == NULL)
1929 "DeferredTriggerSaveEvent() called outside of transaction");
1932 * Get the CTID's of OLD and NEW
1935 ItemPointerCopy(&(oldtup->t_self), &(oldctid));
1937 ItemPointerSetInvalid(&(oldctid));
1939 ItemPointerCopy(&(newtup->t_self), &(newctid));
1941 ItemPointerSetInvalid(&(newctid));
1944 * Create a new event
1946 oldcxt = MemoryContextSwitchTo(deftrig_cxt);
1948 ntriggers = trigdesc->n_after_row[event];
1949 tgindx = trigdesc->tg_after_row[event];
1950 new_size = offsetof(DeferredTriggerEventData, dte_item[0]) +
1951 ntriggers * sizeof(DeferredTriggerEventItem);
1953 new_event = (DeferredTriggerEvent) palloc(new_size);
1954 new_event->dte_next = NULL;
1955 new_event->dte_event = event & TRIGGER_EVENT_OPMASK;
1956 new_event->dte_relid = rel->rd_id;
1957 ItemPointerCopy(&oldctid, &(new_event->dte_oldctid));
1958 ItemPointerCopy(&newctid, &(new_event->dte_newctid));
1959 new_event->dte_n_items = ntriggers;
1960 for (i = 0; i < ntriggers; i++)
1962 Trigger *trigger = &trigdesc->triggers[tgindx[i]];
1964 new_event->dte_item[i].dti_tgoid = trigger->tgoid;
1965 new_event->dte_item[i].dti_state =
1966 ((trigger->tgdeferrable) ?
1967 TRIGGER_DEFERRED_DEFERRABLE : 0) |
1968 ((trigger->tginitdeferred) ?
1969 TRIGGER_DEFERRED_INITDEFERRED : 0) |
1970 ((trigdesc->n_before_row[event] > 0) ?
1971 TRIGGER_DEFERRED_HAS_BEFORE : 0);
1974 MemoryContextSwitchTo(oldcxt);
1976 switch (event & TRIGGER_EVENT_OPMASK)
1978 case TRIGGER_EVENT_INSERT:
1982 case TRIGGER_EVENT_UPDATE:
1984 * Check if one of the referenced keys is changed.
1986 for (i = 0; i < ntriggers; i++)
1988 Trigger *trigger = &trigdesc->triggers[tgindx[i]];
1993 * We are interested in RI_FKEY triggers only.
1995 switch (trigger->tgfoid)
1997 case F_RI_FKEY_NOACTION_UPD:
1998 case F_RI_FKEY_CASCADE_UPD:
1999 case F_RI_FKEY_RESTRICT_UPD:
2000 case F_RI_FKEY_SETNULL_UPD:
2001 case F_RI_FKEY_SETDEFAULT_UPD:
2002 is_ri_trigger = true;
2006 is_ri_trigger = false;
2012 LocTriggerData.type = T_TriggerData;
2013 LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE;
2014 LocTriggerData.tg_relation = rel;
2015 LocTriggerData.tg_trigtuple = oldtup;
2016 LocTriggerData.tg_newtuple = newtup;
2017 LocTriggerData.tg_trigger = trigger;
2019 key_unchanged = RI_FKey_keyequal_upd(&LocTriggerData);
2024 * The key hasn't changed, so no need later to invoke
2025 * the trigger at all.
2027 new_event->dte_item[i].dti_state |= TRIGGER_DEFERRED_DONE;
2033 case TRIGGER_EVENT_DELETE:
2039 * Add the new event to the queue.
2041 deferredTriggerAddEvent(new_event);