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 = castNode(TriggerTransition, lfirst(lc));
347 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
348 errmsg("ROW variable naming in the REFERENCING clause is not supported"),
349 errhint("Use OLD TABLE or NEW TABLE for naming transition tables.")));
352 * Because of the above test, we omit further ROW-related testing
353 * below. If we later allow naming OLD and NEW ROW variables,
354 * adjustments will be needed below.
357 if (stmt->timing != TRIGGER_TYPE_AFTER)
359 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
360 errmsg("transition table name can only be specified for an AFTER trigger")));
364 if (!(TRIGGER_FOR_INSERT(tgtype) ||
365 TRIGGER_FOR_UPDATE(tgtype)))
367 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
368 errmsg("NEW TABLE can only be specified for an INSERT or UPDATE trigger")));
370 if (newtablename != NULL)
372 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
373 errmsg("NEW TABLE cannot be specified multiple times")));
375 newtablename = tt->name;
379 if (!(TRIGGER_FOR_DELETE(tgtype) ||
380 TRIGGER_FOR_UPDATE(tgtype)))
382 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
383 errmsg("OLD TABLE can only be specified for a DELETE or UPDATE trigger")));
385 if (oldtablename != NULL)
387 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
388 errmsg("OLD TABLE cannot be specified multiple times")));
390 oldtablename = tt->name;
394 if (newtablename != NULL && oldtablename != NULL &&
395 strcmp(newtablename, oldtablename) == 0)
397 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
398 errmsg("OLD TABLE name and NEW TABLE name cannot be the same")));
402 * Parse the WHEN clause, if any
404 if (stmt->whenClause)
411 /* Set up a pstate to parse with */
412 pstate = make_parsestate(NULL);
413 pstate->p_sourcetext = queryString;
416 * Set up RTEs for OLD and NEW references.
418 * 'OLD' must always have varno equal to 1 and 'NEW' equal to 2.
420 rte = addRangeTableEntryForRelation(pstate, rel,
421 makeAlias("old", NIL),
423 addRTEtoQuery(pstate, rte, false, true, true);
424 rte = addRangeTableEntryForRelation(pstate, rel,
425 makeAlias("new", NIL),
427 addRTEtoQuery(pstate, rte, false, true, true);
429 /* Transform expression. Copy to be sure we don't modify original */
430 whenClause = transformWhereClause(pstate,
431 copyObject(stmt->whenClause),
432 EXPR_KIND_TRIGGER_WHEN,
434 /* we have to fix its collations too */
435 assign_expr_collations(pstate, whenClause);
438 * Check for disallowed references to OLD/NEW.
440 * NB: pull_var_clause is okay here only because we don't allow
441 * subselects in WHEN clauses; it would fail to examine the contents
444 varList = pull_var_clause(whenClause, 0);
447 Var *var = (Var *) lfirst(lc);
452 if (!TRIGGER_FOR_ROW(tgtype))
454 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
455 errmsg("statement trigger's WHEN condition cannot reference column values"),
456 parser_errposition(pstate, var->location)));
457 if (TRIGGER_FOR_INSERT(tgtype))
459 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
460 errmsg("INSERT trigger's WHEN condition cannot reference OLD values"),
461 parser_errposition(pstate, var->location)));
462 /* system columns are okay here */
465 if (!TRIGGER_FOR_ROW(tgtype))
467 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
468 errmsg("statement trigger's WHEN condition cannot reference column values"),
469 parser_errposition(pstate, var->location)));
470 if (TRIGGER_FOR_DELETE(tgtype))
472 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
473 errmsg("DELETE trigger's WHEN condition cannot reference NEW values"),
474 parser_errposition(pstate, var->location)));
475 if (var->varattno < 0 && TRIGGER_FOR_BEFORE(tgtype))
477 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
478 errmsg("BEFORE trigger's WHEN condition cannot reference NEW system columns"),
479 parser_errposition(pstate, var->location)));
482 /* can't happen without add_missing_from, so just elog */
483 elog(ERROR, "trigger WHEN condition cannot contain references to other relations");
488 /* we'll need the rtable for recordDependencyOnExpr */
489 whenRtable = pstate->p_rtable;
491 qual = nodeToString(whenClause);
493 free_parsestate(pstate);
503 * Find and validate the trigger function.
505 funcoid = LookupFuncName(stmt->funcname, 0, fargtypes, false);
508 aclresult = pg_proc_aclcheck(funcoid, GetUserId(), ACL_EXECUTE);
509 if (aclresult != ACLCHECK_OK)
510 aclcheck_error(aclresult, ACL_KIND_PROC,
511 NameListToString(stmt->funcname));
513 funcrettype = get_func_rettype(funcoid);
514 if (funcrettype != TRIGGEROID)
517 * We allow OPAQUE just so we can load old dump files. When we see a
518 * trigger function declared OPAQUE, change it to TRIGGER.
520 if (funcrettype == OPAQUEOID)
523 (errmsg("changing return type of function %s from %s to %s",
524 NameListToString(stmt->funcname),
525 "opaque", "trigger")));
526 SetFunctionReturnType(funcoid, TRIGGEROID);
530 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
531 errmsg("function %s must return type %s",
532 NameListToString(stmt->funcname), "trigger")));
536 * If the command is a user-entered CREATE CONSTRAINT TRIGGER command that
537 * references one of the built-in RI_FKey trigger functions, assume it is
538 * from a dump of a pre-7.3 foreign key constraint, and take steps to
539 * convert this legacy representation into a regular foreign key
540 * constraint. Ugly, but necessary for loading old dump files.
542 if (stmt->isconstraint && !isInternal &&
543 list_length(stmt->args) >= 6 &&
544 (list_length(stmt->args) % 2) == 0 &&
545 RI_FKey_trigger_type(funcoid) != RI_TRIGGER_NONE)
547 /* Keep lock on target rel until end of xact */
548 heap_close(rel, NoLock);
550 ConvertTriggerToFK(stmt, funcoid);
552 return InvalidObjectAddress;
556 * If it's a user-entered CREATE CONSTRAINT TRIGGER command, make a
557 * corresponding pg_constraint entry.
559 if (stmt->isconstraint && !OidIsValid(constraintOid))
561 /* Internal callers should have made their own constraints */
563 constraintOid = CreateConstraintEntry(stmt->trigname,
564 RelationGetNamespace(rel),
569 RelationGetRelid(rel),
570 NULL, /* no conkey */
572 InvalidOid, /* no domain */
573 InvalidOid, /* no index */
574 InvalidOid, /* no foreign key */
583 NULL, /* no exclusion */
584 NULL, /* no check constraint */
589 true, /* isnoinherit */
590 isInternal); /* is_internal */
594 * Generate the trigger's OID now, so that we can use it in the name if
597 tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
599 trigoid = GetNewOid(tgrel);
602 * If trigger is internally generated, modify the provided trigger name to
603 * ensure uniqueness by appending the trigger OID. (Callers will usually
604 * supply a simple constant trigger name in these cases.)
608 snprintf(internaltrigname, sizeof(internaltrigname),
609 "%s_%u", stmt->trigname, trigoid);
610 trigname = internaltrigname;
614 /* user-defined trigger; use the specified trigger name as-is */
615 trigname = stmt->trigname;
619 * Scan pg_trigger for existing triggers on relation. We do this only to
620 * give a nice error message if there's already a trigger of the same
621 * name. (The unique index on tgrelid/tgname would complain anyway.) We
622 * can skip this for internally generated triggers, since the name
623 * modification above should be sufficient.
625 * NOTE that this is cool only because we have ShareRowExclusiveLock on
626 * the relation, so the trigger set won't be changing underneath us.
631 Anum_pg_trigger_tgrelid,
632 BTEqualStrategyNumber, F_OIDEQ,
633 ObjectIdGetDatum(RelationGetRelid(rel)));
634 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
636 while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
638 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
640 if (namestrcmp(&(pg_trigger->tgname), trigname) == 0)
642 (errcode(ERRCODE_DUPLICATE_OBJECT),
643 errmsg("trigger \"%s\" for relation \"%s\" already exists",
644 trigname, RelationGetRelationName(rel))));
646 systable_endscan(tgscan);
650 * Build the new pg_trigger tuple.
652 memset(nulls, false, sizeof(nulls));
654 values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
655 values[Anum_pg_trigger_tgname - 1] = DirectFunctionCall1(namein,
656 CStringGetDatum(trigname));
657 values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid);
658 values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype);
659 values[Anum_pg_trigger_tgenabled - 1] = CharGetDatum(TRIGGER_FIRES_ON_ORIGIN);
660 values[Anum_pg_trigger_tgisinternal - 1] = BoolGetDatum(isInternal);
661 values[Anum_pg_trigger_tgconstrrelid - 1] = ObjectIdGetDatum(constrrelid);
662 values[Anum_pg_trigger_tgconstrindid - 1] = ObjectIdGetDatum(indexOid);
663 values[Anum_pg_trigger_tgconstraint - 1] = ObjectIdGetDatum(constraintOid);
664 values[Anum_pg_trigger_tgdeferrable - 1] = BoolGetDatum(stmt->deferrable);
665 values[Anum_pg_trigger_tginitdeferred - 1] = BoolGetDatum(stmt->initdeferred);
671 int16 nargs = list_length(stmt->args);
674 foreach(le, stmt->args)
676 char *ar = strVal(lfirst(le));
678 len += strlen(ar) + 4;
685 args = (char *) palloc(len + 1);
687 foreach(le, stmt->args)
689 char *s = strVal(lfirst(le));
690 char *d = args + strlen(args);
700 values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(nargs);
701 values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
702 CStringGetDatum(args));
706 values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(0);
707 values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
708 CStringGetDatum(""));
711 /* build column number array if it's a column-specific trigger */
712 ncolumns = list_length(stmt->columns);
720 columns = (int16 *) palloc(ncolumns * sizeof(int16));
721 foreach(cell, stmt->columns)
723 char *name = strVal(lfirst(cell));
727 /* Lookup column name. System columns are not allowed */
728 attnum = attnameAttNum(rel, name, false);
729 if (attnum == InvalidAttrNumber)
731 (errcode(ERRCODE_UNDEFINED_COLUMN),
732 errmsg("column \"%s\" of relation \"%s\" does not exist",
733 name, RelationGetRelationName(rel))));
735 /* Check for duplicates */
736 for (j = i - 1; j >= 0; j--)
738 if (columns[j] == attnum)
740 (errcode(ERRCODE_DUPLICATE_COLUMN),
741 errmsg("column \"%s\" specified more than once",
745 columns[i++] = attnum;
748 tgattr = buildint2vector(columns, ncolumns);
749 values[Anum_pg_trigger_tgattr - 1] = PointerGetDatum(tgattr);
751 /* set tgqual if trigger has WHEN clause */
753 values[Anum_pg_trigger_tgqual - 1] = CStringGetTextDatum(qual);
755 nulls[Anum_pg_trigger_tgqual - 1] = true;
758 values[Anum_pg_trigger_tgoldtable - 1] = DirectFunctionCall1(namein,
759 CStringGetDatum(oldtablename));
761 nulls[Anum_pg_trigger_tgoldtable - 1] = true;
763 values[Anum_pg_trigger_tgnewtable - 1] = DirectFunctionCall1(namein,
764 CStringGetDatum(newtablename));
766 nulls[Anum_pg_trigger_tgnewtable - 1] = true;
768 tuple = heap_form_tuple(tgrel->rd_att, values, nulls);
770 /* force tuple to have the desired OID */
771 HeapTupleSetOid(tuple, trigoid);
774 * Insert tuple into pg_trigger.
776 CatalogTupleInsert(tgrel, tuple);
778 heap_freetuple(tuple);
779 heap_close(tgrel, RowExclusiveLock);
781 pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
782 pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1]));
783 pfree(DatumGetPointer(values[Anum_pg_trigger_tgattr - 1]));
785 pfree(DatumGetPointer(values[Anum_pg_trigger_tgoldtable - 1]));
787 pfree(DatumGetPointer(values[Anum_pg_trigger_tgnewtable - 1]));
790 * Update relation's pg_class entry. Crucial side-effect: other backends
791 * (and this one too!) are sent SI message to make them rebuild relcache
794 pgrel = heap_open(RelationRelationId, RowExclusiveLock);
795 tuple = SearchSysCacheCopy1(RELOID,
796 ObjectIdGetDatum(RelationGetRelid(rel)));
797 if (!HeapTupleIsValid(tuple))
798 elog(ERROR, "cache lookup failed for relation %u",
799 RelationGetRelid(rel));
801 ((Form_pg_class) GETSTRUCT(tuple))->relhastriggers = true;
803 CatalogTupleUpdate(pgrel, &tuple->t_self, tuple);
805 heap_freetuple(tuple);
806 heap_close(pgrel, RowExclusiveLock);
809 * We used to try to update the rel's relcache entry here, but that's
810 * fairly pointless since it will happen as a byproduct of the upcoming
811 * CommandCounterIncrement...
815 * Record dependencies for trigger. Always place a normal dependency on
818 myself.classId = TriggerRelationId;
819 myself.objectId = trigoid;
820 myself.objectSubId = 0;
822 referenced.classId = ProcedureRelationId;
823 referenced.objectId = funcoid;
824 referenced.objectSubId = 0;
825 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
827 if (isInternal && OidIsValid(constraintOid))
830 * Internally-generated trigger for a constraint, so make it an
831 * internal dependency of the constraint. We can skip depending on
832 * the relation(s), as there'll be an indirect dependency via the
835 referenced.classId = ConstraintRelationId;
836 referenced.objectId = constraintOid;
837 referenced.objectSubId = 0;
838 recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
843 * User CREATE TRIGGER, so place dependencies. We make trigger be
844 * auto-dropped if its relation is dropped or if the FK relation is
845 * dropped. (Auto drop is compatible with our pre-7.3 behavior.)
847 referenced.classId = RelationRelationId;
848 referenced.objectId = RelationGetRelid(rel);
849 referenced.objectSubId = 0;
850 recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
851 if (OidIsValid(constrrelid))
853 referenced.classId = RelationRelationId;
854 referenced.objectId = constrrelid;
855 referenced.objectSubId = 0;
856 recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
858 /* Not possible to have an index dependency in this case */
859 Assert(!OidIsValid(indexOid));
862 * If it's a user-specified constraint trigger, make the constraint
863 * internally dependent on the trigger instead of vice versa.
865 if (OidIsValid(constraintOid))
867 referenced.classId = ConstraintRelationId;
868 referenced.objectId = constraintOid;
869 referenced.objectSubId = 0;
870 recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
874 /* If column-specific trigger, add normal dependencies on columns */
879 referenced.classId = RelationRelationId;
880 referenced.objectId = RelationGetRelid(rel);
881 for (i = 0; i < ncolumns; i++)
883 referenced.objectSubId = columns[i];
884 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
889 * If it has a WHEN clause, add dependencies on objects mentioned in the
890 * expression (eg, functions, as well as any columns used).
892 if (whenClause != NULL)
893 recordDependencyOnExpr(&myself, whenClause, whenRtable,
896 /* Post creation hook for new trigger */
897 InvokeObjectPostCreateHookArg(TriggerRelationId, trigoid, 0,
900 /* Keep lock on target rel until end of xact */
901 heap_close(rel, NoLock);
908 * Convert legacy (pre-7.3) CREATE CONSTRAINT TRIGGER commands into
909 * full-fledged foreign key constraints.
911 * The conversion is complex because a pre-7.3 foreign key involved three
912 * separate triggers, which were reported separately in dumps. While the
913 * single trigger on the referencing table adds no new information, we need
914 * to know the trigger functions of both of the triggers on the referenced
915 * table to build the constraint declaration. Also, due to lack of proper
916 * dependency checking pre-7.3, it is possible that the source database had
917 * an incomplete set of triggers resulting in an only partially enforced
918 * FK constraint. (This would happen if one of the tables had been dropped
919 * and re-created, but only if the DB had been affected by a 7.0 pg_dump bug
920 * that caused loss of tgconstrrelid information.) We choose to translate to
921 * an FK constraint only when we've seen all three triggers of a set. This is
922 * implemented by storing unmatched items in a list in TopMemoryContext.
923 * We match triggers together by comparing the trigger arguments (which
924 * include constraint name, table and column names, so should be good enough).
928 List *args; /* list of (T_String) Values or NIL */
929 Oid funcoids[3]; /* OIDs of trigger functions */
930 /* The three function OIDs are stored in the order update, delete, child */
934 ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
936 static List *info_list = NIL;
938 static const char *const funcdescr[3] = {
939 gettext_noop("Found referenced table's UPDATE trigger."),
940 gettext_noop("Found referenced table's DELETE trigger."),
941 gettext_noop("Found referencing table's trigger.")
947 char fk_matchtype = FKCONSTR_MATCH_SIMPLE;
948 List *fk_attrs = NIL;
949 List *pk_attrs = NIL;
952 OldTriggerInfo *info = NULL;
956 /* Parse out the trigger arguments */
957 constr_name = strVal(linitial(stmt->args));
958 fk_table_name = strVal(lsecond(stmt->args));
959 pk_table_name = strVal(lthird(stmt->args));
961 foreach(l, stmt->args)
963 Value *arg = (Value *) lfirst(l);
966 if (i < 4) /* skip constraint and table names */
968 if (i == 4) /* handle match type */
970 if (strcmp(strVal(arg), "FULL") == 0)
971 fk_matchtype = FKCONSTR_MATCH_FULL;
973 fk_matchtype = FKCONSTR_MATCH_SIMPLE;
977 fk_attrs = lappend(fk_attrs, arg);
979 pk_attrs = lappend(pk_attrs, arg);
982 /* Prepare description of constraint for use in messages */
983 initStringInfo(&buf);
984 appendStringInfo(&buf, "FOREIGN KEY %s(",
985 quote_identifier(fk_table_name));
989 Value *arg = (Value *) lfirst(l);
992 appendStringInfoChar(&buf, ',');
993 appendStringInfoString(&buf, quote_identifier(strVal(arg)));
995 appendStringInfo(&buf, ") REFERENCES %s(",
996 quote_identifier(pk_table_name));
1000 Value *arg = (Value *) lfirst(l);
1003 appendStringInfoChar(&buf, ',');
1004 appendStringInfoString(&buf, quote_identifier(strVal(arg)));
1006 appendStringInfoChar(&buf, ')');
1008 /* Identify class of trigger --- update, delete, or referencing-table */
1011 case F_RI_FKEY_CASCADE_UPD:
1012 case F_RI_FKEY_RESTRICT_UPD:
1013 case F_RI_FKEY_SETNULL_UPD:
1014 case F_RI_FKEY_SETDEFAULT_UPD:
1015 case F_RI_FKEY_NOACTION_UPD:
1019 case F_RI_FKEY_CASCADE_DEL:
1020 case F_RI_FKEY_RESTRICT_DEL:
1021 case F_RI_FKEY_SETNULL_DEL:
1022 case F_RI_FKEY_SETDEFAULT_DEL:
1023 case F_RI_FKEY_NOACTION_DEL:
1032 /* See if we have a match to this trigger */
1033 foreach(l, info_list)
1035 info = (OldTriggerInfo *) lfirst(l);
1036 if (info->funcoids[funcnum] == InvalidOid &&
1037 equal(info->args, stmt->args))
1039 info->funcoids[funcnum] = funcoid;
1046 /* First trigger of set, so create a new list entry */
1047 MemoryContext oldContext;
1050 (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
1051 constr_name, buf.data),
1052 errdetail_internal("%s", _(funcdescr[funcnum]))));
1053 oldContext = MemoryContextSwitchTo(TopMemoryContext);
1054 info = (OldTriggerInfo *) palloc0(sizeof(OldTriggerInfo));
1055 info->args = copyObject(stmt->args);
1056 info->funcoids[funcnum] = funcoid;
1057 info_list = lappend(info_list, info);
1058 MemoryContextSwitchTo(oldContext);
1060 else if (info->funcoids[0] == InvalidOid ||
1061 info->funcoids[1] == InvalidOid ||
1062 info->funcoids[2] == InvalidOid)
1064 /* Second trigger of set */
1066 (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
1067 constr_name, buf.data),
1068 errdetail_internal("%s", _(funcdescr[funcnum]))));
1072 /* OK, we have a set, so make the FK constraint ALTER TABLE cmd */
1073 AlterTableStmt *atstmt = makeNode(AlterTableStmt);
1074 AlterTableCmd *atcmd = makeNode(AlterTableCmd);
1075 Constraint *fkcon = makeNode(Constraint);
1076 PlannedStmt *wrapper = makeNode(PlannedStmt);
1079 (errmsg("converting trigger group into constraint \"%s\" %s",
1080 constr_name, buf.data),
1081 errdetail_internal("%s", _(funcdescr[funcnum]))));
1082 fkcon->contype = CONSTR_FOREIGN;
1083 fkcon->location = -1;
1086 /* This trigger is on the FK table */
1087 atstmt->relation = stmt->relation;
1088 if (stmt->constrrel)
1089 fkcon->pktable = stmt->constrrel;
1092 /* Work around ancient pg_dump bug that omitted constrrel */
1093 fkcon->pktable = makeRangeVar(NULL, pk_table_name, -1);
1098 /* This trigger is on the PK table */
1099 fkcon->pktable = stmt->relation;
1100 if (stmt->constrrel)
1101 atstmt->relation = stmt->constrrel;
1104 /* Work around ancient pg_dump bug that omitted constrrel */
1105 atstmt->relation = makeRangeVar(NULL, fk_table_name, -1);
1108 atstmt->cmds = list_make1(atcmd);
1109 atstmt->relkind = OBJECT_TABLE;
1110 atcmd->subtype = AT_AddConstraint;
1111 atcmd->def = (Node *) fkcon;
1112 if (strcmp(constr_name, "<unnamed>") == 0)
1113 fkcon->conname = NULL;
1115 fkcon->conname = constr_name;
1116 fkcon->fk_attrs = fk_attrs;
1117 fkcon->pk_attrs = pk_attrs;
1118 fkcon->fk_matchtype = fk_matchtype;
1119 switch (info->funcoids[0])
1121 case F_RI_FKEY_NOACTION_UPD:
1122 fkcon->fk_upd_action = FKCONSTR_ACTION_NOACTION;
1124 case F_RI_FKEY_CASCADE_UPD:
1125 fkcon->fk_upd_action = FKCONSTR_ACTION_CASCADE;
1127 case F_RI_FKEY_RESTRICT_UPD:
1128 fkcon->fk_upd_action = FKCONSTR_ACTION_RESTRICT;
1130 case F_RI_FKEY_SETNULL_UPD:
1131 fkcon->fk_upd_action = FKCONSTR_ACTION_SETNULL;
1133 case F_RI_FKEY_SETDEFAULT_UPD:
1134 fkcon->fk_upd_action = FKCONSTR_ACTION_SETDEFAULT;
1137 /* can't get here because of earlier checks */
1138 elog(ERROR, "confused about RI update function");
1140 switch (info->funcoids[1])
1142 case F_RI_FKEY_NOACTION_DEL:
1143 fkcon->fk_del_action = FKCONSTR_ACTION_NOACTION;
1145 case F_RI_FKEY_CASCADE_DEL:
1146 fkcon->fk_del_action = FKCONSTR_ACTION_CASCADE;
1148 case F_RI_FKEY_RESTRICT_DEL:
1149 fkcon->fk_del_action = FKCONSTR_ACTION_RESTRICT;
1151 case F_RI_FKEY_SETNULL_DEL:
1152 fkcon->fk_del_action = FKCONSTR_ACTION_SETNULL;
1154 case F_RI_FKEY_SETDEFAULT_DEL:
1155 fkcon->fk_del_action = FKCONSTR_ACTION_SETDEFAULT;
1158 /* can't get here because of earlier checks */
1159 elog(ERROR, "confused about RI delete function");
1161 fkcon->deferrable = stmt->deferrable;
1162 fkcon->initdeferred = stmt->initdeferred;
1163 fkcon->skip_validation = false;
1164 fkcon->initially_valid = true;
1166 /* finally, wrap it in a dummy PlannedStmt */
1167 wrapper->commandType = CMD_UTILITY;
1168 wrapper->canSetTag = false;
1169 wrapper->utilityStmt = (Node *) atstmt;
1170 wrapper->stmt_location = -1;
1171 wrapper->stmt_len = -1;
1173 /* ... and execute it */
1174 ProcessUtility(wrapper,
1175 "(generated ALTER TABLE ADD FOREIGN KEY command)",
1176 PROCESS_UTILITY_SUBCOMMAND, NULL,
1177 None_Receiver, NULL);
1179 /* Remove the matched item from the list */
1180 info_list = list_delete_ptr(info_list, info);
1182 /* We leak the copied args ... not worth worrying about */
1187 * Guts of trigger deletion.
1190 RemoveTriggerById(Oid trigOid)
1194 ScanKeyData skey[1];
1199 tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
1202 * Find the trigger to delete.
1204 ScanKeyInit(&skey[0],
1205 ObjectIdAttributeNumber,
1206 BTEqualStrategyNumber, F_OIDEQ,
1207 ObjectIdGetDatum(trigOid));
1209 tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
1212 tup = systable_getnext(tgscan);
1213 if (!HeapTupleIsValid(tup))
1214 elog(ERROR, "could not find tuple for trigger %u", trigOid);
1217 * Open and exclusive-lock the relation the trigger belongs to.
1219 relid = ((Form_pg_trigger) GETSTRUCT(tup))->tgrelid;
1221 rel = heap_open(relid, AccessExclusiveLock);
1223 if (rel->rd_rel->relkind != RELKIND_RELATION &&
1224 rel->rd_rel->relkind != RELKIND_VIEW &&
1225 rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
1226 rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1228 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1229 errmsg("\"%s\" is not a table, view, or foreign table",
1230 RelationGetRelationName(rel))));
1232 if (!allowSystemTableMods && IsSystemRelation(rel))
1234 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1235 errmsg("permission denied: \"%s\" is a system catalog",
1236 RelationGetRelationName(rel))));
1239 * Delete the pg_trigger tuple.
1241 CatalogTupleDelete(tgrel, &tup->t_self);
1243 systable_endscan(tgscan);
1244 heap_close(tgrel, RowExclusiveLock);
1247 * We do not bother to try to determine whether any other triggers remain,
1248 * which would be needed in order to decide whether it's safe to clear the
1249 * relation's relhastriggers. (In any case, there might be a concurrent
1250 * process adding new triggers.) Instead, just force a relcache inval to
1251 * make other backends (and this one too!) rebuild their relcache entries.
1252 * There's no great harm in leaving relhastriggers true even if there are
1255 CacheInvalidateRelcache(rel);
1257 /* Keep lock on trigger's rel until end of xact */
1258 heap_close(rel, NoLock);
1262 * get_trigger_oid - Look up a trigger by name to find its OID.
1264 * If missing_ok is false, throw an error if trigger not found. If
1265 * true, just return InvalidOid.
1268 get_trigger_oid(Oid relid, const char *trigname, bool missing_ok)
1271 ScanKeyData skey[2];
1277 * Find the trigger, verify permissions, set up object address
1279 tgrel = heap_open(TriggerRelationId, AccessShareLock);
1281 ScanKeyInit(&skey[0],
1282 Anum_pg_trigger_tgrelid,
1283 BTEqualStrategyNumber, F_OIDEQ,
1284 ObjectIdGetDatum(relid));
1285 ScanKeyInit(&skey[1],
1286 Anum_pg_trigger_tgname,
1287 BTEqualStrategyNumber, F_NAMEEQ,
1288 CStringGetDatum(trigname));
1290 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1293 tup = systable_getnext(tgscan);
1295 if (!HeapTupleIsValid(tup))
1299 (errcode(ERRCODE_UNDEFINED_OBJECT),
1300 errmsg("trigger \"%s\" for table \"%s\" does not exist",
1301 trigname, get_rel_name(relid))));
1306 oid = HeapTupleGetOid(tup);
1309 systable_endscan(tgscan);
1310 heap_close(tgrel, AccessShareLock);
1315 * Perform permissions and integrity checks before acquiring a relation lock.
1318 RangeVarCallbackForRenameTrigger(const RangeVar *rv, Oid relid, Oid oldrelid,
1324 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1325 if (!HeapTupleIsValid(tuple))
1326 return; /* concurrently dropped */
1327 form = (Form_pg_class) GETSTRUCT(tuple);
1329 /* only tables and views can have triggers */
1330 if (form->relkind != RELKIND_RELATION && form->relkind != RELKIND_VIEW &&
1331 form->relkind != RELKIND_FOREIGN_TABLE &&
1332 form->relkind != RELKIND_PARTITIONED_TABLE)
1334 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1335 errmsg("\"%s\" is not a table, view, or foreign table",
1338 /* you must own the table to rename one of its triggers */
1339 if (!pg_class_ownercheck(relid, GetUserId()))
1340 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, rv->relname);
1341 if (!allowSystemTableMods && IsSystemClass(relid, form))
1343 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1344 errmsg("permission denied: \"%s\" is a system catalog",
1347 ReleaseSysCache(tuple);
1351 * renametrig - changes the name of a trigger on a relation
1353 * trigger name is changed in trigger catalog.
1354 * No record of the previous name is kept.
1356 * get proper relrelation from relation catalog (if not arg)
1357 * scan trigger catalog
1358 * for name conflict (within rel)
1359 * for original trigger (if not arg)
1360 * modify tgname in trigger tuple
1361 * update row in catalog
1364 renametrig(RenameStmt *stmt)
1373 ObjectAddress address;
1376 * Look up name, check permissions, and acquire lock (which we will NOT
1377 * release until end of transaction).
1379 relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
1381 RangeVarCallbackForRenameTrigger,
1384 /* Have lock already, so just need to build relcache entry. */
1385 targetrel = relation_open(relid, NoLock);
1388 * Scan pg_trigger twice for existing triggers on relation. We do this in
1389 * order to ensure a trigger does not exist with newname (The unique index
1390 * on tgrelid/tgname would complain anyway) and to ensure a trigger does
1391 * exist with oldname.
1393 * NOTE that this is cool only because we have AccessExclusiveLock on the
1394 * relation, so the trigger set won't be changing underneath us.
1396 tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
1399 * First pass -- look for name conflict
1401 ScanKeyInit(&key[0],
1402 Anum_pg_trigger_tgrelid,
1403 BTEqualStrategyNumber, F_OIDEQ,
1404 ObjectIdGetDatum(relid));
1405 ScanKeyInit(&key[1],
1406 Anum_pg_trigger_tgname,
1407 BTEqualStrategyNumber, F_NAMEEQ,
1408 PointerGetDatum(stmt->newname));
1409 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1411 if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1413 (errcode(ERRCODE_DUPLICATE_OBJECT),
1414 errmsg("trigger \"%s\" for relation \"%s\" already exists",
1415 stmt->newname, RelationGetRelationName(targetrel))));
1416 systable_endscan(tgscan);
1419 * Second pass -- look for trigger existing with oldname and update
1421 ScanKeyInit(&key[0],
1422 Anum_pg_trigger_tgrelid,
1423 BTEqualStrategyNumber, F_OIDEQ,
1424 ObjectIdGetDatum(relid));
1425 ScanKeyInit(&key[1],
1426 Anum_pg_trigger_tgname,
1427 BTEqualStrategyNumber, F_NAMEEQ,
1428 PointerGetDatum(stmt->subname));
1429 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1431 if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1433 tgoid = HeapTupleGetOid(tuple);
1436 * Update pg_trigger tuple with new tgname.
1438 tuple = heap_copytuple(tuple); /* need a modifiable copy */
1440 namestrcpy(&((Form_pg_trigger) GETSTRUCT(tuple))->tgname,
1443 CatalogTupleUpdate(tgrel, &tuple->t_self, tuple);
1445 InvokeObjectPostAlterHook(TriggerRelationId,
1446 HeapTupleGetOid(tuple), 0);
1449 * Invalidate relation's relcache entry so that other backends (and
1450 * this one too!) are sent SI message to make them rebuild relcache
1451 * entries. (Ideally this should happen automatically...)
1453 CacheInvalidateRelcache(targetrel);
1458 (errcode(ERRCODE_UNDEFINED_OBJECT),
1459 errmsg("trigger \"%s\" for table \"%s\" does not exist",
1460 stmt->subname, RelationGetRelationName(targetrel))));
1463 ObjectAddressSet(address, TriggerRelationId, tgoid);
1465 systable_endscan(tgscan);
1467 heap_close(tgrel, RowExclusiveLock);
1470 * Close rel, but keep exclusive lock!
1472 relation_close(targetrel, NoLock);
1479 * EnableDisableTrigger()
1481 * Called by ALTER TABLE ENABLE/DISABLE [ REPLICA | ALWAYS ] TRIGGER
1482 * to change 'tgenabled' field for the specified trigger(s)
1484 * rel: relation to process (caller must hold suitable lock on it)
1485 * tgname: trigger to process, or NULL to scan all triggers
1486 * fires_when: new value for tgenabled field. In addition to generic
1487 * enablement/disablement, this also defines when the trigger
1488 * should be fired in session replication roles.
1489 * skip_system: if true, skip "system" triggers (constraint triggers)
1491 * Caller should have checked permissions for the table; here we also
1492 * enforce that superuser privilege is required to alter the state of
1496 EnableDisableTrigger(Relation rel, const char *tgname,
1497 char fires_when, bool skip_system)
1501 ScanKeyData keys[2];
1507 /* Scan the relevant entries in pg_triggers */
1508 tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
1510 ScanKeyInit(&keys[0],
1511 Anum_pg_trigger_tgrelid,
1512 BTEqualStrategyNumber, F_OIDEQ,
1513 ObjectIdGetDatum(RelationGetRelid(rel)));
1516 ScanKeyInit(&keys[1],
1517 Anum_pg_trigger_tgname,
1518 BTEqualStrategyNumber, F_NAMEEQ,
1519 CStringGetDatum(tgname));
1525 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1528 found = changed = false;
1530 while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1532 Form_pg_trigger oldtrig = (Form_pg_trigger) GETSTRUCT(tuple);
1534 if (oldtrig->tgisinternal)
1536 /* system trigger ... ok to process? */
1541 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1542 errmsg("permission denied: \"%s\" is a system trigger",
1543 NameStr(oldtrig->tgname))));
1548 if (oldtrig->tgenabled != fires_when)
1550 /* need to change this one ... make a copy to scribble on */
1551 HeapTuple newtup = heap_copytuple(tuple);
1552 Form_pg_trigger newtrig = (Form_pg_trigger) GETSTRUCT(newtup);
1554 newtrig->tgenabled = fires_when;
1556 CatalogTupleUpdate(tgrel, &newtup->t_self, newtup);
1558 heap_freetuple(newtup);
1563 InvokeObjectPostAlterHook(TriggerRelationId,
1564 HeapTupleGetOid(tuple), 0);
1567 systable_endscan(tgscan);
1569 heap_close(tgrel, RowExclusiveLock);
1571 if (tgname && !found)
1573 (errcode(ERRCODE_UNDEFINED_OBJECT),
1574 errmsg("trigger \"%s\" for table \"%s\" does not exist",
1575 tgname, RelationGetRelationName(rel))));
1578 * If we changed anything, broadcast a SI inval message to force each
1579 * backend (including our own!) to rebuild relation's relcache entry.
1580 * Otherwise they will fail to apply the change promptly.
1583 CacheInvalidateRelcache(rel);
1588 * Build trigger data to attach to the given relcache entry.
1590 * Note that trigger data attached to a relcache entry must be stored in
1591 * CacheMemoryContext to ensure it survives as long as the relcache entry.
1592 * But we should be running in a less long-lived working context. To avoid
1593 * leaking cache memory if this routine fails partway through, we build a
1594 * temporary TriggerDesc in working memory and then copy the completed
1595 * structure into cache memory.
1598 RelationBuildTriggers(Relation relation)
1600 TriggerDesc *trigdesc;
1608 MemoryContext oldContext;
1612 * Allocate a working array to hold the triggers (the array is extended if
1616 triggers = (Trigger *) palloc(maxtrigs * sizeof(Trigger));
1620 * Note: since we scan the triggers using TriggerRelidNameIndexId, we will
1621 * be reading the triggers in name order, except possibly during
1622 * emergency-recovery operations (ie, IgnoreSystemIndexes). This in turn
1623 * ensures that triggers will be fired in name order.
1626 Anum_pg_trigger_tgrelid,
1627 BTEqualStrategyNumber, F_OIDEQ,
1628 ObjectIdGetDatum(RelationGetRelid(relation)));
1630 tgrel = heap_open(TriggerRelationId, AccessShareLock);
1631 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1634 while (HeapTupleIsValid(htup = systable_getnext(tgscan)))
1636 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
1641 if (numtrigs >= maxtrigs)
1644 triggers = (Trigger *) repalloc(triggers, maxtrigs * sizeof(Trigger));
1646 build = &(triggers[numtrigs]);
1648 build->tgoid = HeapTupleGetOid(htup);
1649 build->tgname = DatumGetCString(DirectFunctionCall1(nameout,
1650 NameGetDatum(&pg_trigger->tgname)));
1651 build->tgfoid = pg_trigger->tgfoid;
1652 build->tgtype = pg_trigger->tgtype;
1653 build->tgenabled = pg_trigger->tgenabled;
1654 build->tgisinternal = pg_trigger->tgisinternal;
1655 build->tgconstrrelid = pg_trigger->tgconstrrelid;
1656 build->tgconstrindid = pg_trigger->tgconstrindid;
1657 build->tgconstraint = pg_trigger->tgconstraint;
1658 build->tgdeferrable = pg_trigger->tgdeferrable;
1659 build->tginitdeferred = pg_trigger->tginitdeferred;
1660 build->tgnargs = pg_trigger->tgnargs;
1661 /* tgattr is first var-width field, so OK to access directly */
1662 build->tgnattr = pg_trigger->tgattr.dim1;
1663 if (build->tgnattr > 0)
1665 build->tgattr = (int16 *) palloc(build->tgnattr * sizeof(int16));
1666 memcpy(build->tgattr, &(pg_trigger->tgattr.values),
1667 build->tgnattr * sizeof(int16));
1670 build->tgattr = NULL;
1671 if (build->tgnargs > 0)
1676 val = DatumGetByteaPP(fastgetattr(htup,
1677 Anum_pg_trigger_tgargs,
1678 tgrel->rd_att, &isnull));
1680 elog(ERROR, "tgargs is null in trigger for relation \"%s\"",
1681 RelationGetRelationName(relation));
1682 p = (char *) VARDATA_ANY(val);
1683 build->tgargs = (char **) palloc(build->tgnargs * sizeof(char *));
1684 for (i = 0; i < build->tgnargs; i++)
1686 build->tgargs[i] = pstrdup(p);
1691 build->tgargs = NULL;
1693 datum = fastgetattr(htup, Anum_pg_trigger_tgoldtable,
1694 tgrel->rd_att, &isnull);
1697 DatumGetCString(DirectFunctionCall1(nameout, datum));
1699 build->tgoldtable = NULL;
1701 datum = fastgetattr(htup, Anum_pg_trigger_tgnewtable,
1702 tgrel->rd_att, &isnull);
1705 DatumGetCString(DirectFunctionCall1(nameout, datum));
1707 build->tgnewtable = NULL;
1709 datum = fastgetattr(htup, Anum_pg_trigger_tgqual,
1710 tgrel->rd_att, &isnull);
1712 build->tgqual = TextDatumGetCString(datum);
1714 build->tgqual = NULL;
1719 systable_endscan(tgscan);
1720 heap_close(tgrel, AccessShareLock);
1722 /* There might not be any triggers */
1729 /* Build trigdesc */
1730 trigdesc = (TriggerDesc *) palloc0(sizeof(TriggerDesc));
1731 trigdesc->triggers = triggers;
1732 trigdesc->numtriggers = numtrigs;
1733 for (i = 0; i < numtrigs; i++)
1734 SetTriggerFlags(trigdesc, &(triggers[i]));
1736 /* Copy completed trigdesc into cache storage */
1737 oldContext = MemoryContextSwitchTo(CacheMemoryContext);
1738 relation->trigdesc = CopyTriggerDesc(trigdesc);
1739 MemoryContextSwitchTo(oldContext);
1741 /* Release working memory */
1742 FreeTriggerDesc(trigdesc);
1746 * Update the TriggerDesc's hint flags to include the specified trigger
1749 SetTriggerFlags(TriggerDesc *trigdesc, Trigger *trigger)
1751 int16 tgtype = trigger->tgtype;
1753 trigdesc->trig_insert_before_row |=
1754 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1755 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
1756 trigdesc->trig_insert_after_row |=
1757 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1758 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
1759 trigdesc->trig_insert_instead_row |=
1760 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1761 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_INSERT);
1762 trigdesc->trig_insert_before_statement |=
1763 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1764 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
1765 trigdesc->trig_insert_after_statement |=
1766 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1767 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
1768 trigdesc->trig_update_before_row |=
1769 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1770 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
1771 trigdesc->trig_update_after_row |=
1772 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1773 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
1774 trigdesc->trig_update_instead_row |=
1775 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1776 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_UPDATE);
1777 trigdesc->trig_update_before_statement |=
1778 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1779 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
1780 trigdesc->trig_update_after_statement |=
1781 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1782 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
1783 trigdesc->trig_delete_before_row |=
1784 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1785 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
1786 trigdesc->trig_delete_after_row |=
1787 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1788 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
1789 trigdesc->trig_delete_instead_row |=
1790 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1791 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_DELETE);
1792 trigdesc->trig_delete_before_statement |=
1793 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1794 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
1795 trigdesc->trig_delete_after_statement |=
1796 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1797 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
1798 /* there are no row-level truncate triggers */
1799 trigdesc->trig_truncate_before_statement |=
1800 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1801 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_TRUNCATE);
1802 trigdesc->trig_truncate_after_statement |=
1803 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1804 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_TRUNCATE);
1806 trigdesc->trig_insert_new_table |=
1807 (TRIGGER_FOR_INSERT(tgtype) &&
1808 TRIGGER_USES_TRANSITION_TABLE(trigger->tgnewtable));
1809 trigdesc->trig_update_old_table |=
1810 (TRIGGER_FOR_UPDATE(tgtype) &&
1811 TRIGGER_USES_TRANSITION_TABLE(trigger->tgoldtable));
1812 trigdesc->trig_update_new_table |=
1813 (TRIGGER_FOR_UPDATE(tgtype) &&
1814 TRIGGER_USES_TRANSITION_TABLE(trigger->tgnewtable));
1815 trigdesc->trig_delete_old_table |=
1816 (TRIGGER_FOR_DELETE(tgtype) &&
1817 TRIGGER_USES_TRANSITION_TABLE(trigger->tgoldtable));
1821 * Copy a TriggerDesc data structure.
1823 * The copy is allocated in the current memory context.
1826 CopyTriggerDesc(TriggerDesc *trigdesc)
1828 TriggerDesc *newdesc;
1832 if (trigdesc == NULL || trigdesc->numtriggers <= 0)
1835 newdesc = (TriggerDesc *) palloc(sizeof(TriggerDesc));
1836 memcpy(newdesc, trigdesc, sizeof(TriggerDesc));
1838 trigger = (Trigger *) palloc(trigdesc->numtriggers * sizeof(Trigger));
1839 memcpy(trigger, trigdesc->triggers,
1840 trigdesc->numtriggers * sizeof(Trigger));
1841 newdesc->triggers = trigger;
1843 for (i = 0; i < trigdesc->numtriggers; i++)
1845 trigger->tgname = pstrdup(trigger->tgname);
1846 if (trigger->tgnattr > 0)
1850 newattr = (int16 *) palloc(trigger->tgnattr * sizeof(int16));
1851 memcpy(newattr, trigger->tgattr,
1852 trigger->tgnattr * sizeof(int16));
1853 trigger->tgattr = newattr;
1855 if (trigger->tgnargs > 0)
1860 newargs = (char **) palloc(trigger->tgnargs * sizeof(char *));
1861 for (j = 0; j < trigger->tgnargs; j++)
1862 newargs[j] = pstrdup(trigger->tgargs[j]);
1863 trigger->tgargs = newargs;
1865 if (trigger->tgqual)
1866 trigger->tgqual = pstrdup(trigger->tgqual);
1867 if (trigger->tgoldtable)
1868 trigger->tgoldtable = pstrdup(trigger->tgoldtable);
1869 if (trigger->tgnewtable)
1870 trigger->tgnewtable = pstrdup(trigger->tgnewtable);
1878 * Free a TriggerDesc data structure.
1881 FreeTriggerDesc(TriggerDesc *trigdesc)
1886 if (trigdesc == NULL)
1889 trigger = trigdesc->triggers;
1890 for (i = 0; i < trigdesc->numtriggers; i++)
1892 pfree(trigger->tgname);
1893 if (trigger->tgnattr > 0)
1894 pfree(trigger->tgattr);
1895 if (trigger->tgnargs > 0)
1897 while (--(trigger->tgnargs) >= 0)
1898 pfree(trigger->tgargs[trigger->tgnargs]);
1899 pfree(trigger->tgargs);
1901 if (trigger->tgqual)
1902 pfree(trigger->tgqual);
1903 if (trigger->tgoldtable)
1904 pfree(trigger->tgoldtable);
1905 if (trigger->tgnewtable)
1906 pfree(trigger->tgnewtable);
1909 pfree(trigdesc->triggers);
1914 * Compare two TriggerDesc structures for logical equality.
1918 equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
1924 * We need not examine the hint flags, just the trigger array itself; if
1925 * we have the same triggers with the same types, the flags should match.
1927 * As of 7.3 we assume trigger set ordering is significant in the
1928 * comparison; so we just compare corresponding slots of the two sets.
1930 * Note: comparing the stringToNode forms of the WHEN clauses means that
1931 * parse column locations will affect the result. This is okay as long as
1932 * this function is only used for detecting exact equality, as for example
1933 * in checking for staleness of a cache entry.
1935 if (trigdesc1 != NULL)
1937 if (trigdesc2 == NULL)
1939 if (trigdesc1->numtriggers != trigdesc2->numtriggers)
1941 for (i = 0; i < trigdesc1->numtriggers; i++)
1943 Trigger *trig1 = trigdesc1->triggers + i;
1944 Trigger *trig2 = trigdesc2->triggers + i;
1946 if (trig1->tgoid != trig2->tgoid)
1948 if (strcmp(trig1->tgname, trig2->tgname) != 0)
1950 if (trig1->tgfoid != trig2->tgfoid)
1952 if (trig1->tgtype != trig2->tgtype)
1954 if (trig1->tgenabled != trig2->tgenabled)
1956 if (trig1->tgisinternal != trig2->tgisinternal)
1958 if (trig1->tgconstrrelid != trig2->tgconstrrelid)
1960 if (trig1->tgconstrindid != trig2->tgconstrindid)
1962 if (trig1->tgconstraint != trig2->tgconstraint)
1964 if (trig1->tgdeferrable != trig2->tgdeferrable)
1966 if (trig1->tginitdeferred != trig2->tginitdeferred)
1968 if (trig1->tgnargs != trig2->tgnargs)
1970 if (trig1->tgnattr != trig2->tgnattr)
1972 if (trig1->tgnattr > 0 &&
1973 memcmp(trig1->tgattr, trig2->tgattr,
1974 trig1->tgnattr * sizeof(int16)) != 0)
1976 for (j = 0; j < trig1->tgnargs; j++)
1977 if (strcmp(trig1->tgargs[j], trig2->tgargs[j]) != 0)
1979 if (trig1->tgqual == NULL && trig2->tgqual == NULL)
1981 else if (trig1->tgqual == NULL || trig2->tgqual == NULL)
1983 else if (strcmp(trig1->tgqual, trig2->tgqual) != 0)
1985 if (trig1->tgoldtable == NULL && trig2->tgoldtable == NULL)
1987 else if (trig1->tgoldtable == NULL || trig2->tgoldtable == NULL)
1989 else if (strcmp(trig1->tgoldtable, trig2->tgoldtable) != 0)
1991 if (trig1->tgnewtable == NULL && trig2->tgnewtable == NULL)
1993 else if (trig1->tgnewtable == NULL || trig2->tgnewtable == NULL)
1995 else if (strcmp(trig1->tgnewtable, trig2->tgnewtable) != 0)
1999 else if (trigdesc2 != NULL)
2003 #endif /* NOT_USED */
2006 * Call a trigger function.
2008 * trigdata: trigger descriptor.
2009 * tgindx: trigger's index in finfo and instr arrays.
2010 * finfo: array of cached trigger function call information.
2011 * instr: optional array of EXPLAIN ANALYZE instrumentation state.
2012 * per_tuple_context: memory context to execute the function in.
2014 * Returns the tuple (or NULL) as returned by the function.
2017 ExecCallTriggerFunc(TriggerData *trigdata,
2020 Instrumentation *instr,
2021 MemoryContext per_tuple_context)
2023 FunctionCallInfoData fcinfo;
2024 PgStat_FunctionCallUsage fcusage;
2026 MemoryContext oldContext;
2029 * Protect against code paths that may fail to initialize transition table
2032 Assert(((TRIGGER_FIRED_BY_INSERT(trigdata->tg_event) ||
2033 TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event) ||
2034 TRIGGER_FIRED_BY_DELETE(trigdata->tg_event)) &&
2035 TRIGGER_FIRED_AFTER(trigdata->tg_event) &&
2036 !(trigdata->tg_event & AFTER_TRIGGER_DEFERRABLE) &&
2037 !(trigdata->tg_event & AFTER_TRIGGER_INITDEFERRED)) ||
2038 (trigdata->tg_oldtable == NULL && trigdata->tg_newtable == NULL));
2043 * We cache fmgr lookup info, to avoid making the lookup again on each
2046 if (finfo->fn_oid == InvalidOid)
2047 fmgr_info(trigdata->tg_trigger->tgfoid, finfo);
2049 Assert(finfo->fn_oid == trigdata->tg_trigger->tgfoid);
2052 * If doing EXPLAIN ANALYZE, start charging time to this trigger.
2055 InstrStartNode(instr + tgindx);
2058 * Do the function evaluation in the per-tuple memory context, so that
2059 * leaked memory will be reclaimed once per tuple. Note in particular that
2060 * any new tuple created by the trigger function will live till the end of
2063 oldContext = MemoryContextSwitchTo(per_tuple_context);
2066 * Call the function, passing no arguments but setting a context.
2068 InitFunctionCallInfoData(fcinfo, finfo, 0,
2069 InvalidOid, (Node *) trigdata, NULL);
2071 pgstat_init_function_usage(&fcinfo, &fcusage);
2076 result = FunctionCallInvoke(&fcinfo);
2086 pgstat_end_function_usage(&fcusage, true);
2088 MemoryContextSwitchTo(oldContext);
2091 * Trigger protocol allows function to return a null pointer, but NOT to
2092 * set the isnull result flag.
2096 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2097 errmsg("trigger function %u returned null value",
2098 fcinfo.flinfo->fn_oid)));
2101 * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
2102 * one "tuple returned" (really the number of firings).
2105 InstrStopNode(instr + tgindx, 1);
2107 return (HeapTuple) DatumGetPointer(result);
2111 ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
2113 TriggerDesc *trigdesc;
2115 TriggerData LocTriggerData;
2117 trigdesc = relinfo->ri_TrigDesc;
2119 if (trigdesc == NULL)
2121 if (!trigdesc->trig_insert_before_statement)
2124 LocTriggerData.type = T_TriggerData;
2125 LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
2126 TRIGGER_EVENT_BEFORE;
2127 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2128 LocTriggerData.tg_trigtuple = NULL;
2129 LocTriggerData.tg_newtuple = NULL;
2130 LocTriggerData.tg_oldtable = NULL;
2131 LocTriggerData.tg_newtable = NULL;
2132 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2133 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2134 for (i = 0; i < trigdesc->numtriggers; i++)
2136 Trigger *trigger = &trigdesc->triggers[i];
2139 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2140 TRIGGER_TYPE_STATEMENT,
2141 TRIGGER_TYPE_BEFORE,
2142 TRIGGER_TYPE_INSERT))
2144 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2148 LocTriggerData.tg_trigger = trigger;
2149 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2151 relinfo->ri_TrigFunctions,
2152 relinfo->ri_TrigInstrument,
2153 GetPerTupleMemoryContext(estate));
2157 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2158 errmsg("BEFORE STATEMENT trigger cannot return a value")));
2163 ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo)
2165 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2167 if (trigdesc && trigdesc->trig_insert_after_statement)
2168 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_INSERT,
2169 false, NULL, NULL, NIL, NULL);
2173 ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
2174 TupleTableSlot *slot)
2176 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2177 HeapTuple slottuple = ExecMaterializeSlot(slot);
2178 HeapTuple newtuple = slottuple;
2180 TriggerData LocTriggerData;
2183 LocTriggerData.type = T_TriggerData;
2184 LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
2186 TRIGGER_EVENT_BEFORE;
2187 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2188 LocTriggerData.tg_newtuple = NULL;
2189 LocTriggerData.tg_oldtable = NULL;
2190 LocTriggerData.tg_newtable = NULL;
2191 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2192 for (i = 0; i < trigdesc->numtriggers; i++)
2194 Trigger *trigger = &trigdesc->triggers[i];
2196 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2198 TRIGGER_TYPE_BEFORE,
2199 TRIGGER_TYPE_INSERT))
2201 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2202 NULL, NULL, newtuple))
2205 LocTriggerData.tg_trigtuple = oldtuple = newtuple;
2206 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2207 LocTriggerData.tg_trigger = trigger;
2208 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2210 relinfo->ri_TrigFunctions,
2211 relinfo->ri_TrigInstrument,
2212 GetPerTupleMemoryContext(estate));
2213 if (oldtuple != newtuple && oldtuple != slottuple)
2214 heap_freetuple(oldtuple);
2215 if (newtuple == NULL)
2216 return NULL; /* "do nothing" */
2219 if (newtuple != slottuple)
2222 * Return the modified tuple using the es_trig_tuple_slot. We assume
2223 * the tuple was allocated in per-tuple memory context, and therefore
2224 * will go away by itself. The tuple table slot should not try to
2227 TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2228 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2230 if (newslot->tts_tupleDescriptor != tupdesc)
2231 ExecSetSlotDescriptor(newslot, tupdesc);
2232 ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2239 ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo,
2240 HeapTuple trigtuple, List *recheckIndexes)
2242 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2245 (trigdesc->trig_insert_after_row || trigdesc->trig_insert_new_table))
2246 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_INSERT,
2247 true, NULL, trigtuple, recheckIndexes, NULL);
2251 ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
2252 TupleTableSlot *slot)
2254 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2255 HeapTuple slottuple = ExecMaterializeSlot(slot);
2256 HeapTuple newtuple = slottuple;
2258 TriggerData LocTriggerData;
2261 LocTriggerData.type = T_TriggerData;
2262 LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
2264 TRIGGER_EVENT_INSTEAD;
2265 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2266 LocTriggerData.tg_newtuple = NULL;
2267 LocTriggerData.tg_oldtable = NULL;
2268 LocTriggerData.tg_newtable = NULL;
2269 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2270 for (i = 0; i < trigdesc->numtriggers; i++)
2272 Trigger *trigger = &trigdesc->triggers[i];
2274 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2276 TRIGGER_TYPE_INSTEAD,
2277 TRIGGER_TYPE_INSERT))
2279 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2280 NULL, NULL, newtuple))
2283 LocTriggerData.tg_trigtuple = oldtuple = newtuple;
2284 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2285 LocTriggerData.tg_trigger = trigger;
2286 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2288 relinfo->ri_TrigFunctions,
2289 relinfo->ri_TrigInstrument,
2290 GetPerTupleMemoryContext(estate));
2291 if (oldtuple != newtuple && oldtuple != slottuple)
2292 heap_freetuple(oldtuple);
2293 if (newtuple == NULL)
2294 return NULL; /* "do nothing" */
2297 if (newtuple != slottuple)
2300 * Return the modified tuple using the es_trig_tuple_slot. We assume
2301 * the tuple was allocated in per-tuple memory context, and therefore
2302 * will go away by itself. The tuple table slot should not try to
2305 TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2306 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2308 if (newslot->tts_tupleDescriptor != tupdesc)
2309 ExecSetSlotDescriptor(newslot, tupdesc);
2310 ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2317 ExecBSDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
2319 TriggerDesc *trigdesc;
2321 TriggerData LocTriggerData;
2323 trigdesc = relinfo->ri_TrigDesc;
2325 if (trigdesc == NULL)
2327 if (!trigdesc->trig_delete_before_statement)
2330 LocTriggerData.type = T_TriggerData;
2331 LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
2332 TRIGGER_EVENT_BEFORE;
2333 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2334 LocTriggerData.tg_trigtuple = NULL;
2335 LocTriggerData.tg_newtuple = NULL;
2336 LocTriggerData.tg_oldtable = NULL;
2337 LocTriggerData.tg_newtable = NULL;
2338 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2339 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2340 for (i = 0; i < trigdesc->numtriggers; i++)
2342 Trigger *trigger = &trigdesc->triggers[i];
2345 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2346 TRIGGER_TYPE_STATEMENT,
2347 TRIGGER_TYPE_BEFORE,
2348 TRIGGER_TYPE_DELETE))
2350 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2354 LocTriggerData.tg_trigger = trigger;
2355 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2357 relinfo->ri_TrigFunctions,
2358 relinfo->ri_TrigInstrument,
2359 GetPerTupleMemoryContext(estate));
2363 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2364 errmsg("BEFORE STATEMENT trigger cannot return a value")));
2369 ExecASDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
2371 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2373 if (trigdesc && trigdesc->trig_delete_after_statement)
2374 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_DELETE,
2375 false, NULL, NULL, NIL, NULL);
2379 ExecBRDeleteTriggers(EState *estate, EPQState *epqstate,
2380 ResultRelInfo *relinfo,
2381 ItemPointer tupleid,
2382 HeapTuple fdw_trigtuple)
2384 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2386 TriggerData LocTriggerData;
2387 HeapTuple trigtuple;
2389 TupleTableSlot *newSlot;
2392 Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2393 if (fdw_trigtuple == NULL)
2395 trigtuple = GetTupleForTrigger(estate, epqstate, relinfo, tupleid,
2396 LockTupleExclusive, &newSlot);
2397 if (trigtuple == NULL)
2401 trigtuple = fdw_trigtuple;
2403 LocTriggerData.type = T_TriggerData;
2404 LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
2406 TRIGGER_EVENT_BEFORE;
2407 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2408 LocTriggerData.tg_newtuple = NULL;
2409 LocTriggerData.tg_oldtable = NULL;
2410 LocTriggerData.tg_newtable = NULL;
2411 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2412 for (i = 0; i < trigdesc->numtriggers; i++)
2414 Trigger *trigger = &trigdesc->triggers[i];
2416 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2418 TRIGGER_TYPE_BEFORE,
2419 TRIGGER_TYPE_DELETE))
2421 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2422 NULL, trigtuple, NULL))
2425 LocTriggerData.tg_trigtuple = trigtuple;
2426 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2427 LocTriggerData.tg_trigger = trigger;
2428 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2430 relinfo->ri_TrigFunctions,
2431 relinfo->ri_TrigInstrument,
2432 GetPerTupleMemoryContext(estate));
2433 if (newtuple == NULL)
2435 result = false; /* tell caller to suppress delete */
2438 if (newtuple != trigtuple)
2439 heap_freetuple(newtuple);
2441 if (trigtuple != fdw_trigtuple)
2442 heap_freetuple(trigtuple);
2448 ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
2449 ItemPointer tupleid,
2450 HeapTuple fdw_trigtuple)
2452 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2455 (trigdesc->trig_delete_after_row || trigdesc->trig_delete_old_table))
2457 HeapTuple trigtuple;
2459 Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2460 if (fdw_trigtuple == NULL)
2461 trigtuple = GetTupleForTrigger(estate,
2468 trigtuple = fdw_trigtuple;
2470 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_DELETE,
2471 true, trigtuple, NULL, NIL, NULL);
2472 if (trigtuple != fdw_trigtuple)
2473 heap_freetuple(trigtuple);
2478 ExecIRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
2479 HeapTuple trigtuple)
2481 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2482 TriggerData LocTriggerData;
2486 LocTriggerData.type = T_TriggerData;
2487 LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
2489 TRIGGER_EVENT_INSTEAD;
2490 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2491 LocTriggerData.tg_newtuple = NULL;
2492 LocTriggerData.tg_oldtable = NULL;
2493 LocTriggerData.tg_newtable = NULL;
2494 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2495 for (i = 0; i < trigdesc->numtriggers; i++)
2497 Trigger *trigger = &trigdesc->triggers[i];
2499 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2501 TRIGGER_TYPE_INSTEAD,
2502 TRIGGER_TYPE_DELETE))
2504 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2505 NULL, trigtuple, NULL))
2508 LocTriggerData.tg_trigtuple = trigtuple;
2509 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2510 LocTriggerData.tg_trigger = trigger;
2511 rettuple = ExecCallTriggerFunc(&LocTriggerData,
2513 relinfo->ri_TrigFunctions,
2514 relinfo->ri_TrigInstrument,
2515 GetPerTupleMemoryContext(estate));
2516 if (rettuple == NULL)
2517 return false; /* Delete was suppressed */
2518 if (rettuple != trigtuple)
2519 heap_freetuple(rettuple);
2525 ExecBSUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
2527 TriggerDesc *trigdesc;
2529 TriggerData LocTriggerData;
2530 Bitmapset *updatedCols;
2532 trigdesc = relinfo->ri_TrigDesc;
2534 if (trigdesc == NULL)
2536 if (!trigdesc->trig_update_before_statement)
2539 updatedCols = GetUpdatedColumns(relinfo, estate);
2541 LocTriggerData.type = T_TriggerData;
2542 LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
2543 TRIGGER_EVENT_BEFORE;
2544 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2545 LocTriggerData.tg_trigtuple = NULL;
2546 LocTriggerData.tg_newtuple = NULL;
2547 LocTriggerData.tg_oldtable = NULL;
2548 LocTriggerData.tg_newtable = NULL;
2549 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2550 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2551 for (i = 0; i < trigdesc->numtriggers; i++)
2553 Trigger *trigger = &trigdesc->triggers[i];
2556 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2557 TRIGGER_TYPE_STATEMENT,
2558 TRIGGER_TYPE_BEFORE,
2559 TRIGGER_TYPE_UPDATE))
2561 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2562 updatedCols, NULL, NULL))
2565 LocTriggerData.tg_trigger = trigger;
2566 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2568 relinfo->ri_TrigFunctions,
2569 relinfo->ri_TrigInstrument,
2570 GetPerTupleMemoryContext(estate));
2574 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2575 errmsg("BEFORE STATEMENT trigger cannot return a value")));
2580 ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
2582 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2584 if (trigdesc && trigdesc->trig_update_after_statement)
2585 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_UPDATE,
2586 false, NULL, NULL, NIL,
2587 GetUpdatedColumns(relinfo, estate));
2591 ExecBRUpdateTriggers(EState *estate, EPQState *epqstate,
2592 ResultRelInfo *relinfo,
2593 ItemPointer tupleid,
2594 HeapTuple fdw_trigtuple,
2595 TupleTableSlot *slot)
2597 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2598 HeapTuple slottuple = ExecMaterializeSlot(slot);
2599 HeapTuple newtuple = slottuple;
2600 TriggerData LocTriggerData;
2601 HeapTuple trigtuple;
2603 TupleTableSlot *newSlot;
2605 Bitmapset *updatedCols;
2606 LockTupleMode lockmode;
2608 /* Determine lock mode to use */
2609 lockmode = ExecUpdateLockMode(estate, relinfo);
2611 Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2612 if (fdw_trigtuple == NULL)
2614 /* get a copy of the on-disk tuple we are planning to update */
2615 trigtuple = GetTupleForTrigger(estate, epqstate, relinfo, tupleid,
2616 lockmode, &newSlot);
2617 if (trigtuple == NULL)
2618 return NULL; /* cancel the update action */
2622 trigtuple = fdw_trigtuple;
2627 * In READ COMMITTED isolation level it's possible that target tuple was
2628 * changed due to concurrent update. In that case we have a raw subplan
2629 * output tuple in newSlot, and need to run it through the junk filter to
2630 * produce an insertable tuple.
2632 * Caution: more than likely, the passed-in slot is the same as the
2633 * junkfilter's output slot, so we are clobbering the original value of
2634 * slottuple by doing the filtering. This is OK since neither we nor our
2635 * caller have any more interest in the prior contents of that slot.
2637 if (newSlot != NULL)
2639 slot = ExecFilterJunk(relinfo->ri_junkFilter, newSlot);
2640 slottuple = ExecMaterializeSlot(slot);
2641 newtuple = slottuple;
2645 LocTriggerData.type = T_TriggerData;
2646 LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
2648 TRIGGER_EVENT_BEFORE;
2649 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2650 LocTriggerData.tg_oldtable = NULL;
2651 LocTriggerData.tg_newtable = NULL;
2652 updatedCols = GetUpdatedColumns(relinfo, estate);
2653 for (i = 0; i < trigdesc->numtriggers; i++)
2655 Trigger *trigger = &trigdesc->triggers[i];
2657 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2659 TRIGGER_TYPE_BEFORE,
2660 TRIGGER_TYPE_UPDATE))
2662 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2663 updatedCols, trigtuple, newtuple))
2666 LocTriggerData.tg_trigtuple = trigtuple;
2667 LocTriggerData.tg_newtuple = oldtuple = newtuple;
2668 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2669 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2670 LocTriggerData.tg_trigger = trigger;
2671 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2673 relinfo->ri_TrigFunctions,
2674 relinfo->ri_TrigInstrument,
2675 GetPerTupleMemoryContext(estate));
2676 if (oldtuple != newtuple && oldtuple != slottuple)
2677 heap_freetuple(oldtuple);
2678 if (newtuple == NULL)
2680 if (trigtuple != fdw_trigtuple)
2681 heap_freetuple(trigtuple);
2682 return NULL; /* "do nothing" */
2685 if (trigtuple != fdw_trigtuple)
2686 heap_freetuple(trigtuple);
2688 if (newtuple != slottuple)
2691 * Return the modified tuple using the es_trig_tuple_slot. We assume
2692 * the tuple was allocated in per-tuple memory context, and therefore
2693 * will go away by itself. The tuple table slot should not try to
2696 TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2697 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2699 if (newslot->tts_tupleDescriptor != tupdesc)
2700 ExecSetSlotDescriptor(newslot, tupdesc);
2701 ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2708 ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
2709 ItemPointer tupleid,
2710 HeapTuple fdw_trigtuple,
2712 List *recheckIndexes)
2714 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2716 if (trigdesc && (trigdesc->trig_update_after_row ||
2717 trigdesc->trig_update_old_table || trigdesc->trig_update_new_table))
2719 HeapTuple trigtuple;
2721 Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2722 if (fdw_trigtuple == NULL)
2723 trigtuple = GetTupleForTrigger(estate,
2730 trigtuple = fdw_trigtuple;
2732 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_UPDATE,
2733 true, trigtuple, newtuple, recheckIndexes,
2734 GetUpdatedColumns(relinfo, estate));
2735 if (trigtuple != fdw_trigtuple)
2736 heap_freetuple(trigtuple);
2741 ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
2742 HeapTuple trigtuple, TupleTableSlot *slot)
2744 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2745 HeapTuple slottuple = ExecMaterializeSlot(slot);
2746 HeapTuple newtuple = slottuple;
2747 TriggerData LocTriggerData;
2751 LocTriggerData.type = T_TriggerData;
2752 LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
2754 TRIGGER_EVENT_INSTEAD;
2755 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2756 LocTriggerData.tg_oldtable = NULL;
2757 LocTriggerData.tg_newtable = NULL;
2758 for (i = 0; i < trigdesc->numtriggers; i++)
2760 Trigger *trigger = &trigdesc->triggers[i];
2762 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2764 TRIGGER_TYPE_INSTEAD,
2765 TRIGGER_TYPE_UPDATE))
2767 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2768 NULL, trigtuple, newtuple))
2771 LocTriggerData.tg_trigtuple = trigtuple;
2772 LocTriggerData.tg_newtuple = oldtuple = newtuple;
2773 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2774 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2775 LocTriggerData.tg_trigger = trigger;
2776 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2778 relinfo->ri_TrigFunctions,
2779 relinfo->ri_TrigInstrument,
2780 GetPerTupleMemoryContext(estate));
2781 if (oldtuple != newtuple && oldtuple != slottuple)
2782 heap_freetuple(oldtuple);
2783 if (newtuple == NULL)
2784 return NULL; /* "do nothing" */
2787 if (newtuple != slottuple)
2790 * Return the modified tuple using the es_trig_tuple_slot. We assume
2791 * the tuple was allocated in per-tuple memory context, and therefore
2792 * will go away by itself. The tuple table slot should not try to
2795 TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2796 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2798 if (newslot->tts_tupleDescriptor != tupdesc)
2799 ExecSetSlotDescriptor(newslot, tupdesc);
2800 ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2807 ExecBSTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
2809 TriggerDesc *trigdesc;
2811 TriggerData LocTriggerData;
2813 trigdesc = relinfo->ri_TrigDesc;
2815 if (trigdesc == NULL)
2817 if (!trigdesc->trig_truncate_before_statement)
2820 LocTriggerData.type = T_TriggerData;
2821 LocTriggerData.tg_event = TRIGGER_EVENT_TRUNCATE |
2822 TRIGGER_EVENT_BEFORE;
2823 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2824 LocTriggerData.tg_trigtuple = NULL;
2825 LocTriggerData.tg_newtuple = NULL;
2826 LocTriggerData.tg_oldtable = NULL;
2827 LocTriggerData.tg_newtable = NULL;
2828 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2829 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2830 for (i = 0; i < trigdesc->numtriggers; i++)
2832 Trigger *trigger = &trigdesc->triggers[i];
2835 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2836 TRIGGER_TYPE_STATEMENT,
2837 TRIGGER_TYPE_BEFORE,
2838 TRIGGER_TYPE_TRUNCATE))
2840 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2844 LocTriggerData.tg_trigger = trigger;
2845 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2847 relinfo->ri_TrigFunctions,
2848 relinfo->ri_TrigInstrument,
2849 GetPerTupleMemoryContext(estate));
2853 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2854 errmsg("BEFORE STATEMENT trigger cannot return a value")));
2859 ExecASTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
2861 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2863 if (trigdesc && trigdesc->trig_truncate_after_statement)
2864 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_TRUNCATE,
2865 false, NULL, NULL, NIL, NULL);
2870 GetTupleForTrigger(EState *estate,
2872 ResultRelInfo *relinfo,
2874 LockTupleMode lockmode,
2875 TupleTableSlot **newSlot)
2877 Relation relation = relinfo->ri_RelationDesc;
2878 HeapTupleData tuple;
2882 if (newSlot != NULL)
2885 HeapUpdateFailureData hufd;
2889 /* caller must pass an epqstate if EvalPlanQual is possible */
2890 Assert(epqstate != NULL);
2893 * lock tuple for update
2896 tuple.t_self = *tid;
2897 test = heap_lock_tuple(relation, &tuple,
2898 estate->es_output_cid,
2899 lockmode, LockWaitBlock,
2900 false, &buffer, &hufd);
2903 case HeapTupleSelfUpdated:
2906 * The target tuple was already updated or deleted by the
2907 * current command, or by a later command in the current
2908 * transaction. We ignore the tuple in the former case, and
2909 * throw error in the latter case, for the same reasons
2910 * enumerated in ExecUpdate and ExecDelete in
2911 * nodeModifyTable.c.
2913 if (hufd.cmax != estate->es_output_cid)
2915 (errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
2916 errmsg("tuple to be updated was already modified by an operation triggered by the current command"),
2917 errhint("Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
2919 /* treat it as deleted; do not process */
2920 ReleaseBuffer(buffer);
2923 case HeapTupleMayBeUpdated:
2926 case HeapTupleUpdated:
2927 ReleaseBuffer(buffer);
2928 if (IsolationUsesXactSnapshot())
2930 (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
2931 errmsg("could not serialize access due to concurrent update")));
2932 if (!ItemPointerEquals(&hufd.ctid, &tuple.t_self))
2934 /* it was updated, so look at the updated version */
2935 TupleTableSlot *epqslot;
2937 epqslot = EvalPlanQual(estate,
2940 relinfo->ri_RangeTableIndex,
2944 if (!TupIsNull(epqslot))
2950 * EvalPlanQual already locked the tuple, but we
2951 * re-call heap_lock_tuple anyway as an easy way of
2952 * re-fetching the correct tuple. Speed is hardly a
2953 * criterion in this path anyhow.
2960 * if tuple was deleted or PlanQual failed for updated tuple -
2961 * we must not process this tuple!
2965 case HeapTupleInvisible:
2966 elog(ERROR, "attempted to lock invisible tuple");
2969 ReleaseBuffer(buffer);
2970 elog(ERROR, "unrecognized heap_lock_tuple status: %u", test);
2971 return NULL; /* keep compiler quiet */
2979 buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
2982 * Although we already know this tuple is valid, we must lock the
2983 * buffer to ensure that no one has a buffer cleanup lock; otherwise
2984 * they might move the tuple while we try to copy it. But we can
2985 * release the lock before actually doing the heap_copytuple call,
2986 * since holding pin is sufficient to prevent anyone from getting a
2987 * cleanup lock they don't already hold.
2989 LockBuffer(buffer, BUFFER_LOCK_SHARE);
2991 page = BufferGetPage(buffer);
2992 lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
2994 Assert(ItemIdIsNormal(lp));
2996 tuple.t_data = (HeapTupleHeader) PageGetItem(page, lp);
2997 tuple.t_len = ItemIdGetLength(lp);
2998 tuple.t_self = *tid;
2999 tuple.t_tableOid = RelationGetRelid(relation);
3001 LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3004 result = heap_copytuple(&tuple);
3005 ReleaseBuffer(buffer);
3011 * Is trigger enabled to fire?
3014 TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
3015 Trigger *trigger, TriggerEvent event,
3016 Bitmapset *modifiedCols,
3017 HeapTuple oldtup, HeapTuple newtup)
3019 /* Check replication-role-dependent enable state */
3020 if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
3022 if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
3023 trigger->tgenabled == TRIGGER_DISABLED)
3026 else /* ORIGIN or LOCAL role */
3028 if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
3029 trigger->tgenabled == TRIGGER_DISABLED)
3034 * Check for column-specific trigger (only possible for UPDATE, and in
3035 * fact we *must* ignore tgattr for other event types)
3037 if (trigger->tgnattr > 0 && TRIGGER_FIRED_BY_UPDATE(event))
3043 for (i = 0; i < trigger->tgnattr; i++)
3045 if (bms_is_member(trigger->tgattr[i] - FirstLowInvalidHeapAttributeNumber,
3056 /* Check for WHEN clause */
3057 if (trigger->tgqual)
3059 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
3060 ExprState **predicate;
3061 ExprContext *econtext;
3062 TupleTableSlot *oldslot = NULL;
3063 TupleTableSlot *newslot = NULL;
3064 MemoryContext oldContext;
3067 Assert(estate != NULL);
3070 * trigger is an element of relinfo->ri_TrigDesc->triggers[]; find the
3071 * matching element of relinfo->ri_TrigWhenExprs[]
3073 i = trigger - relinfo->ri_TrigDesc->triggers;
3074 predicate = &relinfo->ri_TrigWhenExprs[i];
3077 * If first time through for this WHEN expression, build expression
3078 * nodetrees for it. Keep them in the per-query memory context so
3079 * they'll survive throughout the query.
3081 if (*predicate == NULL)
3085 oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
3086 tgqual = stringToNode(trigger->tgqual);
3087 /* Change references to OLD and NEW to INNER_VAR and OUTER_VAR */
3088 ChangeVarNodes(tgqual, PRS2_OLD_VARNO, INNER_VAR, 0);
3089 ChangeVarNodes(tgqual, PRS2_NEW_VARNO, OUTER_VAR, 0);
3090 /* ExecPrepareQual wants implicit-AND form */
3091 tgqual = (Node *) make_ands_implicit((Expr *) tgqual);
3092 *predicate = ExecPrepareQual((List *) tgqual, estate);
3093 MemoryContextSwitchTo(oldContext);
3097 * We will use the EState's per-tuple context for evaluating WHEN
3098 * expressions (creating it if it's not already there).
3100 econtext = GetPerTupleExprContext(estate);
3103 * Put OLD and NEW tuples into tupleslots for expression evaluation.
3104 * These slots can be shared across the whole estate, but be careful
3105 * that they have the current resultrel's tupdesc.
3107 if (HeapTupleIsValid(oldtup))
3109 if (estate->es_trig_oldtup_slot == NULL)
3111 oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
3112 estate->es_trig_oldtup_slot = ExecInitExtraTupleSlot(estate);
3113 MemoryContextSwitchTo(oldContext);
3115 oldslot = estate->es_trig_oldtup_slot;
3116 if (oldslot->tts_tupleDescriptor != tupdesc)
3117 ExecSetSlotDescriptor(oldslot, tupdesc);
3118 ExecStoreTuple(oldtup, oldslot, InvalidBuffer, false);
3120 if (HeapTupleIsValid(newtup))
3122 if (estate->es_trig_newtup_slot == NULL)
3124 oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
3125 estate->es_trig_newtup_slot = ExecInitExtraTupleSlot(estate);
3126 MemoryContextSwitchTo(oldContext);
3128 newslot = estate->es_trig_newtup_slot;
3129 if (newslot->tts_tupleDescriptor != tupdesc)
3130 ExecSetSlotDescriptor(newslot, tupdesc);
3131 ExecStoreTuple(newtup, newslot, InvalidBuffer, false);
3135 * Finally evaluate the expression, making the old and/or new tuples
3136 * available as INNER_VAR/OUTER_VAR respectively.
3138 econtext->ecxt_innertuple = oldslot;
3139 econtext->ecxt_outertuple = newslot;
3140 if (!ExecQual(*predicate, econtext))
3149 * After-trigger stuff
3151 * The AfterTriggersData struct holds data about pending AFTER trigger events
3152 * during the current transaction tree. (BEFORE triggers are fired
3153 * immediately so we don't need any persistent state about them.) The struct
3154 * and most of its subsidiary data are kept in TopTransactionContext; however
3155 * the individual event records are kept in a separate sub-context. This is
3156 * done mainly so that it's easy to tell from a memory context dump how much
3157 * space is being eaten by trigger events.
3159 * Because the list of pending events can grow large, we go to some
3160 * considerable effort to minimize per-event memory consumption. The event
3161 * records are grouped into chunks and common data for similar events in the
3162 * same chunk is only stored once.
3164 * XXX We need to be able to save the per-event data in a file if it grows too
3169 /* Per-trigger SET CONSTRAINT status */
3170 typedef struct SetConstraintTriggerData
3173 bool sct_tgisdeferred;
3174 } SetConstraintTriggerData;
3176 typedef struct SetConstraintTriggerData *SetConstraintTrigger;
3179 * SET CONSTRAINT intra-transaction status.
3181 * We make this a single palloc'd object so it can be copied and freed easily.
3183 * all_isset and all_isdeferred are used to keep track
3184 * of SET CONSTRAINTS ALL {DEFERRED, IMMEDIATE}.
3186 * trigstates[] stores per-trigger tgisdeferred settings.
3188 typedef struct SetConstraintStateData
3191 bool all_isdeferred;
3192 int numstates; /* number of trigstates[] entries in use */
3193 int numalloc; /* allocated size of trigstates[] */
3194 SetConstraintTriggerData trigstates[FLEXIBLE_ARRAY_MEMBER];
3195 } SetConstraintStateData;
3197 typedef SetConstraintStateData *SetConstraintState;
3201 * Per-trigger-event data
3203 * The actual per-event data, AfterTriggerEventData, includes DONE/IN_PROGRESS
3204 * status bits and up to two tuple CTIDs. Each event record also has an
3205 * associated AfterTriggerSharedData that is shared across all instances of
3206 * similar events within a "chunk".
3208 * For row-level triggers, we arrange not to waste storage on unneeded ctid
3209 * fields. Updates of regular tables use two; inserts and deletes of regular
3210 * tables use one; foreign tables always use zero and save the tuple(s) to a
3211 * tuplestore. AFTER_TRIGGER_FDW_FETCH directs AfterTriggerExecute() to
3212 * retrieve a fresh tuple or pair of tuples from that tuplestore, while
3213 * AFTER_TRIGGER_FDW_REUSE directs it to use the most-recently-retrieved
3214 * tuple(s). This permits storing tuples once regardless of the number of
3215 * row-level triggers on a foreign table.
3217 * Statement-level triggers always bear AFTER_TRIGGER_1CTID, though they
3218 * require no ctid field. We lack the flag bit space to neatly represent that
3219 * distinct case, and it seems unlikely to be worth much trouble.
3221 * Note: ats_firing_id is initially zero and is set to something else when
3222 * AFTER_TRIGGER_IN_PROGRESS is set. It indicates which trigger firing
3223 * cycle the trigger will be fired in (or was fired in, if DONE is set).
3224 * Although this is mutable state, we can keep it in AfterTriggerSharedData
3225 * because all instances of the same type of event in a given event list will
3226 * be fired at the same time, if they were queued between the same firing
3227 * cycles. So we need only ensure that ats_firing_id is zero when attaching
3228 * a new event to an existing AfterTriggerSharedData record.
3230 typedef uint32 TriggerFlags;
3232 #define AFTER_TRIGGER_OFFSET 0x0FFFFFFF /* must be low-order
3234 #define AFTER_TRIGGER_DONE 0x10000000
3235 #define AFTER_TRIGGER_IN_PROGRESS 0x20000000
3236 /* bits describing the size and tuple sources of this event */
3237 #define AFTER_TRIGGER_FDW_REUSE 0x00000000
3238 #define AFTER_TRIGGER_FDW_FETCH 0x80000000
3239 #define AFTER_TRIGGER_1CTID 0x40000000
3240 #define AFTER_TRIGGER_2CTID 0xC0000000
3241 #define AFTER_TRIGGER_TUP_BITS 0xC0000000
3243 typedef struct AfterTriggerSharedData *AfterTriggerShared;
3245 typedef struct AfterTriggerSharedData
3247 TriggerEvent ats_event; /* event type indicator, see trigger.h */
3248 Oid ats_tgoid; /* the trigger's ID */
3249 Oid ats_relid; /* the relation it's on */
3250 CommandId ats_firing_id; /* ID for firing cycle */
3251 } AfterTriggerSharedData;
3253 typedef struct AfterTriggerEventData *AfterTriggerEvent;
3255 typedef struct AfterTriggerEventData
3257 TriggerFlags ate_flags; /* status bits and offset to shared data */
3258 ItemPointerData ate_ctid1; /* inserted, deleted, or old updated tuple */
3259 ItemPointerData ate_ctid2; /* new updated tuple */
3260 } AfterTriggerEventData;
3262 /* AfterTriggerEventData, minus ate_ctid2 */
3263 typedef struct AfterTriggerEventDataOneCtid
3265 TriggerFlags ate_flags; /* status bits and offset to shared data */
3266 ItemPointerData ate_ctid1; /* inserted, deleted, or old updated tuple */
3267 } AfterTriggerEventDataOneCtid;
3269 /* AfterTriggerEventData, minus ate_ctid1 and ate_ctid2 */
3270 typedef struct AfterTriggerEventDataZeroCtids
3272 TriggerFlags ate_flags; /* status bits and offset to shared data */
3273 } AfterTriggerEventDataZeroCtids;
3275 #define SizeofTriggerEvent(evt) \
3276 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_2CTID ? \
3277 sizeof(AfterTriggerEventData) : \
3278 ((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_1CTID ? \
3279 sizeof(AfterTriggerEventDataOneCtid) : \
3280 sizeof(AfterTriggerEventDataZeroCtids))
3282 #define GetTriggerSharedData(evt) \
3283 ((AfterTriggerShared) ((char *) (evt) + ((evt)->ate_flags & AFTER_TRIGGER_OFFSET)))
3286 * To avoid palloc overhead, we keep trigger events in arrays in successively-
3287 * larger chunks (a slightly more sophisticated version of an expansible
3288 * array). The space between CHUNK_DATA_START and freeptr is occupied by
3289 * AfterTriggerEventData records; the space between endfree and endptr is
3290 * occupied by AfterTriggerSharedData records.
3292 typedef struct AfterTriggerEventChunk
3294 struct AfterTriggerEventChunk *next; /* list link */
3295 char *freeptr; /* start of free space in chunk */
3296 char *endfree; /* end of free space in chunk */
3297 char *endptr; /* end of chunk */
3298 /* event data follows here */
3299 } AfterTriggerEventChunk;
3301 #define CHUNK_DATA_START(cptr) ((char *) (cptr) + MAXALIGN(sizeof(AfterTriggerEventChunk)))
3303 /* A list of events */
3304 typedef struct AfterTriggerEventList
3306 AfterTriggerEventChunk *head;
3307 AfterTriggerEventChunk *tail;
3308 char *tailfree; /* freeptr of tail chunk */
3309 } AfterTriggerEventList;
3311 /* Macros to help in iterating over a list of events */
3312 #define for_each_chunk(cptr, evtlist) \
3313 for (cptr = (evtlist).head; cptr != NULL; cptr = cptr->next)
3314 #define for_each_event(eptr, cptr) \
3315 for (eptr = (AfterTriggerEvent) CHUNK_DATA_START(cptr); \
3316 (char *) eptr < (cptr)->freeptr; \
3317 eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
3318 /* Use this if no special per-chunk processing is needed */
3319 #define for_each_event_chunk(eptr, cptr, evtlist) \
3320 for_each_chunk(cptr, evtlist) for_each_event(eptr, cptr)
3324 * All per-transaction data for the AFTER TRIGGERS module.
3326 * AfterTriggersData has the following fields:
3328 * firing_counter is incremented for each call of afterTriggerInvokeEvents.
3329 * We mark firable events with the current firing cycle's ID so that we can
3330 * tell which ones to work on. This ensures sane behavior if a trigger
3331 * function chooses to do SET CONSTRAINTS: the inner SET CONSTRAINTS will
3332 * only fire those events that weren't already scheduled for firing.
3334 * state keeps track of the transaction-local effects of SET CONSTRAINTS.
3335 * This is saved and restored across failed subtransactions.
3337 * events is the current list of deferred events. This is global across
3338 * all subtransactions of the current transaction. In a subtransaction
3339 * abort, we know that the events added by the subtransaction are at the
3340 * end of the list, so it is relatively easy to discard them. The event
3341 * list chunks themselves are stored in event_cxt.
3343 * query_depth is the current depth of nested AfterTriggerBeginQuery calls
3344 * (-1 when the stack is empty).
3346 * query_stack[query_depth] is a list of AFTER trigger events queued by the
3347 * current query (and the query_stack entries below it are lists of trigger
3348 * events queued by calling queries). None of these are valid until the
3349 * matching AfterTriggerEndQuery call occurs. At that point we fire
3350 * immediate-mode triggers, and append any deferred events to the main events
3353 * fdw_tuplestores[query_depth] is a tuplestore containing the foreign tuples
3354 * needed for the current query.
3356 * old_tuplestores[query_depth] and new_tuplestores[query_depth] hold the
3357 * transition relations for the current query.
3359 * maxquerydepth is just the allocated length of query_stack and the
3362 * state_stack is a stack of pointers to saved copies of the SET CONSTRAINTS
3363 * state data; each subtransaction level that modifies that state first
3364 * saves a copy, which we use to restore the state if we abort.
3366 * events_stack is a stack of copies of the events head/tail pointers,
3367 * which we use to restore those values during subtransaction abort.
3369 * depth_stack is a stack of copies of subtransaction-start-time query_depth,
3370 * which we similarly use to clean up at subtransaction abort.
3372 * firing_stack is a stack of copies of subtransaction-start-time
3373 * firing_counter. We use this to recognize which deferred triggers were
3374 * fired (or marked for firing) within an aborted subtransaction.
3376 * We use GetCurrentTransactionNestLevel() to determine the correct array
3377 * index in these stacks. maxtransdepth is the number of allocated entries in
3378 * each stack. (By not keeping our own stack pointer, we can avoid trouble
3379 * in cases where errors during subxact abort cause multiple invocations
3380 * of AfterTriggerEndSubXact() at the same nesting depth.)
3382 typedef struct AfterTriggersData
3384 CommandId firing_counter; /* next firing ID to assign */
3385 SetConstraintState state; /* the active S C state */
3386 AfterTriggerEventList events; /* deferred-event list */
3387 int query_depth; /* current query list index */
3388 AfterTriggerEventList *query_stack; /* events pending from each query */
3389 Tuplestorestate **fdw_tuplestores; /* foreign tuples for one row from each query */
3390 Tuplestorestate **old_tuplestores; /* all old tuples from each query */
3391 Tuplestorestate **new_tuplestores; /* all new tuples from each query */
3392 int maxquerydepth; /* allocated len of above array */
3393 MemoryContext event_cxt; /* memory context for events, if any */
3395 /* these fields are just for resetting at subtrans abort: */
3397 SetConstraintState *state_stack; /* stacked S C states */
3398 AfterTriggerEventList *events_stack; /* stacked list pointers */
3399 int *depth_stack; /* stacked query_depths */
3400 CommandId *firing_stack; /* stacked firing_counters */
3401 int maxtransdepth; /* allocated len of above arrays */
3402 } AfterTriggersData;
3404 static AfterTriggersData afterTriggers;
3406 static void AfterTriggerExecute(AfterTriggerEvent event,
3407 Relation rel, TriggerDesc *trigdesc,
3409 Instrumentation *instr,
3410 MemoryContext per_tuple_context,
3411 TupleTableSlot *trig_tuple_slot1,
3412 TupleTableSlot *trig_tuple_slot2);
3413 static SetConstraintState SetConstraintStateCreate(int numalloc);
3414 static SetConstraintState SetConstraintStateCopy(SetConstraintState state);
3415 static SetConstraintState SetConstraintStateAddItem(SetConstraintState state,
3416 Oid tgoid, bool tgisdeferred);
3420 * Gets a current query transition tuplestore and initializes it if necessary.
3421 * This can be holding a single transition row tuple (in the case of an FDW)
3422 * or a transition table (for an AFTER trigger).
3424 static Tuplestorestate *
3425 GetTriggerTransitionTuplestore(Tuplestorestate **tss)
3427 Tuplestorestate *ret;
3429 ret = tss[afterTriggers.query_depth];
3432 MemoryContext oldcxt;
3433 ResourceOwner saveResourceOwner;
3436 * Make the tuplestore valid until end of transaction. This is the
3437 * allocation lifespan of the associated events list, but we really
3438 * only need it until AfterTriggerEndQuery().
3440 oldcxt = MemoryContextSwitchTo(TopTransactionContext);
3441 saveResourceOwner = CurrentResourceOwner;
3444 CurrentResourceOwner = TopTransactionResourceOwner;
3445 ret = tuplestore_begin_heap(false, false, work_mem);
3449 CurrentResourceOwner = saveResourceOwner;
3453 CurrentResourceOwner = saveResourceOwner;
3454 MemoryContextSwitchTo(oldcxt);
3456 tss[afterTriggers.query_depth] = ret;
3463 * afterTriggerCheckState()
3465 * Returns true if the trigger event is actually in state DEFERRED.
3469 afterTriggerCheckState(AfterTriggerShared evtshared)
3471 Oid tgoid = evtshared->ats_tgoid;
3472 SetConstraintState state = afterTriggers.state;
3476 * For not-deferrable triggers (i.e. normal AFTER ROW triggers and
3477 * constraints declared NOT DEFERRABLE), the state is always false.
3479 if ((evtshared->ats_event & AFTER_TRIGGER_DEFERRABLE) == 0)
3483 * If constraint state exists, SET CONSTRAINTS might have been executed
3484 * either for this trigger or for all triggers.
3488 /* Check for SET CONSTRAINTS for this specific trigger. */
3489 for (i = 0; i < state->numstates; i++)
3491 if (state->trigstates[i].sct_tgoid == tgoid)
3492 return state->trigstates[i].sct_tgisdeferred;
3495 /* Check for SET CONSTRAINTS ALL. */
3496 if (state->all_isset)
3497 return state->all_isdeferred;
3501 * Otherwise return the default state for the trigger.
3503 return ((evtshared->ats_event & AFTER_TRIGGER_INITDEFERRED) != 0);
3508 * afterTriggerAddEvent()
3510 * Add a new trigger event to the specified queue.
3511 * The passed-in event data is copied.
3515 afterTriggerAddEvent(AfterTriggerEventList *events,
3516 AfterTriggerEvent event, AfterTriggerShared evtshared)
3518 Size eventsize = SizeofTriggerEvent(event);
3519 Size needed = eventsize + sizeof(AfterTriggerSharedData);
3520 AfterTriggerEventChunk *chunk;
3521 AfterTriggerShared newshared;
3522 AfterTriggerEvent newevent;
3525 * If empty list or not enough room in the tail chunk, make a new chunk.
3526 * We assume here that a new shared record will always be needed.
3528 chunk = events->tail;
3529 if (chunk == NULL ||
3530 chunk->endfree - chunk->freeptr < needed)
3534 /* Create event context if we didn't already */
3535 if (afterTriggers.event_cxt == NULL)
3536 afterTriggers.event_cxt =
3537 AllocSetContextCreate(TopTransactionContext,
3538 "AfterTriggerEvents",
3539 ALLOCSET_DEFAULT_SIZES);
3542 * Chunk size starts at 1KB and is allowed to increase up to 1MB.
3543 * These numbers are fairly arbitrary, though there is a hard limit at
3544 * AFTER_TRIGGER_OFFSET; else we couldn't link event records to their
3545 * shared records using the available space in ate_flags. Another
3546 * constraint is that if the chunk size gets too huge, the search loop
3547 * below would get slow given a (not too common) usage pattern with
3548 * many distinct event types in a chunk. Therefore, we double the
3549 * preceding chunk size only if there weren't too many shared records
3550 * in the preceding chunk; otherwise we halve it. This gives us some
3551 * ability to adapt to the actual usage pattern of the current query
3552 * while still having large chunk sizes in typical usage. All chunk
3553 * sizes used should be MAXALIGN multiples, to ensure that the shared
3554 * records will be aligned safely.
3556 #define MIN_CHUNK_SIZE 1024
3557 #define MAX_CHUNK_SIZE (1024*1024)
3559 #if MAX_CHUNK_SIZE > (AFTER_TRIGGER_OFFSET+1)
3560 #error MAX_CHUNK_SIZE must not exceed AFTER_TRIGGER_OFFSET
3564 chunksize = MIN_CHUNK_SIZE;
3567 /* preceding chunk size... */
3568 chunksize = chunk->endptr - (char *) chunk;
3569 /* check number of shared records in preceding chunk */
3570 if ((chunk->endptr - chunk->endfree) <=
3571 (100 * sizeof(AfterTriggerSharedData)))
3572 chunksize *= 2; /* okay, double it */
3574 chunksize /= 2; /* too many shared records */
3575 chunksize = Min(chunksize, MAX_CHUNK_SIZE);
3577 chunk = MemoryContextAlloc(afterTriggers.event_cxt, chunksize);
3579 chunk->freeptr = CHUNK_DATA_START(chunk);
3580 chunk->endptr = chunk->endfree = (char *) chunk + chunksize;
3581 Assert(chunk->endfree - chunk->freeptr >= needed);
3583 if (events->head == NULL)
3584 events->head = chunk;
3586 events->tail->next = chunk;
3587 events->tail = chunk;
3588 /* events->tailfree is now out of sync, but we'll fix it below */
3592 * Try to locate a matching shared-data record already in the chunk. If
3593 * none, make a new one.
3595 for (newshared = ((AfterTriggerShared) chunk->endptr) - 1;
3596 (char *) newshared >= chunk->endfree;
3599 if (newshared->ats_tgoid == evtshared->ats_tgoid &&
3600 newshared->ats_relid == evtshared->ats_relid &&
3601 newshared->ats_event == evtshared->ats_event &&
3602 newshared->ats_firing_id == 0)
3605 if ((char *) newshared < chunk->endfree)
3607 *newshared = *evtshared;
3608 newshared->ats_firing_id = 0; /* just to be sure */
3609 chunk->endfree = (char *) newshared;
3612 /* Insert the data */
3613 newevent = (AfterTriggerEvent) chunk->freeptr;
3614 memcpy(newevent, event, eventsize);
3615 /* ... and link the new event to its shared record */
3616 newevent->ate_flags &= ~AFTER_TRIGGER_OFFSET;
3617 newevent->ate_flags |= (char *) newshared - (char *) newevent;
3619 chunk->freeptr += eventsize;
3620 events->tailfree = chunk->freeptr;
3624 * afterTriggerFreeEventList()
3626 * Free all the event storage in the given list.
3630 afterTriggerFreeEventList(AfterTriggerEventList *events)
3632 AfterTriggerEventChunk *chunk;
3633 AfterTriggerEventChunk *next_chunk;
3635 for (chunk = events->head; chunk != NULL; chunk = next_chunk)
3637 next_chunk = chunk->next;
3640 events->head = NULL;
3641 events->tail = NULL;
3642 events->tailfree = NULL;
3646 * afterTriggerRestoreEventList()
3648 * Restore an event list to its prior length, removing all the events
3649 * added since it had the value old_events.
3653 afterTriggerRestoreEventList(AfterTriggerEventList *events,
3654 const AfterTriggerEventList *old_events)
3656 AfterTriggerEventChunk *chunk;
3657 AfterTriggerEventChunk *next_chunk;
3659 if (old_events->tail == NULL)
3661 /* restoring to a completely empty state, so free everything */
3662 afterTriggerFreeEventList(events);
3666 *events = *old_events;
3667 /* free any chunks after the last one we want to keep */
3668 for (chunk = events->tail->next; chunk != NULL; chunk = next_chunk)
3670 next_chunk = chunk->next;
3673 /* and clean up the tail chunk to be the right length */
3674 events->tail->next = NULL;
3675 events->tail->freeptr = events->tailfree;
3678 * We don't make any effort to remove now-unused shared data records.
3679 * They might still be useful, anyway.
3686 * AfterTriggerExecute()
3688 * Fetch the required tuples back from the heap and fire one
3689 * single trigger function.
3691 * Frequently, this will be fired many times in a row for triggers of
3692 * a single relation. Therefore, we cache the open relation and provide
3693 * fmgr lookup cache space at the caller level. (For triggers fired at
3694 * the end of a query, we can even piggyback on the executor's state.)
3696 * event: event currently being fired.
3697 * rel: open relation for event.
3698 * trigdesc: working copy of rel's trigger info.
3699 * finfo: array of fmgr lookup cache entries (one per trigger in trigdesc).
3700 * instr: array of EXPLAIN ANALYZE instrumentation nodes (one per trigger),
3701 * or NULL if no instrumentation is wanted.
3702 * per_tuple_context: memory context to call trigger function in.
3703 * trig_tuple_slot1: scratch slot for tg_trigtuple (foreign tables only)
3704 * trig_tuple_slot2: scratch slot for tg_newtuple (foreign tables only)
3708 AfterTriggerExecute(AfterTriggerEvent event,
3709 Relation rel, TriggerDesc *trigdesc,
3710 FmgrInfo *finfo, Instrumentation *instr,
3711 MemoryContext per_tuple_context,
3712 TupleTableSlot *trig_tuple_slot1,
3713 TupleTableSlot *trig_tuple_slot2)
3715 AfterTriggerShared evtshared = GetTriggerSharedData(event);
3716 Oid tgoid = evtshared->ats_tgoid;
3717 TriggerData LocTriggerData;
3718 HeapTupleData tuple1;
3719 HeapTupleData tuple2;
3721 Buffer buffer1 = InvalidBuffer;
3722 Buffer buffer2 = InvalidBuffer;
3726 * Locate trigger in trigdesc.
3728 LocTriggerData.tg_trigger = NULL;
3729 for (tgindx = 0; tgindx < trigdesc->numtriggers; tgindx++)
3731 if (trigdesc->triggers[tgindx].tgoid == tgoid)
3733 LocTriggerData.tg_trigger = &(trigdesc->triggers[tgindx]);
3737 if (LocTriggerData.tg_trigger == NULL)
3738 elog(ERROR, "could not find trigger %u", tgoid);
3741 * If doing EXPLAIN ANALYZE, start charging time to this trigger. We want
3742 * to include time spent re-fetching tuples in the trigger cost.
3745 InstrStartNode(instr + tgindx);
3748 * Fetch the required tuple(s).
3750 switch (event->ate_flags & AFTER_TRIGGER_TUP_BITS)
3752 case AFTER_TRIGGER_FDW_FETCH:
3754 Tuplestorestate *fdw_tuplestore =
3755 GetTriggerTransitionTuplestore
3756 (afterTriggers.fdw_tuplestores);
3758 if (!tuplestore_gettupleslot(fdw_tuplestore, true, false,
3760 elog(ERROR, "failed to fetch tuple1 for AFTER trigger");
3762 if ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) ==
3763 TRIGGER_EVENT_UPDATE &&
3764 !tuplestore_gettupleslot(fdw_tuplestore, true, false,
3766 elog(ERROR, "failed to fetch tuple2 for AFTER trigger");
3769 case AFTER_TRIGGER_FDW_REUSE:
3772 * Using ExecMaterializeSlot() rather than ExecFetchSlotTuple()
3773 * ensures that tg_trigtuple does not reference tuplestore memory.
3774 * (It is formally possible for the trigger function to queue
3775 * trigger events that add to the same tuplestore, which can push
3776 * other tuples out of memory.) The distinction is academic,
3777 * because we start with a minimal tuple that ExecFetchSlotTuple()
3778 * must materialize anyway.
3780 LocTriggerData.tg_trigtuple =
3781 ExecMaterializeSlot(trig_tuple_slot1);
3782 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
3784 LocTriggerData.tg_newtuple =
3785 ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) ==
3786 TRIGGER_EVENT_UPDATE) ?
3787 ExecMaterializeSlot(trig_tuple_slot2) : NULL;
3788 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
3793 if (ItemPointerIsValid(&(event->ate_ctid1)))
3795 ItemPointerCopy(&(event->ate_ctid1), &(tuple1.t_self));
3796 if (!heap_fetch(rel, SnapshotAny, &tuple1, &buffer1, false, NULL))
3797 elog(ERROR, "failed to fetch tuple1 for AFTER trigger");
3798 LocTriggerData.tg_trigtuple = &tuple1;
3799 LocTriggerData.tg_trigtuplebuf = buffer1;
3803 LocTriggerData.tg_trigtuple = NULL;
3804 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
3807 /* don't touch ctid2 if not there */
3808 if ((event->ate_flags & AFTER_TRIGGER_TUP_BITS) ==
3809 AFTER_TRIGGER_2CTID &&
3810 ItemPointerIsValid(&(event->ate_ctid2)))
3812 ItemPointerCopy(&(event->ate_ctid2), &(tuple2.t_self));
3813 if (!heap_fetch(rel, SnapshotAny, &tuple2, &buffer2, false, NULL))
3814 elog(ERROR, "failed to fetch tuple2 for AFTER trigger");
3815 LocTriggerData.tg_newtuple = &tuple2;
3816 LocTriggerData.tg_newtuplebuf = buffer2;
3820 LocTriggerData.tg_newtuple = NULL;
3821 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
3826 * Set up the tuplestore information.
3828 if (LocTriggerData.tg_trigger->tgoldtable)
3829 LocTriggerData.tg_oldtable =
3830 GetTriggerTransitionTuplestore(afterTriggers.old_tuplestores);
3832 LocTriggerData.tg_oldtable = NULL;
3833 if (LocTriggerData.tg_trigger->tgnewtable)
3834 LocTriggerData.tg_newtable =
3835 GetTriggerTransitionTuplestore(afterTriggers.new_tuplestores);
3837 LocTriggerData.tg_newtable = NULL;
3840 * Setup the remaining trigger information
3842 LocTriggerData.type = T_TriggerData;
3843 LocTriggerData.tg_event =
3844 evtshared->ats_event & (TRIGGER_EVENT_OPMASK | TRIGGER_EVENT_ROW);
3845 LocTriggerData.tg_relation = rel;
3847 MemoryContextReset(per_tuple_context);
3850 * Call the trigger and throw away any possibly returned updated tuple.
3851 * (Don't let ExecCallTriggerFunc measure EXPLAIN time.)
3853 rettuple = ExecCallTriggerFunc(&LocTriggerData,
3858 if (rettuple != NULL &&
3859 rettuple != LocTriggerData.tg_trigtuple &&
3860 rettuple != LocTriggerData.tg_newtuple)
3861 heap_freetuple(rettuple);
3866 if (buffer1 != InvalidBuffer)
3867 ReleaseBuffer(buffer1);
3868 if (buffer2 != InvalidBuffer)
3869 ReleaseBuffer(buffer2);
3872 * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
3873 * one "tuple returned" (really the number of firings).
3876 InstrStopNode(instr + tgindx, 1);
3881 * afterTriggerMarkEvents()
3883 * Scan the given event list for not yet invoked events. Mark the ones
3884 * that can be invoked now with the current firing ID.
3886 * If move_list isn't NULL, events that are not to be invoked now are
3887 * transferred to move_list.
3889 * When immediate_only is TRUE, do not invoke currently-deferred triggers.
3890 * (This will be FALSE only at main transaction exit.)
3892 * Returns TRUE if any invokable events were found.
3895 afterTriggerMarkEvents(AfterTriggerEventList *events,
3896 AfterTriggerEventList *move_list,
3897 bool immediate_only)
3900 AfterTriggerEvent event;
3901 AfterTriggerEventChunk *chunk;
3903 for_each_event_chunk(event, chunk, *events)
3905 AfterTriggerShared evtshared = GetTriggerSharedData(event);
3906 bool defer_it = false;
3908 if (!(event->ate_flags &
3909 (AFTER_TRIGGER_DONE | AFTER_TRIGGER_IN_PROGRESS)))
3912 * This trigger hasn't been called or scheduled yet. Check if we
3913 * should call it now.
3915 if (immediate_only && afterTriggerCheckState(evtshared))
3922 * Mark it as to be fired in this firing cycle.
3924 evtshared->ats_firing_id = afterTriggers.firing_counter;
3925 event->ate_flags |= AFTER_TRIGGER_IN_PROGRESS;
3931 * If it's deferred, move it to move_list, if requested.
3933 if (defer_it && move_list != NULL)
3935 /* add it to move_list */
3936 afterTriggerAddEvent(move_list, event, evtshared);
3937 /* mark original copy "done" so we don't do it again */
3938 event->ate_flags |= AFTER_TRIGGER_DONE;
3946 * afterTriggerInvokeEvents()
3948 * Scan the given event list for events that are marked as to be fired
3949 * in the current firing cycle, and fire them.
3951 * If estate isn't NULL, we use its result relation info to avoid repeated
3952 * openings and closing of trigger target relations. If it is NULL, we
3953 * make one locally to cache the info in case there are multiple trigger
3956 * When delete_ok is TRUE, it's safe to delete fully-processed events.
3957 * (We are not very tense about that: we simply reset a chunk to be empty
3958 * if all its events got fired. The objective here is just to avoid useless
3959 * rescanning of events when a trigger queues new events during transaction
3960 * end, so it's not necessary to worry much about the case where only
3961 * some events are fired.)
3963 * Returns TRUE if no unfired events remain in the list (this allows us
3964 * to avoid repeating afterTriggerMarkEvents).
3967 afterTriggerInvokeEvents(AfterTriggerEventList *events,
3968 CommandId firing_id,
3972 bool all_fired = true;
3973 AfterTriggerEventChunk *chunk;
3974 MemoryContext per_tuple_context;
3975 bool local_estate = false;
3976 Relation rel = NULL;
3977 TriggerDesc *trigdesc = NULL;
3978 FmgrInfo *finfo = NULL;
3979 Instrumentation *instr = NULL;
3980 TupleTableSlot *slot1 = NULL,
3983 /* Make a local EState if need be */
3986 estate = CreateExecutorState();
3987 local_estate = true;
3990 /* Make a per-tuple memory context for trigger function calls */
3992 AllocSetContextCreate(CurrentMemoryContext,
3993 "AfterTriggerTupleContext",
3994 ALLOCSET_DEFAULT_SIZES);
3996 for_each_chunk(chunk, *events)
3998 AfterTriggerEvent event;
3999 bool all_fired_in_chunk = true;
4001 for_each_event(event, chunk)
4003 AfterTriggerShared evtshared = GetTriggerSharedData(event);
4006 * Is it one for me to fire?
4008 if ((event->ate_flags & AFTER_TRIGGER_IN_PROGRESS) &&
4009 evtshared->ats_firing_id == firing_id)
4012 * So let's fire it... but first, find the correct relation if
4013 * this is not the same relation as before.
4015 if (rel == NULL || RelationGetRelid(rel) != evtshared->ats_relid)
4017 ResultRelInfo *rInfo;
4019 rInfo = ExecGetTriggerResultRel(estate, evtshared->ats_relid);
4020 rel = rInfo->ri_RelationDesc;
4021 trigdesc = rInfo->ri_TrigDesc;
4022 finfo = rInfo->ri_TrigFunctions;
4023 instr = rInfo->ri_TrigInstrument;
4024 if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
4028 ExecDropSingleTupleTableSlot(slot1);
4029 ExecDropSingleTupleTableSlot(slot2);
4031 slot1 = MakeSingleTupleTableSlot(rel->rd_att);
4032 slot2 = MakeSingleTupleTableSlot(rel->rd_att);
4034 if (trigdesc == NULL) /* should not happen */
4035 elog(ERROR, "relation %u has no triggers",
4036 evtshared->ats_relid);
4040 * Fire it. Note that the AFTER_TRIGGER_IN_PROGRESS flag is
4041 * still set, so recursive examinations of the event list
4042 * won't try to re-fire it.
4044 AfterTriggerExecute(event, rel, trigdesc, finfo, instr,
4045 per_tuple_context, slot1, slot2);
4048 * Mark the event as done.
4050 event->ate_flags &= ~AFTER_TRIGGER_IN_PROGRESS;
4051 event->ate_flags |= AFTER_TRIGGER_DONE;
4053 else if (!(event->ate_flags & AFTER_TRIGGER_DONE))
4055 /* something remains to be done */
4056 all_fired = all_fired_in_chunk = false;
4060 /* Clear the chunk if delete_ok and nothing left of interest */
4061 if (delete_ok && all_fired_in_chunk)
4063 chunk->freeptr = CHUNK_DATA_START(chunk);
4064 chunk->endfree = chunk->endptr;
4067 * If it's last chunk, must sync event list's tailfree too. Note
4068 * that delete_ok must NOT be passed as true if there could be
4069 * stacked AfterTriggerEventList values pointing at this event
4070 * list, since we'd fail to fix their copies of tailfree.
4072 if (chunk == events->tail)
4073 events->tailfree = chunk->freeptr;
4078 ExecDropSingleTupleTableSlot(slot1);
4079 ExecDropSingleTupleTableSlot(slot2);
4082 /* Release working resources */
4083 MemoryContextDelete(per_tuple_context);
4089 foreach(l, estate->es_trig_target_relations)
4091 ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
4093 /* Close indices and then the relation itself */
4094 ExecCloseIndices(resultRelInfo);
4095 heap_close(resultRelInfo->ri_RelationDesc, NoLock);
4097 FreeExecutorState(estate);
4105 * AfterTriggerBeginXact()
4107 * Called at transaction start (either BEGIN or implicit for single
4108 * statement outside of transaction block).
4112 AfterTriggerBeginXact(void)
4115 * Initialize after-trigger state structure to empty
4117 afterTriggers.firing_counter = (CommandId) 1; /* mustn't be 0 */
4118 afterTriggers.query_depth = -1;
4121 * Verify that there is no leftover state remaining. If these assertions
4122 * trip, it means that AfterTriggerEndXact wasn't called or didn't clean
4125 Assert(afterTriggers.state == NULL);
4126 Assert(afterTriggers.query_stack == NULL);
4127 Assert(afterTriggers.fdw_tuplestores == NULL);
4128 Assert(afterTriggers.old_tuplestores == NULL);
4129 Assert(afterTriggers.new_tuplestores == NULL);
4130 Assert(afterTriggers.maxquerydepth == 0);
4131 Assert(afterTriggers.event_cxt == NULL);
4132 Assert(afterTriggers.events.head == NULL);
4133 Assert(afterTriggers.state_stack == NULL);
4134 Assert(afterTriggers.events_stack == NULL);
4135 Assert(afterTriggers.depth_stack == NULL);
4136 Assert(afterTriggers.firing_stack == NULL);
4137 Assert(afterTriggers.maxtransdepth == 0);
4142 * AfterTriggerBeginQuery()
4144 * Called just before we start processing a single query within a
4145 * transaction (or subtransaction). Most of the real work gets deferred
4146 * until somebody actually tries to queue a trigger event.
4150 AfterTriggerBeginQuery(void)
4152 /* Increase the query stack depth */
4153 afterTriggers.query_depth++;
4158 * AfterTriggerEndQuery()
4160 * Called after one query has been completely processed. At this time
4161 * we invoke all AFTER IMMEDIATE trigger events queued by the query, and
4162 * transfer deferred trigger events to the global deferred-trigger list.
4164 * Note that this must be called BEFORE closing down the executor
4165 * with ExecutorEnd, because we make use of the EState's info about
4166 * target relations. Normally it is called from ExecutorFinish.
4170 AfterTriggerEndQuery(EState *estate)
4172 AfterTriggerEventList *events;
4173 Tuplestorestate *fdw_tuplestore;
4174 Tuplestorestate *old_tuplestore;
4175 Tuplestorestate *new_tuplestore;
4177 /* Must be inside a query, too */
4178 Assert(afterTriggers.query_depth >= 0);
4181 * If we never even got as far as initializing the event stack, there
4182 * certainly won't be any events, so exit quickly.
4184 if (afterTriggers.query_depth >= afterTriggers.maxquerydepth)
4186 afterTriggers.query_depth--;
4191 * Process all immediate-mode triggers queued by the query, and move the
4192 * deferred ones to the main list of deferred events.
4194 * Notice that we decide which ones will be fired, and put the deferred
4195 * ones on the main list, before anything is actually fired. This ensures
4196 * reasonably sane behavior if a trigger function does SET CONSTRAINTS ...
4197 * IMMEDIATE: all events we have decided to defer will be available for it
4200 * We loop in case a trigger queues more events at the same query level.
4201 * Ordinary trigger functions, including all PL/pgSQL trigger functions,
4202 * will instead fire any triggers in a dedicated query level. Foreign key
4203 * enforcement triggers do add to the current query level, thanks to their
4204 * passing fire_triggers = false to SPI_execute_snapshot(). Other
4205 * C-language triggers might do likewise. Be careful here: firing a
4206 * trigger could result in query_stack being repalloc'd, so we can't save
4207 * its address across afterTriggerInvokeEvents calls.
4209 * If we find no firable events, we don't have to increment
4214 events = &afterTriggers.query_stack[afterTriggers.query_depth];
4215 if (afterTriggerMarkEvents(events, &afterTriggers.events, true))
4217 CommandId firing_id = afterTriggers.firing_counter++;
4219 /* OK to delete the immediate events after processing them */
4220 if (afterTriggerInvokeEvents(events, firing_id, estate, true))
4221 break; /* all fired */
4227 /* Release query-local storage for events, including tuplestore if any */
4228 fdw_tuplestore = afterTriggers.fdw_tuplestores[afterTriggers.query_depth];
4231 tuplestore_end(fdw_tuplestore);
4232 afterTriggers.fdw_tuplestores[afterTriggers.query_depth] = NULL;
4234 old_tuplestore = afterTriggers.old_tuplestores[afterTriggers.query_depth];
4237 tuplestore_end(old_tuplestore);
4238 afterTriggers.old_tuplestores[afterTriggers.query_depth] = NULL;
4240 new_tuplestore = afterTriggers.new_tuplestores[afterTriggers.query_depth];
4243 tuplestore_end(new_tuplestore);
4244 afterTriggers.new_tuplestores[afterTriggers.query_depth] = NULL;
4246 afterTriggerFreeEventList(&afterTriggers.query_stack[afterTriggers.query_depth]);
4248 afterTriggers.query_depth--;
4253 * AfterTriggerFireDeferred()
4255 * Called just before the current transaction is committed. At this
4256 * time we invoke all pending DEFERRED triggers.
4258 * It is possible for other modules to queue additional deferred triggers
4259 * during pre-commit processing; therefore xact.c may have to call this
4264 AfterTriggerFireDeferred(void)
4266 AfterTriggerEventList *events;
4267 bool snap_pushed = false;
4269 /* Must not be inside a query */
4270 Assert(afterTriggers.query_depth == -1);
4273 * If there are any triggers to fire, make sure we have set a snapshot for
4274 * them to use. (Since PortalRunUtility doesn't set a snap for COMMIT, we
4275 * can't assume ActiveSnapshot is valid on entry.)
4277 events = &afterTriggers.events;
4278 if (events->head != NULL)
4280 PushActiveSnapshot(GetTransactionSnapshot());
4285 * Run all the remaining triggers. Loop until they are all gone, in case
4286 * some trigger queues more for us to do.
4288 while (afterTriggerMarkEvents(events, NULL, false))
4290 CommandId firing_id = afterTriggers.firing_counter++;
4292 if (afterTriggerInvokeEvents(events, firing_id, NULL, true))
4293 break; /* all fired */
4297 * We don't bother freeing the event list, since it will go away anyway
4298 * (and more efficiently than via pfree) in AfterTriggerEndXact.
4302 PopActiveSnapshot();
4307 * AfterTriggerEndXact()
4309 * The current transaction is finishing.
4311 * Any unfired triggers are canceled so we simply throw
4312 * away anything we know.
4314 * Note: it is possible for this to be called repeatedly in case of
4315 * error during transaction abort; therefore, do not complain if
4316 * already closed down.
4320 AfterTriggerEndXact(bool isCommit)
4323 * Forget the pending-events list.
4325 * Since all the info is in TopTransactionContext or children thereof, we
4326 * don't really need to do anything to reclaim memory. However, the
4327 * pending-events list could be large, and so it's useful to discard it as
4328 * soon as possible --- especially if we are aborting because we ran out
4329 * of memory for the list!
4331 if (afterTriggers.event_cxt)
4333 MemoryContextDelete(afterTriggers.event_cxt);
4334 afterTriggers.event_cxt = NULL;
4335 afterTriggers.events.head = NULL;
4336 afterTriggers.events.tail = NULL;
4337 afterTriggers.events.tailfree = NULL;
4341 * Forget any subtransaction state as well. Since this can't be very
4342 * large, we let the eventual reset of TopTransactionContext free the
4343 * memory instead of doing it here.
4345 afterTriggers.state_stack = NULL;
4346 afterTriggers.events_stack = NULL;
4347 afterTriggers.depth_stack = NULL;
4348 afterTriggers.firing_stack = NULL;
4349 afterTriggers.maxtransdepth = 0;
4353 * Forget the query stack and constraint-related state information. As
4354 * with the subtransaction state information, we don't bother freeing the
4357 afterTriggers.query_stack = NULL;
4358 afterTriggers.fdw_tuplestores = NULL;
4359 afterTriggers.old_tuplestores = NULL;
4360 afterTriggers.new_tuplestores = NULL;
4361 afterTriggers.maxquerydepth = 0;
4362 afterTriggers.state = NULL;
4364 /* No more afterTriggers manipulation until next transaction starts. */
4365 afterTriggers.query_depth = -1;
4369 * AfterTriggerBeginSubXact()
4371 * Start a subtransaction.
4374 AfterTriggerBeginSubXact(void)
4376 int my_level = GetCurrentTransactionNestLevel();
4379 * Allocate more space in the stacks if needed. (Note: because the
4380 * minimum nest level of a subtransaction is 2, we waste the first couple
4381 * entries of each array; not worth the notational effort to avoid it.)
4383 while (my_level >= afterTriggers.maxtransdepth)
4385 if (afterTriggers.maxtransdepth == 0)
4387 MemoryContext old_cxt;
4389 old_cxt = MemoryContextSwitchTo(TopTransactionContext);
4391 #define DEFTRIG_INITALLOC 8
4392 afterTriggers.state_stack = (SetConstraintState *)
4393 palloc(DEFTRIG_INITALLOC * sizeof(SetConstraintState));
4394 afterTriggers.events_stack = (AfterTriggerEventList *)
4395 palloc(DEFTRIG_INITALLOC * sizeof(AfterTriggerEventList));
4396 afterTriggers.depth_stack = (int *)
4397 palloc(DEFTRIG_INITALLOC * sizeof(int));
4398 afterTriggers.firing_stack = (CommandId *)
4399 palloc(DEFTRIG_INITALLOC * sizeof(CommandId));
4400 afterTriggers.maxtransdepth = DEFTRIG_INITALLOC;
4402 MemoryContextSwitchTo(old_cxt);
4406 /* repalloc will keep the stacks in the same context */
4407 int new_alloc = afterTriggers.maxtransdepth * 2;
4409 afterTriggers.state_stack = (SetConstraintState *)
4410 repalloc(afterTriggers.state_stack,
4411 new_alloc * sizeof(SetConstraintState));
4412 afterTriggers.events_stack = (AfterTriggerEventList *)
4413 repalloc(afterTriggers.events_stack,
4414 new_alloc * sizeof(AfterTriggerEventList));
4415 afterTriggers.depth_stack = (int *)
4416 repalloc(afterTriggers.depth_stack,
4417 new_alloc * sizeof(int));
4418 afterTriggers.firing_stack = (CommandId *)
4419 repalloc(afterTriggers.firing_stack,
4420 new_alloc * sizeof(CommandId));
4421 afterTriggers.maxtransdepth = new_alloc;
4426 * Push the current information into the stack. The SET CONSTRAINTS state
4427 * is not saved until/unless changed. Likewise, we don't make a
4428 * per-subtransaction event context until needed.
4430 afterTriggers.state_stack[my_level] = NULL;
4431 afterTriggers.events_stack[my_level] = afterTriggers.events;
4432 afterTriggers.depth_stack[my_level] = afterTriggers.query_depth;
4433 afterTriggers.firing_stack[my_level] = afterTriggers.firing_counter;
4437 * AfterTriggerEndSubXact()
4439 * The current subtransaction is ending.
4442 AfterTriggerEndSubXact(bool isCommit)
4444 int my_level = GetCurrentTransactionNestLevel();
4445 SetConstraintState state;
4446 AfterTriggerEvent event;
4447 AfterTriggerEventChunk *chunk;
4448 CommandId subxact_firing_id;
4451 * Pop the prior state if needed.
4455 Assert(my_level < afterTriggers.maxtransdepth);
4456 /* If we saved a prior state, we don't need it anymore */
4457 state = afterTriggers.state_stack[my_level];
4460 /* this avoids double pfree if error later: */
4461 afterTriggers.state_stack[my_level] = NULL;
4462 Assert(afterTriggers.query_depth ==
4463 afterTriggers.depth_stack[my_level]);
4468 * Aborting. It is possible subxact start failed before calling
4469 * AfterTriggerBeginSubXact, in which case we mustn't risk touching
4470 * stack levels that aren't there.
4472 if (my_level >= afterTriggers.maxtransdepth)
4476 * Release any event lists from queries being aborted, and restore
4477 * query_depth to its pre-subxact value. This assumes that a
4478 * subtransaction will not add events to query levels started in a
4479 * earlier transaction state.
4481 while (afterTriggers.query_depth > afterTriggers.depth_stack[my_level])
4483 if (afterTriggers.query_depth < afterTriggers.maxquerydepth)
4485 Tuplestorestate *ts;
4487 ts = afterTriggers.fdw_tuplestores[afterTriggers.query_depth];
4491 afterTriggers.fdw_tuplestores[afterTriggers.query_depth] = NULL;
4493 ts = afterTriggers.old_tuplestores[afterTriggers.query_depth];
4497 afterTriggers.old_tuplestores[afterTriggers.query_depth] = NULL;
4499 ts = afterTriggers.new_tuplestores[afterTriggers.query_depth];
4503 afterTriggers.new_tuplestores[afterTriggers.query_depth] = NULL;
4506 afterTriggerFreeEventList(&afterTriggers.query_stack[afterTriggers.query_depth]);
4509 afterTriggers.query_depth--;
4511 Assert(afterTriggers.query_depth ==
4512 afterTriggers.depth_stack[my_level]);
4515 * Restore the global deferred-event list to its former length,
4516 * discarding any events queued by the subxact.
4518 afterTriggerRestoreEventList(&afterTriggers.events,
4519 &afterTriggers.events_stack[my_level]);
4522 * Restore the trigger state. If the saved state is NULL, then this
4523 * subxact didn't save it, so it doesn't need restoring.
4525 state = afterTriggers.state_stack[my_level];
4528 pfree(afterTriggers.state);
4529 afterTriggers.state = state;
4531 /* this avoids double pfree if error later: */
4532 afterTriggers.state_stack[my_level] = NULL;
4535 * Scan for any remaining deferred events that were marked DONE or IN
4536 * PROGRESS by this subxact or a child, and un-mark them. We can
4537 * recognize such events because they have a firing ID greater than or
4538 * equal to the firing_counter value we saved at subtransaction start.
4539 * (This essentially assumes that the current subxact includes all
4540 * subxacts started after it.)
4542 subxact_firing_id = afterTriggers.firing_stack[my_level];
4543 for_each_event_chunk(event, chunk, afterTriggers.events)
4545 AfterTriggerShared evtshared = GetTriggerSharedData(event);
4547 if (event->ate_flags &
4548 (AFTER_TRIGGER_DONE | AFTER_TRIGGER_IN_PROGRESS))
4550 if (evtshared->ats_firing_id >= subxact_firing_id)
4552 ~(AFTER_TRIGGER_DONE | AFTER_TRIGGER_IN_PROGRESS);
4559 * AfterTriggerEnlargeQueryState()
4561 * Prepare the necessary state so that we can record AFTER trigger events
4562 * queued by a query. It is allowed to have nested queries within a
4563 * (sub)transaction, so we need to have separate state for each query
4568 AfterTriggerEnlargeQueryState(void)
4570 int init_depth = afterTriggers.maxquerydepth;
4572 Assert(afterTriggers.query_depth >= afterTriggers.maxquerydepth);
4574 if (afterTriggers.maxquerydepth == 0)
4576 int new_alloc = Max(afterTriggers.query_depth + 1, 8);
4578 afterTriggers.query_stack = (AfterTriggerEventList *)
4579 MemoryContextAlloc(TopTransactionContext,
4580 new_alloc * sizeof(AfterTriggerEventList));
4581 afterTriggers.fdw_tuplestores = (Tuplestorestate **)
4582 MemoryContextAllocZero(TopTransactionContext,
4583 new_alloc * sizeof(Tuplestorestate *));
4584 afterTriggers.old_tuplestores = (Tuplestorestate **)
4585 MemoryContextAllocZero(TopTransactionContext,
4586 new_alloc * sizeof(Tuplestorestate *));
4587 afterTriggers.new_tuplestores = (Tuplestorestate **)
4588 MemoryContextAllocZero(TopTransactionContext,
4589 new_alloc * sizeof(Tuplestorestate *));
4590 afterTriggers.maxquerydepth = new_alloc;
4594 /* repalloc will keep the stack in the same context */
4595 int old_alloc = afterTriggers.maxquerydepth;
4596 int new_alloc = Max(afterTriggers.query_depth + 1,
4599 afterTriggers.query_stack = (AfterTriggerEventList *)
4600 repalloc(afterTriggers.query_stack,
4601 new_alloc * sizeof(AfterTriggerEventList));
4602 afterTriggers.fdw_tuplestores = (Tuplestorestate **)
4603 repalloc(afterTriggers.fdw_tuplestores,
4604 new_alloc * sizeof(Tuplestorestate *));
4605 afterTriggers.old_tuplestores = (Tuplestorestate **)
4606 repalloc(afterTriggers.old_tuplestores,
4607 new_alloc * sizeof(Tuplestorestate *));
4608 afterTriggers.new_tuplestores = (Tuplestorestate **)
4609 repalloc(afterTriggers.new_tuplestores,
4610 new_alloc * sizeof(Tuplestorestate *));
4611 /* Clear newly-allocated slots for subsequent lazy initialization. */
4612 memset(afterTriggers.fdw_tuplestores + old_alloc,
4613 0, (new_alloc - old_alloc) * sizeof(Tuplestorestate *));
4614 memset(afterTriggers.old_tuplestores + old_alloc,
4615 0, (new_alloc - old_alloc) * sizeof(Tuplestorestate *));
4616 memset(afterTriggers.new_tuplestores + old_alloc,
4617 0, (new_alloc - old_alloc) * sizeof(Tuplestorestate *));
4618 afterTriggers.maxquerydepth = new_alloc;
4621 /* Initialize new query lists to empty */
4622 while (init_depth < afterTriggers.maxquerydepth)
4624 AfterTriggerEventList *events;
4626 events = &afterTriggers.query_stack[init_depth];
4627 events->head = NULL;
4628 events->tail = NULL;
4629 events->tailfree = NULL;
4636 * Create an empty SetConstraintState with room for numalloc trigstates
4638 static SetConstraintState
4639 SetConstraintStateCreate(int numalloc)
4641 SetConstraintState state;
4643 /* Behave sanely with numalloc == 0 */
4648 * We assume that zeroing will correctly initialize the state values.
4650 state = (SetConstraintState)
4651 MemoryContextAllocZero(TopTransactionContext,
4652 offsetof(SetConstraintStateData, trigstates) +
4653 numalloc * sizeof(SetConstraintTriggerData));
4655 state->numalloc = numalloc;
4661 * Copy a SetConstraintState
4663 static SetConstraintState
4664 SetConstraintStateCopy(SetConstraintState origstate)
4666 SetConstraintState state;
4668 state = SetConstraintStateCreate(origstate->numstates);
4670 state->all_isset = origstate->all_isset;
4671 state->all_isdeferred = origstate->all_isdeferred;
4672 state->numstates = origstate->numstates;
4673 memcpy(state->trigstates, origstate->trigstates,
4674 origstate->numstates * sizeof(SetConstraintTriggerData));
4680 * Add a per-trigger item to a SetConstraintState. Returns possibly-changed
4681 * pointer to the state object (it will change if we have to repalloc).
4683 static SetConstraintState
4684 SetConstraintStateAddItem(SetConstraintState state,
4685 Oid tgoid, bool tgisdeferred)
4687 if (state->numstates >= state->numalloc)
4689 int newalloc = state->numalloc * 2;
4691 newalloc = Max(newalloc, 8); /* in case original has size 0 */
4692 state = (SetConstraintState)
4694 offsetof(SetConstraintStateData, trigstates) +
4695 newalloc * sizeof(SetConstraintTriggerData));
4696 state->numalloc = newalloc;
4697 Assert(state->numstates < state->numalloc);
4700 state->trigstates[state->numstates].sct_tgoid = tgoid;
4701 state->trigstates[state->numstates].sct_tgisdeferred = tgisdeferred;
4708 * AfterTriggerSetState()
4710 * Execute the SET CONSTRAINTS ... utility command.
4714 AfterTriggerSetState(ConstraintsSetStmt *stmt)
4716 int my_level = GetCurrentTransactionNestLevel();
4718 /* If we haven't already done so, initialize our state. */
4719 if (afterTriggers.state == NULL)
4720 afterTriggers.state = SetConstraintStateCreate(8);
4723 * If in a subtransaction, and we didn't save the current state already,
4724 * save it so it can be restored if the subtransaction aborts.
4727 afterTriggers.state_stack[my_level] == NULL)
4729 afterTriggers.state_stack[my_level] =
4730 SetConstraintStateCopy(afterTriggers.state);
4734 * Handle SET CONSTRAINTS ALL ...
4736 if (stmt->constraints == NIL)
4739 * Forget any previous SET CONSTRAINTS commands in this transaction.
4741 afterTriggers.state->numstates = 0;
4744 * Set the per-transaction ALL state to known.
4746 afterTriggers.state->all_isset = true;
4747 afterTriggers.state->all_isdeferred = stmt->deferred;
4753 List *conoidlist = NIL;
4754 List *tgoidlist = NIL;
4758 * Handle SET CONSTRAINTS constraint-name [, ...]
4760 * First, identify all the named constraints and make a list of their
4761 * OIDs. Since, unlike the SQL spec, we allow multiple constraints of
4762 * the same name within a schema, the specifications are not
4763 * necessarily unique. Our strategy is to target all matching
4764 * constraints within the first search-path schema that has any
4765 * matches, but disregard matches in schemas beyond the first match.
4766 * (This is a bit odd but it's the historical behavior.)
4768 conrel = heap_open(ConstraintRelationId, AccessShareLock);
4770 foreach(lc, stmt->constraints)
4772 RangeVar *constraint = lfirst(lc);
4774 List *namespacelist;
4777 if (constraint->catalogname)
4779 if (strcmp(constraint->catalogname, get_database_name(MyDatabaseId)) != 0)
4781 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4782 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
4783 constraint->catalogname, constraint->schemaname,
4784 constraint->relname)));
4788 * If we're given the schema name with the constraint, look only
4789 * in that schema. If given a bare constraint name, use the
4790 * search path to find the first matching constraint.
4792 if (constraint->schemaname)
4794 Oid namespaceId = LookupExplicitNamespace(constraint->schemaname,
4797 namespacelist = list_make1_oid(namespaceId);
4801 namespacelist = fetch_search_path(true);
4805 foreach(nslc, namespacelist)
4807 Oid namespaceId = lfirst_oid(nslc);
4808 SysScanDesc conscan;
4809 ScanKeyData skey[2];
4812 ScanKeyInit(&skey[0],
4813 Anum_pg_constraint_conname,
4814 BTEqualStrategyNumber, F_NAMEEQ,
4815 CStringGetDatum(constraint->relname));
4816 ScanKeyInit(&skey[1],
4817 Anum_pg_constraint_connamespace,
4818 BTEqualStrategyNumber, F_OIDEQ,
4819 ObjectIdGetDatum(namespaceId));
4821 conscan = systable_beginscan(conrel, ConstraintNameNspIndexId,
4822 true, NULL, 2, skey);
4824 while (HeapTupleIsValid(tup = systable_getnext(conscan)))
4826 Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tup);
4828 if (con->condeferrable)
4829 conoidlist = lappend_oid(conoidlist,
4830 HeapTupleGetOid(tup));
4831 else if (stmt->deferred)
4833 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
4834 errmsg("constraint \"%s\" is not deferrable",
4835 constraint->relname)));
4839 systable_endscan(conscan);
4842 * Once we've found a matching constraint we do not search
4843 * later parts of the search path.
4849 list_free(namespacelist);
4856 (errcode(ERRCODE_UNDEFINED_OBJECT),
4857 errmsg("constraint \"%s\" does not exist",
4858 constraint->relname)));
4861 heap_close(conrel, AccessShareLock);
4864 * Now, locate the trigger(s) implementing each of these constraints,
4865 * and make a list of their OIDs.
4867 tgrel = heap_open(TriggerRelationId, AccessShareLock);
4869 foreach(lc, conoidlist)
4871 Oid conoid = lfirst_oid(lc);
4880 Anum_pg_trigger_tgconstraint,
4881 BTEqualStrategyNumber, F_OIDEQ,
4882 ObjectIdGetDatum(conoid));
4884 tgscan = systable_beginscan(tgrel, TriggerConstraintIndexId, true,
4887 while (HeapTupleIsValid(htup = systable_getnext(tgscan)))
4889 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
4892 * Silently skip triggers that are marked as non-deferrable in
4893 * pg_trigger. This is not an error condition, since a
4894 * deferrable RI constraint may have some non-deferrable
4897 if (pg_trigger->tgdeferrable)
4898 tgoidlist = lappend_oid(tgoidlist,
4899 HeapTupleGetOid(htup));
4904 systable_endscan(tgscan);
4906 /* Safety check: a deferrable constraint should have triggers */
4908 elog(ERROR, "no triggers found for constraint with OID %u",
4912 heap_close(tgrel, AccessShareLock);
4915 * Now we can set the trigger states of individual triggers for this
4918 foreach(lc, tgoidlist)
4920 Oid tgoid = lfirst_oid(lc);
4921 SetConstraintState state = afterTriggers.state;
4925 for (i = 0; i < state->numstates; i++)
4927 if (state->trigstates[i].sct_tgoid == tgoid)
4929 state->trigstates[i].sct_tgisdeferred = stmt->deferred;
4936 afterTriggers.state =
4937 SetConstraintStateAddItem(state, tgoid, stmt->deferred);
4943 * SQL99 requires that when a constraint is set to IMMEDIATE, any deferred
4944 * checks against that constraint must be made when the SET CONSTRAINTS
4945 * command is executed -- i.e. the effects of the SET CONSTRAINTS command
4946 * apply retroactively. We've updated the constraints state, so scan the
4947 * list of previously deferred events to fire any that have now become
4950 * Obviously, if this was SET ... DEFERRED then it can't have converted
4951 * any unfired events to immediate, so we need do nothing in that case.
4953 if (!stmt->deferred)
4955 AfterTriggerEventList *events = &afterTriggers.events;
4956 bool snapshot_set = false;
4958 while (afterTriggerMarkEvents(events, NULL, true))
4960 CommandId firing_id = afterTriggers.firing_counter++;
4963 * Make sure a snapshot has been established in case trigger
4964 * functions need one. Note that we avoid setting a snapshot if
4965 * we don't find at least one trigger that has to be fired now.
4966 * This is so that BEGIN; SET CONSTRAINTS ...; SET TRANSACTION
4967 * ISOLATION LEVEL SERIALIZABLE; ... works properly. (If we are
4968 * at the start of a transaction it's not possible for any trigger
4969 * events to be queued yet.)
4973 PushActiveSnapshot(GetTransactionSnapshot());
4974 snapshot_set = true;
4978 * We can delete fired events if we are at top transaction level,
4979 * but we'd better not if inside a subtransaction, since the
4980 * subtransaction could later get rolled back.
4982 if (afterTriggerInvokeEvents(events, firing_id, NULL,
4983 !IsSubTransaction()))
4984 break; /* all fired */
4988 PopActiveSnapshot();
4993 * AfterTriggerPendingOnRel()
4994 * Test to see if there are any pending after-trigger events for rel.
4996 * This is used by TRUNCATE, CLUSTER, ALTER TABLE, etc to detect whether
4997 * it is unsafe to perform major surgery on a relation. Note that only
4998 * local pending events are examined. We assume that having exclusive lock
4999 * on a rel guarantees there are no unserviced events in other backends ---
5000 * but having a lock does not prevent there being such events in our own.
5002 * In some scenarios it'd be reasonable to remove pending events (more
5003 * specifically, mark them DONE by the current subxact) but without a lot
5004 * of knowledge of the trigger semantics we can't do this in general.
5008 AfterTriggerPendingOnRel(Oid relid)
5010 AfterTriggerEvent event;
5011 AfterTriggerEventChunk *chunk;
5014 /* Scan queued events */
5015 for_each_event_chunk(event, chunk, afterTriggers.events)
5017 AfterTriggerShared evtshared = GetTriggerSharedData(event);
5020 * We can ignore completed events. (Even if a DONE flag is rolled
5021 * back by subxact abort, it's OK because the effects of the TRUNCATE
5022 * or whatever must get rolled back too.)
5024 if (event->ate_flags & AFTER_TRIGGER_DONE)
5027 if (evtshared->ats_relid == relid)
5032 * Also scan events queued by incomplete queries. This could only matter
5033 * if TRUNCATE/etc is executed by a function or trigger within an updating
5034 * query on the same relation, which is pretty perverse, but let's check.
5036 for (depth = 0; depth <= afterTriggers.query_depth && depth < afterTriggers.maxquerydepth; depth++)
5038 for_each_event_chunk(event, chunk, afterTriggers.query_stack[depth])
5040 AfterTriggerShared evtshared = GetTriggerSharedData(event);
5042 if (event->ate_flags & AFTER_TRIGGER_DONE)
5045 if (evtshared->ats_relid == relid)
5055 * AfterTriggerSaveEvent()
5057 * Called by ExecA[RS]...Triggers() to queue up the triggers that should
5058 * be fired for an event.
5060 * NOTE: this is called whenever there are any triggers associated with
5061 * the event (even if they are disabled). This function decides which
5062 * triggers actually need to be queued. It is also called after each row,
5063 * even if there are no triggers for that event, if there are any AFTER
5064 * STATEMENT triggers for the statement which use transition tables, so that
5065 * the transition tuplestores can be built.
5067 * Transition tuplestores are built now, rather than when events are pulled
5068 * off of the queue because AFTER ROW triggers are allowed to select from the
5069 * transition tables for the statement.
5073 AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
5074 int event, bool row_trigger,
5075 HeapTuple oldtup, HeapTuple newtup,
5076 List *recheckIndexes, Bitmapset *modifiedCols)
5078 Relation rel = relinfo->ri_RelationDesc;
5079 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
5080 AfterTriggerEventData new_event;
5081 AfterTriggerSharedData new_shared;
5082 char relkind = relinfo->ri_RelationDesc->rd_rel->relkind;
5086 Tuplestorestate *fdw_tuplestore = NULL;
5089 * Check state. We use a normal test not Assert because it is possible to
5090 * reach here in the wrong state given misconfigured RI triggers, in
5091 * particular deferring a cascade action trigger.
5093 if (afterTriggers.query_depth < 0)
5094 elog(ERROR, "AfterTriggerSaveEvent() called outside of query");
5096 /* Be sure we have enough space to record events at this query depth. */
5097 if (afterTriggers.query_depth >= afterTriggers.maxquerydepth)
5098 AfterTriggerEnlargeQueryState();
5101 * If the relation has AFTER ... FOR EACH ROW triggers, capture rows into
5102 * transition tuplestores for this depth.
5106 if ((event == TRIGGER_EVENT_DELETE &&
5107 trigdesc->trig_delete_old_table) ||
5108 (event == TRIGGER_EVENT_UPDATE &&
5109 trigdesc->trig_update_old_table))
5111 Tuplestorestate *old_tuplestore;
5113 Assert(oldtup != NULL);
5115 GetTriggerTransitionTuplestore
5116 (afterTriggers.old_tuplestores);
5117 tuplestore_puttuple(old_tuplestore, oldtup);
5119 if ((event == TRIGGER_EVENT_INSERT &&
5120 trigdesc->trig_insert_new_table) ||
5121 (event == TRIGGER_EVENT_UPDATE &&
5122 trigdesc->trig_update_new_table))
5124 Tuplestorestate *new_tuplestore;
5126 Assert(newtup != NULL);
5128 GetTriggerTransitionTuplestore
5129 (afterTriggers.new_tuplestores);
5130 tuplestore_puttuple(new_tuplestore, newtup);
5133 /* If transition tables are the only reason we're here, return. */
5134 if ((event == TRIGGER_EVENT_DELETE && !trigdesc->trig_delete_after_row) ||
5135 (event == TRIGGER_EVENT_INSERT && !trigdesc->trig_insert_after_row) ||
5136 (event == TRIGGER_EVENT_UPDATE && !trigdesc->trig_update_after_row))
5141 * Validate the event code and collect the associated tuple CTIDs.
5143 * The event code will be used both as a bitmask and an array offset, so
5144 * validation is important to make sure we don't walk off the edge of our
5149 case TRIGGER_EVENT_INSERT:
5150 tgtype_event = TRIGGER_TYPE_INSERT;
5153 Assert(oldtup == NULL);
5154 Assert(newtup != NULL);
5155 ItemPointerCopy(&(newtup->t_self), &(new_event.ate_ctid1));
5156 ItemPointerSetInvalid(&(new_event.ate_ctid2));
5160 Assert(oldtup == NULL);
5161 Assert(newtup == NULL);
5162 ItemPointerSetInvalid(&(new_event.ate_ctid1));
5163 ItemPointerSetInvalid(&(new_event.ate_ctid2));
5166 case TRIGGER_EVENT_DELETE:
5167 tgtype_event = TRIGGER_TYPE_DELETE;
5170 Assert(oldtup != NULL);
5171 Assert(newtup == NULL);
5172 ItemPointerCopy(&(oldtup->t_self), &(new_event.ate_ctid1));
5173 ItemPointerSetInvalid(&(new_event.ate_ctid2));
5177 Assert(oldtup == NULL);
5178 Assert(newtup == NULL);
5179 ItemPointerSetInvalid(&(new_event.ate_ctid1));
5180 ItemPointerSetInvalid(&(new_event.ate_ctid2));
5183 case TRIGGER_EVENT_UPDATE:
5184 tgtype_event = TRIGGER_TYPE_UPDATE;
5187 Assert(oldtup != NULL);
5188 Assert(newtup != NULL);
5189 ItemPointerCopy(&(oldtup->t_self), &(new_event.ate_ctid1));
5190 ItemPointerCopy(&(newtup->t_self), &(new_event.ate_ctid2));
5194 Assert(oldtup == NULL);
5195 Assert(newtup == NULL);
5196 ItemPointerSetInvalid(&(new_event.ate_ctid1));
5197 ItemPointerSetInvalid(&(new_event.ate_ctid2));
5200 case TRIGGER_EVENT_TRUNCATE:
5201 tgtype_event = TRIGGER_TYPE_TRUNCATE;
5202 Assert(oldtup == NULL);
5203 Assert(newtup == NULL);
5204 ItemPointerSetInvalid(&(new_event.ate_ctid1));
5205 ItemPointerSetInvalid(&(new_event.ate_ctid2));
5208 elog(ERROR, "invalid after-trigger event code: %d", event);
5209 tgtype_event = 0; /* keep compiler quiet */
5213 if (!(relkind == RELKIND_FOREIGN_TABLE && row_trigger))
5214 new_event.ate_flags = (row_trigger && event == TRIGGER_EVENT_UPDATE) ?
5215 AFTER_TRIGGER_2CTID : AFTER_TRIGGER_1CTID;
5216 /* else, we'll initialize ate_flags for each trigger */
5218 tgtype_level = (row_trigger ? TRIGGER_TYPE_ROW : TRIGGER_TYPE_STATEMENT);
5220 for (i = 0; i < trigdesc->numtriggers; i++)
5222 Trigger *trigger = &trigdesc->triggers[i];
5224 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
5229 if (!TriggerEnabled(estate, relinfo, trigger, event,
5230 modifiedCols, oldtup, newtup))
5233 if (relkind == RELKIND_FOREIGN_TABLE && row_trigger)
5235 if (fdw_tuplestore == NULL)
5238 GetTriggerTransitionTuplestore
5239 (afterTriggers.fdw_tuplestores);
5240 new_event.ate_flags = AFTER_TRIGGER_FDW_FETCH;
5243 /* subsequent event for the same tuple */
5244 new_event.ate_flags = AFTER_TRIGGER_FDW_REUSE;
5248 * If the trigger is a foreign key enforcement trigger, there are
5249 * certain cases where we can skip queueing the event because we can
5250 * tell by inspection that the FK constraint will still pass.
5252 if (TRIGGER_FIRED_BY_UPDATE(event))
5254 switch (RI_FKey_trigger_type(trigger->tgfoid))
5257 /* Update on trigger's PK table */
5258 if (!RI_FKey_pk_upd_check_required(trigger, rel,
5261 /* skip queuing this event */
5267 /* Update on trigger's FK table */
5268 if (!RI_FKey_fk_upd_check_required(trigger, rel,
5271 /* skip queuing this event */
5276 case RI_TRIGGER_NONE:
5277 /* Not an FK trigger */
5283 * If the trigger is a deferred unique constraint check trigger, only
5284 * queue it if the unique constraint was potentially violated, which
5285 * we know from index insertion time.
5287 if (trigger->tgfoid == F_UNIQUE_KEY_RECHECK)
5289 if (!list_member_oid(recheckIndexes, trigger->tgconstrindid))
5290 continue; /* Uniqueness definitely not violated */
5294 * Fill in event structure and add it to the current query's queue.
5296 new_shared.ats_event =
5297 (event & TRIGGER_EVENT_OPMASK) |
5298 (row_trigger ? TRIGGER_EVENT_ROW : 0) |
5299 (trigger->tgdeferrable ? AFTER_TRIGGER_DEFERRABLE : 0) |
5300 (trigger->tginitdeferred ? AFTER_TRIGGER_INITDEFERRED : 0);
5301 new_shared.ats_tgoid = trigger->tgoid;
5302 new_shared.ats_relid = RelationGetRelid(rel);
5303 new_shared.ats_firing_id = 0;
5305 afterTriggerAddEvent(&afterTriggers.query_stack[afterTriggers.query_depth],
5306 &new_event, &new_shared);
5310 * Finally, spool any foreign tuple(s). The tuplestore squashes them to
5311 * minimal tuples, so this loses any system columns. The executor lost
5312 * those columns before us, for an unrelated reason, so this is fine.
5317 tuplestore_puttuple(fdw_tuplestore, oldtup);
5319 tuplestore_puttuple(fdw_tuplestore, newtup);
5324 pg_trigger_depth(PG_FUNCTION_ARGS)
5326 PG_RETURN_INT32(MyTriggerDepth);