1 /*-------------------------------------------------------------------------
4 * PostgreSQL TRIGGERs support code.
6 * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * src/backend/commands/trigger.c
12 *-------------------------------------------------------------------------
16 #include "access/genam.h"
17 #include "access/heapam.h"
18 #include "access/sysattr.h"
19 #include "access/htup_details.h"
20 #include "access/xact.h"
21 #include "catalog/catalog.h"
22 #include "catalog/dependency.h"
23 #include "catalog/indexing.h"
24 #include "catalog/objectaccess.h"
25 #include "catalog/pg_constraint.h"
26 #include "catalog/pg_constraint_fn.h"
27 #include "catalog/pg_proc.h"
28 #include "catalog/pg_trigger.h"
29 #include "catalog/pg_type.h"
30 #include "commands/dbcommands.h"
31 #include "commands/defrem.h"
32 #include "commands/trigger.h"
33 #include "executor/executor.h"
34 #include "miscadmin.h"
35 #include "nodes/bitmapset.h"
36 #include "nodes/makefuncs.h"
37 #include "optimizer/clauses.h"
38 #include "optimizer/var.h"
39 #include "parser/parse_clause.h"
40 #include "parser/parse_collate.h"
41 #include "parser/parse_func.h"
42 #include "parser/parse_relation.h"
43 #include "parser/parsetree.h"
45 #include "rewrite/rewriteManip.h"
46 #include "storage/bufmgr.h"
47 #include "storage/lmgr.h"
48 #include "tcop/utility.h"
49 #include "utils/acl.h"
50 #include "utils/builtins.h"
51 #include "utils/bytea.h"
52 #include "utils/fmgroids.h"
53 #include "utils/inval.h"
54 #include "utils/lsyscache.h"
55 #include "utils/memutils.h"
56 #include "utils/rel.h"
57 #include "utils/snapmgr.h"
58 #include "utils/syscache.h"
59 #include "utils/tqual.h"
60 #include "utils/tuplestore.h"
64 int SessionReplicationRole = SESSION_REPLICATION_ROLE_ORIGIN;
66 /* How many levels deep into trigger execution are we? */
67 static int MyTriggerDepth = 0;
70 * Note that similar macros also exist in executor/execMain.c. There does not
71 * appear to be any good header to put them into, given the structures that
72 * they use, so we let them be duplicated. Be sure to update all if one needs
73 * to be changed, however.
75 #define GetUpdatedColumns(relinfo, estate) \
76 (rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->updatedCols)
78 /* Local function prototypes */
79 static void ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid);
80 static void SetTriggerFlags(TriggerDesc *trigdesc, Trigger *trigger);
81 static HeapTuple GetTupleForTrigger(EState *estate,
83 ResultRelInfo *relinfo,
85 LockTupleMode lockmode,
86 TupleTableSlot **newSlot);
87 static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
88 Trigger *trigger, TriggerEvent event,
89 Bitmapset *modifiedCols,
90 HeapTuple oldtup, HeapTuple newtup);
91 static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata,
94 Instrumentation *instr,
95 MemoryContext per_tuple_context);
96 static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
97 int event, bool row_trigger,
98 HeapTuple oldtup, HeapTuple newtup,
99 List *recheckIndexes, Bitmapset *modifiedCols);
100 static void AfterTriggerEnlargeQueryState(void);
104 * Create a trigger. Returns the address of the created trigger.
106 * queryString is the source text of the CREATE TRIGGER command.
107 * This must be supplied if a whenClause is specified, else it can be NULL.
109 * relOid, if nonzero, is the relation on which the trigger should be
110 * created. If zero, the name provided in the statement will be looked up.
112 * refRelOid, if nonzero, is the relation to which the constraint trigger
113 * refers. If zero, the constraint relation name provided in the statement
114 * will be looked up as needed.
116 * constraintOid, if nonzero, says that this trigger is being created
117 * internally to implement that constraint. A suitable pg_depend entry will
118 * be made to link the trigger to that constraint. constraintOid is zero when
119 * executing a user-entered CREATE TRIGGER command. (For CREATE CONSTRAINT
120 * TRIGGER, we build a pg_constraint entry internally.)
122 * indexOid, if nonzero, is the OID of an index associated with the constraint.
123 * We do nothing with this except store it into pg_trigger.tgconstrindid.
125 * If isInternal is true then this is an internally-generated trigger.
126 * This argument sets the tgisinternal field of the pg_trigger entry, and
127 * if TRUE causes us to modify the given trigger name to ensure uniqueness.
129 * When isInternal is not true we require ACL_TRIGGER permissions on the
130 * relation, as well as ACL_EXECUTE on the trigger function. For internal
131 * triggers the caller must apply any required permission checks.
133 * Note: can return InvalidObjectAddress if we decided to not create a trigger
134 * at all, but a foreign-key constraint. This is a kluge for backwards
138 CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
139 Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid,
149 Datum values[Natts_pg_trigger];
150 bool nulls[Natts_pg_trigger];
158 Oid fargtypes[1]; /* dummy */
162 char internaltrigname[NAMEDATALEN];
164 Oid constrrelid = InvalidOid;
165 ObjectAddress myself,
167 char *oldtablename = NULL;
168 char *newtablename = NULL;
170 if (OidIsValid(relOid))
171 rel = heap_open(relOid, ShareRowExclusiveLock);
173 rel = heap_openrv(stmt->relation, ShareRowExclusiveLock);
176 * Triggers must be on tables or views, and there are additional
177 * relation-type-specific restrictions.
179 if (rel->rd_rel->relkind == RELKIND_RELATION ||
180 rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
182 /* Tables can't have INSTEAD OF triggers */
183 if (stmt->timing != TRIGGER_TYPE_BEFORE &&
184 stmt->timing != TRIGGER_TYPE_AFTER)
186 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
187 errmsg("\"%s\" is a table",
188 RelationGetRelationName(rel)),
189 errdetail("Tables cannot have INSTEAD OF triggers.")));
190 /* Disallow ROW triggers on partitioned tables */
191 if (stmt->row && rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
193 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
194 errmsg("\"%s\" is a partitioned table",
195 RelationGetRelationName(rel)),
196 errdetail("Partitioned tables cannot have ROW triggers.")));
198 else if (rel->rd_rel->relkind == RELKIND_VIEW)
201 * Views can have INSTEAD OF triggers (which we check below are
202 * row-level), or statement-level BEFORE/AFTER triggers.
204 if (stmt->timing != TRIGGER_TYPE_INSTEAD && stmt->row)
206 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
207 errmsg("\"%s\" is a view",
208 RelationGetRelationName(rel)),
209 errdetail("Views cannot have row-level BEFORE or AFTER triggers.")));
210 /* Disallow TRUNCATE triggers on VIEWs */
211 if (TRIGGER_FOR_TRUNCATE(stmt->events))
213 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
214 errmsg("\"%s\" is a view",
215 RelationGetRelationName(rel)),
216 errdetail("Views cannot have TRUNCATE triggers.")));
218 else if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
220 if (stmt->timing != TRIGGER_TYPE_BEFORE &&
221 stmt->timing != TRIGGER_TYPE_AFTER)
223 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
224 errmsg("\"%s\" is a foreign table",
225 RelationGetRelationName(rel)),
226 errdetail("Foreign tables cannot have INSTEAD OF triggers.")));
228 if (TRIGGER_FOR_TRUNCATE(stmt->events))
230 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
231 errmsg("\"%s\" is a foreign table",
232 RelationGetRelationName(rel)),
233 errdetail("Foreign tables cannot have TRUNCATE triggers.")));
235 if (stmt->isconstraint)
237 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
238 errmsg("\"%s\" is a foreign table",
239 RelationGetRelationName(rel)),
240 errdetail("Foreign tables cannot have constraint triggers.")));
244 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
245 errmsg("\"%s\" is not a table or view",
246 RelationGetRelationName(rel))));
248 if (!allowSystemTableMods && IsSystemRelation(rel))
250 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
251 errmsg("permission denied: \"%s\" is a system catalog",
252 RelationGetRelationName(rel))));
254 if (stmt->isconstraint)
257 * We must take a lock on the target relation to protect against
258 * concurrent drop. It's not clear that AccessShareLock is strong
259 * enough, but we certainly need at least that much... otherwise, we
260 * might end up creating a pg_constraint entry referencing a
263 if (OidIsValid(refRelOid))
265 LockRelationOid(refRelOid, AccessShareLock);
266 constrrelid = refRelOid;
268 else if (stmt->constrrel != NULL)
269 constrrelid = RangeVarGetRelid(stmt->constrrel, AccessShareLock,
273 /* permission checks */
276 aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
278 if (aclresult != ACLCHECK_OK)
279 aclcheck_error(aclresult, ACL_KIND_CLASS,
280 RelationGetRelationName(rel));
282 if (OidIsValid(constrrelid))
284 aclresult = pg_class_aclcheck(constrrelid, GetUserId(),
286 if (aclresult != ACLCHECK_OK)
287 aclcheck_error(aclresult, ACL_KIND_CLASS,
288 get_rel_name(constrrelid));
293 TRIGGER_CLEAR_TYPE(tgtype);
295 TRIGGER_SETT_ROW(tgtype);
296 tgtype |= stmt->timing;
297 tgtype |= stmt->events;
299 /* Disallow ROW-level TRUNCATE triggers */
300 if (TRIGGER_FOR_ROW(tgtype) && TRIGGER_FOR_TRUNCATE(tgtype))
302 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
303 errmsg("TRUNCATE FOR EACH ROW triggers are not supported")));
305 /* INSTEAD triggers must be row-level, and can't have WHEN or columns */
306 if (TRIGGER_FOR_INSTEAD(tgtype))
308 if (!TRIGGER_FOR_ROW(tgtype))
310 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
311 errmsg("INSTEAD OF triggers must be FOR EACH ROW")));
312 if (stmt->whenClause)
314 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
315 errmsg("INSTEAD OF triggers cannot have WHEN conditions")));
316 if (stmt->columns != NIL)
318 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
319 errmsg("INSTEAD OF triggers cannot have column lists")));
323 * We don't yet support naming ROW transition variables, but the parser
324 * recognizes the syntax so we can give a nicer message here.
326 * Per standard, REFERENCING TABLE names are only allowed on AFTER
327 * triggers. Per standard, REFERENCING ROW names are not allowed with FOR
328 * EACH STATEMENT. Per standard, each OLD/NEW, ROW/TABLE permutation is
329 * only allowed once. Per standard, OLD may not be specified when
330 * creating a trigger only for INSERT, and NEW may not be specified when
331 * creating a trigger only for DELETE.
333 * Notice that the standard allows an AFTER ... FOR EACH ROW trigger to
334 * reference both ROW and TABLE transition data.
336 if (stmt->transitionRels != NIL)
338 List *varList = stmt->transitionRels;
343 TriggerTransition *tt = (TriggerTransition *) lfirst(lc);
345 Assert(IsA(tt, TriggerTransition));
349 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
350 errmsg("ROW variable naming in the REFERENCING clause is not supported"),
351 errhint("Use OLD TABLE or NEW TABLE for naming transition tables.")));
354 * Because of the above test, we omit further ROW-related testing
355 * below. If we later allow naming OLD and NEW ROW variables,
356 * adjustments will be needed below.
359 if (stmt->timing != TRIGGER_TYPE_AFTER)
361 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
362 errmsg("transition table name can only be specified for an AFTER trigger")));
366 if (!(TRIGGER_FOR_INSERT(tgtype) ||
367 TRIGGER_FOR_UPDATE(tgtype)))
369 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
370 errmsg("NEW TABLE can only be specified for an INSERT or UPDATE trigger")));
372 if (newtablename != NULL)
374 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
375 errmsg("NEW TABLE cannot be specified multiple times")));
377 newtablename = tt->name;
381 if (!(TRIGGER_FOR_DELETE(tgtype) ||
382 TRIGGER_FOR_UPDATE(tgtype)))
384 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
385 errmsg("OLD TABLE can only be specified for a DELETE or UPDATE trigger")));
387 if (oldtablename != NULL)
389 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
390 errmsg("OLD TABLE cannot be specified multiple times")));
392 oldtablename = tt->name;
396 if (newtablename != NULL && oldtablename != NULL &&
397 strcmp(newtablename, oldtablename) == 0)
399 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
400 errmsg("OLD TABLE name and NEW TABLE name cannot be the same")));
404 * Parse the WHEN clause, if any
406 if (stmt->whenClause)
413 /* Set up a pstate to parse with */
414 pstate = make_parsestate(NULL);
415 pstate->p_sourcetext = queryString;
418 * Set up RTEs for OLD and NEW references.
420 * 'OLD' must always have varno equal to 1 and 'NEW' equal to 2.
422 rte = addRangeTableEntryForRelation(pstate, rel,
423 makeAlias("old", NIL),
425 addRTEtoQuery(pstate, rte, false, true, true);
426 rte = addRangeTableEntryForRelation(pstate, rel,
427 makeAlias("new", NIL),
429 addRTEtoQuery(pstate, rte, false, true, true);
431 /* Transform expression. Copy to be sure we don't modify original */
432 whenClause = transformWhereClause(pstate,
433 copyObject(stmt->whenClause),
434 EXPR_KIND_TRIGGER_WHEN,
436 /* we have to fix its collations too */
437 assign_expr_collations(pstate, whenClause);
440 * Check for disallowed references to OLD/NEW.
442 * NB: pull_var_clause is okay here only because we don't allow
443 * subselects in WHEN clauses; it would fail to examine the contents
446 varList = pull_var_clause(whenClause, 0);
449 Var *var = (Var *) lfirst(lc);
454 if (!TRIGGER_FOR_ROW(tgtype))
456 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
457 errmsg("statement trigger's WHEN condition cannot reference column values"),
458 parser_errposition(pstate, var->location)));
459 if (TRIGGER_FOR_INSERT(tgtype))
461 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
462 errmsg("INSERT trigger's WHEN condition cannot reference OLD values"),
463 parser_errposition(pstate, var->location)));
464 /* system columns are okay here */
467 if (!TRIGGER_FOR_ROW(tgtype))
469 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
470 errmsg("statement trigger's WHEN condition cannot reference column values"),
471 parser_errposition(pstate, var->location)));
472 if (TRIGGER_FOR_DELETE(tgtype))
474 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
475 errmsg("DELETE trigger's WHEN condition cannot reference NEW values"),
476 parser_errposition(pstate, var->location)));
477 if (var->varattno < 0 && TRIGGER_FOR_BEFORE(tgtype))
479 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
480 errmsg("BEFORE trigger's WHEN condition cannot reference NEW system columns"),
481 parser_errposition(pstate, var->location)));
484 /* can't happen without add_missing_from, so just elog */
485 elog(ERROR, "trigger WHEN condition cannot contain references to other relations");
490 /* we'll need the rtable for recordDependencyOnExpr */
491 whenRtable = pstate->p_rtable;
493 qual = nodeToString(whenClause);
495 free_parsestate(pstate);
505 * Find and validate the trigger function.
507 funcoid = LookupFuncName(stmt->funcname, 0, fargtypes, false);
510 aclresult = pg_proc_aclcheck(funcoid, GetUserId(), ACL_EXECUTE);
511 if (aclresult != ACLCHECK_OK)
512 aclcheck_error(aclresult, ACL_KIND_PROC,
513 NameListToString(stmt->funcname));
515 funcrettype = get_func_rettype(funcoid);
516 if (funcrettype != TRIGGEROID)
519 * We allow OPAQUE just so we can load old dump files. When we see a
520 * trigger function declared OPAQUE, change it to TRIGGER.
522 if (funcrettype == OPAQUEOID)
525 (errmsg("changing return type of function %s from \"opaque\" to \"trigger\"",
526 NameListToString(stmt->funcname))));
527 SetFunctionReturnType(funcoid, TRIGGEROID);
531 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
532 errmsg("function %s must return type %s",
533 NameListToString(stmt->funcname), "trigger")));
537 * If the command is a user-entered CREATE CONSTRAINT TRIGGER command that
538 * references one of the built-in RI_FKey trigger functions, assume it is
539 * from a dump of a pre-7.3 foreign key constraint, and take steps to
540 * convert this legacy representation into a regular foreign key
541 * constraint. Ugly, but necessary for loading old dump files.
543 if (stmt->isconstraint && !isInternal &&
544 list_length(stmt->args) >= 6 &&
545 (list_length(stmt->args) % 2) == 0 &&
546 RI_FKey_trigger_type(funcoid) != RI_TRIGGER_NONE)
548 /* Keep lock on target rel until end of xact */
549 heap_close(rel, NoLock);
551 ConvertTriggerToFK(stmt, funcoid);
553 return InvalidObjectAddress;
557 * If it's a user-entered CREATE CONSTRAINT TRIGGER command, make a
558 * corresponding pg_constraint entry.
560 if (stmt->isconstraint && !OidIsValid(constraintOid))
562 /* Internal callers should have made their own constraints */
564 constraintOid = CreateConstraintEntry(stmt->trigname,
565 RelationGetNamespace(rel),
570 RelationGetRelid(rel),
571 NULL, /* no conkey */
573 InvalidOid, /* no domain */
574 InvalidOid, /* no index */
575 InvalidOid, /* no foreign key */
584 NULL, /* no exclusion */
585 NULL, /* no check constraint */
590 true, /* isnoinherit */
591 isInternal); /* is_internal */
595 * Generate the trigger's OID now, so that we can use it in the name if
598 tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
600 trigoid = GetNewOid(tgrel);
603 * If trigger is internally generated, modify the provided trigger name to
604 * ensure uniqueness by appending the trigger OID. (Callers will usually
605 * supply a simple constant trigger name in these cases.)
609 snprintf(internaltrigname, sizeof(internaltrigname),
610 "%s_%u", stmt->trigname, trigoid);
611 trigname = internaltrigname;
615 /* user-defined trigger; use the specified trigger name as-is */
616 trigname = stmt->trigname;
620 * Scan pg_trigger for existing triggers on relation. We do this only to
621 * give a nice error message if there's already a trigger of the same
622 * name. (The unique index on tgrelid/tgname would complain anyway.) We
623 * can skip this for internally generated triggers, since the name
624 * modification above should be sufficient.
626 * NOTE that this is cool only because we have ShareRowExclusiveLock on
627 * the relation, so the trigger set won't be changing underneath us.
632 Anum_pg_trigger_tgrelid,
633 BTEqualStrategyNumber, F_OIDEQ,
634 ObjectIdGetDatum(RelationGetRelid(rel)));
635 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
637 while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
639 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
641 if (namestrcmp(&(pg_trigger->tgname), trigname) == 0)
643 (errcode(ERRCODE_DUPLICATE_OBJECT),
644 errmsg("trigger \"%s\" for relation \"%s\" already exists",
645 trigname, RelationGetRelationName(rel))));
647 systable_endscan(tgscan);
651 * Build the new pg_trigger tuple.
653 memset(nulls, false, sizeof(nulls));
655 values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
656 values[Anum_pg_trigger_tgname - 1] = DirectFunctionCall1(namein,
657 CStringGetDatum(trigname));
658 values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid);
659 values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype);
660 values[Anum_pg_trigger_tgenabled - 1] = CharGetDatum(TRIGGER_FIRES_ON_ORIGIN);
661 values[Anum_pg_trigger_tgisinternal - 1] = BoolGetDatum(isInternal);
662 values[Anum_pg_trigger_tgconstrrelid - 1] = ObjectIdGetDatum(constrrelid);
663 values[Anum_pg_trigger_tgconstrindid - 1] = ObjectIdGetDatum(indexOid);
664 values[Anum_pg_trigger_tgconstraint - 1] = ObjectIdGetDatum(constraintOid);
665 values[Anum_pg_trigger_tgdeferrable - 1] = BoolGetDatum(stmt->deferrable);
666 values[Anum_pg_trigger_tginitdeferred - 1] = BoolGetDatum(stmt->initdeferred);
672 int16 nargs = list_length(stmt->args);
675 foreach(le, stmt->args)
677 char *ar = strVal(lfirst(le));
679 len += strlen(ar) + 4;
686 args = (char *) palloc(len + 1);
688 foreach(le, stmt->args)
690 char *s = strVal(lfirst(le));
691 char *d = args + strlen(args);
701 values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(nargs);
702 values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
703 CStringGetDatum(args));
707 values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(0);
708 values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
709 CStringGetDatum(""));
712 /* build column number array if it's a column-specific trigger */
713 ncolumns = list_length(stmt->columns);
721 columns = (int16 *) palloc(ncolumns * sizeof(int16));
722 foreach(cell, stmt->columns)
724 char *name = strVal(lfirst(cell));
728 /* Lookup column name. System columns are not allowed */
729 attnum = attnameAttNum(rel, name, false);
730 if (attnum == InvalidAttrNumber)
732 (errcode(ERRCODE_UNDEFINED_COLUMN),
733 errmsg("column \"%s\" of relation \"%s\" does not exist",
734 name, RelationGetRelationName(rel))));
736 /* Check for duplicates */
737 for (j = i - 1; j >= 0; j--)
739 if (columns[j] == attnum)
741 (errcode(ERRCODE_DUPLICATE_COLUMN),
742 errmsg("column \"%s\" specified more than once",
746 columns[i++] = attnum;
749 tgattr = buildint2vector(columns, ncolumns);
750 values[Anum_pg_trigger_tgattr - 1] = PointerGetDatum(tgattr);
752 /* set tgqual if trigger has WHEN clause */
754 values[Anum_pg_trigger_tgqual - 1] = CStringGetTextDatum(qual);
756 nulls[Anum_pg_trigger_tgqual - 1] = true;
759 values[Anum_pg_trigger_tgoldtable - 1] = DirectFunctionCall1(namein,
760 CStringGetDatum(oldtablename));
762 nulls[Anum_pg_trigger_tgoldtable - 1] = true;
764 values[Anum_pg_trigger_tgnewtable - 1] = DirectFunctionCall1(namein,
765 CStringGetDatum(newtablename));
767 nulls[Anum_pg_trigger_tgnewtable - 1] = true;
769 tuple = heap_form_tuple(tgrel->rd_att, values, nulls);
771 /* force tuple to have the desired OID */
772 HeapTupleSetOid(tuple, trigoid);
775 * Insert tuple into pg_trigger.
777 simple_heap_insert(tgrel, tuple);
779 CatalogUpdateIndexes(tgrel, tuple);
781 heap_freetuple(tuple);
782 heap_close(tgrel, RowExclusiveLock);
784 pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
785 pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1]));
786 pfree(DatumGetPointer(values[Anum_pg_trigger_tgattr - 1]));
788 pfree(DatumGetPointer(values[Anum_pg_trigger_tgoldtable - 1]));
790 pfree(DatumGetPointer(values[Anum_pg_trigger_tgnewtable - 1]));
793 * Update relation's pg_class entry. Crucial side-effect: other backends
794 * (and this one too!) are sent SI message to make them rebuild relcache
797 pgrel = heap_open(RelationRelationId, RowExclusiveLock);
798 tuple = SearchSysCacheCopy1(RELOID,
799 ObjectIdGetDatum(RelationGetRelid(rel)));
800 if (!HeapTupleIsValid(tuple))
801 elog(ERROR, "cache lookup failed for relation %u",
802 RelationGetRelid(rel));
804 ((Form_pg_class) GETSTRUCT(tuple))->relhastriggers = true;
806 simple_heap_update(pgrel, &tuple->t_self, tuple);
808 CatalogUpdateIndexes(pgrel, tuple);
810 heap_freetuple(tuple);
811 heap_close(pgrel, RowExclusiveLock);
814 * We used to try to update the rel's relcache entry here, but that's
815 * fairly pointless since it will happen as a byproduct of the upcoming
816 * CommandCounterIncrement...
820 * Record dependencies for trigger. Always place a normal dependency on
823 myself.classId = TriggerRelationId;
824 myself.objectId = trigoid;
825 myself.objectSubId = 0;
827 referenced.classId = ProcedureRelationId;
828 referenced.objectId = funcoid;
829 referenced.objectSubId = 0;
830 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
832 if (isInternal && OidIsValid(constraintOid))
835 * Internally-generated trigger for a constraint, so make it an
836 * internal dependency of the constraint. We can skip depending on
837 * the relation(s), as there'll be an indirect dependency via the
840 referenced.classId = ConstraintRelationId;
841 referenced.objectId = constraintOid;
842 referenced.objectSubId = 0;
843 recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
848 * User CREATE TRIGGER, so place dependencies. We make trigger be
849 * auto-dropped if its relation is dropped or if the FK relation is
850 * dropped. (Auto drop is compatible with our pre-7.3 behavior.)
852 referenced.classId = RelationRelationId;
853 referenced.objectId = RelationGetRelid(rel);
854 referenced.objectSubId = 0;
855 recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
856 if (OidIsValid(constrrelid))
858 referenced.classId = RelationRelationId;
859 referenced.objectId = constrrelid;
860 referenced.objectSubId = 0;
861 recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
863 /* Not possible to have an index dependency in this case */
864 Assert(!OidIsValid(indexOid));
867 * If it's a user-specified constraint trigger, make the constraint
868 * internally dependent on the trigger instead of vice versa.
870 if (OidIsValid(constraintOid))
872 referenced.classId = ConstraintRelationId;
873 referenced.objectId = constraintOid;
874 referenced.objectSubId = 0;
875 recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
879 /* If column-specific trigger, add normal dependencies on columns */
884 referenced.classId = RelationRelationId;
885 referenced.objectId = RelationGetRelid(rel);
886 for (i = 0; i < ncolumns; i++)
888 referenced.objectSubId = columns[i];
889 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
894 * If it has a WHEN clause, add dependencies on objects mentioned in the
895 * expression (eg, functions, as well as any columns used).
897 if (whenClause != NULL)
898 recordDependencyOnExpr(&myself, whenClause, whenRtable,
901 /* Post creation hook for new trigger */
902 InvokeObjectPostCreateHookArg(TriggerRelationId, trigoid, 0,
905 /* Keep lock on target rel until end of xact */
906 heap_close(rel, NoLock);
913 * Convert legacy (pre-7.3) CREATE CONSTRAINT TRIGGER commands into
914 * full-fledged foreign key constraints.
916 * The conversion is complex because a pre-7.3 foreign key involved three
917 * separate triggers, which were reported separately in dumps. While the
918 * single trigger on the referencing table adds no new information, we need
919 * to know the trigger functions of both of the triggers on the referenced
920 * table to build the constraint declaration. Also, due to lack of proper
921 * dependency checking pre-7.3, it is possible that the source database had
922 * an incomplete set of triggers resulting in an only partially enforced
923 * FK constraint. (This would happen if one of the tables had been dropped
924 * and re-created, but only if the DB had been affected by a 7.0 pg_dump bug
925 * that caused loss of tgconstrrelid information.) We choose to translate to
926 * an FK constraint only when we've seen all three triggers of a set. This is
927 * implemented by storing unmatched items in a list in TopMemoryContext.
928 * We match triggers together by comparing the trigger arguments (which
929 * include constraint name, table and column names, so should be good enough).
933 List *args; /* list of (T_String) Values or NIL */
934 Oid funcoids[3]; /* OIDs of trigger functions */
935 /* The three function OIDs are stored in the order update, delete, child */
939 ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
941 static List *info_list = NIL;
943 static const char *const funcdescr[3] = {
944 gettext_noop("Found referenced table's UPDATE trigger."),
945 gettext_noop("Found referenced table's DELETE trigger."),
946 gettext_noop("Found referencing table's trigger.")
952 char fk_matchtype = FKCONSTR_MATCH_SIMPLE;
953 List *fk_attrs = NIL;
954 List *pk_attrs = NIL;
957 OldTriggerInfo *info = NULL;
961 /* Parse out the trigger arguments */
962 constr_name = strVal(linitial(stmt->args));
963 fk_table_name = strVal(lsecond(stmt->args));
964 pk_table_name = strVal(lthird(stmt->args));
966 foreach(l, stmt->args)
968 Value *arg = (Value *) lfirst(l);
971 if (i < 4) /* skip constraint and table names */
973 if (i == 4) /* handle match type */
975 if (strcmp(strVal(arg), "FULL") == 0)
976 fk_matchtype = FKCONSTR_MATCH_FULL;
978 fk_matchtype = FKCONSTR_MATCH_SIMPLE;
982 fk_attrs = lappend(fk_attrs, arg);
984 pk_attrs = lappend(pk_attrs, arg);
987 /* Prepare description of constraint for use in messages */
988 initStringInfo(&buf);
989 appendStringInfo(&buf, "FOREIGN KEY %s(",
990 quote_identifier(fk_table_name));
994 Value *arg = (Value *) lfirst(l);
997 appendStringInfoChar(&buf, ',');
998 appendStringInfoString(&buf, quote_identifier(strVal(arg)));
1000 appendStringInfo(&buf, ") REFERENCES %s(",
1001 quote_identifier(pk_table_name));
1003 foreach(l, pk_attrs)
1005 Value *arg = (Value *) lfirst(l);
1008 appendStringInfoChar(&buf, ',');
1009 appendStringInfoString(&buf, quote_identifier(strVal(arg)));
1011 appendStringInfoChar(&buf, ')');
1013 /* Identify class of trigger --- update, delete, or referencing-table */
1016 case F_RI_FKEY_CASCADE_UPD:
1017 case F_RI_FKEY_RESTRICT_UPD:
1018 case F_RI_FKEY_SETNULL_UPD:
1019 case F_RI_FKEY_SETDEFAULT_UPD:
1020 case F_RI_FKEY_NOACTION_UPD:
1024 case F_RI_FKEY_CASCADE_DEL:
1025 case F_RI_FKEY_RESTRICT_DEL:
1026 case F_RI_FKEY_SETNULL_DEL:
1027 case F_RI_FKEY_SETDEFAULT_DEL:
1028 case F_RI_FKEY_NOACTION_DEL:
1037 /* See if we have a match to this trigger */
1038 foreach(l, info_list)
1040 info = (OldTriggerInfo *) lfirst(l);
1041 if (info->funcoids[funcnum] == InvalidOid &&
1042 equal(info->args, stmt->args))
1044 info->funcoids[funcnum] = funcoid;
1051 /* First trigger of set, so create a new list entry */
1052 MemoryContext oldContext;
1055 (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
1056 constr_name, buf.data),
1057 errdetail_internal("%s", _(funcdescr[funcnum]))));
1058 oldContext = MemoryContextSwitchTo(TopMemoryContext);
1059 info = (OldTriggerInfo *) palloc0(sizeof(OldTriggerInfo));
1060 info->args = copyObject(stmt->args);
1061 info->funcoids[funcnum] = funcoid;
1062 info_list = lappend(info_list, info);
1063 MemoryContextSwitchTo(oldContext);
1065 else if (info->funcoids[0] == InvalidOid ||
1066 info->funcoids[1] == InvalidOid ||
1067 info->funcoids[2] == InvalidOid)
1069 /* Second trigger of set */
1071 (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
1072 constr_name, buf.data),
1073 errdetail_internal("%s", _(funcdescr[funcnum]))));
1077 /* OK, we have a set, so make the FK constraint ALTER TABLE cmd */
1078 AlterTableStmt *atstmt = makeNode(AlterTableStmt);
1079 AlterTableCmd *atcmd = makeNode(AlterTableCmd);
1080 Constraint *fkcon = makeNode(Constraint);
1081 PlannedStmt *wrapper = makeNode(PlannedStmt);
1084 (errmsg("converting trigger group into constraint \"%s\" %s",
1085 constr_name, buf.data),
1086 errdetail_internal("%s", _(funcdescr[funcnum]))));
1087 fkcon->contype = CONSTR_FOREIGN;
1088 fkcon->location = -1;
1091 /* This trigger is on the FK table */
1092 atstmt->relation = stmt->relation;
1093 if (stmt->constrrel)
1094 fkcon->pktable = stmt->constrrel;
1097 /* Work around ancient pg_dump bug that omitted constrrel */
1098 fkcon->pktable = makeRangeVar(NULL, pk_table_name, -1);
1103 /* This trigger is on the PK table */
1104 fkcon->pktable = stmt->relation;
1105 if (stmt->constrrel)
1106 atstmt->relation = stmt->constrrel;
1109 /* Work around ancient pg_dump bug that omitted constrrel */
1110 atstmt->relation = makeRangeVar(NULL, fk_table_name, -1);
1113 atstmt->cmds = list_make1(atcmd);
1114 atstmt->relkind = OBJECT_TABLE;
1115 atcmd->subtype = AT_AddConstraint;
1116 atcmd->def = (Node *) fkcon;
1117 if (strcmp(constr_name, "<unnamed>") == 0)
1118 fkcon->conname = NULL;
1120 fkcon->conname = constr_name;
1121 fkcon->fk_attrs = fk_attrs;
1122 fkcon->pk_attrs = pk_attrs;
1123 fkcon->fk_matchtype = fk_matchtype;
1124 switch (info->funcoids[0])
1126 case F_RI_FKEY_NOACTION_UPD:
1127 fkcon->fk_upd_action = FKCONSTR_ACTION_NOACTION;
1129 case F_RI_FKEY_CASCADE_UPD:
1130 fkcon->fk_upd_action = FKCONSTR_ACTION_CASCADE;
1132 case F_RI_FKEY_RESTRICT_UPD:
1133 fkcon->fk_upd_action = FKCONSTR_ACTION_RESTRICT;
1135 case F_RI_FKEY_SETNULL_UPD:
1136 fkcon->fk_upd_action = FKCONSTR_ACTION_SETNULL;
1138 case F_RI_FKEY_SETDEFAULT_UPD:
1139 fkcon->fk_upd_action = FKCONSTR_ACTION_SETDEFAULT;
1142 /* can't get here because of earlier checks */
1143 elog(ERROR, "confused about RI update function");
1145 switch (info->funcoids[1])
1147 case F_RI_FKEY_NOACTION_DEL:
1148 fkcon->fk_del_action = FKCONSTR_ACTION_NOACTION;
1150 case F_RI_FKEY_CASCADE_DEL:
1151 fkcon->fk_del_action = FKCONSTR_ACTION_CASCADE;
1153 case F_RI_FKEY_RESTRICT_DEL:
1154 fkcon->fk_del_action = FKCONSTR_ACTION_RESTRICT;
1156 case F_RI_FKEY_SETNULL_DEL:
1157 fkcon->fk_del_action = FKCONSTR_ACTION_SETNULL;
1159 case F_RI_FKEY_SETDEFAULT_DEL:
1160 fkcon->fk_del_action = FKCONSTR_ACTION_SETDEFAULT;
1163 /* can't get here because of earlier checks */
1164 elog(ERROR, "confused about RI delete function");
1166 fkcon->deferrable = stmt->deferrable;
1167 fkcon->initdeferred = stmt->initdeferred;
1168 fkcon->skip_validation = false;
1169 fkcon->initially_valid = true;
1171 /* finally, wrap it in a dummy PlannedStmt */
1172 wrapper->commandType = CMD_UTILITY;
1173 wrapper->canSetTag = false;
1174 wrapper->utilityStmt = (Node *) atstmt;
1175 wrapper->stmt_location = -1;
1176 wrapper->stmt_len = -1;
1178 /* ... and execute it */
1179 ProcessUtility(wrapper,
1180 "(generated ALTER TABLE ADD FOREIGN KEY command)",
1181 PROCESS_UTILITY_SUBCOMMAND, NULL,
1182 None_Receiver, NULL);
1184 /* Remove the matched item from the list */
1185 info_list = list_delete_ptr(info_list, info);
1187 /* We leak the copied args ... not worth worrying about */
1192 * Guts of trigger deletion.
1195 RemoveTriggerById(Oid trigOid)
1199 ScanKeyData skey[1];
1204 tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
1207 * Find the trigger to delete.
1209 ScanKeyInit(&skey[0],
1210 ObjectIdAttributeNumber,
1211 BTEqualStrategyNumber, F_OIDEQ,
1212 ObjectIdGetDatum(trigOid));
1214 tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
1217 tup = systable_getnext(tgscan);
1218 if (!HeapTupleIsValid(tup))
1219 elog(ERROR, "could not find tuple for trigger %u", trigOid);
1222 * Open and exclusive-lock the relation the trigger belongs to.
1224 relid = ((Form_pg_trigger) GETSTRUCT(tup))->tgrelid;
1226 rel = heap_open(relid, AccessExclusiveLock);
1228 if (rel->rd_rel->relkind != RELKIND_RELATION &&
1229 rel->rd_rel->relkind != RELKIND_VIEW &&
1230 rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
1231 rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1233 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1234 errmsg("\"%s\" is not a table, view, or foreign table",
1235 RelationGetRelationName(rel))));
1237 if (!allowSystemTableMods && IsSystemRelation(rel))
1239 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1240 errmsg("permission denied: \"%s\" is a system catalog",
1241 RelationGetRelationName(rel))));
1244 * Delete the pg_trigger tuple.
1246 simple_heap_delete(tgrel, &tup->t_self);
1248 systable_endscan(tgscan);
1249 heap_close(tgrel, RowExclusiveLock);
1252 * We do not bother to try to determine whether any other triggers remain,
1253 * which would be needed in order to decide whether it's safe to clear the
1254 * relation's relhastriggers. (In any case, there might be a concurrent
1255 * process adding new triggers.) Instead, just force a relcache inval to
1256 * make other backends (and this one too!) rebuild their relcache entries.
1257 * There's no great harm in leaving relhastriggers true even if there are
1260 CacheInvalidateRelcache(rel);
1262 /* Keep lock on trigger's rel until end of xact */
1263 heap_close(rel, NoLock);
1267 * get_trigger_oid - Look up a trigger by name to find its OID.
1269 * If missing_ok is false, throw an error if trigger not found. If
1270 * true, just return InvalidOid.
1273 get_trigger_oid(Oid relid, const char *trigname, bool missing_ok)
1276 ScanKeyData skey[2];
1282 * Find the trigger, verify permissions, set up object address
1284 tgrel = heap_open(TriggerRelationId, AccessShareLock);
1286 ScanKeyInit(&skey[0],
1287 Anum_pg_trigger_tgrelid,
1288 BTEqualStrategyNumber, F_OIDEQ,
1289 ObjectIdGetDatum(relid));
1290 ScanKeyInit(&skey[1],
1291 Anum_pg_trigger_tgname,
1292 BTEqualStrategyNumber, F_NAMEEQ,
1293 CStringGetDatum(trigname));
1295 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1298 tup = systable_getnext(tgscan);
1300 if (!HeapTupleIsValid(tup))
1304 (errcode(ERRCODE_UNDEFINED_OBJECT),
1305 errmsg("trigger \"%s\" for table \"%s\" does not exist",
1306 trigname, get_rel_name(relid))));
1311 oid = HeapTupleGetOid(tup);
1314 systable_endscan(tgscan);
1315 heap_close(tgrel, AccessShareLock);
1320 * Perform permissions and integrity checks before acquiring a relation lock.
1323 RangeVarCallbackForRenameTrigger(const RangeVar *rv, Oid relid, Oid oldrelid,
1329 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1330 if (!HeapTupleIsValid(tuple))
1331 return; /* concurrently dropped */
1332 form = (Form_pg_class) GETSTRUCT(tuple);
1334 /* only tables and views can have triggers */
1335 if (form->relkind != RELKIND_RELATION && form->relkind != RELKIND_VIEW &&
1336 form->relkind != RELKIND_FOREIGN_TABLE &&
1337 form->relkind != RELKIND_PARTITIONED_TABLE)
1339 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1340 errmsg("\"%s\" is not a table, view, or foreign table",
1343 /* you must own the table to rename one of its triggers */
1344 if (!pg_class_ownercheck(relid, GetUserId()))
1345 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, rv->relname);
1346 if (!allowSystemTableMods && IsSystemClass(relid, form))
1348 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1349 errmsg("permission denied: \"%s\" is a system catalog",
1352 ReleaseSysCache(tuple);
1356 * renametrig - changes the name of a trigger on a relation
1358 * trigger name is changed in trigger catalog.
1359 * No record of the previous name is kept.
1361 * get proper relrelation from relation catalog (if not arg)
1362 * scan trigger catalog
1363 * for name conflict (within rel)
1364 * for original trigger (if not arg)
1365 * modify tgname in trigger tuple
1366 * update row in catalog
1369 renametrig(RenameStmt *stmt)
1378 ObjectAddress address;
1381 * Look up name, check permissions, and acquire lock (which we will NOT
1382 * release until end of transaction).
1384 relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
1386 RangeVarCallbackForRenameTrigger,
1389 /* Have lock already, so just need to build relcache entry. */
1390 targetrel = relation_open(relid, NoLock);
1393 * Scan pg_trigger twice for existing triggers on relation. We do this in
1394 * order to ensure a trigger does not exist with newname (The unique index
1395 * on tgrelid/tgname would complain anyway) and to ensure a trigger does
1396 * exist with oldname.
1398 * NOTE that this is cool only because we have AccessExclusiveLock on the
1399 * relation, so the trigger set won't be changing underneath us.
1401 tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
1404 * First pass -- look for name conflict
1406 ScanKeyInit(&key[0],
1407 Anum_pg_trigger_tgrelid,
1408 BTEqualStrategyNumber, F_OIDEQ,
1409 ObjectIdGetDatum(relid));
1410 ScanKeyInit(&key[1],
1411 Anum_pg_trigger_tgname,
1412 BTEqualStrategyNumber, F_NAMEEQ,
1413 PointerGetDatum(stmt->newname));
1414 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1416 if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1418 (errcode(ERRCODE_DUPLICATE_OBJECT),
1419 errmsg("trigger \"%s\" for relation \"%s\" already exists",
1420 stmt->newname, RelationGetRelationName(targetrel))));
1421 systable_endscan(tgscan);
1424 * Second pass -- look for trigger existing with oldname and update
1426 ScanKeyInit(&key[0],
1427 Anum_pg_trigger_tgrelid,
1428 BTEqualStrategyNumber, F_OIDEQ,
1429 ObjectIdGetDatum(relid));
1430 ScanKeyInit(&key[1],
1431 Anum_pg_trigger_tgname,
1432 BTEqualStrategyNumber, F_NAMEEQ,
1433 PointerGetDatum(stmt->subname));
1434 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1436 if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1438 tgoid = HeapTupleGetOid(tuple);
1441 * Update pg_trigger tuple with new tgname.
1443 tuple = heap_copytuple(tuple); /* need a modifiable copy */
1445 namestrcpy(&((Form_pg_trigger) GETSTRUCT(tuple))->tgname,
1448 simple_heap_update(tgrel, &tuple->t_self, tuple);
1450 /* keep system catalog indexes current */
1451 CatalogUpdateIndexes(tgrel, tuple);
1453 InvokeObjectPostAlterHook(TriggerRelationId,
1454 HeapTupleGetOid(tuple), 0);
1457 * Invalidate relation's relcache entry so that other backends (and
1458 * this one too!) are sent SI message to make them rebuild relcache
1459 * entries. (Ideally this should happen automatically...)
1461 CacheInvalidateRelcache(targetrel);
1466 (errcode(ERRCODE_UNDEFINED_OBJECT),
1467 errmsg("trigger \"%s\" for table \"%s\" does not exist",
1468 stmt->subname, RelationGetRelationName(targetrel))));
1471 ObjectAddressSet(address, TriggerRelationId, tgoid);
1473 systable_endscan(tgscan);
1475 heap_close(tgrel, RowExclusiveLock);
1478 * Close rel, but keep exclusive lock!
1480 relation_close(targetrel, NoLock);
1487 * EnableDisableTrigger()
1489 * Called by ALTER TABLE ENABLE/DISABLE [ REPLICA | ALWAYS ] TRIGGER
1490 * to change 'tgenabled' field for the specified trigger(s)
1492 * rel: relation to process (caller must hold suitable lock on it)
1493 * tgname: trigger to process, or NULL to scan all triggers
1494 * fires_when: new value for tgenabled field. In addition to generic
1495 * enablement/disablement, this also defines when the trigger
1496 * should be fired in session replication roles.
1497 * skip_system: if true, skip "system" triggers (constraint triggers)
1499 * Caller should have checked permissions for the table; here we also
1500 * enforce that superuser privilege is required to alter the state of
1504 EnableDisableTrigger(Relation rel, const char *tgname,
1505 char fires_when, bool skip_system)
1509 ScanKeyData keys[2];
1515 /* Scan the relevant entries in pg_triggers */
1516 tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
1518 ScanKeyInit(&keys[0],
1519 Anum_pg_trigger_tgrelid,
1520 BTEqualStrategyNumber, F_OIDEQ,
1521 ObjectIdGetDatum(RelationGetRelid(rel)));
1524 ScanKeyInit(&keys[1],
1525 Anum_pg_trigger_tgname,
1526 BTEqualStrategyNumber, F_NAMEEQ,
1527 CStringGetDatum(tgname));
1533 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1536 found = changed = false;
1538 while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1540 Form_pg_trigger oldtrig = (Form_pg_trigger) GETSTRUCT(tuple);
1542 if (oldtrig->tgisinternal)
1544 /* system trigger ... ok to process? */
1549 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1550 errmsg("permission denied: \"%s\" is a system trigger",
1551 NameStr(oldtrig->tgname))));
1556 if (oldtrig->tgenabled != fires_when)
1558 /* need to change this one ... make a copy to scribble on */
1559 HeapTuple newtup = heap_copytuple(tuple);
1560 Form_pg_trigger newtrig = (Form_pg_trigger) GETSTRUCT(newtup);
1562 newtrig->tgenabled = fires_when;
1564 simple_heap_update(tgrel, &newtup->t_self, newtup);
1566 /* Keep catalog indexes current */
1567 CatalogUpdateIndexes(tgrel, newtup);
1569 heap_freetuple(newtup);
1574 InvokeObjectPostAlterHook(TriggerRelationId,
1575 HeapTupleGetOid(tuple), 0);
1578 systable_endscan(tgscan);
1580 heap_close(tgrel, RowExclusiveLock);
1582 if (tgname && !found)
1584 (errcode(ERRCODE_UNDEFINED_OBJECT),
1585 errmsg("trigger \"%s\" for table \"%s\" does not exist",
1586 tgname, RelationGetRelationName(rel))));
1589 * If we changed anything, broadcast a SI inval message to force each
1590 * backend (including our own!) to rebuild relation's relcache entry.
1591 * Otherwise they will fail to apply the change promptly.
1594 CacheInvalidateRelcache(rel);
1599 * Build trigger data to attach to the given relcache entry.
1601 * Note that trigger data attached to a relcache entry must be stored in
1602 * CacheMemoryContext to ensure it survives as long as the relcache entry.
1603 * But we should be running in a less long-lived working context. To avoid
1604 * leaking cache memory if this routine fails partway through, we build a
1605 * temporary TriggerDesc in working memory and then copy the completed
1606 * structure into cache memory.
1609 RelationBuildTriggers(Relation relation)
1611 TriggerDesc *trigdesc;
1619 MemoryContext oldContext;
1623 * Allocate a working array to hold the triggers (the array is extended if
1627 triggers = (Trigger *) palloc(maxtrigs * sizeof(Trigger));
1631 * Note: since we scan the triggers using TriggerRelidNameIndexId, we will
1632 * be reading the triggers in name order, except possibly during
1633 * emergency-recovery operations (ie, IgnoreSystemIndexes). This in turn
1634 * ensures that triggers will be fired in name order.
1637 Anum_pg_trigger_tgrelid,
1638 BTEqualStrategyNumber, F_OIDEQ,
1639 ObjectIdGetDatum(RelationGetRelid(relation)));
1641 tgrel = heap_open(TriggerRelationId, AccessShareLock);
1642 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1645 while (HeapTupleIsValid(htup = systable_getnext(tgscan)))
1647 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
1652 if (numtrigs >= maxtrigs)
1655 triggers = (Trigger *) repalloc(triggers, maxtrigs * sizeof(Trigger));
1657 build = &(triggers[numtrigs]);
1659 build->tgoid = HeapTupleGetOid(htup);
1660 build->tgname = DatumGetCString(DirectFunctionCall1(nameout,
1661 NameGetDatum(&pg_trigger->tgname)));
1662 build->tgfoid = pg_trigger->tgfoid;
1663 build->tgtype = pg_trigger->tgtype;
1664 build->tgenabled = pg_trigger->tgenabled;
1665 build->tgisinternal = pg_trigger->tgisinternal;
1666 build->tgconstrrelid = pg_trigger->tgconstrrelid;
1667 build->tgconstrindid = pg_trigger->tgconstrindid;
1668 build->tgconstraint = pg_trigger->tgconstraint;
1669 build->tgdeferrable = pg_trigger->tgdeferrable;
1670 build->tginitdeferred = pg_trigger->tginitdeferred;
1671 build->tgnargs = pg_trigger->tgnargs;
1672 /* tgattr is first var-width field, so OK to access directly */
1673 build->tgnattr = pg_trigger->tgattr.dim1;
1674 if (build->tgnattr > 0)
1676 build->tgattr = (int16 *) palloc(build->tgnattr * sizeof(int16));
1677 memcpy(build->tgattr, &(pg_trigger->tgattr.values),
1678 build->tgnattr * sizeof(int16));
1681 build->tgattr = NULL;
1682 if (build->tgnargs > 0)
1687 val = DatumGetByteaP(fastgetattr(htup,
1688 Anum_pg_trigger_tgargs,
1689 tgrel->rd_att, &isnull));
1691 elog(ERROR, "tgargs is null in trigger for relation \"%s\"",
1692 RelationGetRelationName(relation));
1693 p = (char *) VARDATA(val);
1694 build->tgargs = (char **) palloc(build->tgnargs * sizeof(char *));
1695 for (i = 0; i < build->tgnargs; i++)
1697 build->tgargs[i] = pstrdup(p);
1702 build->tgargs = NULL;
1704 datum = fastgetattr(htup, Anum_pg_trigger_tgoldtable,
1705 tgrel->rd_att, &isnull);
1708 DatumGetCString(DirectFunctionCall1(nameout, datum));
1710 build->tgoldtable = NULL;
1712 datum = fastgetattr(htup, Anum_pg_trigger_tgnewtable,
1713 tgrel->rd_att, &isnull);
1716 DatumGetCString(DirectFunctionCall1(nameout, datum));
1718 build->tgnewtable = NULL;
1720 datum = fastgetattr(htup, Anum_pg_trigger_tgqual,
1721 tgrel->rd_att, &isnull);
1723 build->tgqual = TextDatumGetCString(datum);
1725 build->tgqual = NULL;
1730 systable_endscan(tgscan);
1731 heap_close(tgrel, AccessShareLock);
1733 /* There might not be any triggers */
1740 /* Build trigdesc */
1741 trigdesc = (TriggerDesc *) palloc0(sizeof(TriggerDesc));
1742 trigdesc->triggers = triggers;
1743 trigdesc->numtriggers = numtrigs;
1744 for (i = 0; i < numtrigs; i++)
1745 SetTriggerFlags(trigdesc, &(triggers[i]));
1747 /* Copy completed trigdesc into cache storage */
1748 oldContext = MemoryContextSwitchTo(CacheMemoryContext);
1749 relation->trigdesc = CopyTriggerDesc(trigdesc);
1750 MemoryContextSwitchTo(oldContext);
1752 /* Release working memory */
1753 FreeTriggerDesc(trigdesc);
1757 * Update the TriggerDesc's hint flags to include the specified trigger
1760 SetTriggerFlags(TriggerDesc *trigdesc, Trigger *trigger)
1762 int16 tgtype = trigger->tgtype;
1764 trigdesc->trig_insert_before_row |=
1765 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1766 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
1767 trigdesc->trig_insert_after_row |=
1768 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1769 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
1770 trigdesc->trig_insert_instead_row |=
1771 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1772 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_INSERT);
1773 trigdesc->trig_insert_before_statement |=
1774 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1775 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
1776 trigdesc->trig_insert_after_statement |=
1777 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1778 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
1779 trigdesc->trig_update_before_row |=
1780 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1781 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
1782 trigdesc->trig_update_after_row |=
1783 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1784 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
1785 trigdesc->trig_update_instead_row |=
1786 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1787 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_UPDATE);
1788 trigdesc->trig_update_before_statement |=
1789 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1790 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
1791 trigdesc->trig_update_after_statement |=
1792 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1793 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
1794 trigdesc->trig_delete_before_row |=
1795 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1796 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
1797 trigdesc->trig_delete_after_row |=
1798 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1799 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
1800 trigdesc->trig_delete_instead_row |=
1801 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1802 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_DELETE);
1803 trigdesc->trig_delete_before_statement |=
1804 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1805 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
1806 trigdesc->trig_delete_after_statement |=
1807 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1808 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
1809 /* there are no row-level truncate triggers */
1810 trigdesc->trig_truncate_before_statement |=
1811 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1812 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_TRUNCATE);
1813 trigdesc->trig_truncate_after_statement |=
1814 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1815 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_TRUNCATE);
1817 trigdesc->trig_insert_new_table |=
1818 (TRIGGER_FOR_INSERT(tgtype) &&
1819 TRIGGER_USES_TRANSITION_TABLE(trigger->tgnewtable));
1820 trigdesc->trig_update_old_table |=
1821 (TRIGGER_FOR_UPDATE(tgtype) &&
1822 TRIGGER_USES_TRANSITION_TABLE(trigger->tgoldtable));
1823 trigdesc->trig_update_new_table |=
1824 (TRIGGER_FOR_UPDATE(tgtype) &&
1825 TRIGGER_USES_TRANSITION_TABLE(trigger->tgnewtable));
1826 trigdesc->trig_delete_old_table |=
1827 (TRIGGER_FOR_DELETE(tgtype) &&
1828 TRIGGER_USES_TRANSITION_TABLE(trigger->tgoldtable));
1832 * Copy a TriggerDesc data structure.
1834 * The copy is allocated in the current memory context.
1837 CopyTriggerDesc(TriggerDesc *trigdesc)
1839 TriggerDesc *newdesc;
1843 if (trigdesc == NULL || trigdesc->numtriggers <= 0)
1846 newdesc = (TriggerDesc *) palloc(sizeof(TriggerDesc));
1847 memcpy(newdesc, trigdesc, sizeof(TriggerDesc));
1849 trigger = (Trigger *) palloc(trigdesc->numtriggers * sizeof(Trigger));
1850 memcpy(trigger, trigdesc->triggers,
1851 trigdesc->numtriggers * sizeof(Trigger));
1852 newdesc->triggers = trigger;
1854 for (i = 0; i < trigdesc->numtriggers; i++)
1856 trigger->tgname = pstrdup(trigger->tgname);
1857 if (trigger->tgnattr > 0)
1861 newattr = (int16 *) palloc(trigger->tgnattr * sizeof(int16));
1862 memcpy(newattr, trigger->tgattr,
1863 trigger->tgnattr * sizeof(int16));
1864 trigger->tgattr = newattr;
1866 if (trigger->tgnargs > 0)
1871 newargs = (char **) palloc(trigger->tgnargs * sizeof(char *));
1872 for (j = 0; j < trigger->tgnargs; j++)
1873 newargs[j] = pstrdup(trigger->tgargs[j]);
1874 trigger->tgargs = newargs;
1876 if (trigger->tgqual)
1877 trigger->tgqual = pstrdup(trigger->tgqual);
1878 if (trigger->tgoldtable)
1879 trigger->tgoldtable = pstrdup(trigger->tgoldtable);
1880 if (trigger->tgnewtable)
1881 trigger->tgnewtable = pstrdup(trigger->tgnewtable);
1889 * Free a TriggerDesc data structure.
1892 FreeTriggerDesc(TriggerDesc *trigdesc)
1897 if (trigdesc == NULL)
1900 trigger = trigdesc->triggers;
1901 for (i = 0; i < trigdesc->numtriggers; i++)
1903 pfree(trigger->tgname);
1904 if (trigger->tgnattr > 0)
1905 pfree(trigger->tgattr);
1906 if (trigger->tgnargs > 0)
1908 while (--(trigger->tgnargs) >= 0)
1909 pfree(trigger->tgargs[trigger->tgnargs]);
1910 pfree(trigger->tgargs);
1912 if (trigger->tgqual)
1913 pfree(trigger->tgqual);
1914 if (trigger->tgoldtable)
1915 pfree(trigger->tgoldtable);
1916 if (trigger->tgnewtable)
1917 pfree(trigger->tgnewtable);
1920 pfree(trigdesc->triggers);
1925 * Compare two TriggerDesc structures for logical equality.
1929 equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
1935 * We need not examine the hint flags, just the trigger array itself; if
1936 * we have the same triggers with the same types, the flags should match.
1938 * As of 7.3 we assume trigger set ordering is significant in the
1939 * comparison; so we just compare corresponding slots of the two sets.
1941 * Note: comparing the stringToNode forms of the WHEN clauses means that
1942 * parse column locations will affect the result. This is okay as long as
1943 * this function is only used for detecting exact equality, as for example
1944 * in checking for staleness of a cache entry.
1946 if (trigdesc1 != NULL)
1948 if (trigdesc2 == NULL)
1950 if (trigdesc1->numtriggers != trigdesc2->numtriggers)
1952 for (i = 0; i < trigdesc1->numtriggers; i++)
1954 Trigger *trig1 = trigdesc1->triggers + i;
1955 Trigger *trig2 = trigdesc2->triggers + i;
1957 if (trig1->tgoid != trig2->tgoid)
1959 if (strcmp(trig1->tgname, trig2->tgname) != 0)
1961 if (trig1->tgfoid != trig2->tgfoid)
1963 if (trig1->tgtype != trig2->tgtype)
1965 if (trig1->tgenabled != trig2->tgenabled)
1967 if (trig1->tgisinternal != trig2->tgisinternal)
1969 if (trig1->tgconstrrelid != trig2->tgconstrrelid)
1971 if (trig1->tgconstrindid != trig2->tgconstrindid)
1973 if (trig1->tgconstraint != trig2->tgconstraint)
1975 if (trig1->tgdeferrable != trig2->tgdeferrable)
1977 if (trig1->tginitdeferred != trig2->tginitdeferred)
1979 if (trig1->tgnargs != trig2->tgnargs)
1981 if (trig1->tgnattr != trig2->tgnattr)
1983 if (trig1->tgnattr > 0 &&
1984 memcmp(trig1->tgattr, trig2->tgattr,
1985 trig1->tgnattr * sizeof(int16)) != 0)
1987 for (j = 0; j < trig1->tgnargs; j++)
1988 if (strcmp(trig1->tgargs[j], trig2->tgargs[j]) != 0)
1990 if (trig1->tgqual == NULL && trig2->tgqual == NULL)
1992 else if (trig1->tgqual == NULL || trig2->tgqual == NULL)
1994 else if (strcmp(trig1->tgqual, trig2->tgqual) != 0)
1996 if (trig1->tgoldtable == NULL && trig2->tgoldtable == NULL)
1998 else if (trig1->tgoldtable == NULL || trig2->tgoldtable == NULL)
2000 else if (strcmp(trig1->tgoldtable, trig2->tgoldtable) != 0)
2002 if (trig1->tgnewtable == NULL && trig2->tgnewtable == NULL)
2004 else if (trig1->tgnewtable == NULL || trig2->tgnewtable == NULL)
2006 else if (strcmp(trig1->tgnewtable, trig2->tgnewtable) != 0)
2010 else if (trigdesc2 != NULL)
2014 #endif /* NOT_USED */
2017 * Call a trigger function.
2019 * trigdata: trigger descriptor.
2020 * tgindx: trigger's index in finfo and instr arrays.
2021 * finfo: array of cached trigger function call information.
2022 * instr: optional array of EXPLAIN ANALYZE instrumentation state.
2023 * per_tuple_context: memory context to execute the function in.
2025 * Returns the tuple (or NULL) as returned by the function.
2028 ExecCallTriggerFunc(TriggerData *trigdata,
2031 Instrumentation *instr,
2032 MemoryContext per_tuple_context)
2034 FunctionCallInfoData fcinfo;
2035 PgStat_FunctionCallUsage fcusage;
2037 MemoryContext oldContext;
2040 * Protect against code paths that may fail to initialize transition table
2043 Assert(((TRIGGER_FIRED_BY_INSERT(trigdata->tg_event) ||
2044 TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event) ||
2045 TRIGGER_FIRED_BY_DELETE(trigdata->tg_event)) &&
2046 TRIGGER_FIRED_AFTER(trigdata->tg_event) &&
2047 !(trigdata->tg_event & AFTER_TRIGGER_DEFERRABLE) &&
2048 !(trigdata->tg_event & AFTER_TRIGGER_INITDEFERRED)) ||
2049 (trigdata->tg_oldtable == NULL && trigdata->tg_newtable == NULL));
2054 * We cache fmgr lookup info, to avoid making the lookup again on each
2057 if (finfo->fn_oid == InvalidOid)
2058 fmgr_info(trigdata->tg_trigger->tgfoid, finfo);
2060 Assert(finfo->fn_oid == trigdata->tg_trigger->tgfoid);
2063 * If doing EXPLAIN ANALYZE, start charging time to this trigger.
2066 InstrStartNode(instr + tgindx);
2069 * Do the function evaluation in the per-tuple memory context, so that
2070 * leaked memory will be reclaimed once per tuple. Note in particular that
2071 * any new tuple created by the trigger function will live till the end of
2074 oldContext = MemoryContextSwitchTo(per_tuple_context);
2077 * Call the function, passing no arguments but setting a context.
2079 InitFunctionCallInfoData(fcinfo, finfo, 0,
2080 InvalidOid, (Node *) trigdata, NULL);
2082 pgstat_init_function_usage(&fcinfo, &fcusage);
2087 result = FunctionCallInvoke(&fcinfo);
2097 pgstat_end_function_usage(&fcusage, true);
2099 MemoryContextSwitchTo(oldContext);
2102 * Trigger protocol allows function to return a null pointer, but NOT to
2103 * set the isnull result flag.
2107 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2108 errmsg("trigger function %u returned null value",
2109 fcinfo.flinfo->fn_oid)));
2112 * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
2113 * one "tuple returned" (really the number of firings).
2116 InstrStopNode(instr + tgindx, 1);
2118 return (HeapTuple) DatumGetPointer(result);
2122 ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
2124 TriggerDesc *trigdesc;
2126 TriggerData LocTriggerData;
2128 trigdesc = relinfo->ri_TrigDesc;
2130 if (trigdesc == NULL)
2132 if (!trigdesc->trig_insert_before_statement)
2135 LocTriggerData.type = T_TriggerData;
2136 LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
2137 TRIGGER_EVENT_BEFORE;
2138 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2139 LocTriggerData.tg_trigtuple = NULL;
2140 LocTriggerData.tg_newtuple = NULL;
2141 LocTriggerData.tg_oldtable = NULL;
2142 LocTriggerData.tg_newtable = NULL;
2143 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2144 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2145 for (i = 0; i < trigdesc->numtriggers; i++)
2147 Trigger *trigger = &trigdesc->triggers[i];
2150 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2151 TRIGGER_TYPE_STATEMENT,
2152 TRIGGER_TYPE_BEFORE,
2153 TRIGGER_TYPE_INSERT))
2155 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2159 LocTriggerData.tg_trigger = trigger;
2160 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2162 relinfo->ri_TrigFunctions,
2163 relinfo->ri_TrigInstrument,
2164 GetPerTupleMemoryContext(estate));
2168 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2169 errmsg("BEFORE STATEMENT trigger cannot return a value")));
2174 ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo)
2176 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2178 if (trigdesc && trigdesc->trig_insert_after_statement)
2179 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_INSERT,
2180 false, NULL, NULL, NIL, NULL);
2184 ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
2185 TupleTableSlot *slot)
2187 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2188 HeapTuple slottuple = ExecMaterializeSlot(slot);
2189 HeapTuple newtuple = slottuple;
2191 TriggerData LocTriggerData;
2194 LocTriggerData.type = T_TriggerData;
2195 LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
2197 TRIGGER_EVENT_BEFORE;
2198 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2199 LocTriggerData.tg_newtuple = NULL;
2200 LocTriggerData.tg_oldtable = NULL;
2201 LocTriggerData.tg_newtable = NULL;
2202 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2203 for (i = 0; i < trigdesc->numtriggers; i++)
2205 Trigger *trigger = &trigdesc->triggers[i];
2207 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2209 TRIGGER_TYPE_BEFORE,
2210 TRIGGER_TYPE_INSERT))
2212 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2213 NULL, NULL, newtuple))
2216 LocTriggerData.tg_trigtuple = oldtuple = newtuple;
2217 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2218 LocTriggerData.tg_trigger = trigger;
2219 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2221 relinfo->ri_TrigFunctions,
2222 relinfo->ri_TrigInstrument,
2223 GetPerTupleMemoryContext(estate));
2224 if (oldtuple != newtuple && oldtuple != slottuple)
2225 heap_freetuple(oldtuple);
2226 if (newtuple == NULL)
2227 return NULL; /* "do nothing" */
2230 if (newtuple != slottuple)
2233 * Return the modified tuple using the es_trig_tuple_slot. We assume
2234 * the tuple was allocated in per-tuple memory context, and therefore
2235 * will go away by itself. The tuple table slot should not try to
2238 TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2239 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2241 if (newslot->tts_tupleDescriptor != tupdesc)
2242 ExecSetSlotDescriptor(newslot, tupdesc);
2243 ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2250 ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo,
2251 HeapTuple trigtuple, List *recheckIndexes)
2253 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2256 (trigdesc->trig_insert_after_row || trigdesc->trig_insert_new_table))
2257 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_INSERT,
2258 true, NULL, trigtuple, recheckIndexes, NULL);
2262 ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
2263 TupleTableSlot *slot)
2265 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2266 HeapTuple slottuple = ExecMaterializeSlot(slot);
2267 HeapTuple newtuple = slottuple;
2269 TriggerData LocTriggerData;
2272 LocTriggerData.type = T_TriggerData;
2273 LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
2275 TRIGGER_EVENT_INSTEAD;
2276 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2277 LocTriggerData.tg_newtuple = NULL;
2278 LocTriggerData.tg_oldtable = NULL;
2279 LocTriggerData.tg_newtable = NULL;
2280 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2281 for (i = 0; i < trigdesc->numtriggers; i++)
2283 Trigger *trigger = &trigdesc->triggers[i];
2285 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2287 TRIGGER_TYPE_INSTEAD,
2288 TRIGGER_TYPE_INSERT))
2290 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2291 NULL, NULL, newtuple))
2294 LocTriggerData.tg_trigtuple = oldtuple = newtuple;
2295 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2296 LocTriggerData.tg_trigger = trigger;
2297 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2299 relinfo->ri_TrigFunctions,
2300 relinfo->ri_TrigInstrument,
2301 GetPerTupleMemoryContext(estate));
2302 if (oldtuple != newtuple && oldtuple != slottuple)
2303 heap_freetuple(oldtuple);
2304 if (newtuple == NULL)
2305 return NULL; /* "do nothing" */
2308 if (newtuple != slottuple)
2311 * Return the modified tuple using the es_trig_tuple_slot. We assume
2312 * the tuple was allocated in per-tuple memory context, and therefore
2313 * will go away by itself. The tuple table slot should not try to
2316 TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2317 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2319 if (newslot->tts_tupleDescriptor != tupdesc)
2320 ExecSetSlotDescriptor(newslot, tupdesc);
2321 ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2328 ExecBSDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
2330 TriggerDesc *trigdesc;
2332 TriggerData LocTriggerData;
2334 trigdesc = relinfo->ri_TrigDesc;
2336 if (trigdesc == NULL)
2338 if (!trigdesc->trig_delete_before_statement)
2341 LocTriggerData.type = T_TriggerData;
2342 LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
2343 TRIGGER_EVENT_BEFORE;
2344 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2345 LocTriggerData.tg_trigtuple = NULL;
2346 LocTriggerData.tg_newtuple = NULL;
2347 LocTriggerData.tg_oldtable = NULL;
2348 LocTriggerData.tg_newtable = NULL;
2349 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2350 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2351 for (i = 0; i < trigdesc->numtriggers; i++)
2353 Trigger *trigger = &trigdesc->triggers[i];
2356 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2357 TRIGGER_TYPE_STATEMENT,
2358 TRIGGER_TYPE_BEFORE,
2359 TRIGGER_TYPE_DELETE))
2361 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2365 LocTriggerData.tg_trigger = trigger;
2366 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2368 relinfo->ri_TrigFunctions,
2369 relinfo->ri_TrigInstrument,
2370 GetPerTupleMemoryContext(estate));
2374 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2375 errmsg("BEFORE STATEMENT trigger cannot return a value")));
2380 ExecASDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
2382 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2384 if (trigdesc && trigdesc->trig_delete_after_statement)
2385 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_DELETE,
2386 false, NULL, NULL, NIL, NULL);
2390 ExecBRDeleteTriggers(EState *estate, EPQState *epqstate,
2391 ResultRelInfo *relinfo,
2392 ItemPointer tupleid,
2393 HeapTuple fdw_trigtuple)
2395 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2397 TriggerData LocTriggerData;
2398 HeapTuple trigtuple;
2400 TupleTableSlot *newSlot;
2403 Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2404 if (fdw_trigtuple == NULL)
2406 trigtuple = GetTupleForTrigger(estate, epqstate, relinfo, tupleid,
2407 LockTupleExclusive, &newSlot);
2408 if (trigtuple == NULL)
2412 trigtuple = fdw_trigtuple;
2414 LocTriggerData.type = T_TriggerData;
2415 LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
2417 TRIGGER_EVENT_BEFORE;
2418 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2419 LocTriggerData.tg_newtuple = NULL;
2420 LocTriggerData.tg_oldtable = NULL;
2421 LocTriggerData.tg_newtable = NULL;
2422 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2423 for (i = 0; i < trigdesc->numtriggers; i++)
2425 Trigger *trigger = &trigdesc->triggers[i];
2427 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2429 TRIGGER_TYPE_BEFORE,
2430 TRIGGER_TYPE_DELETE))
2432 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2433 NULL, trigtuple, NULL))
2436 LocTriggerData.tg_trigtuple = trigtuple;
2437 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2438 LocTriggerData.tg_trigger = trigger;
2439 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2441 relinfo->ri_TrigFunctions,
2442 relinfo->ri_TrigInstrument,
2443 GetPerTupleMemoryContext(estate));
2444 if (newtuple == NULL)
2446 result = false; /* tell caller to suppress delete */
2449 if (newtuple != trigtuple)
2450 heap_freetuple(newtuple);
2452 if (trigtuple != fdw_trigtuple)
2453 heap_freetuple(trigtuple);
2459 ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
2460 ItemPointer tupleid,
2461 HeapTuple fdw_trigtuple)
2463 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2466 (trigdesc->trig_delete_after_row || trigdesc->trig_delete_old_table))
2468 HeapTuple trigtuple;
2470 Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2471 if (fdw_trigtuple == NULL)
2472 trigtuple = GetTupleForTrigger(estate,
2479 trigtuple = fdw_trigtuple;
2481 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_DELETE,
2482 true, trigtuple, NULL, NIL, NULL);
2483 if (trigtuple != fdw_trigtuple)
2484 heap_freetuple(trigtuple);
2489 ExecIRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
2490 HeapTuple trigtuple)
2492 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2493 TriggerData LocTriggerData;
2497 LocTriggerData.type = T_TriggerData;
2498 LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
2500 TRIGGER_EVENT_INSTEAD;
2501 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2502 LocTriggerData.tg_newtuple = NULL;
2503 LocTriggerData.tg_oldtable = NULL;
2504 LocTriggerData.tg_newtable = NULL;
2505 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2506 for (i = 0; i < trigdesc->numtriggers; i++)
2508 Trigger *trigger = &trigdesc->triggers[i];
2510 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2512 TRIGGER_TYPE_INSTEAD,
2513 TRIGGER_TYPE_DELETE))
2515 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2516 NULL, trigtuple, NULL))
2519 LocTriggerData.tg_trigtuple = trigtuple;
2520 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2521 LocTriggerData.tg_trigger = trigger;
2522 rettuple = ExecCallTriggerFunc(&LocTriggerData,
2524 relinfo->ri_TrigFunctions,
2525 relinfo->ri_TrigInstrument,
2526 GetPerTupleMemoryContext(estate));
2527 if (rettuple == NULL)
2528 return false; /* Delete was suppressed */
2529 if (rettuple != trigtuple)
2530 heap_freetuple(rettuple);
2536 ExecBSUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
2538 TriggerDesc *trigdesc;
2540 TriggerData LocTriggerData;
2541 Bitmapset *updatedCols;
2543 trigdesc = relinfo->ri_TrigDesc;
2545 if (trigdesc == NULL)
2547 if (!trigdesc->trig_update_before_statement)
2550 updatedCols = GetUpdatedColumns(relinfo, estate);
2552 LocTriggerData.type = T_TriggerData;
2553 LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
2554 TRIGGER_EVENT_BEFORE;
2555 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2556 LocTriggerData.tg_trigtuple = NULL;
2557 LocTriggerData.tg_newtuple = NULL;
2558 LocTriggerData.tg_oldtable = NULL;
2559 LocTriggerData.tg_newtable = NULL;
2560 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2561 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2562 for (i = 0; i < trigdesc->numtriggers; i++)
2564 Trigger *trigger = &trigdesc->triggers[i];
2567 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2568 TRIGGER_TYPE_STATEMENT,
2569 TRIGGER_TYPE_BEFORE,
2570 TRIGGER_TYPE_UPDATE))
2572 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2573 updatedCols, NULL, NULL))
2576 LocTriggerData.tg_trigger = trigger;
2577 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2579 relinfo->ri_TrigFunctions,
2580 relinfo->ri_TrigInstrument,
2581 GetPerTupleMemoryContext(estate));
2585 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2586 errmsg("BEFORE STATEMENT trigger cannot return a value")));
2591 ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
2593 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2595 if (trigdesc && trigdesc->trig_update_after_statement)
2596 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_UPDATE,
2597 false, NULL, NULL, NIL,
2598 GetUpdatedColumns(relinfo, estate));
2602 ExecBRUpdateTriggers(EState *estate, EPQState *epqstate,
2603 ResultRelInfo *relinfo,
2604 ItemPointer tupleid,
2605 HeapTuple fdw_trigtuple,
2606 TupleTableSlot *slot)
2608 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2609 HeapTuple slottuple = ExecMaterializeSlot(slot);
2610 HeapTuple newtuple = slottuple;
2611 TriggerData LocTriggerData;
2612 HeapTuple trigtuple;
2614 TupleTableSlot *newSlot;
2616 Bitmapset *updatedCols;
2617 LockTupleMode lockmode;
2619 /* Determine lock mode to use */
2620 lockmode = ExecUpdateLockMode(estate, relinfo);
2622 Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2623 if (fdw_trigtuple == NULL)
2625 /* get a copy of the on-disk tuple we are planning to update */
2626 trigtuple = GetTupleForTrigger(estate, epqstate, relinfo, tupleid,
2627 lockmode, &newSlot);
2628 if (trigtuple == NULL)
2629 return NULL; /* cancel the update action */
2633 trigtuple = fdw_trigtuple;
2638 * In READ COMMITTED isolation level it's possible that target tuple was
2639 * changed due to concurrent update. In that case we have a raw subplan
2640 * output tuple in newSlot, and need to run it through the junk filter to
2641 * produce an insertable tuple.
2643 * Caution: more than likely, the passed-in slot is the same as the
2644 * junkfilter's output slot, so we are clobbering the original value of
2645 * slottuple by doing the filtering. This is OK since neither we nor our
2646 * caller have any more interest in the prior contents of that slot.
2648 if (newSlot != NULL)
2650 slot = ExecFilterJunk(relinfo->ri_junkFilter, newSlot);
2651 slottuple = ExecMaterializeSlot(slot);
2652 newtuple = slottuple;
2656 LocTriggerData.type = T_TriggerData;
2657 LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
2659 TRIGGER_EVENT_BEFORE;
2660 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2661 LocTriggerData.tg_oldtable = NULL;
2662 LocTriggerData.tg_newtable = NULL;
2663 updatedCols = GetUpdatedColumns(relinfo, estate);
2664 for (i = 0; i < trigdesc->numtriggers; i++)
2666 Trigger *trigger = &trigdesc->triggers[i];
2668 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2670 TRIGGER_TYPE_BEFORE,
2671 TRIGGER_TYPE_UPDATE))
2673 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2674 updatedCols, trigtuple, newtuple))
2677 LocTriggerData.tg_trigtuple = trigtuple;
2678 LocTriggerData.tg_newtuple = oldtuple = newtuple;
2679 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2680 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2681 LocTriggerData.tg_trigger = trigger;
2682 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2684 relinfo->ri_TrigFunctions,
2685 relinfo->ri_TrigInstrument,
2686 GetPerTupleMemoryContext(estate));
2687 if (oldtuple != newtuple && oldtuple != slottuple)
2688 heap_freetuple(oldtuple);
2689 if (newtuple == NULL)
2691 if (trigtuple != fdw_trigtuple)
2692 heap_freetuple(trigtuple);
2693 return NULL; /* "do nothing" */
2696 if (trigtuple != fdw_trigtuple)
2697 heap_freetuple(trigtuple);
2699 if (newtuple != slottuple)
2702 * Return the modified tuple using the es_trig_tuple_slot. We assume
2703 * the tuple was allocated in per-tuple memory context, and therefore
2704 * will go away by itself. The tuple table slot should not try to
2707 TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2708 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2710 if (newslot->tts_tupleDescriptor != tupdesc)
2711 ExecSetSlotDescriptor(newslot, tupdesc);
2712 ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2719 ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
2720 ItemPointer tupleid,
2721 HeapTuple fdw_trigtuple,
2723 List *recheckIndexes)
2725 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2727 if (trigdesc && (trigdesc->trig_update_after_row ||
2728 trigdesc->trig_update_old_table || trigdesc->trig_update_new_table))
2730 HeapTuple trigtuple;
2732 Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2733 if (fdw_trigtuple == NULL)
2734 trigtuple = GetTupleForTrigger(estate,
2741 trigtuple = fdw_trigtuple;
2743 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_UPDATE,
2744 true, trigtuple, newtuple, recheckIndexes,
2745 GetUpdatedColumns(relinfo, estate));
2746 if (trigtuple != fdw_trigtuple)
2747 heap_freetuple(trigtuple);
2752 ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
2753 HeapTuple trigtuple, TupleTableSlot *slot)
2755 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2756 HeapTuple slottuple = ExecMaterializeSlot(slot);
2757 HeapTuple newtuple = slottuple;
2758 TriggerData LocTriggerData;
2762 LocTriggerData.type = T_TriggerData;
2763 LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
2765 TRIGGER_EVENT_INSTEAD;
2766 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2767 LocTriggerData.tg_oldtable = NULL;
2768 LocTriggerData.tg_newtable = NULL;
2769 for (i = 0; i < trigdesc->numtriggers; i++)
2771 Trigger *trigger = &trigdesc->triggers[i];
2773 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2775 TRIGGER_TYPE_INSTEAD,
2776 TRIGGER_TYPE_UPDATE))
2778 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2779 NULL, trigtuple, newtuple))
2782 LocTriggerData.tg_trigtuple = trigtuple;
2783 LocTriggerData.tg_newtuple = oldtuple = newtuple;
2784 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2785 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2786 LocTriggerData.tg_trigger = trigger;
2787 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2789 relinfo->ri_TrigFunctions,
2790 relinfo->ri_TrigInstrument,
2791 GetPerTupleMemoryContext(estate));
2792 if (oldtuple != newtuple && oldtuple != slottuple)
2793 heap_freetuple(oldtuple);
2794 if (newtuple == NULL)
2795 return NULL; /* "do nothing" */
2798 if (newtuple != slottuple)
2801 * Return the modified tuple using the es_trig_tuple_slot. We assume
2802 * the tuple was allocated in per-tuple memory context, and therefore
2803 * will go away by itself. The tuple table slot should not try to
2806 TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2807 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2809 if (newslot->tts_tupleDescriptor != tupdesc)
2810 ExecSetSlotDescriptor(newslot, tupdesc);
2811 ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2818 ExecBSTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
2820 TriggerDesc *trigdesc;
2822 TriggerData LocTriggerData;
2824 trigdesc = relinfo->ri_TrigDesc;
2826 if (trigdesc == NULL)
2828 if (!trigdesc->trig_truncate_before_statement)
2831 LocTriggerData.type = T_TriggerData;
2832 LocTriggerData.tg_event = TRIGGER_EVENT_TRUNCATE |
2833 TRIGGER_EVENT_BEFORE;
2834 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2835 LocTriggerData.tg_trigtuple = NULL;
2836 LocTriggerData.tg_newtuple = NULL;
2837 LocTriggerData.tg_oldtable = NULL;
2838 LocTriggerData.tg_newtable = NULL;
2839 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2840 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2841 for (i = 0; i < trigdesc->numtriggers; i++)
2843 Trigger *trigger = &trigdesc->triggers[i];
2846 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2847 TRIGGER_TYPE_STATEMENT,
2848 TRIGGER_TYPE_BEFORE,
2849 TRIGGER_TYPE_TRUNCATE))
2851 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2855 LocTriggerData.tg_trigger = trigger;
2856 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2858 relinfo->ri_TrigFunctions,
2859 relinfo->ri_TrigInstrument,
2860 GetPerTupleMemoryContext(estate));
2864 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2865 errmsg("BEFORE STATEMENT trigger cannot return a value")));
2870 ExecASTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
2872 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2874 if (trigdesc && trigdesc->trig_truncate_after_statement)
2875 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_TRUNCATE,
2876 false, NULL, NULL, NIL, NULL);
2881 GetTupleForTrigger(EState *estate,
2883 ResultRelInfo *relinfo,
2885 LockTupleMode lockmode,
2886 TupleTableSlot **newSlot)
2888 Relation relation = relinfo->ri_RelationDesc;
2889 HeapTupleData tuple;
2893 if (newSlot != NULL)
2896 HeapUpdateFailureData hufd;
2900 /* caller must pass an epqstate if EvalPlanQual is possible */
2901 Assert(epqstate != NULL);
2904 * lock tuple for update
2907 tuple.t_self = *tid;
2908 test = heap_lock_tuple(relation, &tuple,
2909 estate->es_output_cid,
2910 lockmode, LockWaitBlock,
2911 false, &buffer, &hufd);
2914 case HeapTupleSelfUpdated:
2917 * The target tuple was already updated or deleted by the
2918 * current command, or by a later command in the current
2919 * transaction. We ignore the tuple in the former case, and
2920 * throw error in the latter case, for the same reasons
2921 * enumerated in ExecUpdate and ExecDelete in
2922 * nodeModifyTable.c.
2924 if (hufd.cmax != estate->es_output_cid)
2926 (errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
2927 errmsg("tuple to be updated was already modified by an operation triggered by the current command"),
2928 errhint("Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
2930 /* treat it as deleted; do not process */
2931 ReleaseBuffer(buffer);
2934 case HeapTupleMayBeUpdated:
2937 case HeapTupleUpdated:
2938 ReleaseBuffer(buffer);
2939 if (IsolationUsesXactSnapshot())
2941 (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
2942 errmsg("could not serialize access due to concurrent update")));
2943 if (!ItemPointerEquals(&hufd.ctid, &tuple.t_self))
2945 /* it was updated, so look at the updated version */
2946 TupleTableSlot *epqslot;
2948 epqslot = EvalPlanQual(estate,
2951 relinfo->ri_RangeTableIndex,
2955 if (!TupIsNull(epqslot))
2961 * EvalPlanQual already locked the tuple, but we
2962 * re-call heap_lock_tuple anyway as an easy way of
2963 * re-fetching the correct tuple. Speed is hardly a
2964 * criterion in this path anyhow.
2971 * if tuple was deleted or PlanQual failed for updated tuple -
2972 * we must not process this tuple!
2976 case HeapTupleInvisible:
2977 elog(ERROR, "attempted to lock invisible tuple");
2980 ReleaseBuffer(buffer);
2981 elog(ERROR, "unrecognized heap_lock_tuple status: %u", test);
2982 return NULL; /* keep compiler quiet */
2990 buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
2993 * Although we already know this tuple is valid, we must lock the
2994 * buffer to ensure that no one has a buffer cleanup lock; otherwise
2995 * they might move the tuple while we try to copy it. But we can
2996 * release the lock before actually doing the heap_copytuple call,
2997 * since holding pin is sufficient to prevent anyone from getting a
2998 * cleanup lock they don't already hold.
3000 LockBuffer(buffer, BUFFER_LOCK_SHARE);
3002 page = BufferGetPage(buffer);
3003 lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
3005 Assert(ItemIdIsNormal(lp));
3007 tuple.t_data = (HeapTupleHeader) PageGetItem(page, lp);
3008 tuple.t_len = ItemIdGetLength(lp);
3009 tuple.t_self = *tid;
3010 tuple.t_tableOid = RelationGetRelid(relation);
3012 LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3015 result = heap_copytuple(&tuple);
3016 ReleaseBuffer(buffer);
3022 * Is trigger enabled to fire?
3025 TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
3026 Trigger *trigger, TriggerEvent event,
3027 Bitmapset *modifiedCols,
3028 HeapTuple oldtup, HeapTuple newtup)
3030 /* Check replication-role-dependent enable state */
3031 if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
3033 if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
3034 trigger->tgenabled == TRIGGER_DISABLED)
3037 else /* ORIGIN or LOCAL role */
3039 if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
3040 trigger->tgenabled == TRIGGER_DISABLED)
3045 * Check for column-specific trigger (only possible for UPDATE, and in
3046 * fact we *must* ignore tgattr for other event types)
3048 if (trigger->tgnattr > 0 && TRIGGER_FIRED_BY_UPDATE(event))
3054 for (i = 0; i < trigger->tgnattr; i++)
3056 if (bms_is_member(trigger->tgattr[i] - FirstLowInvalidHeapAttributeNumber,
3067 /* Check for WHEN clause */
3068 if (trigger->tgqual)
3070 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
3072 ExprContext *econtext;
3073 TupleTableSlot *oldslot = NULL;
3074 TupleTableSlot *newslot = NULL;
3075 MemoryContext oldContext;
3078 Assert(estate != NULL);
3081 * trigger is an element of relinfo->ri_TrigDesc->triggers[]; find the
3082 * matching element of relinfo->ri_TrigWhenExprs[]
3084 i = trigger - relinfo->ri_TrigDesc->triggers;
3085 predicate = &relinfo->ri_TrigWhenExprs[i];
3088 * If first time through for this WHEN expression, build expression
3089 * nodetrees for it. Keep them in the per-query memory context so
3090 * they'll survive throughout the query.
3092 if (*predicate == NIL)
3096 oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
3097 tgqual = stringToNode(trigger->tgqual);
3098 /* Change references to OLD and NEW to INNER_VAR and OUTER_VAR */
3099 ChangeVarNodes(tgqual, PRS2_OLD_VARNO, INNER_VAR, 0);
3100 ChangeVarNodes(tgqual, PRS2_NEW_VARNO, OUTER_VAR, 0);
3101 /* ExecQual wants implicit-AND form */
3102 tgqual = (Node *) make_ands_implicit((Expr *) tgqual);
3103 *predicate = (List *) ExecPrepareExpr((Expr *) tgqual, estate);
3104 MemoryContextSwitchTo(oldContext);
3108 * We will use the EState's per-tuple context for evaluating WHEN
3109 * expressions (creating it if it's not already there).
3111 econtext = GetPerTupleExprContext(estate);
3114 * Put OLD and NEW tuples into tupleslots for expression evaluation.
3115 * These slots can be shared across the whole estate, but be careful
3116 * that they have the current resultrel's tupdesc.
3118 if (HeapTupleIsValid(oldtup))
3120 if (estate->es_trig_oldtup_slot == NULL)
3122 oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
3123 estate->es_trig_oldtup_slot = ExecInitExtraTupleSlot(estate);
3124 MemoryContextSwitchTo(oldContext);
3126 oldslot = estate->es_trig_oldtup_slot;
3127 if (oldslot->tts_tupleDescriptor != tupdesc)
3128 ExecSetSlotDescriptor(oldslot, tupdesc);
3129 ExecStoreTuple(oldtup, oldslot, InvalidBuffer, false);
3131 if (HeapTupleIsValid(newtup))
3133 if (estate->es_trig_newtup_slot == NULL)
3135 oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
3136 estate->es_trig_newtup_slot = ExecInitExtraTupleSlot(estate);
3137 MemoryContextSwitchTo(oldContext);
3139 newslot = estate->es_trig_newtup_slot;
3140 if (newslot->tts_tupleDescriptor != tupdesc)
3141 ExecSetSlotDescriptor(newslot, tupdesc);
3142 ExecStoreTuple(newtup, newslot, InvalidBuffer, false);
3146 * Finally evaluate the expression, making the old and/or new tuples
3147 * available as INNER_VAR/OUTER_VAR respectively.
3149 econtext->ecxt_innertuple = oldslot;
3150 econtext->ecxt_outertuple = newslot;
3151 if (!ExecQual(*predicate, econtext, false))
3160 * After-trigger stuff
3162 * The AfterTriggersData struct holds data about pending AFTER trigger events
3163 * during the current transaction tree. (BEFORE triggers are fired
3164 * immediately so we don't need any persistent state about them.) The struct
3165 * and most of its subsidiary data are kept in TopTransactionContext; however
3166 * the individual event records are kept in a separate sub-context. This is
3167 * done mainly so that it's easy to tell from a memory context dump how much
3168 * space is being eaten by trigger events.
3170 * Because the list of pending events can grow large, we go to some
3171 * considerable effort to minimize per-event memory consumption. The event
3172 * records are grouped into chunks and common data for similar events in the
3173 * same chunk is only stored once.
3175 * XXX We need to be able to save the per-event data in a file if it grows too
3180 /* Per-trigger SET CONSTRAINT status */
3181 typedef struct SetConstraintTriggerData
3184 bool sct_tgisdeferred;
3185 } SetConstraintTriggerData;
3187 typedef struct SetConstraintTriggerData *SetConstraintTrigger;
3190 * SET CONSTRAINT intra-transaction status.
3192 * We make this a single palloc'd object so it can be copied and freed easily.
3194 * all_isset and all_isdeferred are used to keep track
3195 * of SET CONSTRAINTS ALL {DEFERRED, IMMEDIATE}.
3197 * trigstates[] stores per-trigger tgisdeferred settings.
3199 typedef struct SetConstraintStateData
3202 bool all_isdeferred;
3203 int numstates; /* number of trigstates[] entries in use */
3204 int numalloc; /* allocated size of trigstates[] */
3205 SetConstraintTriggerData trigstates[FLEXIBLE_ARRAY_MEMBER];
3206 } SetConstraintStateData;
3208 typedef SetConstraintStateData *SetConstraintState;
3212 * Per-trigger-event data
3214 * The actual per-event data, AfterTriggerEventData, includes DONE/IN_PROGRESS
3215 * status bits and up to two tuple CTIDs. Each event record also has an
3216 * associated AfterTriggerSharedData that is shared across all instances of
3217 * similar events within a "chunk".
3219 * For row-level triggers, we arrange not to waste storage on unneeded ctid
3220 * fields. Updates of regular tables use two; inserts and deletes of regular
3221 * tables use one; foreign tables always use zero and save the tuple(s) to a
3222 * tuplestore. AFTER_TRIGGER_FDW_FETCH directs AfterTriggerExecute() to
3223 * retrieve a fresh tuple or pair of tuples from that tuplestore, while
3224 * AFTER_TRIGGER_FDW_REUSE directs it to use the most-recently-retrieved
3225 * tuple(s). This permits storing tuples once regardless of the number of
3226 * row-level triggers on a foreign table.
3228 * Statement-level triggers always bear AFTER_TRIGGER_1CTID, though they
3229 * require no ctid field. We lack the flag bit space to neatly represent that
3230 * distinct case, and it seems unlikely to be worth much trouble.
3232 * Note: ats_firing_id is initially zero and is set to something else when
3233 * AFTER_TRIGGER_IN_PROGRESS is set. It indicates which trigger firing
3234 * cycle the trigger will be fired in (or was fired in, if DONE is set).
3235 * Although this is mutable state, we can keep it in AfterTriggerSharedData
3236 * because all instances of the same type of event in a given event list will
3237 * be fired at the same time, if they were queued between the same firing
3238 * cycles. So we need only ensure that ats_firing_id is zero when attaching
3239 * a new event to an existing AfterTriggerSharedData record.
3241 typedef uint32 TriggerFlags;
3243 #define AFTER_TRIGGER_OFFSET 0x0FFFFFFF /* must be low-order
3245 #define AFTER_TRIGGER_DONE 0x10000000
3246 #define AFTER_TRIGGER_IN_PROGRESS 0x20000000
3247 /* bits describing the size and tuple sources of this event */
3248 #define AFTER_TRIGGER_FDW_REUSE 0x00000000
3249 #define AFTER_TRIGGER_FDW_FETCH 0x80000000
3250 #define AFTER_TRIGGER_1CTID 0x40000000
3251 #define AFTER_TRIGGER_2CTID 0xC0000000
3252 #define AFTER_TRIGGER_TUP_BITS 0xC0000000
3254 typedef struct AfterTriggerSharedData *AfterTriggerShared;
3256 typedef struct AfterTriggerSharedData
3258 TriggerEvent ats_event; /* event type indicator, see trigger.h */
3259 Oid ats_tgoid; /* the trigger's ID */
3260 Oid ats_relid; /* the relation it's on */
3261 CommandId ats_firing_id; /* ID for firing cycle */
3262 } AfterTriggerSharedData;
3264 typedef struct AfterTriggerEventData *AfterTriggerEvent;
3266 typedef struct AfterTriggerEventData
3268 TriggerFlags ate_flags; /* status bits and offset to shared data */
3269 ItemPointerData ate_ctid1; /* inserted, deleted, or old updated tuple */
3270 ItemPointerData ate_ctid2; /* new updated tuple */
3271 } AfterTriggerEventData;
3273 /* AfterTriggerEventData, minus ate_ctid2 */
3274 typedef struct AfterTriggerEventDataOneCtid
3276 TriggerFlags ate_flags; /* status bits and offset to shared data */
3277 ItemPointerData ate_ctid1; /* inserted, deleted, or old updated tuple */
3278 } AfterTriggerEventDataOneCtid;
3280 /* AfterTriggerEventData, minus ate_ctid1 and ate_ctid2 */
3281 typedef struct AfterTriggerEventDataZeroCtids
3283 TriggerFlags ate_flags; /* status bits and offset to shared data */
3284 } AfterTriggerEventDataZeroCtids;
3286 #define SizeofTriggerEvent(evt) \
3287 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_2CTID ? \
3288 sizeof(AfterTriggerEventData) : \
3289 ((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_1CTID ? \
3290 sizeof(AfterTriggerEventDataOneCtid) : \
3291 sizeof(AfterTriggerEventDataZeroCtids))
3293 #define GetTriggerSharedData(evt) \
3294 ((AfterTriggerShared) ((char *) (evt) + ((evt)->ate_flags & AFTER_TRIGGER_OFFSET)))
3297 * To avoid palloc overhead, we keep trigger events in arrays in successively-
3298 * larger chunks (a slightly more sophisticated version of an expansible
3299 * array). The space between CHUNK_DATA_START and freeptr is occupied by
3300 * AfterTriggerEventData records; the space between endfree and endptr is
3301 * occupied by AfterTriggerSharedData records.
3303 typedef struct AfterTriggerEventChunk
3305 struct AfterTriggerEventChunk *next; /* list link */
3306 char *freeptr; /* start of free space in chunk */
3307 char *endfree; /* end of free space in chunk */
3308 char *endptr; /* end of chunk */
3309 /* event data follows here */
3310 } AfterTriggerEventChunk;
3312 #define CHUNK_DATA_START(cptr) ((char *) (cptr) + MAXALIGN(sizeof(AfterTriggerEventChunk)))
3314 /* A list of events */
3315 typedef struct AfterTriggerEventList
3317 AfterTriggerEventChunk *head;
3318 AfterTriggerEventChunk *tail;
3319 char *tailfree; /* freeptr of tail chunk */
3320 } AfterTriggerEventList;
3322 /* Macros to help in iterating over a list of events */
3323 #define for_each_chunk(cptr, evtlist) \
3324 for (cptr = (evtlist).head; cptr != NULL; cptr = cptr->next)
3325 #define for_each_event(eptr, cptr) \
3326 for (eptr = (AfterTriggerEvent) CHUNK_DATA_START(cptr); \
3327 (char *) eptr < (cptr)->freeptr; \
3328 eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
3329 /* Use this if no special per-chunk processing is needed */
3330 #define for_each_event_chunk(eptr, cptr, evtlist) \
3331 for_each_chunk(cptr, evtlist) for_each_event(eptr, cptr)
3335 * All per-transaction data for the AFTER TRIGGERS module.
3337 * AfterTriggersData has the following fields:
3339 * firing_counter is incremented for each call of afterTriggerInvokeEvents.
3340 * We mark firable events with the current firing cycle's ID so that we can
3341 * tell which ones to work on. This ensures sane behavior if a trigger
3342 * function chooses to do SET CONSTRAINTS: the inner SET CONSTRAINTS will
3343 * only fire those events that weren't already scheduled for firing.
3345 * state keeps track of the transaction-local effects of SET CONSTRAINTS.
3346 * This is saved and restored across failed subtransactions.
3348 * events is the current list of deferred events. This is global across
3349 * all subtransactions of the current transaction. In a subtransaction
3350 * abort, we know that the events added by the subtransaction are at the
3351 * end of the list, so it is relatively easy to discard them. The event
3352 * list chunks themselves are stored in event_cxt.
3354 * query_depth is the current depth of nested AfterTriggerBeginQuery calls
3355 * (-1 when the stack is empty).
3357 * query_stack[query_depth] is a list of AFTER trigger events queued by the
3358 * current query (and the query_stack entries below it are lists of trigger
3359 * events queued by calling queries). None of these are valid until the
3360 * matching AfterTriggerEndQuery call occurs. At that point we fire
3361 * immediate-mode triggers, and append any deferred events to the main events
3364 * fdw_tuplestores[query_depth] is a tuplestore containing the foreign tuples
3365 * needed for the current query.
3367 * old_tuplestores[query_depth] and new_tuplestores[query_depth] hold the
3368 * transition relations for the current query.
3370 * maxquerydepth is just the allocated length of query_stack and the
3373 * state_stack is a stack of pointers to saved copies of the SET CONSTRAINTS
3374 * state data; each subtransaction level that modifies that state first
3375 * saves a copy, which we use to restore the state if we abort.
3377 * events_stack is a stack of copies of the events head/tail pointers,
3378 * which we use to restore those values during subtransaction abort.
3380 * depth_stack is a stack of copies of subtransaction-start-time query_depth,
3381 * which we similarly use to clean up at subtransaction abort.
3383 * firing_stack is a stack of copies of subtransaction-start-time
3384 * firing_counter. We use this to recognize which deferred triggers were
3385 * fired (or marked for firing) within an aborted subtransaction.
3387 * We use GetCurrentTransactionNestLevel() to determine the correct array
3388 * index in these stacks. maxtransdepth is the number of allocated entries in
3389 * each stack. (By not keeping our own stack pointer, we can avoid trouble
3390 * in cases where errors during subxact abort cause multiple invocations
3391 * of AfterTriggerEndSubXact() at the same nesting depth.)
3393 typedef struct AfterTriggersData
3395 CommandId firing_counter; /* next firing ID to assign */
3396 SetConstraintState state; /* the active S C state */
3397 AfterTriggerEventList events; /* deferred-event list */
3398 int query_depth; /* current query list index */
3399 AfterTriggerEventList *query_stack; /* events pending from each query */
3400 Tuplestorestate **fdw_tuplestores; /* foreign tuples for one row from each query */
3401 Tuplestorestate **old_tuplestores; /* all old tuples from each query */
3402 Tuplestorestate **new_tuplestores; /* all new tuples from each query */
3403 int maxquerydepth; /* allocated len of above array */
3404 MemoryContext event_cxt; /* memory context for events, if any */
3406 /* these fields are just for resetting at subtrans abort: */
3408 SetConstraintState *state_stack; /* stacked S C states */
3409 AfterTriggerEventList *events_stack; /* stacked list pointers */
3410 int *depth_stack; /* stacked query_depths */
3411 CommandId *firing_stack; /* stacked firing_counters */
3412 int maxtransdepth; /* allocated len of above arrays */
3413 } AfterTriggersData;
3415 static AfterTriggersData afterTriggers;
3417 static void AfterTriggerExecute(AfterTriggerEvent event,
3418 Relation rel, TriggerDesc *trigdesc,
3420 Instrumentation *instr,
3421 MemoryContext per_tuple_context,
3422 TupleTableSlot *trig_tuple_slot1,
3423 TupleTableSlot *trig_tuple_slot2);
3424 static SetConstraintState SetConstraintStateCreate(int numalloc);
3425 static SetConstraintState SetConstraintStateCopy(SetConstraintState state);
3426 static SetConstraintState SetConstraintStateAddItem(SetConstraintState state,
3427 Oid tgoid, bool tgisdeferred);
3431 * Gets a current query transition tuplestore and initializes it if necessary.
3432 * This can be holding a single transition row tuple (in the case of an FDW)
3433 * or a transition table (for an AFTER trigger).
3435 static Tuplestorestate *
3436 GetTriggerTransitionTuplestore(Tuplestorestate **tss)
3438 Tuplestorestate *ret;
3440 ret = tss[afterTriggers.query_depth];
3443 MemoryContext oldcxt;
3444 ResourceOwner saveResourceOwner;
3447 * Make the tuplestore valid until end of transaction. This is the
3448 * allocation lifespan of the associated events list, but we really
3449 * only need it until AfterTriggerEndQuery().
3451 oldcxt = MemoryContextSwitchTo(TopTransactionContext);
3452 saveResourceOwner = CurrentResourceOwner;
3455 CurrentResourceOwner = TopTransactionResourceOwner;
3456 ret = tuplestore_begin_heap(false, false, work_mem);
3460 CurrentResourceOwner = saveResourceOwner;
3464 CurrentResourceOwner = saveResourceOwner;
3465 MemoryContextSwitchTo(oldcxt);
3467 tss[afterTriggers.query_depth] = ret;
3474 * afterTriggerCheckState()
3476 * Returns true if the trigger event is actually in state DEFERRED.
3480 afterTriggerCheckState(AfterTriggerShared evtshared)
3482 Oid tgoid = evtshared->ats_tgoid;
3483 SetConstraintState state = afterTriggers.state;
3487 * For not-deferrable triggers (i.e. normal AFTER ROW triggers and
3488 * constraints declared NOT DEFERRABLE), the state is always false.
3490 if ((evtshared->ats_event & AFTER_TRIGGER_DEFERRABLE) == 0)
3494 * If constraint state exists, SET CONSTRAINTS might have been executed
3495 * either for this trigger or for all triggers.
3499 /* Check for SET CONSTRAINTS for this specific trigger. */
3500 for (i = 0; i < state->numstates; i++)
3502 if (state->trigstates[i].sct_tgoid == tgoid)
3503 return state->trigstates[i].sct_tgisdeferred;
3506 /* Check for SET CONSTRAINTS ALL. */
3507 if (state->all_isset)
3508 return state->all_isdeferred;
3512 * Otherwise return the default state for the trigger.
3514 return ((evtshared->ats_event & AFTER_TRIGGER_INITDEFERRED) != 0);
3519 * afterTriggerAddEvent()
3521 * Add a new trigger event to the specified queue.
3522 * The passed-in event data is copied.
3526 afterTriggerAddEvent(AfterTriggerEventList *events,
3527 AfterTriggerEvent event, AfterTriggerShared evtshared)
3529 Size eventsize = SizeofTriggerEvent(event);
3530 Size needed = eventsize + sizeof(AfterTriggerSharedData);
3531 AfterTriggerEventChunk *chunk;
3532 AfterTriggerShared newshared;
3533 AfterTriggerEvent newevent;
3536 * If empty list or not enough room in the tail chunk, make a new chunk.
3537 * We assume here that a new shared record will always be needed.
3539 chunk = events->tail;
3540 if (chunk == NULL ||
3541 chunk->endfree - chunk->freeptr < needed)
3545 /* Create event context if we didn't already */
3546 if (afterTriggers.event_cxt == NULL)
3547 afterTriggers.event_cxt =
3548 AllocSetContextCreate(TopTransactionContext,
3549 "AfterTriggerEvents",
3550 ALLOCSET_DEFAULT_SIZES);
3553 * Chunk size starts at 1KB and is allowed to increase up to 1MB.
3554 * These numbers are fairly arbitrary, though there is a hard limit at
3555 * AFTER_TRIGGER_OFFSET; else we couldn't link event records to their
3556 * shared records using the available space in ate_flags. Another
3557 * constraint is that if the chunk size gets too huge, the search loop
3558 * below would get slow given a (not too common) usage pattern with
3559 * many distinct event types in a chunk. Therefore, we double the
3560 * preceding chunk size only if there weren't too many shared records
3561 * in the preceding chunk; otherwise we halve it. This gives us some
3562 * ability to adapt to the actual usage pattern of the current query
3563 * while still having large chunk sizes in typical usage. All chunk
3564 * sizes used should be MAXALIGN multiples, to ensure that the shared
3565 * records will be aligned safely.
3567 #define MIN_CHUNK_SIZE 1024
3568 #define MAX_CHUNK_SIZE (1024*1024)
3570 #if MAX_CHUNK_SIZE > (AFTER_TRIGGER_OFFSET+1)
3571 #error MAX_CHUNK_SIZE must not exceed AFTER_TRIGGER_OFFSET
3575 chunksize = MIN_CHUNK_SIZE;
3578 /* preceding chunk size... */
3579 chunksize = chunk->endptr - (char *) chunk;
3580 /* check number of shared records in preceding chunk */
3581 if ((chunk->endptr - chunk->endfree) <=
3582 (100 * sizeof(AfterTriggerSharedData)))
3583 chunksize *= 2; /* okay, double it */
3585 chunksize /= 2; /* too many shared records */
3586 chunksize = Min(chunksize, MAX_CHUNK_SIZE);
3588 chunk = MemoryContextAlloc(afterTriggers.event_cxt, chunksize);
3590 chunk->freeptr = CHUNK_DATA_START(chunk);
3591 chunk->endptr = chunk->endfree = (char *) chunk + chunksize;
3592 Assert(chunk->endfree - chunk->freeptr >= needed);
3594 if (events->head == NULL)
3595 events->head = chunk;
3597 events->tail->next = chunk;
3598 events->tail = chunk;
3599 /* events->tailfree is now out of sync, but we'll fix it below */
3603 * Try to locate a matching shared-data record already in the chunk. If
3604 * none, make a new one.
3606 for (newshared = ((AfterTriggerShared) chunk->endptr) - 1;
3607 (char *) newshared >= chunk->endfree;
3610 if (newshared->ats_tgoid == evtshared->ats_tgoid &&
3611 newshared->ats_relid == evtshared->ats_relid &&
3612 newshared->ats_event == evtshared->ats_event &&
3613 newshared->ats_firing_id == 0)
3616 if ((char *) newshared < chunk->endfree)
3618 *newshared = *evtshared;
3619 newshared->ats_firing_id = 0; /* just to be sure */
3620 chunk->endfree = (char *) newshared;
3623 /* Insert the data */
3624 newevent = (AfterTriggerEvent) chunk->freeptr;
3625 memcpy(newevent, event, eventsize);
3626 /* ... and link the new event to its shared record */
3627 newevent->ate_flags &= ~AFTER_TRIGGER_OFFSET;
3628 newevent->ate_flags |= (char *) newshared - (char *) newevent;
3630 chunk->freeptr += eventsize;
3631 events->tailfree = chunk->freeptr;
3635 * afterTriggerFreeEventList()
3637 * Free all the event storage in the given list.
3641 afterTriggerFreeEventList(AfterTriggerEventList *events)
3643 AfterTriggerEventChunk *chunk;
3644 AfterTriggerEventChunk *next_chunk;
3646 for (chunk = events->head; chunk != NULL; chunk = next_chunk)
3648 next_chunk = chunk->next;
3651 events->head = NULL;
3652 events->tail = NULL;
3653 events->tailfree = NULL;
3657 * afterTriggerRestoreEventList()
3659 * Restore an event list to its prior length, removing all the events
3660 * added since it had the value old_events.
3664 afterTriggerRestoreEventList(AfterTriggerEventList *events,
3665 const AfterTriggerEventList *old_events)
3667 AfterTriggerEventChunk *chunk;
3668 AfterTriggerEventChunk *next_chunk;
3670 if (old_events->tail == NULL)
3672 /* restoring to a completely empty state, so free everything */
3673 afterTriggerFreeEventList(events);
3677 *events = *old_events;
3678 /* free any chunks after the last one we want to keep */
3679 for (chunk = events->tail->next; chunk != NULL; chunk = next_chunk)
3681 next_chunk = chunk->next;
3684 /* and clean up the tail chunk to be the right length */
3685 events->tail->next = NULL;
3686 events->tail->freeptr = events->tailfree;
3689 * We don't make any effort to remove now-unused shared data records.
3690 * They might still be useful, anyway.
3697 * AfterTriggerExecute()
3699 * Fetch the required tuples back from the heap and fire one
3700 * single trigger function.
3702 * Frequently, this will be fired many times in a row for triggers of
3703 * a single relation. Therefore, we cache the open relation and provide
3704 * fmgr lookup cache space at the caller level. (For triggers fired at
3705 * the end of a query, we can even piggyback on the executor's state.)
3707 * event: event currently being fired.
3708 * rel: open relation for event.
3709 * trigdesc: working copy of rel's trigger info.
3710 * finfo: array of fmgr lookup cache entries (one per trigger in trigdesc).
3711 * instr: array of EXPLAIN ANALYZE instrumentation nodes (one per trigger),
3712 * or NULL if no instrumentation is wanted.
3713 * per_tuple_context: memory context to call trigger function in.
3714 * trig_tuple_slot1: scratch slot for tg_trigtuple (foreign tables only)
3715 * trig_tuple_slot2: scratch slot for tg_newtuple (foreign tables only)
3719 AfterTriggerExecute(AfterTriggerEvent event,
3720 Relation rel, TriggerDesc *trigdesc,
3721 FmgrInfo *finfo, Instrumentation *instr,
3722 MemoryContext per_tuple_context,
3723 TupleTableSlot *trig_tuple_slot1,
3724 TupleTableSlot *trig_tuple_slot2)
3726 AfterTriggerShared evtshared = GetTriggerSharedData(event);
3727 Oid tgoid = evtshared->ats_tgoid;
3728 TriggerData LocTriggerData;
3729 HeapTupleData tuple1;
3730 HeapTupleData tuple2;
3732 Buffer buffer1 = InvalidBuffer;
3733 Buffer buffer2 = InvalidBuffer;
3737 * Locate trigger in trigdesc.
3739 LocTriggerData.tg_trigger = NULL;
3740 for (tgindx = 0; tgindx < trigdesc->numtriggers; tgindx++)
3742 if (trigdesc->triggers[tgindx].tgoid == tgoid)
3744 LocTriggerData.tg_trigger = &(trigdesc->triggers[tgindx]);
3748 if (LocTriggerData.tg_trigger == NULL)
3749 elog(ERROR, "could not find trigger %u", tgoid);
3752 * If doing EXPLAIN ANALYZE, start charging time to this trigger. We want
3753 * to include time spent re-fetching tuples in the trigger cost.
3756 InstrStartNode(instr + tgindx);
3759 * Fetch the required tuple(s).
3761 switch (event->ate_flags & AFTER_TRIGGER_TUP_BITS)
3763 case AFTER_TRIGGER_FDW_FETCH:
3765 Tuplestorestate *fdw_tuplestore =
3766 GetTriggerTransitionTuplestore
3767 (afterTriggers.fdw_tuplestores);
3769 if (!tuplestore_gettupleslot(fdw_tuplestore, true, false,
3771 elog(ERROR, "failed to fetch tuple1 for AFTER trigger");
3773 if ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) ==
3774 TRIGGER_EVENT_UPDATE &&
3775 !tuplestore_gettupleslot(fdw_tuplestore, true, false,
3777 elog(ERROR, "failed to fetch tuple2 for AFTER trigger");
3780 case AFTER_TRIGGER_FDW_REUSE:
3783 * Using ExecMaterializeSlot() rather than ExecFetchSlotTuple()
3784 * ensures that tg_trigtuple does not reference tuplestore memory.
3785 * (It is formally possible for the trigger function to queue
3786 * trigger events that add to the same tuplestore, which can push
3787 * other tuples out of memory.) The distinction is academic,
3788 * because we start with a minimal tuple that ExecFetchSlotTuple()
3789 * must materialize anyway.
3791 LocTriggerData.tg_trigtuple =
3792 ExecMaterializeSlot(trig_tuple_slot1);
3793 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
3795 LocTriggerData.tg_newtuple =
3796 ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) ==
3797 TRIGGER_EVENT_UPDATE) ?
3798 ExecMaterializeSlot(trig_tuple_slot2) : NULL;
3799 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
3804 if (ItemPointerIsValid(&(event->ate_ctid1)))
3806 ItemPointerCopy(&(event->ate_ctid1), &(tuple1.t_self));
3807 if (!heap_fetch(rel, SnapshotAny, &tuple1, &buffer1, false, NULL))
3808 elog(ERROR, "failed to fetch tuple1 for AFTER trigger");
3809 LocTriggerData.tg_trigtuple = &tuple1;
3810 LocTriggerData.tg_trigtuplebuf = buffer1;
3814 LocTriggerData.tg_trigtuple = NULL;
3815 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
3818 /* don't touch ctid2 if not there */
3819 if ((event->ate_flags & AFTER_TRIGGER_TUP_BITS) ==
3820 AFTER_TRIGGER_2CTID &&
3821 ItemPointerIsValid(&(event->ate_ctid2)))
3823 ItemPointerCopy(&(event->ate_ctid2), &(tuple2.t_self));
3824 if (!heap_fetch(rel, SnapshotAny, &tuple2, &buffer2, false, NULL))
3825 elog(ERROR, "failed to fetch tuple2 for AFTER trigger");
3826 LocTriggerData.tg_newtuple = &tuple2;
3827 LocTriggerData.tg_newtuplebuf = buffer2;
3831 LocTriggerData.tg_newtuple = NULL;
3832 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
3837 * Set up the tuplestore information.
3839 if (LocTriggerData.tg_trigger->tgoldtable)
3840 LocTriggerData.tg_oldtable =
3841 GetTriggerTransitionTuplestore(afterTriggers.old_tuplestores);
3843 LocTriggerData.tg_oldtable = NULL;
3844 if (LocTriggerData.tg_trigger->tgnewtable)
3845 LocTriggerData.tg_newtable =
3846 GetTriggerTransitionTuplestore(afterTriggers.new_tuplestores);
3848 LocTriggerData.tg_newtable = NULL;
3851 * Setup the remaining trigger information
3853 LocTriggerData.type = T_TriggerData;
3854 LocTriggerData.tg_event =
3855 evtshared->ats_event & (TRIGGER_EVENT_OPMASK | TRIGGER_EVENT_ROW);
3856 LocTriggerData.tg_relation = rel;
3858 MemoryContextReset(per_tuple_context);
3861 * Call the trigger and throw away any possibly returned updated tuple.
3862 * (Don't let ExecCallTriggerFunc measure EXPLAIN time.)
3864 rettuple = ExecCallTriggerFunc(&LocTriggerData,
3869 if (rettuple != NULL &&
3870 rettuple != LocTriggerData.tg_trigtuple &&
3871 rettuple != LocTriggerData.tg_newtuple)
3872 heap_freetuple(rettuple);
3877 if (buffer1 != InvalidBuffer)
3878 ReleaseBuffer(buffer1);
3879 if (buffer2 != InvalidBuffer)
3880 ReleaseBuffer(buffer2);
3883 * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
3884 * one "tuple returned" (really the number of firings).
3887 InstrStopNode(instr + tgindx, 1);
3892 * afterTriggerMarkEvents()
3894 * Scan the given event list for not yet invoked events. Mark the ones
3895 * that can be invoked now with the current firing ID.
3897 * If move_list isn't NULL, events that are not to be invoked now are
3898 * transferred to move_list.
3900 * When immediate_only is TRUE, do not invoke currently-deferred triggers.
3901 * (This will be FALSE only at main transaction exit.)
3903 * Returns TRUE if any invokable events were found.
3906 afterTriggerMarkEvents(AfterTriggerEventList *events,
3907 AfterTriggerEventList *move_list,
3908 bool immediate_only)
3911 AfterTriggerEvent event;
3912 AfterTriggerEventChunk *chunk;
3914 for_each_event_chunk(event, chunk, *events)
3916 AfterTriggerShared evtshared = GetTriggerSharedData(event);
3917 bool defer_it = false;
3919 if (!(event->ate_flags &
3920 (AFTER_TRIGGER_DONE | AFTER_TRIGGER_IN_PROGRESS)))
3923 * This trigger hasn't been called or scheduled yet. Check if we
3924 * should call it now.
3926 if (immediate_only && afterTriggerCheckState(evtshared))
3933 * Mark it as to be fired in this firing cycle.
3935 evtshared->ats_firing_id = afterTriggers.firing_counter;
3936 event->ate_flags |= AFTER_TRIGGER_IN_PROGRESS;
3942 * If it's deferred, move it to move_list, if requested.
3944 if (defer_it && move_list != NULL)
3946 /* add it to move_list */
3947 afterTriggerAddEvent(move_list, event, evtshared);
3948 /* mark original copy "done" so we don't do it again */
3949 event->ate_flags |= AFTER_TRIGGER_DONE;
3957 * afterTriggerInvokeEvents()
3959 * Scan the given event list for events that are marked as to be fired
3960 * in the current firing cycle, and fire them.
3962 * If estate isn't NULL, we use its result relation info to avoid repeated
3963 * openings and closing of trigger target relations. If it is NULL, we
3964 * make one locally to cache the info in case there are multiple trigger
3967 * When delete_ok is TRUE, it's safe to delete fully-processed events.
3968 * (We are not very tense about that: we simply reset a chunk to be empty
3969 * if all its events got fired. The objective here is just to avoid useless
3970 * rescanning of events when a trigger queues new events during transaction
3971 * end, so it's not necessary to worry much about the case where only
3972 * some events are fired.)
3974 * Returns TRUE if no unfired events remain in the list (this allows us
3975 * to avoid repeating afterTriggerMarkEvents).
3978 afterTriggerInvokeEvents(AfterTriggerEventList *events,
3979 CommandId firing_id,
3983 bool all_fired = true;
3984 AfterTriggerEventChunk *chunk;
3985 MemoryContext per_tuple_context;
3986 bool local_estate = false;
3987 Relation rel = NULL;
3988 TriggerDesc *trigdesc = NULL;
3989 FmgrInfo *finfo = NULL;
3990 Instrumentation *instr = NULL;
3991 TupleTableSlot *slot1 = NULL,
3994 /* Make a local EState if need be */
3997 estate = CreateExecutorState();
3998 local_estate = true;
4001 /* Make a per-tuple memory context for trigger function calls */
4003 AllocSetContextCreate(CurrentMemoryContext,
4004 "AfterTriggerTupleContext",
4005 ALLOCSET_DEFAULT_SIZES);
4007 for_each_chunk(chunk, *events)
4009 AfterTriggerEvent event;
4010 bool all_fired_in_chunk = true;
4012 for_each_event(event, chunk)
4014 AfterTriggerShared evtshared = GetTriggerSharedData(event);
4017 * Is it one for me to fire?
4019 if ((event->ate_flags & AFTER_TRIGGER_IN_PROGRESS) &&
4020 evtshared->ats_firing_id == firing_id)
4023 * So let's fire it... but first, find the correct relation if
4024 * this is not the same relation as before.
4026 if (rel == NULL || RelationGetRelid(rel) != evtshared->ats_relid)
4028 ResultRelInfo *rInfo;
4030 rInfo = ExecGetTriggerResultRel(estate, evtshared->ats_relid);
4031 rel = rInfo->ri_RelationDesc;
4032 trigdesc = rInfo->ri_TrigDesc;
4033 finfo = rInfo->ri_TrigFunctions;
4034 instr = rInfo->ri_TrigInstrument;
4035 if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
4039 ExecDropSingleTupleTableSlot(slot1);
4040 ExecDropSingleTupleTableSlot(slot2);
4042 slot1 = MakeSingleTupleTableSlot(rel->rd_att);
4043 slot2 = MakeSingleTupleTableSlot(rel->rd_att);
4045 if (trigdesc == NULL) /* should not happen */
4046 elog(ERROR, "relation %u has no triggers",
4047 evtshared->ats_relid);
4051 * Fire it. Note that the AFTER_TRIGGER_IN_PROGRESS flag is
4052 * still set, so recursive examinations of the event list
4053 * won't try to re-fire it.
4055 AfterTriggerExecute(event, rel, trigdesc, finfo, instr,
4056 per_tuple_context, slot1, slot2);
4059 * Mark the event as done.
4061 event->ate_flags &= ~AFTER_TRIGGER_IN_PROGRESS;
4062 event->ate_flags |= AFTER_TRIGGER_DONE;
4064 else if (!(event->ate_flags & AFTER_TRIGGER_DONE))
4066 /* something remains to be done */
4067 all_fired = all_fired_in_chunk = false;
4071 /* Clear the chunk if delete_ok and nothing left of interest */
4072 if (delete_ok && all_fired_in_chunk)
4074 chunk->freeptr = CHUNK_DATA_START(chunk);
4075 chunk->endfree = chunk->endptr;
4078 * If it's last chunk, must sync event list's tailfree too. Note
4079 * that delete_ok must NOT be passed as true if there could be
4080 * stacked AfterTriggerEventList values pointing at this event
4081 * list, since we'd fail to fix their copies of tailfree.
4083 if (chunk == events->tail)
4084 events->tailfree = chunk->freeptr;
4089 ExecDropSingleTupleTableSlot(slot1);
4090 ExecDropSingleTupleTableSlot(slot2);
4093 /* Release working resources */
4094 MemoryContextDelete(per_tuple_context);
4100 foreach(l, estate->es_trig_target_relations)
4102 ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
4104 /* Close indices and then the relation itself */
4105 ExecCloseIndices(resultRelInfo);
4106 heap_close(resultRelInfo->ri_RelationDesc, NoLock);
4108 FreeExecutorState(estate);
4116 * AfterTriggerBeginXact()
4118 * Called at transaction start (either BEGIN or implicit for single
4119 * statement outside of transaction block).
4123 AfterTriggerBeginXact(void)
4126 * Initialize after-trigger state structure to empty
4128 afterTriggers.firing_counter = (CommandId) 1; /* mustn't be 0 */
4129 afterTriggers.query_depth = -1;
4132 * Verify that there is no leftover state remaining. If these assertions
4133 * trip, it means that AfterTriggerEndXact wasn't called or didn't clean
4136 Assert(afterTriggers.state == NULL);
4137 Assert(afterTriggers.query_stack == NULL);
4138 Assert(afterTriggers.fdw_tuplestores == NULL);
4139 Assert(afterTriggers.old_tuplestores == NULL);
4140 Assert(afterTriggers.new_tuplestores == NULL);
4141 Assert(afterTriggers.maxquerydepth == 0);
4142 Assert(afterTriggers.event_cxt == NULL);
4143 Assert(afterTriggers.events.head == NULL);
4144 Assert(afterTriggers.state_stack == NULL);
4145 Assert(afterTriggers.events_stack == NULL);
4146 Assert(afterTriggers.depth_stack == NULL);
4147 Assert(afterTriggers.firing_stack == NULL);
4148 Assert(afterTriggers.maxtransdepth == 0);
4153 * AfterTriggerBeginQuery()
4155 * Called just before we start processing a single query within a
4156 * transaction (or subtransaction). Most of the real work gets deferred
4157 * until somebody actually tries to queue a trigger event.
4161 AfterTriggerBeginQuery(void)
4163 /* Increase the query stack depth */
4164 afterTriggers.query_depth++;
4169 * AfterTriggerEndQuery()
4171 * Called after one query has been completely processed. At this time
4172 * we invoke all AFTER IMMEDIATE trigger events queued by the query, and
4173 * transfer deferred trigger events to the global deferred-trigger list.
4175 * Note that this must be called BEFORE closing down the executor
4176 * with ExecutorEnd, because we make use of the EState's info about
4177 * target relations. Normally it is called from ExecutorFinish.
4181 AfterTriggerEndQuery(EState *estate)
4183 AfterTriggerEventList *events;
4184 Tuplestorestate *fdw_tuplestore;
4185 Tuplestorestate *old_tuplestore;
4186 Tuplestorestate *new_tuplestore;
4188 /* Must be inside a query, too */
4189 Assert(afterTriggers.query_depth >= 0);
4192 * If we never even got as far as initializing the event stack, there
4193 * certainly won't be any events, so exit quickly.
4195 if (afterTriggers.query_depth >= afterTriggers.maxquerydepth)
4197 afterTriggers.query_depth--;
4202 * Process all immediate-mode triggers queued by the query, and move the
4203 * deferred ones to the main list of deferred events.
4205 * Notice that we decide which ones will be fired, and put the deferred
4206 * ones on the main list, before anything is actually fired. This ensures
4207 * reasonably sane behavior if a trigger function does SET CONSTRAINTS ...
4208 * IMMEDIATE: all events we have decided to defer will be available for it
4211 * We loop in case a trigger queues more events at the same query level.
4212 * Ordinary trigger functions, including all PL/pgSQL trigger functions,
4213 * will instead fire any triggers in a dedicated query level. Foreign key
4214 * enforcement triggers do add to the current query level, thanks to their
4215 * passing fire_triggers = false to SPI_execute_snapshot(). Other
4216 * C-language triggers might do likewise. Be careful here: firing a
4217 * trigger could result in query_stack being repalloc'd, so we can't save
4218 * its address across afterTriggerInvokeEvents calls.
4220 * If we find no firable events, we don't have to increment
4225 events = &afterTriggers.query_stack[afterTriggers.query_depth];
4226 if (afterTriggerMarkEvents(events, &afterTriggers.events, true))
4228 CommandId firing_id = afterTriggers.firing_counter++;
4230 /* OK to delete the immediate events after processing them */
4231 if (afterTriggerInvokeEvents(events, firing_id, estate, true))
4232 break; /* all fired */
4238 /* Release query-local storage for events, including tuplestore if any */
4239 fdw_tuplestore = afterTriggers.fdw_tuplestores[afterTriggers.query_depth];
4242 tuplestore_end(fdw_tuplestore);
4243 afterTriggers.fdw_tuplestores[afterTriggers.query_depth] = NULL;
4245 old_tuplestore = afterTriggers.old_tuplestores[afterTriggers.query_depth];
4248 tuplestore_end(old_tuplestore);
4249 afterTriggers.old_tuplestores[afterTriggers.query_depth] = NULL;
4251 new_tuplestore = afterTriggers.new_tuplestores[afterTriggers.query_depth];
4254 tuplestore_end(new_tuplestore);
4255 afterTriggers.new_tuplestores[afterTriggers.query_depth] = NULL;
4257 afterTriggerFreeEventList(&afterTriggers.query_stack[afterTriggers.query_depth]);
4259 afterTriggers.query_depth--;
4264 * AfterTriggerFireDeferred()
4266 * Called just before the current transaction is committed. At this
4267 * time we invoke all pending DEFERRED triggers.
4269 * It is possible for other modules to queue additional deferred triggers
4270 * during pre-commit processing; therefore xact.c may have to call this
4275 AfterTriggerFireDeferred(void)
4277 AfterTriggerEventList *events;
4278 bool snap_pushed = false;
4280 /* Must not be inside a query */
4281 Assert(afterTriggers.query_depth == -1);
4284 * If there are any triggers to fire, make sure we have set a snapshot for
4285 * them to use. (Since PortalRunUtility doesn't set a snap for COMMIT, we
4286 * can't assume ActiveSnapshot is valid on entry.)
4288 events = &afterTriggers.events;
4289 if (events->head != NULL)
4291 PushActiveSnapshot(GetTransactionSnapshot());
4296 * Run all the remaining triggers. Loop until they are all gone, in case
4297 * some trigger queues more for us to do.
4299 while (afterTriggerMarkEvents(events, NULL, false))
4301 CommandId firing_id = afterTriggers.firing_counter++;
4303 if (afterTriggerInvokeEvents(events, firing_id, NULL, true))
4304 break; /* all fired */
4308 * We don't bother freeing the event list, since it will go away anyway
4309 * (and more efficiently than via pfree) in AfterTriggerEndXact.
4313 PopActiveSnapshot();
4318 * AfterTriggerEndXact()
4320 * The current transaction is finishing.
4322 * Any unfired triggers are canceled so we simply throw
4323 * away anything we know.
4325 * Note: it is possible for this to be called repeatedly in case of
4326 * error during transaction abort; therefore, do not complain if
4327 * already closed down.
4331 AfterTriggerEndXact(bool isCommit)
4334 * Forget the pending-events list.
4336 * Since all the info is in TopTransactionContext or children thereof, we
4337 * don't really need to do anything to reclaim memory. However, the
4338 * pending-events list could be large, and so it's useful to discard it as
4339 * soon as possible --- especially if we are aborting because we ran out
4340 * of memory for the list!
4342 if (afterTriggers.event_cxt)
4344 MemoryContextDelete(afterTriggers.event_cxt);
4345 afterTriggers.event_cxt = NULL;
4346 afterTriggers.events.head = NULL;
4347 afterTriggers.events.tail = NULL;
4348 afterTriggers.events.tailfree = NULL;
4352 * Forget any subtransaction state as well. Since this can't be very
4353 * large, we let the eventual reset of TopTransactionContext free the
4354 * memory instead of doing it here.
4356 afterTriggers.state_stack = NULL;
4357 afterTriggers.events_stack = NULL;
4358 afterTriggers.depth_stack = NULL;
4359 afterTriggers.firing_stack = NULL;
4360 afterTriggers.maxtransdepth = 0;
4364 * Forget the query stack and constraint-related state information. As
4365 * with the subtransaction state information, we don't bother freeing the
4368 afterTriggers.query_stack = NULL;
4369 afterTriggers.fdw_tuplestores = NULL;
4370 afterTriggers.old_tuplestores = NULL;
4371 afterTriggers.new_tuplestores = NULL;
4372 afterTriggers.maxquerydepth = 0;
4373 afterTriggers.state = NULL;
4375 /* No more afterTriggers manipulation until next transaction starts. */
4376 afterTriggers.query_depth = -1;
4380 * AfterTriggerBeginSubXact()
4382 * Start a subtransaction.
4385 AfterTriggerBeginSubXact(void)
4387 int my_level = GetCurrentTransactionNestLevel();
4390 * Allocate more space in the stacks if needed. (Note: because the
4391 * minimum nest level of a subtransaction is 2, we waste the first couple
4392 * entries of each array; not worth the notational effort to avoid it.)
4394 while (my_level >= afterTriggers.maxtransdepth)
4396 if (afterTriggers.maxtransdepth == 0)
4398 MemoryContext old_cxt;
4400 old_cxt = MemoryContextSwitchTo(TopTransactionContext);
4402 #define DEFTRIG_INITALLOC 8
4403 afterTriggers.state_stack = (SetConstraintState *)
4404 palloc(DEFTRIG_INITALLOC * sizeof(SetConstraintState));
4405 afterTriggers.events_stack = (AfterTriggerEventList *)
4406 palloc(DEFTRIG_INITALLOC * sizeof(AfterTriggerEventList));
4407 afterTriggers.depth_stack = (int *)
4408 palloc(DEFTRIG_INITALLOC * sizeof(int));
4409 afterTriggers.firing_stack = (CommandId *)
4410 palloc(DEFTRIG_INITALLOC * sizeof(CommandId));
4411 afterTriggers.maxtransdepth = DEFTRIG_INITALLOC;
4413 MemoryContextSwitchTo(old_cxt);
4417 /* repalloc will keep the stacks in the same context */
4418 int new_alloc = afterTriggers.maxtransdepth * 2;
4420 afterTriggers.state_stack = (SetConstraintState *)
4421 repalloc(afterTriggers.state_stack,
4422 new_alloc * sizeof(SetConstraintState));
4423 afterTriggers.events_stack = (AfterTriggerEventList *)
4424 repalloc(afterTriggers.events_stack,
4425 new_alloc * sizeof(AfterTriggerEventList));
4426 afterTriggers.depth_stack = (int *)
4427 repalloc(afterTriggers.depth_stack,
4428 new_alloc * sizeof(int));
4429 afterTriggers.firing_stack = (CommandId *)
4430 repalloc(afterTriggers.firing_stack,
4431 new_alloc * sizeof(CommandId));
4432 afterTriggers.maxtransdepth = new_alloc;
4437 * Push the current information into the stack. The SET CONSTRAINTS state
4438 * is not saved until/unless changed. Likewise, we don't make a
4439 * per-subtransaction event context until needed.
4441 afterTriggers.state_stack[my_level] = NULL;
4442 afterTriggers.events_stack[my_level] = afterTriggers.events;
4443 afterTriggers.depth_stack[my_level] = afterTriggers.query_depth;
4444 afterTriggers.firing_stack[my_level] = afterTriggers.firing_counter;
4448 * AfterTriggerEndSubXact()
4450 * The current subtransaction is ending.
4453 AfterTriggerEndSubXact(bool isCommit)
4455 int my_level = GetCurrentTransactionNestLevel();
4456 SetConstraintState state;
4457 AfterTriggerEvent event;
4458 AfterTriggerEventChunk *chunk;
4459 CommandId subxact_firing_id;
4462 * Pop the prior state if needed.
4466 Assert(my_level < afterTriggers.maxtransdepth);
4467 /* If we saved a prior state, we don't need it anymore */
4468 state = afterTriggers.state_stack[my_level];
4471 /* this avoids double pfree if error later: */
4472 afterTriggers.state_stack[my_level] = NULL;
4473 Assert(afterTriggers.query_depth ==
4474 afterTriggers.depth_stack[my_level]);
4479 * Aborting. It is possible subxact start failed before calling
4480 * AfterTriggerBeginSubXact, in which case we mustn't risk touching
4481 * stack levels that aren't there.
4483 if (my_level >= afterTriggers.maxtransdepth)
4487 * Release any event lists from queries being aborted, and restore
4488 * query_depth to its pre-subxact value. This assumes that a
4489 * subtransaction will not add events to query levels started in a
4490 * earlier transaction state.
4492 while (afterTriggers.query_depth > afterTriggers.depth_stack[my_level])
4494 if (afterTriggers.query_depth < afterTriggers.maxquerydepth)
4496 Tuplestorestate *ts;
4498 ts = afterTriggers.fdw_tuplestores[afterTriggers.query_depth];
4502 afterTriggers.fdw_tuplestores[afterTriggers.query_depth] = NULL;
4504 ts = afterTriggers.old_tuplestores[afterTriggers.query_depth];
4508 afterTriggers.old_tuplestores[afterTriggers.query_depth] = NULL;
4510 ts = afterTriggers.new_tuplestores[afterTriggers.query_depth];
4514 afterTriggers.new_tuplestores[afterTriggers.query_depth] = NULL;
4517 afterTriggerFreeEventList(&afterTriggers.query_stack[afterTriggers.query_depth]);
4520 afterTriggers.query_depth--;
4522 Assert(afterTriggers.query_depth ==
4523 afterTriggers.depth_stack[my_level]);
4526 * Restore the global deferred-event list to its former length,
4527 * discarding any events queued by the subxact.
4529 afterTriggerRestoreEventList(&afterTriggers.events,
4530 &afterTriggers.events_stack[my_level]);
4533 * Restore the trigger state. If the saved state is NULL, then this
4534 * subxact didn't save it, so it doesn't need restoring.
4536 state = afterTriggers.state_stack[my_level];
4539 pfree(afterTriggers.state);
4540 afterTriggers.state = state;
4542 /* this avoids double pfree if error later: */
4543 afterTriggers.state_stack[my_level] = NULL;
4546 * Scan for any remaining deferred events that were marked DONE or IN
4547 * PROGRESS by this subxact or a child, and un-mark them. We can
4548 * recognize such events because they have a firing ID greater than or
4549 * equal to the firing_counter value we saved at subtransaction start.
4550 * (This essentially assumes that the current subxact includes all
4551 * subxacts started after it.)
4553 subxact_firing_id = afterTriggers.firing_stack[my_level];
4554 for_each_event_chunk(event, chunk, afterTriggers.events)
4556 AfterTriggerShared evtshared = GetTriggerSharedData(event);
4558 if (event->ate_flags &
4559 (AFTER_TRIGGER_DONE | AFTER_TRIGGER_IN_PROGRESS))
4561 if (evtshared->ats_firing_id >= subxact_firing_id)
4563 ~(AFTER_TRIGGER_DONE | AFTER_TRIGGER_IN_PROGRESS);
4570 * AfterTriggerEnlargeQueryState()
4572 * Prepare the necessary state so that we can record AFTER trigger events
4573 * queued by a query. It is allowed to have nested queries within a
4574 * (sub)transaction, so we need to have separate state for each query
4579 AfterTriggerEnlargeQueryState(void)
4581 int init_depth = afterTriggers.maxquerydepth;
4583 Assert(afterTriggers.query_depth >= afterTriggers.maxquerydepth);
4585 if (afterTriggers.maxquerydepth == 0)
4587 int new_alloc = Max(afterTriggers.query_depth + 1, 8);
4589 afterTriggers.query_stack = (AfterTriggerEventList *)
4590 MemoryContextAlloc(TopTransactionContext,
4591 new_alloc * sizeof(AfterTriggerEventList));
4592 afterTriggers.fdw_tuplestores = (Tuplestorestate **)
4593 MemoryContextAllocZero(TopTransactionContext,
4594 new_alloc * sizeof(Tuplestorestate *));
4595 afterTriggers.old_tuplestores = (Tuplestorestate **)
4596 MemoryContextAllocZero(TopTransactionContext,
4597 new_alloc * sizeof(Tuplestorestate *));
4598 afterTriggers.new_tuplestores = (Tuplestorestate **)
4599 MemoryContextAllocZero(TopTransactionContext,
4600 new_alloc * sizeof(Tuplestorestate *));
4601 afterTriggers.maxquerydepth = new_alloc;
4605 /* repalloc will keep the stack in the same context */
4606 int old_alloc = afterTriggers.maxquerydepth;
4607 int new_alloc = Max(afterTriggers.query_depth + 1,
4610 afterTriggers.query_stack = (AfterTriggerEventList *)
4611 repalloc(afterTriggers.query_stack,
4612 new_alloc * sizeof(AfterTriggerEventList));
4613 afterTriggers.fdw_tuplestores = (Tuplestorestate **)
4614 repalloc(afterTriggers.fdw_tuplestores,
4615 new_alloc * sizeof(Tuplestorestate *));
4616 afterTriggers.old_tuplestores = (Tuplestorestate **)
4617 repalloc(afterTriggers.old_tuplestores,
4618 new_alloc * sizeof(Tuplestorestate *));
4619 afterTriggers.new_tuplestores = (Tuplestorestate **)
4620 repalloc(afterTriggers.new_tuplestores,
4621 new_alloc * sizeof(Tuplestorestate *));
4622 /* Clear newly-allocated slots for subsequent lazy initialization. */
4623 memset(afterTriggers.fdw_tuplestores + old_alloc,
4624 0, (new_alloc - old_alloc) * sizeof(Tuplestorestate *));
4625 memset(afterTriggers.old_tuplestores + old_alloc,
4626 0, (new_alloc - old_alloc) * sizeof(Tuplestorestate *));
4627 memset(afterTriggers.new_tuplestores + old_alloc,
4628 0, (new_alloc - old_alloc) * sizeof(Tuplestorestate *));
4629 afterTriggers.maxquerydepth = new_alloc;
4632 /* Initialize new query lists to empty */
4633 while (init_depth < afterTriggers.maxquerydepth)
4635 AfterTriggerEventList *events;
4637 events = &afterTriggers.query_stack[init_depth];
4638 events->head = NULL;
4639 events->tail = NULL;
4640 events->tailfree = NULL;
4647 * Create an empty SetConstraintState with room for numalloc trigstates
4649 static SetConstraintState
4650 SetConstraintStateCreate(int numalloc)
4652 SetConstraintState state;
4654 /* Behave sanely with numalloc == 0 */
4659 * We assume that zeroing will correctly initialize the state values.
4661 state = (SetConstraintState)
4662 MemoryContextAllocZero(TopTransactionContext,
4663 offsetof(SetConstraintStateData, trigstates) +
4664 numalloc * sizeof(SetConstraintTriggerData));
4666 state->numalloc = numalloc;
4672 * Copy a SetConstraintState
4674 static SetConstraintState
4675 SetConstraintStateCopy(SetConstraintState origstate)
4677 SetConstraintState state;
4679 state = SetConstraintStateCreate(origstate->numstates);
4681 state->all_isset = origstate->all_isset;
4682 state->all_isdeferred = origstate->all_isdeferred;
4683 state->numstates = origstate->numstates;
4684 memcpy(state->trigstates, origstate->trigstates,
4685 origstate->numstates * sizeof(SetConstraintTriggerData));
4691 * Add a per-trigger item to a SetConstraintState. Returns possibly-changed
4692 * pointer to the state object (it will change if we have to repalloc).
4694 static SetConstraintState
4695 SetConstraintStateAddItem(SetConstraintState state,
4696 Oid tgoid, bool tgisdeferred)
4698 if (state->numstates >= state->numalloc)
4700 int newalloc = state->numalloc * 2;
4702 newalloc = Max(newalloc, 8); /* in case original has size 0 */
4703 state = (SetConstraintState)
4705 offsetof(SetConstraintStateData, trigstates) +
4706 newalloc * sizeof(SetConstraintTriggerData));
4707 state->numalloc = newalloc;
4708 Assert(state->numstates < state->numalloc);
4711 state->trigstates[state->numstates].sct_tgoid = tgoid;
4712 state->trigstates[state->numstates].sct_tgisdeferred = tgisdeferred;
4719 * AfterTriggerSetState()
4721 * Execute the SET CONSTRAINTS ... utility command.
4725 AfterTriggerSetState(ConstraintsSetStmt *stmt)
4727 int my_level = GetCurrentTransactionNestLevel();
4729 /* If we haven't already done so, initialize our state. */
4730 if (afterTriggers.state == NULL)
4731 afterTriggers.state = SetConstraintStateCreate(8);
4734 * If in a subtransaction, and we didn't save the current state already,
4735 * save it so it can be restored if the subtransaction aborts.
4738 afterTriggers.state_stack[my_level] == NULL)
4740 afterTriggers.state_stack[my_level] =
4741 SetConstraintStateCopy(afterTriggers.state);
4745 * Handle SET CONSTRAINTS ALL ...
4747 if (stmt->constraints == NIL)
4750 * Forget any previous SET CONSTRAINTS commands in this transaction.
4752 afterTriggers.state->numstates = 0;
4755 * Set the per-transaction ALL state to known.
4757 afterTriggers.state->all_isset = true;
4758 afterTriggers.state->all_isdeferred = stmt->deferred;
4764 List *conoidlist = NIL;
4765 List *tgoidlist = NIL;
4769 * Handle SET CONSTRAINTS constraint-name [, ...]
4771 * First, identify all the named constraints and make a list of their
4772 * OIDs. Since, unlike the SQL spec, we allow multiple constraints of
4773 * the same name within a schema, the specifications are not
4774 * necessarily unique. Our strategy is to target all matching
4775 * constraints within the first search-path schema that has any
4776 * matches, but disregard matches in schemas beyond the first match.
4777 * (This is a bit odd but it's the historical behavior.)
4779 conrel = heap_open(ConstraintRelationId, AccessShareLock);
4781 foreach(lc, stmt->constraints)
4783 RangeVar *constraint = lfirst(lc);
4785 List *namespacelist;
4788 if (constraint->catalogname)
4790 if (strcmp(constraint->catalogname, get_database_name(MyDatabaseId)) != 0)
4792 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4793 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
4794 constraint->catalogname, constraint->schemaname,
4795 constraint->relname)));
4799 * If we're given the schema name with the constraint, look only
4800 * in that schema. If given a bare constraint name, use the
4801 * search path to find the first matching constraint.
4803 if (constraint->schemaname)
4805 Oid namespaceId = LookupExplicitNamespace(constraint->schemaname,
4808 namespacelist = list_make1_oid(namespaceId);
4812 namespacelist = fetch_search_path(true);
4816 foreach(nslc, namespacelist)
4818 Oid namespaceId = lfirst_oid(nslc);
4819 SysScanDesc conscan;
4820 ScanKeyData skey[2];
4823 ScanKeyInit(&skey[0],
4824 Anum_pg_constraint_conname,
4825 BTEqualStrategyNumber, F_NAMEEQ,
4826 CStringGetDatum(constraint->relname));
4827 ScanKeyInit(&skey[1],
4828 Anum_pg_constraint_connamespace,
4829 BTEqualStrategyNumber, F_OIDEQ,
4830 ObjectIdGetDatum(namespaceId));
4832 conscan = systable_beginscan(conrel, ConstraintNameNspIndexId,
4833 true, NULL, 2, skey);
4835 while (HeapTupleIsValid(tup = systable_getnext(conscan)))
4837 Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tup);
4839 if (con->condeferrable)
4840 conoidlist = lappend_oid(conoidlist,
4841 HeapTupleGetOid(tup));
4842 else if (stmt->deferred)
4844 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
4845 errmsg("constraint \"%s\" is not deferrable",
4846 constraint->relname)));
4850 systable_endscan(conscan);
4853 * Once we've found a matching constraint we do not search
4854 * later parts of the search path.
4860 list_free(namespacelist);
4867 (errcode(ERRCODE_UNDEFINED_OBJECT),
4868 errmsg("constraint \"%s\" does not exist",
4869 constraint->relname)));
4872 heap_close(conrel, AccessShareLock);
4875 * Now, locate the trigger(s) implementing each of these constraints,
4876 * and make a list of their OIDs.
4878 tgrel = heap_open(TriggerRelationId, AccessShareLock);
4880 foreach(lc, conoidlist)
4882 Oid conoid = lfirst_oid(lc);
4891 Anum_pg_trigger_tgconstraint,
4892 BTEqualStrategyNumber, F_OIDEQ,
4893 ObjectIdGetDatum(conoid));
4895 tgscan = systable_beginscan(tgrel, TriggerConstraintIndexId, true,
4898 while (HeapTupleIsValid(htup = systable_getnext(tgscan)))
4900 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
4903 * Silently skip triggers that are marked as non-deferrable in
4904 * pg_trigger. This is not an error condition, since a
4905 * deferrable RI constraint may have some non-deferrable
4908 if (pg_trigger->tgdeferrable)
4909 tgoidlist = lappend_oid(tgoidlist,
4910 HeapTupleGetOid(htup));
4915 systable_endscan(tgscan);
4917 /* Safety check: a deferrable constraint should have triggers */
4919 elog(ERROR, "no triggers found for constraint with OID %u",
4923 heap_close(tgrel, AccessShareLock);
4926 * Now we can set the trigger states of individual triggers for this
4929 foreach(lc, tgoidlist)
4931 Oid tgoid = lfirst_oid(lc);
4932 SetConstraintState state = afterTriggers.state;
4936 for (i = 0; i < state->numstates; i++)
4938 if (state->trigstates[i].sct_tgoid == tgoid)
4940 state->trigstates[i].sct_tgisdeferred = stmt->deferred;
4947 afterTriggers.state =
4948 SetConstraintStateAddItem(state, tgoid, stmt->deferred);
4954 * SQL99 requires that when a constraint is set to IMMEDIATE, any deferred
4955 * checks against that constraint must be made when the SET CONSTRAINTS
4956 * command is executed -- i.e. the effects of the SET CONSTRAINTS command
4957 * apply retroactively. We've updated the constraints state, so scan the
4958 * list of previously deferred events to fire any that have now become
4961 * Obviously, if this was SET ... DEFERRED then it can't have converted
4962 * any unfired events to immediate, so we need do nothing in that case.
4964 if (!stmt->deferred)
4966 AfterTriggerEventList *events = &afterTriggers.events;
4967 bool snapshot_set = false;
4969 while (afterTriggerMarkEvents(events, NULL, true))
4971 CommandId firing_id = afterTriggers.firing_counter++;
4974 * Make sure a snapshot has been established in case trigger
4975 * functions need one. Note that we avoid setting a snapshot if
4976 * we don't find at least one trigger that has to be fired now.
4977 * This is so that BEGIN; SET CONSTRAINTS ...; SET TRANSACTION
4978 * ISOLATION LEVEL SERIALIZABLE; ... works properly. (If we are
4979 * at the start of a transaction it's not possible for any trigger
4980 * events to be queued yet.)
4984 PushActiveSnapshot(GetTransactionSnapshot());
4985 snapshot_set = true;
4989 * We can delete fired events if we are at top transaction level,
4990 * but we'd better not if inside a subtransaction, since the
4991 * subtransaction could later get rolled back.
4993 if (afterTriggerInvokeEvents(events, firing_id, NULL,
4994 !IsSubTransaction()))
4995 break; /* all fired */
4999 PopActiveSnapshot();
5004 * AfterTriggerPendingOnRel()
5005 * Test to see if there are any pending after-trigger events for rel.
5007 * This is used by TRUNCATE, CLUSTER, ALTER TABLE, etc to detect whether
5008 * it is unsafe to perform major surgery on a relation. Note that only
5009 * local pending events are examined. We assume that having exclusive lock
5010 * on a rel guarantees there are no unserviced events in other backends ---
5011 * but having a lock does not prevent there being such events in our own.
5013 * In some scenarios it'd be reasonable to remove pending events (more
5014 * specifically, mark them DONE by the current subxact) but without a lot
5015 * of knowledge of the trigger semantics we can't do this in general.
5019 AfterTriggerPendingOnRel(Oid relid)
5021 AfterTriggerEvent event;
5022 AfterTriggerEventChunk *chunk;
5025 /* Scan queued events */
5026 for_each_event_chunk(event, chunk, afterTriggers.events)
5028 AfterTriggerShared evtshared = GetTriggerSharedData(event);
5031 * We can ignore completed events. (Even if a DONE flag is rolled
5032 * back by subxact abort, it's OK because the effects of the TRUNCATE
5033 * or whatever must get rolled back too.)
5035 if (event->ate_flags & AFTER_TRIGGER_DONE)
5038 if (evtshared->ats_relid == relid)
5043 * Also scan events queued by incomplete queries. This could only matter
5044 * if TRUNCATE/etc is executed by a function or trigger within an updating
5045 * query on the same relation, which is pretty perverse, but let's check.
5047 for (depth = 0; depth <= afterTriggers.query_depth && depth < afterTriggers.maxquerydepth; depth++)
5049 for_each_event_chunk(event, chunk, afterTriggers.query_stack[depth])
5051 AfterTriggerShared evtshared = GetTriggerSharedData(event);
5053 if (event->ate_flags & AFTER_TRIGGER_DONE)
5056 if (evtshared->ats_relid == relid)
5066 * AfterTriggerSaveEvent()
5068 * Called by ExecA[RS]...Triggers() to queue up the triggers that should
5069 * be fired for an event.
5071 * NOTE: this is called whenever there are any triggers associated with
5072 * the event (even if they are disabled). This function decides which
5073 * triggers actually need to be queued. It is also called after each row,
5074 * even if there are no triggers for that event, if there are any AFTER
5075 * STATEMENT triggers for the statement which use transition tables, so that
5076 * the transition tuplestores can be built.
5078 * Transition tuplestores are built now, rather than when events are pulled
5079 * off of the queue because AFTER ROW triggers are allowed to select from the
5080 * transition tables for the statement.
5084 AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
5085 int event, bool row_trigger,
5086 HeapTuple oldtup, HeapTuple newtup,
5087 List *recheckIndexes, Bitmapset *modifiedCols)
5089 Relation rel = relinfo->ri_RelationDesc;
5090 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
5091 AfterTriggerEventData new_event;
5092 AfterTriggerSharedData new_shared;
5093 char relkind = relinfo->ri_RelationDesc->rd_rel->relkind;
5097 Tuplestorestate *fdw_tuplestore = NULL;
5100 * Check state. We use a normal test not Assert because it is possible to
5101 * reach here in the wrong state given misconfigured RI triggers, in
5102 * particular deferring a cascade action trigger.
5104 if (afterTriggers.query_depth < 0)
5105 elog(ERROR, "AfterTriggerSaveEvent() called outside of query");
5107 /* Be sure we have enough space to record events at this query depth. */
5108 if (afterTriggers.query_depth >= afterTriggers.maxquerydepth)
5109 AfterTriggerEnlargeQueryState();
5112 * If the relation has AFTER ... FOR EACH ROW triggers, capture rows into
5113 * transition tuplestores for this depth.
5117 if ((event == TRIGGER_EVENT_DELETE &&
5118 trigdesc->trig_delete_old_table) ||
5119 (event == TRIGGER_EVENT_UPDATE &&
5120 trigdesc->trig_update_old_table))
5122 Tuplestorestate *old_tuplestore;
5124 Assert(oldtup != NULL);
5126 GetTriggerTransitionTuplestore
5127 (afterTriggers.old_tuplestores);
5128 tuplestore_puttuple(old_tuplestore, oldtup);
5130 if ((event == TRIGGER_EVENT_INSERT &&
5131 trigdesc->trig_insert_new_table) ||
5132 (event == TRIGGER_EVENT_UPDATE &&
5133 trigdesc->trig_update_new_table))
5135 Tuplestorestate *new_tuplestore;
5137 Assert(newtup != NULL);
5139 GetTriggerTransitionTuplestore
5140 (afterTriggers.new_tuplestores);
5141 tuplestore_puttuple(new_tuplestore, newtup);
5144 /* If transition tables are the only reason we're here, return. */
5145 if ((event == TRIGGER_EVENT_DELETE && !trigdesc->trig_delete_after_row) ||
5146 (event == TRIGGER_EVENT_INSERT && !trigdesc->trig_insert_after_row) ||
5147 (event == TRIGGER_EVENT_UPDATE && !trigdesc->trig_update_after_row))
5152 * Validate the event code and collect the associated tuple CTIDs.
5154 * The event code will be used both as a bitmask and an array offset, so
5155 * validation is important to make sure we don't walk off the edge of our
5160 case TRIGGER_EVENT_INSERT:
5161 tgtype_event = TRIGGER_TYPE_INSERT;
5164 Assert(oldtup == NULL);
5165 Assert(newtup != NULL);
5166 ItemPointerCopy(&(newtup->t_self), &(new_event.ate_ctid1));
5167 ItemPointerSetInvalid(&(new_event.ate_ctid2));
5171 Assert(oldtup == NULL);
5172 Assert(newtup == NULL);
5173 ItemPointerSetInvalid(&(new_event.ate_ctid1));
5174 ItemPointerSetInvalid(&(new_event.ate_ctid2));
5177 case TRIGGER_EVENT_DELETE:
5178 tgtype_event = TRIGGER_TYPE_DELETE;
5181 Assert(oldtup != NULL);
5182 Assert(newtup == NULL);
5183 ItemPointerCopy(&(oldtup->t_self), &(new_event.ate_ctid1));
5184 ItemPointerSetInvalid(&(new_event.ate_ctid2));
5188 Assert(oldtup == NULL);
5189 Assert(newtup == NULL);
5190 ItemPointerSetInvalid(&(new_event.ate_ctid1));
5191 ItemPointerSetInvalid(&(new_event.ate_ctid2));
5194 case TRIGGER_EVENT_UPDATE:
5195 tgtype_event = TRIGGER_TYPE_UPDATE;
5198 Assert(oldtup != NULL);
5199 Assert(newtup != NULL);
5200 ItemPointerCopy(&(oldtup->t_self), &(new_event.ate_ctid1));
5201 ItemPointerCopy(&(newtup->t_self), &(new_event.ate_ctid2));
5205 Assert(oldtup == NULL);
5206 Assert(newtup == NULL);
5207 ItemPointerSetInvalid(&(new_event.ate_ctid1));
5208 ItemPointerSetInvalid(&(new_event.ate_ctid2));
5211 case TRIGGER_EVENT_TRUNCATE:
5212 tgtype_event = TRIGGER_TYPE_TRUNCATE;
5213 Assert(oldtup == NULL);
5214 Assert(newtup == NULL);
5215 ItemPointerSetInvalid(&(new_event.ate_ctid1));
5216 ItemPointerSetInvalid(&(new_event.ate_ctid2));
5219 elog(ERROR, "invalid after-trigger event code: %d", event);
5220 tgtype_event = 0; /* keep compiler quiet */
5224 if (!(relkind == RELKIND_FOREIGN_TABLE && row_trigger))
5225 new_event.ate_flags = (row_trigger && event == TRIGGER_EVENT_UPDATE) ?
5226 AFTER_TRIGGER_2CTID : AFTER_TRIGGER_1CTID;
5227 /* else, we'll initialize ate_flags for each trigger */
5229 tgtype_level = (row_trigger ? TRIGGER_TYPE_ROW : TRIGGER_TYPE_STATEMENT);
5231 for (i = 0; i < trigdesc->numtriggers; i++)
5233 Trigger *trigger = &trigdesc->triggers[i];
5235 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
5240 if (!TriggerEnabled(estate, relinfo, trigger, event,
5241 modifiedCols, oldtup, newtup))
5244 if (relkind == RELKIND_FOREIGN_TABLE && row_trigger)
5246 if (fdw_tuplestore == NULL)
5249 GetTriggerTransitionTuplestore
5250 (afterTriggers.fdw_tuplestores);
5251 new_event.ate_flags = AFTER_TRIGGER_FDW_FETCH;
5254 /* subsequent event for the same tuple */
5255 new_event.ate_flags = AFTER_TRIGGER_FDW_REUSE;
5259 * If the trigger is a foreign key enforcement trigger, there are
5260 * certain cases where we can skip queueing the event because we can
5261 * tell by inspection that the FK constraint will still pass.
5263 if (TRIGGER_FIRED_BY_UPDATE(event))
5265 switch (RI_FKey_trigger_type(trigger->tgfoid))
5268 /* Update on trigger's PK table */
5269 if (!RI_FKey_pk_upd_check_required(trigger, rel,
5272 /* skip queuing this event */
5278 /* Update on trigger's FK table */
5279 if (!RI_FKey_fk_upd_check_required(trigger, rel,
5282 /* skip queuing this event */
5287 case RI_TRIGGER_NONE:
5288 /* Not an FK trigger */
5294 * If the trigger is a deferred unique constraint check trigger, only
5295 * queue it if the unique constraint was potentially violated, which
5296 * we know from index insertion time.
5298 if (trigger->tgfoid == F_UNIQUE_KEY_RECHECK)
5300 if (!list_member_oid(recheckIndexes, trigger->tgconstrindid))
5301 continue; /* Uniqueness definitely not violated */
5305 * Fill in event structure and add it to the current query's queue.
5307 new_shared.ats_event =
5308 (event & TRIGGER_EVENT_OPMASK) |
5309 (row_trigger ? TRIGGER_EVENT_ROW : 0) |
5310 (trigger->tgdeferrable ? AFTER_TRIGGER_DEFERRABLE : 0) |
5311 (trigger->tginitdeferred ? AFTER_TRIGGER_INITDEFERRED : 0);
5312 new_shared.ats_tgoid = trigger->tgoid;
5313 new_shared.ats_relid = RelationGetRelid(rel);
5314 new_shared.ats_firing_id = 0;
5316 afterTriggerAddEvent(&afterTriggers.query_stack[afterTriggers.query_depth],
5317 &new_event, &new_shared);
5321 * Finally, spool any foreign tuple(s). The tuplestore squashes them to
5322 * minimal tuples, so this loses any system columns. The executor lost
5323 * those columns before us, for an unrelated reason, so this is fine.
5328 tuplestore_puttuple(fdw_tuplestore, oldtup);
5330 tuplestore_puttuple(fdw_tuplestore, newtup);
5335 pg_trigger_depth(PG_FUNCTION_ARGS)
5337 PG_RETURN_INT32(MyTriggerDepth);