Fix pg_dump bug in the database-level collation patch. "datcollate" and
[PostgreSQL.git] / src / backend / commands / trigger.c
blob9c3639ee193771de0fbbbc71b32ece89de56816b
1 /*-------------------------------------------------------------------------
3 * trigger.c
4 * PostgreSQL TRIGGERs support code.
6 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
9 * IDENTIFICATION
10 * $PostgreSQL$
12 *-------------------------------------------------------------------------
14 #include "postgres.h"
16 #include "access/genam.h"
17 #include "access/heapam.h"
18 #include "access/sysattr.h"
19 #include "access/xact.h"
20 #include "catalog/catalog.h"
21 #include "catalog/dependency.h"
22 #include "catalog/indexing.h"
23 #include "catalog/pg_constraint.h"
24 #include "catalog/pg_proc.h"
25 #include "catalog/pg_trigger.h"
26 #include "catalog/pg_type.h"
27 #include "commands/dbcommands.h"
28 #include "commands/defrem.h"
29 #include "commands/trigger.h"
30 #include "executor/executor.h"
31 #include "executor/instrument.h"
32 #include "miscadmin.h"
33 #include "nodes/makefuncs.h"
34 #include "parser/parse_func.h"
35 #include "pgstat.h"
36 #include "storage/bufmgr.h"
37 #include "tcop/utility.h"
38 #include "utils/acl.h"
39 #include "utils/builtins.h"
40 #include "utils/fmgroids.h"
41 #include "utils/inval.h"
42 #include "utils/lsyscache.h"
43 #include "utils/memutils.h"
44 #include "utils/snapmgr.h"
45 #include "utils/syscache.h"
46 #include "utils/tqual.h"
49 /* GUC variables */
50 int SessionReplicationRole = SESSION_REPLICATION_ROLE_ORIGIN;
53 /* Local function prototypes */
54 static void ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid);
55 static void InsertTrigger(TriggerDesc *trigdesc, Trigger *trigger, int indx);
56 static HeapTuple GetTupleForTrigger(EState *estate,
57 ResultRelInfo *relinfo,
58 ItemPointer tid,
59 TupleTableSlot **newSlot);
60 static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata,
61 int tgindx,
62 FmgrInfo *finfo,
63 Instrumentation *instr,
64 MemoryContext per_tuple_context);
65 static void AfterTriggerSaveEvent(ResultRelInfo *relinfo, int event,
66 bool row_trigger, HeapTuple oldtup, HeapTuple newtup);
70 * Create a trigger. Returns the OID of the created trigger.
72 * constraintOid, if nonzero, says that this trigger is being created
73 * internally to implement that constraint. A suitable pg_depend entry will
74 * be made to link the trigger to that constraint. constraintOid is zero when
75 * executing a user-entered CREATE TRIGGER command.
77 * Note: can return InvalidOid if we decided to not create a trigger at all,
78 * but a foreign-key constraint. This is a kluge for backwards compatibility.
80 Oid
81 CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid)
83 int16 tgtype;
84 int2vector *tgattr;
85 Datum values[Natts_pg_trigger];
86 char nulls[Natts_pg_trigger];
87 Relation rel;
88 AclResult aclresult;
89 Relation tgrel;
90 SysScanDesc tgscan;
91 ScanKeyData key;
92 Relation pgrel;
93 HeapTuple tuple;
94 Oid fargtypes[1]; /* dummy */
95 Oid funcoid;
96 Oid funcrettype;
97 Oid trigoid;
98 int found = 0;
99 int i;
100 char constrtrigname[NAMEDATALEN];
101 char *trigname;
102 char *constrname;
103 Oid constrrelid = InvalidOid;
104 ObjectAddress myself,
105 referenced;
107 rel = heap_openrv(stmt->relation, AccessExclusiveLock);
109 if (rel->rd_rel->relkind != RELKIND_RELATION)
110 ereport(ERROR,
111 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
112 errmsg("\"%s\" is not a table",
113 RelationGetRelationName(rel))));
115 if (!allowSystemTableMods && IsSystemRelation(rel))
116 ereport(ERROR,
117 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
118 errmsg("permission denied: \"%s\" is a system catalog",
119 RelationGetRelationName(rel))));
121 /* permission checks */
123 if (stmt->isconstraint)
125 /* constraint trigger */
126 aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
127 ACL_REFERENCES);
128 if (aclresult != ACLCHECK_OK)
129 aclcheck_error(aclresult, ACL_KIND_CLASS,
130 RelationGetRelationName(rel));
132 if (stmt->constrrel != NULL)
134 constrrelid = RangeVarGetRelid(stmt->constrrel, false);
136 aclresult = pg_class_aclcheck(constrrelid, GetUserId(),
137 ACL_REFERENCES);
138 if (aclresult != ACLCHECK_OK)
139 aclcheck_error(aclresult, ACL_KIND_CLASS,
140 get_rel_name(constrrelid));
143 else
145 /* regular trigger */
146 aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
147 ACL_TRIGGER);
148 if (aclresult != ACLCHECK_OK)
149 aclcheck_error(aclresult, ACL_KIND_CLASS,
150 RelationGetRelationName(rel));
153 /* Compute tgtype */
154 TRIGGER_CLEAR_TYPE(tgtype);
155 if (stmt->before)
156 TRIGGER_SETT_BEFORE(tgtype);
157 if (stmt->row)
158 TRIGGER_SETT_ROW(tgtype);
160 for (i = 0; stmt->actions[i]; i++)
162 switch (stmt->actions[i])
164 case 'i':
165 if (TRIGGER_FOR_INSERT(tgtype))
166 ereport(ERROR,
167 (errcode(ERRCODE_SYNTAX_ERROR),
168 errmsg("multiple INSERT events specified")));
169 TRIGGER_SETT_INSERT(tgtype);
170 break;
171 case 'd':
172 if (TRIGGER_FOR_DELETE(tgtype))
173 ereport(ERROR,
174 (errcode(ERRCODE_SYNTAX_ERROR),
175 errmsg("multiple DELETE events specified")));
176 TRIGGER_SETT_DELETE(tgtype);
177 break;
178 case 'u':
179 if (TRIGGER_FOR_UPDATE(tgtype))
180 ereport(ERROR,
181 (errcode(ERRCODE_SYNTAX_ERROR),
182 errmsg("multiple UPDATE events specified")));
183 TRIGGER_SETT_UPDATE(tgtype);
184 break;
185 case 't':
186 if (TRIGGER_FOR_TRUNCATE(tgtype))
187 ereport(ERROR,
188 (errcode(ERRCODE_SYNTAX_ERROR),
189 errmsg("multiple TRUNCATE events specified")));
190 TRIGGER_SETT_TRUNCATE(tgtype);
191 /* Disallow ROW-level TRUNCATE triggers */
192 if (stmt->row)
193 ereport(ERROR,
194 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
195 errmsg("TRUNCATE FOR EACH ROW triggers are not supported")));
196 break;
197 default:
198 elog(ERROR, "unrecognized trigger event: %d",
199 (int) stmt->actions[i]);
200 break;
205 * Find and validate the trigger function.
207 funcoid = LookupFuncName(stmt->funcname, 0, fargtypes, false);
208 funcrettype = get_func_rettype(funcoid);
209 if (funcrettype != TRIGGEROID)
212 * We allow OPAQUE just so we can load old dump files. When we see a
213 * trigger function declared OPAQUE, change it to TRIGGER.
215 if (funcrettype == OPAQUEOID)
217 ereport(WARNING,
218 (errmsg("changing return type of function %s from \"opaque\" to \"trigger\"",
219 NameListToString(stmt->funcname))));
220 SetFunctionReturnType(funcoid, TRIGGEROID);
222 else
223 ereport(ERROR,
224 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
225 errmsg("function %s must return type \"trigger\"",
226 NameListToString(stmt->funcname))));
230 * If the command is a user-entered CREATE CONSTRAINT TRIGGER command that
231 * references one of the built-in RI_FKey trigger functions, assume it is
232 * from a dump of a pre-7.3 foreign key constraint, and take steps to
233 * convert this legacy representation into a regular foreign key
234 * constraint. Ugly, but necessary for loading old dump files.
236 if (stmt->isconstraint && !OidIsValid(constraintOid) &&
237 list_length(stmt->args) >= 6 &&
238 (list_length(stmt->args) % 2) == 0 &&
239 RI_FKey_trigger_type(funcoid) != RI_TRIGGER_NONE)
241 /* Keep lock on target rel until end of xact */
242 heap_close(rel, NoLock);
244 ConvertTriggerToFK(stmt, funcoid);
246 return InvalidOid;
250 * Generate the trigger's OID now, so that we can use it in the name if
251 * needed.
253 tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
255 trigoid = GetNewOid(tgrel);
258 * If trigger is for an RI constraint, the passed-in name is the
259 * constraint name; save that and build a unique trigger name to avoid
260 * collisions with user-selected trigger names.
262 if (OidIsValid(constraintOid))
264 snprintf(constrtrigname, sizeof(constrtrigname),
265 "RI_ConstraintTrigger_%u", trigoid);
266 trigname = constrtrigname;
267 constrname = stmt->trigname;
269 else if (stmt->isconstraint)
271 /* constraint trigger: trigger name is also constraint name */
272 trigname = stmt->trigname;
273 constrname = stmt->trigname;
275 else
277 /* regular trigger: use empty constraint name */
278 trigname = stmt->trigname;
279 constrname = "";
283 * Scan pg_trigger for existing triggers on relation. We do this mainly
284 * because we must count them; a secondary benefit is to give a nice error
285 * message if there's already a trigger of the same name. (The unique
286 * index on tgrelid/tgname would complain anyway.)
288 * NOTE that this is cool only because we have AccessExclusiveLock on the
289 * relation, so the trigger set won't be changing underneath us.
291 ScanKeyInit(&key,
292 Anum_pg_trigger_tgrelid,
293 BTEqualStrategyNumber, F_OIDEQ,
294 ObjectIdGetDatum(RelationGetRelid(rel)));
295 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
296 SnapshotNow, 1, &key);
297 while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
299 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
301 if (namestrcmp(&(pg_trigger->tgname), trigname) == 0)
302 ereport(ERROR,
303 (errcode(ERRCODE_DUPLICATE_OBJECT),
304 errmsg("trigger \"%s\" for relation \"%s\" already exists",
305 trigname, stmt->relation->relname)));
306 found++;
308 systable_endscan(tgscan);
311 * Build the new pg_trigger tuple.
313 memset(nulls, ' ', Natts_pg_trigger * sizeof(char));
315 values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
316 values[Anum_pg_trigger_tgname - 1] = DirectFunctionCall1(namein,
317 CStringGetDatum(trigname));
318 values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid);
319 values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype);
320 values[Anum_pg_trigger_tgenabled - 1] = CharGetDatum(TRIGGER_FIRES_ON_ORIGIN);
321 values[Anum_pg_trigger_tgisconstraint - 1] = BoolGetDatum(stmt->isconstraint);
322 values[Anum_pg_trigger_tgconstrname - 1] = DirectFunctionCall1(namein,
323 CStringGetDatum(constrname));
324 values[Anum_pg_trigger_tgconstrrelid - 1] = ObjectIdGetDatum(constrrelid);
325 values[Anum_pg_trigger_tgconstraint - 1] = ObjectIdGetDatum(constraintOid);
326 values[Anum_pg_trigger_tgdeferrable - 1] = BoolGetDatum(stmt->deferrable);
327 values[Anum_pg_trigger_tginitdeferred - 1] = BoolGetDatum(stmt->initdeferred);
329 if (stmt->args)
331 ListCell *le;
332 char *args;
333 int16 nargs = list_length(stmt->args);
334 int len = 0;
336 foreach(le, stmt->args)
338 char *ar = strVal(lfirst(le));
340 len += strlen(ar) + 4;
341 for (; *ar; ar++)
343 if (*ar == '\\')
344 len++;
347 args = (char *) palloc(len + 1);
348 args[0] = '\0';
349 foreach(le, stmt->args)
351 char *s = strVal(lfirst(le));
352 char *d = args + strlen(args);
354 while (*s)
356 if (*s == '\\')
357 *d++ = '\\';
358 *d++ = *s++;
360 strcpy(d, "\\000");
362 values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(nargs);
363 values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
364 CStringGetDatum(args));
366 else
368 values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(0);
369 values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
370 CStringGetDatum(""));
373 /* tgattr is currently always a zero-length array */
374 tgattr = buildint2vector(NULL, 0);
375 values[Anum_pg_trigger_tgattr - 1] = PointerGetDatum(tgattr);
377 tuple = heap_formtuple(tgrel->rd_att, values, nulls);
379 /* force tuple to have the desired OID */
380 HeapTupleSetOid(tuple, trigoid);
383 * Insert tuple into pg_trigger.
385 simple_heap_insert(tgrel, tuple);
387 CatalogUpdateIndexes(tgrel, tuple);
389 heap_freetuple(tuple);
390 heap_close(tgrel, RowExclusiveLock);
392 pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
393 pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1]));
396 * Update relation's pg_class entry. Crucial side-effect: other backends
397 * (and this one too!) are sent SI message to make them rebuild relcache
398 * entries.
400 pgrel = heap_open(RelationRelationId, RowExclusiveLock);
401 tuple = SearchSysCacheCopy(RELOID,
402 ObjectIdGetDatum(RelationGetRelid(rel)),
403 0, 0, 0);
404 if (!HeapTupleIsValid(tuple))
405 elog(ERROR, "cache lookup failed for relation %u",
406 RelationGetRelid(rel));
408 ((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1;
410 simple_heap_update(pgrel, &tuple->t_self, tuple);
412 CatalogUpdateIndexes(pgrel, tuple);
414 heap_freetuple(tuple);
415 heap_close(pgrel, RowExclusiveLock);
418 * We used to try to update the rel's relcache entry here, but that's
419 * fairly pointless since it will happen as a byproduct of the upcoming
420 * CommandCounterIncrement...
424 * Record dependencies for trigger. Always place a normal dependency on
425 * the function.
427 myself.classId = TriggerRelationId;
428 myself.objectId = trigoid;
429 myself.objectSubId = 0;
431 referenced.classId = ProcedureRelationId;
432 referenced.objectId = funcoid;
433 referenced.objectSubId = 0;
434 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
436 if (OidIsValid(constraintOid))
439 * It's for a constraint, so make it an internal dependency of the
440 * constraint. We can skip depending on the relations, as there'll be
441 * an indirect dependency via the constraint.
443 referenced.classId = ConstraintRelationId;
444 referenced.objectId = constraintOid;
445 referenced.objectSubId = 0;
446 recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
448 else
451 * Regular CREATE TRIGGER, so place dependencies. We make trigger be
452 * auto-dropped if its relation is dropped or if the FK relation is
453 * dropped. (Auto drop is compatible with our pre-7.3 behavior.)
455 referenced.classId = RelationRelationId;
456 referenced.objectId = RelationGetRelid(rel);
457 referenced.objectSubId = 0;
458 recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
459 if (constrrelid != InvalidOid)
461 referenced.classId = RelationRelationId;
462 referenced.objectId = constrrelid;
463 referenced.objectSubId = 0;
464 recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
468 /* Keep lock on target rel until end of xact */
469 heap_close(rel, NoLock);
471 return trigoid;
476 * Convert legacy (pre-7.3) CREATE CONSTRAINT TRIGGER commands into
477 * full-fledged foreign key constraints.
479 * The conversion is complex because a pre-7.3 foreign key involved three
480 * separate triggers, which were reported separately in dumps. While the
481 * single trigger on the referencing table adds no new information, we need
482 * to know the trigger functions of both of the triggers on the referenced
483 * table to build the constraint declaration. Also, due to lack of proper
484 * dependency checking pre-7.3, it is possible that the source database had
485 * an incomplete set of triggers resulting in an only partially enforced
486 * FK constraint. (This would happen if one of the tables had been dropped
487 * and re-created, but only if the DB had been affected by a 7.0 pg_dump bug
488 * that caused loss of tgconstrrelid information.) We choose to translate to
489 * an FK constraint only when we've seen all three triggers of a set. This is
490 * implemented by storing unmatched items in a list in TopMemoryContext.
491 * We match triggers together by comparing the trigger arguments (which
492 * include constraint name, table and column names, so should be good enough).
494 typedef struct
496 List *args; /* list of (T_String) Values or NIL */
497 Oid funcoids[3]; /* OIDs of trigger functions */
498 /* The three function OIDs are stored in the order update, delete, child */
499 } OldTriggerInfo;
501 static void
502 ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
504 static List *info_list = NIL;
506 static const char *const funcdescr[3] = {
507 gettext_noop("Found referenced table's UPDATE trigger."),
508 gettext_noop("Found referenced table's DELETE trigger."),
509 gettext_noop("Found referencing table's trigger.")
512 char *constr_name;
513 char *fk_table_name;
514 char *pk_table_name;
515 char fk_matchtype = FKCONSTR_MATCH_UNSPECIFIED;
516 List *fk_attrs = NIL;
517 List *pk_attrs = NIL;
518 StringInfoData buf;
519 int funcnum;
520 OldTriggerInfo *info = NULL;
521 ListCell *l;
522 int i;
524 /* Parse out the trigger arguments */
525 constr_name = strVal(linitial(stmt->args));
526 fk_table_name = strVal(lsecond(stmt->args));
527 pk_table_name = strVal(lthird(stmt->args));
528 i = 0;
529 foreach(l, stmt->args)
531 Value *arg = (Value *) lfirst(l);
533 i++;
534 if (i < 4) /* skip constraint and table names */
535 continue;
536 if (i == 4) /* handle match type */
538 if (strcmp(strVal(arg), "FULL") == 0)
539 fk_matchtype = FKCONSTR_MATCH_FULL;
540 else
541 fk_matchtype = FKCONSTR_MATCH_UNSPECIFIED;
542 continue;
544 if (i % 2)
545 fk_attrs = lappend(fk_attrs, arg);
546 else
547 pk_attrs = lappend(pk_attrs, arg);
550 /* Prepare description of constraint for use in messages */
551 initStringInfo(&buf);
552 appendStringInfo(&buf, "FOREIGN KEY %s(",
553 quote_identifier(fk_table_name));
554 i = 0;
555 foreach(l, fk_attrs)
557 Value *arg = (Value *) lfirst(l);
559 if (i++ > 0)
560 appendStringInfoChar(&buf, ',');
561 appendStringInfoString(&buf, quote_identifier(strVal(arg)));
563 appendStringInfo(&buf, ") REFERENCES %s(",
564 quote_identifier(pk_table_name));
565 i = 0;
566 foreach(l, pk_attrs)
568 Value *arg = (Value *) lfirst(l);
570 if (i++ > 0)
571 appendStringInfoChar(&buf, ',');
572 appendStringInfoString(&buf, quote_identifier(strVal(arg)));
574 appendStringInfoChar(&buf, ')');
576 /* Identify class of trigger --- update, delete, or referencing-table */
577 switch (funcoid)
579 case F_RI_FKEY_CASCADE_UPD:
580 case F_RI_FKEY_RESTRICT_UPD:
581 case F_RI_FKEY_SETNULL_UPD:
582 case F_RI_FKEY_SETDEFAULT_UPD:
583 case F_RI_FKEY_NOACTION_UPD:
584 funcnum = 0;
585 break;
587 case F_RI_FKEY_CASCADE_DEL:
588 case F_RI_FKEY_RESTRICT_DEL:
589 case F_RI_FKEY_SETNULL_DEL:
590 case F_RI_FKEY_SETDEFAULT_DEL:
591 case F_RI_FKEY_NOACTION_DEL:
592 funcnum = 1;
593 break;
595 default:
596 funcnum = 2;
597 break;
600 /* See if we have a match to this trigger */
601 foreach(l, info_list)
603 info = (OldTriggerInfo *) lfirst(l);
604 if (info->funcoids[funcnum] == InvalidOid &&
605 equal(info->args, stmt->args))
607 info->funcoids[funcnum] = funcoid;
608 break;
612 if (l == NULL)
614 /* First trigger of set, so create a new list entry */
615 MemoryContext oldContext;
617 ereport(NOTICE,
618 (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
619 constr_name, buf.data),
620 errdetail(funcdescr[funcnum])));
621 oldContext = MemoryContextSwitchTo(TopMemoryContext);
622 info = (OldTriggerInfo *) palloc0(sizeof(OldTriggerInfo));
623 info->args = copyObject(stmt->args);
624 info->funcoids[funcnum] = funcoid;
625 info_list = lappend(info_list, info);
626 MemoryContextSwitchTo(oldContext);
628 else if (info->funcoids[0] == InvalidOid ||
629 info->funcoids[1] == InvalidOid ||
630 info->funcoids[2] == InvalidOid)
632 /* Second trigger of set */
633 ereport(NOTICE,
634 (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
635 constr_name, buf.data),
636 errdetail(funcdescr[funcnum])));
638 else
640 /* OK, we have a set, so make the FK constraint ALTER TABLE cmd */
641 AlterTableStmt *atstmt = makeNode(AlterTableStmt);
642 AlterTableCmd *atcmd = makeNode(AlterTableCmd);
643 FkConstraint *fkcon = makeNode(FkConstraint);
645 ereport(NOTICE,
646 (errmsg("converting trigger group into constraint \"%s\" %s",
647 constr_name, buf.data),
648 errdetail(funcdescr[funcnum])));
649 if (funcnum == 2)
651 /* This trigger is on the FK table */
652 atstmt->relation = stmt->relation;
653 if (stmt->constrrel)
654 fkcon->pktable = stmt->constrrel;
655 else
657 /* Work around ancient pg_dump bug that omitted constrrel */
658 fkcon->pktable = makeRangeVar(NULL, pk_table_name, -1);
661 else
663 /* This trigger is on the PK table */
664 fkcon->pktable = stmt->relation;
665 if (stmt->constrrel)
666 atstmt->relation = stmt->constrrel;
667 else
669 /* Work around ancient pg_dump bug that omitted constrrel */
670 atstmt->relation = makeRangeVar(NULL, fk_table_name, -1);
673 atstmt->cmds = list_make1(atcmd);
674 atstmt->relkind = OBJECT_TABLE;
675 atcmd->subtype = AT_AddConstraint;
676 atcmd->def = (Node *) fkcon;
677 if (strcmp(constr_name, "<unnamed>") == 0)
678 fkcon->constr_name = NULL;
679 else
680 fkcon->constr_name = constr_name;
681 fkcon->fk_attrs = fk_attrs;
682 fkcon->pk_attrs = pk_attrs;
683 fkcon->fk_matchtype = fk_matchtype;
684 switch (info->funcoids[0])
686 case F_RI_FKEY_NOACTION_UPD:
687 fkcon->fk_upd_action = FKCONSTR_ACTION_NOACTION;
688 break;
689 case F_RI_FKEY_CASCADE_UPD:
690 fkcon->fk_upd_action = FKCONSTR_ACTION_CASCADE;
691 break;
692 case F_RI_FKEY_RESTRICT_UPD:
693 fkcon->fk_upd_action = FKCONSTR_ACTION_RESTRICT;
694 break;
695 case F_RI_FKEY_SETNULL_UPD:
696 fkcon->fk_upd_action = FKCONSTR_ACTION_SETNULL;
697 break;
698 case F_RI_FKEY_SETDEFAULT_UPD:
699 fkcon->fk_upd_action = FKCONSTR_ACTION_SETDEFAULT;
700 break;
701 default:
702 /* can't get here because of earlier checks */
703 elog(ERROR, "confused about RI update function");
705 switch (info->funcoids[1])
707 case F_RI_FKEY_NOACTION_DEL:
708 fkcon->fk_del_action = FKCONSTR_ACTION_NOACTION;
709 break;
710 case F_RI_FKEY_CASCADE_DEL:
711 fkcon->fk_del_action = FKCONSTR_ACTION_CASCADE;
712 break;
713 case F_RI_FKEY_RESTRICT_DEL:
714 fkcon->fk_del_action = FKCONSTR_ACTION_RESTRICT;
715 break;
716 case F_RI_FKEY_SETNULL_DEL:
717 fkcon->fk_del_action = FKCONSTR_ACTION_SETNULL;
718 break;
719 case F_RI_FKEY_SETDEFAULT_DEL:
720 fkcon->fk_del_action = FKCONSTR_ACTION_SETDEFAULT;
721 break;
722 default:
723 /* can't get here because of earlier checks */
724 elog(ERROR, "confused about RI delete function");
726 fkcon->deferrable = stmt->deferrable;
727 fkcon->initdeferred = stmt->initdeferred;
729 /* ... and execute it */
730 ProcessUtility((Node *) atstmt,
731 "(generated ALTER TABLE ADD FOREIGN KEY command)",
732 NULL, false, None_Receiver, NULL);
734 /* Remove the matched item from the list */
735 info_list = list_delete_ptr(info_list, info);
736 pfree(info);
737 /* We leak the copied args ... not worth worrying about */
743 * DropTrigger - drop an individual trigger by name
745 void
746 DropTrigger(Oid relid, const char *trigname, DropBehavior behavior,
747 bool missing_ok)
749 Relation tgrel;
750 ScanKeyData skey[2];
751 SysScanDesc tgscan;
752 HeapTuple tup;
753 ObjectAddress object;
756 * Find the trigger, verify permissions, set up object address
758 tgrel = heap_open(TriggerRelationId, AccessShareLock);
760 ScanKeyInit(&skey[0],
761 Anum_pg_trigger_tgrelid,
762 BTEqualStrategyNumber, F_OIDEQ,
763 ObjectIdGetDatum(relid));
765 ScanKeyInit(&skey[1],
766 Anum_pg_trigger_tgname,
767 BTEqualStrategyNumber, F_NAMEEQ,
768 CStringGetDatum(trigname));
770 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
771 SnapshotNow, 2, skey);
773 tup = systable_getnext(tgscan);
775 if (!HeapTupleIsValid(tup))
777 if (!missing_ok)
778 ereport(ERROR,
779 (errcode(ERRCODE_UNDEFINED_OBJECT),
780 errmsg("trigger \"%s\" for table \"%s\" does not exist",
781 trigname, get_rel_name(relid))));
782 else
783 ereport(NOTICE,
784 (errmsg("trigger \"%s\" for table \"%s\" does not exist, skipping",
785 trigname, get_rel_name(relid))));
786 /* cleanup */
787 systable_endscan(tgscan);
788 heap_close(tgrel, AccessShareLock);
789 return;
792 if (!pg_class_ownercheck(relid, GetUserId()))
793 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
794 get_rel_name(relid));
796 object.classId = TriggerRelationId;
797 object.objectId = HeapTupleGetOid(tup);
798 object.objectSubId = 0;
800 systable_endscan(tgscan);
801 heap_close(tgrel, AccessShareLock);
804 * Do the deletion
806 performDeletion(&object, behavior);
810 * Guts of trigger deletion.
812 void
813 RemoveTriggerById(Oid trigOid)
815 Relation tgrel;
816 SysScanDesc tgscan;
817 ScanKeyData skey[1];
818 HeapTuple tup;
819 Oid relid;
820 Relation rel;
821 Relation pgrel;
822 HeapTuple tuple;
823 Form_pg_class classForm;
825 tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
828 * Find the trigger to delete.
830 ScanKeyInit(&skey[0],
831 ObjectIdAttributeNumber,
832 BTEqualStrategyNumber, F_OIDEQ,
833 ObjectIdGetDatum(trigOid));
835 tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
836 SnapshotNow, 1, skey);
838 tup = systable_getnext(tgscan);
839 if (!HeapTupleIsValid(tup))
840 elog(ERROR, "could not find tuple for trigger %u", trigOid);
843 * Open and exclusive-lock the relation the trigger belongs to.
845 relid = ((Form_pg_trigger) GETSTRUCT(tup))->tgrelid;
847 rel = heap_open(relid, AccessExclusiveLock);
849 if (rel->rd_rel->relkind != RELKIND_RELATION)
850 ereport(ERROR,
851 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
852 errmsg("\"%s\" is not a table",
853 RelationGetRelationName(rel))));
855 if (!allowSystemTableMods && IsSystemRelation(rel))
856 ereport(ERROR,
857 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
858 errmsg("permission denied: \"%s\" is a system catalog",
859 RelationGetRelationName(rel))));
862 * Delete the pg_trigger tuple.
864 simple_heap_delete(tgrel, &tup->t_self);
866 systable_endscan(tgscan);
867 heap_close(tgrel, RowExclusiveLock);
870 * Update relation's pg_class entry. Crucial side-effect: other backends
871 * (and this one too!) are sent SI message to make them rebuild relcache
872 * entries.
874 * Note this is OK only because we have AccessExclusiveLock on the rel, so
875 * no one else is creating/deleting triggers on this rel at the same time.
877 pgrel = heap_open(RelationRelationId, RowExclusiveLock);
878 tuple = SearchSysCacheCopy(RELOID,
879 ObjectIdGetDatum(relid),
880 0, 0, 0);
881 if (!HeapTupleIsValid(tuple))
882 elog(ERROR, "cache lookup failed for relation %u", relid);
883 classForm = (Form_pg_class) GETSTRUCT(tuple);
885 if (classForm->reltriggers == 0) /* should not happen */
886 elog(ERROR, "relation \"%s\" has reltriggers = 0",
887 RelationGetRelationName(rel));
888 classForm->reltriggers--;
890 simple_heap_update(pgrel, &tuple->t_self, tuple);
892 CatalogUpdateIndexes(pgrel, tuple);
894 heap_freetuple(tuple);
896 heap_close(pgrel, RowExclusiveLock);
898 /* Keep lock on trigger's rel until end of xact */
899 heap_close(rel, NoLock);
903 * renametrig - changes the name of a trigger on a relation
905 * trigger name is changed in trigger catalog.
906 * No record of the previous name is kept.
908 * get proper relrelation from relation catalog (if not arg)
909 * scan trigger catalog
910 * for name conflict (within rel)
911 * for original trigger (if not arg)
912 * modify tgname in trigger tuple
913 * update row in catalog
915 void
916 renametrig(Oid relid,
917 const char *oldname,
918 const char *newname)
920 Relation targetrel;
921 Relation tgrel;
922 HeapTuple tuple;
923 SysScanDesc tgscan;
924 ScanKeyData key[2];
927 * Grab an exclusive lock on the target table, which we will NOT release
928 * until end of transaction.
930 targetrel = heap_open(relid, AccessExclusiveLock);
933 * Scan pg_trigger twice for existing triggers on relation. We do this in
934 * order to ensure a trigger does not exist with newname (The unique index
935 * on tgrelid/tgname would complain anyway) and to ensure a trigger does
936 * exist with oldname.
938 * NOTE that this is cool only because we have AccessExclusiveLock on the
939 * relation, so the trigger set won't be changing underneath us.
941 tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
944 * First pass -- look for name conflict
946 ScanKeyInit(&key[0],
947 Anum_pg_trigger_tgrelid,
948 BTEqualStrategyNumber, F_OIDEQ,
949 ObjectIdGetDatum(relid));
950 ScanKeyInit(&key[1],
951 Anum_pg_trigger_tgname,
952 BTEqualStrategyNumber, F_NAMEEQ,
953 PointerGetDatum(newname));
954 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
955 SnapshotNow, 2, key);
956 if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
957 ereport(ERROR,
958 (errcode(ERRCODE_DUPLICATE_OBJECT),
959 errmsg("trigger \"%s\" for relation \"%s\" already exists",
960 newname, RelationGetRelationName(targetrel))));
961 systable_endscan(tgscan);
964 * Second pass -- look for trigger existing with oldname and update
966 ScanKeyInit(&key[0],
967 Anum_pg_trigger_tgrelid,
968 BTEqualStrategyNumber, F_OIDEQ,
969 ObjectIdGetDatum(relid));
970 ScanKeyInit(&key[1],
971 Anum_pg_trigger_tgname,
972 BTEqualStrategyNumber, F_NAMEEQ,
973 PointerGetDatum(oldname));
974 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
975 SnapshotNow, 2, key);
976 if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
979 * Update pg_trigger tuple with new tgname.
981 tuple = heap_copytuple(tuple); /* need a modifiable copy */
983 namestrcpy(&((Form_pg_trigger) GETSTRUCT(tuple))->tgname, newname);
985 simple_heap_update(tgrel, &tuple->t_self, tuple);
987 /* keep system catalog indexes current */
988 CatalogUpdateIndexes(tgrel, tuple);
991 * Invalidate relation's relcache entry so that other backends (and
992 * this one too!) are sent SI message to make them rebuild relcache
993 * entries. (Ideally this should happen automatically...)
995 CacheInvalidateRelcache(targetrel);
997 else
999 ereport(ERROR,
1000 (errcode(ERRCODE_UNDEFINED_OBJECT),
1001 errmsg("trigger \"%s\" for table \"%s\" does not exist",
1002 oldname, RelationGetRelationName(targetrel))));
1005 systable_endscan(tgscan);
1007 heap_close(tgrel, RowExclusiveLock);
1010 * Close rel, but keep exclusive lock!
1012 heap_close(targetrel, NoLock);
1017 * EnableDisableTrigger()
1019 * Called by ALTER TABLE ENABLE/DISABLE TRIGGER
1020 * to change 'tgenabled' field for the specified trigger(s)
1022 * rel: relation to process (caller must hold suitable lock on it)
1023 * tgname: trigger to process, or NULL to scan all triggers
1024 * enable: new value for tgenabled field
1025 * skip_system: if true, skip "system" triggers (constraint triggers)
1027 * Caller should have checked permissions for the table; here we also
1028 * enforce that superuser privilege is required to alter the state of
1029 * system triggers
1031 void
1032 EnableDisableTrigger(Relation rel, const char *tgname,
1033 char fires_when, bool skip_system)
1035 Relation tgrel;
1036 int nkeys;
1037 ScanKeyData keys[2];
1038 SysScanDesc tgscan;
1039 HeapTuple tuple;
1040 bool found;
1041 bool changed;
1043 /* Scan the relevant entries in pg_triggers */
1044 tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
1046 ScanKeyInit(&keys[0],
1047 Anum_pg_trigger_tgrelid,
1048 BTEqualStrategyNumber, F_OIDEQ,
1049 ObjectIdGetDatum(RelationGetRelid(rel)));
1050 if (tgname)
1052 ScanKeyInit(&keys[1],
1053 Anum_pg_trigger_tgname,
1054 BTEqualStrategyNumber, F_NAMEEQ,
1055 CStringGetDatum(tgname));
1056 nkeys = 2;
1058 else
1059 nkeys = 1;
1061 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1062 SnapshotNow, nkeys, keys);
1064 found = changed = false;
1066 while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1068 Form_pg_trigger oldtrig = (Form_pg_trigger) GETSTRUCT(tuple);
1070 if (OidIsValid(oldtrig->tgconstraint))
1072 /* system trigger ... ok to process? */
1073 if (skip_system)
1074 continue;
1075 if (!superuser())
1076 ereport(ERROR,
1077 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1078 errmsg("permission denied: \"%s\" is a system trigger",
1079 NameStr(oldtrig->tgname))));
1082 found = true;
1084 if (oldtrig->tgenabled != fires_when)
1086 /* need to change this one ... make a copy to scribble on */
1087 HeapTuple newtup = heap_copytuple(tuple);
1088 Form_pg_trigger newtrig = (Form_pg_trigger) GETSTRUCT(newtup);
1090 newtrig->tgenabled = fires_when;
1092 simple_heap_update(tgrel, &newtup->t_self, newtup);
1094 /* Keep catalog indexes current */
1095 CatalogUpdateIndexes(tgrel, newtup);
1097 heap_freetuple(newtup);
1099 changed = true;
1103 systable_endscan(tgscan);
1105 heap_close(tgrel, RowExclusiveLock);
1107 if (tgname && !found)
1108 ereport(ERROR,
1109 (errcode(ERRCODE_UNDEFINED_OBJECT),
1110 errmsg("trigger \"%s\" for table \"%s\" does not exist",
1111 tgname, RelationGetRelationName(rel))));
1114 * If we changed anything, broadcast a SI inval message to force each
1115 * backend (including our own!) to rebuild relation's relcache entry.
1116 * Otherwise they will fail to apply the change promptly.
1118 if (changed)
1119 CacheInvalidateRelcache(rel);
1124 * Build trigger data to attach to the given relcache entry.
1126 * Note that trigger data attached to a relcache entry must be stored in
1127 * CacheMemoryContext to ensure it survives as long as the relcache entry.
1128 * But we should be running in a less long-lived working context. To avoid
1129 * leaking cache memory if this routine fails partway through, we build a
1130 * temporary TriggerDesc in working memory and then copy the completed
1131 * structure into cache memory.
1133 void
1134 RelationBuildTriggers(Relation relation)
1136 TriggerDesc *trigdesc;
1137 int ntrigs = relation->rd_rel->reltriggers;
1138 Trigger *triggers;
1139 int found = 0;
1140 Relation tgrel;
1141 ScanKeyData skey;
1142 SysScanDesc tgscan;
1143 HeapTuple htup;
1144 MemoryContext oldContext;
1146 Assert(ntrigs > 0); /* else I should not have been called */
1148 triggers = (Trigger *) palloc(ntrigs * sizeof(Trigger));
1151 * Note: since we scan the triggers using TriggerRelidNameIndexId, we will
1152 * be reading the triggers in name order, except possibly during
1153 * emergency-recovery operations (ie, IgnoreSystemIndexes). This in turn
1154 * ensures that triggers will be fired in name order.
1156 ScanKeyInit(&skey,
1157 Anum_pg_trigger_tgrelid,
1158 BTEqualStrategyNumber, F_OIDEQ,
1159 ObjectIdGetDatum(RelationGetRelid(relation)));
1161 tgrel = heap_open(TriggerRelationId, AccessShareLock);
1162 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1163 SnapshotNow, 1, &skey);
1165 while (HeapTupleIsValid(htup = systable_getnext(tgscan)))
1167 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
1168 Trigger *build;
1170 if (found >= ntrigs)
1171 elog(ERROR, "too many trigger records found for relation \"%s\"",
1172 RelationGetRelationName(relation));
1173 build = &(triggers[found]);
1175 build->tgoid = HeapTupleGetOid(htup);
1176 build->tgname = DatumGetCString(DirectFunctionCall1(nameout,
1177 NameGetDatum(&pg_trigger->tgname)));
1178 build->tgfoid = pg_trigger->tgfoid;
1179 build->tgtype = pg_trigger->tgtype;
1180 build->tgenabled = pg_trigger->tgenabled;
1181 build->tgisconstraint = pg_trigger->tgisconstraint;
1182 build->tgconstrrelid = pg_trigger->tgconstrrelid;
1183 build->tgconstraint = pg_trigger->tgconstraint;
1184 build->tgdeferrable = pg_trigger->tgdeferrable;
1185 build->tginitdeferred = pg_trigger->tginitdeferred;
1186 build->tgnargs = pg_trigger->tgnargs;
1187 /* tgattr is first var-width field, so OK to access directly */
1188 build->tgnattr = pg_trigger->tgattr.dim1;
1189 if (build->tgnattr > 0)
1191 build->tgattr = (int2 *) palloc(build->tgnattr * sizeof(int2));
1192 memcpy(build->tgattr, &(pg_trigger->tgattr.values),
1193 build->tgnattr * sizeof(int2));
1195 else
1196 build->tgattr = NULL;
1197 if (build->tgnargs > 0)
1199 bytea *val;
1200 bool isnull;
1201 char *p;
1202 int i;
1204 val = DatumGetByteaP(fastgetattr(htup,
1205 Anum_pg_trigger_tgargs,
1206 tgrel->rd_att, &isnull));
1207 if (isnull)
1208 elog(ERROR, "tgargs is null in trigger for relation \"%s\"",
1209 RelationGetRelationName(relation));
1210 p = (char *) VARDATA(val);
1211 build->tgargs = (char **) palloc(build->tgnargs * sizeof(char *));
1212 for (i = 0; i < build->tgnargs; i++)
1214 build->tgargs[i] = pstrdup(p);
1215 p += strlen(p) + 1;
1218 else
1219 build->tgargs = NULL;
1221 found++;
1224 systable_endscan(tgscan);
1225 heap_close(tgrel, AccessShareLock);
1227 if (found != ntrigs)
1228 elog(ERROR, "%d trigger record(s) not found for relation \"%s\"",
1229 ntrigs - found,
1230 RelationGetRelationName(relation));
1232 /* Build trigdesc */
1233 trigdesc = (TriggerDesc *) palloc0(sizeof(TriggerDesc));
1234 trigdesc->triggers = triggers;
1235 trigdesc->numtriggers = ntrigs;
1236 for (found = 0; found < ntrigs; found++)
1237 InsertTrigger(trigdesc, &(triggers[found]), found);
1239 /* Copy completed trigdesc into cache storage */
1240 oldContext = MemoryContextSwitchTo(CacheMemoryContext);
1241 relation->trigdesc = CopyTriggerDesc(trigdesc);
1242 MemoryContextSwitchTo(oldContext);
1244 /* Release working memory */
1245 FreeTriggerDesc(trigdesc);
1249 * Insert the given trigger into the appropriate index list(s) for it
1251 * To simplify storage management, we allocate each index list at the max
1252 * possible size (trigdesc->numtriggers) if it's used at all. This does
1253 * not waste space permanently since we're only building a temporary
1254 * trigdesc at this point.
1256 static void
1257 InsertTrigger(TriggerDesc *trigdesc, Trigger *trigger, int indx)
1259 uint16 *n;
1260 int **t,
1261 **tp;
1263 if (TRIGGER_FOR_ROW(trigger->tgtype))
1265 /* ROW trigger */
1266 if (TRIGGER_FOR_BEFORE(trigger->tgtype))
1268 n = trigdesc->n_before_row;
1269 t = trigdesc->tg_before_row;
1271 else
1273 n = trigdesc->n_after_row;
1274 t = trigdesc->tg_after_row;
1277 else
1279 /* STATEMENT trigger */
1280 if (TRIGGER_FOR_BEFORE(trigger->tgtype))
1282 n = trigdesc->n_before_statement;
1283 t = trigdesc->tg_before_statement;
1285 else
1287 n = trigdesc->n_after_statement;
1288 t = trigdesc->tg_after_statement;
1292 if (TRIGGER_FOR_INSERT(trigger->tgtype))
1294 tp = &(t[TRIGGER_EVENT_INSERT]);
1295 if (*tp == NULL)
1296 *tp = (int *) palloc(trigdesc->numtriggers * sizeof(int));
1297 (*tp)[n[TRIGGER_EVENT_INSERT]] = indx;
1298 (n[TRIGGER_EVENT_INSERT])++;
1301 if (TRIGGER_FOR_DELETE(trigger->tgtype))
1303 tp = &(t[TRIGGER_EVENT_DELETE]);
1304 if (*tp == NULL)
1305 *tp = (int *) palloc(trigdesc->numtriggers * sizeof(int));
1306 (*tp)[n[TRIGGER_EVENT_DELETE]] = indx;
1307 (n[TRIGGER_EVENT_DELETE])++;
1310 if (TRIGGER_FOR_UPDATE(trigger->tgtype))
1312 tp = &(t[TRIGGER_EVENT_UPDATE]);
1313 if (*tp == NULL)
1314 *tp = (int *) palloc(trigdesc->numtriggers * sizeof(int));
1315 (*tp)[n[TRIGGER_EVENT_UPDATE]] = indx;
1316 (n[TRIGGER_EVENT_UPDATE])++;
1319 if (TRIGGER_FOR_TRUNCATE(trigger->tgtype))
1321 tp = &(t[TRIGGER_EVENT_TRUNCATE]);
1322 if (*tp == NULL)
1323 *tp = (int *) palloc(trigdesc->numtriggers * sizeof(int));
1324 (*tp)[n[TRIGGER_EVENT_TRUNCATE]] = indx;
1325 (n[TRIGGER_EVENT_TRUNCATE])++;
1330 * Copy a TriggerDesc data structure.
1332 * The copy is allocated in the current memory context.
1334 TriggerDesc *
1335 CopyTriggerDesc(TriggerDesc *trigdesc)
1337 TriggerDesc *newdesc;
1338 uint16 *n;
1339 int **t,
1340 *tnew;
1341 Trigger *trigger;
1342 int i;
1344 if (trigdesc == NULL || trigdesc->numtriggers <= 0)
1345 return NULL;
1347 newdesc = (TriggerDesc *) palloc(sizeof(TriggerDesc));
1348 memcpy(newdesc, trigdesc, sizeof(TriggerDesc));
1350 trigger = (Trigger *) palloc(trigdesc->numtriggers * sizeof(Trigger));
1351 memcpy(trigger, trigdesc->triggers,
1352 trigdesc->numtriggers * sizeof(Trigger));
1353 newdesc->triggers = trigger;
1355 for (i = 0; i < trigdesc->numtriggers; i++)
1357 trigger->tgname = pstrdup(trigger->tgname);
1358 if (trigger->tgnattr > 0)
1360 int2 *newattr;
1362 newattr = (int2 *) palloc(trigger->tgnattr * sizeof(int2));
1363 memcpy(newattr, trigger->tgattr,
1364 trigger->tgnattr * sizeof(int2));
1365 trigger->tgattr = newattr;
1367 if (trigger->tgnargs > 0)
1369 char **newargs;
1370 int16 j;
1372 newargs = (char **) palloc(trigger->tgnargs * sizeof(char *));
1373 for (j = 0; j < trigger->tgnargs; j++)
1374 newargs[j] = pstrdup(trigger->tgargs[j]);
1375 trigger->tgargs = newargs;
1377 trigger++;
1380 n = newdesc->n_before_statement;
1381 t = newdesc->tg_before_statement;
1382 for (i = 0; i < TRIGGER_NUM_EVENT_CLASSES; i++)
1384 if (n[i] > 0)
1386 tnew = (int *) palloc(n[i] * sizeof(int));
1387 memcpy(tnew, t[i], n[i] * sizeof(int));
1388 t[i] = tnew;
1390 else
1391 t[i] = NULL;
1393 n = newdesc->n_before_row;
1394 t = newdesc->tg_before_row;
1395 for (i = 0; i < TRIGGER_NUM_EVENT_CLASSES; i++)
1397 if (n[i] > 0)
1399 tnew = (int *) palloc(n[i] * sizeof(int));
1400 memcpy(tnew, t[i], n[i] * sizeof(int));
1401 t[i] = tnew;
1403 else
1404 t[i] = NULL;
1406 n = newdesc->n_after_row;
1407 t = newdesc->tg_after_row;
1408 for (i = 0; i < TRIGGER_NUM_EVENT_CLASSES; i++)
1410 if (n[i] > 0)
1412 tnew = (int *) palloc(n[i] * sizeof(int));
1413 memcpy(tnew, t[i], n[i] * sizeof(int));
1414 t[i] = tnew;
1416 else
1417 t[i] = NULL;
1419 n = newdesc->n_after_statement;
1420 t = newdesc->tg_after_statement;
1421 for (i = 0; i < TRIGGER_NUM_EVENT_CLASSES; i++)
1423 if (n[i] > 0)
1425 tnew = (int *) palloc(n[i] * sizeof(int));
1426 memcpy(tnew, t[i], n[i] * sizeof(int));
1427 t[i] = tnew;
1429 else
1430 t[i] = NULL;
1433 return newdesc;
1437 * Free a TriggerDesc data structure.
1439 void
1440 FreeTriggerDesc(TriggerDesc *trigdesc)
1442 int **t;
1443 Trigger *trigger;
1444 int i;
1446 if (trigdesc == NULL)
1447 return;
1449 t = trigdesc->tg_before_statement;
1450 for (i = 0; i < TRIGGER_NUM_EVENT_CLASSES; i++)
1451 if (t[i] != NULL)
1452 pfree(t[i]);
1453 t = trigdesc->tg_before_row;
1454 for (i = 0; i < TRIGGER_NUM_EVENT_CLASSES; i++)
1455 if (t[i] != NULL)
1456 pfree(t[i]);
1457 t = trigdesc->tg_after_row;
1458 for (i = 0; i < TRIGGER_NUM_EVENT_CLASSES; i++)
1459 if (t[i] != NULL)
1460 pfree(t[i]);
1461 t = trigdesc->tg_after_statement;
1462 for (i = 0; i < TRIGGER_NUM_EVENT_CLASSES; i++)
1463 if (t[i] != NULL)
1464 pfree(t[i]);
1466 trigger = trigdesc->triggers;
1467 for (i = 0; i < trigdesc->numtriggers; i++)
1469 pfree(trigger->tgname);
1470 if (trigger->tgnattr > 0)
1471 pfree(trigger->tgattr);
1472 if (trigger->tgnargs > 0)
1474 while (--(trigger->tgnargs) >= 0)
1475 pfree(trigger->tgargs[trigger->tgnargs]);
1476 pfree(trigger->tgargs);
1478 trigger++;
1480 pfree(trigdesc->triggers);
1481 pfree(trigdesc);
1485 * Compare two TriggerDesc structures for logical equality.
1487 #ifdef NOT_USED
1488 bool
1489 equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
1491 int i,
1495 * We need not examine the "index" data, just the trigger array itself; if
1496 * we have the same triggers with the same types, the derived index data
1497 * should match.
1499 * As of 7.3 we assume trigger set ordering is significant in the
1500 * comparison; so we just compare corresponding slots of the two sets.
1502 if (trigdesc1 != NULL)
1504 if (trigdesc2 == NULL)
1505 return false;
1506 if (trigdesc1->numtriggers != trigdesc2->numtriggers)
1507 return false;
1508 for (i = 0; i < trigdesc1->numtriggers; i++)
1510 Trigger *trig1 = trigdesc1->triggers + i;
1511 Trigger *trig2 = trigdesc2->triggers + i;
1513 if (trig1->tgoid != trig2->tgoid)
1514 return false;
1515 if (strcmp(trig1->tgname, trig2->tgname) != 0)
1516 return false;
1517 if (trig1->tgfoid != trig2->tgfoid)
1518 return false;
1519 if (trig1->tgtype != trig2->tgtype)
1520 return false;
1521 if (trig1->tgenabled != trig2->tgenabled)
1522 return false;
1523 if (trig1->tgisconstraint != trig2->tgisconstraint)
1524 return false;
1525 if (trig1->tgconstrrelid != trig2->tgconstrrelid)
1526 return false;
1527 if (trig1->tgconstraint != trig2->tgconstraint)
1528 return false;
1529 if (trig1->tgdeferrable != trig2->tgdeferrable)
1530 return false;
1531 if (trig1->tginitdeferred != trig2->tginitdeferred)
1532 return false;
1533 if (trig1->tgnargs != trig2->tgnargs)
1534 return false;
1535 if (trig1->tgnattr != trig2->tgnattr)
1536 return false;
1537 if (trig1->tgnattr > 0 &&
1538 memcmp(trig1->tgattr, trig2->tgattr,
1539 trig1->tgnattr * sizeof(int2)) != 0)
1540 return false;
1541 for (j = 0; j < trig1->tgnargs; j++)
1542 if (strcmp(trig1->tgargs[j], trig2->tgargs[j]) != 0)
1543 return false;
1546 else if (trigdesc2 != NULL)
1547 return false;
1548 return true;
1550 #endif /* NOT_USED */
1553 * Call a trigger function.
1555 * trigdata: trigger descriptor.
1556 * tgindx: trigger's index in finfo and instr arrays.
1557 * finfo: array of cached trigger function call information.
1558 * instr: optional array of EXPLAIN ANALYZE instrumentation state.
1559 * per_tuple_context: memory context to execute the function in.
1561 * Returns the tuple (or NULL) as returned by the function.
1563 static HeapTuple
1564 ExecCallTriggerFunc(TriggerData *trigdata,
1565 int tgindx,
1566 FmgrInfo *finfo,
1567 Instrumentation *instr,
1568 MemoryContext per_tuple_context)
1570 FunctionCallInfoData fcinfo;
1571 PgStat_FunctionCallUsage fcusage;
1572 Datum result;
1573 MemoryContext oldContext;
1575 finfo += tgindx;
1578 * We cache fmgr lookup info, to avoid making the lookup again on each
1579 * call.
1581 if (finfo->fn_oid == InvalidOid)
1582 fmgr_info(trigdata->tg_trigger->tgfoid, finfo);
1584 Assert(finfo->fn_oid == trigdata->tg_trigger->tgfoid);
1587 * If doing EXPLAIN ANALYZE, start charging time to this trigger.
1589 if (instr)
1590 InstrStartNode(instr + tgindx);
1593 * Do the function evaluation in the per-tuple memory context, so that
1594 * leaked memory will be reclaimed once per tuple. Note in particular that
1595 * any new tuple created by the trigger function will live till the end of
1596 * the tuple cycle.
1598 oldContext = MemoryContextSwitchTo(per_tuple_context);
1601 * Call the function, passing no arguments but setting a context.
1603 InitFunctionCallInfoData(fcinfo, finfo, 0, (Node *) trigdata, NULL);
1605 pgstat_init_function_usage(&fcinfo, &fcusage);
1607 result = FunctionCallInvoke(&fcinfo);
1609 pgstat_end_function_usage(&fcusage, true);
1611 MemoryContextSwitchTo(oldContext);
1614 * Trigger protocol allows function to return a null pointer, but NOT to
1615 * set the isnull result flag.
1617 if (fcinfo.isnull)
1618 ereport(ERROR,
1619 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
1620 errmsg("trigger function %u returned null value",
1621 fcinfo.flinfo->fn_oid)));
1624 * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
1625 * one "tuple returned" (really the number of firings).
1627 if (instr)
1628 InstrStopNode(instr + tgindx, 1);
1630 return (HeapTuple) DatumGetPointer(result);
1633 void
1634 ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
1636 TriggerDesc *trigdesc;
1637 int ntrigs;
1638 int *tgindx;
1639 int i;
1640 TriggerData LocTriggerData;
1642 trigdesc = relinfo->ri_TrigDesc;
1644 if (trigdesc == NULL)
1645 return;
1647 ntrigs = trigdesc->n_before_statement[TRIGGER_EVENT_INSERT];
1648 tgindx = trigdesc->tg_before_statement[TRIGGER_EVENT_INSERT];
1650 if (ntrigs == 0)
1651 return;
1653 LocTriggerData.type = T_TriggerData;
1654 LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
1655 TRIGGER_EVENT_BEFORE;
1656 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
1657 LocTriggerData.tg_trigtuple = NULL;
1658 LocTriggerData.tg_newtuple = NULL;
1659 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
1660 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
1661 for (i = 0; i < ntrigs; i++)
1663 Trigger *trigger = &trigdesc->triggers[tgindx[i]];
1664 HeapTuple newtuple;
1666 if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
1668 if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
1669 trigger->tgenabled == TRIGGER_DISABLED)
1670 continue;
1672 else /* ORIGIN or LOCAL role */
1674 if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
1675 trigger->tgenabled == TRIGGER_DISABLED)
1676 continue;
1678 LocTriggerData.tg_trigger = trigger;
1679 newtuple = ExecCallTriggerFunc(&LocTriggerData,
1680 tgindx[i],
1681 relinfo->ri_TrigFunctions,
1682 relinfo->ri_TrigInstrument,
1683 GetPerTupleMemoryContext(estate));
1685 if (newtuple)
1686 ereport(ERROR,
1687 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
1688 errmsg("BEFORE STATEMENT trigger cannot return a value")));
1692 void
1693 ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo)
1695 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
1697 if (trigdesc && trigdesc->n_after_statement[TRIGGER_EVENT_INSERT] > 0)
1698 AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_INSERT,
1699 false, NULL, NULL);
1702 HeapTuple
1703 ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
1704 HeapTuple trigtuple)
1706 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
1707 int ntrigs = trigdesc->n_before_row[TRIGGER_EVENT_INSERT];
1708 int *tgindx = trigdesc->tg_before_row[TRIGGER_EVENT_INSERT];
1709 HeapTuple newtuple = trigtuple;
1710 HeapTuple oldtuple;
1711 TriggerData LocTriggerData;
1712 int i;
1714 LocTriggerData.type = T_TriggerData;
1715 LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
1716 TRIGGER_EVENT_ROW |
1717 TRIGGER_EVENT_BEFORE;
1718 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
1719 LocTriggerData.tg_newtuple = NULL;
1720 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
1721 for (i = 0; i < ntrigs; i++)
1723 Trigger *trigger = &trigdesc->triggers[tgindx[i]];
1725 if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
1727 if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
1728 trigger->tgenabled == TRIGGER_DISABLED)
1729 continue;
1731 else /* ORIGIN or LOCAL role */
1733 if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
1734 trigger->tgenabled == TRIGGER_DISABLED)
1735 continue;
1737 LocTriggerData.tg_trigtuple = oldtuple = newtuple;
1738 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
1739 LocTriggerData.tg_trigger = trigger;
1740 newtuple = ExecCallTriggerFunc(&LocTriggerData,
1741 tgindx[i],
1742 relinfo->ri_TrigFunctions,
1743 relinfo->ri_TrigInstrument,
1744 GetPerTupleMemoryContext(estate));
1745 if (oldtuple != newtuple && oldtuple != trigtuple)
1746 heap_freetuple(oldtuple);
1747 if (newtuple == NULL)
1748 break;
1750 return newtuple;
1753 void
1754 ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo,
1755 HeapTuple trigtuple)
1757 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
1759 if (trigdesc && trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0)
1760 AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_INSERT,
1761 true, NULL, trigtuple);
1764 void
1765 ExecBSDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
1767 TriggerDesc *trigdesc;
1768 int ntrigs;
1769 int *tgindx;
1770 int i;
1771 TriggerData LocTriggerData;
1773 trigdesc = relinfo->ri_TrigDesc;
1775 if (trigdesc == NULL)
1776 return;
1778 ntrigs = trigdesc->n_before_statement[TRIGGER_EVENT_DELETE];
1779 tgindx = trigdesc->tg_before_statement[TRIGGER_EVENT_DELETE];
1781 if (ntrigs == 0)
1782 return;
1784 LocTriggerData.type = T_TriggerData;
1785 LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
1786 TRIGGER_EVENT_BEFORE;
1787 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
1788 LocTriggerData.tg_trigtuple = NULL;
1789 LocTriggerData.tg_newtuple = NULL;
1790 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
1791 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
1792 for (i = 0; i < ntrigs; i++)
1794 Trigger *trigger = &trigdesc->triggers[tgindx[i]];
1795 HeapTuple newtuple;
1797 if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
1799 if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
1800 trigger->tgenabled == TRIGGER_DISABLED)
1801 continue;
1803 else /* ORIGIN or LOCAL role */
1805 if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
1806 trigger->tgenabled == TRIGGER_DISABLED)
1807 continue;
1809 LocTriggerData.tg_trigger = trigger;
1810 newtuple = ExecCallTriggerFunc(&LocTriggerData,
1811 tgindx[i],
1812 relinfo->ri_TrigFunctions,
1813 relinfo->ri_TrigInstrument,
1814 GetPerTupleMemoryContext(estate));
1816 if (newtuple)
1817 ereport(ERROR,
1818 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
1819 errmsg("BEFORE STATEMENT trigger cannot return a value")));
1823 void
1824 ExecASDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
1826 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
1828 if (trigdesc && trigdesc->n_after_statement[TRIGGER_EVENT_DELETE] > 0)
1829 AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_DELETE,
1830 false, NULL, NULL);
1833 bool
1834 ExecBRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
1835 ItemPointer tupleid)
1837 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
1838 int ntrigs = trigdesc->n_before_row[TRIGGER_EVENT_DELETE];
1839 int *tgindx = trigdesc->tg_before_row[TRIGGER_EVENT_DELETE];
1840 bool result = true;
1841 TriggerData LocTriggerData;
1842 HeapTuple trigtuple;
1843 HeapTuple newtuple;
1844 TupleTableSlot *newSlot;
1845 int i;
1847 trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, &newSlot);
1848 if (trigtuple == NULL)
1849 return false;
1851 LocTriggerData.type = T_TriggerData;
1852 LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
1853 TRIGGER_EVENT_ROW |
1854 TRIGGER_EVENT_BEFORE;
1855 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
1856 LocTriggerData.tg_newtuple = NULL;
1857 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
1858 for (i = 0; i < ntrigs; i++)
1860 Trigger *trigger = &trigdesc->triggers[tgindx[i]];
1862 if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
1864 if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
1865 trigger->tgenabled == TRIGGER_DISABLED)
1866 continue;
1868 else /* ORIGIN or LOCAL role */
1870 if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
1871 trigger->tgenabled == TRIGGER_DISABLED)
1872 continue;
1874 LocTriggerData.tg_trigtuple = trigtuple;
1875 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
1876 LocTriggerData.tg_trigger = trigger;
1877 newtuple = ExecCallTriggerFunc(&LocTriggerData,
1878 tgindx[i],
1879 relinfo->ri_TrigFunctions,
1880 relinfo->ri_TrigInstrument,
1881 GetPerTupleMemoryContext(estate));
1882 if (newtuple == NULL)
1884 result = false; /* tell caller to suppress delete */
1885 break;
1887 if (newtuple != trigtuple)
1888 heap_freetuple(newtuple);
1890 heap_freetuple(trigtuple);
1892 return result;
1895 void
1896 ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
1897 ItemPointer tupleid)
1899 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
1901 if (trigdesc && trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
1903 HeapTuple trigtuple = GetTupleForTrigger(estate, relinfo,
1904 tupleid, NULL);
1906 AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_DELETE,
1907 true, trigtuple, NULL);
1908 heap_freetuple(trigtuple);
1912 void
1913 ExecBSUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
1915 TriggerDesc *trigdesc;
1916 int ntrigs;
1917 int *tgindx;
1918 int i;
1919 TriggerData LocTriggerData;
1921 trigdesc = relinfo->ri_TrigDesc;
1923 if (trigdesc == NULL)
1924 return;
1926 ntrigs = trigdesc->n_before_statement[TRIGGER_EVENT_UPDATE];
1927 tgindx = trigdesc->tg_before_statement[TRIGGER_EVENT_UPDATE];
1929 if (ntrigs == 0)
1930 return;
1932 LocTriggerData.type = T_TriggerData;
1933 LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
1934 TRIGGER_EVENT_BEFORE;
1935 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
1936 LocTriggerData.tg_trigtuple = NULL;
1937 LocTriggerData.tg_newtuple = NULL;
1938 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
1939 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
1940 for (i = 0; i < ntrigs; i++)
1942 Trigger *trigger = &trigdesc->triggers[tgindx[i]];
1943 HeapTuple newtuple;
1945 if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
1947 if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
1948 trigger->tgenabled == TRIGGER_DISABLED)
1949 continue;
1951 else /* ORIGIN or LOCAL role */
1953 if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
1954 trigger->tgenabled == TRIGGER_DISABLED)
1955 continue;
1957 LocTriggerData.tg_trigger = trigger;
1958 newtuple = ExecCallTriggerFunc(&LocTriggerData,
1959 tgindx[i],
1960 relinfo->ri_TrigFunctions,
1961 relinfo->ri_TrigInstrument,
1962 GetPerTupleMemoryContext(estate));
1964 if (newtuple)
1965 ereport(ERROR,
1966 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
1967 errmsg("BEFORE STATEMENT trigger cannot return a value")));
1971 void
1972 ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
1974 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
1976 if (trigdesc && trigdesc->n_after_statement[TRIGGER_EVENT_UPDATE] > 0)
1977 AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_UPDATE,
1978 false, NULL, NULL);
1981 HeapTuple
1982 ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
1983 ItemPointer tupleid, HeapTuple newtuple)
1985 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
1986 int ntrigs = trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
1987 int *tgindx = trigdesc->tg_before_row[TRIGGER_EVENT_UPDATE];
1988 TriggerData LocTriggerData;
1989 HeapTuple trigtuple;
1990 HeapTuple oldtuple;
1991 HeapTuple intuple = newtuple;
1992 TupleTableSlot *newSlot;
1993 int i;
1995 trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, &newSlot);
1996 if (trigtuple == NULL)
1997 return NULL;
2000 * In READ COMMITTED isolation level it's possible that newtuple was
2001 * changed due to concurrent update.
2003 if (newSlot != NULL)
2004 intuple = newtuple = ExecRemoveJunk(estate->es_junkFilter, newSlot);
2006 LocTriggerData.type = T_TriggerData;
2007 LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
2008 TRIGGER_EVENT_ROW |
2009 TRIGGER_EVENT_BEFORE;
2010 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2011 for (i = 0; i < ntrigs; i++)
2013 Trigger *trigger = &trigdesc->triggers[tgindx[i]];
2015 if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
2017 if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
2018 trigger->tgenabled == TRIGGER_DISABLED)
2019 continue;
2021 else /* ORIGIN or LOCAL role */
2023 if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
2024 trigger->tgenabled == TRIGGER_DISABLED)
2025 continue;
2027 LocTriggerData.tg_trigtuple = trigtuple;
2028 LocTriggerData.tg_newtuple = oldtuple = newtuple;
2029 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2030 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2031 LocTriggerData.tg_trigger = trigger;
2032 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2033 tgindx[i],
2034 relinfo->ri_TrigFunctions,
2035 relinfo->ri_TrigInstrument,
2036 GetPerTupleMemoryContext(estate));
2037 if (oldtuple != newtuple && oldtuple != intuple)
2038 heap_freetuple(oldtuple);
2039 if (newtuple == NULL)
2040 break;
2042 heap_freetuple(trigtuple);
2043 return newtuple;
2046 void
2047 ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
2048 ItemPointer tupleid, HeapTuple newtuple)
2050 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2052 if (trigdesc && trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0)
2054 HeapTuple trigtuple = GetTupleForTrigger(estate, relinfo,
2055 tupleid, NULL);
2057 AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_UPDATE,
2058 true, trigtuple, newtuple);
2059 heap_freetuple(trigtuple);
2063 void
2064 ExecBSTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
2066 TriggerDesc *trigdesc;
2067 int ntrigs;
2068 int *tgindx;
2069 int i;
2070 TriggerData LocTriggerData;
2072 trigdesc = relinfo->ri_TrigDesc;
2074 if (trigdesc == NULL)
2075 return;
2077 ntrigs = trigdesc->n_before_statement[TRIGGER_EVENT_TRUNCATE];
2078 tgindx = trigdesc->tg_before_statement[TRIGGER_EVENT_TRUNCATE];
2080 if (ntrigs == 0)
2081 return;
2083 LocTriggerData.type = T_TriggerData;
2084 LocTriggerData.tg_event = TRIGGER_EVENT_TRUNCATE |
2085 TRIGGER_EVENT_BEFORE;
2086 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2087 LocTriggerData.tg_trigtuple = NULL;
2088 LocTriggerData.tg_newtuple = NULL;
2089 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2090 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2091 for (i = 0; i < ntrigs; i++)
2093 Trigger *trigger = &trigdesc->triggers[tgindx[i]];
2094 HeapTuple newtuple;
2096 if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
2098 if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
2099 trigger->tgenabled == TRIGGER_DISABLED)
2100 continue;
2102 else /* ORIGIN or LOCAL role */
2104 if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
2105 trigger->tgenabled == TRIGGER_DISABLED)
2106 continue;
2108 LocTriggerData.tg_trigger = trigger;
2109 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2110 tgindx[i],
2111 relinfo->ri_TrigFunctions,
2112 relinfo->ri_TrigInstrument,
2113 GetPerTupleMemoryContext(estate));
2115 if (newtuple)
2116 ereport(ERROR,
2117 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2118 errmsg("BEFORE STATEMENT trigger cannot return a value")));
2122 void
2123 ExecASTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
2125 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2127 if (trigdesc && trigdesc->n_after_statement[TRIGGER_EVENT_TRUNCATE] > 0)
2128 AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_TRUNCATE,
2129 false, NULL, NULL);
2133 static HeapTuple
2134 GetTupleForTrigger(EState *estate, ResultRelInfo *relinfo,
2135 ItemPointer tid,
2136 TupleTableSlot **newSlot)
2138 Relation relation = relinfo->ri_RelationDesc;
2139 HeapTupleData tuple;
2140 HeapTuple result;
2141 Buffer buffer;
2143 if (newSlot != NULL)
2145 HTSU_Result test;
2146 ItemPointerData update_ctid;
2147 TransactionId update_xmax;
2149 *newSlot = NULL;
2152 * lock tuple for update
2154 ltrmark:;
2155 tuple.t_self = *tid;
2156 test = heap_lock_tuple(relation, &tuple, &buffer,
2157 &update_ctid, &update_xmax,
2158 estate->es_output_cid,
2159 LockTupleExclusive, false);
2160 switch (test)
2162 case HeapTupleSelfUpdated:
2163 /* treat it as deleted; do not process */
2164 ReleaseBuffer(buffer);
2165 return NULL;
2167 case HeapTupleMayBeUpdated:
2168 break;
2170 case HeapTupleUpdated:
2171 ReleaseBuffer(buffer);
2172 if (IsXactIsoLevelSerializable)
2173 ereport(ERROR,
2174 (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
2175 errmsg("could not serialize access due to concurrent update")));
2176 else if (!ItemPointerEquals(&update_ctid, &tuple.t_self))
2178 /* it was updated, so look at the updated version */
2179 TupleTableSlot *epqslot;
2181 epqslot = EvalPlanQual(estate,
2182 relinfo->ri_RangeTableIndex,
2183 &update_ctid,
2184 update_xmax);
2185 if (!TupIsNull(epqslot))
2187 *tid = update_ctid;
2188 *newSlot = epqslot;
2189 goto ltrmark;
2194 * if tuple was deleted or PlanQual failed for updated tuple -
2195 * we have not process this tuple!
2197 return NULL;
2199 default:
2200 ReleaseBuffer(buffer);
2201 elog(ERROR, "unrecognized heap_lock_tuple status: %u", test);
2202 return NULL; /* keep compiler quiet */
2205 else
2207 Page page;
2208 ItemId lp;
2210 buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
2212 page = BufferGetPage(buffer);
2213 lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
2215 Assert(ItemIdIsNormal(lp));
2217 tuple.t_data = (HeapTupleHeader) PageGetItem(page, lp);
2218 tuple.t_len = ItemIdGetLength(lp);
2219 tuple.t_self = *tid;
2220 tuple.t_tableOid = RelationGetRelid(relation);
2223 result = heap_copytuple(&tuple);
2224 ReleaseBuffer(buffer);
2226 return result;
2230 /* ----------
2231 * After-trigger stuff
2233 * The AfterTriggersData struct holds data about pending AFTER trigger events
2234 * during the current transaction tree. (BEFORE triggers are fired
2235 * immediately so we don't need any persistent state about them.) The struct
2236 * and most of its subsidiary data are kept in TopTransactionContext; however
2237 * the individual event records are kept in separate contexts, to make them
2238 * easy to delete during subtransaction abort.
2240 * Because the list of pending events can grow large, we go to some effort
2241 * to minimize memory consumption. We do not use the generic List mechanism
2242 * but thread the events manually.
2244 * XXX We need to be able to save the per-event data in a file if it grows too
2245 * large.
2246 * ----------
2249 /* Per-trigger SET CONSTRAINT status */
2250 typedef struct SetConstraintTriggerData
2252 Oid sct_tgoid;
2253 bool sct_tgisdeferred;
2254 } SetConstraintTriggerData;
2256 typedef struct SetConstraintTriggerData *SetConstraintTrigger;
2259 * SET CONSTRAINT intra-transaction status.
2261 * We make this a single palloc'd object so it can be copied and freed easily.
2263 * all_isset and all_isdeferred are used to keep track
2264 * of SET CONSTRAINTS ALL {DEFERRED, IMMEDIATE}.
2266 * trigstates[] stores per-trigger tgisdeferred settings.
2268 typedef struct SetConstraintStateData
2270 bool all_isset;
2271 bool all_isdeferred;
2272 int numstates; /* number of trigstates[] entries in use */
2273 int numalloc; /* allocated size of trigstates[] */
2274 SetConstraintTriggerData trigstates[1]; /* VARIABLE LENGTH ARRAY */
2275 } SetConstraintStateData;
2277 typedef SetConstraintStateData *SetConstraintState;
2281 * Per-trigger-event data
2283 * Note: ate_firing_id is meaningful when either AFTER_TRIGGER_DONE
2284 * or AFTER_TRIGGER_IN_PROGRESS is set. It indicates which trigger firing
2285 * cycle the trigger was or will be fired in.
2287 typedef struct AfterTriggerEventData *AfterTriggerEvent;
2289 typedef struct AfterTriggerEventData
2291 AfterTriggerEvent ate_next; /* list link */
2292 TriggerEvent ate_event; /* event type and status bits */
2293 CommandId ate_firing_id; /* ID for firing cycle */
2294 Oid ate_tgoid; /* the trigger's ID */
2295 Oid ate_relid; /* the relation it's on */
2296 ItemPointerData ate_oldctid; /* specific tuple(s) involved */
2297 ItemPointerData ate_newctid;
2298 } AfterTriggerEventData;
2300 /* A list of events */
2301 typedef struct AfterTriggerEventList
2303 AfterTriggerEvent head;
2304 AfterTriggerEvent tail;
2305 } AfterTriggerEventList;
2309 * All per-transaction data for the AFTER TRIGGERS module.
2311 * AfterTriggersData has the following fields:
2313 * firing_counter is incremented for each call of afterTriggerInvokeEvents.
2314 * We mark firable events with the current firing cycle's ID so that we can
2315 * tell which ones to work on. This ensures sane behavior if a trigger
2316 * function chooses to do SET CONSTRAINTS: the inner SET CONSTRAINTS will
2317 * only fire those events that weren't already scheduled for firing.
2319 * state keeps track of the transaction-local effects of SET CONSTRAINTS.
2320 * This is saved and restored across failed subtransactions.
2322 * events is the current list of deferred events. This is global across
2323 * all subtransactions of the current transaction. In a subtransaction
2324 * abort, we know that the events added by the subtransaction are at the
2325 * end of the list, so it is relatively easy to discard them. The event
2326 * structs themselves are stored in event_cxt if generated by the top-level
2327 * transaction, else in per-subtransaction contexts identified by the
2328 * entries in cxt_stack.
2330 * query_depth is the current depth of nested AfterTriggerBeginQuery calls
2331 * (-1 when the stack is empty).
2333 * query_stack[query_depth] is a list of AFTER trigger events queued by the
2334 * current query (and the query_stack entries below it are lists of trigger
2335 * events queued by calling queries). None of these are valid until the
2336 * matching AfterTriggerEndQuery call occurs. At that point we fire
2337 * immediate-mode triggers, and append any deferred events to the main events
2338 * list.
2340 * maxquerydepth is just the allocated length of query_stack.
2342 * state_stack is a stack of pointers to saved copies of the SET CONSTRAINTS
2343 * state data; each subtransaction level that modifies that state first
2344 * saves a copy, which we use to restore the state if we abort.
2346 * events_stack is a stack of copies of the events head/tail pointers,
2347 * which we use to restore those values during subtransaction abort.
2349 * depth_stack is a stack of copies of subtransaction-start-time query_depth,
2350 * which we similarly use to clean up at subtransaction abort.
2352 * firing_stack is a stack of copies of subtransaction-start-time
2353 * firing_counter. We use this to recognize which deferred triggers were
2354 * fired (or marked for firing) within an aborted subtransaction.
2356 * We use GetCurrentTransactionNestLevel() to determine the correct array
2357 * index in these stacks. maxtransdepth is the number of allocated entries in
2358 * each stack. (By not keeping our own stack pointer, we can avoid trouble
2359 * in cases where errors during subxact abort cause multiple invocations
2360 * of AfterTriggerEndSubXact() at the same nesting depth.)
2362 typedef struct AfterTriggersData
2364 CommandId firing_counter; /* next firing ID to assign */
2365 SetConstraintState state; /* the active S C state */
2366 AfterTriggerEventList events; /* deferred-event list */
2367 int query_depth; /* current query list index */
2368 AfterTriggerEventList *query_stack; /* events pending from each query */
2369 int maxquerydepth; /* allocated len of above array */
2370 MemoryContext event_cxt; /* top transaction's event context, if any */
2371 MemoryContext *cxt_stack; /* per-subtransaction event contexts */
2373 /* these fields are just for resetting at subtrans abort: */
2375 SetConstraintState *state_stack; /* stacked S C states */
2376 AfterTriggerEventList *events_stack; /* stacked list pointers */
2377 int *depth_stack; /* stacked query_depths */
2378 CommandId *firing_stack; /* stacked firing_counters */
2379 int maxtransdepth; /* allocated len of above arrays */
2380 } AfterTriggersData;
2382 typedef AfterTriggersData *AfterTriggers;
2384 static AfterTriggers afterTriggers;
2387 static void AfterTriggerExecute(AfterTriggerEvent event,
2388 Relation rel, TriggerDesc *trigdesc,
2389 FmgrInfo *finfo,
2390 Instrumentation *instr,
2391 MemoryContext per_tuple_context);
2392 static SetConstraintState SetConstraintStateCreate(int numalloc);
2393 static SetConstraintState SetConstraintStateCopy(SetConstraintState state);
2394 static SetConstraintState SetConstraintStateAddItem(SetConstraintState state,
2395 Oid tgoid, bool tgisdeferred);
2398 /* ----------
2399 * afterTriggerCheckState()
2401 * Returns true if the trigger identified by tgoid is actually
2402 * in state DEFERRED.
2403 * ----------
2405 static bool
2406 afterTriggerCheckState(Oid tgoid, TriggerEvent eventstate)
2408 SetConstraintState state = afterTriggers->state;
2409 int i;
2412 * For not-deferrable triggers (i.e. normal AFTER ROW triggers and
2413 * constraints declared NOT DEFERRABLE), the state is always false.
2415 if ((eventstate & AFTER_TRIGGER_DEFERRABLE) == 0)
2416 return false;
2419 * Check if SET CONSTRAINTS has been executed for this specific trigger.
2421 for (i = 0; i < state->numstates; i++)
2423 if (state->trigstates[i].sct_tgoid == tgoid)
2424 return state->trigstates[i].sct_tgisdeferred;
2428 * Check if SET CONSTRAINTS ALL has been executed; if so use that.
2430 if (state->all_isset)
2431 return state->all_isdeferred;
2434 * Otherwise return the default state for the trigger.
2436 return ((eventstate & AFTER_TRIGGER_INITDEFERRED) != 0);
2440 /* ----------
2441 * afterTriggerAddEvent()
2443 * Add a new trigger event to the current query's queue.
2444 * ----------
2446 static void
2447 afterTriggerAddEvent(AfterTriggerEvent event)
2449 AfterTriggerEventList *events;
2451 Assert(event->ate_next == NULL);
2453 /* Must be inside a query */
2454 Assert(afterTriggers->query_depth >= 0);
2456 events = &afterTriggers->query_stack[afterTriggers->query_depth];
2457 if (events->tail == NULL)
2459 /* first list entry */
2460 events->head = event;
2461 events->tail = event;
2463 else
2465 events->tail->ate_next = event;
2466 events->tail = event;
2471 /* ----------
2472 * AfterTriggerExecute()
2474 * Fetch the required tuples back from the heap and fire one
2475 * single trigger function.
2477 * Frequently, this will be fired many times in a row for triggers of
2478 * a single relation. Therefore, we cache the open relation and provide
2479 * fmgr lookup cache space at the caller level. (For triggers fired at
2480 * the end of a query, we can even piggyback on the executor's state.)
2482 * event: event currently being fired.
2483 * rel: open relation for event.
2484 * trigdesc: working copy of rel's trigger info.
2485 * finfo: array of fmgr lookup cache entries (one per trigger in trigdesc).
2486 * instr: array of EXPLAIN ANALYZE instrumentation nodes (one per trigger),
2487 * or NULL if no instrumentation is wanted.
2488 * per_tuple_context: memory context to call trigger function in.
2489 * ----------
2491 static void
2492 AfterTriggerExecute(AfterTriggerEvent event,
2493 Relation rel, TriggerDesc *trigdesc,
2494 FmgrInfo *finfo, Instrumentation *instr,
2495 MemoryContext per_tuple_context)
2497 Oid tgoid = event->ate_tgoid;
2498 TriggerData LocTriggerData;
2499 HeapTupleData oldtuple;
2500 HeapTupleData newtuple;
2501 HeapTuple rettuple;
2502 Buffer oldbuffer = InvalidBuffer;
2503 Buffer newbuffer = InvalidBuffer;
2504 int tgindx;
2507 * Locate trigger in trigdesc.
2509 LocTriggerData.tg_trigger = NULL;
2510 for (tgindx = 0; tgindx < trigdesc->numtriggers; tgindx++)
2512 if (trigdesc->triggers[tgindx].tgoid == tgoid)
2514 LocTriggerData.tg_trigger = &(trigdesc->triggers[tgindx]);
2515 break;
2518 if (LocTriggerData.tg_trigger == NULL)
2519 elog(ERROR, "could not find trigger %u", tgoid);
2522 * If doing EXPLAIN ANALYZE, start charging time to this trigger. We want
2523 * to include time spent re-fetching tuples in the trigger cost.
2525 if (instr)
2526 InstrStartNode(instr + tgindx);
2529 * Fetch the required OLD and NEW tuples.
2531 LocTriggerData.tg_trigtuple = NULL;
2532 LocTriggerData.tg_newtuple = NULL;
2533 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2534 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2536 if (ItemPointerIsValid(&(event->ate_oldctid)))
2538 ItemPointerCopy(&(event->ate_oldctid), &(oldtuple.t_self));
2539 if (!heap_fetch(rel, SnapshotAny, &oldtuple, &oldbuffer, false, NULL))
2540 elog(ERROR, "failed to fetch old tuple for AFTER trigger");
2541 LocTriggerData.tg_trigtuple = &oldtuple;
2542 LocTriggerData.tg_trigtuplebuf = oldbuffer;
2545 if (ItemPointerIsValid(&(event->ate_newctid)))
2547 ItemPointerCopy(&(event->ate_newctid), &(newtuple.t_self));
2548 if (!heap_fetch(rel, SnapshotAny, &newtuple, &newbuffer, false, NULL))
2549 elog(ERROR, "failed to fetch new tuple for AFTER trigger");
2550 if (LocTriggerData.tg_trigtuple != NULL)
2552 LocTriggerData.tg_newtuple = &newtuple;
2553 LocTriggerData.tg_newtuplebuf = newbuffer;
2555 else
2557 LocTriggerData.tg_trigtuple = &newtuple;
2558 LocTriggerData.tg_trigtuplebuf = newbuffer;
2563 * Setup the remaining trigger information
2565 LocTriggerData.type = T_TriggerData;
2566 LocTriggerData.tg_event =
2567 event->ate_event & (TRIGGER_EVENT_OPMASK | TRIGGER_EVENT_ROW);
2568 LocTriggerData.tg_relation = rel;
2570 MemoryContextReset(per_tuple_context);
2573 * Call the trigger and throw away any possibly returned updated tuple.
2574 * (Don't let ExecCallTriggerFunc measure EXPLAIN time.)
2576 rettuple = ExecCallTriggerFunc(&LocTriggerData,
2577 tgindx,
2578 finfo,
2579 NULL,
2580 per_tuple_context);
2581 if (rettuple != NULL && rettuple != &oldtuple && rettuple != &newtuple)
2582 heap_freetuple(rettuple);
2585 * Release buffers
2587 if (oldbuffer != InvalidBuffer)
2588 ReleaseBuffer(oldbuffer);
2589 if (newbuffer != InvalidBuffer)
2590 ReleaseBuffer(newbuffer);
2593 * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
2594 * one "tuple returned" (really the number of firings).
2596 if (instr)
2597 InstrStopNode(instr + tgindx, 1);
2602 * afterTriggerMarkEvents()
2604 * Scan the given event list for not yet invoked events. Mark the ones
2605 * that can be invoked now with the current firing ID.
2607 * If move_list isn't NULL, events that are not to be invoked now are
2608 * removed from the given list and appended to move_list.
2610 * When immediate_only is TRUE, do not invoke currently-deferred triggers.
2611 * (This will be FALSE only at main transaction exit.)
2613 * Returns TRUE if any invokable events were found.
2615 static bool
2616 afterTriggerMarkEvents(AfterTriggerEventList *events,
2617 AfterTriggerEventList *move_list,
2618 bool immediate_only)
2620 bool found = false;
2621 AfterTriggerEvent event,
2622 prev_event;
2624 prev_event = NULL;
2625 event = events->head;
2627 while (event != NULL)
2629 bool defer_it = false;
2630 AfterTriggerEvent next_event;
2632 if (!(event->ate_event &
2633 (AFTER_TRIGGER_DONE | AFTER_TRIGGER_IN_PROGRESS)))
2636 * This trigger hasn't been called or scheduled yet. Check if we
2637 * should call it now.
2639 if (immediate_only &&
2640 afterTriggerCheckState(event->ate_tgoid, event->ate_event))
2642 defer_it = true;
2644 else
2647 * Mark it as to be fired in this firing cycle.
2649 event->ate_firing_id = afterTriggers->firing_counter;
2650 event->ate_event |= AFTER_TRIGGER_IN_PROGRESS;
2651 found = true;
2656 * If it's deferred, move it to move_list, if requested.
2658 next_event = event->ate_next;
2660 if (defer_it && move_list != NULL)
2662 /* Delink it from input list */
2663 if (prev_event)
2664 prev_event->ate_next = next_event;
2665 else
2666 events->head = next_event;
2667 /* and add it to move_list */
2668 event->ate_next = NULL;
2669 if (move_list->tail == NULL)
2671 /* first list entry */
2672 move_list->head = event;
2673 move_list->tail = event;
2675 else
2677 move_list->tail->ate_next = event;
2678 move_list->tail = event;
2681 else
2683 /* Keep it in input list */
2684 prev_event = event;
2687 event = next_event;
2690 /* Update list tail pointer in case we moved tail event */
2691 events->tail = prev_event;
2693 return found;
2696 /* ----------
2697 * afterTriggerInvokeEvents()
2699 * Scan the given event list for events that are marked as to be fired
2700 * in the current firing cycle, and fire them.
2702 * If estate isn't NULL, we use its result relation info to avoid repeated
2703 * openings and closing of trigger target relations. If it is NULL, we
2704 * make one locally to cache the info in case there are multiple trigger
2705 * events per rel.
2707 * When delete_ok is TRUE, it's okay to delete fully-processed events.
2708 * The events list pointers are updated.
2709 * ----------
2711 static void
2712 afterTriggerInvokeEvents(AfterTriggerEventList *events,
2713 CommandId firing_id,
2714 EState *estate,
2715 bool delete_ok)
2717 AfterTriggerEvent event,
2718 prev_event;
2719 MemoryContext per_tuple_context;
2720 bool local_estate = false;
2721 Relation rel = NULL;
2722 TriggerDesc *trigdesc = NULL;
2723 FmgrInfo *finfo = NULL;
2724 Instrumentation *instr = NULL;
2726 /* Make a local EState if need be */
2727 if (estate == NULL)
2729 estate = CreateExecutorState();
2730 local_estate = true;
2733 /* Make a per-tuple memory context for trigger function calls */
2734 per_tuple_context =
2735 AllocSetContextCreate(CurrentMemoryContext,
2736 "AfterTriggerTupleContext",
2737 ALLOCSET_DEFAULT_MINSIZE,
2738 ALLOCSET_DEFAULT_INITSIZE,
2739 ALLOCSET_DEFAULT_MAXSIZE);
2741 prev_event = NULL;
2742 event = events->head;
2744 while (event != NULL)
2746 AfterTriggerEvent next_event;
2749 * Is it one for me to fire?
2751 if ((event->ate_event & AFTER_TRIGGER_IN_PROGRESS) &&
2752 event->ate_firing_id == firing_id)
2755 * So let's fire it... but first, find the correct relation if
2756 * this is not the same relation as before.
2758 if (rel == NULL || RelationGetRelid(rel) != event->ate_relid)
2760 ResultRelInfo *rInfo;
2762 rInfo = ExecGetTriggerResultRel(estate, event->ate_relid);
2763 rel = rInfo->ri_RelationDesc;
2764 trigdesc = rInfo->ri_TrigDesc;
2765 finfo = rInfo->ri_TrigFunctions;
2766 instr = rInfo->ri_TrigInstrument;
2767 if (trigdesc == NULL) /* should not happen */
2768 elog(ERROR, "relation %u has no triggers",
2769 event->ate_relid);
2773 * Fire it. Note that the AFTER_TRIGGER_IN_PROGRESS flag is still
2774 * set, so recursive examinations of the event list won't try to
2775 * re-fire it.
2777 AfterTriggerExecute(event, rel, trigdesc, finfo, instr,
2778 per_tuple_context);
2781 * Mark the event as done.
2783 event->ate_event &= ~AFTER_TRIGGER_IN_PROGRESS;
2784 event->ate_event |= AFTER_TRIGGER_DONE;
2788 * If it's now done, throw it away, if allowed.
2790 * NB: it's possible the trigger call above added more events to the
2791 * queue, or that calls we will do later will want to add more, so we
2792 * have to be careful about maintaining list validity at all points
2793 * here.
2795 next_event = event->ate_next;
2797 if ((event->ate_event & AFTER_TRIGGER_DONE) && delete_ok)
2799 /* Delink it from list and free it */
2800 if (prev_event)
2801 prev_event->ate_next = next_event;
2802 else
2803 events->head = next_event;
2804 pfree(event);
2806 else
2808 /* Keep it in list */
2809 prev_event = event;
2812 event = next_event;
2815 /* Update list tail pointer in case we just deleted tail event */
2816 events->tail = prev_event;
2818 /* Release working resources */
2819 MemoryContextDelete(per_tuple_context);
2821 if (local_estate)
2823 ListCell *l;
2825 foreach(l, estate->es_trig_target_relations)
2827 ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
2829 /* Close indices and then the relation itself */
2830 ExecCloseIndices(resultRelInfo);
2831 heap_close(resultRelInfo->ri_RelationDesc, NoLock);
2833 FreeExecutorState(estate);
2838 /* ----------
2839 * AfterTriggerBeginXact()
2841 * Called at transaction start (either BEGIN or implicit for single
2842 * statement outside of transaction block).
2843 * ----------
2845 void
2846 AfterTriggerBeginXact(void)
2848 Assert(afterTriggers == NULL);
2851 * Build empty after-trigger state structure
2853 afterTriggers = (AfterTriggers)
2854 MemoryContextAlloc(TopTransactionContext,
2855 sizeof(AfterTriggersData));
2857 afterTriggers->firing_counter = FirstCommandId;
2858 afterTriggers->state = SetConstraintStateCreate(8);
2859 afterTriggers->events.head = NULL;
2860 afterTriggers->events.tail = NULL;
2861 afterTriggers->query_depth = -1;
2863 /* We initialize the query stack to a reasonable size */
2864 afterTriggers->query_stack = (AfterTriggerEventList *)
2865 MemoryContextAlloc(TopTransactionContext,
2866 8 * sizeof(AfterTriggerEventList));
2867 afterTriggers->maxquerydepth = 8;
2869 /* Context for events is created only when needed */
2870 afterTriggers->event_cxt = NULL;
2872 /* Subtransaction stack is empty until/unless needed */
2873 afterTriggers->cxt_stack = NULL;
2874 afterTriggers->state_stack = NULL;
2875 afterTriggers->events_stack = NULL;
2876 afterTriggers->depth_stack = NULL;
2877 afterTriggers->firing_stack = NULL;
2878 afterTriggers->maxtransdepth = 0;
2882 /* ----------
2883 * AfterTriggerBeginQuery()
2885 * Called just before we start processing a single query within a
2886 * transaction (or subtransaction). Set up to record AFTER trigger
2887 * events queued by the query. Note that it is allowed to have
2888 * nested queries within a (sub)transaction.
2889 * ----------
2891 void
2892 AfterTriggerBeginQuery(void)
2894 /* Must be inside a transaction */
2895 Assert(afterTriggers != NULL);
2897 /* Increase the query stack depth */
2898 afterTriggers->query_depth++;
2901 * Allocate more space in the query stack if needed.
2903 if (afterTriggers->query_depth >= afterTriggers->maxquerydepth)
2905 /* repalloc will keep the stack in the same context */
2906 int new_alloc = afterTriggers->maxquerydepth * 2;
2908 afterTriggers->query_stack = (AfterTriggerEventList *)
2909 repalloc(afterTriggers->query_stack,
2910 new_alloc * sizeof(AfterTriggerEventList));
2911 afterTriggers->maxquerydepth = new_alloc;
2914 /* Initialize this query's list to empty */
2915 afterTriggers->query_stack[afterTriggers->query_depth].head = NULL;
2916 afterTriggers->query_stack[afterTriggers->query_depth].tail = NULL;
2920 /* ----------
2921 * AfterTriggerEndQuery()
2923 * Called after one query has been completely processed. At this time
2924 * we invoke all AFTER IMMEDIATE trigger events queued by the query, and
2925 * transfer deferred trigger events to the global deferred-trigger list.
2927 * Note that this should be called just BEFORE closing down the executor
2928 * with ExecutorEnd, because we make use of the EState's info about
2929 * target relations.
2930 * ----------
2932 void
2933 AfterTriggerEndQuery(EState *estate)
2935 AfterTriggerEventList *events;
2937 /* Must be inside a transaction */
2938 Assert(afterTriggers != NULL);
2940 /* Must be inside a query, too */
2941 Assert(afterTriggers->query_depth >= 0);
2944 * Process all immediate-mode triggers queued by the query, and move the
2945 * deferred ones to the main list of deferred events.
2947 * Notice that we decide which ones will be fired, and put the deferred
2948 * ones on the main list, before anything is actually fired. This ensures
2949 * reasonably sane behavior if a trigger function does SET CONSTRAINTS ...
2950 * IMMEDIATE: all events we have decided to defer will be available for it
2951 * to fire.
2953 * We loop in case a trigger queues more events.
2955 * If we find no firable events, we don't have to increment
2956 * firing_counter.
2958 events = &afterTriggers->query_stack[afterTriggers->query_depth];
2959 while (afterTriggerMarkEvents(events, &afterTriggers->events, true))
2961 CommandId firing_id = afterTriggers->firing_counter++;
2963 /* OK to delete the immediate events after processing them */
2964 afterTriggerInvokeEvents(events, firing_id, estate, true);
2967 afterTriggers->query_depth--;
2971 /* ----------
2972 * AfterTriggerFireDeferred()
2974 * Called just before the current transaction is committed. At this
2975 * time we invoke all pending DEFERRED triggers.
2977 * It is possible for other modules to queue additional deferred triggers
2978 * during pre-commit processing; therefore xact.c may have to call this
2979 * multiple times.
2980 * ----------
2982 void
2983 AfterTriggerFireDeferred(void)
2985 AfterTriggerEventList *events;
2986 bool snap_pushed = false;
2988 /* Must be inside a transaction */
2989 Assert(afterTriggers != NULL);
2991 /* ... but not inside a query */
2992 Assert(afterTriggers->query_depth == -1);
2995 * If there are any triggers to fire, make sure we have set a snapshot for
2996 * them to use. (Since PortalRunUtility doesn't set a snap for COMMIT, we
2997 * can't assume ActiveSnapshot is valid on entry.)
2999 events = &afterTriggers->events;
3000 if (events->head != NULL)
3002 PushActiveSnapshot(GetTransactionSnapshot());
3003 snap_pushed = true;
3007 * Run all the remaining triggers. Loop until they are all gone, in case
3008 * some trigger queues more for us to do.
3010 while (afterTriggerMarkEvents(events, NULL, false))
3012 CommandId firing_id = afterTriggers->firing_counter++;
3014 afterTriggerInvokeEvents(events, firing_id, NULL, true);
3017 if (snap_pushed)
3018 PopActiveSnapshot();
3020 Assert(events->head == NULL);
3024 /* ----------
3025 * AfterTriggerEndXact()
3027 * The current transaction is finishing.
3029 * Any unfired triggers are canceled so we simply throw
3030 * away anything we know.
3032 * Note: it is possible for this to be called repeatedly in case of
3033 * error during transaction abort; therefore, do not complain if
3034 * already closed down.
3035 * ----------
3037 void
3038 AfterTriggerEndXact(bool isCommit)
3041 * Forget everything we know about AFTER triggers.
3043 * Since all the info is in TopTransactionContext or children thereof, we
3044 * don't really need to do anything to reclaim memory. However, the
3045 * pending-events list could be large, and so it's useful to discard it as
3046 * soon as possible --- especially if we are aborting because we ran out
3047 * of memory for the list!
3049 * (Note: any event_cxts of child subtransactions could also be deleted
3050 * here, but we have no convenient way to find them, so we leave it to
3051 * TopTransactionContext reset to clean them up.)
3053 if (afterTriggers && afterTriggers->event_cxt)
3054 MemoryContextDelete(afterTriggers->event_cxt);
3056 afterTriggers = NULL;
3060 * AfterTriggerBeginSubXact()
3062 * Start a subtransaction.
3064 void
3065 AfterTriggerBeginSubXact(void)
3067 int my_level = GetCurrentTransactionNestLevel();
3070 * Ignore call if the transaction is in aborted state. (Probably
3071 * shouldn't happen?)
3073 if (afterTriggers == NULL)
3074 return;
3077 * Allocate more space in the stacks if needed. (Note: because the
3078 * minimum nest level of a subtransaction is 2, we waste the first couple
3079 * entries of each array; not worth the notational effort to avoid it.)
3081 while (my_level >= afterTriggers->maxtransdepth)
3083 if (afterTriggers->maxtransdepth == 0)
3085 MemoryContext old_cxt;
3087 old_cxt = MemoryContextSwitchTo(TopTransactionContext);
3089 #define DEFTRIG_INITALLOC 8
3090 afterTriggers->cxt_stack = (MemoryContext *)
3091 palloc(DEFTRIG_INITALLOC * sizeof(MemoryContext));
3092 afterTriggers->state_stack = (SetConstraintState *)
3093 palloc(DEFTRIG_INITALLOC * sizeof(SetConstraintState));
3094 afterTriggers->events_stack = (AfterTriggerEventList *)
3095 palloc(DEFTRIG_INITALLOC * sizeof(AfterTriggerEventList));
3096 afterTriggers->depth_stack = (int *)
3097 palloc(DEFTRIG_INITALLOC * sizeof(int));
3098 afterTriggers->firing_stack = (CommandId *)
3099 palloc(DEFTRIG_INITALLOC * sizeof(CommandId));
3100 afterTriggers->maxtransdepth = DEFTRIG_INITALLOC;
3102 MemoryContextSwitchTo(old_cxt);
3104 else
3106 /* repalloc will keep the stacks in the same context */
3107 int new_alloc = afterTriggers->maxtransdepth * 2;
3109 afterTriggers->cxt_stack = (MemoryContext *)
3110 repalloc(afterTriggers->cxt_stack,
3111 new_alloc * sizeof(MemoryContext));
3112 afterTriggers->state_stack = (SetConstraintState *)
3113 repalloc(afterTriggers->state_stack,
3114 new_alloc * sizeof(SetConstraintState));
3115 afterTriggers->events_stack = (AfterTriggerEventList *)
3116 repalloc(afterTriggers->events_stack,
3117 new_alloc * sizeof(AfterTriggerEventList));
3118 afterTriggers->depth_stack = (int *)
3119 repalloc(afterTriggers->depth_stack,
3120 new_alloc * sizeof(int));
3121 afterTriggers->firing_stack = (CommandId *)
3122 repalloc(afterTriggers->firing_stack,
3123 new_alloc * sizeof(CommandId));
3124 afterTriggers->maxtransdepth = new_alloc;
3129 * Push the current information into the stack. The SET CONSTRAINTS state
3130 * is not saved until/unless changed. Likewise, we don't make a
3131 * per-subtransaction event context until needed.
3133 afterTriggers->cxt_stack[my_level] = NULL;
3134 afterTriggers->state_stack[my_level] = NULL;
3135 afterTriggers->events_stack[my_level] = afterTriggers->events;
3136 afterTriggers->depth_stack[my_level] = afterTriggers->query_depth;
3137 afterTriggers->firing_stack[my_level] = afterTriggers->firing_counter;
3141 * AfterTriggerEndSubXact()
3143 * The current subtransaction is ending.
3145 void
3146 AfterTriggerEndSubXact(bool isCommit)
3148 int my_level = GetCurrentTransactionNestLevel();
3149 SetConstraintState state;
3150 AfterTriggerEvent event;
3151 CommandId subxact_firing_id;
3154 * Ignore call if the transaction is in aborted state. (Probably
3155 * unneeded)
3157 if (afterTriggers == NULL)
3158 return;
3161 * Pop the prior state if needed.
3163 Assert(my_level < afterTriggers->maxtransdepth);
3165 if (isCommit)
3167 /* If we saved a prior state, we don't need it anymore */
3168 state = afterTriggers->state_stack[my_level];
3169 if (state != NULL)
3170 pfree(state);
3171 /* this avoids double pfree if error later: */
3172 afterTriggers->state_stack[my_level] = NULL;
3173 Assert(afterTriggers->query_depth ==
3174 afterTriggers->depth_stack[my_level]);
3177 * It's entirely possible that the subxact created an event_cxt but
3178 * there is not anything left in it (because all the triggers were
3179 * fired at end-of-statement). If so, we should release the context
3180 * to prevent memory leakage in a long sequence of subtransactions. We
3181 * can detect whether there's anything of use in the context by seeing
3182 * if anything was added to the global events list since subxact
3183 * start. (This test doesn't catch every case where the context is
3184 * deletable; for instance maybe the only additions were from a
3185 * sub-sub-xact. But it handles the common case.)
3187 if (afterTriggers->cxt_stack[my_level] &&
3188 afterTriggers->events.tail == afterTriggers->events_stack[my_level].tail)
3190 MemoryContextDelete(afterTriggers->cxt_stack[my_level]);
3191 /* avoid double delete if abort later */
3192 afterTriggers->cxt_stack[my_level] = NULL;
3195 else
3198 * Aborting. We don't really need to release the subxact's event_cxt,
3199 * since it will go away anyway when CurTransactionContext gets reset,
3200 * but doing so early in subxact abort helps free space we might need.
3202 * (Note: any event_cxts of child subtransactions could also be
3203 * deleted here, but we have no convenient way to find them, so we
3204 * leave it to CurTransactionContext reset to clean them up.)
3206 if (afterTriggers->cxt_stack[my_level])
3208 MemoryContextDelete(afterTriggers->cxt_stack[my_level]);
3209 /* avoid double delete if repeated aborts */
3210 afterTriggers->cxt_stack[my_level] = NULL;
3214 * Restore the pointers from the stacks.
3216 afterTriggers->events = afterTriggers->events_stack[my_level];
3217 afterTriggers->query_depth = afterTriggers->depth_stack[my_level];
3220 * Cleanup the tail of the list.
3222 if (afterTriggers->events.tail != NULL)
3223 afterTriggers->events.tail->ate_next = NULL;
3226 * Restore the trigger state. If the saved state is NULL, then this
3227 * subxact didn't save it, so it doesn't need restoring.
3229 state = afterTriggers->state_stack[my_level];
3230 if (state != NULL)
3232 pfree(afterTriggers->state);
3233 afterTriggers->state = state;
3235 /* this avoids double pfree if error later: */
3236 afterTriggers->state_stack[my_level] = NULL;
3239 * Scan for any remaining deferred events that were marked DONE or IN
3240 * PROGRESS by this subxact or a child, and un-mark them. We can
3241 * recognize such events because they have a firing ID greater than or
3242 * equal to the firing_counter value we saved at subtransaction start.
3243 * (This essentially assumes that the current subxact includes all
3244 * subxacts started after it.)
3246 subxact_firing_id = afterTriggers->firing_stack[my_level];
3247 for (event = afterTriggers->events.head;
3248 event != NULL;
3249 event = event->ate_next)
3251 if (event->ate_event &
3252 (AFTER_TRIGGER_DONE | AFTER_TRIGGER_IN_PROGRESS))
3254 if (event->ate_firing_id >= subxact_firing_id)
3255 event->ate_event &=
3256 ~(AFTER_TRIGGER_DONE | AFTER_TRIGGER_IN_PROGRESS);
3263 * Create an empty SetConstraintState with room for numalloc trigstates
3265 static SetConstraintState
3266 SetConstraintStateCreate(int numalloc)
3268 SetConstraintState state;
3270 /* Behave sanely with numalloc == 0 */
3271 if (numalloc <= 0)
3272 numalloc = 1;
3275 * We assume that zeroing will correctly initialize the state values.
3277 state = (SetConstraintState)
3278 MemoryContextAllocZero(TopTransactionContext,
3279 sizeof(SetConstraintStateData) +
3280 (numalloc - 1) *sizeof(SetConstraintTriggerData));
3282 state->numalloc = numalloc;
3284 return state;
3288 * Copy a SetConstraintState
3290 static SetConstraintState
3291 SetConstraintStateCopy(SetConstraintState origstate)
3293 SetConstraintState state;
3295 state = SetConstraintStateCreate(origstate->numstates);
3297 state->all_isset = origstate->all_isset;
3298 state->all_isdeferred = origstate->all_isdeferred;
3299 state->numstates = origstate->numstates;
3300 memcpy(state->trigstates, origstate->trigstates,
3301 origstate->numstates * sizeof(SetConstraintTriggerData));
3303 return state;
3307 * Add a per-trigger item to a SetConstraintState. Returns possibly-changed
3308 * pointer to the state object (it will change if we have to repalloc).
3310 static SetConstraintState
3311 SetConstraintStateAddItem(SetConstraintState state,
3312 Oid tgoid, bool tgisdeferred)
3314 if (state->numstates >= state->numalloc)
3316 int newalloc = state->numalloc * 2;
3318 newalloc = Max(newalloc, 8); /* in case original has size 0 */
3319 state = (SetConstraintState)
3320 repalloc(state,
3321 sizeof(SetConstraintStateData) +
3322 (newalloc - 1) *sizeof(SetConstraintTriggerData));
3323 state->numalloc = newalloc;
3324 Assert(state->numstates < state->numalloc);
3327 state->trigstates[state->numstates].sct_tgoid = tgoid;
3328 state->trigstates[state->numstates].sct_tgisdeferred = tgisdeferred;
3329 state->numstates++;
3331 return state;
3334 /* ----------
3335 * AfterTriggerSetState()
3337 * Execute the SET CONSTRAINTS ... utility command.
3338 * ----------
3340 void
3341 AfterTriggerSetState(ConstraintsSetStmt *stmt)
3343 int my_level = GetCurrentTransactionNestLevel();
3346 * Ignore call if we aren't in a transaction. (Shouldn't happen?)
3348 if (afterTriggers == NULL)
3349 return;
3352 * If in a subtransaction, and we didn't save the current state already,
3353 * save it so it can be restored if the subtransaction aborts.
3355 if (my_level > 1 &&
3356 afterTriggers->state_stack[my_level] == NULL)
3358 afterTriggers->state_stack[my_level] =
3359 SetConstraintStateCopy(afterTriggers->state);
3363 * Handle SET CONSTRAINTS ALL ...
3365 if (stmt->constraints == NIL)
3368 * Forget any previous SET CONSTRAINTS commands in this transaction.
3370 afterTriggers->state->numstates = 0;
3373 * Set the per-transaction ALL state to known.
3375 afterTriggers->state->all_isset = true;
3376 afterTriggers->state->all_isdeferred = stmt->deferred;
3378 else
3380 Relation tgrel;
3381 ListCell *l;
3382 List *oidlist = NIL;
3384 /* ----------
3385 * Handle SET CONSTRAINTS constraint-name [, ...]
3386 * First lookup all trigger Oid's for the constraint names.
3387 * ----------
3389 tgrel = heap_open(TriggerRelationId, AccessShareLock);
3391 foreach(l, stmt->constraints)
3393 RangeVar *constraint = lfirst(l);
3394 ScanKeyData skey;
3395 SysScanDesc tgscan;
3396 HeapTuple htup;
3397 bool found;
3398 List *namespaceSearchList;
3399 ListCell *namespaceSearchCell;
3401 if (constraint->catalogname)
3403 if (strcmp(constraint->catalogname, get_database_name(MyDatabaseId)) != 0)
3404 ereport(ERROR,
3405 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3406 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
3407 constraint->catalogname, constraint->schemaname,
3408 constraint->relname)));
3412 * If we're given the schema name with the constraint, look only
3413 * in that schema. If given a bare constraint name, use the
3414 * search path to find the first matching constraint.
3416 if (constraint->schemaname)
3418 Oid namespaceId = LookupExplicitNamespace(constraint->schemaname);
3420 namespaceSearchList = list_make1_oid(namespaceId);
3422 else
3424 namespaceSearchList = fetch_search_path(true);
3427 found = false;
3428 foreach(namespaceSearchCell, namespaceSearchList)
3430 Oid searchNamespaceId = lfirst_oid(namespaceSearchCell);
3433 * Setup to scan pg_trigger by tgconstrname ...
3435 ScanKeyInit(&skey,
3436 Anum_pg_trigger_tgconstrname,
3437 BTEqualStrategyNumber, F_NAMEEQ,
3438 PointerGetDatum(constraint->relname));
3440 tgscan = systable_beginscan(tgrel, TriggerConstrNameIndexId, true,
3441 SnapshotNow, 1, &skey);
3444 * ... and search for the constraint trigger row
3446 while (HeapTupleIsValid(htup = systable_getnext(tgscan)))
3448 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
3449 Oid constraintNamespaceId;
3452 * Foreign key constraints have triggers on both the
3453 * parent and child tables. Since these tables may be in
3454 * different schemas we must pick the child table because
3455 * that table "owns" the constraint.
3457 * Referential triggers on the parent table other than
3458 * NOACTION_DEL and NOACTION_UPD are ignored below, so it
3459 * is possible to not check them here, but it seems safer
3460 * to always check.
3462 if (pg_trigger->tgfoid == F_RI_FKEY_NOACTION_DEL ||
3463 pg_trigger->tgfoid == F_RI_FKEY_NOACTION_UPD ||
3464 pg_trigger->tgfoid == F_RI_FKEY_RESTRICT_UPD ||
3465 pg_trigger->tgfoid == F_RI_FKEY_RESTRICT_DEL ||
3466 pg_trigger->tgfoid == F_RI_FKEY_CASCADE_UPD ||
3467 pg_trigger->tgfoid == F_RI_FKEY_CASCADE_DEL ||
3468 pg_trigger->tgfoid == F_RI_FKEY_SETNULL_UPD ||
3469 pg_trigger->tgfoid == F_RI_FKEY_SETNULL_DEL ||
3470 pg_trigger->tgfoid == F_RI_FKEY_SETDEFAULT_UPD ||
3471 pg_trigger->tgfoid == F_RI_FKEY_SETDEFAULT_DEL)
3472 constraintNamespaceId = get_rel_namespace(pg_trigger->tgconstrrelid);
3473 else
3474 constraintNamespaceId = get_rel_namespace(pg_trigger->tgrelid);
3477 * If this constraint is not in the schema we're currently
3478 * searching for, keep looking.
3480 if (constraintNamespaceId != searchNamespaceId)
3481 continue;
3484 * If we found some, check that they fit the deferrability
3485 * but skip referential action ones, since they are
3486 * silently never deferrable.
3488 if (pg_trigger->tgfoid != F_RI_FKEY_RESTRICT_UPD &&
3489 pg_trigger->tgfoid != F_RI_FKEY_RESTRICT_DEL &&
3490 pg_trigger->tgfoid != F_RI_FKEY_CASCADE_UPD &&
3491 pg_trigger->tgfoid != F_RI_FKEY_CASCADE_DEL &&
3492 pg_trigger->tgfoid != F_RI_FKEY_SETNULL_UPD &&
3493 pg_trigger->tgfoid != F_RI_FKEY_SETNULL_DEL &&
3494 pg_trigger->tgfoid != F_RI_FKEY_SETDEFAULT_UPD &&
3495 pg_trigger->tgfoid != F_RI_FKEY_SETDEFAULT_DEL)
3497 if (stmt->deferred && !pg_trigger->tgdeferrable)
3498 ereport(ERROR,
3499 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
3500 errmsg("constraint \"%s\" is not deferrable",
3501 constraint->relname)));
3502 oidlist = lappend_oid(oidlist, HeapTupleGetOid(htup));
3504 found = true;
3507 systable_endscan(tgscan);
3510 * Once we've found a matching constraint we do not search
3511 * later parts of the search path.
3513 if (found)
3514 break;
3518 list_free(namespaceSearchList);
3521 * Not found ?
3523 if (!found)
3524 ereport(ERROR,
3525 (errcode(ERRCODE_UNDEFINED_OBJECT),
3526 errmsg("constraint \"%s\" does not exist",
3527 constraint->relname)));
3529 heap_close(tgrel, AccessShareLock);
3532 * Set the trigger states of individual triggers for this xact.
3534 foreach(l, oidlist)
3536 Oid tgoid = lfirst_oid(l);
3537 SetConstraintState state = afterTriggers->state;
3538 bool found = false;
3539 int i;
3541 for (i = 0; i < state->numstates; i++)
3543 if (state->trigstates[i].sct_tgoid == tgoid)
3545 state->trigstates[i].sct_tgisdeferred = stmt->deferred;
3546 found = true;
3547 break;
3550 if (!found)
3552 afterTriggers->state =
3553 SetConstraintStateAddItem(state, tgoid, stmt->deferred);
3559 * SQL99 requires that when a constraint is set to IMMEDIATE, any deferred
3560 * checks against that constraint must be made when the SET CONSTRAINTS
3561 * command is executed -- i.e. the effects of the SET CONSTRAINTS command
3562 * apply retroactively. We've updated the constraints state, so scan the
3563 * list of previously deferred events to fire any that have now become
3564 * immediate.
3566 * Obviously, if this was SET ... DEFERRED then it can't have converted
3567 * any unfired events to immediate, so we need do nothing in that case.
3569 if (!stmt->deferred)
3571 AfterTriggerEventList *events = &afterTriggers->events;
3573 while (afterTriggerMarkEvents(events, NULL, true))
3575 CommandId firing_id = afterTriggers->firing_counter++;
3578 * We can delete fired events if we are at top transaction level,
3579 * but we'd better not if inside a subtransaction, since the
3580 * subtransaction could later get rolled back.
3582 afterTriggerInvokeEvents(events, firing_id, NULL,
3583 !IsSubTransaction());
3588 /* ----------
3589 * AfterTriggerPendingOnRel()
3590 * Test to see if there are any pending after-trigger events for rel.
3592 * This is used by TRUNCATE, CLUSTER, ALTER TABLE, etc to detect whether
3593 * it is unsafe to perform major surgery on a relation. Note that only
3594 * local pending events are examined. We assume that having exclusive lock
3595 * on a rel guarantees there are no unserviced events in other backends ---
3596 * but having a lock does not prevent there being such events in our own.
3598 * In some scenarios it'd be reasonable to remove pending events (more
3599 * specifically, mark them DONE by the current subxact) but without a lot
3600 * of knowledge of the trigger semantics we can't do this in general.
3601 * ----------
3603 bool
3604 AfterTriggerPendingOnRel(Oid relid)
3606 AfterTriggerEvent event;
3607 int depth;
3609 /* No-op if we aren't in a transaction. (Shouldn't happen?) */
3610 if (afterTriggers == NULL)
3611 return false;
3613 /* Scan queued events */
3614 for (event = afterTriggers->events.head;
3615 event != NULL;
3616 event = event->ate_next)
3619 * We can ignore completed events. (Even if a DONE flag is rolled
3620 * back by subxact abort, it's OK because the effects of the TRUNCATE
3621 * or whatever must get rolled back too.)
3623 if (event->ate_event & AFTER_TRIGGER_DONE)
3624 continue;
3626 if (event->ate_relid == relid)
3627 return true;
3631 * Also scan events queued by incomplete queries. This could only matter
3632 * if TRUNCATE/etc is executed by a function or trigger within an updating
3633 * query on the same relation, which is pretty perverse, but let's check.
3635 for (depth = 0; depth <= afterTriggers->query_depth; depth++)
3637 for (event = afterTriggers->query_stack[depth].head;
3638 event != NULL;
3639 event = event->ate_next)
3641 if (event->ate_event & AFTER_TRIGGER_DONE)
3642 continue;
3644 if (event->ate_relid == relid)
3645 return true;
3649 return false;
3653 /* ----------
3654 * AfterTriggerSaveEvent()
3656 * Called by ExecA[RS]...Triggers() to add the event to the queue.
3658 * NOTE: should be called only if we've determined that an event must
3659 * be added to the queue.
3660 * ----------
3662 static void
3663 AfterTriggerSaveEvent(ResultRelInfo *relinfo, int event, bool row_trigger,
3664 HeapTuple oldtup, HeapTuple newtup)
3666 Relation rel = relinfo->ri_RelationDesc;
3667 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
3668 int my_level = GetCurrentTransactionNestLevel();
3669 MemoryContext *cxtptr;
3670 AfterTriggerEvent new_event;
3671 int i;
3672 int ntriggers;
3673 int *tgindx;
3674 ItemPointerData oldctid;
3675 ItemPointerData newctid;
3677 if (afterTriggers == NULL)
3678 elog(ERROR, "AfterTriggerSaveEvent() called outside of transaction");
3681 * event is used both as a bitmask and an array offset,
3682 * so make sure we don't walk off the edge of our arrays
3684 Assert(event >= 0 && event < TRIGGER_NUM_EVENT_CLASSES);
3687 * Get the CTID's of OLD and NEW
3689 if (oldtup != NULL)
3690 ItemPointerCopy(&(oldtup->t_self), &(oldctid));
3691 else
3692 ItemPointerSetInvalid(&(oldctid));
3693 if (newtup != NULL)
3694 ItemPointerCopy(&(newtup->t_self), &(newctid));
3695 else
3696 ItemPointerSetInvalid(&(newctid));
3699 * Scan the appropriate set of triggers
3701 if (row_trigger)
3703 ntriggers = trigdesc->n_after_row[event];
3704 tgindx = trigdesc->tg_after_row[event];
3706 else
3708 ntriggers = trigdesc->n_after_statement[event];
3709 tgindx = trigdesc->tg_after_statement[event];
3712 for (i = 0; i < ntriggers; i++)
3714 Trigger *trigger = &trigdesc->triggers[tgindx[i]];
3716 /* Ignore disabled triggers */
3717 if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
3719 if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
3720 trigger->tgenabled == TRIGGER_DISABLED)
3721 continue;
3723 else /* ORIGIN or LOCAL role */
3725 if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
3726 trigger->tgenabled == TRIGGER_DISABLED)
3727 continue;
3731 * If this is an UPDATE of a PK table or FK table that does not change
3732 * the PK or FK respectively, we can skip queuing the event: there is
3733 * no need to fire the trigger.
3735 if ((event & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_UPDATE)
3737 switch (RI_FKey_trigger_type(trigger->tgfoid))
3739 case RI_TRIGGER_PK:
3740 /* Update on PK table */
3741 if (RI_FKey_keyequal_upd_pk(trigger, rel, oldtup, newtup))
3743 /* key unchanged, so skip queuing this event */
3744 continue;
3746 break;
3748 case RI_TRIGGER_FK:
3751 * Update on FK table
3753 * There is one exception when updating FK tables: if the
3754 * updated row was inserted by our own transaction and the
3755 * FK is deferred, we still need to fire the trigger. This
3756 * is because our UPDATE will invalidate the INSERT so the
3757 * end-of-transaction INSERT RI trigger will not do
3758 * anything, so we have to do the check for the UPDATE
3759 * anyway.
3761 if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(oldtup->t_data)) &&
3762 RI_FKey_keyequal_upd_fk(trigger, rel, oldtup, newtup))
3764 continue;
3766 break;
3768 case RI_TRIGGER_NONE:
3769 /* Not an FK trigger */
3770 break;
3775 * If we don't yet have an event context for the current (sub)xact,
3776 * create one. Make it a child of CurTransactionContext to ensure it
3777 * will go away if the subtransaction aborts.
3779 if (my_level > 1) /* subtransaction? */
3781 Assert(my_level < afterTriggers->maxtransdepth);
3782 cxtptr = &afterTriggers->cxt_stack[my_level];
3784 else
3785 cxtptr = &afterTriggers->event_cxt;
3786 if (*cxtptr == NULL)
3787 *cxtptr = AllocSetContextCreate(CurTransactionContext,
3788 "AfterTriggerEvents",
3789 ALLOCSET_DEFAULT_MINSIZE,
3790 ALLOCSET_DEFAULT_INITSIZE,
3791 ALLOCSET_DEFAULT_MAXSIZE);
3794 * Create a new event.
3796 new_event = (AfterTriggerEvent)
3797 MemoryContextAlloc(*cxtptr, sizeof(AfterTriggerEventData));
3798 new_event->ate_next = NULL;
3799 new_event->ate_event =
3800 (event & TRIGGER_EVENT_OPMASK) |
3801 (row_trigger ? TRIGGER_EVENT_ROW : 0) |
3802 (trigger->tgdeferrable ? AFTER_TRIGGER_DEFERRABLE : 0) |
3803 (trigger->tginitdeferred ? AFTER_TRIGGER_INITDEFERRED : 0);
3804 new_event->ate_firing_id = 0;
3805 new_event->ate_tgoid = trigger->tgoid;
3806 new_event->ate_relid = rel->rd_id;
3807 ItemPointerCopy(&oldctid, &(new_event->ate_oldctid));
3808 ItemPointerCopy(&newctid, &(new_event->ate_newctid));
3811 * Add the new event to the queue.
3813 afterTriggerAddEvent(new_event);