PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
trigger.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * trigger.c
4  * PostgreSQL TRIGGERs support code.
5  *
6  * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  * src/backend/commands/trigger.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15 
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"
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"
44 #include "pgstat.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"
61 
62 
63 /* GUC variables */
65 
66 /* How many levels deep into trigger execution are we? */
67 static int MyTriggerDepth = 0;
68 
69 /*
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.
74  */
75 #define GetUpdatedColumns(relinfo, estate) \
76  (rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->updatedCols)
77 
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,
82  EPQState *epqstate,
83  ResultRelInfo *relinfo,
84  ItemPointer tid,
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);
92  int tgindx,
93  FmgrInfo *finfo,
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);
101 
102 
103 /*
104  * Create a trigger. Returns the address of the created trigger.
105  *
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.
108  *
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.
111  *
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.
115  *
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.)
121  *
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.
124  *
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.
128  *
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.
132  *
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
135  * compatibility.
136  */
138 CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
139  Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid,
140  bool isInternal)
141 {
142  int16 tgtype;
143  int ncolumns;
144  int16 *columns;
145  int2vector *tgattr;
146  Node *whenClause;
147  List *whenRtable;
148  char *qual;
150  bool nulls[Natts_pg_trigger];
151  Relation rel;
152  AclResult aclresult;
153  Relation tgrel;
154  SysScanDesc tgscan;
155  ScanKeyData key;
156  Relation pgrel;
157  HeapTuple tuple;
158  Oid fargtypes[1]; /* dummy */
159  Oid funcoid;
160  Oid funcrettype;
161  Oid trigoid;
162  char internaltrigname[NAMEDATALEN];
163  char *trigname;
164  Oid constrrelid = InvalidOid;
165  ObjectAddress myself,
166  referenced;
167 
168  if (OidIsValid(relOid))
169  rel = heap_open(relOid, ShareRowExclusiveLock);
170  else
172 
173  /*
174  * Triggers must be on tables or views, and there are additional
175  * relation-type-specific restrictions.
176  */
177  if (rel->rd_rel->relkind == RELKIND_RELATION)
178  {
179  /* Tables can't have INSTEAD OF triggers */
180  if (stmt->timing != TRIGGER_TYPE_BEFORE &&
181  stmt->timing != TRIGGER_TYPE_AFTER)
182  ereport(ERROR,
183  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
184  errmsg("\"%s\" is a table",
186  errdetail("Tables cannot have INSTEAD OF triggers.")));
187  }
188  else if (rel->rd_rel->relkind == RELKIND_VIEW)
189  {
190  /*
191  * Views can have INSTEAD OF triggers (which we check below are
192  * row-level), or statement-level BEFORE/AFTER triggers.
193  */
194  if (stmt->timing != TRIGGER_TYPE_INSTEAD && stmt->row)
195  ereport(ERROR,
196  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
197  errmsg("\"%s\" is a view",
199  errdetail("Views cannot have row-level BEFORE or AFTER triggers.")));
200  /* Disallow TRUNCATE triggers on VIEWs */
201  if (TRIGGER_FOR_TRUNCATE(stmt->events))
202  ereport(ERROR,
203  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
204  errmsg("\"%s\" is a view",
206  errdetail("Views cannot have TRUNCATE triggers.")));
207  }
208  else if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
209  {
210  if (stmt->timing != TRIGGER_TYPE_BEFORE &&
211  stmt->timing != TRIGGER_TYPE_AFTER)
212  ereport(ERROR,
213  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
214  errmsg("\"%s\" is a foreign table",
216  errdetail("Foreign tables cannot have INSTEAD OF triggers.")));
217 
218  if (TRIGGER_FOR_TRUNCATE(stmt->events))
219  ereport(ERROR,
220  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
221  errmsg("\"%s\" is a foreign table",
223  errdetail("Foreign tables cannot have TRUNCATE triggers.")));
224 
225  if (stmt->isconstraint)
226  ereport(ERROR,
227  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
228  errmsg("\"%s\" is a foreign table",
230  errdetail("Foreign tables cannot have constraint triggers.")));
231  }
232  else
233  ereport(ERROR,
234  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
235  errmsg("\"%s\" is not a table or view",
236  RelationGetRelationName(rel))));
237 
239  ereport(ERROR,
240  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
241  errmsg("permission denied: \"%s\" is a system catalog",
242  RelationGetRelationName(rel))));
243 
244  if (stmt->isconstraint)
245  {
246  /*
247  * We must take a lock on the target relation to protect against
248  * concurrent drop. It's not clear that AccessShareLock is strong
249  * enough, but we certainly need at least that much... otherwise, we
250  * might end up creating a pg_constraint entry referencing a
251  * nonexistent table.
252  */
253  if (OidIsValid(refRelOid))
254  {
255  LockRelationOid(refRelOid, AccessShareLock);
256  constrrelid = refRelOid;
257  }
258  else if (stmt->constrrel != NULL)
259  constrrelid = RangeVarGetRelid(stmt->constrrel, AccessShareLock,
260  false);
261  }
262 
263  /* permission checks */
264  if (!isInternal)
265  {
266  aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
267  ACL_TRIGGER);
268  if (aclresult != ACLCHECK_OK)
269  aclcheck_error(aclresult, ACL_KIND_CLASS,
271 
272  if (OidIsValid(constrrelid))
273  {
274  aclresult = pg_class_aclcheck(constrrelid, GetUserId(),
275  ACL_TRIGGER);
276  if (aclresult != ACLCHECK_OK)
277  aclcheck_error(aclresult, ACL_KIND_CLASS,
278  get_rel_name(constrrelid));
279  }
280  }
281 
282  /* Compute tgtype */
283  TRIGGER_CLEAR_TYPE(tgtype);
284  if (stmt->row)
285  TRIGGER_SETT_ROW(tgtype);
286  tgtype |= stmt->timing;
287  tgtype |= stmt->events;
288 
289  /* Disallow ROW-level TRUNCATE triggers */
290  if (TRIGGER_FOR_ROW(tgtype) && TRIGGER_FOR_TRUNCATE(tgtype))
291  ereport(ERROR,
292  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
293  errmsg("TRUNCATE FOR EACH ROW triggers are not supported")));
294 
295  /* INSTEAD triggers must be row-level, and can't have WHEN or columns */
296  if (TRIGGER_FOR_INSTEAD(tgtype))
297  {
298  if (!TRIGGER_FOR_ROW(tgtype))
299  ereport(ERROR,
300  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
301  errmsg("INSTEAD OF triggers must be FOR EACH ROW")));
302  if (stmt->whenClause)
303  ereport(ERROR,
304  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
305  errmsg("INSTEAD OF triggers cannot have WHEN conditions")));
306  if (stmt->columns != NIL)
307  ereport(ERROR,
308  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
309  errmsg("INSTEAD OF triggers cannot have column lists")));
310  }
311 
312  /*
313  * Parse the WHEN clause, if any
314  */
315  if (stmt->whenClause)
316  {
317  ParseState *pstate;
318  RangeTblEntry *rte;
319  List *varList;
320  ListCell *lc;
321 
322  /* Set up a pstate to parse with */
323  pstate = make_parsestate(NULL);
324  pstate->p_sourcetext = queryString;
325 
326  /*
327  * Set up RTEs for OLD and NEW references.
328  *
329  * 'OLD' must always have varno equal to 1 and 'NEW' equal to 2.
330  */
331  rte = addRangeTableEntryForRelation(pstate, rel,
332  makeAlias("old", NIL),
333  false, false);
334  addRTEtoQuery(pstate, rte, false, true, true);
335  rte = addRangeTableEntryForRelation(pstate, rel,
336  makeAlias("new", NIL),
337  false, false);
338  addRTEtoQuery(pstate, rte, false, true, true);
339 
340  /* Transform expression. Copy to be sure we don't modify original */
341  whenClause = transformWhereClause(pstate,
342  copyObject(stmt->whenClause),
344  "WHEN");
345  /* we have to fix its collations too */
346  assign_expr_collations(pstate, whenClause);
347 
348  /*
349  * Check for disallowed references to OLD/NEW.
350  *
351  * NB: pull_var_clause is okay here only because we don't allow
352  * subselects in WHEN clauses; it would fail to examine the contents
353  * of subselects.
354  */
355  varList = pull_var_clause(whenClause, 0);
356  foreach(lc, varList)
357  {
358  Var *var = (Var *) lfirst(lc);
359 
360  switch (var->varno)
361  {
362  case PRS2_OLD_VARNO:
363  if (!TRIGGER_FOR_ROW(tgtype))
364  ereport(ERROR,
365  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
366  errmsg("statement trigger's WHEN condition cannot reference column values"),
367  parser_errposition(pstate, var->location)));
368  if (TRIGGER_FOR_INSERT(tgtype))
369  ereport(ERROR,
370  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
371  errmsg("INSERT trigger's WHEN condition cannot reference OLD values"),
372  parser_errposition(pstate, var->location)));
373  /* system columns are okay here */
374  break;
375  case PRS2_NEW_VARNO:
376  if (!TRIGGER_FOR_ROW(tgtype))
377  ereport(ERROR,
378  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
379  errmsg("statement trigger's WHEN condition cannot reference column values"),
380  parser_errposition(pstate, var->location)));
381  if (TRIGGER_FOR_DELETE(tgtype))
382  ereport(ERROR,
383  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
384  errmsg("DELETE trigger's WHEN condition cannot reference NEW values"),
385  parser_errposition(pstate, var->location)));
386  if (var->varattno < 0 && TRIGGER_FOR_BEFORE(tgtype))
387  ereport(ERROR,
388  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
389  errmsg("BEFORE trigger's WHEN condition cannot reference NEW system columns"),
390  parser_errposition(pstate, var->location)));
391  break;
392  default:
393  /* can't happen without add_missing_from, so just elog */
394  elog(ERROR, "trigger WHEN condition cannot contain references to other relations");
395  break;
396  }
397  }
398 
399  /* we'll need the rtable for recordDependencyOnExpr */
400  whenRtable = pstate->p_rtable;
401 
402  qual = nodeToString(whenClause);
403 
404  free_parsestate(pstate);
405  }
406  else
407  {
408  whenClause = NULL;
409  whenRtable = NIL;
410  qual = NULL;
411  }
412 
413  /*
414  * Find and validate the trigger function.
415  */
416  funcoid = LookupFuncName(stmt->funcname, 0, fargtypes, false);
417  if (!isInternal)
418  {
419  aclresult = pg_proc_aclcheck(funcoid, GetUserId(), ACL_EXECUTE);
420  if (aclresult != ACLCHECK_OK)
421  aclcheck_error(aclresult, ACL_KIND_PROC,
422  NameListToString(stmt->funcname));
423  }
424  funcrettype = get_func_rettype(funcoid);
425  if (funcrettype != TRIGGEROID)
426  {
427  /*
428  * We allow OPAQUE just so we can load old dump files. When we see a
429  * trigger function declared OPAQUE, change it to TRIGGER.
430  */
431  if (funcrettype == OPAQUEOID)
432  {
434  (errmsg("changing return type of function %s from \"opaque\" to \"trigger\"",
435  NameListToString(stmt->funcname))));
437  }
438  else
439  ereport(ERROR,
440  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
441  errmsg("function %s must return type %s",
442  NameListToString(stmt->funcname), "trigger")));
443  }
444 
445  /*
446  * If the command is a user-entered CREATE CONSTRAINT TRIGGER command that
447  * references one of the built-in RI_FKey trigger functions, assume it is
448  * from a dump of a pre-7.3 foreign key constraint, and take steps to
449  * convert this legacy representation into a regular foreign key
450  * constraint. Ugly, but necessary for loading old dump files.
451  */
452  if (stmt->isconstraint && !isInternal &&
453  list_length(stmt->args) >= 6 &&
454  (list_length(stmt->args) % 2) == 0 &&
456  {
457  /* Keep lock on target rel until end of xact */
458  heap_close(rel, NoLock);
459 
460  ConvertTriggerToFK(stmt, funcoid);
461 
462  return InvalidObjectAddress;
463  }
464 
465  /*
466  * If it's a user-entered CREATE CONSTRAINT TRIGGER command, make a
467  * corresponding pg_constraint entry.
468  */
469  if (stmt->isconstraint && !OidIsValid(constraintOid))
470  {
471  /* Internal callers should have made their own constraints */
472  Assert(!isInternal);
473  constraintOid = CreateConstraintEntry(stmt->trigname,
476  stmt->deferrable,
477  stmt->initdeferred,
478  true,
479  RelationGetRelid(rel),
480  NULL, /* no conkey */
481  0,
482  InvalidOid, /* no domain */
483  InvalidOid, /* no index */
484  InvalidOid, /* no foreign key */
485  NULL,
486  NULL,
487  NULL,
488  NULL,
489  0,
490  ' ',
491  ' ',
492  ' ',
493  NULL, /* no exclusion */
494  NULL, /* no check constraint */
495  NULL,
496  NULL,
497  true, /* islocal */
498  0, /* inhcount */
499  true, /* isnoinherit */
500  isInternal); /* is_internal */
501  }
502 
503  /*
504  * Generate the trigger's OID now, so that we can use it in the name if
505  * needed.
506  */
508 
509  trigoid = GetNewOid(tgrel);
510 
511  /*
512  * If trigger is internally generated, modify the provided trigger name to
513  * ensure uniqueness by appending the trigger OID. (Callers will usually
514  * supply a simple constant trigger name in these cases.)
515  */
516  if (isInternal)
517  {
518  snprintf(internaltrigname, sizeof(internaltrigname),
519  "%s_%u", stmt->trigname, trigoid);
520  trigname = internaltrigname;
521  }
522  else
523  {
524  /* user-defined trigger; use the specified trigger name as-is */
525  trigname = stmt->trigname;
526  }
527 
528  /*
529  * Scan pg_trigger for existing triggers on relation. We do this only to
530  * give a nice error message if there's already a trigger of the same
531  * name. (The unique index on tgrelid/tgname would complain anyway.) We
532  * can skip this for internally generated triggers, since the name
533  * modification above should be sufficient.
534  *
535  * NOTE that this is cool only because we have ShareRowExclusiveLock on
536  * the relation, so the trigger set won't be changing underneath us.
537  */
538  if (!isInternal)
539  {
540  ScanKeyInit(&key,
542  BTEqualStrategyNumber, F_OIDEQ,
544  tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
545  NULL, 1, &key);
546  while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
547  {
548  Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
549 
550  if (namestrcmp(&(pg_trigger->tgname), trigname) == 0)
551  ereport(ERROR,
553  errmsg("trigger \"%s\" for relation \"%s\" already exists",
554  trigname, RelationGetRelationName(rel))));
555  }
556  systable_endscan(tgscan);
557  }
558 
559  /*
560  * Build the new pg_trigger tuple.
561  */
562  memset(nulls, false, sizeof(nulls));
563 
566  CStringGetDatum(trigname));
567  values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid);
568  values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype);
570  values[Anum_pg_trigger_tgisinternal - 1] = BoolGetDatum(isInternal);
571  values[Anum_pg_trigger_tgconstrrelid - 1] = ObjectIdGetDatum(constrrelid);
572  values[Anum_pg_trigger_tgconstrindid - 1] = ObjectIdGetDatum(indexOid);
573  values[Anum_pg_trigger_tgconstraint - 1] = ObjectIdGetDatum(constraintOid);
576 
577  if (stmt->args)
578  {
579  ListCell *le;
580  char *args;
581  int16 nargs = list_length(stmt->args);
582  int len = 0;
583 
584  foreach(le, stmt->args)
585  {
586  char *ar = strVal(lfirst(le));
587 
588  len += strlen(ar) + 4;
589  for (; *ar; ar++)
590  {
591  if (*ar == '\\')
592  len++;
593  }
594  }
595  args = (char *) palloc(len + 1);
596  args[0] = '\0';
597  foreach(le, stmt->args)
598  {
599  char *s = strVal(lfirst(le));
600  char *d = args + strlen(args);
601 
602  while (*s)
603  {
604  if (*s == '\\')
605  *d++ = '\\';
606  *d++ = *s++;
607  }
608  strcpy(d, "\\000");
609  }
610  values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(nargs);
612  CStringGetDatum(args));
613  }
614  else
615  {
616  values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(0);
618  CStringGetDatum(""));
619  }
620 
621  /* build column number array if it's a column-specific trigger */
622  ncolumns = list_length(stmt->columns);
623  if (ncolumns == 0)
624  columns = NULL;
625  else
626  {
627  ListCell *cell;
628  int i = 0;
629 
630  columns = (int16 *) palloc(ncolumns * sizeof(int16));
631  foreach(cell, stmt->columns)
632  {
633  char *name = strVal(lfirst(cell));
634  int16 attnum;
635  int j;
636 
637  /* Lookup column name. System columns are not allowed */
638  attnum = attnameAttNum(rel, name, false);
639  if (attnum == InvalidAttrNumber)
640  ereport(ERROR,
641  (errcode(ERRCODE_UNDEFINED_COLUMN),
642  errmsg("column \"%s\" of relation \"%s\" does not exist",
643  name, RelationGetRelationName(rel))));
644 
645  /* Check for duplicates */
646  for (j = i - 1; j >= 0; j--)
647  {
648  if (columns[j] == attnum)
649  ereport(ERROR,
650  (errcode(ERRCODE_DUPLICATE_COLUMN),
651  errmsg("column \"%s\" specified more than once",
652  name)));
653  }
654 
655  columns[i++] = attnum;
656  }
657  }
658  tgattr = buildint2vector(columns, ncolumns);
659  values[Anum_pg_trigger_tgattr - 1] = PointerGetDatum(tgattr);
660 
661  /* set tgqual if trigger has WHEN clause */
662  if (qual)
663  values[Anum_pg_trigger_tgqual - 1] = CStringGetTextDatum(qual);
664  else
665  nulls[Anum_pg_trigger_tgqual - 1] = true;
666 
667  tuple = heap_form_tuple(tgrel->rd_att, values, nulls);
668 
669  /* force tuple to have the desired OID */
670  HeapTupleSetOid(tuple, trigoid);
671 
672  /*
673  * Insert tuple into pg_trigger.
674  */
675  simple_heap_insert(tgrel, tuple);
676 
677  CatalogUpdateIndexes(tgrel, tuple);
678 
679  heap_freetuple(tuple);
681 
685 
686  /*
687  * Update relation's pg_class entry. Crucial side-effect: other backends
688  * (and this one too!) are sent SI message to make them rebuild relcache
689  * entries.
690  */
692  tuple = SearchSysCacheCopy1(RELOID,
694  if (!HeapTupleIsValid(tuple))
695  elog(ERROR, "cache lookup failed for relation %u",
696  RelationGetRelid(rel));
697 
698  ((Form_pg_class) GETSTRUCT(tuple))->relhastriggers = true;
699 
700  simple_heap_update(pgrel, &tuple->t_self, tuple);
701 
702  CatalogUpdateIndexes(pgrel, tuple);
703 
704  heap_freetuple(tuple);
706 
707  /*
708  * We used to try to update the rel's relcache entry here, but that's
709  * fairly pointless since it will happen as a byproduct of the upcoming
710  * CommandCounterIncrement...
711  */
712 
713  /*
714  * Record dependencies for trigger. Always place a normal dependency on
715  * the function.
716  */
717  myself.classId = TriggerRelationId;
718  myself.objectId = trigoid;
719  myself.objectSubId = 0;
720 
721  referenced.classId = ProcedureRelationId;
722  referenced.objectId = funcoid;
723  referenced.objectSubId = 0;
724  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
725 
726  if (isInternal && OidIsValid(constraintOid))
727  {
728  /*
729  * Internally-generated trigger for a constraint, so make it an
730  * internal dependency of the constraint. We can skip depending on
731  * the relation(s), as there'll be an indirect dependency via the
732  * constraint.
733  */
734  referenced.classId = ConstraintRelationId;
735  referenced.objectId = constraintOid;
736  referenced.objectSubId = 0;
737  recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
738  }
739  else
740  {
741  /*
742  * User CREATE TRIGGER, so place dependencies. We make trigger be
743  * auto-dropped if its relation is dropped or if the FK relation is
744  * dropped. (Auto drop is compatible with our pre-7.3 behavior.)
745  */
746  referenced.classId = RelationRelationId;
747  referenced.objectId = RelationGetRelid(rel);
748  referenced.objectSubId = 0;
749  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
750  if (OidIsValid(constrrelid))
751  {
752  referenced.classId = RelationRelationId;
753  referenced.objectId = constrrelid;
754  referenced.objectSubId = 0;
755  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
756  }
757  /* Not possible to have an index dependency in this case */
758  Assert(!OidIsValid(indexOid));
759 
760  /*
761  * If it's a user-specified constraint trigger, make the constraint
762  * internally dependent on the trigger instead of vice versa.
763  */
764  if (OidIsValid(constraintOid))
765  {
766  referenced.classId = ConstraintRelationId;
767  referenced.objectId = constraintOid;
768  referenced.objectSubId = 0;
769  recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
770  }
771  }
772 
773  /* If column-specific trigger, add normal dependencies on columns */
774  if (columns != NULL)
775  {
776  int i;
777 
778  referenced.classId = RelationRelationId;
779  referenced.objectId = RelationGetRelid(rel);
780  for (i = 0; i < ncolumns; i++)
781  {
782  referenced.objectSubId = columns[i];
783  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
784  }
785  }
786 
787  /*
788  * If it has a WHEN clause, add dependencies on objects mentioned in the
789  * expression (eg, functions, as well as any columns used).
790  */
791  if (whenClause != NULL)
792  recordDependencyOnExpr(&myself, whenClause, whenRtable,
794 
795  /* Post creation hook for new trigger */
797  isInternal);
798 
799  /* Keep lock on target rel until end of xact */
800  heap_close(rel, NoLock);
801 
802  return myself;
803 }
804 
805 
806 /*
807  * Convert legacy (pre-7.3) CREATE CONSTRAINT TRIGGER commands into
808  * full-fledged foreign key constraints.
809  *
810  * The conversion is complex because a pre-7.3 foreign key involved three
811  * separate triggers, which were reported separately in dumps. While the
812  * single trigger on the referencing table adds no new information, we need
813  * to know the trigger functions of both of the triggers on the referenced
814  * table to build the constraint declaration. Also, due to lack of proper
815  * dependency checking pre-7.3, it is possible that the source database had
816  * an incomplete set of triggers resulting in an only partially enforced
817  * FK constraint. (This would happen if one of the tables had been dropped
818  * and re-created, but only if the DB had been affected by a 7.0 pg_dump bug
819  * that caused loss of tgconstrrelid information.) We choose to translate to
820  * an FK constraint only when we've seen all three triggers of a set. This is
821  * implemented by storing unmatched items in a list in TopMemoryContext.
822  * We match triggers together by comparing the trigger arguments (which
823  * include constraint name, table and column names, so should be good enough).
824  */
825 typedef struct
826 {
827  List *args; /* list of (T_String) Values or NIL */
828  Oid funcoids[3]; /* OIDs of trigger functions */
829  /* The three function OIDs are stored in the order update, delete, child */
831 
832 static void
834 {
835  static List *info_list = NIL;
836 
837  static const char *const funcdescr[3] = {
838  gettext_noop("Found referenced table's UPDATE trigger."),
839  gettext_noop("Found referenced table's DELETE trigger."),
840  gettext_noop("Found referencing table's trigger.")
841  };
842 
843  char *constr_name;
844  char *fk_table_name;
845  char *pk_table_name;
846  char fk_matchtype = FKCONSTR_MATCH_SIMPLE;
847  List *fk_attrs = NIL;
848  List *pk_attrs = NIL;
850  int funcnum;
851  OldTriggerInfo *info = NULL;
852  ListCell *l;
853  int i;
854 
855  /* Parse out the trigger arguments */
856  constr_name = strVal(linitial(stmt->args));
857  fk_table_name = strVal(lsecond(stmt->args));
858  pk_table_name = strVal(lthird(stmt->args));
859  i = 0;
860  foreach(l, stmt->args)
861  {
862  Value *arg = (Value *) lfirst(l);
863 
864  i++;
865  if (i < 4) /* skip constraint and table names */
866  continue;
867  if (i == 4) /* handle match type */
868  {
869  if (strcmp(strVal(arg), "FULL") == 0)
870  fk_matchtype = FKCONSTR_MATCH_FULL;
871  else
872  fk_matchtype = FKCONSTR_MATCH_SIMPLE;
873  continue;
874  }
875  if (i % 2)
876  fk_attrs = lappend(fk_attrs, arg);
877  else
878  pk_attrs = lappend(pk_attrs, arg);
879  }
880 
881  /* Prepare description of constraint for use in messages */
882  initStringInfo(&buf);
883  appendStringInfo(&buf, "FOREIGN KEY %s(",
884  quote_identifier(fk_table_name));
885  i = 0;
886  foreach(l, fk_attrs)
887  {
888  Value *arg = (Value *) lfirst(l);
889 
890  if (i++ > 0)
891  appendStringInfoChar(&buf, ',');
893  }
894  appendStringInfo(&buf, ") REFERENCES %s(",
895  quote_identifier(pk_table_name));
896  i = 0;
897  foreach(l, pk_attrs)
898  {
899  Value *arg = (Value *) lfirst(l);
900 
901  if (i++ > 0)
902  appendStringInfoChar(&buf, ',');
904  }
905  appendStringInfoChar(&buf, ')');
906 
907  /* Identify class of trigger --- update, delete, or referencing-table */
908  switch (funcoid)
909  {
910  case F_RI_FKEY_CASCADE_UPD:
911  case F_RI_FKEY_RESTRICT_UPD:
912  case F_RI_FKEY_SETNULL_UPD:
913  case F_RI_FKEY_SETDEFAULT_UPD:
914  case F_RI_FKEY_NOACTION_UPD:
915  funcnum = 0;
916  break;
917 
918  case F_RI_FKEY_CASCADE_DEL:
919  case F_RI_FKEY_RESTRICT_DEL:
920  case F_RI_FKEY_SETNULL_DEL:
921  case F_RI_FKEY_SETDEFAULT_DEL:
922  case F_RI_FKEY_NOACTION_DEL:
923  funcnum = 1;
924  break;
925 
926  default:
927  funcnum = 2;
928  break;
929  }
930 
931  /* See if we have a match to this trigger */
932  foreach(l, info_list)
933  {
934  info = (OldTriggerInfo *) lfirst(l);
935  if (info->funcoids[funcnum] == InvalidOid &&
936  equal(info->args, stmt->args))
937  {
938  info->funcoids[funcnum] = funcoid;
939  break;
940  }
941  }
942 
943  if (l == NULL)
944  {
945  /* First trigger of set, so create a new list entry */
946  MemoryContext oldContext;
947 
948  ereport(NOTICE,
949  (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
950  constr_name, buf.data),
951  errdetail_internal("%s", _(funcdescr[funcnum]))));
953  info = (OldTriggerInfo *) palloc0(sizeof(OldTriggerInfo));
954  info->args = copyObject(stmt->args);
955  info->funcoids[funcnum] = funcoid;
956  info_list = lappend(info_list, info);
957  MemoryContextSwitchTo(oldContext);
958  }
959  else if (info->funcoids[0] == InvalidOid ||
960  info->funcoids[1] == InvalidOid ||
961  info->funcoids[2] == InvalidOid)
962  {
963  /* Second trigger of set */
964  ereport(NOTICE,
965  (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
966  constr_name, buf.data),
967  errdetail_internal("%s", _(funcdescr[funcnum]))));
968  }
969  else
970  {
971  /* OK, we have a set, so make the FK constraint ALTER TABLE cmd */
974  Constraint *fkcon = makeNode(Constraint);
975 
976  ereport(NOTICE,
977  (errmsg("converting trigger group into constraint \"%s\" %s",
978  constr_name, buf.data),
979  errdetail_internal("%s", _(funcdescr[funcnum]))));
980  fkcon->contype = CONSTR_FOREIGN;
981  fkcon->location = -1;
982  if (funcnum == 2)
983  {
984  /* This trigger is on the FK table */
985  atstmt->relation = stmt->relation;
986  if (stmt->constrrel)
987  fkcon->pktable = stmt->constrrel;
988  else
989  {
990  /* Work around ancient pg_dump bug that omitted constrrel */
991  fkcon->pktable = makeRangeVar(NULL, pk_table_name, -1);
992  }
993  }
994  else
995  {
996  /* This trigger is on the PK table */
997  fkcon->pktable = stmt->relation;
998  if (stmt->constrrel)
999  atstmt->relation = stmt->constrrel;
1000  else
1001  {
1002  /* Work around ancient pg_dump bug that omitted constrrel */
1003  atstmt->relation = makeRangeVar(NULL, fk_table_name, -1);
1004  }
1005  }
1006  atstmt->cmds = list_make1(atcmd);
1007  atstmt->relkind = OBJECT_TABLE;
1008  atcmd->subtype = AT_AddConstraint;
1009  atcmd->def = (Node *) fkcon;
1010  if (strcmp(constr_name, "<unnamed>") == 0)
1011  fkcon->conname = NULL;
1012  else
1013  fkcon->conname = constr_name;
1014  fkcon->fk_attrs = fk_attrs;
1015  fkcon->pk_attrs = pk_attrs;
1016  fkcon->fk_matchtype = fk_matchtype;
1017  switch (info->funcoids[0])
1018  {
1019  case F_RI_FKEY_NOACTION_UPD:
1021  break;
1022  case F_RI_FKEY_CASCADE_UPD:
1024  break;
1025  case F_RI_FKEY_RESTRICT_UPD:
1027  break;
1028  case F_RI_FKEY_SETNULL_UPD:
1030  break;
1031  case F_RI_FKEY_SETDEFAULT_UPD:
1033  break;
1034  default:
1035  /* can't get here because of earlier checks */
1036  elog(ERROR, "confused about RI update function");
1037  }
1038  switch (info->funcoids[1])
1039  {
1040  case F_RI_FKEY_NOACTION_DEL:
1042  break;
1043  case F_RI_FKEY_CASCADE_DEL:
1045  break;
1046  case F_RI_FKEY_RESTRICT_DEL:
1048  break;
1049  case F_RI_FKEY_SETNULL_DEL:
1051  break;
1052  case F_RI_FKEY_SETDEFAULT_DEL:
1054  break;
1055  default:
1056  /* can't get here because of earlier checks */
1057  elog(ERROR, "confused about RI delete function");
1058  }
1059  fkcon->deferrable = stmt->deferrable;
1060  fkcon->initdeferred = stmt->initdeferred;
1061  fkcon->skip_validation = false;
1062  fkcon->initially_valid = true;
1063 
1064  /* ... and execute it */
1065  ProcessUtility((Node *) atstmt,
1066  "(generated ALTER TABLE ADD FOREIGN KEY command)",
1068  None_Receiver, NULL);
1069 
1070  /* Remove the matched item from the list */
1071  info_list = list_delete_ptr(info_list, info);
1072  pfree(info);
1073  /* We leak the copied args ... not worth worrying about */
1074  }
1075 }
1076 
1077 /*
1078  * Guts of trigger deletion.
1079  */
1080 void
1082 {
1083  Relation tgrel;
1084  SysScanDesc tgscan;
1085  ScanKeyData skey[1];
1086  HeapTuple tup;
1087  Oid relid;
1088  Relation rel;
1089 
1091 
1092  /*
1093  * Find the trigger to delete.
1094  */
1095  ScanKeyInit(&skey[0],
1097  BTEqualStrategyNumber, F_OIDEQ,
1098  ObjectIdGetDatum(trigOid));
1099 
1100  tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
1101  NULL, 1, skey);
1102 
1103  tup = systable_getnext(tgscan);
1104  if (!HeapTupleIsValid(tup))
1105  elog(ERROR, "could not find tuple for trigger %u", trigOid);
1106 
1107  /*
1108  * Open and exclusive-lock the relation the trigger belongs to.
1109  */
1110  relid = ((Form_pg_trigger) GETSTRUCT(tup))->tgrelid;
1111 
1112  rel = heap_open(relid, AccessExclusiveLock);
1113 
1114  if (rel->rd_rel->relkind != RELKIND_RELATION &&
1115  rel->rd_rel->relkind != RELKIND_VIEW &&
1116  rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
1117  ereport(ERROR,
1118  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1119  errmsg("\"%s\" is not a table, view, or foreign table",
1120  RelationGetRelationName(rel))));
1121 
1123  ereport(ERROR,
1124  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1125  errmsg("permission denied: \"%s\" is a system catalog",
1126  RelationGetRelationName(rel))));
1127 
1128  /*
1129  * Delete the pg_trigger tuple.
1130  */
1131  simple_heap_delete(tgrel, &tup->t_self);
1132 
1133  systable_endscan(tgscan);
1134  heap_close(tgrel, RowExclusiveLock);
1135 
1136  /*
1137  * We do not bother to try to determine whether any other triggers remain,
1138  * which would be needed in order to decide whether it's safe to clear the
1139  * relation's relhastriggers. (In any case, there might be a concurrent
1140  * process adding new triggers.) Instead, just force a relcache inval to
1141  * make other backends (and this one too!) rebuild their relcache entries.
1142  * There's no great harm in leaving relhastriggers true even if there are
1143  * no triggers left.
1144  */
1146 
1147  /* Keep lock on trigger's rel until end of xact */
1148  heap_close(rel, NoLock);
1149 }
1150 
1151 /*
1152  * get_trigger_oid - Look up a trigger by name to find its OID.
1153  *
1154  * If missing_ok is false, throw an error if trigger not found. If
1155  * true, just return InvalidOid.
1156  */
1157 Oid
1158 get_trigger_oid(Oid relid, const char *trigname, bool missing_ok)
1159 {
1160  Relation tgrel;
1161  ScanKeyData skey[2];
1162  SysScanDesc tgscan;
1163  HeapTuple tup;
1164  Oid oid;
1165 
1166  /*
1167  * Find the trigger, verify permissions, set up object address
1168  */
1170 
1171  ScanKeyInit(&skey[0],
1173  BTEqualStrategyNumber, F_OIDEQ,
1174  ObjectIdGetDatum(relid));
1175  ScanKeyInit(&skey[1],
1177  BTEqualStrategyNumber, F_NAMEEQ,
1178  CStringGetDatum(trigname));
1179 
1180  tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1181  NULL, 2, skey);
1182 
1183  tup = systable_getnext(tgscan);
1184 
1185  if (!HeapTupleIsValid(tup))
1186  {
1187  if (!missing_ok)
1188  ereport(ERROR,
1189  (errcode(ERRCODE_UNDEFINED_OBJECT),
1190  errmsg("trigger \"%s\" for table \"%s\" does not exist",
1191  trigname, get_rel_name(relid))));
1192  oid = InvalidOid;
1193  }
1194  else
1195  {
1196  oid = HeapTupleGetOid(tup);
1197  }
1198 
1199  systable_endscan(tgscan);
1200  heap_close(tgrel, AccessShareLock);
1201  return oid;
1202 }
1203 
1204 /*
1205  * Perform permissions and integrity checks before acquiring a relation lock.
1206  */
1207 static void
1209  void *arg)
1210 {
1211  HeapTuple tuple;
1212  Form_pg_class form;
1213 
1214  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1215  if (!HeapTupleIsValid(tuple))
1216  return; /* concurrently dropped */
1217  form = (Form_pg_class) GETSTRUCT(tuple);
1218 
1219  /* only tables and views can have triggers */
1220  if (form->relkind != RELKIND_RELATION && form->relkind != RELKIND_VIEW &&
1221  form->relkind != RELKIND_FOREIGN_TABLE)
1222  ereport(ERROR,
1223  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1224  errmsg("\"%s\" is not a table, view, or foreign table",
1225  rv->relname)));
1226 
1227  /* you must own the table to rename one of its triggers */
1228  if (!pg_class_ownercheck(relid, GetUserId()))
1230  if (!allowSystemTableMods && IsSystemClass(relid, form))
1231  ereport(ERROR,
1232  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1233  errmsg("permission denied: \"%s\" is a system catalog",
1234  rv->relname)));
1235 
1236  ReleaseSysCache(tuple);
1237 }
1238 
1239 /*
1240  * renametrig - changes the name of a trigger on a relation
1241  *
1242  * trigger name is changed in trigger catalog.
1243  * No record of the previous name is kept.
1244  *
1245  * get proper relrelation from relation catalog (if not arg)
1246  * scan trigger catalog
1247  * for name conflict (within rel)
1248  * for original trigger (if not arg)
1249  * modify tgname in trigger tuple
1250  * update row in catalog
1251  */
1254 {
1255  Oid tgoid;
1256  Relation targetrel;
1257  Relation tgrel;
1258  HeapTuple tuple;
1259  SysScanDesc tgscan;
1260  ScanKeyData key[2];
1261  Oid relid;
1262  ObjectAddress address;
1263 
1264  /*
1265  * Look up name, check permissions, and acquire lock (which we will NOT
1266  * release until end of transaction).
1267  */
1269  false, false,
1271  NULL);
1272 
1273  /* Have lock already, so just need to build relcache entry. */
1274  targetrel = relation_open(relid, NoLock);
1275 
1276  /*
1277  * Scan pg_trigger twice for existing triggers on relation. We do this in
1278  * order to ensure a trigger does not exist with newname (The unique index
1279  * on tgrelid/tgname would complain anyway) and to ensure a trigger does
1280  * exist with oldname.
1281  *
1282  * NOTE that this is cool only because we have AccessExclusiveLock on the
1283  * relation, so the trigger set won't be changing underneath us.
1284  */
1286 
1287  /*
1288  * First pass -- look for name conflict
1289  */
1290  ScanKeyInit(&key[0],
1292  BTEqualStrategyNumber, F_OIDEQ,
1293  ObjectIdGetDatum(relid));
1294  ScanKeyInit(&key[1],
1296  BTEqualStrategyNumber, F_NAMEEQ,
1297  PointerGetDatum(stmt->newname));
1298  tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1299  NULL, 2, key);
1300  if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1301  ereport(ERROR,
1303  errmsg("trigger \"%s\" for relation \"%s\" already exists",
1304  stmt->newname, RelationGetRelationName(targetrel))));
1305  systable_endscan(tgscan);
1306 
1307  /*
1308  * Second pass -- look for trigger existing with oldname and update
1309  */
1310  ScanKeyInit(&key[0],
1312  BTEqualStrategyNumber, F_OIDEQ,
1313  ObjectIdGetDatum(relid));
1314  ScanKeyInit(&key[1],
1316  BTEqualStrategyNumber, F_NAMEEQ,
1317  PointerGetDatum(stmt->subname));
1318  tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1319  NULL, 2, key);
1320  if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1321  {
1322  tgoid = HeapTupleGetOid(tuple);
1323 
1324  /*
1325  * Update pg_trigger tuple with new tgname.
1326  */
1327  tuple = heap_copytuple(tuple); /* need a modifiable copy */
1328 
1329  namestrcpy(&((Form_pg_trigger) GETSTRUCT(tuple))->tgname,
1330  stmt->newname);
1331 
1332  simple_heap_update(tgrel, &tuple->t_self, tuple);
1333 
1334  /* keep system catalog indexes current */
1335  CatalogUpdateIndexes(tgrel, tuple);
1336 
1338  HeapTupleGetOid(tuple), 0);
1339 
1340  /*
1341  * Invalidate relation's relcache entry so that other backends (and
1342  * this one too!) are sent SI message to make them rebuild relcache
1343  * entries. (Ideally this should happen automatically...)
1344  */
1345  CacheInvalidateRelcache(targetrel);
1346  }
1347  else
1348  {
1349  ereport(ERROR,
1350  (errcode(ERRCODE_UNDEFINED_OBJECT),
1351  errmsg("trigger \"%s\" for table \"%s\" does not exist",
1352  stmt->subname, RelationGetRelationName(targetrel))));
1353  }
1354 
1355  ObjectAddressSet(address, TriggerRelationId, tgoid);
1356 
1357  systable_endscan(tgscan);
1358 
1359  heap_close(tgrel, RowExclusiveLock);
1360 
1361  /*
1362  * Close rel, but keep exclusive lock!
1363  */
1364  relation_close(targetrel, NoLock);
1365 
1366  return address;
1367 }
1368 
1369 
1370 /*
1371  * EnableDisableTrigger()
1372  *
1373  * Called by ALTER TABLE ENABLE/DISABLE [ REPLICA | ALWAYS ] TRIGGER
1374  * to change 'tgenabled' field for the specified trigger(s)
1375  *
1376  * rel: relation to process (caller must hold suitable lock on it)
1377  * tgname: trigger to process, or NULL to scan all triggers
1378  * fires_when: new value for tgenabled field. In addition to generic
1379  * enablement/disablement, this also defines when the trigger
1380  * should be fired in session replication roles.
1381  * skip_system: if true, skip "system" triggers (constraint triggers)
1382  *
1383  * Caller should have checked permissions for the table; here we also
1384  * enforce that superuser privilege is required to alter the state of
1385  * system triggers
1386  */
1387 void
1388 EnableDisableTrigger(Relation rel, const char *tgname,
1389  char fires_when, bool skip_system)
1390 {
1391  Relation tgrel;
1392  int nkeys;
1393  ScanKeyData keys[2];
1394  SysScanDesc tgscan;
1395  HeapTuple tuple;
1396  bool found;
1397  bool changed;
1398 
1399  /* Scan the relevant entries in pg_triggers */
1401 
1402  ScanKeyInit(&keys[0],
1404  BTEqualStrategyNumber, F_OIDEQ,
1406  if (tgname)
1407  {
1408  ScanKeyInit(&keys[1],
1410  BTEqualStrategyNumber, F_NAMEEQ,
1411  CStringGetDatum(tgname));
1412  nkeys = 2;
1413  }
1414  else
1415  nkeys = 1;
1416 
1417  tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1418  NULL, nkeys, keys);
1419 
1420  found = changed = false;
1421 
1422  while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1423  {
1424  Form_pg_trigger oldtrig = (Form_pg_trigger) GETSTRUCT(tuple);
1425 
1426  if (oldtrig->tgisinternal)
1427  {
1428  /* system trigger ... ok to process? */
1429  if (skip_system)
1430  continue;
1431  if (!superuser())
1432  ereport(ERROR,
1433  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1434  errmsg("permission denied: \"%s\" is a system trigger",
1435  NameStr(oldtrig->tgname))));
1436  }
1437 
1438  found = true;
1439 
1440  if (oldtrig->tgenabled != fires_when)
1441  {
1442  /* need to change this one ... make a copy to scribble on */
1443  HeapTuple newtup = heap_copytuple(tuple);
1444  Form_pg_trigger newtrig = (Form_pg_trigger) GETSTRUCT(newtup);
1445 
1446  newtrig->tgenabled = fires_when;
1447 
1448  simple_heap_update(tgrel, &newtup->t_self, newtup);
1449 
1450  /* Keep catalog indexes current */
1451  CatalogUpdateIndexes(tgrel, newtup);
1452 
1453  heap_freetuple(newtup);
1454 
1455  changed = true;
1456  }
1457 
1459  HeapTupleGetOid(tuple), 0);
1460  }
1461 
1462  systable_endscan(tgscan);
1463 
1464  heap_close(tgrel, RowExclusiveLock);
1465 
1466  if (tgname && !found)
1467  ereport(ERROR,
1468  (errcode(ERRCODE_UNDEFINED_OBJECT),
1469  errmsg("trigger \"%s\" for table \"%s\" does not exist",
1470  tgname, RelationGetRelationName(rel))));
1471 
1472  /*
1473  * If we changed anything, broadcast a SI inval message to force each
1474  * backend (including our own!) to rebuild relation's relcache entry.
1475  * Otherwise they will fail to apply the change promptly.
1476  */
1477  if (changed)
1479 }
1480 
1481 
1482 /*
1483  * Build trigger data to attach to the given relcache entry.
1484  *
1485  * Note that trigger data attached to a relcache entry must be stored in
1486  * CacheMemoryContext to ensure it survives as long as the relcache entry.
1487  * But we should be running in a less long-lived working context. To avoid
1488  * leaking cache memory if this routine fails partway through, we build a
1489  * temporary TriggerDesc in working memory and then copy the completed
1490  * structure into cache memory.
1491  */
1492 void
1494 {
1495  TriggerDesc *trigdesc;
1496  int numtrigs;
1497  int maxtrigs;
1498  Trigger *triggers;
1499  Relation tgrel;
1500  ScanKeyData skey;
1501  SysScanDesc tgscan;
1502  HeapTuple htup;
1503  MemoryContext oldContext;
1504  int i;
1505 
1506  /*
1507  * Allocate a working array to hold the triggers (the array is extended if
1508  * necessary)
1509  */
1510  maxtrigs = 16;
1511  triggers = (Trigger *) palloc(maxtrigs * sizeof(Trigger));
1512  numtrigs = 0;
1513 
1514  /*
1515  * Note: since we scan the triggers using TriggerRelidNameIndexId, we will
1516  * be reading the triggers in name order, except possibly during
1517  * emergency-recovery operations (ie, IgnoreSystemIndexes). This in turn
1518  * ensures that triggers will be fired in name order.
1519  */
1520  ScanKeyInit(&skey,
1522  BTEqualStrategyNumber, F_OIDEQ,
1523  ObjectIdGetDatum(RelationGetRelid(relation)));
1524 
1526  tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1527  NULL, 1, &skey);
1528 
1529  while (HeapTupleIsValid(htup = systable_getnext(tgscan)))
1530  {
1531  Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
1532  Trigger *build;
1533  Datum datum;
1534  bool isnull;
1535 
1536  if (numtrigs >= maxtrigs)
1537  {
1538  maxtrigs *= 2;
1539  triggers = (Trigger *) repalloc(triggers, maxtrigs * sizeof(Trigger));
1540  }
1541  build = &(triggers[numtrigs]);
1542 
1543  build->tgoid = HeapTupleGetOid(htup);
1545  NameGetDatum(&pg_trigger->tgname)));
1546  build->tgfoid = pg_trigger->tgfoid;
1547  build->tgtype = pg_trigger->tgtype;
1548  build->tgenabled = pg_trigger->tgenabled;
1549  build->tgisinternal = pg_trigger->tgisinternal;
1550  build->tgconstrrelid = pg_trigger->tgconstrrelid;
1551  build->tgconstrindid = pg_trigger->tgconstrindid;
1552  build->tgconstraint = pg_trigger->tgconstraint;
1553  build->tgdeferrable = pg_trigger->tgdeferrable;
1554  build->tginitdeferred = pg_trigger->tginitdeferred;
1555  build->tgnargs = pg_trigger->tgnargs;
1556  /* tgattr is first var-width field, so OK to access directly */
1557  build->tgnattr = pg_trigger->tgattr.dim1;
1558  if (build->tgnattr > 0)
1559  {
1560  build->tgattr = (int16 *) palloc(build->tgnattr * sizeof(int16));
1561  memcpy(build->tgattr, &(pg_trigger->tgattr.values),
1562  build->tgnattr * sizeof(int16));
1563  }
1564  else
1565  build->tgattr = NULL;
1566  if (build->tgnargs > 0)
1567  {
1568  bytea *val;
1569  char *p;
1570 
1571  val = DatumGetByteaP(fastgetattr(htup,
1573  tgrel->rd_att, &isnull));
1574  if (isnull)
1575  elog(ERROR, "tgargs is null in trigger for relation \"%s\"",
1576  RelationGetRelationName(relation));
1577  p = (char *) VARDATA(val);
1578  build->tgargs = (char **) palloc(build->tgnargs * sizeof(char *));
1579  for (i = 0; i < build->tgnargs; i++)
1580  {
1581  build->tgargs[i] = pstrdup(p);
1582  p += strlen(p) + 1;
1583  }
1584  }
1585  else
1586  build->tgargs = NULL;
1587  datum = fastgetattr(htup, Anum_pg_trigger_tgqual,
1588  tgrel->rd_att, &isnull);
1589  if (!isnull)
1590  build->tgqual = TextDatumGetCString(datum);
1591  else
1592  build->tgqual = NULL;
1593 
1594  numtrigs++;
1595  }
1596 
1597  systable_endscan(tgscan);
1598  heap_close(tgrel, AccessShareLock);
1599 
1600  /* There might not be any triggers */
1601  if (numtrigs == 0)
1602  {
1603  pfree(triggers);
1604  return;
1605  }
1606 
1607  /* Build trigdesc */
1608  trigdesc = (TriggerDesc *) palloc0(sizeof(TriggerDesc));
1609  trigdesc->triggers = triggers;
1610  trigdesc->numtriggers = numtrigs;
1611  for (i = 0; i < numtrigs; i++)
1612  SetTriggerFlags(trigdesc, &(triggers[i]));
1613 
1614  /* Copy completed trigdesc into cache storage */
1616  relation->trigdesc = CopyTriggerDesc(trigdesc);
1617  MemoryContextSwitchTo(oldContext);
1618 
1619  /* Release working memory */
1620  FreeTriggerDesc(trigdesc);
1621 }
1622 
1623 /*
1624  * Update the TriggerDesc's hint flags to include the specified trigger
1625  */
1626 static void
1628 {
1629  int16 tgtype = trigger->tgtype;
1630 
1631  trigdesc->trig_insert_before_row |=
1634  trigdesc->trig_insert_after_row |=
1637  trigdesc->trig_insert_instead_row |=
1640  trigdesc->trig_insert_before_statement |=
1643  trigdesc->trig_insert_after_statement |=
1646  trigdesc->trig_update_before_row |=
1649  trigdesc->trig_update_after_row |=
1652  trigdesc->trig_update_instead_row |=
1655  trigdesc->trig_update_before_statement |=
1658  trigdesc->trig_update_after_statement |=
1661  trigdesc->trig_delete_before_row |=
1664  trigdesc->trig_delete_after_row |=
1667  trigdesc->trig_delete_instead_row |=
1670  trigdesc->trig_delete_before_statement |=
1673  trigdesc->trig_delete_after_statement |=
1676  /* there are no row-level truncate triggers */
1677  trigdesc->trig_truncate_before_statement |=
1680  trigdesc->trig_truncate_after_statement |=
1683 }
1684 
1685 /*
1686  * Copy a TriggerDesc data structure.
1687  *
1688  * The copy is allocated in the current memory context.
1689  */
1690 TriggerDesc *
1692 {
1693  TriggerDesc *newdesc;
1694  Trigger *trigger;
1695  int i;
1696 
1697  if (trigdesc == NULL || trigdesc->numtriggers <= 0)
1698  return NULL;
1699 
1700  newdesc = (TriggerDesc *) palloc(sizeof(TriggerDesc));
1701  memcpy(newdesc, trigdesc, sizeof(TriggerDesc));
1702 
1703  trigger = (Trigger *) palloc(trigdesc->numtriggers * sizeof(Trigger));
1704  memcpy(trigger, trigdesc->triggers,
1705  trigdesc->numtriggers * sizeof(Trigger));
1706  newdesc->triggers = trigger;
1707 
1708  for (i = 0; i < trigdesc->numtriggers; i++)
1709  {
1710  trigger->tgname = pstrdup(trigger->tgname);
1711  if (trigger->tgnattr > 0)
1712  {
1713  int16 *newattr;
1714 
1715  newattr = (int16 *) palloc(trigger->tgnattr * sizeof(int16));
1716  memcpy(newattr, trigger->tgattr,
1717  trigger->tgnattr * sizeof(int16));
1718  trigger->tgattr = newattr;
1719  }
1720  if (trigger->tgnargs > 0)
1721  {
1722  char **newargs;
1723  int16 j;
1724 
1725  newargs = (char **) palloc(trigger->tgnargs * sizeof(char *));
1726  for (j = 0; j < trigger->tgnargs; j++)
1727  newargs[j] = pstrdup(trigger->tgargs[j]);
1728  trigger->tgargs = newargs;
1729  }
1730  if (trigger->tgqual)
1731  trigger->tgqual = pstrdup(trigger->tgqual);
1732  trigger++;
1733  }
1734 
1735  return newdesc;
1736 }
1737 
1738 /*
1739  * Free a TriggerDesc data structure.
1740  */
1741 void
1743 {
1744  Trigger *trigger;
1745  int i;
1746 
1747  if (trigdesc == NULL)
1748  return;
1749 
1750  trigger = trigdesc->triggers;
1751  for (i = 0; i < trigdesc->numtriggers; i++)
1752  {
1753  pfree(trigger->tgname);
1754  if (trigger->tgnattr > 0)
1755  pfree(trigger->tgattr);
1756  if (trigger->tgnargs > 0)
1757  {
1758  while (--(trigger->tgnargs) >= 0)
1759  pfree(trigger->tgargs[trigger->tgnargs]);
1760  pfree(trigger->tgargs);
1761  }
1762  if (trigger->tgqual)
1763  pfree(trigger->tgqual);
1764  trigger++;
1765  }
1766  pfree(trigdesc->triggers);
1767  pfree(trigdesc);
1768 }
1769 
1770 /*
1771  * Compare two TriggerDesc structures for logical equality.
1772  */
1773 #ifdef NOT_USED
1774 bool
1775 equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
1776 {
1777  int i,
1778  j;
1779 
1780  /*
1781  * We need not examine the hint flags, just the trigger array itself; if
1782  * we have the same triggers with the same types, the flags should match.
1783  *
1784  * As of 7.3 we assume trigger set ordering is significant in the
1785  * comparison; so we just compare corresponding slots of the two sets.
1786  *
1787  * Note: comparing the stringToNode forms of the WHEN clauses means that
1788  * parse column locations will affect the result. This is okay as long as
1789  * this function is only used for detecting exact equality, as for example
1790  * in checking for staleness of a cache entry.
1791  */
1792  if (trigdesc1 != NULL)
1793  {
1794  if (trigdesc2 == NULL)
1795  return false;
1796  if (trigdesc1->numtriggers != trigdesc2->numtriggers)
1797  return false;
1798  for (i = 0; i < trigdesc1->numtriggers; i++)
1799  {
1800  Trigger *trig1 = trigdesc1->triggers + i;
1801  Trigger *trig2 = trigdesc2->triggers + i;
1802 
1803  if (trig1->tgoid != trig2->tgoid)
1804  return false;
1805  if (strcmp(trig1->tgname, trig2->tgname) != 0)
1806  return false;
1807  if (trig1->tgfoid != trig2->tgfoid)
1808  return false;
1809  if (trig1->tgtype != trig2->tgtype)
1810  return false;
1811  if (trig1->tgenabled != trig2->tgenabled)
1812  return false;
1813  if (trig1->tgisinternal != trig2->tgisinternal)
1814  return false;
1815  if (trig1->tgconstrrelid != trig2->tgconstrrelid)
1816  return false;
1817  if (trig1->tgconstrindid != trig2->tgconstrindid)
1818  return false;
1819  if (trig1->tgconstraint != trig2->tgconstraint)
1820  return false;
1821  if (trig1->tgdeferrable != trig2->tgdeferrable)
1822  return false;
1823  if (trig1->tginitdeferred != trig2->tginitdeferred)
1824  return false;
1825  if (trig1->tgnargs != trig2->tgnargs)
1826  return false;
1827  if (trig1->tgnattr != trig2->tgnattr)
1828  return false;
1829  if (trig1->tgnattr > 0 &&
1830  memcmp(trig1->tgattr, trig2->tgattr,
1831  trig1->tgnattr * sizeof(int16)) != 0)
1832  return false;
1833  for (j = 0; j < trig1->tgnargs; j++)
1834  if (strcmp(trig1->tgargs[j], trig2->tgargs[j]) != 0)
1835  return false;
1836  if (trig1->tgqual == NULL && trig2->tgqual == NULL)
1837  /* ok */ ;
1838  else if (trig1->tgqual == NULL || trig2->tgqual == NULL)
1839  return false;
1840  else if (strcmp(trig1->tgqual, trig2->tgqual) != 0)
1841  return false;
1842  }
1843  }
1844  else if (trigdesc2 != NULL)
1845  return false;
1846  return true;
1847 }
1848 #endif /* NOT_USED */
1849 
1850 /*
1851  * Call a trigger function.
1852  *
1853  * trigdata: trigger descriptor.
1854  * tgindx: trigger's index in finfo and instr arrays.
1855  * finfo: array of cached trigger function call information.
1856  * instr: optional array of EXPLAIN ANALYZE instrumentation state.
1857  * per_tuple_context: memory context to execute the function in.
1858  *
1859  * Returns the tuple (or NULL) as returned by the function.
1860  */
1861 static HeapTuple
1863  int tgindx,
1864  FmgrInfo *finfo,
1865  Instrumentation *instr,
1866  MemoryContext per_tuple_context)
1867 {
1868  FunctionCallInfoData fcinfo;
1869  PgStat_FunctionCallUsage fcusage;
1870  Datum result;
1871  MemoryContext oldContext;
1872 
1873  finfo += tgindx;
1874 
1875  /*
1876  * We cache fmgr lookup info, to avoid making the lookup again on each
1877  * call.
1878  */
1879  if (finfo->fn_oid == InvalidOid)
1880  fmgr_info(trigdata->tg_trigger->tgfoid, finfo);
1881 
1882  Assert(finfo->fn_oid == trigdata->tg_trigger->tgfoid);
1883 
1884  /*
1885  * If doing EXPLAIN ANALYZE, start charging time to this trigger.
1886  */
1887  if (instr)
1888  InstrStartNode(instr + tgindx);
1889 
1890  /*
1891  * Do the function evaluation in the per-tuple memory context, so that
1892  * leaked memory will be reclaimed once per tuple. Note in particular that
1893  * any new tuple created by the trigger function will live till the end of
1894  * the tuple cycle.
1895  */
1896  oldContext = MemoryContextSwitchTo(per_tuple_context);
1897 
1898  /*
1899  * Call the function, passing no arguments but setting a context.
1900  */
1901  InitFunctionCallInfoData(fcinfo, finfo, 0,
1902  InvalidOid, (Node *) trigdata, NULL);
1903 
1904  pgstat_init_function_usage(&fcinfo, &fcusage);
1905 
1906  MyTriggerDepth++;
1907  PG_TRY();
1908  {
1909  result = FunctionCallInvoke(&fcinfo);
1910  }
1911  PG_CATCH();
1912  {
1913  MyTriggerDepth--;
1914  PG_RE_THROW();
1915  }
1916  PG_END_TRY();
1917  MyTriggerDepth--;
1918 
1919  pgstat_end_function_usage(&fcusage, true);
1920 
1921  MemoryContextSwitchTo(oldContext);
1922 
1923  /*
1924  * Trigger protocol allows function to return a null pointer, but NOT to
1925  * set the isnull result flag.
1926  */
1927  if (fcinfo.isnull)
1928  ereport(ERROR,
1929  (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
1930  errmsg("trigger function %u returned null value",
1931  fcinfo.flinfo->fn_oid)));
1932 
1933  /*
1934  * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
1935  * one "tuple returned" (really the number of firings).
1936  */
1937  if (instr)
1938  InstrStopNode(instr + tgindx, 1);
1939 
1940  return (HeapTuple) DatumGetPointer(result);
1941 }
1942 
1943 void
1945 {
1946  TriggerDesc *trigdesc;
1947  int i;
1948  TriggerData LocTriggerData;
1949 
1950  trigdesc = relinfo->ri_TrigDesc;
1951 
1952  if (trigdesc == NULL)
1953  return;
1954  if (!trigdesc->trig_insert_before_statement)
1955  return;
1956 
1957  LocTriggerData.type = T_TriggerData;
1958  LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
1960  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
1961  LocTriggerData.tg_trigtuple = NULL;
1962  LocTriggerData.tg_newtuple = NULL;
1963  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
1964  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
1965  for (i = 0; i < trigdesc->numtriggers; i++)
1966  {
1967  Trigger *trigger = &trigdesc->triggers[i];
1968  HeapTuple newtuple;
1969 
1970  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
1974  continue;
1975  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
1976  NULL, NULL, NULL))
1977  continue;
1978 
1979  LocTriggerData.tg_trigger = trigger;
1980  newtuple = ExecCallTriggerFunc(&LocTriggerData,
1981  i,
1982  relinfo->ri_TrigFunctions,
1983  relinfo->ri_TrigInstrument,
1984  GetPerTupleMemoryContext(estate));
1985 
1986  if (newtuple)
1987  ereport(ERROR,
1988  (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
1989  errmsg("BEFORE STATEMENT trigger cannot return a value")));
1990  }
1991 }
1992 
1993 void
1995 {
1996  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
1997 
1998  if (trigdesc && trigdesc->trig_insert_after_statement)
2000  false, NULL, NULL, NIL, NULL);
2001 }
2002 
2005  TupleTableSlot *slot)
2006 {
2007  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2008  HeapTuple slottuple = ExecMaterializeSlot(slot);
2009  HeapTuple newtuple = slottuple;
2010  HeapTuple oldtuple;
2011  TriggerData LocTriggerData;
2012  int i;
2013 
2014  LocTriggerData.type = T_TriggerData;
2015  LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
2018  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2019  LocTriggerData.tg_newtuple = NULL;
2020  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2021  for (i = 0; i < trigdesc->numtriggers; i++)
2022  {
2023  Trigger *trigger = &trigdesc->triggers[i];
2024 
2025  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2029  continue;
2030  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2031  NULL, NULL, newtuple))
2032  continue;
2033 
2034  LocTriggerData.tg_trigtuple = oldtuple = newtuple;
2035  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2036  LocTriggerData.tg_trigger = trigger;
2037  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2038  i,
2039  relinfo->ri_TrigFunctions,
2040  relinfo->ri_TrigInstrument,
2041  GetPerTupleMemoryContext(estate));
2042  if (oldtuple != newtuple && oldtuple != slottuple)
2043  heap_freetuple(oldtuple);
2044  if (newtuple == NULL)
2045  return NULL; /* "do nothing" */
2046  }
2047 
2048  if (newtuple != slottuple)
2049  {
2050  /*
2051  * Return the modified tuple using the es_trig_tuple_slot. We assume
2052  * the tuple was allocated in per-tuple memory context, and therefore
2053  * will go away by itself. The tuple table slot should not try to
2054  * clear it.
2055  */
2056  TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2057  TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2058 
2059  if (newslot->tts_tupleDescriptor != tupdesc)
2060  ExecSetSlotDescriptor(newslot, tupdesc);
2061  ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2062  slot = newslot;
2063  }
2064  return slot;
2065 }
2066 
2067 void
2069  HeapTuple trigtuple, List *recheckIndexes)
2070 {
2071  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2072 
2073  if (trigdesc && trigdesc->trig_insert_after_row)
2075  true, NULL, trigtuple, recheckIndexes, NULL);
2076 }
2077 
2080  TupleTableSlot *slot)
2081 {
2082  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2083  HeapTuple slottuple = ExecMaterializeSlot(slot);
2084  HeapTuple newtuple = slottuple;
2085  HeapTuple oldtuple;
2086  TriggerData LocTriggerData;
2087  int i;
2088 
2089  LocTriggerData.type = T_TriggerData;
2090  LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
2093  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2094  LocTriggerData.tg_newtuple = NULL;
2095  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2096  for (i = 0; i < trigdesc->numtriggers; i++)
2097  {
2098  Trigger *trigger = &trigdesc->triggers[i];
2099 
2100  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2104  continue;
2105  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2106  NULL, NULL, newtuple))
2107  continue;
2108 
2109  LocTriggerData.tg_trigtuple = oldtuple = newtuple;
2110  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2111  LocTriggerData.tg_trigger = trigger;
2112  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2113  i,
2114  relinfo->ri_TrigFunctions,
2115  relinfo->ri_TrigInstrument,
2116  GetPerTupleMemoryContext(estate));
2117  if (oldtuple != newtuple && oldtuple != slottuple)
2118  heap_freetuple(oldtuple);
2119  if (newtuple == NULL)
2120  return NULL; /* "do nothing" */
2121  }
2122 
2123  if (newtuple != slottuple)
2124  {
2125  /*
2126  * Return the modified tuple using the es_trig_tuple_slot. We assume
2127  * the tuple was allocated in per-tuple memory context, and therefore
2128  * will go away by itself. The tuple table slot should not try to
2129  * clear it.
2130  */
2131  TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2132  TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2133 
2134  if (newslot->tts_tupleDescriptor != tupdesc)
2135  ExecSetSlotDescriptor(newslot, tupdesc);
2136  ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2137  slot = newslot;
2138  }
2139  return slot;
2140 }
2141 
2142 void
2144 {
2145  TriggerDesc *trigdesc;
2146  int i;
2147  TriggerData LocTriggerData;
2148 
2149  trigdesc = relinfo->ri_TrigDesc;
2150 
2151  if (trigdesc == NULL)
2152  return;
2153  if (!trigdesc->trig_delete_before_statement)
2154  return;
2155 
2156  LocTriggerData.type = T_TriggerData;
2157  LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
2159  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2160  LocTriggerData.tg_trigtuple = NULL;
2161  LocTriggerData.tg_newtuple = NULL;
2162  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2163  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2164  for (i = 0; i < trigdesc->numtriggers; i++)
2165  {
2166  Trigger *trigger = &trigdesc->triggers[i];
2167  HeapTuple newtuple;
2168 
2169  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2173  continue;
2174  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2175  NULL, NULL, NULL))
2176  continue;
2177 
2178  LocTriggerData.tg_trigger = trigger;
2179  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2180  i,
2181  relinfo->ri_TrigFunctions,
2182  relinfo->ri_TrigInstrument,
2183  GetPerTupleMemoryContext(estate));
2184 
2185  if (newtuple)
2186  ereport(ERROR,
2187  (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2188  errmsg("BEFORE STATEMENT trigger cannot return a value")));
2189  }
2190 }
2191 
2192 void
2194 {
2195  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2196 
2197  if (trigdesc && trigdesc->trig_delete_after_statement)
2199  false, NULL, NULL, NIL, NULL);
2200 }
2201 
2202 bool
2204  ResultRelInfo *relinfo,
2205  ItemPointer tupleid,
2206  HeapTuple fdw_trigtuple)
2207 {
2208  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2209  bool result = true;
2210  TriggerData LocTriggerData;
2211  HeapTuple trigtuple;
2212  HeapTuple newtuple;
2213  TupleTableSlot *newSlot;
2214  int i;
2215 
2216  Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2217  if (fdw_trigtuple == NULL)
2218  {
2219  trigtuple = GetTupleForTrigger(estate, epqstate, relinfo, tupleid,
2220  LockTupleExclusive, &newSlot);
2221  if (trigtuple == NULL)
2222  return false;
2223  }
2224  else
2225  trigtuple = fdw_trigtuple;
2226 
2227  LocTriggerData.type = T_TriggerData;
2228  LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
2231  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2232  LocTriggerData.tg_newtuple = NULL;
2233  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2234  for (i = 0; i < trigdesc->numtriggers; i++)
2235  {
2236  Trigger *trigger = &trigdesc->triggers[i];
2237 
2238  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2242  continue;
2243  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2244  NULL, trigtuple, NULL))
2245  continue;
2246 
2247  LocTriggerData.tg_trigtuple = trigtuple;
2248  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2249  LocTriggerData.tg_trigger = trigger;
2250  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2251  i,
2252  relinfo->ri_TrigFunctions,
2253  relinfo->ri_TrigInstrument,
2254  GetPerTupleMemoryContext(estate));
2255  if (newtuple == NULL)
2256  {
2257  result = false; /* tell caller to suppress delete */
2258  break;
2259  }
2260  if (newtuple != trigtuple)
2261  heap_freetuple(newtuple);
2262  }
2263  if (trigtuple != fdw_trigtuple)
2264  heap_freetuple(trigtuple);
2265 
2266  return result;
2267 }
2268 
2269 void
2271  ItemPointer tupleid,
2272  HeapTuple fdw_trigtuple)
2273 {
2274  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2275 
2276  if (trigdesc && trigdesc->trig_delete_after_row)
2277  {
2278  HeapTuple trigtuple;
2279 
2280  Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2281  if (fdw_trigtuple == NULL)
2282  trigtuple = GetTupleForTrigger(estate,
2283  NULL,
2284  relinfo,
2285  tupleid,
2287  NULL);
2288  else
2289  trigtuple = fdw_trigtuple;
2290 
2292  true, trigtuple, NULL, NIL, NULL);
2293  if (trigtuple != fdw_trigtuple)
2294  heap_freetuple(trigtuple);
2295  }
2296 }
2297 
2298 bool
2300  HeapTuple trigtuple)
2301 {
2302  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2303  TriggerData LocTriggerData;
2304  HeapTuple rettuple;
2305  int i;
2306 
2307  LocTriggerData.type = T_TriggerData;
2308  LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
2311  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2312  LocTriggerData.tg_newtuple = NULL;
2313  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2314  for (i = 0; i < trigdesc->numtriggers; i++)
2315  {
2316  Trigger *trigger = &trigdesc->triggers[i];
2317 
2318  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2322  continue;
2323  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2324  NULL, trigtuple, NULL))
2325  continue;
2326 
2327  LocTriggerData.tg_trigtuple = trigtuple;
2328  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2329  LocTriggerData.tg_trigger = trigger;
2330  rettuple = ExecCallTriggerFunc(&LocTriggerData,
2331  i,
2332  relinfo->ri_TrigFunctions,
2333  relinfo->ri_TrigInstrument,
2334  GetPerTupleMemoryContext(estate));
2335  if (rettuple == NULL)
2336  return false; /* Delete was suppressed */
2337  if (rettuple != trigtuple)
2338  heap_freetuple(rettuple);
2339  }
2340  return true;
2341 }
2342 
2343 void
2345 {
2346  TriggerDesc *trigdesc;
2347  int i;
2348  TriggerData LocTriggerData;
2349  Bitmapset *updatedCols;
2350 
2351  trigdesc = relinfo->ri_TrigDesc;
2352 
2353  if (trigdesc == NULL)
2354  return;
2355  if (!trigdesc->trig_update_before_statement)
2356  return;
2357 
2358  updatedCols = GetUpdatedColumns(relinfo, estate);
2359 
2360  LocTriggerData.type = T_TriggerData;
2361  LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
2363  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2364  LocTriggerData.tg_trigtuple = NULL;
2365  LocTriggerData.tg_newtuple = NULL;
2366  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2367  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2368  for (i = 0; i < trigdesc->numtriggers; i++)
2369  {
2370  Trigger *trigger = &trigdesc->triggers[i];
2371  HeapTuple newtuple;
2372 
2373  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2377  continue;
2378  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2379  updatedCols, NULL, NULL))
2380  continue;
2381 
2382  LocTriggerData.tg_trigger = trigger;
2383  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2384  i,
2385  relinfo->ri_TrigFunctions,
2386  relinfo->ri_TrigInstrument,
2387  GetPerTupleMemoryContext(estate));
2388 
2389  if (newtuple)
2390  ereport(ERROR,
2391  (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2392  errmsg("BEFORE STATEMENT trigger cannot return a value")));
2393  }
2394 }
2395 
2396 void
2398 {
2399  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2400 
2401  if (trigdesc && trigdesc->trig_update_after_statement)
2403  false, NULL, NULL, NIL,
2404  GetUpdatedColumns(relinfo, estate));
2405 }
2406 
2409  ResultRelInfo *relinfo,
2410  ItemPointer tupleid,
2411  HeapTuple fdw_trigtuple,
2412  TupleTableSlot *slot)
2413 {
2414  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2415  HeapTuple slottuple = ExecMaterializeSlot(slot);
2416  HeapTuple newtuple = slottuple;
2417  TriggerData LocTriggerData;
2418  HeapTuple trigtuple;
2419  HeapTuple oldtuple;
2420  TupleTableSlot *newSlot;
2421  int i;
2422  Bitmapset *updatedCols;
2423  LockTupleMode lockmode;
2424 
2425  /* Determine lock mode to use */
2426  lockmode = ExecUpdateLockMode(estate, relinfo);
2427 
2428  Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2429  if (fdw_trigtuple == NULL)
2430  {
2431  /* get a copy of the on-disk tuple we are planning to update */
2432  trigtuple = GetTupleForTrigger(estate, epqstate, relinfo, tupleid,
2433  lockmode, &newSlot);
2434  if (trigtuple == NULL)
2435  return NULL; /* cancel the update action */
2436  }
2437  else
2438  {
2439  trigtuple = fdw_trigtuple;
2440  newSlot = NULL;
2441  }
2442 
2443  /*
2444  * In READ COMMITTED isolation level it's possible that target tuple was
2445  * changed due to concurrent update. In that case we have a raw subplan
2446  * output tuple in newSlot, and need to run it through the junk filter to
2447  * produce an insertable tuple.
2448  *
2449  * Caution: more than likely, the passed-in slot is the same as the
2450  * junkfilter's output slot, so we are clobbering the original value of
2451  * slottuple by doing the filtering. This is OK since neither we nor our
2452  * caller have any more interest in the prior contents of that slot.
2453  */
2454  if (newSlot != NULL)
2455  {
2456  slot = ExecFilterJunk(relinfo->ri_junkFilter, newSlot);
2457  slottuple = ExecMaterializeSlot(slot);
2458  newtuple = slottuple;
2459  }
2460 
2461 
2462  LocTriggerData.type = T_TriggerData;
2463  LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
2466  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2467  updatedCols = GetUpdatedColumns(relinfo, estate);
2468  for (i = 0; i < trigdesc->numtriggers; i++)
2469  {
2470  Trigger *trigger = &trigdesc->triggers[i];
2471 
2472  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2476  continue;
2477  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2478  updatedCols, trigtuple, newtuple))
2479  continue;
2480 
2481  LocTriggerData.tg_trigtuple = trigtuple;
2482  LocTriggerData.tg_newtuple = oldtuple = newtuple;
2483  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2484  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2485  LocTriggerData.tg_trigger = trigger;
2486  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2487  i,
2488  relinfo->ri_TrigFunctions,
2489  relinfo->ri_TrigInstrument,
2490  GetPerTupleMemoryContext(estate));
2491  if (oldtuple != newtuple && oldtuple != slottuple)
2492  heap_freetuple(oldtuple);
2493  if (newtuple == NULL)
2494  {
2495  if (trigtuple != fdw_trigtuple)
2496  heap_freetuple(trigtuple);
2497  return NULL; /* "do nothing" */
2498  }
2499  }
2500  if (trigtuple != fdw_trigtuple)
2501  heap_freetuple(trigtuple);
2502 
2503  if (newtuple != slottuple)
2504  {
2505  /*
2506  * Return the modified tuple using the es_trig_tuple_slot. We assume
2507  * the tuple was allocated in per-tuple memory context, and therefore
2508  * will go away by itself. The tuple table slot should not try to
2509  * clear it.
2510  */
2511  TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2512  TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2513 
2514  if (newslot->tts_tupleDescriptor != tupdesc)
2515  ExecSetSlotDescriptor(newslot, tupdesc);
2516  ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2517  slot = newslot;
2518  }
2519  return slot;
2520 }
2521 
2522 void
2524  ItemPointer tupleid,
2525  HeapTuple fdw_trigtuple,
2526  HeapTuple newtuple,
2527  List *recheckIndexes)
2528 {
2529  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2530 
2531  if (trigdesc && trigdesc->trig_update_after_row)
2532  {
2533  HeapTuple trigtuple;
2534 
2535  Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2536  if (fdw_trigtuple == NULL)
2537  trigtuple = GetTupleForTrigger(estate,
2538  NULL,
2539  relinfo,
2540  tupleid,
2542  NULL);
2543  else
2544  trigtuple = fdw_trigtuple;
2545 
2547  true, trigtuple, newtuple, recheckIndexes,
2548  GetUpdatedColumns(relinfo, estate));
2549  if (trigtuple != fdw_trigtuple)
2550  heap_freetuple(trigtuple);
2551  }
2552 }
2553 
2556  HeapTuple trigtuple, TupleTableSlot *slot)
2557 {
2558  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2559  HeapTuple slottuple = ExecMaterializeSlot(slot);
2560  HeapTuple newtuple = slottuple;
2561  TriggerData LocTriggerData;
2562  HeapTuple oldtuple;
2563  int i;
2564 
2565  LocTriggerData.type = T_TriggerData;
2566  LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
2569  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2570  for (i = 0; i < trigdesc->numtriggers; i++)
2571  {
2572  Trigger *trigger = &trigdesc->triggers[i];
2573 
2574  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2578  continue;
2579  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2580  NULL, trigtuple, newtuple))
2581  continue;
2582 
2583  LocTriggerData.tg_trigtuple = trigtuple;
2584  LocTriggerData.tg_newtuple = oldtuple = newtuple;
2585  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2586  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2587  LocTriggerData.tg_trigger = trigger;
2588  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2589  i,
2590  relinfo->ri_TrigFunctions,
2591  relinfo->ri_TrigInstrument,
2592  GetPerTupleMemoryContext(estate));
2593  if (oldtuple != newtuple && oldtuple != slottuple)
2594  heap_freetuple(oldtuple);
2595  if (newtuple == NULL)
2596  return NULL; /* "do nothing" */
2597  }
2598 
2599  if (newtuple != slottuple)
2600  {
2601  /*
2602  * Return the modified tuple using the es_trig_tuple_slot. We assume
2603  * the tuple was allocated in per-tuple memory context, and therefore
2604  * will go away by itself. The tuple table slot should not try to
2605  * clear it.
2606  */
2607  TupleTableSlot *newslot = estate->es_trig_tuple_slot;
2608  TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2609 
2610  if (newslot->tts_tupleDescriptor != tupdesc)
2611  ExecSetSlotDescriptor(newslot, tupdesc);
2612  ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
2613  slot = newslot;
2614  }
2615  return slot;
2616 }
2617 
2618 void
2620 {
2621  TriggerDesc *trigdesc;
2622  int i;
2623  TriggerData LocTriggerData;
2624 
2625  trigdesc = relinfo->ri_TrigDesc;
2626 
2627  if (trigdesc == NULL)
2628  return;
2629  if (!trigdesc->trig_truncate_before_statement)
2630  return;
2631 
2632  LocTriggerData.type = T_TriggerData;
2633  LocTriggerData.tg_event = TRIGGER_EVENT_TRUNCATE |
2635  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2636  LocTriggerData.tg_trigtuple = NULL;
2637  LocTriggerData.tg_newtuple = NULL;
2638  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
2639  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
2640  for (i = 0; i < trigdesc->numtriggers; i++)
2641  {
2642  Trigger *trigger = &trigdesc->triggers[i];
2643  HeapTuple newtuple;
2644 
2645  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2649  continue;
2650  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2651  NULL, NULL, NULL))
2652  continue;
2653 
2654  LocTriggerData.tg_trigger = trigger;
2655  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2656  i,
2657  relinfo->ri_TrigFunctions,
2658  relinfo->ri_TrigInstrument,
2659  GetPerTupleMemoryContext(estate));
2660 
2661  if (newtuple)
2662  ereport(ERROR,
2663  (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2664  errmsg("BEFORE STATEMENT trigger cannot return a value")));
2665  }
2666 }
2667 
2668 void
2670 {
2671  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2672 
2673  if (trigdesc && trigdesc->trig_truncate_after_statement)
2675  false, NULL, NULL, NIL, NULL);
2676 }
2677 
2678 
2679 static HeapTuple
2681  EPQState *epqstate,
2682  ResultRelInfo *relinfo,
2683  ItemPointer tid,
2684  LockTupleMode lockmode,
2685  TupleTableSlot **newSlot)
2686 {
2687  Relation relation = relinfo->ri_RelationDesc;
2688  HeapTupleData tuple;
2689  HeapTuple result;
2690  Buffer buffer;
2691 
2692  if (newSlot != NULL)
2693  {
2694  HTSU_Result test;
2695  HeapUpdateFailureData hufd;
2696 
2697  *newSlot = NULL;
2698 
2699  /* caller must pass an epqstate if EvalPlanQual is possible */
2700  Assert(epqstate != NULL);
2701 
2702  /*
2703  * lock tuple for update
2704  */
2705 ltrmark:;
2706  tuple.t_self = *tid;
2707  test = heap_lock_tuple(relation, &tuple,
2708  estate->es_output_cid,
2709  lockmode, LockWaitBlock,
2710  false, &buffer, &hufd);
2711  switch (test)
2712  {
2713  case HeapTupleSelfUpdated:
2714 
2715  /*
2716  * The target tuple was already updated or deleted by the
2717  * current command, or by a later command in the current
2718  * transaction. We ignore the tuple in the former case, and
2719  * throw error in the latter case, for the same reasons
2720  * enumerated in ExecUpdate and ExecDelete in
2721  * nodeModifyTable.c.
2722  */
2723  if (hufd.cmax != estate->es_output_cid)
2724  ereport(ERROR,
2725  (errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
2726  errmsg("tuple to be updated was already modified by an operation triggered by the current command"),
2727  errhint("Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
2728 
2729  /* treat it as deleted; do not process */
2730  ReleaseBuffer(buffer);
2731  return NULL;
2732 
2733  case HeapTupleMayBeUpdated:
2734  break;
2735 
2736  case HeapTupleUpdated:
2737  ReleaseBuffer(buffer);
2739  ereport(ERROR,
2740  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
2741  errmsg("could not serialize access due to concurrent update")));
2742  if (!ItemPointerEquals(&hufd.ctid, &tuple.t_self))
2743  {
2744  /* it was updated, so look at the updated version */
2745  TupleTableSlot *epqslot;
2746 
2747  epqslot = EvalPlanQual(estate,
2748  epqstate,
2749  relation,
2750  relinfo->ri_RangeTableIndex,
2751  lockmode,
2752  &hufd.ctid,
2753  hufd.xmax);
2754  if (!TupIsNull(epqslot))
2755  {
2756  *tid = hufd.ctid;
2757  *newSlot = epqslot;
2758 
2759  /*
2760  * EvalPlanQual already locked the tuple, but we
2761  * re-call heap_lock_tuple anyway as an easy way of
2762  * re-fetching the correct tuple. Speed is hardly a
2763  * criterion in this path anyhow.
2764  */
2765  goto ltrmark;
2766  }
2767  }
2768 
2769  /*
2770  * if tuple was deleted or PlanQual failed for updated tuple -
2771  * we must not process this tuple!
2772  */
2773  return NULL;
2774 
2775  case HeapTupleInvisible:
2776  elog(ERROR, "attempted to lock invisible tuple");
2777 
2778  default:
2779  ReleaseBuffer(buffer);
2780  elog(ERROR, "unrecognized heap_lock_tuple status: %u", test);
2781  return NULL; /* keep compiler quiet */
2782  }
2783  }
2784  else
2785  {
2786  Page page;
2787  ItemId lp;
2788 
2789  buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
2790 
2791  /*
2792  * Although we already know this tuple is valid, we must lock the
2793  * buffer to ensure that no one has a buffer cleanup lock; otherwise
2794  * they might move the tuple while we try to copy it. But we can
2795  * release the lock before actually doing the heap_copytuple call,
2796  * since holding pin is sufficient to prevent anyone from getting a
2797  * cleanup lock they don't already hold.
2798  */
2799  LockBuffer(buffer, BUFFER_LOCK_SHARE);
2800 
2801  page = BufferGetPage(buffer);
2802  lp = PageGetItemId(page, ItemPointerGetOffsetNumber(tid));
2803 
2804  Assert(ItemIdIsNormal(lp));
2805 
2806  tuple.t_data = (HeapTupleHeader) PageGetItem(page, lp);
2807  tuple.t_len = ItemIdGetLength(lp);
2808  tuple.t_self = *tid;
2809  tuple.t_tableOid = RelationGetRelid(relation);
2810 
2811  LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
2812  }
2813 
2814  result = heap_copytuple(&tuple);
2815  ReleaseBuffer(buffer);
2816 
2817  return result;
2818 }
2819 
2820 /*
2821  * Is trigger enabled to fire?
2822  */
2823 static bool
2825  Trigger *trigger, TriggerEvent event,
2826  Bitmapset *modifiedCols,
2827  HeapTuple oldtup, HeapTuple newtup)
2828 {
2829  /* Check replication-role-dependent enable state */
2831  {
2832  if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
2833  trigger->tgenabled == TRIGGER_DISABLED)
2834  return false;
2835  }
2836  else /* ORIGIN or LOCAL role */
2837  {
2838  if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
2839  trigger->tgenabled == TRIGGER_DISABLED)
2840  return false;
2841  }
2842 
2843  /*
2844  * Check for column-specific trigger (only possible for UPDATE, and in
2845  * fact we *must* ignore tgattr for other event types)
2846  */
2847  if (trigger->tgnattr > 0 && TRIGGER_FIRED_BY_UPDATE(event))
2848  {
2849  int i;
2850  bool modified;
2851 
2852  modified = false;
2853  for (i = 0; i < trigger->tgnattr; i++)
2854  {
2856  modifiedCols))
2857  {
2858  modified = true;
2859  break;
2860  }
2861  }
2862  if (!modified)
2863  return false;
2864  }
2865 
2866  /* Check for WHEN clause */
2867  if (trigger->tgqual)
2868  {
2869  TupleDesc tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
2870  List **predicate;
2871  ExprContext *econtext;
2872  TupleTableSlot *oldslot = NULL;
2873  TupleTableSlot *newslot = NULL;
2874  MemoryContext oldContext;
2875  int i;
2876 
2877  Assert(estate != NULL);
2878 
2879  /*
2880  * trigger is an element of relinfo->ri_TrigDesc->triggers[]; find the
2881  * matching element of relinfo->ri_TrigWhenExprs[]
2882  */
2883  i = trigger - relinfo->ri_TrigDesc->triggers;
2884  predicate = &relinfo->ri_TrigWhenExprs[i];
2885 
2886  /*
2887  * If first time through for this WHEN expression, build expression
2888  * nodetrees for it. Keep them in the per-query memory context so
2889  * they'll survive throughout the query.
2890  */
2891  if (*predicate == NIL)
2892  {
2893  Node *tgqual;
2894 
2895  oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
2896  tgqual = stringToNode(trigger->tgqual);
2897  /* Change references to OLD and NEW to INNER_VAR and OUTER_VAR */
2900  /* ExecQual wants implicit-AND form */
2901  tgqual = (Node *) make_ands_implicit((Expr *) tgqual);
2902  *predicate = (List *) ExecPrepareExpr((Expr *) tgqual, estate);
2903  MemoryContextSwitchTo(oldContext);
2904  }
2905 
2906  /*
2907  * We will use the EState's per-tuple context for evaluating WHEN
2908  * expressions (creating it if it's not already there).
2909  */
2910  econtext = GetPerTupleExprContext(estate);
2911 
2912  /*
2913  * Put OLD and NEW tuples into tupleslots for expression evaluation.
2914  * These slots can be shared across the whole estate, but be careful
2915  * that they have the current resultrel's tupdesc.
2916  */
2917  if (HeapTupleIsValid(oldtup))
2918  {
2919  if (estate->es_trig_oldtup_slot == NULL)
2920  {
2921  oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
2922  estate->es_trig_oldtup_slot = ExecInitExtraTupleSlot(estate);
2923  MemoryContextSwitchTo(oldContext);
2924  }
2925  oldslot = estate->es_trig_oldtup_slot;
2926  if (oldslot->tts_tupleDescriptor != tupdesc)
2927  ExecSetSlotDescriptor(oldslot, tupdesc);
2928  ExecStoreTuple(oldtup, oldslot, InvalidBuffer, false);
2929  }
2930  if (HeapTupleIsValid(newtup))
2931  {
2932  if (estate->es_trig_newtup_slot == NULL)
2933  {
2934  oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
2935  estate->es_trig_newtup_slot = ExecInitExtraTupleSlot(estate);
2936  MemoryContextSwitchTo(oldContext);
2937  }
2938  newslot = estate->es_trig_newtup_slot;
2939  if (newslot->tts_tupleDescriptor != tupdesc)
2940  ExecSetSlotDescriptor(newslot, tupdesc);
2941  ExecStoreTuple(newtup, newslot, InvalidBuffer, false);
2942  }
2943 
2944  /*
2945  * Finally evaluate the expression, making the old and/or new tuples
2946  * available as INNER_VAR/OUTER_VAR respectively.
2947  */
2948  econtext->ecxt_innertuple = oldslot;
2949  econtext->ecxt_outertuple = newslot;
2950  if (!ExecQual(*predicate, econtext, false))
2951  return false;
2952  }
2953 
2954  return true;
2955 }
2956 
2957 
2958 /* ----------
2959  * After-trigger stuff
2960  *
2961  * The AfterTriggersData struct holds data about pending AFTER trigger events
2962  * during the current transaction tree. (BEFORE triggers are fired
2963  * immediately so we don't need any persistent state about them.) The struct
2964  * and most of its subsidiary data are kept in TopTransactionContext; however
2965  * the individual event records are kept in a separate sub-context. This is
2966  * done mainly so that it's easy to tell from a memory context dump how much
2967  * space is being eaten by trigger events.
2968  *
2969  * Because the list of pending events can grow large, we go to some
2970  * considerable effort to minimize per-event memory consumption. The event
2971  * records are grouped into chunks and common data for similar events in the
2972  * same chunk is only stored once.
2973  *
2974  * XXX We need to be able to save the per-event data in a file if it grows too
2975  * large.
2976  * ----------
2977  */
2978 
2979 /* Per-trigger SET CONSTRAINT status */
2981 {
2985 
2987 
2988 /*
2989  * SET CONSTRAINT intra-transaction status.
2990  *
2991  * We make this a single palloc'd object so it can be copied and freed easily.
2992  *
2993  * all_isset and all_isdeferred are used to keep track
2994  * of SET CONSTRAINTS ALL {DEFERRED, IMMEDIATE}.
2995  *
2996  * trigstates[] stores per-trigger tgisdeferred settings.
2997  */
2999 {
3002  int numstates; /* number of trigstates[] entries in use */
3003  int numalloc; /* allocated size of trigstates[] */
3004  SetConstraintTriggerData trigstates[FLEXIBLE_ARRAY_MEMBER];
3006 
3008 
3009 
3010 /*
3011  * Per-trigger-event data
3012  *
3013  * The actual per-event data, AfterTriggerEventData, includes DONE/IN_PROGRESS
3014  * status bits and up to two tuple CTIDs. Each event record also has an
3015  * associated AfterTriggerSharedData that is shared across all instances of
3016  * similar events within a "chunk".
3017  *
3018  * For row-level triggers, we arrange not to waste storage on unneeded ctid
3019  * fields. Updates of regular tables use two; inserts and deletes of regular
3020  * tables use one; foreign tables always use zero and save the tuple(s) to a
3021  * tuplestore. AFTER_TRIGGER_FDW_FETCH directs AfterTriggerExecute() to
3022  * retrieve a fresh tuple or pair of tuples from that tuplestore, while
3023  * AFTER_TRIGGER_FDW_REUSE directs it to use the most-recently-retrieved
3024  * tuple(s). This permits storing tuples once regardless of the number of
3025  * row-level triggers on a foreign table.
3026  *
3027  * Statement-level triggers always bear AFTER_TRIGGER_1CTID, though they
3028  * require no ctid field. We lack the flag bit space to neatly represent that
3029  * distinct case, and it seems unlikely to be worth much trouble.
3030  *
3031  * Note: ats_firing_id is initially zero and is set to something else when
3032  * AFTER_TRIGGER_IN_PROGRESS is set. It indicates which trigger firing
3033  * cycle the trigger will be fired in (or was fired in, if DONE is set).
3034  * Although this is mutable state, we can keep it in AfterTriggerSharedData
3035  * because all instances of the same type of event in a given event list will
3036  * be fired at the same time, if they were queued between the same firing
3037  * cycles. So we need only ensure that ats_firing_id is zero when attaching
3038  * a new event to an existing AfterTriggerSharedData record.
3039  */
3041 
3042 #define AFTER_TRIGGER_OFFSET 0x0FFFFFFF /* must be low-order
3043  * bits */
3044 #define AFTER_TRIGGER_DONE 0x10000000
3045 #define AFTER_TRIGGER_IN_PROGRESS 0x20000000
3046 /* bits describing the size and tuple sources of this event */
3047 #define AFTER_TRIGGER_FDW_REUSE 0x00000000
3048 #define AFTER_TRIGGER_FDW_FETCH 0x80000000
3049 #define AFTER_TRIGGER_1CTID 0x40000000
3050 #define AFTER_TRIGGER_2CTID 0xC0000000
3051 #define AFTER_TRIGGER_TUP_BITS 0xC0000000
3052 
3054 
3056 {
3057  TriggerEvent ats_event; /* event type indicator, see trigger.h */
3058  Oid ats_tgoid; /* the trigger's ID */
3059  Oid ats_relid; /* the relation it's on */
3060  CommandId ats_firing_id; /* ID for firing cycle */
3062 
3064 
3066 {
3067  TriggerFlags ate_flags; /* status bits and offset to shared data */
3068  ItemPointerData ate_ctid1; /* inserted, deleted, or old updated tuple */
3069  ItemPointerData ate_ctid2; /* new updated tuple */
3071 
3072 /* AfterTriggerEventData, minus ate_ctid2 */
3074 {
3075  TriggerFlags ate_flags; /* status bits and offset to shared data */
3076  ItemPointerData ate_ctid1; /* inserted, deleted, or old updated tuple */
3078 
3079 /* AfterTriggerEventData, minus ate_ctid1 and ate_ctid2 */
3081 {
3082  TriggerFlags ate_flags; /* status bits and offset to shared data */
3084 
3085 #define SizeofTriggerEvent(evt) \
3086  (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_2CTID ? \
3087  sizeof(AfterTriggerEventData) : \
3088  ((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_1CTID ? \
3089  sizeof(AfterTriggerEventDataOneCtid) : \
3090  sizeof(AfterTriggerEventDataZeroCtids))
3091 
3092 #define GetTriggerSharedData(evt) \
3093  ((AfterTriggerShared) ((char *) (evt) + ((evt)->ate_flags & AFTER_TRIGGER_OFFSET)))
3094 
3095 /*
3096  * To avoid palloc overhead, we keep trigger events in arrays in successively-
3097  * larger chunks (a slightly more sophisticated version of an expansible
3098  * array). The space between CHUNK_DATA_START and freeptr is occupied by
3099  * AfterTriggerEventData records; the space between endfree and endptr is
3100  * occupied by AfterTriggerSharedData records.
3101  */
3103 {
3104  struct AfterTriggerEventChunk *next; /* list link */
3105  char *freeptr; /* start of free space in chunk */
3106  char *endfree; /* end of free space in chunk */
3107  char *endptr; /* end of chunk */
3108  /* event data follows here */
3110 
3111 #define CHUNK_DATA_START(cptr) ((char *) (cptr) + MAXALIGN(sizeof(AfterTriggerEventChunk)))
3112 
3113 /* A list of events */
3115 {
3118  char *tailfree; /* freeptr of tail chunk */
3120 
3121 /* Macros to help in iterating over a list of events */
3122 #define for_each_chunk(cptr, evtlist) \
3123  for (cptr = (evtlist).head; cptr != NULL; cptr = cptr->next)
3124 #define for_each_event(eptr, cptr) \
3125  for (eptr = (AfterTriggerEvent) CHUNK_DATA_START(cptr); \
3126  (char *) eptr < (cptr)->freeptr; \
3127  eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
3128 /* Use this if no special per-chunk processing is needed */
3129 #define for_each_event_chunk(eptr, cptr, evtlist) \
3130  for_each_chunk(cptr, evtlist) for_each_event(eptr, cptr)
3131 
3132 
3133 /*
3134  * All per-transaction data for the AFTER TRIGGERS module.
3135  *
3136  * AfterTriggersData has the following fields:
3137  *
3138  * firing_counter is incremented for each call of afterTriggerInvokeEvents.
3139  * We mark firable events with the current firing cycle's ID so that we can
3140  * tell which ones to work on. This ensures sane behavior if a trigger
3141  * function chooses to do SET CONSTRAINTS: the inner SET CONSTRAINTS will
3142  * only fire those events that weren't already scheduled for firing.
3143  *
3144  * state keeps track of the transaction-local effects of SET CONSTRAINTS.
3145  * This is saved and restored across failed subtransactions.
3146  *
3147  * events is the current list of deferred events. This is global across
3148  * all subtransactions of the current transaction. In a subtransaction
3149  * abort, we know that the events added by the subtransaction are at the
3150  * end of the list, so it is relatively easy to discard them. The event
3151  * list chunks themselves are stored in event_cxt.
3152  *
3153  * query_depth is the current depth of nested AfterTriggerBeginQuery calls
3154  * (-1 when the stack is empty).
3155  *
3156  * query_stack[query_depth] is a list of AFTER trigger events queued by the
3157  * current query (and the query_stack entries below it are lists of trigger
3158  * events queued by calling queries). None of these are valid until the
3159  * matching AfterTriggerEndQuery call occurs. At that point we fire
3160  * immediate-mode triggers, and append any deferred events to the main events
3161  * list.
3162  *
3163  * fdw_tuplestores[query_depth] is a tuplestore containing the foreign tuples
3164  * needed for the current query.
3165  *
3166  * maxquerydepth is just the allocated length of query_stack and
3167  * fdw_tuplestores.
3168  *
3169  * state_stack is a stack of pointers to saved copies of the SET CONSTRAINTS
3170  * state data; each subtransaction level that modifies that state first
3171  * saves a copy, which we use to restore the state if we abort.
3172  *
3173  * events_stack is a stack of copies of the events head/tail pointers,
3174  * which we use to restore those values during subtransaction abort.
3175  *
3176  * depth_stack is a stack of copies of subtransaction-start-time query_depth,
3177  * which we similarly use to clean up at subtransaction abort.
3178  *
3179  * firing_stack is a stack of copies of subtransaction-start-time
3180  * firing_counter. We use this to recognize which deferred triggers were
3181  * fired (or marked for firing) within an aborted subtransaction.
3182  *
3183  * We use GetCurrentTransactionNestLevel() to determine the correct array
3184  * index in these stacks. maxtransdepth is the number of allocated entries in
3185  * each stack. (By not keeping our own stack pointer, we can avoid trouble
3186  * in cases where errors during subxact abort cause multiple invocations
3187  * of AfterTriggerEndSubXact() at the same nesting depth.)
3188  */
3189 typedef struct AfterTriggersData
3190 {
3191  CommandId firing_counter; /* next firing ID to assign */
3192  SetConstraintState state; /* the active S C state */
3193  AfterTriggerEventList events; /* deferred-event list */
3194  int query_depth; /* current query list index */
3195  AfterTriggerEventList *query_stack; /* events pending from each query */
3196  Tuplestorestate **fdw_tuplestores; /* foreign tuples from each query */
3197  int maxquerydepth; /* allocated len of above array */
3198  MemoryContext event_cxt; /* memory context for events, if any */
3199 
3200  /* these fields are just for resetting at subtrans abort: */
3201 
3202  SetConstraintState *state_stack; /* stacked S C states */
3203  AfterTriggerEventList *events_stack; /* stacked list pointers */
3204  int *depth_stack; /* stacked query_depths */
3205  CommandId *firing_stack; /* stacked firing_counters */
3206  int maxtransdepth; /* allocated len of above arrays */
3208 
3210 
3211 static void AfterTriggerExecute(AfterTriggerEvent event,
3212  Relation rel, TriggerDesc *trigdesc,
3213  FmgrInfo *finfo,
3214  Instrumentation *instr,
3215  MemoryContext per_tuple_context,
3216  TupleTableSlot *trig_tuple_slot1,
3217  TupleTableSlot *trig_tuple_slot2);
3218 static SetConstraintState SetConstraintStateCreate(int numalloc);
3219 static SetConstraintState SetConstraintStateCopy(SetConstraintState state);
3220 static SetConstraintState SetConstraintStateAddItem(SetConstraintState state,
3221  Oid tgoid, bool tgisdeferred);
3222 
3223 
3224 /*
3225  * Gets the current query fdw tuplestore and initializes it if necessary
3226  */
3227 static Tuplestorestate *
3229 {
3230  Tuplestorestate *ret;
3231 
3232  ret = afterTriggers.fdw_tuplestores[afterTriggers.query_depth];
3233  if (ret == NULL)
3234  {
3235  MemoryContext oldcxt;
3236  ResourceOwner saveResourceOwner;
3237 
3238  /*
3239  * Make the tuplestore valid until end of transaction. This is the
3240  * allocation lifespan of the associated events list, but we really
3241  * only need it until AfterTriggerEndQuery().
3242  */
3244  saveResourceOwner = CurrentResourceOwner;
3245  PG_TRY();
3246  {
3248  ret = tuplestore_begin_heap(false, false, work_mem);
3249  }
3250  PG_CATCH();
3251  {
3252  CurrentResourceOwner = saveResourceOwner;
3253  PG_RE_THROW();
3254  }
3255  PG_END_TRY();
3256  CurrentResourceOwner = saveResourceOwner;
3257  MemoryContextSwitchTo(oldcxt);
3258 
3259  afterTriggers.fdw_tuplestores[afterTriggers.query_depth] = ret;
3260  }
3261 
3262  return ret;
3263 }
3264 
3265 /* ----------
3266  * afterTriggerCheckState()
3267  *
3268  * Returns true if the trigger event is actually in state DEFERRED.
3269  * ----------
3270  */
3271 static bool
3272 afterTriggerCheckState(AfterTriggerShared evtshared)
3273 {
3274  Oid tgoid = evtshared->ats_tgoid;
3275  SetConstraintState state = afterTriggers.state;
3276  int i;
3277 
3278  /*
3279  * For not-deferrable triggers (i.e. normal AFTER ROW triggers and
3280  * constraints declared NOT DEFERRABLE), the state is always false.
3281  */
3282  if ((evtshared->ats_event & AFTER_TRIGGER_DEFERRABLE) == 0)
3283  return false;
3284 
3285  /*
3286  * If constraint state exists, SET CONSTRAINTS might have been executed
3287  * either for this trigger or for all triggers.
3288  */
3289  if (state != NULL)
3290  {
3291  /* Check for SET CONSTRAINTS for this specific trigger. */
3292  for (i = 0; i < state->numstates; i++)
3293  {
3294  if (state->trigstates[i].sct_tgoid == tgoid)
3295  return state->trigstates[i].sct_tgisdeferred;
3296  }
3297 
3298  /* Check for SET CONSTRAINTS ALL. */
3299  if (state->all_isset)
3300  return state->all_isdeferred;
3301  }
3302 
3303  /*
3304  * Otherwise return the default state for the trigger.
3305  */
3306  return ((evtshared->ats_event & AFTER_TRIGGER_INITDEFERRED) != 0);
3307 }
3308 
3309 
3310 /* ----------
3311  * afterTriggerAddEvent()
3312  *
3313  * Add a new trigger event to the specified queue.
3314  * The passed-in event data is copied.
3315  * ----------
3316  */
3317 static void
3319  AfterTriggerEvent event, AfterTriggerShared evtshared)
3320 {
3321  Size eventsize = SizeofTriggerEvent(event);
3322  Size needed = eventsize + sizeof(AfterTriggerSharedData);
3323  AfterTriggerEventChunk *chunk;
3324  AfterTriggerShared newshared;
3325  AfterTriggerEvent newevent;
3326 
3327  /*
3328  * If empty list or not enough room in the tail chunk, make a new chunk.
3329  * We assume here that a new shared record will always be needed.
3330  */
3331  chunk = events->tail;
3332  if (chunk == NULL ||
3333  chunk->endfree - chunk->freeptr < needed)
3334  {
3335  Size chunksize;
3336 
3337  /* Create event context if we didn't already */
3338  if (afterTriggers.event_cxt == NULL)
3339  afterTriggers.event_cxt =
3341  "AfterTriggerEvents",
3345 
3346  /*
3347  * Chunk size starts at 1KB and is allowed to increase up to 1MB.
3348  * These numbers are fairly arbitrary, though there is a hard limit at
3349  * AFTER_TRIGGER_OFFSET; else we couldn't link event records to their
3350  * shared records using the available space in ate_flags. Another
3351  * constraint is that if the chunk size gets too huge, the search loop
3352  * below would get slow given a (not too common) usage pattern with
3353  * many distinct event types in a chunk. Therefore, we double the
3354  * preceding chunk size only if there weren't too many shared records
3355  * in the preceding chunk; otherwise we halve it. This gives us some
3356  * ability to adapt to the actual usage pattern of the current query
3357  * while still having large chunk sizes in typical usage. All chunk
3358  * sizes used should be MAXALIGN multiples, to ensure that the shared
3359  * records will be aligned safely.
3360  */
3361 #define MIN_CHUNK_SIZE 1024
3362 #define MAX_CHUNK_SIZE (1024*1024)
3363 
3364 #if MAX_CHUNK_SIZE > (AFTER_TRIGGER_OFFSET+1)
3365 #error MAX_CHUNK_SIZE must not exceed AFTER_TRIGGER_OFFSET
3366 #endif
3367 
3368  if (chunk == NULL)
3369  chunksize = MIN_CHUNK_SIZE;
3370  else
3371  {
3372  /* preceding chunk size... */
3373  chunksize = chunk->endptr - (char *) chunk;
3374  /* check number of shared records in preceding chunk */
3375  if ((chunk->endptr - chunk->endfree) <=
3376  (100 * sizeof(AfterTriggerSharedData)))
3377  chunksize *= 2; /* okay, double it */
3378  else
3379  chunksize /= 2; /* too many shared records */
3380  chunksize = Min(chunksize, MAX_CHUNK_SIZE);
3381  }
3382  chunk = MemoryContextAlloc(afterTriggers.event_cxt, chunksize);
3383  chunk->next = NULL;
3384  chunk->freeptr = CHUNK_DATA_START(chunk);
3385  chunk->endptr = chunk->endfree = (char *) chunk + chunksize;
3386  Assert(chunk->endfree - chunk->freeptr >= needed);
3387 
3388  if (events->head == NULL)
3389  events->head = chunk;
3390  else
3391  events->tail->next = chunk;
3392  events->tail = chunk;
3393  /* events->tailfree is now out of sync, but we'll fix it below */
3394  }
3395 
3396  /*
3397  * Try to locate a matching shared-data record already in the chunk. If
3398  * none, make a new one.
3399  */
3400  for (newshared = ((AfterTriggerShared) chunk->endptr) - 1;
3401  (char *) newshared >= chunk->endfree;
3402  newshared--)
3403  {
3404  if (newshared->ats_tgoid == evtshared->ats_tgoid &&
3405  newshared->ats_relid == evtshared->ats_relid &&
3406  newshared->ats_event == evtshared->ats_event &&
3407  newshared->ats_firing_id == 0)
3408  break;
3409  }
3410  if ((char *) newshared < chunk->endfree)
3411  {
3412  *newshared = *evtshared;
3413  newshared->ats_firing_id = 0; /* just to be sure */
3414  chunk->endfree = (char *) newshared;
3415  }
3416 
3417  /* Insert the data */
3418  newevent = (AfterTriggerEvent) chunk->freeptr;
3419  memcpy(newevent, event, eventsize);
3420  /* ... and link the new event to its shared record */
3421  newevent->ate_flags &= ~AFTER_TRIGGER_OFFSET;
3422  newevent->ate_flags |= (char *) newshared - (char *) newevent;
3423 
3424  chunk->freeptr += eventsize;
3425  events->tailfree = chunk->freeptr;
3426 }
3427 
3428 /* ----------
3429  * afterTriggerFreeEventList()
3430  *
3431  * Free all the event storage in the given list.
3432  * ----------
3433  */
3434 static void
3436 {
3437  AfterTriggerEventChunk *chunk;
3438  AfterTriggerEventChunk *next_chunk;
3439 
3440  for (chunk = events->head; chunk != NULL; chunk = next_chunk)
3441  {
3442  next_chunk = chunk->next;
3443  pfree(chunk);
3444  }
3445  events->head = NULL;
3446  events->tail = NULL;
3447  events->tailfree = NULL;
3448 }
3449 
3450 /* ----------
3451  * afterTriggerRestoreEventList()
3452  *
3453  * Restore an event list to its prior length, removing all the events
3454  * added since it had the value old_events.
3455  * ----------
3456  */
3457 static void
3459  const AfterTriggerEventList *old_events)
3460 {
3461  AfterTriggerEventChunk *chunk;
3462  AfterTriggerEventChunk *next_chunk;
3463 
3464  if (old_events->tail == NULL)
3465  {
3466  /* restoring to a completely empty state, so free everything */
3467  afterTriggerFreeEventList(events);
3468  }
3469  else
3470  {
3471  *events = *old_events;
3472  /* free any chunks after the last one we want to keep */
3473  for (chunk = events->tail->next; chunk != NULL; chunk = next_chunk)
3474  {
3475  next_chunk = chunk->next;
3476  pfree(chunk);
3477  }
3478  /* and clean up the tail chunk to be the right length */
3479  events->tail->next = NULL;
3480  events->tail->freeptr = events->tailfree;
3481 
3482  /*
3483  * We don't make any effort to remove now-unused shared data records.
3484  * They might still be useful, anyway.
3485  */
3486  }
3487 }
3488 
3489 
3490 /* ----------
3491  * AfterTriggerExecute()
3492  *
3493  * Fetch the required tuples back from the heap and fire one
3494  * single trigger function.
3495  *
3496  * Frequently, this will be fired many times in a row for triggers of
3497  * a single relation. Therefore, we cache the open relation and provide
3498  * fmgr lookup cache space at the caller level. (For triggers fired at
3499  * the end of a query, we can even piggyback on the executor's state.)
3500  *
3501  * event: event currently being fired.
3502  * rel: open relation for event.
3503  * trigdesc: working copy of rel's trigger info.
3504  * finfo: array of fmgr lookup cache entries (one per trigger in trigdesc).
3505  * instr: array of EXPLAIN ANALYZE instrumentation nodes (one per trigger),
3506  * or NULL if no instrumentation is wanted.
3507  * per_tuple_context: memory context to call trigger function in.
3508  * trig_tuple_slot1: scratch slot for tg_trigtuple (foreign tables only)
3509  * trig_tuple_slot2: scratch slot for tg_newtuple (foreign tables only)
3510  * ----------
3511  */
3512 static void
3513 AfterTriggerExecute(AfterTriggerEvent event,
3514  Relation rel, TriggerDesc *trigdesc,
3515  FmgrInfo *finfo, Instrumentation *instr,
3516  MemoryContext per_tuple_context,
3517  TupleTableSlot *trig_tuple_slot1,
3518  TupleTableSlot *trig_tuple_slot2)
3519 {
3520  AfterTriggerShared evtshared = GetTriggerSharedData(event);
3521  Oid tgoid = evtshared->ats_tgoid;
3522  TriggerData LocTriggerData;
3523  HeapTupleData tuple1;
3524  HeapTupleData tuple2;
3525  HeapTuple rettuple;
3526  Buffer buffer1 = InvalidBuffer;
3527  Buffer buffer2 = InvalidBuffer;
3528  int tgindx;
3529 
3530  /*
3531  * Locate trigger in trigdesc.
3532  */
3533  LocTriggerData.tg_trigger = NULL;
3534  for (tgindx = 0; tgindx < trigdesc->numtriggers; tgindx++)
3535  {
3536  if (trigdesc->triggers[tgindx].tgoid == tgoid)
3537  {
3538  LocTriggerData.tg_trigger = &(trigdesc->triggers[tgindx]);
3539  break;
3540  }
3541  }
3542  if (LocTriggerData.tg_trigger == NULL)
3543  elog(ERROR, "could not find trigger %u", tgoid);
3544 
3545  /*
3546  * If doing EXPLAIN ANALYZE, start charging time to this trigger. We want
3547  * to include time spent re-fetching tuples in the trigger cost.
3548  */
3549  if (instr)
3550  InstrStartNode(instr + tgindx);
3551 
3552  /*
3553  * Fetch the required tuple(s).
3554  */
3555  switch (event->ate_flags & AFTER_TRIGGER_TUP_BITS)
3556  {
3558  {
3559  Tuplestorestate *fdw_tuplestore = GetCurrentFDWTuplestore();
3560 
3561  if (!tuplestore_gettupleslot(fdw_tuplestore, true, false,
3562  trig_tuple_slot1))
3563  elog(ERROR, "failed to fetch tuple1 for AFTER trigger");
3564 
3565  if ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) ==
3567  !tuplestore_gettupleslot(fdw_tuplestore, true, false,
3568  trig_tuple_slot2))
3569  elog(ERROR, "failed to fetch tuple2 for AFTER trigger");
3570  }
3571  /* fall through */
3573 
3574  /*
3575  * Using ExecMaterializeSlot() rather than ExecFetchSlotTuple()
3576  * ensures that tg_trigtuple does not reference tuplestore memory.
3577  * (It is formally possible for the trigger function to queue
3578  * trigger events that add to the same tuplestore, which can push
3579  * other tuples out of memory.) The distinction is academic,
3580  * because we start with a minimal tuple that ExecFetchSlotTuple()
3581  * must materialize anyway.
3582  */
3583  LocTriggerData.tg_trigtuple =
3584  ExecMaterializeSlot(trig_tuple_slot1);
3585  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
3586 
3587  LocTriggerData.tg_newtuple =
3588  ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) ==
3590  ExecMaterializeSlot(trig_tuple_slot2) : NULL;
3591  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
3592 
3593  break;
3594 
3595  default:
3596  if (ItemPointerIsValid(&(event->ate_ctid1)))
3597  {
3598  ItemPointerCopy(&(event->ate_ctid1), &(tuple1.t_self));
3599  if (!heap_fetch(rel, SnapshotAny, &tuple1, &buffer1, false, NULL))
3600  elog(ERROR, "failed to fetch tuple1 for AFTER trigger");
3601  LocTriggerData.tg_trigtuple = &tuple1;
3602  LocTriggerData.tg_trigtuplebuf = buffer1;
3603  }
3604  else
3605  {
3606  LocTriggerData.tg_trigtuple = NULL;
3607  LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
3608  }
3609 
3610  /* don't touch ctid2 if not there */
3611  if ((event->ate_flags & AFTER_TRIGGER_TUP_BITS) ==
3613  ItemPointerIsValid(&(event->ate_ctid2)))
3614  {
3615  ItemPointerCopy(&(event->ate_ctid2), &(tuple2.t_self));
3616  if (!heap_fetch(rel, SnapshotAny, &tuple2, &buffer2, false, NULL))
3617  elog(ERROR, "failed to fetch tuple2 for AFTER trigger");
3618  LocTriggerData.tg_newtuple = &tuple2;
3619  LocTriggerData.tg_newtuplebuf = buffer2;
3620  }
3621  else
3622  {
3623  LocTriggerData.tg_newtuple = NULL;
3624  LocTriggerData.tg_newtuplebuf = InvalidBuffer;
3625  }
3626  }
3627 
3628  /*
3629  * Setup the remaining trigger information
3630  */
3631  LocTriggerData.type = T_TriggerData;
3632  LocTriggerData.tg_event =
3634  LocTriggerData.tg_relation = rel;
3635 
3636  MemoryContextReset(per_tuple_context);
3637 
3638  /*
3639  * Call the trigger and throw away any possibly returned updated tuple.
3640  * (Don't let ExecCallTriggerFunc measure EXPLAIN time.)
3641  */
3642  rettuple = ExecCallTriggerFunc(&LocTriggerData,
3643  tgindx,
3644  finfo,
3645  NULL,
3646  per_tuple_context);
3647  if (rettuple != NULL &&
3648  rettuple != LocTriggerData.tg_trigtuple &&
3649  rettuple != LocTriggerData.tg_newtuple)
3650  heap_freetuple(rettuple);
3651 
3652  /*
3653  * Release buffers
3654  */
3655  if (buffer1 != InvalidBuffer)
3656  ReleaseBuffer(buffer1);
3657  if (buffer2 != InvalidBuffer)
3658  ReleaseBuffer(buffer2);
3659 
3660  /*
3661  * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
3662  * one "tuple returned" (really the number of firings).
3663  */
3664  if (instr)
3665  InstrStopNode(instr + tgindx, 1);
3666 }
3667 
3668 
3669 /*
3670  * afterTriggerMarkEvents()
3671  *
3672  * Scan the given event list for not yet invoked events. Mark the ones
3673  * that can be invoked now with the current firing ID.
3674  *
3675  * If move_list isn't NULL, events that are not to be invoked now are
3676  * transferred to move_list.
3677  *
3678  * When immediate_only is TRUE, do not invoke currently-deferred triggers.
3679  * (This will be FALSE only at main transaction exit.)
3680  *
3681  * Returns TRUE if any invokable events were found.
3682  */
3683 static bool
3685  AfterTriggerEventList *move_list,
3686  bool immediate_only)
3687 {
3688  bool found = false;
3689  AfterTriggerEvent event;
3690  AfterTriggerEventChunk *chunk;
3691 
3692  for_each_event_chunk(event, chunk, *events)
3693  {
3694  AfterTriggerShared evtshared = GetTriggerSharedData(event);
3695  bool defer_it = false;
3696 
3697  if (!(event->ate_flags &
3699  {
3700  /*
3701  * This trigger hasn't been called or scheduled yet. Check if we
3702  * should call it now.
3703  */
3704  if (immediate_only && afterTriggerCheckState(evtshared))
3705  {
3706  defer_it = true;
3707  }
3708  else
3709  {
3710  /*
3711  * Mark it as to be fired in this firing cycle.
3712  */
3713  evtshared->ats_firing_id = afterTriggers.firing_counter;
3714  event->ate_flags |= AFTER_TRIGGER_IN_PROGRESS;
3715  found = true;
3716  }
3717  }
3718 
3719  /*
3720  * If it's deferred, move it to move_list, if requested.
3721  */
3722  if (defer_it && move_list != NULL)
3723  {
3724  /* add it to move_list */
3725  afterTriggerAddEvent(move_list, event, evtshared);
3726  /* mark original copy "done" so we don't do it again */
3727  event->ate_flags |= AFTER_TRIGGER_DONE;
3728  }
3729  }
3730 
3731  return found;
3732 }
3733 
3734 /*
3735  * afterTriggerInvokeEvents()
3736  *
3737  * Scan the given event list for events that are marked as to be fired
3738  * in the current firing cycle, and fire them.
3739  *
3740  * If estate isn't NULL, we use its result relation info to avoid repeated
3741  * openings and closing of trigger target relations. If it is NULL, we
3742  * make one locally to cache the info in case there are multiple trigger
3743  * events per rel.
3744  *
3745  * When delete_ok is TRUE, it's safe to delete fully-processed events.
3746  * (We are not very tense about that: we simply reset a chunk to be empty
3747  * if all its events got fired. The objective here is just to avoid useless
3748  * rescanning of events when a trigger queues new events during transaction
3749  * end, so it's not necessary to worry much about the case where only
3750  * some events are fired.)
3751  *
3752  * Returns TRUE if no unfired events remain in the list (this allows us
3753  * to avoid repeating afterTriggerMarkEvents).
3754  */
3755 static bool
3757  CommandId firing_id,
3758  EState *estate,
3759  bool delete_ok)
3760 {
3761  bool all_fired = true;
3762  AfterTriggerEventChunk *chunk;
3763  MemoryContext per_tuple_context;
3764  bool local_estate = false;
3765  Relation rel = NULL;
3766  TriggerDesc *trigdesc = NULL;
3767  FmgrInfo *finfo = NULL;
3768  Instrumentation *instr = NULL;
3769  TupleTableSlot *slot1 = NULL,
3770  *slot2 = NULL;
3771 
3772  /* Make a local EState if need be */
3773  if (estate == NULL)
3774  {
3775  estate = CreateExecutorState();
3776  local_estate = true;
3777  }
3778 
3779  /* Make a per-tuple memory context for trigger function calls */
3780  per_tuple_context =
3782  "AfterTriggerTupleContext",
3786 
3787  for_each_chunk(chunk, *events)
3788  {
3789  AfterTriggerEvent event;
3790  bool all_fired_in_chunk = true;
3791 
3792  for_each_event(event, chunk)
3793  {
3794  AfterTriggerShared evtshared = GetTriggerSharedData(event);
3795 
3796  /*
3797  * Is it one for me to fire?
3798  */
3799  if ((event->ate_flags & AFTER_TRIGGER_IN_PROGRESS) &&
3800  evtshared->ats_firing_id == firing_id)
3801  {
3802  /*
3803  * So let's fire it... but first, find the correct relation if
3804  * this is not the same relation as before.
3805  */
3806  if (rel == NULL || RelationGetRelid(rel) != evtshared->ats_relid)
3807  {
3808  ResultRelInfo *rInfo;
3809 
3810  rInfo = ExecGetTriggerResultRel(estate, evtshared->ats_relid);
3811  rel = rInfo->ri_RelationDesc;
3812  trigdesc = rInfo->ri_TrigDesc;
3813  finfo = rInfo->ri_TrigFunctions;
3814  instr = rInfo->ri_TrigInstrument;
3815  if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
3816  {
3817  if (slot1 != NULL)
3818  {
3821  }
3822  slot1 = MakeSingleTupleTableSlot(rel->rd_att);
3823  slot2 = MakeSingleTupleTableSlot(rel->rd_att);
3824  }
3825  if (trigdesc == NULL) /* should not happen */
3826  elog(ERROR, "relation %u has no triggers",
3827  evtshared->ats_relid);
3828  }
3829 
3830  /*
3831  * Fire it. Note that the AFTER_TRIGGER_IN_PROGRESS flag is
3832  * still set, so recursive examinations of the event list
3833  * won't try to re-fire it.
3834  */
3835  AfterTriggerExecute(event, rel, trigdesc, finfo, instr,
3836  per_tuple_context, slot1, slot2);
3837 
3838  /*
3839  * Mark the event as done.
3840  */
3841  event->ate_flags &= ~AFTER_TRIGGER_IN_PROGRESS;
3842  event->ate_flags |= AFTER_TRIGGER_DONE;
3843  }
3844  else if (!(event->ate_flags & AFTER_TRIGGER_DONE))
3845  {
3846  /* something remains to be done */
3847  all_fired = all_fired_in_chunk = false;
3848  }
3849  }
3850 
3851  /* Clear the chunk if delete_ok and nothing left of interest */
3852  if (delete_ok && all_fired_in_chunk)
3853  {
3854  chunk->freeptr = CHUNK_DATA_START(chunk);
3855  chunk->endfree = chunk->endptr;
3856 
3857  /*
3858  * If it's last chunk, must sync event list's tailfree too. Note
3859  * that delete_ok must NOT be passed as true if there could be
3860  * stacked AfterTriggerEventList values pointing at this event
3861  * list, since we'd fail to fix their copies of tailfree.
3862  */
3863  if (chunk == events->tail)
3864  events->tailfree = chunk->freeptr;
3865  }
3866  }
3867  if (slot1 != NULL)
3868  {
3871  }
3872 
3873  /* Release working resources */
3874  MemoryContextDelete(per_tuple_context);
3875 
3876  if (local_estate)
3877  {
3878  ListCell *l;
3879 
3880  foreach(l, estate->es_trig_target_relations)
3881  {
3882  ResultRelInfo *resultRelInfo = (ResultRelInfo *) lfirst(l);
3883 
3884  /* Close indices and then the relation itself */
3885  ExecCloseIndices(resultRelInfo);
3886  heap_close(resultRelInfo->ri_RelationDesc, NoLock);
3887  }
3888  FreeExecutorState(estate);
3889  }
3890 
3891  return all_fired;
3892 }
3893 
3894 
3895 /* ----------
3896  * AfterTriggerBeginXact()
3897  *
3898  * Called at transaction start (either BEGIN or implicit for single
3899  * statement outside of transaction block).
3900  * ----------
3901  */
3902 void
3904 {
3905  /*
3906  * Initialize after-trigger state structure to empty
3907  */
3908  afterTriggers.firing_counter = (CommandId) 1; /* mustn't be 0 */
3909  afterTriggers.query_depth = -1;
3910 
3911  /*
3912  * Verify that there is no leftover state remaining. If these assertions
3913  * trip, it means that AfterTriggerEndXact wasn't called or didn't clean
3914  * up properly.
3915  */
3916  Assert(afterTriggers.state == NULL);
3917  Assert(afterTriggers.query_stack == NULL);
3918  Assert(afterTriggers.fdw_tuplestores == NULL);
3919  Assert(afterTriggers.maxquerydepth == 0);
3920  Assert(afterTriggers.event_cxt == NULL);
3921  Assert(afterTriggers.events.head == NULL);
3922  Assert(afterTriggers.state_stack == NULL);
3923  Assert(afterTriggers.events_stack == NULL);
3924  Assert(afterTriggers.depth_stack == NULL);
3925  Assert(afterTriggers.firing_stack == NULL);
3926  Assert(afterTriggers.maxtransdepth == 0);
3927 }
3928 
3929 
3930 /* ----------
3931  * AfterTriggerBeginQuery()
3932  *
3933  * Called just before we start processing a single query within a
3934  * transaction (or subtransaction). Most of the real work gets deferred
3935  * until somebody actually tries to queue a trigger event.
3936  * ----------
3937  */
3938 void
3940 {
3941  /* Increase the query stack depth */
3942  afterTriggers.query_depth++;
3943 }
3944 
3945 
3946 /* ----------
3947  * AfterTriggerEndQuery()
3948  *
3949  * Called after one query has been completely processed. At this time
3950  * we invoke all AFTER IMMEDIATE trigger events queued by the query, and
3951  * transfer deferred trigger events to the global deferred-trigger list.
3952  *
3953  * Note that this must be called BEFORE closing down the executor
3954  * with ExecutorEnd, because we make use of the EState's info about
3955  * target relations. Normally it is called from ExecutorFinish.
3956  * ----------
3957  */
3958 void
3960 {
3961  AfterTriggerEventList *events;
3962  Tuplestorestate *fdw_tuplestore;
3963 
3964  /* Must be inside a query, too */
3965  Assert(afterTriggers.query_depth >= 0);
3966 
3967  /*
3968  * If we never even got as far as initializing the event stack, there
3969  * certainly won't be any events, so exit quickly.
3970  */
3971  if (afterTriggers.query_depth >= afterTriggers.maxquerydepth)
3972  {
3973  afterTriggers.query_depth--;
3974  return;
3975  }
3976 
3977  /*
3978  * Process all immediate-mode triggers queued by the query, and move the
3979  * deferred ones to the main list of deferred events.
3980  *
3981  * Notice that we decide which ones will be fired, and put the deferred
3982  * ones on the main list, before anything is actually fired. This ensures
3983  * reasonably sane behavior if a trigger function does SET CONSTRAINTS ...
3984  * IMMEDIATE: all events we have decided to defer will be available for it
3985  * to fire.
3986  *
3987  * We loop in case a trigger queues more events at the same query level.
3988  * Ordinary trigger functions, including all PL/pgSQL trigger functions,
3989  * will instead fire any triggers in a dedicated query level. Foreign key
3990  * enforcement triggers do add to the current query level, thanks to their
3991  * passing fire_triggers = false to SPI_execute_snapshot(). Other
3992  * C-language triggers might do likewise. Be careful here: firing a
3993  * trigger could result in query_stack being repalloc'd, so we can't save
3994  * its address across afterTriggerInvokeEvents calls.
3995  *
3996  * If we find no firable events, we don't have to increment
3997  * firing_counter.
3998  */
3999  for (;;)
4000  {
4001  events = &afterTriggers.query_stack[afterTriggers.query_depth];
4002  if (afterTriggerMarkEvents(events, &afterTriggers.events, true))
4003  {
4004  CommandId firing_id = afterTriggers.firing_counter++;
4005 
4006  /* OK to delete the immediate events after processing them */
4007  if (afterTriggerInvokeEvents(events, firing_id, estate, true))
4008  break; /* all fired */
4009  }
4010  else
4011  break;
4012  }
4013 
4014  /* Release query-local storage for events, including tuplestore if any */
4015  fdw_tuplestore = afterTriggers.fdw_tuplestores[afterTriggers.query_depth];
4016  if (fdw_tuplestore)
4017  {
4018  tuplestore_end(fdw_tuplestore);
4019  afterTriggers.fdw_tuplestores[afterTriggers.query_depth] = NULL;
4020  }
4021  afterTriggerFreeEventList(&afterTriggers.query_stack[afterTriggers.query_depth]);
4022 
4023  afterTriggers.query_depth--;
4024 }
4025 
4026 
4027 /* ----------
4028  * AfterTriggerFireDeferred()
4029  *
4030  * Called just before the current transaction is committed. At this
4031  * time we invoke all pending DEFERRED triggers.
4032  *
4033  * It is possible for other modules to queue additional deferred triggers
4034  * during pre-commit processing; therefore xact.c may have to call this
4035  * multiple times.
4036  * ----------
4037  */
4038 void
4040 {
4041  AfterTriggerEventList *events;
4042  bool snap_pushed = false;
4043 
4044  /* Must not be inside a query */
4045  Assert(afterTriggers.query_depth == -1);
4046 
4047  /*
4048  * If there are any triggers to fire, make sure we have set a snapshot for
4049  * them to use. (Since PortalRunUtility doesn't set a snap for COMMIT, we
4050  * can't assume ActiveSnapshot is valid on entry.)
4051  */
4052  events = &afterTriggers.events;
4053  if (events->head != NULL)
4054  {
4056  snap_pushed = true;
4057  }
4058 
4059  /*
4060  * Run all the remaining triggers. Loop until they are all gone, in case
4061  * some trigger queues more for us to do.
4062  */
4063  while (afterTriggerMarkEvents(events, NULL, false))
4064  {
4065  CommandId firing_id = afterTriggers.firing_counter++;
4066 
4067  if (afterTriggerInvokeEvents(events, firing_id, NULL, true))
4068  break; /* all fired */
4069  }
4070 
4071  /*
4072  * We don't bother freeing the event list, since it will go away anyway
4073  * (and more efficiently than via pfree) in AfterTriggerEndXact.
4074  */
4075 
4076  if (snap_pushed)
4078 }
4079 
4080 
4081 /* ----------
4082  * AfterTriggerEndXact()
4083  *
4084  * The current transaction is finishing.
4085  *
4086  * Any unfired triggers are canceled so we simply throw
4087  * away anything we know.
4088  *
4089  * Note: it is possible for this to be called repeatedly in case of
4090  * error during transaction abort; therefore, do not complain if
4091  * already closed down.
4092  * ----------
4093  */
4094 void
4095 AfterTriggerEndXact(bool isCommit)
4096 {
4097  /*
4098  * Forget the pending-events list.
4099  *
4100  * Since all the info is in TopTransactionContext or children thereof, we
4101  * don't really need to do anything to reclaim memory. However, the
4102  * pending-events list could be large, and so it's useful to discard it as
4103  * soon as possible --- especially if we are aborting because we ran out
4104  * of memory for the list!
4105  */
4106  if (afterTriggers.event_cxt)
4107  {
4108  MemoryContextDelete(afterTriggers.event_cxt);
4109  afterTriggers.event_cxt = NULL;
4110  afterTriggers.events.head = NULL;
4111  afterTriggers.events.tail = NULL;
4112  afterTriggers.events.tailfree = NULL;
4113  }
4114 
4115  /*
4116  * Forget any subtransaction state as well. Since this can't be very
4117  * large, we let the eventual reset of TopTransactionContext free the
4118  * memory instead of doing it here.
4119  */
4120  afterTriggers.state_stack = NULL;
4121  afterTriggers.events_stack = NULL;
4122  afterTriggers.depth_stack = NULL;
4123  afterTriggers.firing_stack = NULL;
4124  afterTriggers.maxtransdepth = 0;
4125 
4126 
4127  /*
4128  * Forget the query stack and constraint-related state information. As
4129  * with the subtransaction state information, we don't bother freeing the
4130  * memory here.
4131  */
4132  afterTriggers.query_stack = NULL;
4133  afterTriggers.fdw_tuplestores = NULL;
4134  afterTriggers.maxquerydepth = 0;
4135  afterTriggers.state = NULL;
4136 
4137  /* No more afterTriggers manipulation until next transaction starts. */
4138  afterTriggers.query_depth = -1;
4139 }
4140 
4141 /*
4142  * AfterTriggerBeginSubXact()
4143  *
4144  * Start a subtransaction.
4145  */
4146 void
4148 {
4149  int my_level = GetCurrentTransactionNestLevel();
4150 
4151  /*
4152  * Allocate more space in the stacks if needed. (Note: because the
4153  * minimum nest level of a subtransaction is 2, we waste the first couple
4154  * entries of each array; not worth the notational effort to avoid it.)
4155  */
4156  while (my_level >= afterTriggers.maxtransdepth)
4157  {
4158  if (afterTriggers.maxtransdepth == 0)
4159  {
4160  MemoryContext old_cxt;
4161 
4163 
4164 #define DEFTRIG_INITALLOC 8
4165  afterTriggers.state_stack = (SetConstraintState *)
4166  palloc(DEFTRIG_INITALLOC * sizeof(SetConstraintState));
4167  afterTriggers.events_stack = (AfterTriggerEventList *)
4169  afterTriggers.depth_stack = (int *)
4170  palloc(DEFTRIG_INITALLOC * sizeof(int));
4171  afterTriggers.firing_stack = (CommandId *)
4172  palloc(DEFTRIG_INITALLOC * sizeof(CommandId));
4173  afterTriggers.maxtransdepth = DEFTRIG_INITALLOC;
4174 
4175  MemoryContextSwitchTo(old_cxt);
4176  }
4177  else
4178  {
4179  /* repalloc will keep the stacks in the same context */
4180  int new_alloc = afterTriggers.maxtransdepth * 2;
4181 
4182  afterTriggers.state_stack = (SetConstraintState *)
4183  repalloc(afterTriggers.state_stack,
4184  new_alloc * sizeof(SetConstraintState));
4185  afterTriggers.events_stack = (AfterTriggerEventList *)
4186  repalloc(afterTriggers.events_stack,
4187  new_alloc * sizeof(AfterTriggerEventList));
4188  afterTriggers.depth_stack = (int *)
4189  repalloc(afterTriggers.depth_stack,
4190  new_alloc * sizeof(int));
4191  afterTriggers.firing_stack = (CommandId *)
4192  repalloc(afterTriggers.firing_stack,
4193  new_alloc * sizeof(CommandId));
4194  afterTriggers.maxtransdepth = new_alloc;
4195  }
4196  }
4197 
4198  /*
4199  * Push the current information into the stack. The SET CONSTRAINTS state
4200  * is not saved until/unless changed. Likewise, we don't make a
4201  * per-subtransaction event context until needed.
4202  */
4203  afterTriggers.state_stack[my_level] = NULL;
4204  afterTriggers.events_stack[my_level] = afterTriggers.events;
4205  afterTriggers.depth_stack[my_level] = afterTriggers.query_depth;
4206  afterTriggers.firing_stack[my_level] = afterTriggers.firing_counter;
4207 }
4208 
4209 /*
4210  * AfterTriggerEndSubXact()
4211  *
4212  * The current subtransaction is ending.
4213  */
4214 void
4216 {
4217  int my_level = GetCurrentTransactionNestLevel();
4218  SetConstraintState state;
4219  AfterTriggerEvent event;
4220  AfterTriggerEventChunk *chunk;
4221  CommandId subxact_firing_id;
4222 
4223  /*
4224  * Pop the prior state if needed.
4225  */
4226  if (isCommit)
4227  {
4228  Assert(my_level < afterTriggers.maxtransdepth);
4229  /* If we saved a prior state, we don't need it anymore */
4230  state = afterTriggers.state_stack[my_level];
4231  if (state != NULL)
4232  pfree(state);
4233  /* this avoids double pfree if error later: */
4234  afterTriggers.state_stack[my_level] = NULL;
4235  Assert(afterTriggers.query_depth ==
4236  afterTriggers.depth_stack[my_level]);
4237  }
4238  else
4239  {
4240  /*
4241  * Aborting. It is possible subxact start failed before calling
4242  * AfterTriggerBeginSubXact, in which case we mustn't risk touching
4243  * stack levels that aren't there.
4244  */
4245  if (my_level >= afterTriggers.maxtransdepth)
4246  return;
4247 
4248  /*
4249  * Release any event lists from queries being aborted, and restore
4250  * query_depth to its pre-subxact value. This assumes that a
4251  * subtransaction will not add events to query levels started in a
4252  * earlier transaction state.
4253  */
4254  while (afterTriggers.query_depth > afterTriggers.depth_stack[my_level])
4255  {
4256  if (afterTriggers.query_depth < afterTriggers.maxquerydepth)
4257  {
4258  Tuplestorestate *ts;
4259 
4260  ts = afterTriggers.fdw_tuplestores[afterTriggers.query_depth];
4261  if (ts)
4262  {
4263  tuplestore_end(ts);
4264  afterTriggers.fdw_tuplestores[afterTriggers.query_depth] = NULL;
4265  }
4266 
4267  afterTriggerFreeEventList(&afterTriggers.query_stack[afterTriggers.query_depth]);
4268  }
4269 
4270  afterTriggers.query_depth--;
4271  }
4272  Assert(afterTriggers.query_depth ==
4273  afterTriggers.depth_stack[my_level]);
4274 
4275  /*
4276  * Restore the global deferred-event list to its former length,
4277  * discarding any events queued by the subxact.
4278  */
4279  afterTriggerRestoreEventList(&afterTriggers.events,
4280  &afterTriggers.events_stack[my_level]);
4281 
4282  /*
4283  * Restore the trigger state. If the saved state is NULL, then this
4284  * subxact didn't save it, so it doesn't need restoring.
4285  */
4286  state = afterTriggers.state_stack[my_level];
4287  if (state != NULL)
4288  {
4289  pfree(afterTriggers.state);
4290  afterTriggers.state = state;
4291  }
4292  /* this avoids double pfree if error later: */
4293  afterTriggers.state_stack[my_level] = NULL;
4294 
4295  /*
4296  * Scan for any remaining deferred events that were marked DONE or IN
4297  * PROGRESS by this subxact or a child, and un-mark them. We can
4298  * recognize such events because they have a firing ID greater than or
4299  * equal to the firing_counter value we saved at subtransaction start.
4300  * (This essentially assumes that the current subxact includes all
4301  * subxacts started after it.)
4302  */
4303  subxact_firing_id = afterTriggers.firing_stack[my_level];
4304  for_each_event_chunk(event, chunk, afterTriggers.events)
4305  {
4306  AfterTriggerShared evtshared = GetTriggerSharedData(event);
4307 
4308  if (event->ate_flags &
4310  {
4311  if (evtshared->ats_firing_id >= subxact_firing_id)
4312  event->ate_flags &=
4314  }
4315  }
4316  }
4317 }
4318 
4319 /* ----------
4320  * AfterTriggerEnlargeQueryState()
4321  *
4322  * Prepare the necessary state so that we can record AFTER trigger events
4323  * queued by a query. It is allowed to have nested queries within a
4324  * (sub)transaction, so we need to have separate state for each query
4325  * nesting level.
4326  * ----------
4327  */
4328 static void
4330 {
4331  int init_depth = afterTriggers.maxquerydepth;
4332 
4333  Assert(afterTriggers.query_depth >= afterTriggers.maxquerydepth);
4334 
4335  if (afterTriggers.maxquerydepth == 0)
4336  {
4337  int new_alloc = Max(afterTriggers.query_depth + 1, 8);
4338 
4339  afterTriggers.query_stack = (AfterTriggerEventList *)
4341  new_alloc * sizeof(AfterTriggerEventList));
4342  afterTriggers.fdw_tuplestores = (Tuplestorestate **)
4344  new_alloc * sizeof(Tuplestorestate *));
4345  afterTriggers.maxquerydepth = new_alloc;
4346  }
4347  else
4348  {
4349  /* repalloc will keep the stack in the same context */
4350  int old_alloc = afterTriggers.maxquerydepth;
4351  int new_alloc = Max(afterTriggers.query_depth + 1,
4352  old_alloc * 2);
4353 
4354  afterTriggers.query_stack = (AfterTriggerEventList *)
4355  repalloc(afterTriggers.query_stack,
4356  new_alloc * sizeof(AfterTriggerEventList));
4357  afterTriggers.fdw_tuplestores = (Tuplestorestate **)
4358  repalloc(afterTriggers.fdw_tuplestores,
4359  new_alloc * sizeof(Tuplestorestate *));
4360  /* Clear newly-allocated slots for subsequent lazy initialization. */
4361  memset(afterTriggers.fdw_tuplestores + old_alloc,
4362  0, (new_alloc - old_alloc) * sizeof(Tuplestorestate *));
4363  afterTriggers.maxquerydepth = new_alloc;
4364  }
4365 
4366  /* Initialize new query lists to empty */
4367  while (init_depth < afterTriggers.maxquerydepth)
4368  {
4369  AfterTriggerEventList *events;
4370 
4371  events = &afterTriggers.query_stack[init_depth];
4372  events->head = NULL;
4373  events->tail = NULL;
4374  events->tailfree = NULL;
4375 
4376  ++init_depth;
4377  }
4378 }
4379 
4380 /*
4381  * Create an empty SetConstraintState with room for numalloc trigstates
4382  */
4383 static SetConstraintState
4385 {
4386  SetConstraintState state;
4387 
4388  /* Behave sanely with numalloc == 0 */
4389  if (numalloc <= 0)
4390  numalloc = 1;
4391 
4392  /*
4393  * We assume that zeroing will correctly initialize the state values.
4394  */
4395  state = (SetConstraintState)
4397  offsetof(SetConstraintStateData, trigstates) +
4398  numalloc * sizeof(SetConstraintTriggerData));
4399 
4400  state->numalloc = numalloc;
4401 
4402  return state;
4403 }
4404 
4405 /*
4406  * Copy a SetConstraintState
4407  */
4408 static SetConstraintState
4409 SetConstraintStateCopy(SetConstraintState origstate)
4410 {
4411  SetConstraintState state;
4412 
4413  state = SetConstraintStateCreate(origstate->numstates);
4414 
4415  state->all_isset = origstate->all_isset;
4416  state->all_isdeferred = origstate->all_isdeferred;
4417  state->numstates = origstate->numstates;
4418  memcpy(state->trigstates, origstate->trigstates,
4419  origstate->numstates * sizeof(SetConstraintTriggerData));
4420 
4421  return state;
4422 }
4423 
4424 /*
4425  * Add a per-trigger item to a SetConstraintState. Returns possibly-changed
4426  * pointer to the state object (it will change if we have to repalloc).
4427  */
4428 static SetConstraintState
4430  Oid tgoid, bool tgisdeferred)
4431 {
4432  if (state->numstates >= state->numalloc)
4433  {
4434  int newalloc = state->numalloc * 2;
4435 
4436  newalloc = Max(newalloc, 8); /* in case original has size 0 */
4437  state = (SetConstraintState)
4438  repalloc(state,
4439  offsetof(SetConstraintStateData, trigstates) +
4440  newalloc * sizeof(SetConstraintTriggerData));
4441  state->numalloc = newalloc;
4442  Assert(state->numstates < state->numalloc);
4443  }
4444 
4445  state->trigstates[state->numstates].sct_tgoid = tgoid;
4446  state->trigstates[state->numstates].sct_tgisdeferred = tgisdeferred;
4447  state->numstates++;
4448 
4449  return state;
4450 }
4451 
4452 /* ----------
4453  * AfterTriggerSetState()
4454  *
4455  * Execute the SET CONSTRAINTS ... utility command.
4456  * ----------
4457  */
4458 void
4460 {
4461  int my_level = GetCurrentTransactionNestLevel();
4462 
4463  /* If we haven't already done so, initialize our state. */
4464  if (afterTriggers.state == NULL)
4465  afterTriggers.state = SetConstraintStateCreate(8);
4466 
4467  /*
4468  * If in a subtransaction, and we didn't save the current state already,
4469  * save it so it can be restored if the subtransaction aborts.
4470  */
4471  if (my_level > 1 &&
4472  afterTriggers.state_stack[my_level] == NULL)
4473  {
4474  afterTriggers.state_stack[my_level] =
4475  SetConstraintStateCopy(afterTriggers.state);
4476  }
4477 
4478  /*
4479  * Handle SET CONSTRAINTS ALL ...
4480  */
4481  if (stmt->constraints == NIL)
4482  {
4483  /*
4484  * Forget any previous SET CONSTRAINTS commands in this transaction.
4485  */
4486  afterTriggers.state->numstates = 0;
4487 
4488  /*
4489  * Set the per-transaction ALL state to known.
4490  */
4491  afterTriggers.state->all_isset = true;
4492  afterTriggers.state->all_isdeferred = stmt->deferred;
4493  }
4494  else
4495  {
4496  Relation conrel;
4497  Relation tgrel;
4498  List *conoidlist = NIL;
4499  List *tgoidlist = NIL;
4500  ListCell *lc;
4501 
4502  /*
4503  * Handle SET CONSTRAINTS constraint-name [, ...]
4504  *
4505  * First, identify all the named constraints and make a list of their
4506  * OIDs. Since, unlike the SQL spec, we allow multiple constraints of
4507  * the same name within a schema, the specifications are not
4508  * necessarily unique. Our strategy is to target all matching
4509  * constraints within the first search-path schema that has any
4510  * matches, but disregard matches in schemas beyond the first match.
4511  * (This is a bit odd but it's the historical behavior.)
4512  */
4514 
4515  foreach(lc, stmt->constraints)
4516  {
4517  RangeVar *constraint = lfirst(lc);
4518  bool found;
4519  List *namespacelist;
4520  ListCell *nslc;
4521 
4522  if (constraint->catalogname)
4523  {
4524  if (strcmp(constraint->catalogname, get_database_name(MyDatabaseId)) != 0)
4525  ereport(ERROR,
4526  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4527  errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
4528  constraint->catalogname, constraint->schemaname,
4529  constraint->relname)));
4530  }
4531 
4532  /*
4533  * If we're given the schema name with the constraint, look only
4534  * in that schema. If given a bare constraint name, use the
4535  * search path to find the first matching constraint.
4536  */
4537  if (constraint->schemaname)
4538  {
4539  Oid namespaceId = LookupExplicitNamespace(constraint->schemaname,
4540  false);
4541 
4542  namespacelist = list_make1_oid(namespaceId);
4543  }
4544  else
4545  {
4546  namespacelist = fetch_search_path(true);
4547  }
4548 
4549  found = false;
4550  foreach(nslc, namespacelist)
4551  {
4552  Oid namespaceId = lfirst_oid(nslc);
4553  SysScanDesc conscan;
4554  ScanKeyData skey[2];
4555  HeapTuple tup;
4556 
4557  ScanKeyInit(&skey[0],
4559  BTEqualStrategyNumber, F_NAMEEQ,
4560  CStringGetDatum(constraint->relname));
4561  ScanKeyInit(&skey[1],
4563  BTEqualStrategyNumber, F_OIDEQ,
4564  ObjectIdGetDatum(namespaceId));
4565 
4566  conscan = systable_beginscan(conrel, ConstraintNameNspIndexId,
4567  true, NULL, 2, skey);
4568 
4569  while (HeapTupleIsValid(tup = systable_getnext(conscan)))
4570  {
4572 
4573  if (con->condeferrable)
4574  conoidlist = lappend_oid(conoidlist,
4575  HeapTupleGetOid(tup));
4576  else if (stmt->deferred)
4577  ereport(ERROR,
4578  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
4579  errmsg("constraint \"%s\" is not deferrable",
4580  constraint->relname)));
4581  found = true;
4582  }
4583 
4584  systable_endscan(conscan);
4585 
4586  /*
4587  * Once we've found a matching constraint we do not search
4588  * later parts of the search path.
4589  */
4590  if (found)
4591  break;
4592  }
4593 
4594  list_free(namespacelist);
4595 
4596  /*
4597  * Not found ?
4598  */
4599  if (!found)
4600  ereport(ERROR,
4601  (errcode(ERRCODE_UNDEFINED_OBJECT),
4602  errmsg("constraint \"%s\" does not exist",
4603  constraint->relname)));
4604  }
4605 
4606  heap_close(conrel, AccessShareLock);
4607 
4608  /*
4609  * Now, locate the trigger(s) implementing each of these constraints,
4610  * and make a list of their OIDs.
4611  */
4613 
4614  foreach(lc, conoidlist)
4615  {
4616  Oid conoid = lfirst_oid(lc);
4617  bool found;
4618  ScanKeyData skey;
4619  SysScanDesc tgscan;
4620  HeapTuple htup;
4621 
4622  found = false;
4623 
4624  ScanKeyInit(&skey,
4626  BTEqualStrategyNumber, F_OIDEQ,
4627  ObjectIdGetDatum(conoid));
4628 
4629  tgscan = systable_beginscan(tgrel, TriggerConstraintIndexId, true,
4630  NULL, 1, &skey);
4631 
4632  while (HeapTupleIsValid(htup = systable_getnext(tgscan)))
4633  {
4634  Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
4635 
4636  /*
4637  * Silently skip triggers that are marked as non-deferrable in
4638  * pg_trigger. This is not an error condition, since a
4639  * deferrable RI constraint may have some non-deferrable
4640  * actions.
4641  */
4642  if (pg_trigger->tgdeferrable)
4643  tgoidlist = lappend_oid(tgoidlist,
4644  HeapTupleGetOid(htup));
4645 
4646  found = true;
4647  }
4648 
4649  systable_endscan(tgscan);
4650 
4651  /* Safety check: a deferrable constraint should have triggers */
4652  if (!found)
4653  elog(ERROR, "no triggers found for constraint with OID %u",
4654  conoid);
4655  }
4656 
4657  heap_close(tgrel, AccessShareLock);
4658 
4659  /*
4660  * Now we can set the trigger states of individual triggers for this
4661  * xact.
4662  */
4663  foreach(lc, tgoidlist)
4664  {
4665  Oid tgoid = lfirst_oid(lc);
4666  SetConstraintState state = afterTriggers.state;
4667  bool found = false;
4668  int i;
4669 
4670  for (i = 0; i < state->numstates; i++)
4671  {
4672  if (state->trigstates[i].sct_tgoid == tgoid)
4673  {
4674  state->trigstates[i].sct_tgisdeferred = stmt->deferred;
4675  found = true;
4676  break;
4677  }
4678  }
4679  if (!found)
4680  {
4681  afterTriggers.state =
4682  SetConstraintStateAddItem(state, tgoid, stmt->deferred);
4683  }
4684  }
4685  }
4686 
4687  /*
4688  * SQL99 requires that when a constraint is set to IMMEDIATE, any deferred
4689  * checks against that constraint must be made when the SET CONSTRAINTS
4690  * command is executed -- i.e. the effects of the SET CONSTRAINTS command
4691  * apply retroactively. We've updated the constraints state, so scan the
4692  * list of previously deferred events to fire any that have now become
4693  * immediate.
4694  *
4695  * Obviously, if this was SET ... DEFERRED then it can't have converted
4696  * any unfired events to immediate, so we need do nothing in that case.
4697  */
4698  if (!stmt->deferred)
4699  {
4700  AfterTriggerEventList *events = &afterTriggers.events;
4701  bool snapshot_set = false;
4702 
4703  while (afterTriggerMarkEvents(events, NULL, true))
4704  {
4705  CommandId firing_id = afterTriggers.firing_counter++;
4706 
4707  /*
4708  * Make sure a snapshot has been established in case trigger
4709  * functions need one. Note that we avoid setting a snapshot if
4710  * we don't find at least one trigger that has to be fired now.
4711  * This is so that BEGIN; SET CONSTRAINTS ...; SET TRANSACTION
4712  * ISOLATION LEVEL SERIALIZABLE; ... works properly. (If we are
4713  * at the start of a transaction it's not possible for any trigger
4714  * events to be queued yet.)
4715  */
4716  if (!snapshot_set)
4717  {
4719  snapshot_set = true;
4720  }
4721 
4722  /*
4723  * We can delete fired events if we are at top transaction level,
4724  * but we'd better not if inside a subtransaction, since the
4725  * subtransaction could later get rolled back.
4726  */
4727  if (afterTriggerInvokeEvents(events, firing_id, NULL,
4728  !IsSubTransaction()))
4729  break; /* all fired */
4730  }
4731 
4732  if (snapshot_set)
4734  }
4735 }
4736 
4737 /* ----------
4738  * AfterTriggerPendingOnRel()
4739  * Test to see if there are any pending after-trigger events for rel.
4740  *
4741  * This is used by TRUNCATE, CLUSTER, ALTER TABLE, etc to detect whether
4742  * it is unsafe to perform major surgery on a relation. Note that only
4743  * local pending events are examined. We assume that having exclusive lock
4744  * on a rel guarantees there are no unserviced events in other backends ---
4745  * but having a lock does not prevent there being such events in our own.
4746  *
4747  * In some scenarios it'd be reasonable to remove pending events (more
4748  * specifically, mark them DONE by the current subxact) but without a lot
4749  * of knowledge of the trigger semantics we can't do this in general.
4750  * ----------
4751  */
4752 bool
4754 {
4755  AfterTriggerEvent event;
4756  AfterTriggerEventChunk *chunk;
4757  int depth;
4758 
4759  /* Scan queued events */
4760  for_each_event_chunk(event, chunk, afterTriggers.events)
4761  {
4762  AfterTriggerShared evtshared = GetTriggerSharedData(event);
4763 
4764  /*
4765  * We can ignore completed events. (Even if a DONE flag is rolled
4766  * back by subxact abort, it's OK because the effects of the TRUNCATE
4767  * or whatever must get rolled back too.)
4768  */
4769  if (event->ate_flags & AFTER_TRIGGER_DONE)
4770  continue;
4771 
4772  if (evtshared->ats_relid == relid)
4773  return true;
4774  }
4775 
4776  /*
4777  * Also scan events queued by incomplete queries. This could only matter
4778  * if TRUNCATE/etc is executed by a function or trigger within an updating
4779  * query on the same relation, which is pretty perverse, but let's check.
4780  */
4781  for (depth = 0; depth <= afterTriggers.query_depth && depth < afterTriggers.maxquerydepth; depth++)
4782  {
4783  for_each_event_chunk(event, chunk, afterTriggers.query_stack[depth])
4784  {
4785  AfterTriggerShared evtshared = GetTriggerSharedData(event);
4786 
4787  if (event->ate_flags & AFTER_TRIGGER_DONE)
4788  continue;
4789 
4790  if (evtshared->ats_relid == relid)
4791  return true;
4792  }
4793  }
4794 
4795  return false;
4796 }
4797 
4798 
4799 /* ----------
4800  * AfterTriggerSaveEvent()
4801  *
4802  * Called by ExecA[RS]...Triggers() to queue up the triggers that should
4803  * be fired for an event.
4804  *
4805  * NOTE: this is called whenever there are any triggers associated with
4806  * the event (even if they are disabled). This function decides which
4807  * triggers actually need to be queued.
4808  * ----------
4809  */
4810 static void
4812  int event, bool row_trigger,
4813  HeapTuple oldtup, HeapTuple newtup,
4814  List *recheckIndexes, Bitmapset *modifiedCols)
4815 {
4816  Relation rel = relinfo->ri_RelationDesc;
4817  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
4818  AfterTriggerEventData new_event;
4819  AfterTriggerSharedData new_shared;
4820  char relkind = relinfo->ri_RelationDesc->rd_rel->relkind;
4821  int tgtype_event;
4822  int tgtype_level;
4823  int i;
4824  Tuplestorestate *fdw_tuplestore = NULL;
4825 
4826  /*
4827  * Check state. We use a normal test not Assert because it is possible to
4828  * reach here in the wrong state given misconfigured RI triggers, in
4829  * particular deferring a cascade action trigger.
4830  */
4831  if (afterTriggers.query_depth < 0)
4832  elog(ERROR, "AfterTriggerSaveEvent() called outside of query");
4833 
4834  /* Be sure we have enough space to record events at this query depth. */
4835  if (afterTriggers.query_depth >= afterTriggers.maxquerydepth)
4837 
4838  /*
4839  * Validate the event code and collect the associated tuple CTIDs.
4840  *
4841  * The event code will be used both as a bitmask and an array offset, so
4842  * validation is important to make sure we don't walk off the edge of our
4843  * arrays.
4844  */
4845  switch (event)
4846  {
4847  case TRIGGER_EVENT_INSERT:
4848  tgtype_event = TRIGGER_TYPE_INSERT;
4849  if (row_trigger)
4850  {
4851  Assert(oldtup == NULL);
4852  Assert(newtup != NULL);
4853  ItemPointerCopy(&(newtup->t_self), &(new_event.ate_ctid1));
4854  ItemPointerSetInvalid(&(new_event.ate_ctid2));
4855  }
4856  else
4857  {
4858  Assert(oldtup == NULL);
4859  Assert(newtup == NULL);
4860  ItemPointerSetInvalid(&(new_event.ate_ctid1));
4861  ItemPointerSetInvalid(&(new_event.ate_ctid2));
4862  }
4863  break;
4864  case TRIGGER_EVENT_DELETE:
4865  tgtype_event = TRIGGER_TYPE_DELETE;
4866  if (row_trigger)
4867  {
4868  Assert(oldtup != NULL);
4869  Assert(newtup == NULL);
4870  ItemPointerCopy(&(oldtup->t_self), &(new_event.ate_ctid1));
4871  ItemPointerSetInvalid(&(new_event.ate_ctid2));
4872  }
4873  else
4874  {
4875  Assert(oldtup == NULL);
4876  Assert(newtup == NULL);
4877  ItemPointerSetInvalid(&(new_event.ate_ctid1));
4878  ItemPointerSetInvalid(&(new_event.ate_ctid2));
4879  }
4880  break;
4881  case TRIGGER_EVENT_UPDATE:
4882  tgtype_event = TRIGGER_TYPE_UPDATE;
4883  if (row_trigger)
4884  {
4885  Assert(oldtup != NULL);
4886  Assert(newtup != NULL);
4887  ItemPointerCopy(&(oldtup->t_self), &(new_event.ate_ctid1));
4888  ItemPointerCopy(&(newtup->t_self), &(new_event.ate_ctid2));
4889  }
4890  else
4891  {
4892  Assert(oldtup == NULL);
4893  Assert(newtup == NULL);
4894  ItemPointerSetInvalid(&(new_event.ate_ctid1));
4895  ItemPointerSetInvalid(&(new_event.ate_ctid2));
4896  }
4897  break;
4899  tgtype_event = TRIGGER_TYPE_TRUNCATE;
4900  Assert(oldtup == NULL);
4901  Assert(newtup == NULL);
4902  ItemPointerSetInvalid(&(new_event.ate_ctid1));
4903  ItemPointerSetInvalid(&(new_event.ate_ctid2));
4904  break;
4905  default:
4906  elog(ERROR, "invalid after-trigger event code: %d", event);
4907  tgtype_event = 0; /* keep compiler quiet */
4908  break;
4909  }
4910 
4911  if (!(relkind == RELKIND_FOREIGN_TABLE && row_trigger))
4912  new_event.ate_flags = (row_trigger && event == TRIGGER_EVENT_UPDATE) ?
4914  /* else, we'll initialize ate_flags for each trigger */
4915 
4916  tgtype_level = (row_trigger ? TRIGGER_TYPE_ROW : TRIGGER_TYPE_STATEMENT);
4917 
4918  for (i = 0; i < trigdesc->numtriggers; i++)
4919  {
4920  Trigger *trigger = &trigdesc->triggers[i];
4921 
4922  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
4923  tgtype_level,
4925  tgtype_event))
4926  continue;
4927  if (!TriggerEnabled(estate, relinfo, trigger, event,
4928  modifiedCols, oldtup, newtup))
4929  continue;
4930 
4931  if (relkind == RELKIND_FOREIGN_TABLE && row_trigger)
4932  {
4933  if (fdw_tuplestore == NULL)
4934  {
4935  fdw_tuplestore = GetCurrentFDWTuplestore();
4936  new_event.ate_flags = AFTER_TRIGGER_FDW_FETCH;
4937  }
4938  else
4939  /* subsequent event for the same tuple */
4940  new_event.ate_flags = AFTER_TRIGGER_FDW_REUSE;
4941  }
4942 
4943  /*
4944  * If the trigger is a foreign key enforcement trigger, there are
4945  * certain cases where we can skip queueing the event because we can
4946  * tell by inspection that the FK constraint will still pass.
4947  */
4948  if (TRIGGER_FIRED_BY_UPDATE(event))
4949  {
4950  switch (RI_FKey_trigger_type(trigger->tgfoid))
4951  {
4952  case RI_TRIGGER_PK:
4953  /* Update on trigger's PK table */
4954  if (!RI_FKey_pk_upd_check_required(trigger, rel,
4955  oldtup, newtup))
4956  {
4957  /* skip queuing this event */
4958  continue;
4959  }
4960  break;
4961 
4962  case RI_TRIGGER_FK:
4963  /* Update on trigger's FK table */
4964  if (!RI_FKey_fk_upd_check_required(trigger, rel,
4965  oldtup, newtup))
4966  {
4967  /* skip queuing this event */
4968  continue;
4969  }
4970  break;
4971 
4972  case RI_TRIGGER_NONE:
4973  /* Not an FK trigger */
4974  break;
4975  }
4976  }
4977 
4978  /*
4979  * If the trigger is a deferred unique constraint check trigger, only
4980  * queue it if the unique constraint was potentially violated, which
4981  * we know from index insertion time.
4982  */
4983  if (trigger->tgfoid == F_UNIQUE_KEY_RECHECK)
4984  {
4985  if (!list_member_oid(recheckIndexes, trigger->tgconstrindid))
4986  continue; /* Uniqueness definitely not violated */
4987  }
4988 
4989  /*
4990  * Fill in event structure and add it to the current query's queue.
4991  */
4992  new_shared.ats_event =
4993  (event & TRIGGER_EVENT_OPMASK) |
4994  (row_trigger ? TRIGGER_EVENT_ROW : 0) |
4995  (trigger->tgdeferrable ? AFTER_TRIGGER_DEFERRABLE : 0) |
4996  (trigger->tginitdeferred ? AFTER_TRIGGER_INITDEFERRED : 0);
4997  new_shared.ats_tgoid = trigger->tgoid;
4998  new_shared.ats_relid = RelationGetRelid(rel);
4999  new_shared.ats_firing_id = 0;
5000 
5001  afterTriggerAddEvent(&afterTriggers.query_stack[afterTriggers.query_depth],
5002  &new_event, &new_shared);
5003  }
5004 
5005  /*
5006  * Finally, spool any foreign tuple(s). The tuplestore squashes them to
5007  * minimal tuples, so this loses any system columns. The executor lost
5008  * those columns before us, for an unrelated reason, so this is fine.
5009  */
5010  if (fdw_tuplestore)
5011  {
5012  if (oldtup != NULL)
5013  tuplestore_puttuple(fdw_tuplestore, oldtup);
5014  if (newtup != NULL)
5015  tuplestore_puttuple(fdw_tuplestore, newtup);
5016  }
5017 }
5018 
5019 Datum
5021 {
5023 }
void RemoveTriggerById(Oid trigOid)
Definition: trigger.c:1081
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:63
signed short int16
Definition: c.h:252
#define TRIGGER_EVENT_ROW
Definition: trigger.h:56
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:608
#define NIL
Definition: pg_list.h:69
void ExecASDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2193
uint32 CommandId
Definition: c.h:407
TriggerEvent ats_event
Definition: trigger.c:3057
#define Anum_pg_trigger_tgdeferrable
Definition: pg_trigger.h:86
void InstrStopNode(Instrumentation *instr, double nTuples)
Definition: instrument.c:80
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:323
#define FKCONSTR_MATCH_SIMPLE
Definition: parsenodes.h:1819
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:99
JunkFilter * ri_junkFilter
Definition: execnodes.h:342
Definition: fmgr.h:53
void * stringToNode(char *str)
Definition: read.c:38
Relation ri_RelationDesc
Definition: execnodes.h:328
#define TRIGGER_FOR_DELETE(type)
Definition: pg_trigger.h:131
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
Definition: execQual.c:5180
struct AfterTriggerEventDataOneCtid AfterTriggerEventDataOneCtid
bool ExecIRDeleteTriggers(EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple)
Definition: trigger.c:2299
#define NameGetDatum(X)
Definition: postgres.h:603
int RI_FKey_trigger_type(Oid tgfoid)
Definition: ri_triggers.c:3706
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:203
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:46
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate)
Definition: execTuples.c:855
#define AFTER_TRIGGER_FDW_REUSE
Definition: trigger.c:3047
#define TriggerOidIndexId
Definition: indexing.h:235
#define AFTER_TRIGGER_INITDEFERRED
Definition: trigger.h:66
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:2702
int errhint(const char *fmt,...)
Definition: elog.c:987
#define VARDATA(PTR)
Definition: postgres.h:305
void ExecBSDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2143
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
static Tuplestorestate * GetCurrentFDWTuplestore(void)
Definition: trigger.c:3228
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:719
MemoryContext TopTransactionContext
Definition: mcxt.c:48
CommandId es_output_cid
Definition: execnodes.h:368
static void test(void)
bool IsSystemRelation(Relation relation)
Definition: catalog.c:61
char * subname
Definition: parsenodes.h:2531
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:9526
ItemPointerData ate_ctid2
Definition: trigger.c:3069
#define TRIGGER_TYPE_DELETE
Definition: pg_trigger.h:97
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2716
#define RelationGetDescr(relation)
Definition: rel.h:383
#define TRIGGER_EVENT_DELETE
Definition: trigger.h:51
Oid GetUserId(void)
Definition: miscinit.c:282
SetConstraintStateData * SetConstraintState
Definition: trigger.c:3007
TupleTableSlot * es_trig_newtup_slot
Definition: execnodes.h:379
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
Oid tgfoid
Definition: reltrigger.h:28
#define MIN_CHUNK_SIZE
TriggerFlags ate_flags
Definition: trigger.c:3067
HTSU_Result heap_lock_tuple(Relation relation, HeapTuple tuple, CommandId cid, LockTupleMode mode, LockWaitPolicy wait_policy, bool follow_updates, Buffer *buffer, HeapUpdateFailureData *hufd)
Definition: heapam.c:4500
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:232
#define AFTER_TRIGGER_DEFERRABLE
Definition: trigger.h:65
ResourceOwner TopTransactionResourceOwner
Definition: resowner.c:140
void ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2397
#define PointerGetDatum(X)
Definition: postgres.h:564
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:53
Buffer tg_newtuplebuf
Definition: trigger.h:39
bool heap_fetch(Relation relation, Snapshot snapshot, HeapTuple tuple, Buffer *userbuf, bool keep_buf, Relation stats_relation)
Definition: heapam.c:1848
#define Anum_pg_trigger_tgconstraint
Definition: pg_trigger.h:85
#define FKCONSTR_ACTION_NOACTION
Definition: parsenodes.h:1810
#define ProcedureRelationId
Definition: pg_proc.h:33
char fk_matchtype
Definition: parsenodes.h:1855
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
Node * whenClause
Definition: parsenodes.h:2103
#define AFTER_TRIGGER_DONE
Definition: trigger.c:3044
#define TRIGGER_TYPE_MATCHES(type, level, timing, event)
Definition: pg_trigger.h:142
char * pstrdup(const char *in)
Definition: mcxt.c:1168
#define RelationRelationId
Definition: pg_class.h:29
TupleTableSlot * EvalPlanQual(EState *estate, EPQState *epqstate, Relation relation, Index rti, int lockmode, ItemPointer tid, TransactionId priorXmax)
Definition: execMain.c:2159
int2vector * buildint2vector(const int16 *int2s, int n)
Definition: int.c:112
#define FKCONSTR_ACTION_SETDEFAULT
Definition: parsenodes.h:1814
#define CHUNK_DATA_START(cptr)
Definition: trigger.c:3111
ObjectAddress CreateTrigger(CreateTrigStmt *stmt, const char *queryString, Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid, bool isInternal)
Definition: trigger.c:138
SetConstraintTriggerData trigstates[FLEXIBLE_ARRAY_MEMBER]
Definition: trigger.c:3004
struct AfterTriggerSharedData AfterTriggerSharedData
TupleTableSlot * ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot *slot)
Definition: trigger.c:2408
#define Anum_pg_trigger_tgqual
Definition: pg_trigger.h:91
Oid tgoid
Definition: reltrigger.h:25
#define Min(x, y)
Definition: c.h:798
TupleTableSlot * ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2079
bool trig_insert_after_statement
Definition: reltrigger.h:57
struct AfterTriggersData AfterTriggersData
static int MyTriggerDepth
Definition: trigger.c:67
#define AFTER_TRIGGER_TUP_BITS
Definition: trigger.c:3051
void AfterTriggerSetState(ConstraintsSetStmt *stmt)
Definition: trigger.c:4459
#define TRIGGER_CLEAR_TYPE(type)
Definition: pg_trigger.h:114
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define IsolationUsesXactSnapshot()
Definition: xact.h:43
#define Int16GetDatum(X)
Definition: postgres.h:459
#define PG_RETURN_INT32(x)
Definition: fmgr.h:298
#define DEFTRIG_INITALLOC
#define Anum_pg_trigger_tgtype
Definition: pg_trigger.h:80
#define AccessShareLock
Definition: lockdefs.h:36
Instrumentation * ri_TrigInstrument
Definition: execnodes.h:335
#define for_each_event_chunk(eptr, cptr, evtlist)
Definition: trigger.c:3129
#define InvalidBuffer
Definition: buf.h:25
#define gettext_noop(x)
Definition: c.h:139
#define Anum_pg_trigger_tgnargs
Definition: pg_trigger.h:88
struct SetConstraintTriggerData SetConstraintTriggerData
bool tgisinternal
Definition: reltrigger.h:31
Definition: nodes.h:492
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
int namestrcmp(Name name, const char *str)
Definition: name.c:248
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: heapam.c:1262
bool initdeferred
Definition: parsenodes.h:1829
bool trig_update_before_statement
Definition: reltrigger.h:61
AttrNumber varattno
Definition: primnodes.h:153
AlterTableType subtype
Definition: parsenodes.h:1540
static SetConstraintState SetConstraintStateAddItem(SetConstraintState state, Oid tgoid, bool tgisdeferred)
Definition: trigger.c:4429
AfterTriggerEventChunk * tail
Definition: trigger.c:3117
static bool afterTriggerInvokeEvents(AfterTriggerEventList *events, CommandId firing_id, EState *estate, bool delete_ok)
Definition: trigger.c:3756
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:138
static bool afterTriggerCheckState(AfterTriggerShared evtshared)
Definition: trigger.c:3272
struct AfterTriggerEventData AfterTriggerEventData
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3292
void PopActiveSnapshot(void)
Definition: snapmgr.c:731
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
#define heap_close(r, l)
Definition: heapam.h:97
List * pk_attrs
Definition: parsenodes.h:1854
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:548
char * conname
Definition: parsenodes.h:1827
List * list_delete_ptr(List *list, void *datum)
Definition: list.c:590
#define Anum_pg_constraint_conname
char * newname
Definition: parsenodes.h:2533
Form_pg_class rd_rel
Definition: rel.h:83
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1306
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:148
int namestrcpy(Name name, const char *str)
Definition: name.c:217
DestReceiver * None_Receiver
Definition: dest.c:85
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define Anum_pg_trigger_tgisinternal
Definition: pg_trigger.h:82
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:299
#define OidIsValid(objectId)
Definition: c.h:530
#define TRIGGER_EVENT_OPMASK
Definition: trigger.h:54
#define TRIGGER_FIRES_ON_ORIGIN
Definition: trigger.h:107
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:322
#define lsecond(l)
Definition: pg_list.h:114
int SessionReplicationRole
Definition: trigger.c:64
#define ALLOCSET_DEFAULT_MINSIZE
Definition: memutils.h:142
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:141
Index ri_RangeTableIndex
Definition: execnodes.h:327
CommandId * firing_stack
Definition: trigger.c:3205
HeapTuple tg_trigtuple
Definition: trigger.h:35
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1427
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
Definition: catalog.c:73
int errdetail_internal(const char *fmt,...)
Definition: elog.c:900
#define SESSION_REPLICATION_ROLE_ORIGIN
Definition: trigger.h:98
TupleTableSlot * ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple, TupleTableSlot *slot)
Definition: trigger.c:2555
char * schemaname
Definition: primnodes.h:73
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
void * copyObject(const void *from)
Definition: copyfuncs.c:4279
HeapTupleHeader t_data
Definition: htup.h:67
#define TriggerRelidNameIndexId
Definition: indexing.h:233
#define GetTriggerSharedData(evt)
Definition: trigger.c:3092
#define HeapTupleSetOid(tuple, oid)
Definition: htup_details.h:698
#define for_each_event(eptr, cptr)
Definition: trigger.c:3124
#define list_make1(x1)
Definition: pg_list.h:133
#define NAMEDATALEN
void assign_expr_collations(ParseState *pstate, Node *expr)
LockTupleMode
Definition: heapam.h:38
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:384
char * relname
Definition: primnodes.h:74
RangeVar * constrrel
Definition: parsenodes.h:2108
bool trig_insert_instead_row
Definition: reltrigger.h:55
void FreeExecutorState(EState *estate)
Definition: execUtils.c:169
#define GetPerTupleExprContext(estate)
Definition: executor.h:322
FmgrInfo * flinfo
Definition: fmgr.h:71
#define TRIGGER_TYPE_INSTEAD
Definition: pg_trigger.h:100
Datum pg_trigger_depth(PG_FUNCTION_ARGS)
Definition: trigger.c:5020
struct AfterTriggerEventChunk * next
Definition: trigger.c:3104
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define TRIGGER_FOR_ROW(type)
Definition: pg_trigger.h:126
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
void pfree(void *pointer)
Definition: mcxt.c:995
MemoryContext es_query_cxt
Definition: execnodes.h:386
void ExecBSTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2619
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define linitial(l)
Definition: pg_list.h:110
List * make_ands_implicit(Expr *clause)
Definition: clauses.c:375
void AfterTriggerEndXact(bool isCommit)
Definition: trigger.c:4095
#define OPAQUEOID
Definition: pg_type.h:688
char * tgqual
Definition: reltrigger.h:41
char tgenabled
Definition: reltrigger.h:30
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define TRIGGER_EVENT_INSTEAD
Definition: trigger.h:60
Oid tgconstraint
Definition: reltrigger.h:34
#define DatumGetCString(X)
Definition: postgres.h:574
#define TRIGGER_TYPE_AFTER
Definition: pg_trigger.h:108
char * tgname
Definition: reltrigger.h:27
SetConstraintState * state_stack
Definition: trigger.c:3202
bool deferrable
Definition: parsenodes.h:1828
ItemPointerData ate_ctid1
Definition: trigger.c:3076
void InstrStartNode(Instrumentation *instr)
Definition: instrument.c:63
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:160
int16 tgtype
Definition: reltrigger.h:29
bool tgdeferrable
Definition: reltrigger.h:35
#define TRIGGEROID
Definition: pg_type.h:680
ItemPointerData t_self
Definition: htup.h:65
Datum byteain(PG_FUNCTION_ARGS)
Definition: varlena.c:256
void ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, HeapTuple newtuple, List *recheckIndexes)
Definition: trigger.c:2523
#define DatumGetByteaP(X)
Definition: fmgr.h:246
TriggerDesc * trigdesc
Definition: rel.h:89
bool tginitdeferred
Definition: reltrigger.h:36
SetConstraintState state
Definition: trigger.c:3192
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2024
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:715
#define ACL_TRIGGER
Definition: parsenodes.h:69
static void afterTriggerFreeEventList(AfterTriggerEventList *events)
Definition: trigger.c:3435
int location
Definition: primnodes.h:163
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
struct AfterTriggerEventChunk AfterTriggerEventChunk
bool trig_delete_after_row
Definition: reltrigger.h:64
uint32 t_len
Definition: htup.h:64
#define TRIGGER_EVENT_BEFORE
Definition: trigger.h:58
Trigger * triggers
Definition: reltrigger.h:46
void ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:1944
#define NoLock
Definition: lockdefs.h:34
#define TRIGGER_SETT_ROW(type)
Definition: pg_trigger.h:116
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:129
static char * buf
Definition: pg_test_fsync.c:65
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:654
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:219
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3392
Buffer tg_trigtuplebuf
Definition: trigger.h:38
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:873
bool trig_truncate_before_statement
Definition: reltrigger.h:69
#define CStringGetDatum(X)
Definition: postgres.h:586
#define SizeofTriggerEvent(evt)
Definition: trigger.c:3085
void ExecASTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2669
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1352
bool trig_update_after_statement
Definition: reltrigger.h:62
CommandId cmax
Definition: heapam.h:72
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:123
TupleTableSlot * es_trig_oldtup_slot
Definition: execnodes.h:378
bool trig_delete_before_statement
Definition: reltrigger.h:66
bool trig_update_before_row
Definition: reltrigger.h:58
HTSU_Result
Definition: snapshot.h:118
bool ExecQual(List *qual, ExprContext *econtext, bool resultForNull)
Definition: execQual.c:5231
#define RelationGetRelationName(relation)
Definition: rel.h:391
Oid tgconstrrelid
Definition: reltrigger.h:32
Oid funcoids[3]
Definition: trigger.c:828
#define TupIsNull(slot)
Definition: tuptable.h:138
unsigned int uint32
Definition: c.h:265
bool trig_truncate_after_statement
Definition: reltrigger.h:70
Oid t_tableOid
Definition: htup.h:66
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:162
#define TriggerConstraintIndexId
Definition: indexing.h:231
bool trig_insert_after_row
Definition: reltrigger.h:54
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define TRIGGER_TYPE_ROW
Definition: pg_trigger.h:94
const char * p_sourcetext
Definition: parse_node.h:134
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc)
Definition: execTuples.c:202
#define TRIGGER_FOR_BEFORE(type)
Definition: pg_trigger.h:127
static void ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
Definition: trigger.c:833
TupleTableSlot * es_trig_tuple_slot
Definition: execnodes.h:377
static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, int event, bool row_trigger, HeapTuple oldtup, HeapTuple newtup, List *recheckIndexes, Bitmapset *modifiedCols)
Definition: trigger.c:4811
#define BufferGetPage(buffer)
Definition: bufmgr.h:172
#define AFTER_TRIGGER_1CTID
Definition: trigger.c:3049
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
ObjectAddress renametrig(RenameStmt *stmt)
Definition: trigger.c:1253
ObjectType relkind
Definition: parsenodes.h:1460
#define AFTER_TRIGGER_2CTID
Definition: trigger.c:3050
MemoryContext TopMemoryContext
Definition: mcxt.c:43
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:332
void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
EState * CreateExecutorState(void)
Definition: execUtils.c:72
#define FKCONSTR_ACTION_CASCADE
Definition: parsenodes.h:1812
bool trig_update_after_row
Definition: reltrigger.h:59
void EnableDisableTrigger(Relation rel, const char *tgname, char fires_when, bool skip_system)
Definition: trigger.c:1388
List * lappend(List *list, void *datum)
Definition: list.c:128
struct AfterTriggerEventDataZeroCtids AfterTriggerEventDataZeroCtids
#define PRS2_OLD_VARNO
Definition: primnodes.h:145
bool trig_update_instead_row
Definition: reltrigger.h:60
#define Anum_pg_trigger_tgrelid
Definition: pg_trigger.h:77
#define AFTER_TRIGGER_OFFSET
Definition: trigger.c:3042
ResultRelInfo * ExecGetTriggerResultRel(EState *estate, Oid relid)
Definition: execMain.c:1271
List ** ri_TrigWhenExprs
Definition: execnodes.h:334
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
#define WARNING
Definition: elog.h:40
TransactionId xmax
Definition: heapam.h:71
Index varno
Definition: primnodes.h:151
int numtriggers
Definition: reltrigger.h:47
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:232
char ** tgargs
Definition: reltrigger.h:40
char * NameListToString(List *names)
Definition: namespace.c:2912
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:121
void ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple)
Definition: trigger.c:2270
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:316
#define FKCONSTR_MATCH_FULL
Definition: parsenodes.h:1817
Definition: c.h:462
#define Anum_pg_trigger_tgconstrindid
Definition: pg_trigger.h:84
void FreeTriggerDesc(TriggerDesc *trigdesc)
Definition: trigger.c:1742
List * es_trig_target_relations
Definition: execnodes.h:376
#define TextDatumGetCString(d)
Definition: builtins.h:807
bool trig_insert_before_row
Definition: reltrigger.h:53
bool trig_delete_instead_row
Definition: reltrigger.h:65
int16 * tgattr
Definition: reltrigger.h:39
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:436
void * palloc0(Size size)
Definition: mcxt.c:923
AclResult
Definition: acl.h:169
bool RI_FKey_fk_upd_check_required(Trigger *trigger, Relation fk_rel, HeapTuple old_row, HeapTuple new_row)
Definition: ri_triggers.c:2146
#define TRIGGER_DISABLED
Definition: trigger.h:110
uintptr_t Datum
Definition: postgres.h:374
TupleTableSlot * ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
Definition: execJunk.c:262
#define SESSION_REPLICATION_ROLE_REPLICA
Definition: trigger.h:99
static SetConstraintState SetConstraintStateCreate(int numalloc)
Definition: trigger.c:4384
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:990
#define TRIGGER_TYPE_TRUNCATE
Definition: pg_trigger.h:99
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:250
#define SnapshotAny
Definition: tqual.h:28
void ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:1994
#define list_make1_oid(x1)
Definition: pg_list.h:145
Oid MyDatabaseId
Definition: globals.c:76
Oid simple_heap_insert(Relation relation, HeapTuple tup)
Definition: heapam.c:2914
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3529
#define Anum_pg_trigger_tgenabled
Definition: pg_trigger.h:81
Oid GetNewOid(Relation relation)
Definition: catalog.c:284
#define Anum_pg_constraint_connamespace
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1286
RangeVar * relation
Definition: parsenodes.h:2528
void SetFunctionReturnType(Oid funcOid, Oid newRetType)
#define TRIGGER_FOR_TRUNCATE(type)
Definition: pg_trigger.h:133
int work_mem
Definition: globals.c:112
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
Definition: objectaccess.h:147
Trigger * tg_trigger
Definition: trigger.h:37
TupleDesc rd_att
Definition: rel.h:84
HeapTuple tg_newtuple
Definition: trigger.h:36
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:787
CommandId firing_counter
Definition: trigger.c:3191
#define BoolGetDatum(X)
Definition: postgres.h:410
AfterTriggerEventList * events_stack
Definition: trigger.c:3203
Relation heap_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: heapam.c:1314
bool allowSystemTableMods
Definition: globals.c:111
#define TRIGGER_TYPE_UPDATE
Definition: pg_trigger.h:98
#define InvalidOid
Definition: postgres_ext.h:36
Oid fn_oid
Definition: fmgr.h:56
bool initially_valid
Definition: parsenodes.h:1863
void AfterTriggerFireDeferred(void)
Definition: trigger.c:4039
#define INNER_VAR
Definition: primnodes.h:138
static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo, Trigger *trigger, TriggerEvent event, Bitmapset *modifiedCols, HeapTuple oldtup, HeapTuple newtup)
Definition: trigger.c:2824
#define NOTICE
Definition: elog.h:37
#define ConstraintNameNspIndexId
Definition: indexing.h:118
uint32 TriggerEvent
Definition: trigger.h:28
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:758
static void AfterTriggerEnlargeQueryState(void)
Definition: trigger.c:4329
void AfterTriggerBeginQuery(void)
Definition: trigger.c:3939
#define GetUpdatedColumns(relinfo, estate)
Definition: trigger.c:75
#define PG_CATCH()
Definition: elog.h:292
#define Max(x, y)
Definition: c.h:792
#define for_each_chunk(cptr, evtlist)
Definition: trigger.c:3122
#define RI_TRIGGER_FK
Definition: trigger.h:208
#define makeNode(_type_)
Definition: nodes.h:540
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)
Definition: tuplestore.c:1061
FormData_pg_constraint * Form_pg_constraint
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:124
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
char fk_del_action
Definition: parsenodes.h:1857
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
bool ExecBRDeleteTriggers(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple)
Definition: trigger.c:2203
int attnameAttNum(Relation rd, const char *attname, bool sysColOK)
#define NULL
Definition: c.h:226
TriggerDesc * CopyTriggerDesc(TriggerDesc *trigdesc)
Definition: trigger.c:1691
#define Assert(condition)
Definition: c.h:667
#define lfirst(lc)
Definition: pg_list.h:106
#define Anum_pg_trigger_tgargs
Definition: pg_trigger.h:90
LockTupleMode ExecUpdateLockMode(EState *estate, ResultRelInfo *relinfo)
Definition: execMain.c:2038
Definition: regguts.h:313
Definition: value.h:42
#define ShareRowExclusiveLock
Definition: lockdefs.h:42
void CatalogUpdateIndexes(Relation heapRel, HeapTuple heapTuple)
Definition: indexing.c:157
#define Anum_pg_trigger_tgconstrrelid
Definition: pg_trigger.h:83
TriggerEvent tg_event
Definition: trigger.h:33
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
Definition: aclchk.c:4535
bool trig_delete_after_statement
Definition: reltrigger.h:67
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
#define Anum_pg_trigger_tgname
Definition: pg_trigger.h:78
static void afterTriggerAddEvent(AfterTriggerEventList *events, AfterTriggerEvent event, AfterTriggerShared evtshared)
Definition: trigger.c:3318
#define TriggerRelationId
Definition: pg_trigger.h:34
#define TRIGGER_EVENT_TRUNCATE
Definition: trigger.h:53
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define TRIGGER_FOR_INSERT(type)
Definition: pg_trigger.h:130
Oid tgconstrindid
Definition: reltrigger.h:33
size_t Size
Definition: c.h:352
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:112
bool RI_FKey_pk_upd_check_required(Trigger *trigger, Relation pk_rel, HeapTuple old_row, HeapTuple new_row)
Definition: ri_triggers.c:2089
bool trig_insert_before_statement
Definition: reltrigger.h:56
static int list_length(const List *l)
Definition: pg_list.h:89
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:108
void simple_heap_delete(Relation relation, ItemPointer tid)
Definition: heapam.c:3373
Oid get_trigger_oid(Oid relid, const char *trigname, bool missing_ok)
Definition: trigger.c:1158
void simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
Definition: heapam.c:4411
FormData_pg_trigger * Form_pg_trigger
Definition: pg_trigger.h:70
void tuplestore_end(Tuplestorestate *state)
Definition: tuplestore.c:450
bool AfterTriggerPendingOnRel(Oid relid)
Definition: trigger.c:4753
RangeTblEntry * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, Alias *alias, bool inh, bool inFromCl)
#define TRIGGER_TYPE_INSERT
Definition: pg_trigger.h:96
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:80
static void afterTriggerRestoreEventList(AfterTriggerEventList *events, const AfterTriggerEventList *old_events)
Definition: trigger.c:3458
int16 tgnattr
Definition: reltrigger.h:38
#define AFTER_TRIGGER_FDW_FETCH
Definition: trigger.c:3048
#define PG_RE_THROW()
Definition: elog.h:313
HeapTuple ExecMaterializeSlot(TupleTableSlot *slot)
Definition: execTuples.c:728
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:29
CommandId ats_firing_id
Definition: trigger.c:3060
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1024
void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple, List *recheckIndexes)
Definition: trigger.c:2068
const char * name
Definition: encode.c:521
#define TRIGGER_EVENT_UPDATE
Definition: trigger.h:52
#define InvalidAttrNumber
Definition: attnum.h:23
struct AfterTriggerEventData * AfterTriggerEvent
Definition: trigger.c:3063
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define CharGetDatum(X)
Definition: postgres.h:424
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:327
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4411
void AfterTriggerEndSubXact(bool isCommit)
Definition: trigger.c:4215
#define TRIGGER_FIRES_ON_REPLICA
Definition: trigger.h:109
#define DatumGetPointer(X)
Definition: postgres.h:557
List * args
Definition: trigger.c:827
void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize)
Definition: pgstat.c:1569
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1213
struct AfterTriggerEventList AfterTriggerEventList
#define TRIGGER_TYPE_BEFORE
Definition: pg_trigger.h:95
#define TRIGGER_EVENT_INSERT
Definition: trigger.h:50
#define MAX_CHUNK_SIZE
uint32 TriggerFlags
Definition: trigger.c:3040
AfterTriggerEventChunk * head
Definition: trigger.c:3116
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
Definition: parse_func.c:1904
bool IsSubTransaction(void)
Definition: xact.c:4372
static Datum values[MAXATTR]
Definition: bootstrap.c:160
void pgstat_init_function_usage(FunctionCallInfoData *fcinfo, PgStat_FunctionCallUsage *fcu)
Definition: pgstat.c:1497
static void SetTriggerFlags(TriggerDesc *trigdesc, Trigger *trigger)
Definition: trigger.c:1627
FormData_pg_class * Form_pg_class
Definition: pg_class.h:93
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:150
struct SetConstraintStateData SetConstraintStateData
#define AccessExclusiveLock
Definition: lockdefs.h:46
void ExecBSUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2344
void RelationBuildTriggers(Relation relation)
Definition: trigger.c:1493
#define RI_TRIGGER_PK
Definition: trigger.h:207
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:135
void AfterTriggerEndQuery(EState *estate)
Definition: trigger.c:3959
static HeapTuple GetTupleForTrigger(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tid, LockTupleMode lockmode, TupleTableSlot **newSlot)
Definition: trigger.c:2680
const ObjectAddress InvalidObjectAddress
static void RangeVarCallbackForRenameTrigger(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: trigger.c:1208
void * palloc(Size size)
Definition: mcxt.c:894
int errmsg(const char *fmt,...)
Definition: elog.c:797
NodeTag type
Definition: trigger.h:32
MemoryContext event_cxt
Definition: trigger.c:3198
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:752
RangeVar * relation
Definition: parsenodes.h:1458
#define ACL_EXECUTE
Definition: parsenodes.h:70
#define RELKIND_VIEW
Definition: pg_class.h:160
void list_free(List *list)
Definition: list.c:1133
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4435
#define ALLOCSET_DEFAULT_INITSIZE
Definition: memutils.h:143
int i
struct SetConstraintTriggerData * SetConstraintTrigger
Definition: trigger.c:2986
RangeVar * relation
Definition: parsenodes.h:2094
int16 tgnargs
Definition: reltrigger.h:37
#define AFTER_TRIGGER_IN_PROGRESS
Definition: trigger.c:3045
#define NameStr(name)
Definition: c.h:494
static bool afterTriggerMarkEvents(AfterTriggerEventList *events, AfterTriggerEventList *move_list, bool immediate_only)
Definition: trigger.c:3684
void ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
Definition: rewriteManip.c:607
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:100
#define CStringGetTextDatum(s)
Definition: builtins.h:806
char * nodeToString(const void *obj)
Definition: outfuncs.c:3865
ConstrType contype
Definition: parsenodes.h:1824
Tuplestorestate ** fdw_tuplestores
Definition: trigger.c:3196
void * arg
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1116
#define FKCONSTR_ACTION_RESTRICT
Definition: parsenodes.h:1811
void AfterTriggerBeginXact(void)
Definition: trigger.c:3903
#define lthird(l)
Definition: pg_list.h:118
AfterTriggerEventList events
Definition: trigger.c:3193
Definition: c.h:434
#define PG_FUNCTION_ARGS
Definition: fmgr.h:150
#define ALLOCSET_DEFAULT_MAXSIZE
Definition: memutils.h:144
#define ConstraintRelationId
Definition: pg_constraint.h:29
AfterTriggerEventList * query_stack
Definition: trigger.c:3195
TupleTableSlot * ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2004
void AfterTriggerBeginSubXact(void)
Definition: trigger.c:4147
ItemPointerData ctid
Definition: heapam.h:70
#define elog
Definition: elog.h:218
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:70
#define CONSTRAINT_TRIGGER
Datum nameout(PG_FUNCTION_ARGS)
Definition: name.c:69
static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata, int tgindx, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context)
Definition: trigger.c:1862
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105
#define TRIGGER_TYPE_STATEMENT
Definition: pg_trigger.h:103
#define PG_TRY()
Definition: elog.h:283
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:74
ItemPointerData ate_ctid1
Definition: trigger.c:3068
RangeVar * pktable
Definition: parsenodes.h:1852
#define RELKIND_RELATION
Definition: pg_class.h:156
#define FKCONSTR_ACTION_SETNULL
Definition: parsenodes.h:1813
#define RI_TRIGGER_NONE
Definition: trigger.h:209
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:34
Definition: pg_list.h:45
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1694
int Buffer
Definition: buf.h:23
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:419
#define TRIGGER_FIRED_BY_UPDATE(event)
Definition: trigger.h:74
List * fetch_search_path(bool includeImplicit)
Definition: namespace.c:4028
bool skip_validation
Definition: parsenodes.h:1862
#define _(x)
Definition: elog.c:83
static AfterTriggersData afterTriggers
Definition: trigger.c:3209
#define RelationGetRelid(relation)
Definition: rel.h:371
Oid CreateConstraintEntry(const char *constraintName, Oid constraintNamespace, char constraintType, bool isDeferrable, bool isDeferred, bool isValidated, Oid relId, const int16 *constraintKey, int constraintNKeys, Oid domainId, Oid indexRelId, Oid foreignRelId, const int16 *foreignKey, const Oid *pfEqOp, const Oid *ppEqOp, const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, char foreignMatchType, const Oid *exclOp, Node *conExpr, const char *conBin, const char *conSrc, bool conIsLocal, int conInhCount, bool conNoInherit, bool is_internal)
Definition: pg_constraint.c:49
#define OUTER_VAR
Definition: primnodes.h:139
long val
Definition: informix.c:689
List * fk_attrs
Definition: parsenodes.h:1853
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
Definition: execIndexing.c:224
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:419
char * catalogname
Definition: primnodes.h:72
#define PG_END_TRY()
Definition: elog.h:299
#define PRS2_NEW_VARNO
Definition: primnodes.h:146
#define BTEqualStrategyNumber
Definition: stratnum.h:31
struct AfterTriggerSharedData * AfterTriggerShared
Definition: trigger.c:3053
#define offsetof(type, field)
Definition: c.h:547
static void AfterTriggerExecute(AfterTriggerEvent event, Relation rel, TriggerDesc *trigdesc, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context, TupleTableSlot *trig_tuple_slot1, TupleTableSlot *trig_tuple_slot2)
Definition: trigger.c:3513
char fk_upd_action
Definition: parsenodes.h:1856
#define PageGetItem(page, itemId)
Definition: bufpage.h:337
FmgrInfo * ri_TrigFunctions
Definition: execnodes.h:333
#define Anum_pg_trigger_tgfoid
Definition: pg_trigger.h:79
Pointer Page
Definition: bufpage.h:74
#define Anum_pg_trigger_tginitdeferred
Definition: pg_trigger.h:87
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define Anum_pg_trigger_tgattr
Definition: pg_trigger.h:89
#define ItemPointerCopy(fromPointer, toPointer)
Definition: itemptr.h:124
bool trig_delete_before_row
Definition: reltrigger.h:63
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void ProcessUtility(Node *parsetree, const char *queryString, ProcessUtilityContext context, ParamListInfo params, DestReceiver *dest, char *completionTag)
Definition: utility.c:317
#define Natts_pg_trigger
Definition: pg_trigger.h:76
#define TRIGGER_FOR_INSTEAD(type)
Definition: pg_trigger.h:129
Relation tg_relation
Definition: trigger.h:34
#define RelationGetNamespace(relation)
Definition: rel.h:398
static SetConstraintState SetConstraintStateCopy(SetConstraintState state)
Definition: trigger.c:4409
List * p_rtable
Definition: parse_node.h:135