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 = lfirst_node(TriggerTransition, 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 (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
359 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
360 errmsg("\"%s\" is a partitioned table",
361 RelationGetRelationName(rel)),
362 errdetail("Triggers on partitioned tables cannot have transition tables.")));
364 if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
366 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
367 errmsg("\"%s\" is a foreign table",
368 RelationGetRelationName(rel)),
369 errdetail("Triggers on foreign tables cannot have transition tables.")));
371 if (rel->rd_rel->relkind == RELKIND_VIEW)
373 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
374 errmsg("\"%s\" is a view",
375 RelationGetRelationName(rel)),
376 errdetail("Triggers on views cannot have transition tables.")));
378 if (stmt->timing != TRIGGER_TYPE_AFTER)
380 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
381 errmsg("transition table name can only be specified for an AFTER trigger")));
383 if (TRIGGER_FOR_TRUNCATE(tgtype))
385 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
386 errmsg("TRUNCATE triggers with transition tables are not supported")));
390 if (!(TRIGGER_FOR_INSERT(tgtype) ||
391 TRIGGER_FOR_UPDATE(tgtype)))
393 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
394 errmsg("NEW TABLE can only be specified for an INSERT or UPDATE trigger")));
396 if (newtablename != NULL)
398 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
399 errmsg("NEW TABLE cannot be specified multiple times")));
401 newtablename = tt->name;
405 if (!(TRIGGER_FOR_DELETE(tgtype) ||
406 TRIGGER_FOR_UPDATE(tgtype)))
408 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
409 errmsg("OLD TABLE can only be specified for a DELETE or UPDATE trigger")));
411 if (oldtablename != NULL)
413 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
414 errmsg("OLD TABLE cannot be specified multiple times")));
416 oldtablename = tt->name;
420 if (newtablename != NULL && oldtablename != NULL &&
421 strcmp(newtablename, oldtablename) == 0)
423 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
424 errmsg("OLD TABLE name and NEW TABLE name cannot be the same")));
428 * Parse the WHEN clause, if any
430 if (stmt->whenClause)
437 /* Set up a pstate to parse with */
438 pstate = make_parsestate(NULL);
439 pstate->p_sourcetext = queryString;
442 * Set up RTEs for OLD and NEW references.
444 * 'OLD' must always have varno equal to 1 and 'NEW' equal to 2.
446 rte = addRangeTableEntryForRelation(pstate, rel,
447 makeAlias("old", NIL),
449 addRTEtoQuery(pstate, rte, false, true, true);
450 rte = addRangeTableEntryForRelation(pstate, rel,
451 makeAlias("new", NIL),
453 addRTEtoQuery(pstate, rte, false, true, true);
455 /* Transform expression. Copy to be sure we don't modify original */
456 whenClause = transformWhereClause(pstate,
457 copyObject(stmt->whenClause),
458 EXPR_KIND_TRIGGER_WHEN,
460 /* we have to fix its collations too */
461 assign_expr_collations(pstate, whenClause);
464 * Check for disallowed references to OLD/NEW.
466 * NB: pull_var_clause is okay here only because we don't allow
467 * subselects in WHEN clauses; it would fail to examine the contents
470 varList = pull_var_clause(whenClause, 0);
473 Var *var = (Var *) lfirst(lc);
478 if (!TRIGGER_FOR_ROW(tgtype))
480 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
481 errmsg("statement trigger's WHEN condition cannot reference column values"),
482 parser_errposition(pstate, var->location)));
483 if (TRIGGER_FOR_INSERT(tgtype))
485 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
486 errmsg("INSERT trigger's WHEN condition cannot reference OLD values"),
487 parser_errposition(pstate, var->location)));
488 /* system columns are okay here */
491 if (!TRIGGER_FOR_ROW(tgtype))
493 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
494 errmsg("statement trigger's WHEN condition cannot reference column values"),
495 parser_errposition(pstate, var->location)));
496 if (TRIGGER_FOR_DELETE(tgtype))
498 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
499 errmsg("DELETE trigger's WHEN condition cannot reference NEW values"),
500 parser_errposition(pstate, var->location)));
501 if (var->varattno < 0 && TRIGGER_FOR_BEFORE(tgtype))
503 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
504 errmsg("BEFORE trigger's WHEN condition cannot reference NEW system columns"),
505 parser_errposition(pstate, var->location)));
508 /* can't happen without add_missing_from, so just elog */
509 elog(ERROR, "trigger WHEN condition cannot contain references to other relations");
514 /* we'll need the rtable for recordDependencyOnExpr */
515 whenRtable = pstate->p_rtable;
517 qual = nodeToString(whenClause);
519 free_parsestate(pstate);
529 * Find and validate the trigger function.
531 funcoid = LookupFuncName(stmt->funcname, 0, fargtypes, false);
534 aclresult = pg_proc_aclcheck(funcoid, GetUserId(), ACL_EXECUTE);
535 if (aclresult != ACLCHECK_OK)
536 aclcheck_error(aclresult, ACL_KIND_PROC,
537 NameListToString(stmt->funcname));
539 funcrettype = get_func_rettype(funcoid);
540 if (funcrettype != TRIGGEROID)
543 * We allow OPAQUE just so we can load old dump files. When we see a
544 * trigger function declared OPAQUE, change it to TRIGGER.
546 if (funcrettype == OPAQUEOID)
549 (errmsg("changing return type of function %s from %s to %s",
550 NameListToString(stmt->funcname),
551 "opaque", "trigger")));
552 SetFunctionReturnType(funcoid, TRIGGEROID);
556 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
557 errmsg("function %s must return type %s",
558 NameListToString(stmt->funcname), "trigger")));
562 * If the command is a user-entered CREATE CONSTRAINT TRIGGER command that
563 * references one of the built-in RI_FKey trigger functions, assume it is
564 * from a dump of a pre-7.3 foreign key constraint, and take steps to
565 * convert this legacy representation into a regular foreign key
566 * constraint. Ugly, but necessary for loading old dump files.
568 if (stmt->isconstraint && !isInternal &&
569 list_length(stmt->args) >= 6 &&
570 (list_length(stmt->args) % 2) == 0 &&
571 RI_FKey_trigger_type(funcoid) != RI_TRIGGER_NONE)
573 /* Keep lock on target rel until end of xact */
574 heap_close(rel, NoLock);
576 ConvertTriggerToFK(stmt, funcoid);
578 return InvalidObjectAddress;
582 * If it's a user-entered CREATE CONSTRAINT TRIGGER command, make a
583 * corresponding pg_constraint entry.
585 if (stmt->isconstraint && !OidIsValid(constraintOid))
587 /* Internal callers should have made their own constraints */
589 constraintOid = CreateConstraintEntry(stmt->trigname,
590 RelationGetNamespace(rel),
595 RelationGetRelid(rel),
596 NULL, /* no conkey */
598 InvalidOid, /* no domain */
599 InvalidOid, /* no index */
600 InvalidOid, /* no foreign key */
609 NULL, /* no exclusion */
610 NULL, /* no check constraint */
615 true, /* isnoinherit */
616 isInternal); /* is_internal */
620 * Generate the trigger's OID now, so that we can use it in the name if
623 tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
625 trigoid = GetNewOid(tgrel);
628 * If trigger is internally generated, modify the provided trigger name to
629 * ensure uniqueness by appending the trigger OID. (Callers will usually
630 * supply a simple constant trigger name in these cases.)
634 snprintf(internaltrigname, sizeof(internaltrigname),
635 "%s_%u", stmt->trigname, trigoid);
636 trigname = internaltrigname;
640 /* user-defined trigger; use the specified trigger name as-is */
641 trigname = stmt->trigname;
645 * Scan pg_trigger for existing triggers on relation. We do this only to
646 * give a nice error message if there's already a trigger of the same
647 * name. (The unique index on tgrelid/tgname would complain anyway.) We
648 * can skip this for internally generated triggers, since the name
649 * modification above should be sufficient.
651 * NOTE that this is cool only because we have ShareRowExclusiveLock on
652 * the relation, so the trigger set won't be changing underneath us.
657 Anum_pg_trigger_tgrelid,
658 BTEqualStrategyNumber, F_OIDEQ,
659 ObjectIdGetDatum(RelationGetRelid(rel)));
660 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
662 while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
664 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
666 if (namestrcmp(&(pg_trigger->tgname), trigname) == 0)
668 (errcode(ERRCODE_DUPLICATE_OBJECT),
669 errmsg("trigger \"%s\" for relation \"%s\" already exists",
670 trigname, RelationGetRelationName(rel))));
672 systable_endscan(tgscan);
676 * Build the new pg_trigger tuple.
678 memset(nulls, false, sizeof(nulls));
680 values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
681 values[Anum_pg_trigger_tgname - 1] = DirectFunctionCall1(namein,
682 CStringGetDatum(trigname));
683 values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid);
684 values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype);
685 values[Anum_pg_trigger_tgenabled - 1] = CharGetDatum(TRIGGER_FIRES_ON_ORIGIN);
686 values[Anum_pg_trigger_tgisinternal - 1] = BoolGetDatum(isInternal);
687 values[Anum_pg_trigger_tgconstrrelid - 1] = ObjectIdGetDatum(constrrelid);
688 values[Anum_pg_trigger_tgconstrindid - 1] = ObjectIdGetDatum(indexOid);
689 values[Anum_pg_trigger_tgconstraint - 1] = ObjectIdGetDatum(constraintOid);
690 values[Anum_pg_trigger_tgdeferrable - 1] = BoolGetDatum(stmt->deferrable);
691 values[Anum_pg_trigger_tginitdeferred - 1] = BoolGetDatum(stmt->initdeferred);
697 int16 nargs = list_length(stmt->args);
700 foreach(le, stmt->args)
702 char *ar = strVal(lfirst(le));
704 len += strlen(ar) + 4;
711 args = (char *) palloc(len + 1);
713 foreach(le, stmt->args)
715 char *s = strVal(lfirst(le));
716 char *d = args + strlen(args);
726 values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(nargs);
727 values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
728 CStringGetDatum(args));
732 values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(0);
733 values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
734 CStringGetDatum(""));
737 /* build column number array if it's a column-specific trigger */
738 ncolumns = list_length(stmt->columns);
746 columns = (int16 *) palloc(ncolumns * sizeof(int16));
747 foreach(cell, stmt->columns)
749 char *name = strVal(lfirst(cell));
753 /* Lookup column name. System columns are not allowed */
754 attnum = attnameAttNum(rel, name, false);
755 if (attnum == InvalidAttrNumber)
757 (errcode(ERRCODE_UNDEFINED_COLUMN),
758 errmsg("column \"%s\" of relation \"%s\" does not exist",
759 name, RelationGetRelationName(rel))));
761 /* Check for duplicates */
762 for (j = i - 1; j >= 0; j--)
764 if (columns[j] == attnum)
766 (errcode(ERRCODE_DUPLICATE_COLUMN),
767 errmsg("column \"%s\" specified more than once",
771 columns[i++] = attnum;
774 tgattr = buildint2vector(columns, ncolumns);
775 values[Anum_pg_trigger_tgattr - 1] = PointerGetDatum(tgattr);
777 /* set tgqual if trigger has WHEN clause */
779 values[Anum_pg_trigger_tgqual - 1] = CStringGetTextDatum(qual);
781 nulls[Anum_pg_trigger_tgqual - 1] = true;
784 values[Anum_pg_trigger_tgoldtable - 1] = DirectFunctionCall1(namein,
785 CStringGetDatum(oldtablename));
787 nulls[Anum_pg_trigger_tgoldtable - 1] = true;
789 values[Anum_pg_trigger_tgnewtable - 1] = DirectFunctionCall1(namein,
790 CStringGetDatum(newtablename));
792 nulls[Anum_pg_trigger_tgnewtable - 1] = true;
794 tuple = heap_form_tuple(tgrel->rd_att, values, nulls);
796 /* force tuple to have the desired OID */
797 HeapTupleSetOid(tuple, trigoid);
800 * Insert tuple into pg_trigger.
802 CatalogTupleInsert(tgrel, tuple);
804 heap_freetuple(tuple);
805 heap_close(tgrel, RowExclusiveLock);
807 pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
808 pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1]));
809 pfree(DatumGetPointer(values[Anum_pg_trigger_tgattr - 1]));
811 pfree(DatumGetPointer(values[Anum_pg_trigger_tgoldtable - 1]));
813 pfree(DatumGetPointer(values[Anum_pg_trigger_tgnewtable - 1]));
816 * Update relation's pg_class entry. Crucial side-effect: other backends
817 * (and this one too!) are sent SI message to make them rebuild relcache
820 pgrel = heap_open(RelationRelationId, RowExclusiveLock);
821 tuple = SearchSysCacheCopy1(RELOID,
822 ObjectIdGetDatum(RelationGetRelid(rel)));
823 if (!HeapTupleIsValid(tuple))
824 elog(ERROR, "cache lookup failed for relation %u",
825 RelationGetRelid(rel));
827 ((Form_pg_class) GETSTRUCT(tuple))->relhastriggers = true;
829 CatalogTupleUpdate(pgrel, &tuple->t_self, tuple);
831 heap_freetuple(tuple);
832 heap_close(pgrel, RowExclusiveLock);
835 * We used to try to update the rel's relcache entry here, but that's
836 * fairly pointless since it will happen as a byproduct of the upcoming
837 * CommandCounterIncrement...
841 * Record dependencies for trigger. Always place a normal dependency on
844 myself.classId = TriggerRelationId;
845 myself.objectId = trigoid;
846 myself.objectSubId = 0;
848 referenced.classId = ProcedureRelationId;
849 referenced.objectId = funcoid;
850 referenced.objectSubId = 0;
851 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
853 if (isInternal && OidIsValid(constraintOid))
856 * Internally-generated trigger for a constraint, so make it an
857 * internal dependency of the constraint. We can skip depending on
858 * the relation(s), as there'll be an indirect dependency via the
861 referenced.classId = ConstraintRelationId;
862 referenced.objectId = constraintOid;
863 referenced.objectSubId = 0;
864 recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
869 * User CREATE TRIGGER, so place dependencies. We make trigger be
870 * auto-dropped if its relation is dropped or if the FK relation is
871 * dropped. (Auto drop is compatible with our pre-7.3 behavior.)
873 referenced.classId = RelationRelationId;
874 referenced.objectId = RelationGetRelid(rel);
875 referenced.objectSubId = 0;
876 recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
877 if (OidIsValid(constrrelid))
879 referenced.classId = RelationRelationId;
880 referenced.objectId = constrrelid;
881 referenced.objectSubId = 0;
882 recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
884 /* Not possible to have an index dependency in this case */
885 Assert(!OidIsValid(indexOid));
888 * If it's a user-specified constraint trigger, make the constraint
889 * internally dependent on the trigger instead of vice versa.
891 if (OidIsValid(constraintOid))
893 referenced.classId = ConstraintRelationId;
894 referenced.objectId = constraintOid;
895 referenced.objectSubId = 0;
896 recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
900 /* If column-specific trigger, add normal dependencies on columns */
905 referenced.classId = RelationRelationId;
906 referenced.objectId = RelationGetRelid(rel);
907 for (i = 0; i < ncolumns; i++)
909 referenced.objectSubId = columns[i];
910 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
915 * If it has a WHEN clause, add dependencies on objects mentioned in the
916 * expression (eg, functions, as well as any columns used).
918 if (whenClause != NULL)
919 recordDependencyOnExpr(&myself, whenClause, whenRtable,
922 /* Post creation hook for new trigger */
923 InvokeObjectPostCreateHookArg(TriggerRelationId, trigoid, 0,
926 /* Keep lock on target rel until end of xact */
927 heap_close(rel, NoLock);
934 * Convert legacy (pre-7.3) CREATE CONSTRAINT TRIGGER commands into
935 * full-fledged foreign key constraints.
937 * The conversion is complex because a pre-7.3 foreign key involved three
938 * separate triggers, which were reported separately in dumps. While the
939 * single trigger on the referencing table adds no new information, we need
940 * to know the trigger functions of both of the triggers on the referenced
941 * table to build the constraint declaration. Also, due to lack of proper
942 * dependency checking pre-7.3, it is possible that the source database had
943 * an incomplete set of triggers resulting in an only partially enforced
944 * FK constraint. (This would happen if one of the tables had been dropped
945 * and re-created, but only if the DB had been affected by a 7.0 pg_dump bug
946 * that caused loss of tgconstrrelid information.) We choose to translate to
947 * an FK constraint only when we've seen all three triggers of a set. This is
948 * implemented by storing unmatched items in a list in TopMemoryContext.
949 * We match triggers together by comparing the trigger arguments (which
950 * include constraint name, table and column names, so should be good enough).
954 List *args; /* list of (T_String) Values or NIL */
955 Oid funcoids[3]; /* OIDs of trigger functions */
956 /* The three function OIDs are stored in the order update, delete, child */
960 ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
962 static List *info_list = NIL;
964 static const char *const funcdescr[3] = {
965 gettext_noop("Found referenced table's UPDATE trigger."),
966 gettext_noop("Found referenced table's DELETE trigger."),
967 gettext_noop("Found referencing table's trigger.")
973 char fk_matchtype = FKCONSTR_MATCH_SIMPLE;
974 List *fk_attrs = NIL;
975 List *pk_attrs = NIL;
978 OldTriggerInfo *info = NULL;
982 /* Parse out the trigger arguments */
983 constr_name = strVal(linitial(stmt->args));
984 fk_table_name = strVal(lsecond(stmt->args));
985 pk_table_name = strVal(lthird(stmt->args));
987 foreach(l, stmt->args)
989 Value *arg = (Value *) lfirst(l);
992 if (i < 4) /* skip constraint and table names */
994 if (i == 4) /* handle match type */
996 if (strcmp(strVal(arg), "FULL") == 0)
997 fk_matchtype = FKCONSTR_MATCH_FULL;
999 fk_matchtype = FKCONSTR_MATCH_SIMPLE;
1003 fk_attrs = lappend(fk_attrs, arg);
1005 pk_attrs = lappend(pk_attrs, arg);
1008 /* Prepare description of constraint for use in messages */
1009 initStringInfo(&buf);
1010 appendStringInfo(&buf, "FOREIGN KEY %s(",
1011 quote_identifier(fk_table_name));
1013 foreach(l, fk_attrs)
1015 Value *arg = (Value *) lfirst(l);
1018 appendStringInfoChar(&buf, ',');
1019 appendStringInfoString(&buf, quote_identifier(strVal(arg)));
1021 appendStringInfo(&buf, ") REFERENCES %s(",
1022 quote_identifier(pk_table_name));
1024 foreach(l, pk_attrs)
1026 Value *arg = (Value *) lfirst(l);
1029 appendStringInfoChar(&buf, ',');
1030 appendStringInfoString(&buf, quote_identifier(strVal(arg)));
1032 appendStringInfoChar(&buf, ')');
1034 /* Identify class of trigger --- update, delete, or referencing-table */
1037 case F_RI_FKEY_CASCADE_UPD:
1038 case F_RI_FKEY_RESTRICT_UPD:
1039 case F_RI_FKEY_SETNULL_UPD:
1040 case F_RI_FKEY_SETDEFAULT_UPD:
1041 case F_RI_FKEY_NOACTION_UPD:
1045 case F_RI_FKEY_CASCADE_DEL:
1046 case F_RI_FKEY_RESTRICT_DEL:
1047 case F_RI_FKEY_SETNULL_DEL:
1048 case F_RI_FKEY_SETDEFAULT_DEL:
1049 case F_RI_FKEY_NOACTION_DEL:
1058 /* See if we have a match to this trigger */
1059 foreach(l, info_list)
1061 info = (OldTriggerInfo *) lfirst(l);
1062 if (info->funcoids[funcnum] == InvalidOid &&
1063 equal(info->args, stmt->args))
1065 info->funcoids[funcnum] = funcoid;
1072 /* First trigger of set, so create a new list entry */
1073 MemoryContext oldContext;
1076 (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
1077 constr_name, buf.data),
1078 errdetail_internal("%s", _(funcdescr[funcnum]))));
1079 oldContext = MemoryContextSwitchTo(TopMemoryContext);
1080 info = (OldTriggerInfo *) palloc0(sizeof(OldTriggerInfo));
1081 info->args = copyObject(stmt->args);
1082 info->funcoids[funcnum] = funcoid;
1083 info_list = lappend(info_list, info);
1084 MemoryContextSwitchTo(oldContext);
1086 else if (info->funcoids[0] == InvalidOid ||
1087 info->funcoids[1] == InvalidOid ||
1088 info->funcoids[2] == InvalidOid)
1090 /* Second trigger of set */
1092 (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
1093 constr_name, buf.data),
1094 errdetail_internal("%s", _(funcdescr[funcnum]))));
1098 /* OK, we have a set, so make the FK constraint ALTER TABLE cmd */
1099 AlterTableStmt *atstmt = makeNode(AlterTableStmt);
1100 AlterTableCmd *atcmd = makeNode(AlterTableCmd);
1101 Constraint *fkcon = makeNode(Constraint);
1102 PlannedStmt *wrapper = makeNode(PlannedStmt);
1105 (errmsg("converting trigger group into constraint \"%s\" %s",
1106 constr_name, buf.data),
1107 errdetail_internal("%s", _(funcdescr[funcnum]))));
1108 fkcon->contype = CONSTR_FOREIGN;
1109 fkcon->location = -1;
1112 /* This trigger is on the FK table */
1113 atstmt->relation = stmt->relation;
1114 if (stmt->constrrel)
1115 fkcon->pktable = stmt->constrrel;
1118 /* Work around ancient pg_dump bug that omitted constrrel */
1119 fkcon->pktable = makeRangeVar(NULL, pk_table_name, -1);
1124 /* This trigger is on the PK table */
1125 fkcon->pktable = stmt->relation;
1126 if (stmt->constrrel)
1127 atstmt->relation = stmt->constrrel;
1130 /* Work around ancient pg_dump bug that omitted constrrel */
1131 atstmt->relation = makeRangeVar(NULL, fk_table_name, -1);
1134 atstmt->cmds = list_make1(atcmd);
1135 atstmt->relkind = OBJECT_TABLE;
1136 atcmd->subtype = AT_AddConstraint;
1137 atcmd->def = (Node *) fkcon;
1138 if (strcmp(constr_name, "<unnamed>") == 0)
1139 fkcon->conname = NULL;
1141 fkcon->conname = constr_name;
1142 fkcon->fk_attrs = fk_attrs;
1143 fkcon->pk_attrs = pk_attrs;
1144 fkcon->fk_matchtype = fk_matchtype;
1145 switch (info->funcoids[0])
1147 case F_RI_FKEY_NOACTION_UPD:
1148 fkcon->fk_upd_action = FKCONSTR_ACTION_NOACTION;
1150 case F_RI_FKEY_CASCADE_UPD:
1151 fkcon->fk_upd_action = FKCONSTR_ACTION_CASCADE;
1153 case F_RI_FKEY_RESTRICT_UPD:
1154 fkcon->fk_upd_action = FKCONSTR_ACTION_RESTRICT;
1156 case F_RI_FKEY_SETNULL_UPD:
1157 fkcon->fk_upd_action = FKCONSTR_ACTION_SETNULL;
1159 case F_RI_FKEY_SETDEFAULT_UPD:
1160 fkcon->fk_upd_action = FKCONSTR_ACTION_SETDEFAULT;
1163 /* can't get here because of earlier checks */
1164 elog(ERROR, "confused about RI update function");
1166 switch (info->funcoids[1])
1168 case F_RI_FKEY_NOACTION_DEL:
1169 fkcon->fk_del_action = FKCONSTR_ACTION_NOACTION;
1171 case F_RI_FKEY_CASCADE_DEL:
1172 fkcon->fk_del_action = FKCONSTR_ACTION_CASCADE;
1174 case F_RI_FKEY_RESTRICT_DEL:
1175 fkcon->fk_del_action = FKCONSTR_ACTION_RESTRICT;
1177 case F_RI_FKEY_SETNULL_DEL:
1178 fkcon->fk_del_action = FKCONSTR_ACTION_SETNULL;
1180 case F_RI_FKEY_SETDEFAULT_DEL:
1181 fkcon->fk_del_action = FKCONSTR_ACTION_SETDEFAULT;
1184 /* can't get here because of earlier checks */
1185 elog(ERROR, "confused about RI delete function");
1187 fkcon->deferrable = stmt->deferrable;
1188 fkcon->initdeferred = stmt->initdeferred;
1189 fkcon->skip_validation = false;
1190 fkcon->initially_valid = true;
1192 /* finally, wrap it in a dummy PlannedStmt */
1193 wrapper->commandType = CMD_UTILITY;
1194 wrapper->canSetTag = false;
1195 wrapper->utilityStmt = (Node *) atstmt;
1196 wrapper->stmt_location = -1;
1197 wrapper->stmt_len = -1;
1199 /* ... and execute it */
1200 ProcessUtility(wrapper,
1201 "(generated ALTER TABLE ADD FOREIGN KEY command)",
1202 PROCESS_UTILITY_SUBCOMMAND, NULL, NULL,
1203 None_Receiver, NULL);
1205 /* Remove the matched item from the list */
1206 info_list = list_delete_ptr(info_list, info);
1208 /* We leak the copied args ... not worth worrying about */
1213 * Guts of trigger deletion.
1216 RemoveTriggerById(Oid trigOid)
1220 ScanKeyData skey[1];
1225 tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
1228 * Find the trigger to delete.
1230 ScanKeyInit(&skey[0],
1231 ObjectIdAttributeNumber,
1232 BTEqualStrategyNumber, F_OIDEQ,
1233 ObjectIdGetDatum(trigOid));
1235 tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
1238 tup = systable_getnext(tgscan);
1239 if (!HeapTupleIsValid(tup))
1240 elog(ERROR, "could not find tuple for trigger %u", trigOid);
1243 * Open and exclusive-lock the relation the trigger belongs to.
1245 relid = ((Form_pg_trigger) GETSTRUCT(tup))->tgrelid;
1247 rel = heap_open(relid, AccessExclusiveLock);
1249 if (rel->rd_rel->relkind != RELKIND_RELATION &&
1250 rel->rd_rel->relkind != RELKIND_VIEW &&
1251 rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
1252 rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1254 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1255 errmsg("\"%s\" is not a table, view, or foreign table",
1256 RelationGetRelationName(rel))));
1258 if (!allowSystemTableMods && IsSystemRelation(rel))
1260 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1261 errmsg("permission denied: \"%s\" is a system catalog",
1262 RelationGetRelationName(rel))));
1265 * Delete the pg_trigger tuple.
1267 CatalogTupleDelete(tgrel, &tup->t_self);
1269 systable_endscan(tgscan);
1270 heap_close(tgrel, RowExclusiveLock);
1273 * We do not bother to try to determine whether any other triggers remain,
1274 * which would be needed in order to decide whether it's safe to clear the
1275 * relation's relhastriggers. (In any case, there might be a concurrent
1276 * process adding new triggers.) Instead, just force a relcache inval to
1277 * make other backends (and this one too!) rebuild their relcache entries.
1278 * There's no great harm in leaving relhastriggers true even if there are
1281 CacheInvalidateRelcache(rel);
1283 /* Keep lock on trigger's rel until end of xact */
1284 heap_close(rel, NoLock);
1288 * get_trigger_oid - Look up a trigger by name to find its OID.
1290 * If missing_ok is false, throw an error if trigger not found. If
1291 * true, just return InvalidOid.
1294 get_trigger_oid(Oid relid, const char *trigname, bool missing_ok)
1297 ScanKeyData skey[2];
1303 * Find the trigger, verify permissions, set up object address
1305 tgrel = heap_open(TriggerRelationId, AccessShareLock);
1307 ScanKeyInit(&skey[0],
1308 Anum_pg_trigger_tgrelid,
1309 BTEqualStrategyNumber, F_OIDEQ,
1310 ObjectIdGetDatum(relid));
1311 ScanKeyInit(&skey[1],
1312 Anum_pg_trigger_tgname,
1313 BTEqualStrategyNumber, F_NAMEEQ,
1314 CStringGetDatum(trigname));
1316 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1319 tup = systable_getnext(tgscan);
1321 if (!HeapTupleIsValid(tup))
1325 (errcode(ERRCODE_UNDEFINED_OBJECT),
1326 errmsg("trigger \"%s\" for table \"%s\" does not exist",
1327 trigname, get_rel_name(relid))));
1332 oid = HeapTupleGetOid(tup);
1335 systable_endscan(tgscan);
1336 heap_close(tgrel, AccessShareLock);
1341 * Perform permissions and integrity checks before acquiring a relation lock.
1344 RangeVarCallbackForRenameTrigger(const RangeVar *rv, Oid relid, Oid oldrelid,
1350 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1351 if (!HeapTupleIsValid(tuple))
1352 return; /* concurrently dropped */
1353 form = (Form_pg_class) GETSTRUCT(tuple);
1355 /* only tables and views can have triggers */
1356 if (form->relkind != RELKIND_RELATION && form->relkind != RELKIND_VIEW &&
1357 form->relkind != RELKIND_FOREIGN_TABLE &&
1358 form->relkind != RELKIND_PARTITIONED_TABLE)
1360 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1361 errmsg("\"%s\" is not a table, view, or foreign table",
1364 /* you must own the table to rename one of its triggers */
1365 if (!pg_class_ownercheck(relid, GetUserId()))
1366 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, rv->relname);
1367 if (!allowSystemTableMods && IsSystemClass(relid, form))
1369 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1370 errmsg("permission denied: \"%s\" is a system catalog",
1373 ReleaseSysCache(tuple);
1377 * renametrig - changes the name of a trigger on a relation
1379 * trigger name is changed in trigger catalog.
1380 * No record of the previous name is kept.
1382 * get proper relrelation from relation catalog (if not arg)
1383 * scan trigger catalog
1384 * for name conflict (within rel)
1385 * for original trigger (if not arg)
1386 * modify tgname in trigger tuple
1387 * update row in catalog
1390 renametrig(RenameStmt *stmt)
1399 ObjectAddress address;
1402 * Look up name, check permissions, and acquire lock (which we will NOT
1403 * release until end of transaction).
1405 relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
1407 RangeVarCallbackForRenameTrigger,
1410 /* Have lock already, so just need to build relcache entry. */
1411 targetrel = relation_open(relid, NoLock);
1414 * Scan pg_trigger twice for existing triggers on relation. We do this in
1415 * order to ensure a trigger does not exist with newname (The unique index
1416 * on tgrelid/tgname would complain anyway) and to ensure a trigger does
1417 * exist with oldname.
1419 * NOTE that this is cool only because we have AccessExclusiveLock on the
1420 * relation, so the trigger set won't be changing underneath us.
1422 tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
1425 * First pass -- look for name conflict
1427 ScanKeyInit(&key[0],
1428 Anum_pg_trigger_tgrelid,
1429 BTEqualStrategyNumber, F_OIDEQ,
1430 ObjectIdGetDatum(relid));
1431 ScanKeyInit(&key[1],
1432 Anum_pg_trigger_tgname,
1433 BTEqualStrategyNumber, F_NAMEEQ,
1434 PointerGetDatum(stmt->newname));
1435 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1437 if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1439 (errcode(ERRCODE_DUPLICATE_OBJECT),
1440 errmsg("trigger \"%s\" for relation \"%s\" already exists",
1441 stmt->newname, RelationGetRelationName(targetrel))));
1442 systable_endscan(tgscan);
1445 * Second pass -- look for trigger existing with oldname and update
1447 ScanKeyInit(&key[0],
1448 Anum_pg_trigger_tgrelid,
1449 BTEqualStrategyNumber, F_OIDEQ,
1450 ObjectIdGetDatum(relid));
1451 ScanKeyInit(&key[1],
1452 Anum_pg_trigger_tgname,
1453 BTEqualStrategyNumber, F_NAMEEQ,
1454 PointerGetDatum(stmt->subname));
1455 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1457 if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1459 tgoid = HeapTupleGetOid(tuple);
1462 * Update pg_trigger tuple with new tgname.
1464 tuple = heap_copytuple(tuple); /* need a modifiable copy */
1466 namestrcpy(&((Form_pg_trigger) GETSTRUCT(tuple))->tgname,
1469 CatalogTupleUpdate(tgrel, &tuple->t_self, tuple);
1471 InvokeObjectPostAlterHook(TriggerRelationId,
1472 HeapTupleGetOid(tuple), 0);
1475 * Invalidate relation's relcache entry so that other backends (and
1476 * this one too!) are sent SI message to make them rebuild relcache
1477 * entries. (Ideally this should happen automatically...)
1479 CacheInvalidateRelcache(targetrel);
1484 (errcode(ERRCODE_UNDEFINED_OBJECT),
1485 errmsg("trigger \"%s\" for table \"%s\" does not exist",
1486 stmt->subname, RelationGetRelationName(targetrel))));
1489 ObjectAddressSet(address, TriggerRelationId, tgoid);
1491 systable_endscan(tgscan);
1493 heap_close(tgrel, RowExclusiveLock);
1496 * Close rel, but keep exclusive lock!
1498 relation_close(targetrel, NoLock);
1505 * EnableDisableTrigger()
1507 * Called by ALTER TABLE ENABLE/DISABLE [ REPLICA | ALWAYS ] TRIGGER
1508 * to change 'tgenabled' field for the specified trigger(s)
1510 * rel: relation to process (caller must hold suitable lock on it)
1511 * tgname: trigger to process, or NULL to scan all triggers
1512 * fires_when: new value for tgenabled field. In addition to generic
1513 * enablement/disablement, this also defines when the trigger
1514 * should be fired in session replication roles.
1515 * skip_system: if true, skip "system" triggers (constraint triggers)
1517 * Caller should have checked permissions for the table; here we also
1518 * enforce that superuser privilege is required to alter the state of
1522 EnableDisableTrigger(Relation rel, const char *tgname,
1523 char fires_when, bool skip_system)
1527 ScanKeyData keys[2];
1533 /* Scan the relevant entries in pg_triggers */
1534 tgrel = heap_open(TriggerRelationId, RowExclusiveLock);
1536 ScanKeyInit(&keys[0],
1537 Anum_pg_trigger_tgrelid,
1538 BTEqualStrategyNumber, F_OIDEQ,
1539 ObjectIdGetDatum(RelationGetRelid(rel)));
1542 ScanKeyInit(&keys[1],
1543 Anum_pg_trigger_tgname,
1544 BTEqualStrategyNumber, F_NAMEEQ,
1545 CStringGetDatum(tgname));
1551 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1554 found = changed = false;
1556 while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1558 Form_pg_trigger oldtrig = (Form_pg_trigger) GETSTRUCT(tuple);
1560 if (oldtrig->tgisinternal)
1562 /* system trigger ... ok to process? */
1567 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1568 errmsg("permission denied: \"%s\" is a system trigger",
1569 NameStr(oldtrig->tgname))));
1574 if (oldtrig->tgenabled != fires_when)
1576 /* need to change this one ... make a copy to scribble on */
1577 HeapTuple newtup = heap_copytuple(tuple);
1578 Form_pg_trigger newtrig = (Form_pg_trigger) GETSTRUCT(newtup);
1580 newtrig->tgenabled = fires_when;
1582 CatalogTupleUpdate(tgrel, &newtup->t_self, newtup);
1584 heap_freetuple(newtup);
1589 InvokeObjectPostAlterHook(TriggerRelationId,
1590 HeapTupleGetOid(tuple), 0);
1593 systable_endscan(tgscan);
1595 heap_close(tgrel, RowExclusiveLock);
1597 if (tgname && !found)
1599 (errcode(ERRCODE_UNDEFINED_OBJECT),
1600 errmsg("trigger \"%s\" for table \"%s\" does not exist",
1601 tgname, RelationGetRelationName(rel))));
1604 * If we changed anything, broadcast a SI inval message to force each
1605 * backend (including our own!) to rebuild relation's relcache entry.
1606 * Otherwise they will fail to apply the change promptly.
1609 CacheInvalidateRelcache(rel);
1614 * Build trigger data to attach to the given relcache entry.
1616 * Note that trigger data attached to a relcache entry must be stored in
1617 * CacheMemoryContext to ensure it survives as long as the relcache entry.
1618 * But we should be running in a less long-lived working context. To avoid
1619 * leaking cache memory if this routine fails partway through, we build a
1620 * temporary TriggerDesc in working memory and then copy the completed
1621 * structure into cache memory.
1624 RelationBuildTriggers(Relation relation)
1626 TriggerDesc *trigdesc;
1634 MemoryContext oldContext;
1638 * Allocate a working array to hold the triggers (the array is extended if
1642 triggers = (Trigger *) palloc(maxtrigs * sizeof(Trigger));
1646 * Note: since we scan the triggers using TriggerRelidNameIndexId, we will
1647 * be reading the triggers in name order, except possibly during
1648 * emergency-recovery operations (ie, IgnoreSystemIndexes). This in turn
1649 * ensures that triggers will be fired in name order.
1652 Anum_pg_trigger_tgrelid,
1653 BTEqualStrategyNumber, F_OIDEQ,
1654 ObjectIdGetDatum(RelationGetRelid(relation)));
1656 tgrel = heap_open(TriggerRelationId, AccessShareLock);
1657 tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1660 while (HeapTupleIsValid(htup = systable_getnext(tgscan)))
1662 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
1667 if (numtrigs >= maxtrigs)
1670 triggers = (Trigger *) repalloc(triggers, maxtrigs * sizeof(Trigger));
1672 build = &(triggers[numtrigs]);
1674 build->tgoid = HeapTupleGetOid(htup);
1675 build->tgname = DatumGetCString(DirectFunctionCall1(nameout,
1676 NameGetDatum(&pg_trigger->tgname)));
1677 build->tgfoid = pg_trigger->tgfoid;
1678 build->tgtype = pg_trigger->tgtype;
1679 build->tgenabled = pg_trigger->tgenabled;
1680 build->tgisinternal = pg_trigger->tgisinternal;
1681 build->tgconstrrelid = pg_trigger->tgconstrrelid;
1682 build->tgconstrindid = pg_trigger->tgconstrindid;
1683 build->tgconstraint = pg_trigger->tgconstraint;
1684 build->tgdeferrable = pg_trigger->tgdeferrable;
1685 build->tginitdeferred = pg_trigger->tginitdeferred;
1686 build->tgnargs = pg_trigger->tgnargs;
1687 /* tgattr is first var-width field, so OK to access directly */
1688 build->tgnattr = pg_trigger->tgattr.dim1;
1689 if (build->tgnattr > 0)
1691 build->tgattr = (int16 *) palloc(build->tgnattr * sizeof(int16));
1692 memcpy(build->tgattr, &(pg_trigger->tgattr.values),
1693 build->tgnattr * sizeof(int16));
1696 build->tgattr = NULL;
1697 if (build->tgnargs > 0)
1702 val = DatumGetByteaPP(fastgetattr(htup,
1703 Anum_pg_trigger_tgargs,
1704 tgrel->rd_att, &isnull));
1706 elog(ERROR, "tgargs is null in trigger for relation \"%s\"",
1707 RelationGetRelationName(relation));
1708 p = (char *) VARDATA_ANY(val);
1709 build->tgargs = (char **) palloc(build->tgnargs * sizeof(char *));
1710 for (i = 0; i < build->tgnargs; i++)
1712 build->tgargs[i] = pstrdup(p);
1717 build->tgargs = NULL;
1719 datum = fastgetattr(htup, Anum_pg_trigger_tgoldtable,
1720 tgrel->rd_att, &isnull);
1723 DatumGetCString(DirectFunctionCall1(nameout, datum));
1725 build->tgoldtable = NULL;
1727 datum = fastgetattr(htup, Anum_pg_trigger_tgnewtable,
1728 tgrel->rd_att, &isnull);
1731 DatumGetCString(DirectFunctionCall1(nameout, datum));
1733 build->tgnewtable = NULL;
1735 datum = fastgetattr(htup, Anum_pg_trigger_tgqual,
1736 tgrel->rd_att, &isnull);
1738 build->tgqual = TextDatumGetCString(datum);
1740 build->tgqual = NULL;
1745 systable_endscan(tgscan);
1746 heap_close(tgrel, AccessShareLock);
1748 /* There might not be any triggers */
1755 /* Build trigdesc */
1756 trigdesc = (TriggerDesc *) palloc0(sizeof(TriggerDesc));
1757 trigdesc->triggers = triggers;
1758 trigdesc->numtriggers = numtrigs;
1759 for (i = 0; i < numtrigs; i++)
1760 SetTriggerFlags(trigdesc, &(triggers[i]));
1762 /* Copy completed trigdesc into cache storage */
1763 oldContext = MemoryContextSwitchTo(CacheMemoryContext);
1764 relation->trigdesc = CopyTriggerDesc(trigdesc);
1765 MemoryContextSwitchTo(oldContext);
1767 /* Release working memory */
1768 FreeTriggerDesc(trigdesc);
1772 * Update the TriggerDesc's hint flags to include the specified trigger
1775 SetTriggerFlags(TriggerDesc *trigdesc, Trigger *trigger)
1777 int16 tgtype = trigger->tgtype;
1779 trigdesc->trig_insert_before_row |=
1780 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1781 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
1782 trigdesc->trig_insert_after_row |=
1783 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1784 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
1785 trigdesc->trig_insert_instead_row |=
1786 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1787 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_INSERT);
1788 trigdesc->trig_insert_before_statement |=
1789 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1790 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
1791 trigdesc->trig_insert_after_statement |=
1792 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1793 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
1794 trigdesc->trig_update_before_row |=
1795 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1796 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
1797 trigdesc->trig_update_after_row |=
1798 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1799 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
1800 trigdesc->trig_update_instead_row |=
1801 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1802 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_UPDATE);
1803 trigdesc->trig_update_before_statement |=
1804 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1805 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
1806 trigdesc->trig_update_after_statement |=
1807 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1808 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
1809 trigdesc->trig_delete_before_row |=
1810 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1811 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
1812 trigdesc->trig_delete_after_row |=
1813 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1814 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
1815 trigdesc->trig_delete_instead_row |=
1816 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
1817 TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_DELETE);
1818 trigdesc->trig_delete_before_statement |=
1819 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1820 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
1821 trigdesc->trig_delete_after_statement |=
1822 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1823 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
1824 /* there are no row-level truncate triggers */
1825 trigdesc->trig_truncate_before_statement |=
1826 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1827 TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_TRUNCATE);
1828 trigdesc->trig_truncate_after_statement |=
1829 TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
1830 TRIGGER_TYPE_AFTER, TRIGGER_TYPE_TRUNCATE);
1832 trigdesc->trig_insert_new_table |=
1833 (TRIGGER_FOR_INSERT(tgtype) &&
1834 TRIGGER_USES_TRANSITION_TABLE(trigger->tgnewtable));
1835 trigdesc->trig_update_old_table |=
1836 (TRIGGER_FOR_UPDATE(tgtype) &&
1837 TRIGGER_USES_TRANSITION_TABLE(trigger->tgoldtable));
1838 trigdesc->trig_update_new_table |=
1839 (TRIGGER_FOR_UPDATE(tgtype) &&
1840 TRIGGER_USES_TRANSITION_TABLE(trigger->tgnewtable));
1841 trigdesc->trig_delete_old_table |=
1842 (TRIGGER_FOR_DELETE(tgtype) &&
1843 TRIGGER_USES_TRANSITION_TABLE(trigger->tgoldtable));
1847 * Copy a TriggerDesc data structure.
1849 * The copy is allocated in the current memory context.
1852 CopyTriggerDesc(TriggerDesc *trigdesc)
1854 TriggerDesc *newdesc;
1858 if (trigdesc == NULL || trigdesc->numtriggers <= 0)
1861 newdesc = (TriggerDesc *) palloc(sizeof(TriggerDesc));
1862 memcpy(newdesc, trigdesc, sizeof(TriggerDesc));
1864 trigger = (Trigger *) palloc(trigdesc->numtriggers * sizeof(Trigger));
1865 memcpy(trigger, trigdesc->triggers,
1866 trigdesc->numtriggers * sizeof(Trigger));
1867 newdesc->triggers = trigger;
1869 for (i = 0; i < trigdesc->numtriggers; i++)
1871 trigger->tgname = pstrdup(trigger->tgname);
1872 if (trigger->tgnattr > 0)
1876 newattr = (int16 *) palloc(trigger->tgnattr * sizeof(int16));
1877 memcpy(newattr, trigger->tgattr,
1878 trigger->tgnattr * sizeof(int16));
1879 trigger->tgattr = newattr;
1881 if (trigger->tgnargs > 0)
1886 newargs = (char **) palloc(trigger->tgnargs * sizeof(char *));
1887 for (j = 0; j < trigger->tgnargs; j++)
1888 newargs[j] = pstrdup(trigger->tgargs[j]);
1889 trigger->tgargs = newargs;
1891 if (trigger->tgqual)
1892 trigger->tgqual = pstrdup(trigger->tgqual);
1893 if (trigger->tgoldtable)
1894 trigger->tgoldtable = pstrdup(trigger->tgoldtable);
1895 if (trigger->tgnewtable)
1896 trigger->tgnewtable = pstrdup(trigger->tgnewtable);
1904 * Free a TriggerDesc data structure.
1907 FreeTriggerDesc(TriggerDesc *trigdesc)
1912 if (trigdesc == NULL)
1915 trigger = trigdesc->triggers;
1916 for (i = 0; i < trigdesc->numtriggers; i++)
1918 pfree(trigger->tgname);
1919 if (trigger->tgnattr > 0)
1920 pfree(trigger->tgattr);
1921 if (trigger->tgnargs > 0)
1923 while (--(trigger->tgnargs) >= 0)
1924 pfree(trigger->tgargs[trigger->tgnargs]);
1925 pfree(trigger->tgargs);
1927 if (trigger->tgqual)
1928 pfree(trigger->tgqual);
1929 if (trigger->tgoldtable)
1930 pfree(trigger->tgoldtable);
1931 if (trigger->tgnewtable)
1932 pfree(trigger->tgnewtable);
1935 pfree(trigdesc->triggers);
1940 * Compare two TriggerDesc structures for logical equality.
1944 equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
1950 * We need not examine the hint flags, just the trigger array itself; if
1951 * we have the same triggers with the same types, the flags should match.
1953 * As of 7.3 we assume trigger set ordering is significant in the
1954 * comparison; so we just compare corresponding slots of the two sets.
1956 * Note: comparing the stringToNode forms of the WHEN clauses means that
1957 * parse column locations will affect the result. This is okay as long as
1958 * this function is only used for detecting exact equality, as for example
1959 * in checking for staleness of a cache entry.
1961 if (trigdesc1 != NULL)
1963 if (trigdesc2 == NULL)
1965 if (trigdesc1->numtriggers != trigdesc2->numtriggers)
1967 for (i = 0; i < trigdesc1->numtriggers; i++)
1969 Trigger *trig1 = trigdesc1->triggers + i;
1970 Trigger *trig2 = trigdesc2->triggers + i;
1972 if (trig1->tgoid != trig2->tgoid)
1974 if (strcmp(trig1->tgname, trig2->tgname) != 0)
1976 if (trig1->tgfoid != trig2->tgfoid)
1978 if (trig1->tgtype != trig2->tgtype)
1980 if (trig1->tgenabled != trig2->tgenabled)
1982 if (trig1->tgisinternal != trig2->tgisinternal)
1984 if (trig1->tgconstrrelid != trig2->tgconstrrelid)
1986 if (trig1->tgconstrindid != trig2->tgconstrindid)
1988 if (trig1->tgconstraint != trig2->tgconstraint)
1990 if (trig1->tgdeferrable != trig2->tgdeferrable)
1992 if (trig1->tginitdeferred != trig2->tginitdeferred)
1994 if (trig1->tgnargs != trig2->tgnargs)
1996 if (trig1->tgnattr != trig2->tgnattr)
1998 if (trig1->tgnattr > 0 &&
1999 memcmp(trig1->tgattr, trig2->tgattr,
2000 trig1->tgnattr * sizeof(int16)) != 0)
2002 for (j = 0; j < trig1->tgnargs; j++)
2003 if (strcmp(trig1->tgargs[j], trig2->tgargs[j]) != 0)
2005 if (trig1->tgqual == NULL && trig2->tgqual == NULL)
2007 else if (trig1->tgqual == NULL || trig2->tgqual == NULL)
2009 else if (strcmp(trig1->tgqual, trig2->tgqual) != 0)
2011 if (trig1->tgoldtable == NULL && trig2->tgoldtable == NULL)
2013 else if (trig1->tgoldtable == NULL || trig2->tgoldtable == NULL)
2015 else if (strcmp(trig1->tgoldtable, trig2->tgoldtable) != 0)
2017 if (trig1->tgnewtable == NULL && trig2->tgnewtable == NULL)
2019 else if (trig1->tgnewtable == NULL || trig2->tgnewtable == NULL)
2021 else if (strcmp(trig1->tgnewtable, trig2->tgnewtable) != 0)
2025 else if (trigdesc2 != NULL)
2029 #endif /* NOT_USED */
2032 * Call a trigger function.
2034 * trigdata: trigger descriptor.
2035 * tgindx: trigger's index in finfo and instr arrays.
2036 * finfo: array of cached trigger function call information.
2037 * instr: optional array of EXPLAIN ANALYZE instrumentation state.
2038 * per_tuple_context: memory context to execute the function in.
2040 * Returns the tuple (or NULL) as returned by the function.
2043 ExecCallTriggerFunc(TriggerData *trigdata,
2046 Instrumentation *instr,
2047 MemoryContext per_tuple_context)
2049 FunctionCallInfoData fcinfo;
2050 PgStat_FunctionCallUsage fcusage;
2052 MemoryContext oldContext;
2055 * Protect against code paths that may fail to initialize transition table
2058 Assert(((TRIGGER_FIRED_BY_INSERT(trigdata->tg_event) ||
2059 TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event) ||
2060 TRIGGER_FIRED_BY_DELETE(trigdata->tg_event)) &&
2061 TRIGGER_FIRED_AFTER(trigdata->tg_event) &&
2062 !(trigdata->tg_event & AFTER_TRIGGER_DEFERRABLE) &&
2063 !(trigdata->tg_event & AFTER_TRIGGER_INITDEFERRED)) ||
2064 (trigdata->tg_oldtable == NULL && trigdata->tg_newtable == NULL));
2069 * We cache fmgr lookup info, to avoid making the lookup again on each
2072 if (finfo->fn_oid == InvalidOid)
2073 fmgr_info(trigdata->tg_trigger->tgfoid, finfo);
2075 Assert(finfo->fn_oid == trigdata->tg_trigger->tgfoid);
2078 * If doing EXPLAIN ANALYZE, start charging time to this trigger.
2081 InstrStartNode(instr + tgindx);
2084 * Do the function evaluation in the per-tuple memory context, so that
2085 * leaked memory will be reclaimed once per tuple. Note in particular that
2086 * any new tuple created by the trigger function will live till the end of
2089 oldContext = MemoryContextSwitchTo(per_tuple_context);
2092 * Call the function, passing no arguments but setting a context.
2094 InitFunctionCallInfoData(fcinfo, finfo, 0,
2095 InvalidOid, (Node *) trigdata, NULL);
2097 pgstat_init_function_usage(&fcinfo, &fcusage);
2102 result = FunctionCallInvoke(&fcinfo);
2112 pgstat_end_function_usage(&fcusage, true);
2114 MemoryContextSwitchTo(oldContext);
2117 * Trigger protocol allows function to return a null pointer, but NOT to
2118 * set the isnull result flag.
2122 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2123 errmsg("trigger function %u returned null value",
2124 fcinfo.flinfo->fn_oid)));
2127 * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
2128 * one "tuple returned" (really the number of firings).
2131 InstrStopNode(instr + tgindx, 1);
2133 return (HeapTuple) DatumGetPointer(result);
2137 ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
2139 TriggerDesc *trigdesc;
2141 TriggerData LocTriggerData;
2143 trigdesc = relinfo->ri_TrigDesc;
2145 if (trigdesc == NULL)
2147 if (!trigdesc->trig_insert_before_statement)
2150 LocTriggerData.type = T_TriggerData;
2151 LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
2152 TRIGGER_EVENT_BEFORE;
2153 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2154 LocTriggerData.tg_trigtuple = NULL;
2155 LocTriggerData.tg_newtuple = NULL;
2156 LocTriggerData.tg_oldtable = NULL;
2157 LocTriggerData.tg_newtable = NULL;
2158 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2159 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2160 for (i = 0; i < trigdesc->numtriggers; i++)
2162 Trigger *trigger = &trigdesc->triggers[i];
2165 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2166 TRIGGER_TYPE_STATEMENT,
2167 TRIGGER_TYPE_BEFORE,
2168 TRIGGER_TYPE_INSERT))
2170 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2174 LocTriggerData.tg_trigger = trigger;
2175 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2177 relinfo->ri_TrigFunctions,
2178 relinfo->ri_TrigInstrument,
2179 GetPerTupleMemoryContext(estate));
2183 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2184 errmsg("BEFORE STATEMENT trigger cannot return a value")));
2189 ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo)
2191 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2193 if (trigdesc && trigdesc->trig_insert_after_statement)
2194 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_INSERT,
2195 false, NULL, NULL, NIL, NULL);
2199 ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
2200 TupleTableSlot *slot)
2202 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2203 HeapTuple slottuple = ExecMaterializeSlot(slot);
2204 HeapTuple newtuple = slottuple;
2206 TriggerData LocTriggerData;
2209 LocTriggerData.type = T_TriggerData;
2210 LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
2212 TRIGGER_EVENT_BEFORE;
2213 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2214 LocTriggerData.tg_newtuple = NULL;
2215 LocTriggerData.tg_oldtable = NULL;
2216 LocTriggerData.tg_newtable = NULL;
2217 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2218 for (i = 0; i < trigdesc->numtriggers; i++)
2220 Trigger *trigger = &trigdesc->triggers[i];
2222 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2224 TRIGGER_TYPE_BEFORE,
2225 TRIGGER_TYPE_INSERT))
2227 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2228 NULL, NULL, newtuple))
2231 LocTriggerData.tg_trigtuple = oldtuple = newtuple;
2232 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2233 LocTriggerData.tg_trigger = trigger;
2234 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2236 relinfo->ri_TrigFunctions,
2237 relinfo->ri_TrigInstrument,
2238 GetPerTupleMemoryContext(estate));
2239 if (oldtuple != newtuple && oldtuple != slottuple)
2240 heap_freetuple(oldtuple);
2241 if (newtuple == NULL)
2242 return NULL; /* "do nothing" */
2245 if (newtuple != slottuple)
2248 * Return the modified tuple using the es_trig_tuple_slot. We assume
2249 * the tuple was allocated in per-tuple memory context, and therefore
2250 * will go away by itself. The tuple table slot should not try to
2253 TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2254 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2256 if (newslot->tts_tupleDescriptor != tupdesc)
2257 ExecSetSlotDescriptor(newslot, tupdesc);
2258 ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2265 ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo,
2266 HeapTuple trigtuple, List *recheckIndexes)
2268 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2271 (trigdesc->trig_insert_after_row || trigdesc->trig_insert_new_table))
2272 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_INSERT,
2273 true, NULL, trigtuple, recheckIndexes, NULL);
2277 ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
2278 TupleTableSlot *slot)
2280 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2281 HeapTuple slottuple = ExecMaterializeSlot(slot);
2282 HeapTuple newtuple = slottuple;
2284 TriggerData LocTriggerData;
2287 LocTriggerData.type = T_TriggerData;
2288 LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
2290 TRIGGER_EVENT_INSTEAD;
2291 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2292 LocTriggerData.tg_newtuple = NULL;
2293 LocTriggerData.tg_oldtable = NULL;
2294 LocTriggerData.tg_newtable = NULL;
2295 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2296 for (i = 0; i < trigdesc->numtriggers; i++)
2298 Trigger *trigger = &trigdesc->triggers[i];
2300 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2302 TRIGGER_TYPE_INSTEAD,
2303 TRIGGER_TYPE_INSERT))
2305 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2306 NULL, NULL, newtuple))
2309 LocTriggerData.tg_trigtuple = oldtuple = newtuple;
2310 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2311 LocTriggerData.tg_trigger = trigger;
2312 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2314 relinfo->ri_TrigFunctions,
2315 relinfo->ri_TrigInstrument,
2316 GetPerTupleMemoryContext(estate));
2317 if (oldtuple != newtuple && oldtuple != slottuple)
2318 heap_freetuple(oldtuple);
2319 if (newtuple == NULL)
2320 return NULL; /* "do nothing" */
2323 if (newtuple != slottuple)
2326 * Return the modified tuple using the es_trig_tuple_slot. We assume
2327 * the tuple was allocated in per-tuple memory context, and therefore
2328 * will go away by itself. The tuple table slot should not try to
2331 TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2332 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2334 if (newslot->tts_tupleDescriptor != tupdesc)
2335 ExecSetSlotDescriptor(newslot, tupdesc);
2336 ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2343 ExecBSDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
2345 TriggerDesc *trigdesc;
2347 TriggerData LocTriggerData;
2349 trigdesc = relinfo->ri_TrigDesc;
2351 if (trigdesc == NULL)
2353 if (!trigdesc->trig_delete_before_statement)
2356 LocTriggerData.type = T_TriggerData;
2357 LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
2358 TRIGGER_EVENT_BEFORE;
2359 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2360 LocTriggerData.tg_trigtuple = NULL;
2361 LocTriggerData.tg_newtuple = NULL;
2362 LocTriggerData.tg_oldtable = NULL;
2363 LocTriggerData.tg_newtable = NULL;
2364 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2365 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2366 for (i = 0; i < trigdesc->numtriggers; i++)
2368 Trigger *trigger = &trigdesc->triggers[i];
2371 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2372 TRIGGER_TYPE_STATEMENT,
2373 TRIGGER_TYPE_BEFORE,
2374 TRIGGER_TYPE_DELETE))
2376 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2380 LocTriggerData.tg_trigger = trigger;
2381 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2383 relinfo->ri_TrigFunctions,
2384 relinfo->ri_TrigInstrument,
2385 GetPerTupleMemoryContext(estate));
2389 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2390 errmsg("BEFORE STATEMENT trigger cannot return a value")));
2395 ExecASDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
2397 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2399 if (trigdesc && trigdesc->trig_delete_after_statement)
2400 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_DELETE,
2401 false, NULL, NULL, NIL, NULL);
2405 ExecBRDeleteTriggers(EState *estate, EPQState *epqstate,
2406 ResultRelInfo *relinfo,
2407 ItemPointer tupleid,
2408 HeapTuple fdw_trigtuple)
2410 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2412 TriggerData LocTriggerData;
2413 HeapTuple trigtuple;
2415 TupleTableSlot *newSlot;
2418 Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2419 if (fdw_trigtuple == NULL)
2421 trigtuple = GetTupleForTrigger(estate, epqstate, relinfo, tupleid,
2422 LockTupleExclusive, &newSlot);
2423 if (trigtuple == NULL)
2427 trigtuple = fdw_trigtuple;
2429 LocTriggerData.type = T_TriggerData;
2430 LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
2432 TRIGGER_EVENT_BEFORE;
2433 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2434 LocTriggerData.tg_newtuple = NULL;
2435 LocTriggerData.tg_oldtable = NULL;
2436 LocTriggerData.tg_newtable = NULL;
2437 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2438 for (i = 0; i < trigdesc->numtriggers; i++)
2440 Trigger *trigger = &trigdesc->triggers[i];
2442 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2444 TRIGGER_TYPE_BEFORE,
2445 TRIGGER_TYPE_DELETE))
2447 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2448 NULL, trigtuple, NULL))
2451 LocTriggerData.tg_trigtuple = trigtuple;
2452 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2453 LocTriggerData.tg_trigger = trigger;
2454 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2456 relinfo->ri_TrigFunctions,
2457 relinfo->ri_TrigInstrument,
2458 GetPerTupleMemoryContext(estate));
2459 if (newtuple == NULL)
2461 result = false; /* tell caller to suppress delete */
2464 if (newtuple != trigtuple)
2465 heap_freetuple(newtuple);
2467 if (trigtuple != fdw_trigtuple)
2468 heap_freetuple(trigtuple);
2474 ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
2475 ItemPointer tupleid,
2476 HeapTuple fdw_trigtuple)
2478 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2481 (trigdesc->trig_delete_after_row || trigdesc->trig_delete_old_table))
2483 HeapTuple trigtuple;
2485 Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2486 if (fdw_trigtuple == NULL)
2487 trigtuple = GetTupleForTrigger(estate,
2494 trigtuple = fdw_trigtuple;
2496 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_DELETE,
2497 true, trigtuple, NULL, NIL, NULL);
2498 if (trigtuple != fdw_trigtuple)
2499 heap_freetuple(trigtuple);
2504 ExecIRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
2505 HeapTuple trigtuple)
2507 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2508 TriggerData LocTriggerData;
2512 LocTriggerData.type = T_TriggerData;
2513 LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
2515 TRIGGER_EVENT_INSTEAD;
2516 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2517 LocTriggerData.tg_newtuple = NULL;
2518 LocTriggerData.tg_oldtable = NULL;
2519 LocTriggerData.tg_newtable = NULL;
2520 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2521 for (i = 0; i < trigdesc->numtriggers; i++)
2523 Trigger *trigger = &trigdesc->triggers[i];
2525 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2527 TRIGGER_TYPE_INSTEAD,
2528 TRIGGER_TYPE_DELETE))
2530 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2531 NULL, trigtuple, NULL))
2534 LocTriggerData.tg_trigtuple = trigtuple;
2535 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2536 LocTriggerData.tg_trigger = trigger;
2537 rettuple = ExecCallTriggerFunc(&LocTriggerData,
2539 relinfo->ri_TrigFunctions,
2540 relinfo->ri_TrigInstrument,
2541 GetPerTupleMemoryContext(estate));
2542 if (rettuple == NULL)
2543 return false; /* Delete was suppressed */
2544 if (rettuple != trigtuple)
2545 heap_freetuple(rettuple);
2551 ExecBSUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
2553 TriggerDesc *trigdesc;
2555 TriggerData LocTriggerData;
2556 Bitmapset *updatedCols;
2558 trigdesc = relinfo->ri_TrigDesc;
2560 if (trigdesc == NULL)
2562 if (!trigdesc->trig_update_before_statement)
2565 updatedCols = GetUpdatedColumns(relinfo, estate);
2567 LocTriggerData.type = T_TriggerData;
2568 LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
2569 TRIGGER_EVENT_BEFORE;
2570 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2571 LocTriggerData.tg_trigtuple = NULL;
2572 LocTriggerData.tg_newtuple = NULL;
2573 LocTriggerData.tg_oldtable = NULL;
2574 LocTriggerData.tg_newtable = NULL;
2575 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2576 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2577 for (i = 0; i < trigdesc->numtriggers; i++)
2579 Trigger *trigger = &trigdesc->triggers[i];
2582 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2583 TRIGGER_TYPE_STATEMENT,
2584 TRIGGER_TYPE_BEFORE,
2585 TRIGGER_TYPE_UPDATE))
2587 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2588 updatedCols, NULL, NULL))
2591 LocTriggerData.tg_trigger = trigger;
2592 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2594 relinfo->ri_TrigFunctions,
2595 relinfo->ri_TrigInstrument,
2596 GetPerTupleMemoryContext(estate));
2600 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2601 errmsg("BEFORE STATEMENT trigger cannot return a value")));
2606 ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
2608 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2610 if (trigdesc && trigdesc->trig_update_after_statement)
2611 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_UPDATE,
2612 false, NULL, NULL, NIL,
2613 GetUpdatedColumns(relinfo, estate));
2617 ExecBRUpdateTriggers(EState *estate, EPQState *epqstate,
2618 ResultRelInfo *relinfo,
2619 ItemPointer tupleid,
2620 HeapTuple fdw_trigtuple,
2621 TupleTableSlot *slot)
2623 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2624 HeapTuple slottuple = ExecMaterializeSlot(slot);
2625 HeapTuple newtuple = slottuple;
2626 TriggerData LocTriggerData;
2627 HeapTuple trigtuple;
2629 TupleTableSlot *newSlot;
2631 Bitmapset *updatedCols;
2632 LockTupleMode lockmode;
2634 /* Determine lock mode to use */
2635 lockmode = ExecUpdateLockMode(estate, relinfo);
2637 Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2638 if (fdw_trigtuple == NULL)
2640 /* get a copy of the on-disk tuple we are planning to update */
2641 trigtuple = GetTupleForTrigger(estate, epqstate, relinfo, tupleid,
2642 lockmode, &newSlot);
2643 if (trigtuple == NULL)
2644 return NULL; /* cancel the update action */
2648 trigtuple = fdw_trigtuple;
2653 * In READ COMMITTED isolation level it's possible that target tuple was
2654 * changed due to concurrent update. In that case we have a raw subplan
2655 * output tuple in newSlot, and need to run it through the junk filter to
2656 * produce an insertable tuple.
2658 * Caution: more than likely, the passed-in slot is the same as the
2659 * junkfilter's output slot, so we are clobbering the original value of
2660 * slottuple by doing the filtering. This is OK since neither we nor our
2661 * caller have any more interest in the prior contents of that slot.
2663 if (newSlot != NULL)
2665 slot = ExecFilterJunk(relinfo->ri_junkFilter, newSlot);
2666 slottuple = ExecMaterializeSlot(slot);
2667 newtuple = slottuple;
2671 LocTriggerData.type = T_TriggerData;
2672 LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
2674 TRIGGER_EVENT_BEFORE;
2675 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2676 LocTriggerData.tg_oldtable = NULL;
2677 LocTriggerData.tg_newtable = NULL;
2678 updatedCols = GetUpdatedColumns(relinfo, estate);
2679 for (i = 0; i < trigdesc->numtriggers; i++)
2681 Trigger *trigger = &trigdesc->triggers[i];
2683 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2685 TRIGGER_TYPE_BEFORE,
2686 TRIGGER_TYPE_UPDATE))
2688 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2689 updatedCols, trigtuple, newtuple))
2692 LocTriggerData.tg_trigtuple = trigtuple;
2693 LocTriggerData.tg_newtuple = oldtuple = newtuple;
2694 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2695 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2696 LocTriggerData.tg_trigger = trigger;
2697 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2699 relinfo->ri_TrigFunctions,
2700 relinfo->ri_TrigInstrument,
2701 GetPerTupleMemoryContext(estate));
2702 if (oldtuple != newtuple && oldtuple != slottuple)
2703 heap_freetuple(oldtuple);
2704 if (newtuple == NULL)
2706 if (trigtuple != fdw_trigtuple)
2707 heap_freetuple(trigtuple);
2708 return NULL; /* "do nothing" */
2711 if (trigtuple != fdw_trigtuple)
2712 heap_freetuple(trigtuple);
2714 if (newtuple != slottuple)
2717 * Return the modified tuple using the es_trig_tuple_slot. We assume
2718 * the tuple was allocated in per-tuple memory context, and therefore
2719 * will go away by itself. The tuple table slot should not try to
2722 TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2723 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2725 if (newslot->tts_tupleDescriptor != tupdesc)
2726 ExecSetSlotDescriptor(newslot, tupdesc);
2727 ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2734 ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
2735 ItemPointer tupleid,
2736 HeapTuple fdw_trigtuple,
2738 List *recheckIndexes)
2740 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2742 if (trigdesc && (trigdesc->trig_update_after_row ||
2743 trigdesc->trig_update_old_table || trigdesc->trig_update_new_table))
2745 HeapTuple trigtuple;
2747 Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2748 if (fdw_trigtuple == NULL)
2749 trigtuple = GetTupleForTrigger(estate,
2756 trigtuple = fdw_trigtuple;
2758 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_UPDATE,
2759 true, trigtuple, newtuple, recheckIndexes,
2760 GetUpdatedColumns(relinfo, estate));
2761 if (trigtuple != fdw_trigtuple)
2762 heap_freetuple(trigtuple);
2767 ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
2768 HeapTuple trigtuple, TupleTableSlot *slot)
2770 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2771 HeapTuple slottuple = ExecMaterializeSlot(slot);
2772 HeapTuple newtuple = slottuple;
2773 TriggerData LocTriggerData;
2777 LocTriggerData.type = T_TriggerData;
2778 LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
2780 TRIGGER_EVENT_INSTEAD;
2781 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2782 LocTriggerData.tg_oldtable = NULL;
2783 LocTriggerData.tg_newtable = NULL;
2784 for (i = 0; i < trigdesc->numtriggers; i++)
2786 Trigger *trigger = &trigdesc->triggers[i];
2788 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2790 TRIGGER_TYPE_INSTEAD,
2791 TRIGGER_TYPE_UPDATE))
2793 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2794 NULL, trigtuple, newtuple))
2797 LocTriggerData.tg_trigtuple = trigtuple;
2798 LocTriggerData.tg_newtuple = oldtuple = newtuple;
2799 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2800 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2801 LocTriggerData.tg_trigger = trigger;
2802 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2804 relinfo->ri_TrigFunctions,
2805 relinfo->ri_TrigInstrument,
2806 GetPerTupleMemoryContext(estate));
2807 if (oldtuple != newtuple && oldtuple != slottuple)
2808 heap_freetuple(oldtuple);
2809 if (newtuple == NULL)
2810 return NULL; /* "do nothing" */
2813 if (newtuple != slottuple)
2816 * Return the modified tuple using the es_trig_tuple_slot. We assume
2817 * the tuple was allocated in per-tuple memory context, and therefore
2818 * will go away by itself. The tuple table slot should not try to
2821 TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2822 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2824 if (newslot->tts_tupleDescriptor != tupdesc)
2825 ExecSetSlotDescriptor(newslot, tupdesc);
2826 ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2833 ExecBSTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
2835 TriggerDesc *trigdesc;
2837 TriggerData LocTriggerData;
2839 trigdesc = relinfo->ri_TrigDesc;
2841 if (trigdesc == NULL)
2843 if (!trigdesc->trig_truncate_before_statement)
2846 LocTriggerData.type = T_TriggerData;
2847 LocTriggerData.tg_event = TRIGGER_EVENT_TRUNCATE |
2848 TRIGGER_EVENT_BEFORE;
2849 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2850 LocTriggerData.tg_trigtuple = NULL;
2851 LocTriggerData.tg_newtuple = NULL;
2852 LocTriggerData.tg_oldtable = NULL;
2853 LocTriggerData.tg_newtable = NULL;
2854 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2855 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2856 for (i = 0; i < trigdesc->numtriggers; i++)
2858 Trigger *trigger = &trigdesc->triggers[i];
2861 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2862 TRIGGER_TYPE_STATEMENT,
2863 TRIGGER_TYPE_BEFORE,
2864 TRIGGER_TYPE_TRUNCATE))
2866 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2870 LocTriggerData.tg_trigger = trigger;
2871 newtuple = ExecCallTriggerFunc(&LocTriggerData,
2873 relinfo->ri_TrigFunctions,
2874 relinfo->ri_TrigInstrument,
2875 GetPerTupleMemoryContext(estate));
2879 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2880 errmsg("BEFORE STATEMENT trigger cannot return a value")));
2885 ExecASTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
2887 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2889 if (trigdesc && trigdesc->trig_truncate_after_statement)
2890 AfterTriggerSaveEvent(estate, relinfo, TRIGGER_EVENT_TRUNCATE,
2891 false, NULL, NULL, NIL, NULL);
2896 GetTupleForTrigger(EState *estate,
2898 ResultRelInfo *relinfo,
2900 LockTupleMode lockmode,
2901 TupleTableSlot **newSlot)
2903 Relation relation = relinfo->ri_RelationDesc;
2904 HeapTupleData tuple;
2908 if (newSlot != NULL)
2911 HeapUpdateFailureData hufd;
2915 /* caller must pass an epqstate if EvalPlanQual is possible */
2916 Assert(epqstate != NULL);
2919 * lock tuple for update
2922 tuple.t_self = *tid;
2923 test = heap_lock_tuple(relation, &tuple,
2924 estate->es_output_cid,
2925 lockmode, LockWaitBlock,
2926 false, &buffer, &hufd);
2929 case HeapTupleSelfUpdated:
2932 * The target tuple was already updated or deleted by the
2933 * current command, or by a later command in the current
2934 * transaction. We ignore the tuple in the former case, and
2935 * throw error in the latter case, for the same reasons
2936 * enumerated in ExecUpdate and ExecDelete in
2937 * nodeModifyTable.c.
2939 if (hufd.cmax != estate->es_output_cid)
2941 (errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
2942 errmsg("tuple to be updated was already modified by an operation triggered by the current command"),
2943 errhint("Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
2945 /* treat it as deleted; do not process */
2946 ReleaseBuffer(buffer);
2949 case HeapTupleMayBeUpdated:
2952 case HeapTupleUpdated:
2953 ReleaseBuffer(buffer);
2954 if (IsolationUsesXactSnapshot())
2956 (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
2957 errmsg("could not serialize access due to concurrent update")));
2958 if (!ItemPointerEquals(&hufd.ctid, &tuple.t_self))
2960 /* it was updated, so look at the updated version */
2961 TupleTableSlot *epqslot;
2963 epqslot = EvalPlanQual(estate,
2966 relinfo->ri_RangeTableIndex,
2970 if (!TupIsNull(epqslot))
2976 * EvalPlanQual already locked the tuple, but we
2977 * re-call heap_lock_tuple anyway as an easy way of
2978 * re-fetching the correct tuple. Speed is hardly a
2979 * criterion in this path anyhow.
2986 * if tuple was deleted or PlanQual failed for updated tuple -
2987 * we must not process this tuple!
2991 case HeapTupleInvisible:
2992 elog(ERROR, "attempted to lock invisible tuple");
2995 ReleaseBuffer(buffer);
2996 elog(ERROR, "unrecognized heap_lock_tuple status: %u", test);
2997 return NULL; /* keep compiler quiet */
3005 buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
3008 * Although we already know this tuple is valid, we must lock the
3009 * buffer to ensure that no one has a buffer cleanup lock; otherwise
3010 * they might move the tuple while we try to copy it. But we can
3011 * release the lock before actually doing the heap_copytuple call,
3012 * since holding pin is sufficient to prevent anyone from getting a
3013 * cleanup lock they don't already hold.
3015 LockBuffer(buffer, BUFFER_LOCK_SHARE);
3017 page = BufferGetPage(buffer);
3018 lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
3020 Assert(ItemIdIsNormal(lp));
3022 tuple.t_data = (HeapTupleHeader) PageGetItem(page, lp);
3023 tuple.t_len = ItemIdGetLength(lp);
3024 tuple.t_self = *tid;
3025 tuple.t_tableOid = RelationGetRelid(relation);
3027 LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
3030 result = heap_copytuple(&tuple);
3031 ReleaseBuffer(buffer);
3037 * Is trigger enabled to fire?
3040 TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
3041 Trigger *trigger, TriggerEvent event,
3042 Bitmapset *modifiedCols,
3043 HeapTuple oldtup, HeapTuple newtup)
3045 /* Check replication-role-dependent enable state */
3046 if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
3048 if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
3049 trigger->tgenabled == TRIGGER_DISABLED)
3052 else /* ORIGIN or LOCAL role */
3054 if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
3055 trigger->tgenabled == TRIGGER_DISABLED)
3060 * Check for column-specific trigger (only possible for UPDATE, and in
3061 * fact we *must* ignore tgattr for other event types)
3063 if (trigger->tgnattr > 0 && TRIGGER_FIRED_BY_UPDATE(event))
3069 for (i = 0; i < trigger->tgnattr; i++)
3071 if (bms_is_member(trigger->tgattr[i] - FirstLowInvalidHeapAttributeNumber,
3082 /* Check for WHEN clause */
3083 if (trigger->tgqual)
3085 TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
3086 ExprState **predicate;
3087 ExprContext *econtext;
3088 TupleTableSlot *oldslot = NULL;
3089 TupleTableSlot *newslot = NULL;
3090 MemoryContext oldContext;
3093 Assert(estate != NULL);
3096 * trigger is an element of relinfo->ri_TrigDesc->triggers[]; find the
3097 * matching element of relinfo->ri_TrigWhenExprs[]
3099 i = trigger - relinfo->ri_TrigDesc->triggers;
3100 predicate = &relinfo->ri_TrigWhenExprs[i];
3103 * If first time through for this WHEN expression, build expression
3104 * nodetrees for it. Keep them in the per-query memory context so
3105 * they'll survive throughout the query.
3107 if (*predicate == NULL)
3111 oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
3112 tgqual = stringToNode(trigger->tgqual);
3113 /* Change references to OLD and NEW to INNER_VAR and OUTER_VAR */
3114 ChangeVarNodes(tgqual, PRS2_OLD_VARNO, INNER_VAR, 0);
3115 ChangeVarNodes(tgqual, PRS2_NEW_VARNO, OUTER_VAR, 0);
3116 /* ExecPrepareQual wants implicit-AND form */
3117 tgqual = (Node *) make_ands_implicit((Expr *) tgqual);
3118 *predicate = ExecPrepareQual((List *) tgqual, estate);
3119 MemoryContextSwitchTo(oldContext);
3123 * We will use the EState's per-tuple context for evaluating WHEN
3124 * expressions (creating it if it's not already there).
3126 econtext = GetPerTupleExprContext(estate);
3129 * Put OLD and NEW tuples into tupleslots for expression evaluation.
3130 * These slots can be shared across the whole estate, but be careful
3131 * that they have the current resultrel's tupdesc.
3133 if (HeapTupleIsValid(oldtup))
3135 if (estate->es_trig_oldtup_slot == NULL)
3137 oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
3138 estate->es_trig_oldtup_slot = ExecInitExtraTupleSlot(estate);
3139 MemoryContextSwitchTo(oldContext);
3141 oldslot = estate->es_trig_oldtup_slot;
3142 if (oldslot->tts_tupleDescriptor != tupdesc)
3143 ExecSetSlotDescriptor(oldslot, tupdesc);
3144 ExecStoreTuple(oldtup, oldslot, InvalidBuffer, false);
3146 if (HeapTupleIsValid(newtup))
3148 if (estate->es_trig_newtup_slot == NULL)
3150 oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
3151 estate->es_trig_newtup_slot = ExecInitExtraTupleSlot(estate);
3152 MemoryContextSwitchTo(oldContext);
3154 newslot = estate->es_trig_newtup_slot;
3155 if (newslot->tts_tupleDescriptor != tupdesc)
3156 ExecSetSlotDescriptor(newslot, tupdesc);
3157 ExecStoreTuple(newtup, newslot, InvalidBuffer, false);
3161 * Finally evaluate the expression, making the old and/or new tuples
3162 * available as INNER_VAR/OUTER_VAR respectively.
3164 econtext->ecxt_innertuple = oldslot;
3165 econtext->ecxt_outertuple = newslot;
3166 if (!ExecQual(*predicate, econtext))
3175 * After-trigger stuff
3177 * The AfterTriggersData struct holds data about pending AFTER trigger events
3178 * during the current transaction tree. (BEFORE triggers are fired
3179 * immediately so we don't need any persistent state about them.) The struct
3180 * and most of its subsidiary data are kept in TopTransactionContext; however
3181 * the individual event records are kept in a separate sub-context. This is
3182 * done mainly so that it's easy to tell from a memory context dump how much
3183 * space is being eaten by trigger events.
3185 * Because the list of pending events can grow large, we go to some
3186 * considerable effort to minimize per-event memory consumption. The event
3187 * records are grouped into chunks and common data for similar events in the
3188 * same chunk is only stored once.
3190 * XXX We need to be able to save the per-event data in a file if it grows too
3195 /* Per-trigger SET CONSTRAINT status */
3196 typedef struct SetConstraintTriggerData
3199 bool sct_tgisdeferred;
3200 } SetConstraintTriggerData;
3202 typedef struct SetConstraintTriggerData *SetConstraintTrigger;
3205 * SET CONSTRAINT intra-transaction status.
3207 * We make this a single palloc'd object so it can be copied and freed easily.
3209 * all_isset and all_isdeferred are used to keep track
3210 * of SET CONSTRAINTS ALL {DEFERRED, IMMEDIATE}.
3212 * trigstates[] stores per-trigger tgisdeferred settings.
3214 typedef struct SetConstraintStateData
3217 bool all_isdeferred;
3218 int numstates; /* number of trigstates[] entries in use */
3219 int numalloc; /* allocated size of trigstates[] */
3220 SetConstraintTriggerData trigstates[FLEXIBLE_ARRAY_MEMBER];
3221 } SetConstraintStateData;
3223 typedef SetConstraintStateData *SetConstraintState;
3227 * Per-trigger-event data
3229 * The actual per-event data, AfterTriggerEventData, includes DONE/IN_PROGRESS
3230 * status bits and up to two tuple CTIDs. Each event record also has an
3231 * associated AfterTriggerSharedData that is shared across all instances of
3232 * similar events within a "chunk".
3234 * For row-level triggers, we arrange not to waste storage on unneeded ctid
3235 * fields. Updates of regular tables use two; inserts and deletes of regular
3236 * tables use one; foreign tables always use zero and save the tuple(s) to a
3237 * tuplestore. AFTER_TRIGGER_FDW_FETCH directs AfterTriggerExecute() to
3238 * retrieve a fresh tuple or pair of tuples from that tuplestore, while
3239 * AFTER_TRIGGER_FDW_REUSE directs it to use the most-recently-retrieved
3240 * tuple(s). This permits storing tuples once regardless of the number of
3241 * row-level triggers on a foreign table.
3243 * Statement-level triggers always bear AFTER_TRIGGER_1CTID, though they
3244 * require no ctid field. We lack the flag bit space to neatly represent that
3245 * distinct case, and it seems unlikely to be worth much trouble.
3247 * Note: ats_firing_id is initially zero and is set to something else when
3248 * AFTER_TRIGGER_IN_PROGRESS is set. It indicates which trigger firing
3249 * cycle the trigger will be fired in (or was fired in, if DONE is set).
3250 * Although this is mutable state, we can keep it in AfterTriggerSharedData
3251 * because all instances of the same type of event in a given event list will
3252 * be fired at the same time, if they were queued between the same firing
3253 * cycles. So we need only ensure that ats_firing_id is zero when attaching
3254 * a new event to an existing AfterTriggerSharedData record.
3256 typedef uint32 TriggerFlags;
3258 #define AFTER_TRIGGER_OFFSET 0x0FFFFFFF /* must be low-order
3260 #define AFTER_TRIGGER_DONE 0x10000000
3261 #define AFTER_TRIGGER_IN_PROGRESS 0x20000000
3262 /* bits describing the size and tuple sources of this event */
3263 #define AFTER_TRIGGER_FDW_REUSE 0x00000000
3264 #define AFTER_TRIGGER_FDW_FETCH 0x80000000
3265 #define AFTER_TRIGGER_1CTID 0x40000000
3266 #define AFTER_TRIGGER_2CTID 0xC0000000
3267 #define AFTER_TRIGGER_TUP_BITS 0xC0000000
3269 typedef struct AfterTriggerSharedData *AfterTriggerShared;
3271 typedef struct AfterTriggerSharedData
3273 TriggerEvent ats_event; /* event type indicator, see trigger.h */
3274 Oid ats_tgoid; /* the trigger's ID */
3275 Oid ats_relid; /* the relation it's on */
3276 CommandId ats_firing_id; /* ID for firing cycle */
3277 } AfterTriggerSharedData;
3279 typedef struct AfterTriggerEventData *AfterTriggerEvent;
3281 typedef struct AfterTriggerEventData
3283 TriggerFlags ate_flags; /* status bits and offset to shared data */
3284 ItemPointerData ate_ctid1; /* inserted, deleted, or old updated tuple */
3285 ItemPointerData ate_ctid2; /* new updated tuple */
3286 } AfterTriggerEventData;
3288 /* AfterTriggerEventData, minus ate_ctid2 */
3289 typedef struct AfterTriggerEventDataOneCtid
3291 TriggerFlags ate_flags; /* status bits and offset to shared data */
3292 ItemPointerData ate_ctid1; /* inserted, deleted, or old updated tuple */
3293 } AfterTriggerEventDataOneCtid;
3295 /* AfterTriggerEventData, minus ate_ctid1 and ate_ctid2 */
3296 typedef struct AfterTriggerEventDataZeroCtids
3298 TriggerFlags ate_flags; /* status bits and offset to shared data */
3299 } AfterTriggerEventDataZeroCtids;
3301 #define SizeofTriggerEvent(evt) \
3302 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_2CTID ? \
3303 sizeof(AfterTriggerEventData) : \
3304 ((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_1CTID ? \
3305 sizeof(AfterTriggerEventDataOneCtid) : \
3306 sizeof(AfterTriggerEventDataZeroCtids))
3308 #define GetTriggerSharedData(evt) \
3309 ((AfterTriggerShared) ((char *) (evt) + ((evt)->ate_flags & AFTER_TRIGGER_OFFSET)))
3312 * To avoid palloc overhead, we keep trigger events in arrays in successively-
3313 * larger chunks (a slightly more sophisticated version of an expansible
3314 * array). The space between CHUNK_DATA_START and freeptr is occupied by
3315 * AfterTriggerEventData records; the space between endfree and endptr is
3316 * occupied by AfterTriggerSharedData records.
3318 typedef struct AfterTriggerEventChunk
3320 struct AfterTriggerEventChunk *next; /* list link */
3321 char *freeptr; /* start of free space in chunk */
3322 char *endfree; /* end of free space in chunk */
3323 char *endptr; /* end of chunk */
3324 /* event data follows here */
3325 } AfterTriggerEventChunk;
3327 #define CHUNK_DATA_START(cptr) ((char *) (cptr) + MAXALIGN(sizeof(AfterTriggerEventChunk)))
3329 /* A list of events */
3330 typedef struct AfterTriggerEventList
3332 AfterTriggerEventChunk *head;
3333 AfterTriggerEventChunk *tail;
3334 char *tailfree; /* freeptr of tail chunk */
3335 } AfterTriggerEventList;
3337 /* Macros to help in iterating over a list of events */
3338 #define for_each_chunk(cptr, evtlist) \
3339 for (cptr = (evtlist).head; cptr != NULL; cptr = cptr->next)
3340 #define for_each_event(eptr, cptr) \
3341 for (eptr = (AfterTriggerEvent) CHUNK_DATA_START(cptr); \
3342 (char *) eptr < (cptr)->freeptr; \
3343 eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
3344 /* Use this if no special per-chunk processing is needed */
3345 #define for_each_event_chunk(eptr, cptr, evtlist) \
3346 for_each_chunk(cptr, evtlist) for_each_event(eptr, cptr)
3350 * All per-transaction data for the AFTER TRIGGERS module.
3352 * AfterTriggersData has the following fields:
3354 * firing_counter is incremented for each call of afterTriggerInvokeEvents.
3355 * We mark firable events with the current firing cycle's ID so that we can
3356 * tell which ones to work on. This ensures sane behavior if a trigger
3357 * function chooses to do SET CONSTRAINTS: the inner SET CONSTRAINTS will
3358 * only fire those events that weren't already scheduled for firing.
3360 * state keeps track of the transaction-local effects of SET CONSTRAINTS.
3361 * This is saved and restored across failed subtransactions.
3363 * events is the current list of deferred events. This is global across
3364 * all subtransactions of the current transaction. In a subtransaction
3365 * abort, we know that the events added by the subtransaction are at the
3366 * end of the list, so it is relatively easy to discard them. The event
3367 * list chunks themselves are stored in event_cxt.
3369 * query_depth is the current depth of nested AfterTriggerBeginQuery calls
3370 * (-1 when the stack is empty).
3372 * query_stack[query_depth] is a list of AFTER trigger events queued by the
3373 * current query (and the query_stack entries below it are lists of trigger
3374 * events queued by calling queries). None of these are valid until the
3375 * matching AfterTriggerEndQuery call occurs. At that point we fire
3376 * immediate-mode triggers, and append any deferred events to the main events
3379 * fdw_tuplestores[query_depth] is a tuplestore containing the foreign tuples
3380 * needed for the current query.
3382 * old_tuplestores[query_depth] and new_tuplestores[query_depth] hold the
3383 * transition relations for the current query.
3385 * maxquerydepth is just the allocated length of query_stack and the
3388 * state_stack is a stack of pointers to saved copies of the SET CONSTRAINTS
3389 * state data; each subtransaction level that modifies that state first
3390 * saves a copy, which we use to restore the state if we abort.
3392 * events_stack is a stack of copies of the events head/tail pointers,
3393 * which we use to restore those values during subtransaction abort.
3395 * depth_stack is a stack of copies of subtransaction-start-time query_depth,
3396 * which we similarly use to clean up at subtransaction abort.
3398 * firing_stack is a stack of copies of subtransaction-start-time
3399 * firing_counter. We use this to recognize which deferred triggers were
3400 * fired (or marked for firing) within an aborted subtransaction.
3402 * We use GetCurrentTransactionNestLevel() to determine the correct array
3403 * index in these stacks. maxtransdepth is the number of allocated entries in
3404 * each stack. (By not keeping our own stack pointer, we can avoid trouble
3405 * in cases where errors during subxact abort cause multiple invocations
3406 * of AfterTriggerEndSubXact() at the same nesting depth.)
3408 typedef struct AfterTriggersData
3410 CommandId firing_counter; /* next firing ID to assign */
3411 SetConstraintState state; /* the active S C state */
3412 AfterTriggerEventList events; /* deferred-event list */
3413 int query_depth; /* current query list index */
3414 AfterTriggerEventList *query_stack; /* events pending from each query */
3415 Tuplestorestate **fdw_tuplestores; /* foreign tuples for one row from
3417 Tuplestorestate **old_tuplestores; /* all old tuples from each query */
3418 Tuplestorestate **new_tuplestores; /* all new tuples from each query */
3419 int maxquerydepth; /* allocated len of above array */
3420 MemoryContext event_cxt; /* memory context for events, if any */
3422 /* these fields are just for resetting at subtrans abort: */
3424 SetConstraintState *state_stack; /* stacked S C states */
3425 AfterTriggerEventList *events_stack; /* stacked list pointers */
3426 int *depth_stack; /* stacked query_depths */
3427 CommandId *firing_stack; /* stacked firing_counters */
3428 int maxtransdepth; /* allocated len of above arrays */
3429 } AfterTriggersData;
3431 static AfterTriggersData afterTriggers;
3433 static void AfterTriggerExecute(AfterTriggerEvent event,
3434 Relation rel, TriggerDesc *trigdesc,
3436 Instrumentation *instr,
3437 MemoryContext per_tuple_context,
3438 TupleTableSlot *trig_tuple_slot1,
3439 TupleTableSlot *trig_tuple_slot2);
3440 static SetConstraintState SetConstraintStateCreate(int numalloc);
3441 static SetConstraintState SetConstraintStateCopy(SetConstraintState state);
3442 static SetConstraintState SetConstraintStateAddItem(SetConstraintState state,
3443 Oid tgoid, bool tgisdeferred);
3447 * Gets a current query transition tuplestore and initializes it if necessary.
3448 * This can be holding a single transition row tuple (in the case of an FDW)
3449 * or a transition table (for an AFTER trigger).
3451 static Tuplestorestate *
3452 GetTriggerTransitionTuplestore(Tuplestorestate **tss)
3454 Tuplestorestate *ret;
3456 ret = tss[afterTriggers.query_depth];
3459 MemoryContext oldcxt;
3460 ResourceOwner saveResourceOwner;
3463 * Make the tuplestore valid until end of transaction. This is the
3464 * allocation lifespan of the associated events list, but we really
3465 * only need it until AfterTriggerEndQuery().
3467 oldcxt = MemoryContextSwitchTo(TopTransactionContext);
3468 saveResourceOwner = CurrentResourceOwner;
3471 CurrentResourceOwner = TopTransactionResourceOwner;
3472 ret = tuplestore_begin_heap(false, false, work_mem);
3476 CurrentResourceOwner = saveResourceOwner;
3480 CurrentResourceOwner = saveResourceOwner;
3481 MemoryContextSwitchTo(oldcxt);
3483 tss[afterTriggers.query_depth] = ret;
3490 * afterTriggerCheckState()
3492 * Returns true if the trigger event is actually in state DEFERRED.
3496 afterTriggerCheckState(AfterTriggerShared evtshared)
3498 Oid tgoid = evtshared->ats_tgoid;
3499 SetConstraintState state = afterTriggers.state;
3503 * For not-deferrable triggers (i.e. normal AFTER ROW triggers and
3504 * constraints declared NOT DEFERRABLE), the state is always false.
3506 if ((evtshared->ats_event & AFTER_TRIGGER_DEFERRABLE) == 0)
3510 * If constraint state exists, SET CONSTRAINTS might have been executed
3511 * either for this trigger or for all triggers.
3515 /* Check for SET CONSTRAINTS for this specific trigger. */
3516 for (i = 0; i < state->numstates; i++)
3518 if (state->trigstates[i].sct_tgoid == tgoid)
3519 return state->trigstates[i].sct_tgisdeferred;
3522 /* Check for SET CONSTRAINTS ALL. */
3523 if (state->all_isset)
3524 return state->all_isdeferred;
3528 * Otherwise return the default state for the trigger.
3530 return ((evtshared->ats_event & AFTER_TRIGGER_INITDEFERRED) != 0);
3535 * afterTriggerAddEvent()
3537 * Add a new trigger event to the specified queue.
3538 * The passed-in event data is copied.
3542 afterTriggerAddEvent(AfterTriggerEventList *events,
3543 AfterTriggerEvent event, AfterTriggerShared evtshared)
3545 Size eventsize = SizeofTriggerEvent(event);
3546 Size needed = eventsize + sizeof(AfterTriggerSharedData);
3547 AfterTriggerEventChunk *chunk;
3548 AfterTriggerShared newshared;
3549 AfterTriggerEvent newevent;
3552 * If empty list or not enough room in the tail chunk, make a new chunk.
3553 * We assume here that a new shared record will always be needed.
3555 chunk = events->tail;
3556 if (chunk == NULL ||
3557 chunk->endfree - chunk->freeptr < needed)
3561 /* Create event context if we didn't already */
3562 if (afterTriggers.event_cxt == NULL)
3563 afterTriggers.event_cxt =
3564 AllocSetContextCreate(TopTransactionContext,
3565 "AfterTriggerEvents",
3566 ALLOCSET_DEFAULT_SIZES);
3569 * Chunk size starts at 1KB and is allowed to increase up to 1MB.
3570 * These numbers are fairly arbitrary, though there is a hard limit at
3571 * AFTER_TRIGGER_OFFSET; else we couldn't link event records to their
3572 * shared records using the available space in ate_flags. Another
3573 * constraint is that if the chunk size gets too huge, the search loop
3574 * below would get slow given a (not too common) usage pattern with
3575 * many distinct event types in a chunk. Therefore, we double the
3576 * preceding chunk size only if there weren't too many shared records
3577 * in the preceding chunk; otherwise we halve it. This gives us some
3578 * ability to adapt to the actual usage pattern of the current query
3579 * while still having large chunk sizes in typical usage. All chunk
3580 * sizes used should be MAXALIGN multiples, to ensure that the shared
3581 * records will be aligned safely.
3583 #define MIN_CHUNK_SIZE 1024
3584 #define MAX_CHUNK_SIZE (1024*1024)
3586 #if MAX_CHUNK_SIZE > (AFTER_TRIGGER_OFFSET+1)
3587 #error MAX_CHUNK_SIZE must not exceed AFTER_TRIGGER_OFFSET
3591 chunksize = MIN_CHUNK_SIZE;
3594 /* preceding chunk size... */
3595 chunksize = chunk->endptr - (char *) chunk;
3596 /* check number of shared records in preceding chunk */
3597 if ((chunk->endptr - chunk->endfree) <=
3598 (100 * sizeof(AfterTriggerSharedData)))
3599 chunksize *= 2; /* okay, double it */
3601 chunksize /= 2; /* too many shared records */
3602 chunksize = Min(chunksize, MAX_CHUNK_SIZE);
3604 chunk = MemoryContextAlloc(afterTriggers.event_cxt, chunksize);
3606 chunk->freeptr = CHUNK_DATA_START(chunk);
3607 chunk->endptr = chunk->endfree = (char *) chunk + chunksize;
3608 Assert(chunk->endfree - chunk->freeptr >= needed);
3610 if (events->head == NULL)
3611 events->head = chunk;
3613 events->tail->next = chunk;
3614 events->tail = chunk;
3615 /* events->tailfree is now out of sync, but we'll fix it below */
3619 * Try to locate a matching shared-data record already in the chunk. If
3620 * none, make a new one.
3622 for (newshared = ((AfterTriggerShared) chunk->endptr) - 1;
3623 (char *) newshared >= chunk->endfree;
3626 if (newshared->ats_tgoid == evtshared->ats_tgoid &&
3627 newshared->ats_relid == evtshared->ats_relid &&
3628 newshared->ats_event == evtshared->ats_event &&
3629 newshared->ats_firing_id == 0)
3632 if ((char *) newshared < chunk->endfree)
3634 *newshared = *evtshared;
3635 newshared->ats_firing_id = 0; /* just to be sure */
3636 chunk->endfree = (char *) newshared;
3639 /* Insert the data */
3640 newevent = (AfterTriggerEvent) chunk->freeptr;
3641 memcpy(newevent, event, eventsize);
3642 /* ... and link the new event to its shared record */
3643 newevent->ate_flags &= ~AFTER_TRIGGER_OFFSET;
3644 newevent->ate_flags |= (char *) newshared - (char *) newevent;
3646 chunk->freeptr += eventsize;
3647 events->tailfree = chunk->freeptr;
3651 * afterTriggerFreeEventList()
3653 * Free all the event storage in the given list.
3657 afterTriggerFreeEventList(AfterTriggerEventList *events)
3659 AfterTriggerEventChunk *chunk;
3660 AfterTriggerEventChunk *next_chunk;
3662 for (chunk = events->head; chunk != NULL; chunk = next_chunk)
3664 next_chunk = chunk->next;
3667 events->head = NULL;
3668 events->tail = NULL;
3669 events->tailfree = NULL;
3673 * afterTriggerRestoreEventList()
3675 * Restore an event list to its prior length, removing all the events
3676 * added since it had the value old_events.
3680 afterTriggerRestoreEventList(AfterTriggerEventList *events,
3681 const AfterTriggerEventList *old_events)
3683 AfterTriggerEventChunk *chunk;
3684 AfterTriggerEventChunk *next_chunk;
3686 if (old_events->tail == NULL)
3688 /* restoring to a completely empty state, so free everything */
3689 afterTriggerFreeEventList(events);
3693 *events = *old_events;
3694 /* free any chunks after the last one we want to keep */
3695 for (chunk = events->tail->next; chunk != NULL; chunk = next_chunk)
3697 next_chunk = chunk->next;
3700 /* and clean up the tail chunk to be the right length */
3701 events->tail->next = NULL;
3702 events->tail->freeptr = events->tailfree;
3705 * We don't make any effort to remove now-unused shared data records.
3706 * They might still be useful, anyway.
3713 * AfterTriggerExecute()
3715 * Fetch the required tuples back from the heap and fire one
3716 * single trigger function.
3718 * Frequently, this will be fired many times in a row for triggers of
3719 * a single relation. Therefore, we cache the open relation and provide
3720 * fmgr lookup cache space at the caller level. (For triggers fired at
3721 * the end of a query, we can even piggyback on the executor's state.)
3723 * event: event currently being fired.
3724 * rel: open relation for event.
3725 * trigdesc: working copy of rel's trigger info.
3726 * finfo: array of fmgr lookup cache entries (one per trigger in trigdesc).
3727 * instr: array of EXPLAIN ANALYZE instrumentation nodes (one per trigger),
3728 * or NULL if no instrumentation is wanted.
3729 * per_tuple_context: memory context to call trigger function in.
3730 * trig_tuple_slot1: scratch slot for tg_trigtuple (foreign tables only)
3731 * trig_tuple_slot2: scratch slot for tg_newtuple (foreign tables only)
3735 AfterTriggerExecute(AfterTriggerEvent event,
3736 Relation rel, TriggerDesc *trigdesc,
3737 FmgrInfo *finfo, Instrumentation *instr,
3738 MemoryContext per_tuple_context,
3739 TupleTableSlot *trig_tuple_slot1,
3740 TupleTableSlot *trig_tuple_slot2)
3742 AfterTriggerShared evtshared = GetTriggerSharedData(event);
3743 Oid tgoid = evtshared->ats_tgoid;
3744 TriggerData LocTriggerData;
3745 HeapTupleData tuple1;
3746 HeapTupleData tuple2;
3748 Buffer buffer1 = InvalidBuffer;
3749 Buffer buffer2 = InvalidBuffer;
3753 * Locate trigger in trigdesc.
3755 LocTriggerData.tg_trigger = NULL;
3756 for (tgindx = 0; tgindx < trigdesc->numtriggers; tgindx++)
3758 if (trigdesc->triggers[tgindx].tgoid == tgoid)
3760 LocTriggerData.tg_trigger = &(trigdesc->triggers[tgindx]);
3764 if (LocTriggerData.tg_trigger == NULL)
3765 elog(ERROR, "could not find trigger %u", tgoid);
3768 * If doing EXPLAIN ANALYZE, start charging time to this trigger. We want
3769 * to include time spent re-fetching tuples in the trigger cost.
3772 InstrStartNode(instr + tgindx);
3775 * Fetch the required tuple(s).
3777 switch (event->ate_flags & AFTER_TRIGGER_TUP_BITS)
3779 case AFTER_TRIGGER_FDW_FETCH:
3781 Tuplestorestate *fdw_tuplestore =
3782 GetTriggerTransitionTuplestore
3783 (afterTriggers.fdw_tuplestores);
3785 if (!tuplestore_gettupleslot(fdw_tuplestore, true, false,
3787 elog(ERROR, "failed to fetch tuple1 for AFTER trigger");
3789 if ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) ==
3790 TRIGGER_EVENT_UPDATE &&
3791 !tuplestore_gettupleslot(fdw_tuplestore, true, false,
3793 elog(ERROR, "failed to fetch tuple2 for AFTER trigger");
3796 case AFTER_TRIGGER_FDW_REUSE:
3799 * Using ExecMaterializeSlot() rather than ExecFetchSlotTuple()
3800 * ensures that tg_trigtuple does not reference tuplestore memory.
3801 * (It is formally possible for the trigger function to queue
3802 * trigger events that add to the same tuplestore, which can push
3803 * other tuples out of memory.) The distinction is academic,
3804 * because we start with a minimal tuple that ExecFetchSlotTuple()
3805 * must materialize anyway.
3807 LocTriggerData.tg_trigtuple =
3808 ExecMaterializeSlot(trig_tuple_slot1);
3809 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
3811 LocTriggerData.tg_newtuple =
3812 ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) ==
3813 TRIGGER_EVENT_UPDATE) ?
3814 ExecMaterializeSlot(trig_tuple_slot2) : NULL;
3815 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
3820 if (ItemPointerIsValid(&(event->ate_ctid1)))
3822 ItemPointerCopy(&(event->ate_ctid1), &(tuple1.t_self));
3823 if (!heap_fetch(rel, SnapshotAny, &tuple1, &buffer1, false, NULL))
3824 elog(ERROR, "failed to fetch tuple1 for AFTER trigger");
3825 LocTriggerData.tg_trigtuple = &tuple1;
3826 LocTriggerData.tg_trigtuplebuf = buffer1;
3830 LocTriggerData.tg_trigtuple = NULL;
3831 LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
3834 /* don't touch ctid2 if not there */
3835 if ((event->ate_flags & AFTER_TRIGGER_TUP_BITS) ==
3836 AFTER_TRIGGER_2CTID &&
3837 ItemPointerIsValid(&(event->ate_ctid2)))
3839 ItemPointerCopy(&(event->ate_ctid2), &(tuple2.t_self));
3840 if (!heap_fetch(rel, SnapshotAny, &tuple2, &buffer2, false, NULL))
3841 elog(ERROR, "failed to fetch tuple2 for AFTER trigger");
3842 LocTriggerData.tg_newtuple = &tuple2;
3843 LocTriggerData.tg_newtuplebuf = buffer2;
3847 LocTriggerData.tg_newtuple = NULL;
3848 LocTriggerData.tg_newtuplebuf = InvalidBuffer;
3853 * Set up the tuplestore information.
3855 if (LocTriggerData.tg_trigger->tgoldtable)
3856 LocTriggerData.tg_oldtable =
3857 GetTriggerTransitionTuplestore(afterTriggers.old_tuplestores);
3859 LocTriggerData.tg_oldtable = NULL;
3860 if (LocTriggerData.tg_trigger->tgnewtable)
3861 LocTriggerData.tg_newtable =
3862 GetTriggerTransitionTuplestore(afterTriggers.new_tuplestores);
3864 LocTriggerData.tg_newtable = NULL;
3867 * Setup the remaining trigger information
3869 LocTriggerData.type = T_TriggerData;
3870 LocTriggerData.tg_event =
3871 evtshared->ats_event & (TRIGGER_EVENT_OPMASK | TRIGGER_EVENT_ROW);
3872 LocTriggerData.tg_relation = rel;
3874 MemoryContextReset(per_tuple_context);
3877 * Call the trigger and throw away any possibly returned updated tuple.
3878 * (Don't let ExecCallTriggerFunc measure EXPLAIN time.)
3880 rettuple = ExecCallTriggerFunc(&LocTriggerData,
3885 if (rettuple != NULL &&
3886 rettuple != LocTriggerData.tg_trigtuple &&
3887 rettuple != LocTriggerData.tg_newtuple)
3888 heap_freetuple(rettuple);
3893 if (buffer1 != InvalidBuffer)
3894 ReleaseBuffer(buffer1);
3895 if (buffer2 != InvalidBuffer)
3896 ReleaseBuffer(buffer2);
3899 * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
3900 * one "tuple returned" (really the number of firings).
3903 InstrStopNode(instr + tgindx, 1);
3908 * afterTriggerMarkEvents()
3910 * Scan the given event list for not yet invoked events. Mark the ones
3911 * that can be invoked now with the current firing ID.
3913 * If move_list isn't NULL, events that are not to be invoked now are
3914 * transferred to move_list.
3916 * When immediate_only is TRUE, do not invoke currently-deferred triggers.
3917 * (This will be FALSE only at main transaction exit.)
3919 * Returns TRUE if any invokable events were found.
3922 afterTriggerMarkEvents(AfterTriggerEventList *events,
3923 AfterTriggerEventList *move_list,
3924 bool immediate_only)
3927 AfterTriggerEvent event;
3928 AfterTriggerEventChunk *chunk;
3930 for_each_event_chunk(event, chunk, *events)
3932 AfterTriggerShared evtshared = GetTriggerSharedData(event);
3933 bool defer_it = false;
3935 if (!(event->ate_flags &
3936 (AFTER_TRIGGER_DONE | AFTER_TRIGGER_IN_PROGRESS)))
3939 * This trigger hasn't been called or scheduled yet. Check if we
3940 * should call it now.
3942 if (immediate_only && afterTriggerCheckState(evtshared))
3949 * Mark it as to be fired in this firing cycle.
3951 evtshared->ats_firing_id = afterTriggers.firing_counter;
3952 event->ate_flags |= AFTER_TRIGGER_IN_PROGRESS;
3958 * If it's deferred, move it to move_list, if requested.
3960 if (defer_it && move_list != NULL)
3962 /* add it to move_list */
3963 afterTriggerAddEvent(move_list, event, evtshared);
3964 /* mark original copy "done" so we don't do it again */
3965 event->ate_flags |= AFTER_TRIGGER_DONE;
3973 * afterTriggerInvokeEvents()
3975 * Scan the given event list for events that are marked as to be fired
3976 * in the current firing cycle, and fire them.
3978 * If estate isn't NULL, we use its result relation info to avoid repeated
3979 * openings and closing of trigger target relations. If it is NULL, we
3980 * make one locally to cache the info in case there are multiple trigger
3983 * When delete_ok is TRUE, it's safe to delete fully-processed events.
3984 * (We are not very tense about that: we simply reset a chunk to be empty
3985 * if all its events got fired. The objective here is just to avoid useless
3986 * rescanning of events when a trigger queues new events during transaction
3987 * end, so it's not necessary to worry much about the case where only
3988 * some events are fired.)
3990 * Returns TRUE if no unfired events remain in the list (this allows us
3991 * to avoid repeating afterTriggerMarkEvents).
3994 afterTriggerInvokeEvents(AfterTriggerEventList *events,
3995 CommandId firing_id,
3999 bool all_fired = true;
4000 AfterTriggerEventChunk *chunk;
4001 MemoryContext per_tuple_context;
4002 bool local_estate = false;
4003 Relation rel = NULL;
4004 TriggerDesc *trigdesc = NULL;
4005 FmgrInfo *finfo = NULL;
4006 Instrumentation *instr = NULL;
4007 TupleTableSlot *slot1 = NULL,
4010 /* Make a local EState if need be */
4013 estate = CreateExecutorState();
4014 local_estate = true;
4017 /* Make a per-tuple memory context for trigger function calls */
4019 AllocSetContextCreate(CurrentMemoryContext,
4020 "AfterTriggerTupleContext",
4021 ALLOCSET_DEFAULT_SIZES);
4023 for_each_chunk(chunk, *events)
4025 AfterTriggerEvent event;
4026 bool all_fired_in_chunk = true;
4028 for_each_event(event, chunk)
4030 AfterTriggerShared evtshared = GetTriggerSharedData(event);
4033 * Is it one for me to fire?
4035 if ((event->ate_flags & AFTER_TRIGGER_IN_PROGRESS) &&
4036 evtshared->ats_firing_id == firing_id)
4039 * So let's fire it... but first, find the correct relation if
4040 * this is not the same relation as before.
4042 if (rel == NULL || RelationGetRelid(rel) != evtshared->ats_relid)
4044 ResultRelInfo *rInfo;
4046 rInfo = ExecGetTriggerResultRel(estate, evtshared->ats_relid);
4047 rel = rInfo->ri_RelationDesc;
4048 trigdesc = rInfo->ri_TrigDesc;
4049 finfo = rInfo->ri_TrigFunctions;
4050 instr = rInfo->ri_TrigInstrument;
4051 if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
4055 ExecDropSingleTupleTableSlot(slot1);
4056 ExecDropSingleTupleTableSlot(slot2);
4058 slot1 = MakeSingleTupleTableSlot(rel->rd_att);
4059 slot2 = MakeSingleTupleTableSlot(rel->rd_att);
4061 if (trigdesc == NULL) /* should not happen */
4062 elog(ERROR, "relation %u has no triggers",
4063 evtshared->ats_relid);
4067 * Fire it. Note that the AFTER_TRIGGER_IN_PROGRESS flag is
4068 * still set, so recursive examinations of the event list
4069 * won't try to re-fire it.
4071 AfterTriggerExecute(event, rel, trigdesc, finfo, instr,
4072 per_tuple_context, slot1, slot2);
4075 * Mark the event as done.
4077 event->ate_flags &= ~AFTER_TRIGGER_IN_PROGRESS;
4078 event->ate_flags |= AFTER_TRIGGER_DONE;
4080 else if (!(event->ate_flags & AFTER_TRIGGER_DONE))
4082 /* something remains to be done */
4083 all_fired = all_fired_in_chunk = false;
4087 /* Clear the chunk if delete_ok and nothing left of interest */
4088 if (delete_ok && all_fired_in_chunk)
4090 chunk->freeptr = CHUNK_DATA_START(chunk);
4091 chunk->endfree = chunk->endptr;
4094 * If it's last chunk, must sync event list's tailfree too. Note
4095 * that delete_ok must NOT be passed as true if there could be
4096 * stacked AfterTriggerEventList values pointing at this event
4097 * list, since we'd fail to fix their copies of tailfree.
4099 if (chunk == events->tail)
4100 events->tailfree = chunk->freeptr;
4105 ExecDropSingleTupleTableSlot(slot1);
4106 ExecDropSingleTupleTableSlot(slot2);
4109 /* Release working resources */
4110 MemoryContextDelete(per_tuple_context);
4114 ExecCleanUpTriggerState(estate);
4115 FreeExecutorState(estate);
4123 * AfterTriggerBeginXact()
4125 * Called at transaction start (either BEGIN or implicit for single
4126 * statement outside of transaction block).
4130 AfterTriggerBeginXact(void)
4133 * Initialize after-trigger state structure to empty
4135 afterTriggers.firing_counter = (CommandId) 1; /* mustn't be 0 */
4136 afterTriggers.query_depth = -1;
4139 * Verify that there is no leftover state remaining. If these assertions
4140 * trip, it means that AfterTriggerEndXact wasn't called or didn't clean
4143 Assert(afterTriggers.state == NULL);
4144 Assert(afterTriggers.query_stack == NULL);
4145 Assert(afterTriggers.fdw_tuplestores == NULL);
4146 Assert(afterTriggers.old_tuplestores == NULL);
4147 Assert(afterTriggers.new_tuplestores == NULL);
4148 Assert(afterTriggers.maxquerydepth == 0);
4149 Assert(afterTriggers.event_cxt == NULL);
4150 Assert(afterTriggers.events.head == NULL);
4151 Assert(afterTriggers.state_stack == NULL);
4152 Assert(afterTriggers.events_stack == NULL);
4153 Assert(afterTriggers.depth_stack == NULL);
4154 Assert(afterTriggers.firing_stack == NULL);
4155 Assert(afterTriggers.maxtransdepth == 0);
4160 * AfterTriggerBeginQuery()
4162 * Called just before we start processing a single query within a
4163 * transaction (or subtransaction). Most of the real work gets deferred
4164 * until somebody actually tries to queue a trigger event.
4168 AfterTriggerBeginQuery(void)
4170 /* Increase the query stack depth */
4171 afterTriggers.query_depth++;
4176 * AfterTriggerEndQuery()
4178 * Called after one query has been completely processed. At this time
4179 * we invoke all AFTER IMMEDIATE trigger events queued by the query, and
4180 * transfer deferred trigger events to the global deferred-trigger list.
4182 * Note that this must be called BEFORE closing down the executor
4183 * with ExecutorEnd, because we make use of the EState's info about
4184 * target relations. Normally it is called from ExecutorFinish.
4188 AfterTriggerEndQuery(EState *estate)
4190 AfterTriggerEventList *events;
4191 Tuplestorestate *fdw_tuplestore;
4192 Tuplestorestate *old_tuplestore;
4193 Tuplestorestate *new_tuplestore;
4195 /* Must be inside a query, too */
4196 Assert(afterTriggers.query_depth >= 0);
4199 * If we never even got as far as initializing the event stack, there
4200 * certainly won't be any events, so exit quickly.
4202 if (afterTriggers.query_depth >= afterTriggers.maxquerydepth)
4204 afterTriggers.query_depth--;
4209 * Process all immediate-mode triggers queued by the query, and move the
4210 * deferred ones to the main list of deferred events.
4212 * Notice that we decide which ones will be fired, and put the deferred
4213 * ones on the main list, before anything is actually fired. This ensures
4214 * reasonably sane behavior if a trigger function does SET CONSTRAINTS ...
4215 * IMMEDIATE: all events we have decided to defer will be available for it
4218 * We loop in case a trigger queues more events at the same query level.
4219 * Ordinary trigger functions, including all PL/pgSQL trigger functions,
4220 * will instead fire any triggers in a dedicated query level. Foreign key
4221 * enforcement triggers do add to the current query level, thanks to their
4222 * passing fire_triggers = false to SPI_execute_snapshot(). Other
4223 * C-language triggers might do likewise. Be careful here: firing a
4224 * trigger could result in query_stack being repalloc'd, so we can't save
4225 * its address across afterTriggerInvokeEvents calls.
4227 * If we find no firable events, we don't have to increment
4232 events = &afterTriggers.query_stack[afterTriggers.query_depth];
4233 if (afterTriggerMarkEvents(events, &afterTriggers.events, true))
4235 CommandId firing_id = afterTriggers.firing_counter++;
4237 /* OK to delete the immediate events after processing them */
4238 if (afterTriggerInvokeEvents(events, firing_id, estate, true))
4239 break; /* all fired */
4245 /* Release query-local storage for events, including tuplestore if any */
4246 fdw_tuplestore = afterTriggers.fdw_tuplestores[afterTriggers.query_depth];
4249 tuplestore_end(fdw_tuplestore);
4250 afterTriggers.fdw_tuplestores[afterTriggers.query_depth] = NULL;
4252 old_tuplestore = afterTriggers.old_tuplestores[afterTriggers.query_depth];
4255 tuplestore_end(old_tuplestore);
4256 afterTriggers.old_tuplestores[afterTriggers.query_depth] = NULL;
4258 new_tuplestore = afterTriggers.new_tuplestores[afterTriggers.query_depth];
4261 tuplestore_end(new_tuplestore);
4262 afterTriggers.new_tuplestores[afterTriggers.query_depth] = NULL;
4264 afterTriggerFreeEventList(&afterTriggers.query_stack[afterTriggers.query_depth]);
4266 afterTriggers.query_depth--;
4271 * AfterTriggerFireDeferred()
4273 * Called just before the current transaction is committed. At this
4274 * time we invoke all pending DEFERRED triggers.
4276 * It is possible for other modules to queue additional deferred triggers
4277 * during pre-commit processing; therefore xact.c may have to call this
4282 AfterTriggerFireDeferred(void)
4284 AfterTriggerEventList *events;
4285 bool snap_pushed = false;
4287 /* Must not be inside a query */
4288 Assert(afterTriggers.query_depth == -1);
4291 * If there are any triggers to fire, make sure we have set a snapshot for
4292 * them to use. (Since PortalRunUtility doesn't set a snap for COMMIT, we
4293 * can't assume ActiveSnapshot is valid on entry.)
4295 events = &afterTriggers.events;
4296 if (events->head != NULL)
4298 PushActiveSnapshot(GetTransactionSnapshot());
4303 * Run all the remaining triggers. Loop until they are all gone, in case
4304 * some trigger queues more for us to do.
4306 while (afterTriggerMarkEvents(events, NULL, false))
4308 CommandId firing_id = afterTriggers.firing_counter++;
4310 if (afterTriggerInvokeEvents(events, firing_id, NULL, true))
4311 break; /* all fired */
4315 * We don't bother freeing the event list, since it will go away anyway
4316 * (and more efficiently than via pfree) in AfterTriggerEndXact.
4320 PopActiveSnapshot();
4325 * AfterTriggerEndXact()
4327 * The current transaction is finishing.
4329 * Any unfired triggers are canceled so we simply throw
4330 * away anything we know.
4332 * Note: it is possible for this to be called repeatedly in case of
4333 * error during transaction abort; therefore, do not complain if
4334 * already closed down.
4338 AfterTriggerEndXact(bool isCommit)
4341 * Forget the pending-events list.
4343 * Since all the info is in TopTransactionContext or children thereof, we
4344 * don't really need to do anything to reclaim memory. However, the
4345 * pending-events list could be large, and so it's useful to discard it as
4346 * soon as possible --- especially if we are aborting because we ran out
4347 * of memory for the list!
4349 if (afterTriggers.event_cxt)
4351 MemoryContextDelete(afterTriggers.event_cxt);
4352 afterTriggers.event_cxt = NULL;
4353 afterTriggers.events.head = NULL;
4354 afterTriggers.events.tail = NULL;
4355 afterTriggers.events.tailfree = NULL;
4359 * Forget any subtransaction state as well. Since this can't be very
4360 * large, we let the eventual reset of TopTransactionContext free the
4361 * memory instead of doing it here.
4363 afterTriggers.state_stack = NULL;
4364 afterTriggers.events_stack = NULL;
4365 afterTriggers.depth_stack = NULL;
4366 afterTriggers.firing_stack = NULL;
4367 afterTriggers.maxtransdepth = 0;
4371 * Forget the query stack and constraint-related state information. As
4372 * with the subtransaction state information, we don't bother freeing the
4375 afterTriggers.query_stack = NULL;
4376 afterTriggers.fdw_tuplestores = NULL;
4377 afterTriggers.old_tuplestores = NULL;
4378 afterTriggers.new_tuplestores = NULL;
4379 afterTriggers.maxquerydepth = 0;
4380 afterTriggers.state = NULL;
4382 /* No more afterTriggers manipulation until next transaction starts. */
4383 afterTriggers.query_depth = -1;
4387 * AfterTriggerBeginSubXact()
4389 * Start a subtransaction.
4392 AfterTriggerBeginSubXact(void)
4394 int my_level = GetCurrentTransactionNestLevel();
4397 * Allocate more space in the stacks if needed. (Note: because the
4398 * minimum nest level of a subtransaction is 2, we waste the first couple
4399 * entries of each array; not worth the notational effort to avoid it.)
4401 while (my_level >= afterTriggers.maxtransdepth)
4403 if (afterTriggers.maxtransdepth == 0)
4405 MemoryContext old_cxt;
4407 old_cxt = MemoryContextSwitchTo(TopTransactionContext);
4409 #define DEFTRIG_INITALLOC 8
4410 afterTriggers.state_stack = (SetConstraintState *)
4411 palloc(DEFTRIG_INITALLOC * sizeof(SetConstraintState));
4412 afterTriggers.events_stack = (AfterTriggerEventList *)
4413 palloc(DEFTRIG_INITALLOC * sizeof(AfterTriggerEventList));
4414 afterTriggers.depth_stack = (int *)
4415 palloc(DEFTRIG_INITALLOC * sizeof(int));
4416 afterTriggers.firing_stack = (CommandId *)
4417 palloc(DEFTRIG_INITALLOC * sizeof(CommandId));
4418 afterTriggers.maxtransdepth = DEFTRIG_INITALLOC;
4420 MemoryContextSwitchTo(old_cxt);
4424 /* repalloc will keep the stacks in the same context */
4425 int new_alloc = afterTriggers.maxtransdepth * 2;
4427 afterTriggers.state_stack = (SetConstraintState *)
4428 repalloc(afterTriggers.state_stack,
4429 new_alloc * sizeof(SetConstraintState));
4430 afterTriggers.events_stack = (AfterTriggerEventList *)
4431 repalloc(afterTriggers.events_stack,
4432 new_alloc * sizeof(AfterTriggerEventList));
4433 afterTriggers.depth_stack = (int *)
4434 repalloc(afterTriggers.depth_stack,
4435 new_alloc * sizeof(int));
4436 afterTriggers.firing_stack = (CommandId *)
4437 repalloc(afterTriggers.firing_stack,
4438 new_alloc * sizeof(CommandId));
4439 afterTriggers.maxtransdepth = new_alloc;
4444 * Push the current information into the stack. The SET CONSTRAINTS state
4445 * is not saved until/unless changed. Likewise, we don't make a
4446 * per-subtransaction event context until needed.
4448 afterTriggers.state_stack[my_level] = NULL;
4449 afterTriggers.events_stack[my_level] = afterTriggers.events;
4450 afterTriggers.depth_stack[my_level] = afterTriggers.query_depth;
4451 afterTriggers.firing_stack[my_level] = afterTriggers.firing_counter;
4455 * AfterTriggerEndSubXact()
4457 * The current subtransaction is ending.
4460 AfterTriggerEndSubXact(bool isCommit)
4462 int my_level = GetCurrentTransactionNestLevel();
4463 SetConstraintState state;
4464 AfterTriggerEvent event;
4465 AfterTriggerEventChunk *chunk;
4466 CommandId subxact_firing_id;
4469 * Pop the prior state if needed.
4473 Assert(my_level < afterTriggers.maxtransdepth);
4474 /* If we saved a prior state, we don't need it anymore */
4475 state = afterTriggers.state_stack[my_level];
4478 /* this avoids double pfree if error later: */
4479 afterTriggers.state_stack[my_level] = NULL;
4480 Assert(afterTriggers.query_depth ==
4481 afterTriggers.depth_stack[my_level]);
4486 * Aborting. It is possible subxact start failed before calling
4487 * AfterTriggerBeginSubXact, in which case we mustn't risk touching
4488 * stack levels that aren't there.
4490 if (my_level >= afterTriggers.maxtransdepth)
4494 * Release any event lists from queries being aborted, and restore
4495 * query_depth to its pre-subxact value. This assumes that a
4496 * subtransaction will not add events to query levels started in a
4497 * earlier transaction state.
4499 while (afterTriggers.query_depth > afterTriggers.depth_stack[my_level])
4501 if (afterTriggers.query_depth < afterTriggers.maxquerydepth)
4503 Tuplestorestate *ts;
4505 ts = afterTriggers.fdw_tuplestores[afterTriggers.query_depth];
4509 afterTriggers.fdw_tuplestores[afterTriggers.query_depth] = NULL;
4511 ts = afterTriggers.old_tuplestores[afterTriggers.query_depth];
4515 afterTriggers.old_tuplestores[afterTriggers.query_depth] = NULL;
4517 ts = afterTriggers.new_tuplestores[afterTriggers.query_depth];
4521 afterTriggers.new_tuplestores[afterTriggers.query_depth] = NULL;
4524 afterTriggerFreeEventList(&afterTriggers.query_stack[afterTriggers.query_depth]);
4527 afterTriggers.query_depth--;
4529 Assert(afterTriggers.query_depth ==
4530 afterTriggers.depth_stack[my_level]);
4533 * Restore the global deferred-event list to its former length,
4534 * discarding any events queued by the subxact.
4536 afterTriggerRestoreEventList(&afterTriggers.events,
4537 &afterTriggers.events_stack[my_level]);
4540 * Restore the trigger state. If the saved state is NULL, then this
4541 * subxact didn't save it, so it doesn't need restoring.
4543 state = afterTriggers.state_stack[my_level];
4546 pfree(afterTriggers.state);
4547 afterTriggers.state = state;
4549 /* this avoids double pfree if error later: */
4550 afterTriggers.state_stack[my_level] = NULL;
4553 * Scan for any remaining deferred events that were marked DONE or IN
4554 * PROGRESS by this subxact or a child, and un-mark them. We can
4555 * recognize such events because they have a firing ID greater than or
4556 * equal to the firing_counter value we saved at subtransaction start.
4557 * (This essentially assumes that the current subxact includes all
4558 * subxacts started after it.)
4560 subxact_firing_id = afterTriggers.firing_stack[my_level];
4561 for_each_event_chunk(event, chunk, afterTriggers.events)
4563 AfterTriggerShared evtshared = GetTriggerSharedData(event);
4565 if (event->ate_flags &
4566 (AFTER_TRIGGER_DONE | AFTER_TRIGGER_IN_PROGRESS))
4568 if (evtshared->ats_firing_id >= subxact_firing_id)
4570 ~(AFTER_TRIGGER_DONE | AFTER_TRIGGER_IN_PROGRESS);
4577 * AfterTriggerEnlargeQueryState()
4579 * Prepare the necessary state so that we can record AFTER trigger events
4580 * queued by a query. It is allowed to have nested queries within a
4581 * (sub)transaction, so we need to have separate state for each query
4586 AfterTriggerEnlargeQueryState(void)
4588 int init_depth = afterTriggers.maxquerydepth;
4590 Assert(afterTriggers.query_depth >= afterTriggers.maxquerydepth);
4592 if (afterTriggers.maxquerydepth == 0)
4594 int new_alloc = Max(afterTriggers.query_depth + 1, 8);
4596 afterTriggers.query_stack = (AfterTriggerEventList *)
4597 MemoryContextAlloc(TopTransactionContext,
4598 new_alloc * sizeof(AfterTriggerEventList));
4599 afterTriggers.fdw_tuplestores = (Tuplestorestate **)
4600 MemoryContextAllocZero(TopTransactionContext,
4601 new_alloc * sizeof(Tuplestorestate *));
4602 afterTriggers.old_tuplestores = (Tuplestorestate **)
4603 MemoryContextAllocZero(TopTransactionContext,
4604 new_alloc * sizeof(Tuplestorestate *));
4605 afterTriggers.new_tuplestores = (Tuplestorestate **)
4606 MemoryContextAllocZero(TopTransactionContext,
4607 new_alloc * sizeof(Tuplestorestate *));
4608 afterTriggers.maxquerydepth = new_alloc;
4612 /* repalloc will keep the stack in the same context */
4613 int old_alloc = afterTriggers.maxquerydepth;
4614 int new_alloc = Max(afterTriggers.query_depth + 1,
4617 afterTriggers.query_stack = (AfterTriggerEventList *)
4618 repalloc(afterTriggers.query_stack,
4619 new_alloc * sizeof(AfterTriggerEventList));
4620 afterTriggers.fdw_tuplestores = (Tuplestorestate **)
4621 repalloc(afterTriggers.fdw_tuplestores,
4622 new_alloc * sizeof(Tuplestorestate *));
4623 afterTriggers.old_tuplestores = (Tuplestorestate **)
4624 repalloc(afterTriggers.old_tuplestores,
4625 new_alloc * sizeof(Tuplestorestate *));
4626 afterTriggers.new_tuplestores = (Tuplestorestate **)
4627 repalloc(afterTriggers.new_tuplestores,
4628 new_alloc * sizeof(Tuplestorestate *));
4629 /* Clear newly-allocated slots for subsequent lazy initialization. */
4630 memset(afterTriggers.fdw_tuplestores + old_alloc,
4631 0, (new_alloc - old_alloc) * sizeof(Tuplestorestate *));
4632 memset(afterTriggers.old_tuplestores + old_alloc,
4633 0, (new_alloc - old_alloc) * sizeof(Tuplestorestate *));
4634 memset(afterTriggers.new_tuplestores + old_alloc,
4635 0, (new_alloc - old_alloc) * sizeof(Tuplestorestate *));
4636 afterTriggers.maxquerydepth = new_alloc;
4639 /* Initialize new query lists to empty */
4640 while (init_depth < afterTriggers.maxquerydepth)
4642 AfterTriggerEventList *events;
4644 events = &afterTriggers.query_stack[init_depth];
4645 events->head = NULL;
4646 events->tail = NULL;
4647 events->tailfree = NULL;
4654 * Create an empty SetConstraintState with room for numalloc trigstates
4656 static SetConstraintState
4657 SetConstraintStateCreate(int numalloc)
4659 SetConstraintState state;
4661 /* Behave sanely with numalloc == 0 */
4666 * We assume that zeroing will correctly initialize the state values.
4668 state = (SetConstraintState)
4669 MemoryContextAllocZero(TopTransactionContext,
4670 offsetof(SetConstraintStateData, trigstates) +
4671 numalloc * sizeof(SetConstraintTriggerData));
4673 state->numalloc = numalloc;
4679 * Copy a SetConstraintState
4681 static SetConstraintState
4682 SetConstraintStateCopy(SetConstraintState origstate)
4684 SetConstraintState state;
4686 state = SetConstraintStateCreate(origstate->numstates);
4688 state->all_isset = origstate->all_isset;
4689 state->all_isdeferred = origstate->all_isdeferred;
4690 state->numstates = origstate->numstates;
4691 memcpy(state->trigstates, origstate->trigstates,
4692 origstate->numstates * sizeof(SetConstraintTriggerData));
4698 * Add a per-trigger item to a SetConstraintState. Returns possibly-changed
4699 * pointer to the state object (it will change if we have to repalloc).
4701 static SetConstraintState
4702 SetConstraintStateAddItem(SetConstraintState state,
4703 Oid tgoid, bool tgisdeferred)
4705 if (state->numstates >= state->numalloc)
4707 int newalloc = state->numalloc * 2;
4709 newalloc = Max(newalloc, 8); /* in case original has size 0 */
4710 state = (SetConstraintState)
4712 offsetof(SetConstraintStateData, trigstates) +
4713 newalloc * sizeof(SetConstraintTriggerData));
4714 state->numalloc = newalloc;
4715 Assert(state->numstates < state->numalloc);
4718 state->trigstates[state->numstates].sct_tgoid = tgoid;
4719 state->trigstates[state->numstates].sct_tgisdeferred = tgisdeferred;
4726 * AfterTriggerSetState()
4728 * Execute the SET CONSTRAINTS ... utility command.
4732 AfterTriggerSetState(ConstraintsSetStmt *stmt)
4734 int my_level = GetCurrentTransactionNestLevel();
4736 /* If we haven't already done so, initialize our state. */
4737 if (afterTriggers.state == NULL)
4738 afterTriggers.state = SetConstraintStateCreate(8);
4741 * If in a subtransaction, and we didn't save the current state already,
4742 * save it so it can be restored if the subtransaction aborts.
4745 afterTriggers.state_stack[my_level] == NULL)
4747 afterTriggers.state_stack[my_level] =
4748 SetConstraintStateCopy(afterTriggers.state);
4752 * Handle SET CONSTRAINTS ALL ...
4754 if (stmt->constraints == NIL)
4757 * Forget any previous SET CONSTRAINTS commands in this transaction.
4759 afterTriggers.state->numstates = 0;
4762 * Set the per-transaction ALL state to known.
4764 afterTriggers.state->all_isset = true;
4765 afterTriggers.state->all_isdeferred = stmt->deferred;
4771 List *conoidlist = NIL;
4772 List *tgoidlist = NIL;
4776 * Handle SET CONSTRAINTS constraint-name [, ...]
4778 * First, identify all the named constraints and make a list of their
4779 * OIDs. Since, unlike the SQL spec, we allow multiple constraints of
4780 * the same name within a schema, the specifications are not
4781 * necessarily unique. Our strategy is to target all matching
4782 * constraints within the first search-path schema that has any
4783 * matches, but disregard matches in schemas beyond the first match.
4784 * (This is a bit odd but it's the historical behavior.)
4786 conrel = heap_open(ConstraintRelationId, AccessShareLock);
4788 foreach(lc, stmt->constraints)
4790 RangeVar *constraint = lfirst(lc);
4792 List *namespacelist;
4795 if (constraint->catalogname)
4797 if (strcmp(constraint->catalogname, get_database_name(MyDatabaseId)) != 0)
4799 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4800 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
4801 constraint->catalogname, constraint->schemaname,
4802 constraint->relname)));
4806 * If we're given the schema name with the constraint, look only
4807 * in that schema. If given a bare constraint name, use the
4808 * search path to find the first matching constraint.
4810 if (constraint->schemaname)
4812 Oid namespaceId = LookupExplicitNamespace(constraint->schemaname,
4815 namespacelist = list_make1_oid(namespaceId);
4819 namespacelist = fetch_search_path(true);
4823 foreach(nslc, namespacelist)
4825 Oid namespaceId = lfirst_oid(nslc);
4826 SysScanDesc conscan;
4827 ScanKeyData skey[2];
4830 ScanKeyInit(&skey[0],
4831 Anum_pg_constraint_conname,
4832 BTEqualStrategyNumber, F_NAMEEQ,
4833 CStringGetDatum(constraint->relname));
4834 ScanKeyInit(&skey[1],
4835 Anum_pg_constraint_connamespace,
4836 BTEqualStrategyNumber, F_OIDEQ,
4837 ObjectIdGetDatum(namespaceId));
4839 conscan = systable_beginscan(conrel, ConstraintNameNspIndexId,
4840 true, NULL, 2, skey);
4842 while (HeapTupleIsValid(tup = systable_getnext(conscan)))
4844 Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tup);
4846 if (con->condeferrable)
4847 conoidlist = lappend_oid(conoidlist,
4848 HeapTupleGetOid(tup));
4849 else if (stmt->deferred)
4851 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
4852 errmsg("constraint \"%s\" is not deferrable",
4853 constraint->relname)));
4857 systable_endscan(conscan);
4860 * Once we've found a matching constraint we do not search
4861 * later parts of the search path.
4867 list_free(namespacelist);
4874 (errcode(ERRCODE_UNDEFINED_OBJECT),
4875 errmsg("constraint \"%s\" does not exist",
4876 constraint->relname)));
4879 heap_close(conrel, AccessShareLock);
4882 * Now, locate the trigger(s) implementing each of these constraints,
4883 * and make a list of their OIDs.
4885 tgrel = heap_open(TriggerRelationId, AccessShareLock);
4887 foreach(lc, conoidlist)
4889 Oid conoid = lfirst_oid(lc);
4898 Anum_pg_trigger_tgconstraint,
4899 BTEqualStrategyNumber, F_OIDEQ,
4900 ObjectIdGetDatum(conoid));
4902 tgscan = systable_beginscan(tgrel, TriggerConstraintIndexId, true,
4905 while (HeapTupleIsValid(htup = systable_getnext(tgscan)))
4907 Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
4910 * Silently skip triggers that are marked as non-deferrable in
4911 * pg_trigger. This is not an error condition, since a
4912 * deferrable RI constraint may have some non-deferrable
4915 if (pg_trigger->tgdeferrable)
4916 tgoidlist = lappend_oid(tgoidlist,
4917 HeapTupleGetOid(htup));
4922 systable_endscan(tgscan);
4924 /* Safety check: a deferrable constraint should have triggers */
4926 elog(ERROR, "no triggers found for constraint with OID %u",
4930 heap_close(tgrel, AccessShareLock);
4933 * Now we can set the trigger states of individual triggers for this
4936 foreach(lc, tgoidlist)
4938 Oid tgoid = lfirst_oid(lc);
4939 SetConstraintState state = afterTriggers.state;
4943 for (i = 0; i < state->numstates; i++)
4945 if (state->trigstates[i].sct_tgoid == tgoid)
4947 state->trigstates[i].sct_tgisdeferred = stmt->deferred;
4954 afterTriggers.state =
4955 SetConstraintStateAddItem(state, tgoid, stmt->deferred);
4961 * SQL99 requires that when a constraint is set to IMMEDIATE, any deferred
4962 * checks against that constraint must be made when the SET CONSTRAINTS
4963 * command is executed -- i.e. the effects of the SET CONSTRAINTS command
4964 * apply retroactively. We've updated the constraints state, so scan the
4965 * list of previously deferred events to fire any that have now become
4968 * Obviously, if this was SET ... DEFERRED then it can't have converted
4969 * any unfired events to immediate, so we need do nothing in that case.
4971 if (!stmt->deferred)
4973 AfterTriggerEventList *events = &afterTriggers.events;
4974 bool snapshot_set = false;
4976 while (afterTriggerMarkEvents(events, NULL, true))
4978 CommandId firing_id = afterTriggers.firing_counter++;
4981 * Make sure a snapshot has been established in case trigger
4982 * functions need one. Note that we avoid setting a snapshot if
4983 * we don't find at least one trigger that has to be fired now.
4984 * This is so that BEGIN; SET CONSTRAINTS ...; SET TRANSACTION
4985 * ISOLATION LEVEL SERIALIZABLE; ... works properly. (If we are
4986 * at the start of a transaction it's not possible for any trigger
4987 * events to be queued yet.)
4991 PushActiveSnapshot(GetTransactionSnapshot());
4992 snapshot_set = true;
4996 * We can delete fired events if we are at top transaction level,
4997 * but we'd better not if inside a subtransaction, since the
4998 * subtransaction could later get rolled back.
5000 if (afterTriggerInvokeEvents(events, firing_id, NULL,
5001 !IsSubTransaction()))
5002 break; /* all fired */
5006 PopActiveSnapshot();
5011 * AfterTriggerPendingOnRel()
5012 * Test to see if there are any pending after-trigger events for rel.
5014 * This is used by TRUNCATE, CLUSTER, ALTER TABLE, etc to detect whether
5015 * it is unsafe to perform major surgery on a relation. Note that only
5016 * local pending events are examined. We assume that having exclusive lock
5017 * on a rel guarantees there are no unserviced events in other backends ---
5018 * but having a lock does not prevent there being such events in our own.
5020 * In some scenarios it'd be reasonable to remove pending events (more
5021 * specifically, mark them DONE by the current subxact) but without a lot
5022 * of knowledge of the trigger semantics we can't do this in general.
5026 AfterTriggerPendingOnRel(Oid relid)
5028 AfterTriggerEvent event;
5029 AfterTriggerEventChunk *chunk;
5032 /* Scan queued events */
5033 for_each_event_chunk(event, chunk, afterTriggers.events)
5035 AfterTriggerShared evtshared = GetTriggerSharedData(event);
5038 * We can ignore completed events. (Even if a DONE flag is rolled
5039 * back by subxact abort, it's OK because the effects of the TRUNCATE
5040 * or whatever must get rolled back too.)
5042 if (event->ate_flags & AFTER_TRIGGER_DONE)
5045 if (evtshared->ats_relid == relid)
5050 * Also scan events queued by incomplete queries. This could only matter
5051 * if TRUNCATE/etc is executed by a function or trigger within an updating
5052 * query on the same relation, which is pretty perverse, but let's check.
5054 for (depth = 0; depth <= afterTriggers.query_depth && depth < afterTriggers.maxquerydepth; depth++)
5056 for_each_event_chunk(event, chunk, afterTriggers.query_stack[depth])
5058 AfterTriggerShared evtshared = GetTriggerSharedData(event);
5060 if (event->ate_flags & AFTER_TRIGGER_DONE)
5063 if (evtshared->ats_relid == relid)
5073 * AfterTriggerSaveEvent()
5075 * Called by ExecA[RS]...Triggers() to queue up the triggers that should
5076 * be fired for an event.
5078 * NOTE: this is called whenever there are any triggers associated with
5079 * the event (even if they are disabled). This function decides which
5080 * triggers actually need to be queued. It is also called after each row,
5081 * even if there are no triggers for that event, if there are any AFTER
5082 * STATEMENT triggers for the statement which use transition tables, so that
5083 * the transition tuplestores can be built.
5085 * Transition tuplestores are built now, rather than when events are pulled
5086 * off of the queue because AFTER ROW triggers are allowed to select from the
5087 * transition tables for the statement.
5091 AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
5092 int event, bool row_trigger,
5093 HeapTuple oldtup, HeapTuple newtup,
5094 List *recheckIndexes, Bitmapset *modifiedCols)
5096 Relation rel = relinfo->ri_RelationDesc;
5097 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
5098 AfterTriggerEventData new_event;
5099 AfterTriggerSharedData new_shared;
5100 char relkind = relinfo->ri_RelationDesc->rd_rel->relkind;
5104 Tuplestorestate *fdw_tuplestore = NULL;
5107 * Check state. We use a normal test not Assert because it is possible to
5108 * reach here in the wrong state given misconfigured RI triggers, in
5109 * particular deferring a cascade action trigger.
5111 if (afterTriggers.query_depth < 0)
5112 elog(ERROR, "AfterTriggerSaveEvent() called outside of query");
5114 /* Be sure we have enough space to record events at this query depth. */
5115 if (afterTriggers.query_depth >= afterTriggers.maxquerydepth)
5116 AfterTriggerEnlargeQueryState();
5119 * If the relation has AFTER ... FOR EACH ROW triggers, capture rows into
5120 * transition tuplestores for this depth.
5124 if ((event == TRIGGER_EVENT_DELETE &&
5125 trigdesc->trig_delete_old_table) ||
5126 (event == TRIGGER_EVENT_UPDATE &&
5127 trigdesc->trig_update_old_table))
5129 Tuplestorestate *old_tuplestore;
5131 Assert(oldtup != NULL);
5133 GetTriggerTransitionTuplestore
5134 (afterTriggers.old_tuplestores);
5135 tuplestore_puttuple(old_tuplestore, oldtup);
5137 if ((event == TRIGGER_EVENT_INSERT &&
5138 trigdesc->trig_insert_new_table) ||
5139 (event == TRIGGER_EVENT_UPDATE &&
5140 trigdesc->trig_update_new_table))
5142 Tuplestorestate *new_tuplestore;
5144 Assert(newtup != NULL);
5146 GetTriggerTransitionTuplestore
5147 (afterTriggers.new_tuplestores);
5148 tuplestore_puttuple(new_tuplestore, newtup);
5151 /* If transition tables are the only reason we're here, return. */
5152 if ((event == TRIGGER_EVENT_DELETE && !trigdesc->trig_delete_after_row) ||
5153 (event == TRIGGER_EVENT_INSERT && !trigdesc->trig_insert_after_row) ||
5154 (event == TRIGGER_EVENT_UPDATE && !trigdesc->trig_update_after_row))
5159 * Validate the event code and collect the associated tuple CTIDs.
5161 * The event code will be used both as a bitmask and an array offset, so
5162 * validation is important to make sure we don't walk off the edge of our
5167 case TRIGGER_EVENT_INSERT:
5168 tgtype_event = TRIGGER_TYPE_INSERT;
5171 Assert(oldtup == NULL);
5172 Assert(newtup != NULL);
5173 ItemPointerCopy(&(newtup->t_self), &(new_event.ate_ctid1));
5174 ItemPointerSetInvalid(&(new_event.ate_ctid2));
5178 Assert(oldtup == NULL);
5179 Assert(newtup == NULL);
5180 ItemPointerSetInvalid(&(new_event.ate_ctid1));
5181 ItemPointerSetInvalid(&(new_event.ate_ctid2));
5184 case TRIGGER_EVENT_DELETE:
5185 tgtype_event = TRIGGER_TYPE_DELETE;
5188 Assert(oldtup != NULL);
5189 Assert(newtup == NULL);
5190 ItemPointerCopy(&(oldtup->t_self), &(new_event.ate_ctid1));
5191 ItemPointerSetInvalid(&(new_event.ate_ctid2));
5195 Assert(oldtup == NULL);
5196 Assert(newtup == NULL);
5197 ItemPointerSetInvalid(&(new_event.ate_ctid1));
5198 ItemPointerSetInvalid(&(new_event.ate_ctid2));
5201 case TRIGGER_EVENT_UPDATE:
5202 tgtype_event = TRIGGER_TYPE_UPDATE;
5205 Assert(oldtup != NULL);
5206 Assert(newtup != NULL);
5207 ItemPointerCopy(&(oldtup->t_self), &(new_event.ate_ctid1));
5208 ItemPointerCopy(&(newtup->t_self), &(new_event.ate_ctid2));
5212 Assert(oldtup == NULL);
5213 Assert(newtup == NULL);
5214 ItemPointerSetInvalid(&(new_event.ate_ctid1));
5215 ItemPointerSetInvalid(&(new_event.ate_ctid2));
5218 case TRIGGER_EVENT_TRUNCATE:
5219 tgtype_event = TRIGGER_TYPE_TRUNCATE;
5220 Assert(oldtup == NULL);
5221 Assert(newtup == NULL);
5222 ItemPointerSetInvalid(&(new_event.ate_ctid1));
5223 ItemPointerSetInvalid(&(new_event.ate_ctid2));
5226 elog(ERROR, "invalid after-trigger event code: %d", event);
5227 tgtype_event = 0; /* keep compiler quiet */
5231 if (!(relkind == RELKIND_FOREIGN_TABLE && row_trigger))
5232 new_event.ate_flags = (row_trigger && event == TRIGGER_EVENT_UPDATE) ?
5233 AFTER_TRIGGER_2CTID : AFTER_TRIGGER_1CTID;
5234 /* else, we'll initialize ate_flags for each trigger */
5236 tgtype_level = (row_trigger ? TRIGGER_TYPE_ROW : TRIGGER_TYPE_STATEMENT);
5238 for (i = 0; i < trigdesc->numtriggers; i++)
5240 Trigger *trigger = &trigdesc->triggers[i];
5242 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
5247 if (!TriggerEnabled(estate, relinfo, trigger, event,
5248 modifiedCols, oldtup, newtup))
5251 if (relkind == RELKIND_FOREIGN_TABLE && row_trigger)
5253 if (fdw_tuplestore == NULL)
5256 GetTriggerTransitionTuplestore
5257 (afterTriggers.fdw_tuplestores);
5258 new_event.ate_flags = AFTER_TRIGGER_FDW_FETCH;
5261 /* subsequent event for the same tuple */
5262 new_event.ate_flags = AFTER_TRIGGER_FDW_REUSE;
5266 * If the trigger is a foreign key enforcement trigger, there are
5267 * certain cases where we can skip queueing the event because we can
5268 * tell by inspection that the FK constraint will still pass.
5270 if (TRIGGER_FIRED_BY_UPDATE(event))
5272 switch (RI_FKey_trigger_type(trigger->tgfoid))
5275 /* Update on trigger's PK table */
5276 if (!RI_FKey_pk_upd_check_required(trigger, rel,
5279 /* skip queuing this event */
5285 /* Update on trigger's FK table */
5286 if (!RI_FKey_fk_upd_check_required(trigger, rel,
5289 /* skip queuing this event */
5294 case RI_TRIGGER_NONE:
5295 /* Not an FK trigger */
5301 * If the trigger is a deferred unique constraint check trigger, only
5302 * queue it if the unique constraint was potentially violated, which
5303 * we know from index insertion time.
5305 if (trigger->tgfoid == F_UNIQUE_KEY_RECHECK)
5307 if (!list_member_oid(recheckIndexes, trigger->tgconstrindid))
5308 continue; /* Uniqueness definitely not violated */
5312 * Fill in event structure and add it to the current query's queue.
5314 new_shared.ats_event =
5315 (event & TRIGGER_EVENT_OPMASK) |
5316 (row_trigger ? TRIGGER_EVENT_ROW : 0) |
5317 (trigger->tgdeferrable ? AFTER_TRIGGER_DEFERRABLE : 0) |
5318 (trigger->tginitdeferred ? AFTER_TRIGGER_INITDEFERRED : 0);
5319 new_shared.ats_tgoid = trigger->tgoid;
5320 new_shared.ats_relid = RelationGetRelid(rel);
5321 new_shared.ats_firing_id = 0;
5323 afterTriggerAddEvent(&afterTriggers.query_stack[afterTriggers.query_depth],
5324 &new_event, &new_shared);
5328 * Finally, spool any foreign tuple(s). The tuplestore squashes them to
5329 * minimal tuples, so this loses any system columns. The executor lost
5330 * those columns before us, for an unrelated reason, so this is fine.
5335 tuplestore_puttuple(fdw_tuplestore, oldtup);
5337 tuplestore_puttuple(fdw_tuplestore, newtup);
5342 pg_trigger_depth(PG_FUNCTION_ARGS)
5344 PG_RETURN_INT32(MyTriggerDepth);