PostgreSQL Source Code  git master
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-2024, 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/htup_details.h"
18 #include "access/relation.h"
19 #include "access/sysattr.h"
20 #include "access/table.h"
21 #include "access/tableam.h"
22 #include "access/xact.h"
23 #include "catalog/catalog.h"
24 #include "catalog/dependency.h"
25 #include "catalog/indexing.h"
26 #include "catalog/objectaccess.h"
27 #include "catalog/partition.h"
28 #include "catalog/pg_constraint.h"
29 #include "catalog/pg_inherits.h"
30 #include "catalog/pg_proc.h"
31 #include "catalog/pg_trigger.h"
32 #include "catalog/pg_type.h"
33 #include "commands/dbcommands.h"
34 #include "commands/trigger.h"
35 #include "executor/executor.h"
36 #include "miscadmin.h"
37 #include "nodes/bitmapset.h"
38 #include "nodes/makefuncs.h"
39 #include "optimizer/optimizer.h"
40 #include "parser/parse_clause.h"
41 #include "parser/parse_collate.h"
42 #include "parser/parse_func.h"
43 #include "parser/parse_relation.h"
44 #include "partitioning/partdesc.h"
45 #include "pgstat.h"
46 #include "rewrite/rewriteManip.h"
47 #include "storage/lmgr.h"
48 #include "utils/acl.h"
49 #include "utils/builtins.h"
50 #include "utils/fmgroids.h"
51 #include "utils/guc_hooks.h"
52 #include "utils/inval.h"
53 #include "utils/lsyscache.h"
54 #include "utils/memutils.h"
55 #include "utils/plancache.h"
56 #include "utils/rel.h"
57 #include "utils/snapmgr.h"
58 #include "utils/syscache.h"
59 #include "utils/tuplestore.h"
60 
61 
62 /* GUC variables */
64 
65 /* How many levels deep into trigger execution are we? */
66 static int MyTriggerDepth = 0;
67 
68 /* Local function prototypes */
69 static void renametrig_internal(Relation tgrel, Relation targetrel,
70  HeapTuple trigtup, const char *newname,
71  const char *expected_name);
72 static void renametrig_partition(Relation tgrel, Oid partitionId,
73  Oid parentTriggerOid, const char *newname,
74  const char *expected_name);
75 static void SetTriggerFlags(TriggerDesc *trigdesc, Trigger *trigger);
76 static bool GetTupleForTrigger(EState *estate,
77  EPQState *epqstate,
78  ResultRelInfo *relinfo,
79  ItemPointer tid,
80  LockTupleMode lockmode,
81  TupleTableSlot *oldslot,
82  TupleTableSlot **epqslot,
83  TM_Result *tmresultp,
84  TM_FailureData *tmfdp);
85 static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
86  Trigger *trigger, TriggerEvent event,
87  Bitmapset *modifiedCols,
88  TupleTableSlot *oldslot, TupleTableSlot *newslot);
90  int tgindx,
91  FmgrInfo *finfo,
92  Instrumentation *instr,
93  MemoryContext per_tuple_context);
94 static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
95  ResultRelInfo *src_partinfo,
96  ResultRelInfo *dst_partinfo,
97  int event, bool row_trigger,
98  TupleTableSlot *oldslot, TupleTableSlot *newslot,
99  List *recheckIndexes, Bitmapset *modifiedCols,
100  TransitionCaptureState *transition_capture,
101  bool is_crosspart_update);
102 static void AfterTriggerEnlargeQueryState(void);
103 static bool before_stmt_triggers_fired(Oid relid, CmdType cmdType);
104 
105 
106 /*
107  * Create a trigger. Returns the address of the created trigger.
108  *
109  * queryString is the source text of the CREATE TRIGGER command.
110  * This must be supplied if a whenClause is specified, else it can be NULL.
111  *
112  * relOid, if nonzero, is the relation on which the trigger should be
113  * created. If zero, the name provided in the statement will be looked up.
114  *
115  * refRelOid, if nonzero, is the relation to which the constraint trigger
116  * refers. If zero, the constraint relation name provided in the statement
117  * will be looked up as needed.
118  *
119  * constraintOid, if nonzero, says that this trigger is being created
120  * internally to implement that constraint. A suitable pg_depend entry will
121  * be made to link the trigger to that constraint. constraintOid is zero when
122  * executing a user-entered CREATE TRIGGER command. (For CREATE CONSTRAINT
123  * TRIGGER, we build a pg_constraint entry internally.)
124  *
125  * indexOid, if nonzero, is the OID of an index associated with the constraint.
126  * We do nothing with this except store it into pg_trigger.tgconstrindid;
127  * but when creating a trigger for a deferrable unique constraint on a
128  * partitioned table, its children are looked up. Note we don't cope with
129  * invalid indexes in that case.
130  *
131  * funcoid, if nonzero, is the OID of the function to invoke. When this is
132  * given, stmt->funcname is ignored.
133  *
134  * parentTriggerOid, if nonzero, is a trigger that begets this one; so that
135  * if that trigger is dropped, this one should be too. There are two cases
136  * when a nonzero value is passed for this: 1) when this function recurses to
137  * create the trigger on partitions, 2) when creating child foreign key
138  * triggers; see CreateFKCheckTrigger() and createForeignKeyActionTriggers().
139  *
140  * If whenClause is passed, it is an already-transformed expression for
141  * WHEN. In this case, we ignore any that may come in stmt->whenClause.
142  *
143  * If isInternal is true then this is an internally-generated trigger.
144  * This argument sets the tgisinternal field of the pg_trigger entry, and
145  * if true causes us to modify the given trigger name to ensure uniqueness.
146  *
147  * When isInternal is not true we require ACL_TRIGGER permissions on the
148  * relation, as well as ACL_EXECUTE on the trigger function. For internal
149  * triggers the caller must apply any required permission checks.
150  *
151  * When called on partitioned tables, this function recurses to create the
152  * trigger on all the partitions, except if isInternal is true, in which
153  * case caller is expected to execute recursion on its own. in_partition
154  * indicates such a recursive call; outside callers should pass "false"
155  * (but see CloneRowTriggersToPartition).
156  */
158 CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
159  Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid,
160  Oid funcoid, Oid parentTriggerOid, Node *whenClause,
161  bool isInternal, bool in_partition)
162 {
163  return
164  CreateTriggerFiringOn(stmt, queryString, relOid, refRelOid,
165  constraintOid, indexOid, funcoid,
166  parentTriggerOid, whenClause, isInternal,
167  in_partition, TRIGGER_FIRES_ON_ORIGIN);
168 }
169 
170 /*
171  * Like the above; additionally the firing condition
172  * (always/origin/replica/disabled) can be specified.
173  */
175 CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString,
176  Oid relOid, Oid refRelOid, Oid constraintOid,
177  Oid indexOid, Oid funcoid, Oid parentTriggerOid,
178  Node *whenClause, bool isInternal, bool in_partition,
179  char trigger_fires_when)
180 {
181  int16 tgtype;
182  int ncolumns;
183  int16 *columns;
184  int2vector *tgattr;
185  List *whenRtable;
186  char *qual;
187  Datum values[Natts_pg_trigger];
188  bool nulls[Natts_pg_trigger];
189  Relation rel;
190  AclResult aclresult;
191  Relation tgrel;
192  Relation pgrel;
193  HeapTuple tuple = NULL;
194  Oid funcrettype;
195  Oid trigoid = InvalidOid;
196  char internaltrigname[NAMEDATALEN];
197  char *trigname;
198  Oid constrrelid = InvalidOid;
199  ObjectAddress myself,
200  referenced;
201  char *oldtablename = NULL;
202  char *newtablename = NULL;
203  bool partition_recurse;
204  bool trigger_exists = false;
205  Oid existing_constraint_oid = InvalidOid;
206  bool existing_isInternal = false;
207  bool existing_isClone = false;
208 
209  if (OidIsValid(relOid))
210  rel = table_open(relOid, ShareRowExclusiveLock);
211  else
212  rel = table_openrv(stmt->relation, ShareRowExclusiveLock);
213 
214  /*
215  * Triggers must be on tables or views, and there are additional
216  * relation-type-specific restrictions.
217  */
218  if (rel->rd_rel->relkind == RELKIND_RELATION)
219  {
220  /* Tables can't have INSTEAD OF triggers */
221  if (stmt->timing != TRIGGER_TYPE_BEFORE &&
222  stmt->timing != TRIGGER_TYPE_AFTER)
223  ereport(ERROR,
224  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
225  errmsg("\"%s\" is a table",
227  errdetail("Tables cannot have INSTEAD OF triggers.")));
228  }
229  else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
230  {
231  /* Partitioned tables can't have INSTEAD OF triggers */
232  if (stmt->timing != TRIGGER_TYPE_BEFORE &&
233  stmt->timing != TRIGGER_TYPE_AFTER)
234  ereport(ERROR,
235  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
236  errmsg("\"%s\" is a table",
238  errdetail("Tables cannot have INSTEAD OF triggers.")));
239 
240  /*
241  * FOR EACH ROW triggers have further restrictions
242  */
243  if (stmt->row)
244  {
245  /*
246  * Disallow use of transition tables.
247  *
248  * Note that we have another restriction about transition tables
249  * in partitions; search for 'has_superclass' below for an
250  * explanation. The check here is just to protect from the fact
251  * that if we allowed it here, the creation would succeed for a
252  * partitioned table with no partitions, but would be blocked by
253  * the other restriction when the first partition was created,
254  * which is very unfriendly behavior.
255  */
256  if (stmt->transitionRels != NIL)
257  ereport(ERROR,
258  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
259  errmsg("\"%s\" is a partitioned table",
261  errdetail("ROW triggers with transition tables are not supported on partitioned tables.")));
262  }
263  }
264  else if (rel->rd_rel->relkind == RELKIND_VIEW)
265  {
266  /*
267  * Views can have INSTEAD OF triggers (which we check below are
268  * row-level), or statement-level BEFORE/AFTER triggers.
269  */
270  if (stmt->timing != TRIGGER_TYPE_INSTEAD && stmt->row)
271  ereport(ERROR,
272  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
273  errmsg("\"%s\" is a view",
275  errdetail("Views cannot have row-level BEFORE or AFTER triggers.")));
276  /* Disallow TRUNCATE triggers on VIEWs */
277  if (TRIGGER_FOR_TRUNCATE(stmt->events))
278  ereport(ERROR,
279  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
280  errmsg("\"%s\" is a view",
282  errdetail("Views cannot have TRUNCATE triggers.")));
283  }
284  else if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
285  {
286  if (stmt->timing != TRIGGER_TYPE_BEFORE &&
287  stmt->timing != TRIGGER_TYPE_AFTER)
288  ereport(ERROR,
289  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
290  errmsg("\"%s\" is a foreign table",
292  errdetail("Foreign tables cannot have INSTEAD OF triggers.")));
293 
294  /*
295  * We disallow constraint triggers to protect the assumption that
296  * triggers on FKs can't be deferred. See notes with AfterTriggers
297  * data structures, below.
298  */
299  if (stmt->isconstraint)
300  ereport(ERROR,
301  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
302  errmsg("\"%s\" is a foreign table",
304  errdetail("Foreign tables cannot have constraint triggers.")));
305  }
306  else
307  ereport(ERROR,
308  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
309  errmsg("relation \"%s\" cannot have triggers",
311  errdetail_relkind_not_supported(rel->rd_rel->relkind)));
312 
314  ereport(ERROR,
315  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
316  errmsg("permission denied: \"%s\" is a system catalog",
317  RelationGetRelationName(rel))));
318 
319  if (stmt->isconstraint)
320  {
321  /*
322  * We must take a lock on the target relation to protect against
323  * concurrent drop. It's not clear that AccessShareLock is strong
324  * enough, but we certainly need at least that much... otherwise, we
325  * might end up creating a pg_constraint entry referencing a
326  * nonexistent table.
327  */
328  if (OidIsValid(refRelOid))
329  {
330  LockRelationOid(refRelOid, AccessShareLock);
331  constrrelid = refRelOid;
332  }
333  else if (stmt->constrrel != NULL)
334  constrrelid = RangeVarGetRelid(stmt->constrrel, AccessShareLock,
335  false);
336  }
337 
338  /* permission checks */
339  if (!isInternal)
340  {
341  aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
342  ACL_TRIGGER);
343  if (aclresult != ACLCHECK_OK)
344  aclcheck_error(aclresult, get_relkind_objtype(rel->rd_rel->relkind),
346 
347  if (OidIsValid(constrrelid))
348  {
349  aclresult = pg_class_aclcheck(constrrelid, GetUserId(),
350  ACL_TRIGGER);
351  if (aclresult != ACLCHECK_OK)
352  aclcheck_error(aclresult, get_relkind_objtype(get_rel_relkind(constrrelid)),
353  get_rel_name(constrrelid));
354  }
355  }
356 
357  /*
358  * When called on a partitioned table to create a FOR EACH ROW trigger
359  * that's not internal, we create one trigger for each partition, too.
360  *
361  * For that, we'd better hold lock on all of them ahead of time.
362  */
363  partition_recurse = !isInternal && stmt->row &&
364  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE;
365  if (partition_recurse)
367  ShareRowExclusiveLock, NULL));
368 
369  /* Compute tgtype */
370  TRIGGER_CLEAR_TYPE(tgtype);
371  if (stmt->row)
372  TRIGGER_SETT_ROW(tgtype);
373  tgtype |= stmt->timing;
374  tgtype |= stmt->events;
375 
376  /* Disallow ROW-level TRUNCATE triggers */
377  if (TRIGGER_FOR_ROW(tgtype) && TRIGGER_FOR_TRUNCATE(tgtype))
378  ereport(ERROR,
379  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
380  errmsg("TRUNCATE FOR EACH ROW triggers are not supported")));
381 
382  /* INSTEAD triggers must be row-level, and can't have WHEN or columns */
383  if (TRIGGER_FOR_INSTEAD(tgtype))
384  {
385  if (!TRIGGER_FOR_ROW(tgtype))
386  ereport(ERROR,
387  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
388  errmsg("INSTEAD OF triggers must be FOR EACH ROW")));
389  if (stmt->whenClause)
390  ereport(ERROR,
391  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
392  errmsg("INSTEAD OF triggers cannot have WHEN conditions")));
393  if (stmt->columns != NIL)
394  ereport(ERROR,
395  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
396  errmsg("INSTEAD OF triggers cannot have column lists")));
397  }
398 
399  /*
400  * We don't yet support naming ROW transition variables, but the parser
401  * recognizes the syntax so we can give a nicer message here.
402  *
403  * Per standard, REFERENCING TABLE names are only allowed on AFTER
404  * triggers. Per standard, REFERENCING ROW names are not allowed with FOR
405  * EACH STATEMENT. Per standard, each OLD/NEW, ROW/TABLE permutation is
406  * only allowed once. Per standard, OLD may not be specified when
407  * creating a trigger only for INSERT, and NEW may not be specified when
408  * creating a trigger only for DELETE.
409  *
410  * Notice that the standard allows an AFTER ... FOR EACH ROW trigger to
411  * reference both ROW and TABLE transition data.
412  */
413  if (stmt->transitionRels != NIL)
414  {
415  List *varList = stmt->transitionRels;
416  ListCell *lc;
417 
418  foreach(lc, varList)
419  {
421 
422  if (!(tt->isTable))
423  ereport(ERROR,
424  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
425  errmsg("ROW variable naming in the REFERENCING clause is not supported"),
426  errhint("Use OLD TABLE or NEW TABLE for naming transition tables.")));
427 
428  /*
429  * Because of the above test, we omit further ROW-related testing
430  * below. If we later allow naming OLD and NEW ROW variables,
431  * adjustments will be needed below.
432  */
433 
434  if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
435  ereport(ERROR,
436  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
437  errmsg("\"%s\" is a foreign table",
439  errdetail("Triggers on foreign tables cannot have transition tables.")));
440 
441  if (rel->rd_rel->relkind == RELKIND_VIEW)
442  ereport(ERROR,
443  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
444  errmsg("\"%s\" is a view",
446  errdetail("Triggers on views cannot have transition tables.")));
447 
448  /*
449  * We currently don't allow row-level triggers with transition
450  * tables on partition or inheritance children. Such triggers
451  * would somehow need to see tuples converted to the format of the
452  * table they're attached to, and it's not clear which subset of
453  * tuples each child should see. See also the prohibitions in
454  * ATExecAttachPartition() and ATExecAddInherit().
455  */
456  if (TRIGGER_FOR_ROW(tgtype) && has_superclass(rel->rd_id))
457  {
458  /* Use appropriate error message. */
459  if (rel->rd_rel->relispartition)
460  ereport(ERROR,
461  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
462  errmsg("ROW triggers with transition tables are not supported on partitions")));
463  else
464  ereport(ERROR,
465  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
466  errmsg("ROW triggers with transition tables are not supported on inheritance children")));
467  }
468 
469  if (stmt->timing != TRIGGER_TYPE_AFTER)
470  ereport(ERROR,
471  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
472  errmsg("transition table name can only be specified for an AFTER trigger")));
473 
474  if (TRIGGER_FOR_TRUNCATE(tgtype))
475  ereport(ERROR,
476  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
477  errmsg("TRUNCATE triggers with transition tables are not supported")));
478 
479  /*
480  * We currently don't allow multi-event triggers ("INSERT OR
481  * UPDATE") with transition tables, because it's not clear how to
482  * handle INSERT ... ON CONFLICT statements which can fire both
483  * INSERT and UPDATE triggers. We show the inserted tuples to
484  * INSERT triggers and the updated tuples to UPDATE triggers, but
485  * it's not yet clear what INSERT OR UPDATE trigger should see.
486  * This restriction could be lifted if we can decide on the right
487  * semantics in a later release.
488  */
489  if (((TRIGGER_FOR_INSERT(tgtype) ? 1 : 0) +
490  (TRIGGER_FOR_UPDATE(tgtype) ? 1 : 0) +
491  (TRIGGER_FOR_DELETE(tgtype) ? 1 : 0)) != 1)
492  ereport(ERROR,
493  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
494  errmsg("transition tables cannot be specified for triggers with more than one event")));
495 
496  /*
497  * We currently don't allow column-specific triggers with
498  * transition tables. Per spec, that seems to require
499  * accumulating separate transition tables for each combination of
500  * columns, which is a lot of work for a rather marginal feature.
501  */
502  if (stmt->columns != NIL)
503  ereport(ERROR,
504  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
505  errmsg("transition tables cannot be specified for triggers with column lists")));
506 
507  /*
508  * We disallow constraint triggers with transition tables, to
509  * protect the assumption that such triggers can't be deferred.
510  * See notes with AfterTriggers data structures, below.
511  *
512  * Currently this is enforced by the grammar, so just Assert here.
513  */
514  Assert(!stmt->isconstraint);
515 
516  if (tt->isNew)
517  {
518  if (!(TRIGGER_FOR_INSERT(tgtype) ||
519  TRIGGER_FOR_UPDATE(tgtype)))
520  ereport(ERROR,
521  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
522  errmsg("NEW TABLE can only be specified for an INSERT or UPDATE trigger")));
523 
524  if (newtablename != NULL)
525  ereport(ERROR,
526  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
527  errmsg("NEW TABLE cannot be specified multiple times")));
528 
529  newtablename = tt->name;
530  }
531  else
532  {
533  if (!(TRIGGER_FOR_DELETE(tgtype) ||
534  TRIGGER_FOR_UPDATE(tgtype)))
535  ereport(ERROR,
536  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
537  errmsg("OLD TABLE can only be specified for a DELETE or UPDATE trigger")));
538 
539  if (oldtablename != NULL)
540  ereport(ERROR,
541  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
542  errmsg("OLD TABLE cannot be specified multiple times")));
543 
544  oldtablename = tt->name;
545  }
546  }
547 
548  if (newtablename != NULL && oldtablename != NULL &&
549  strcmp(newtablename, oldtablename) == 0)
550  ereport(ERROR,
551  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
552  errmsg("OLD TABLE name and NEW TABLE name cannot be the same")));
553  }
554 
555  /*
556  * Parse the WHEN clause, if any and we weren't passed an already
557  * transformed one.
558  *
559  * Note that as a side effect, we fill whenRtable when parsing. If we got
560  * an already parsed clause, this does not occur, which is what we want --
561  * no point in adding redundant dependencies below.
562  */
563  if (!whenClause && stmt->whenClause)
564  {
565  ParseState *pstate;
566  ParseNamespaceItem *nsitem;
567  List *varList;
568  ListCell *lc;
569 
570  /* Set up a pstate to parse with */
571  pstate = make_parsestate(NULL);
572  pstate->p_sourcetext = queryString;
573 
574  /*
575  * Set up nsitems for OLD and NEW references.
576  *
577  * 'OLD' must always have varno equal to 1 and 'NEW' equal to 2.
578  */
579  nsitem = addRangeTableEntryForRelation(pstate, rel,
581  makeAlias("old", NIL),
582  false, false);
583  addNSItemToQuery(pstate, nsitem, false, true, true);
584  nsitem = addRangeTableEntryForRelation(pstate, rel,
586  makeAlias("new", NIL),
587  false, false);
588  addNSItemToQuery(pstate, nsitem, false, true, true);
589 
590  /* Transform expression. Copy to be sure we don't modify original */
591  whenClause = transformWhereClause(pstate,
592  copyObject(stmt->whenClause),
594  "WHEN");
595  /* we have to fix its collations too */
596  assign_expr_collations(pstate, whenClause);
597 
598  /*
599  * Check for disallowed references to OLD/NEW.
600  *
601  * NB: pull_var_clause is okay here only because we don't allow
602  * subselects in WHEN clauses; it would fail to examine the contents
603  * of subselects.
604  */
605  varList = pull_var_clause(whenClause, 0);
606  foreach(lc, varList)
607  {
608  Var *var = (Var *) lfirst(lc);
609 
610  switch (var->varno)
611  {
612  case PRS2_OLD_VARNO:
613  if (!TRIGGER_FOR_ROW(tgtype))
614  ereport(ERROR,
615  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
616  errmsg("statement trigger's WHEN condition cannot reference column values"),
617  parser_errposition(pstate, var->location)));
618  if (TRIGGER_FOR_INSERT(tgtype))
619  ereport(ERROR,
620  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
621  errmsg("INSERT trigger's WHEN condition cannot reference OLD values"),
622  parser_errposition(pstate, var->location)));
623  /* system columns are okay here */
624  break;
625  case PRS2_NEW_VARNO:
626  if (!TRIGGER_FOR_ROW(tgtype))
627  ereport(ERROR,
628  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
629  errmsg("statement trigger's WHEN condition cannot reference column values"),
630  parser_errposition(pstate, var->location)));
631  if (TRIGGER_FOR_DELETE(tgtype))
632  ereport(ERROR,
633  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
634  errmsg("DELETE trigger's WHEN condition cannot reference NEW values"),
635  parser_errposition(pstate, var->location)));
636  if (var->varattno < 0 && TRIGGER_FOR_BEFORE(tgtype))
637  ereport(ERROR,
638  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
639  errmsg("BEFORE trigger's WHEN condition cannot reference NEW system columns"),
640  parser_errposition(pstate, var->location)));
641  if (TRIGGER_FOR_BEFORE(tgtype) &&
642  var->varattno == 0 &&
643  RelationGetDescr(rel)->constr &&
644  RelationGetDescr(rel)->constr->has_generated_stored)
645  ereport(ERROR,
646  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
647  errmsg("BEFORE trigger's WHEN condition cannot reference NEW generated columns"),
648  errdetail("A whole-row reference is used and the table contains generated columns."),
649  parser_errposition(pstate, var->location)));
650  if (TRIGGER_FOR_BEFORE(tgtype) &&
651  var->varattno > 0 &&
652  TupleDescAttr(RelationGetDescr(rel), var->varattno - 1)->attgenerated)
653  ereport(ERROR,
654  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
655  errmsg("BEFORE trigger's WHEN condition cannot reference NEW generated columns"),
656  errdetail("Column \"%s\" is a generated column.",
657  NameStr(TupleDescAttr(RelationGetDescr(rel), var->varattno - 1)->attname)),
658  parser_errposition(pstate, var->location)));
659  break;
660  default:
661  /* can't happen without add_missing_from, so just elog */
662  elog(ERROR, "trigger WHEN condition cannot contain references to other relations");
663  break;
664  }
665  }
666 
667  /* we'll need the rtable for recordDependencyOnExpr */
668  whenRtable = pstate->p_rtable;
669 
670  qual = nodeToString(whenClause);
671 
672  free_parsestate(pstate);
673  }
674  else if (!whenClause)
675  {
676  whenClause = NULL;
677  whenRtable = NIL;
678  qual = NULL;
679  }
680  else
681  {
682  qual = nodeToString(whenClause);
683  whenRtable = NIL;
684  }
685 
686  /*
687  * Find and validate the trigger function.
688  */
689  if (!OidIsValid(funcoid))
690  funcoid = LookupFuncName(stmt->funcname, 0, NULL, false);
691  if (!isInternal)
692  {
693  aclresult = object_aclcheck(ProcedureRelationId, funcoid, GetUserId(), ACL_EXECUTE);
694  if (aclresult != ACLCHECK_OK)
695  aclcheck_error(aclresult, OBJECT_FUNCTION,
696  NameListToString(stmt->funcname));
697  }
698  funcrettype = get_func_rettype(funcoid);
699  if (funcrettype != TRIGGEROID)
700  ereport(ERROR,
701  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
702  errmsg("function %s must return type %s",
703  NameListToString(stmt->funcname), "trigger")));
704 
705  /*
706  * Scan pg_trigger to see if there is already a trigger of the same name.
707  * Skip this for internally generated triggers, since we'll modify the
708  * name to be unique below.
709  *
710  * NOTE that this is cool only because we have ShareRowExclusiveLock on
711  * the relation, so the trigger set won't be changing underneath us.
712  */
713  tgrel = table_open(TriggerRelationId, RowExclusiveLock);
714  if (!isInternal)
715  {
716  ScanKeyData skeys[2];
717  SysScanDesc tgscan;
718 
719  ScanKeyInit(&skeys[0],
720  Anum_pg_trigger_tgrelid,
721  BTEqualStrategyNumber, F_OIDEQ,
723 
724  ScanKeyInit(&skeys[1],
725  Anum_pg_trigger_tgname,
726  BTEqualStrategyNumber, F_NAMEEQ,
727  CStringGetDatum(stmt->trigname));
728 
729  tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
730  NULL, 2, skeys);
731 
732  /* There should be at most one matching tuple */
733  if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
734  {
735  Form_pg_trigger oldtrigger = (Form_pg_trigger) GETSTRUCT(tuple);
736 
737  trigoid = oldtrigger->oid;
738  existing_constraint_oid = oldtrigger->tgconstraint;
739  existing_isInternal = oldtrigger->tgisinternal;
740  existing_isClone = OidIsValid(oldtrigger->tgparentid);
741  trigger_exists = true;
742  /* copy the tuple to use in CatalogTupleUpdate() */
743  tuple = heap_copytuple(tuple);
744  }
745  systable_endscan(tgscan);
746  }
747 
748  if (!trigger_exists)
749  {
750  /* Generate the OID for the new trigger. */
751  trigoid = GetNewOidWithIndex(tgrel, TriggerOidIndexId,
752  Anum_pg_trigger_oid);
753  }
754  else
755  {
756  /*
757  * If OR REPLACE was specified, we'll replace the old trigger;
758  * otherwise complain about the duplicate name.
759  */
760  if (!stmt->replace)
761  ereport(ERROR,
763  errmsg("trigger \"%s\" for relation \"%s\" already exists",
764  stmt->trigname, RelationGetRelationName(rel))));
765 
766  /*
767  * An internal trigger or a child trigger (isClone) cannot be replaced
768  * by a user-defined trigger. However, skip this test when
769  * in_partition, because then we're recursing from a partitioned table
770  * and the check was made at the parent level.
771  */
772  if ((existing_isInternal || existing_isClone) &&
773  !isInternal && !in_partition)
774  ereport(ERROR,
776  errmsg("trigger \"%s\" for relation \"%s\" is an internal or a child trigger",
777  stmt->trigname, RelationGetRelationName(rel))));
778 
779  /*
780  * It is not allowed to replace with a constraint trigger; gram.y
781  * should have enforced this already.
782  */
783  Assert(!stmt->isconstraint);
784 
785  /*
786  * It is not allowed to replace an existing constraint trigger,
787  * either. (The reason for these restrictions is partly that it seems
788  * difficult to deal with pending trigger events in such cases, and
789  * partly that the command might imply changing the constraint's
790  * properties as well, which doesn't seem nice.)
791  */
792  if (OidIsValid(existing_constraint_oid))
793  ereport(ERROR,
795  errmsg("trigger \"%s\" for relation \"%s\" is a constraint trigger",
796  stmt->trigname, RelationGetRelationName(rel))));
797  }
798 
799  /*
800  * If it's a user-entered CREATE CONSTRAINT TRIGGER command, make a
801  * corresponding pg_constraint entry.
802  */
803  if (stmt->isconstraint && !OidIsValid(constraintOid))
804  {
805  /* Internal callers should have made their own constraints */
806  Assert(!isInternal);
807  constraintOid = CreateConstraintEntry(stmt->trigname,
809  CONSTRAINT_TRIGGER,
810  stmt->deferrable,
811  stmt->initdeferred,
812  true,
813  InvalidOid, /* no parent */
814  RelationGetRelid(rel),
815  NULL, /* no conkey */
816  0,
817  0,
818  InvalidOid, /* no domain */
819  InvalidOid, /* no index */
820  InvalidOid, /* no foreign key */
821  NULL,
822  NULL,
823  NULL,
824  NULL,
825  0,
826  ' ',
827  ' ',
828  NULL,
829  0,
830  ' ',
831  NULL, /* no exclusion */
832  NULL, /* no check constraint */
833  NULL,
834  true, /* islocal */
835  0, /* inhcount */
836  true, /* noinherit */
837  isInternal); /* is_internal */
838  }
839 
840  /*
841  * If trigger is internally generated, modify the provided trigger name to
842  * ensure uniqueness by appending the trigger OID. (Callers will usually
843  * supply a simple constant trigger name in these cases.)
844  */
845  if (isInternal)
846  {
847  snprintf(internaltrigname, sizeof(internaltrigname),
848  "%s_%u", stmt->trigname, trigoid);
849  trigname = internaltrigname;
850  }
851  else
852  {
853  /* user-defined trigger; use the specified trigger name as-is */
854  trigname = stmt->trigname;
855  }
856 
857  /*
858  * Build the new pg_trigger tuple.
859  */
860  memset(nulls, false, sizeof(nulls));
861 
862  values[Anum_pg_trigger_oid - 1] = ObjectIdGetDatum(trigoid);
863  values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
864  values[Anum_pg_trigger_tgparentid - 1] = ObjectIdGetDatum(parentTriggerOid);
865  values[Anum_pg_trigger_tgname - 1] = DirectFunctionCall1(namein,
866  CStringGetDatum(trigname));
867  values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid);
868  values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype);
869  values[Anum_pg_trigger_tgenabled - 1] = trigger_fires_when;
870  values[Anum_pg_trigger_tgisinternal - 1] = BoolGetDatum(isInternal);
871  values[Anum_pg_trigger_tgconstrrelid - 1] = ObjectIdGetDatum(constrrelid);
872  values[Anum_pg_trigger_tgconstrindid - 1] = ObjectIdGetDatum(indexOid);
873  values[Anum_pg_trigger_tgconstraint - 1] = ObjectIdGetDatum(constraintOid);
874  values[Anum_pg_trigger_tgdeferrable - 1] = BoolGetDatum(stmt->deferrable);
875  values[Anum_pg_trigger_tginitdeferred - 1] = BoolGetDatum(stmt->initdeferred);
876 
877  if (stmt->args)
878  {
879  ListCell *le;
880  char *args;
881  int16 nargs = list_length(stmt->args);
882  int len = 0;
883 
884  foreach(le, stmt->args)
885  {
886  char *ar = strVal(lfirst(le));
887 
888  len += strlen(ar) + 4;
889  for (; *ar; ar++)
890  {
891  if (*ar == '\\')
892  len++;
893  }
894  }
895  args = (char *) palloc(len + 1);
896  args[0] = '\0';
897  foreach(le, stmt->args)
898  {
899  char *s = strVal(lfirst(le));
900  char *d = args + strlen(args);
901 
902  while (*s)
903  {
904  if (*s == '\\')
905  *d++ = '\\';
906  *d++ = *s++;
907  }
908  strcpy(d, "\\000");
909  }
910  values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(nargs);
911  values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
913  }
914  else
915  {
916  values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(0);
917  values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
918  CStringGetDatum(""));
919  }
920 
921  /* build column number array if it's a column-specific trigger */
922  ncolumns = list_length(stmt->columns);
923  if (ncolumns == 0)
924  columns = NULL;
925  else
926  {
927  ListCell *cell;
928  int i = 0;
929 
930  columns = (int16 *) palloc(ncolumns * sizeof(int16));
931  foreach(cell, stmt->columns)
932  {
933  char *name = strVal(lfirst(cell));
934  int16 attnum;
935  int j;
936 
937  /* Lookup column name. System columns are not allowed */
938  attnum = attnameAttNum(rel, name, false);
939  if (attnum == InvalidAttrNumber)
940  ereport(ERROR,
941  (errcode(ERRCODE_UNDEFINED_COLUMN),
942  errmsg("column \"%s\" of relation \"%s\" does not exist",
943  name, RelationGetRelationName(rel))));
944 
945  /* Check for duplicates */
946  for (j = i - 1; j >= 0; j--)
947  {
948  if (columns[j] == attnum)
949  ereport(ERROR,
950  (errcode(ERRCODE_DUPLICATE_COLUMN),
951  errmsg("column \"%s\" specified more than once",
952  name)));
953  }
954 
955  columns[i++] = attnum;
956  }
957  }
958  tgattr = buildint2vector(columns, ncolumns);
959  values[Anum_pg_trigger_tgattr - 1] = PointerGetDatum(tgattr);
960 
961  /* set tgqual if trigger has WHEN clause */
962  if (qual)
963  values[Anum_pg_trigger_tgqual - 1] = CStringGetTextDatum(qual);
964  else
965  nulls[Anum_pg_trigger_tgqual - 1] = true;
966 
967  if (oldtablename)
968  values[Anum_pg_trigger_tgoldtable - 1] = DirectFunctionCall1(namein,
969  CStringGetDatum(oldtablename));
970  else
971  nulls[Anum_pg_trigger_tgoldtable - 1] = true;
972  if (newtablename)
973  values[Anum_pg_trigger_tgnewtable - 1] = DirectFunctionCall1(namein,
974  CStringGetDatum(newtablename));
975  else
976  nulls[Anum_pg_trigger_tgnewtable - 1] = true;
977 
978  /*
979  * Insert or replace tuple in pg_trigger.
980  */
981  if (!trigger_exists)
982  {
983  tuple = heap_form_tuple(tgrel->rd_att, values, nulls);
984  CatalogTupleInsert(tgrel, tuple);
985  }
986  else
987  {
988  HeapTuple newtup;
989 
990  newtup = heap_form_tuple(tgrel->rd_att, values, nulls);
991  CatalogTupleUpdate(tgrel, &tuple->t_self, newtup);
992  heap_freetuple(newtup);
993  }
994 
995  heap_freetuple(tuple); /* free either original or new tuple */
997 
998  pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
999  pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1]));
1000  pfree(DatumGetPointer(values[Anum_pg_trigger_tgattr - 1]));
1001  if (oldtablename)
1002  pfree(DatumGetPointer(values[Anum_pg_trigger_tgoldtable - 1]));
1003  if (newtablename)
1004  pfree(DatumGetPointer(values[Anum_pg_trigger_tgnewtable - 1]));
1005 
1006  /*
1007  * Update relation's pg_class entry; if necessary; and if not, send an SI
1008  * message to make other backends (and this one) rebuild relcache entries.
1009  */
1010  pgrel = table_open(RelationRelationId, RowExclusiveLock);
1011  tuple = SearchSysCacheCopy1(RELOID,
1013  if (!HeapTupleIsValid(tuple))
1014  elog(ERROR, "cache lookup failed for relation %u",
1015  RelationGetRelid(rel));
1016  if (!((Form_pg_class) GETSTRUCT(tuple))->relhastriggers)
1017  {
1018  ((Form_pg_class) GETSTRUCT(tuple))->relhastriggers = true;
1019 
1020  CatalogTupleUpdate(pgrel, &tuple->t_self, tuple);
1021 
1023  }
1024  else
1026 
1027  heap_freetuple(tuple);
1028  table_close(pgrel, RowExclusiveLock);
1029 
1030  /*
1031  * If we're replacing a trigger, flush all the old dependencies before
1032  * recording new ones.
1033  */
1034  if (trigger_exists)
1035  deleteDependencyRecordsFor(TriggerRelationId, trigoid, true);
1036 
1037  /*
1038  * Record dependencies for trigger. Always place a normal dependency on
1039  * the function.
1040  */
1041  myself.classId = TriggerRelationId;
1042  myself.objectId = trigoid;
1043  myself.objectSubId = 0;
1044 
1045  referenced.classId = ProcedureRelationId;
1046  referenced.objectId = funcoid;
1047  referenced.objectSubId = 0;
1048  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1049 
1050  if (isInternal && OidIsValid(constraintOid))
1051  {
1052  /*
1053  * Internally-generated trigger for a constraint, so make it an
1054  * internal dependency of the constraint. We can skip depending on
1055  * the relation(s), as there'll be an indirect dependency via the
1056  * constraint.
1057  */
1058  referenced.classId = ConstraintRelationId;
1059  referenced.objectId = constraintOid;
1060  referenced.objectSubId = 0;
1061  recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
1062  }
1063  else
1064  {
1065  /*
1066  * User CREATE TRIGGER, so place dependencies. We make trigger be
1067  * auto-dropped if its relation is dropped or if the FK relation is
1068  * dropped. (Auto drop is compatible with our pre-7.3 behavior.)
1069  */
1070  referenced.classId = RelationRelationId;
1071  referenced.objectId = RelationGetRelid(rel);
1072  referenced.objectSubId = 0;
1073  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1074 
1075  if (OidIsValid(constrrelid))
1076  {
1077  referenced.classId = RelationRelationId;
1078  referenced.objectId = constrrelid;
1079  referenced.objectSubId = 0;
1080  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1081  }
1082  /* Not possible to have an index dependency in this case */
1083  Assert(!OidIsValid(indexOid));
1084 
1085  /*
1086  * If it's a user-specified constraint trigger, make the constraint
1087  * internally dependent on the trigger instead of vice versa.
1088  */
1089  if (OidIsValid(constraintOid))
1090  {
1091  referenced.classId = ConstraintRelationId;
1092  referenced.objectId = constraintOid;
1093  referenced.objectSubId = 0;
1094  recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
1095  }
1096 
1097  /*
1098  * If it's a partition trigger, create the partition dependencies.
1099  */
1100  if (OidIsValid(parentTriggerOid))
1101  {
1102  ObjectAddressSet(referenced, TriggerRelationId, parentTriggerOid);
1103  recordDependencyOn(&myself, &referenced, DEPENDENCY_PARTITION_PRI);
1104  ObjectAddressSet(referenced, RelationRelationId, RelationGetRelid(rel));
1105  recordDependencyOn(&myself, &referenced, DEPENDENCY_PARTITION_SEC);
1106  }
1107  }
1108 
1109  /* If column-specific trigger, add normal dependencies on columns */
1110  if (columns != NULL)
1111  {
1112  int i;
1113 
1114  referenced.classId = RelationRelationId;
1115  referenced.objectId = RelationGetRelid(rel);
1116  for (i = 0; i < ncolumns; i++)
1117  {
1118  referenced.objectSubId = columns[i];
1119  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1120  }
1121  }
1122 
1123  /*
1124  * If it has a WHEN clause, add dependencies on objects mentioned in the
1125  * expression (eg, functions, as well as any columns used).
1126  */
1127  if (whenRtable != NIL)
1128  recordDependencyOnExpr(&myself, whenClause, whenRtable,
1130 
1131  /* Post creation hook for new trigger */
1132  InvokeObjectPostCreateHookArg(TriggerRelationId, trigoid, 0,
1133  isInternal);
1134 
1135  /*
1136  * Lastly, create the trigger on child relations, if needed.
1137  */
1138  if (partition_recurse)
1139  {
1140  PartitionDesc partdesc = RelationGetPartitionDesc(rel, true);
1141  int i;
1142  MemoryContext oldcxt,
1143  perChildCxt;
1144 
1146  "part trig clone",
1148 
1149  /*
1150  * We don't currently expect to be called with a valid indexOid. If
1151  * that ever changes then we'll need to write code here to find the
1152  * corresponding child index.
1153  */
1154  Assert(!OidIsValid(indexOid));
1155 
1156  oldcxt = MemoryContextSwitchTo(perChildCxt);
1157 
1158  /* Iterate to create the trigger on each existing partition */
1159  for (i = 0; i < partdesc->nparts; i++)
1160  {
1161  CreateTrigStmt *childStmt;
1162  Relation childTbl;
1163  Node *qual;
1164 
1165  childTbl = table_open(partdesc->oids[i], ShareRowExclusiveLock);
1166 
1167  /*
1168  * Initialize our fabricated parse node by copying the original
1169  * one, then resetting fields that we pass separately.
1170  */
1171  childStmt = (CreateTrigStmt *) copyObject(stmt);
1172  childStmt->funcname = NIL;
1173  childStmt->whenClause = NULL;
1174 
1175  /* If there is a WHEN clause, create a modified copy of it */
1176  qual = copyObject(whenClause);
1177  qual = (Node *)
1179  childTbl, rel);
1180  qual = (Node *)
1182  childTbl, rel);
1183 
1184  CreateTriggerFiringOn(childStmt, queryString,
1185  partdesc->oids[i], refRelOid,
1187  funcoid, trigoid, qual,
1188  isInternal, true, trigger_fires_when);
1189 
1190  table_close(childTbl, NoLock);
1191 
1192  MemoryContextReset(perChildCxt);
1193  }
1194 
1195  MemoryContextSwitchTo(oldcxt);
1196  MemoryContextDelete(perChildCxt);
1197  }
1198 
1199  /* Keep lock on target rel until end of xact */
1200  table_close(rel, NoLock);
1201 
1202  return myself;
1203 }
1204 
1205 /*
1206  * TriggerSetParentTrigger
1207  * Set a partition's trigger as child of its parent trigger,
1208  * or remove the linkage if parentTrigId is InvalidOid.
1209  *
1210  * This updates the constraint's pg_trigger row to show it as inherited, and
1211  * adds PARTITION dependencies to prevent the trigger from being deleted
1212  * on its own. Alternatively, reverse that.
1213  */
1214 void
1216  Oid childTrigId,
1217  Oid parentTrigId,
1218  Oid childTableId)
1219 {
1220  SysScanDesc tgscan;
1221  ScanKeyData skey[1];
1222  Form_pg_trigger trigForm;
1223  HeapTuple tuple,
1224  newtup;
1225  ObjectAddress depender;
1226  ObjectAddress referenced;
1227 
1228  /*
1229  * Find the trigger to delete.
1230  */
1231  ScanKeyInit(&skey[0],
1232  Anum_pg_trigger_oid,
1233  BTEqualStrategyNumber, F_OIDEQ,
1234  ObjectIdGetDatum(childTrigId));
1235 
1236  tgscan = systable_beginscan(trigRel, TriggerOidIndexId, true,
1237  NULL, 1, skey);
1238 
1239  tuple = systable_getnext(tgscan);
1240  if (!HeapTupleIsValid(tuple))
1241  elog(ERROR, "could not find tuple for trigger %u", childTrigId);
1242  newtup = heap_copytuple(tuple);
1243  trigForm = (Form_pg_trigger) GETSTRUCT(newtup);
1244  if (OidIsValid(parentTrigId))
1245  {
1246  /* don't allow setting parent for a constraint that already has one */
1247  if (OidIsValid(trigForm->tgparentid))
1248  elog(ERROR, "trigger %u already has a parent trigger",
1249  childTrigId);
1250 
1251  trigForm->tgparentid = parentTrigId;
1252 
1253  CatalogTupleUpdate(trigRel, &tuple->t_self, newtup);
1254 
1255  ObjectAddressSet(depender, TriggerRelationId, childTrigId);
1256 
1257  ObjectAddressSet(referenced, TriggerRelationId, parentTrigId);
1258  recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_PRI);
1259 
1260  ObjectAddressSet(referenced, RelationRelationId, childTableId);
1261  recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_SEC);
1262  }
1263  else
1264  {
1265  trigForm->tgparentid = InvalidOid;
1266 
1267  CatalogTupleUpdate(trigRel, &tuple->t_self, newtup);
1268 
1269  deleteDependencyRecordsForClass(TriggerRelationId, childTrigId,
1270  TriggerRelationId,
1272  deleteDependencyRecordsForClass(TriggerRelationId, childTrigId,
1273  RelationRelationId,
1275  }
1276 
1277  heap_freetuple(newtup);
1278  systable_endscan(tgscan);
1279 }
1280 
1281 
1282 /*
1283  * Guts of trigger deletion.
1284  */
1285 void
1287 {
1288  Relation tgrel;
1289  SysScanDesc tgscan;
1290  ScanKeyData skey[1];
1291  HeapTuple tup;
1292  Oid relid;
1293  Relation rel;
1294 
1295  tgrel = table_open(TriggerRelationId, RowExclusiveLock);
1296 
1297  /*
1298  * Find the trigger to delete.
1299  */
1300  ScanKeyInit(&skey[0],
1301  Anum_pg_trigger_oid,
1302  BTEqualStrategyNumber, F_OIDEQ,
1303  ObjectIdGetDatum(trigOid));
1304 
1305  tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
1306  NULL, 1, skey);
1307 
1308  tup = systable_getnext(tgscan);
1309  if (!HeapTupleIsValid(tup))
1310  elog(ERROR, "could not find tuple for trigger %u", trigOid);
1311 
1312  /*
1313  * Open and exclusive-lock the relation the trigger belongs to.
1314  */
1315  relid = ((Form_pg_trigger) GETSTRUCT(tup))->tgrelid;
1316 
1317  rel = table_open(relid, AccessExclusiveLock);
1318 
1319  if (rel->rd_rel->relkind != RELKIND_RELATION &&
1320  rel->rd_rel->relkind != RELKIND_VIEW &&
1321  rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
1322  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1323  ereport(ERROR,
1324  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1325  errmsg("relation \"%s\" cannot have triggers",
1327  errdetail_relkind_not_supported(rel->rd_rel->relkind)));
1328 
1330  ereport(ERROR,
1331  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1332  errmsg("permission denied: \"%s\" is a system catalog",
1333  RelationGetRelationName(rel))));
1334 
1335  /*
1336  * Delete the pg_trigger tuple.
1337  */
1338  CatalogTupleDelete(tgrel, &tup->t_self);
1339 
1340  systable_endscan(tgscan);
1341  table_close(tgrel, RowExclusiveLock);
1342 
1343  /*
1344  * We do not bother to try to determine whether any other triggers remain,
1345  * which would be needed in order to decide whether it's safe to clear the
1346  * relation's relhastriggers. (In any case, there might be a concurrent
1347  * process adding new triggers.) Instead, just force a relcache inval to
1348  * make other backends (and this one too!) rebuild their relcache entries.
1349  * There's no great harm in leaving relhastriggers true even if there are
1350  * no triggers left.
1351  */
1353 
1354  /* Keep lock on trigger's rel until end of xact */
1355  table_close(rel, NoLock);
1356 }
1357 
1358 /*
1359  * get_trigger_oid - Look up a trigger by name to find its OID.
1360  *
1361  * If missing_ok is false, throw an error if trigger not found. If
1362  * true, just return InvalidOid.
1363  */
1364 Oid
1365 get_trigger_oid(Oid relid, const char *trigname, bool missing_ok)
1366 {
1367  Relation tgrel;
1368  ScanKeyData skey[2];
1369  SysScanDesc tgscan;
1370  HeapTuple tup;
1371  Oid oid;
1372 
1373  /*
1374  * Find the trigger, verify permissions, set up object address
1375  */
1376  tgrel = table_open(TriggerRelationId, AccessShareLock);
1377 
1378  ScanKeyInit(&skey[0],
1379  Anum_pg_trigger_tgrelid,
1380  BTEqualStrategyNumber, F_OIDEQ,
1381  ObjectIdGetDatum(relid));
1382  ScanKeyInit(&skey[1],
1383  Anum_pg_trigger_tgname,
1384  BTEqualStrategyNumber, F_NAMEEQ,
1385  CStringGetDatum(trigname));
1386 
1387  tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1388  NULL, 2, skey);
1389 
1390  tup = systable_getnext(tgscan);
1391 
1392  if (!HeapTupleIsValid(tup))
1393  {
1394  if (!missing_ok)
1395  ereport(ERROR,
1396  (errcode(ERRCODE_UNDEFINED_OBJECT),
1397  errmsg("trigger \"%s\" for table \"%s\" does not exist",
1398  trigname, get_rel_name(relid))));
1399  oid = InvalidOid;
1400  }
1401  else
1402  {
1403  oid = ((Form_pg_trigger) GETSTRUCT(tup))->oid;
1404  }
1405 
1406  systable_endscan(tgscan);
1407  table_close(tgrel, AccessShareLock);
1408  return oid;
1409 }
1410 
1411 /*
1412  * Perform permissions and integrity checks before acquiring a relation lock.
1413  */
1414 static void
1416  void *arg)
1417 {
1418  HeapTuple tuple;
1419  Form_pg_class form;
1420 
1421  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1422  if (!HeapTupleIsValid(tuple))
1423  return; /* concurrently dropped */
1424  form = (Form_pg_class) GETSTRUCT(tuple);
1425 
1426  /* only tables and views can have triggers */
1427  if (form->relkind != RELKIND_RELATION && form->relkind != RELKIND_VIEW &&
1428  form->relkind != RELKIND_FOREIGN_TABLE &&
1429  form->relkind != RELKIND_PARTITIONED_TABLE)
1430  ereport(ERROR,
1431  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1432  errmsg("relation \"%s\" cannot have triggers",
1433  rv->relname),
1434  errdetail_relkind_not_supported(form->relkind)));
1435 
1436  /* you must own the table to rename one of its triggers */
1437  if (!object_ownercheck(RelationRelationId, relid, GetUserId()))
1439  if (!allowSystemTableMods && IsSystemClass(relid, form))
1440  ereport(ERROR,
1441  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1442  errmsg("permission denied: \"%s\" is a system catalog",
1443  rv->relname)));
1444 
1445  ReleaseSysCache(tuple);
1446 }
1447 
1448 /*
1449  * renametrig - changes the name of a trigger on a relation
1450  *
1451  * trigger name is changed in trigger catalog.
1452  * No record of the previous name is kept.
1453  *
1454  * get proper relrelation from relation catalog (if not arg)
1455  * scan trigger catalog
1456  * for name conflict (within rel)
1457  * for original trigger (if not arg)
1458  * modify tgname in trigger tuple
1459  * update row in catalog
1460  */
1463 {
1464  Oid tgoid;
1465  Relation targetrel;
1466  Relation tgrel;
1467  HeapTuple tuple;
1468  SysScanDesc tgscan;
1469  ScanKeyData key[2];
1470  Oid relid;
1471  ObjectAddress address;
1472 
1473  /*
1474  * Look up name, check permissions, and acquire lock (which we will NOT
1475  * release until end of transaction).
1476  */
1478  0,
1480  NULL);
1481 
1482  /* Have lock already, so just need to build relcache entry. */
1483  targetrel = relation_open(relid, NoLock);
1484 
1485  /*
1486  * On partitioned tables, this operation recurses to partitions. Lock all
1487  * tables upfront.
1488  */
1489  if (targetrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1490  (void) find_all_inheritors(relid, AccessExclusiveLock, NULL);
1491 
1492  tgrel = table_open(TriggerRelationId, RowExclusiveLock);
1493 
1494  /*
1495  * Search for the trigger to modify.
1496  */
1497  ScanKeyInit(&key[0],
1498  Anum_pg_trigger_tgrelid,
1499  BTEqualStrategyNumber, F_OIDEQ,
1500  ObjectIdGetDatum(relid));
1501  ScanKeyInit(&key[1],
1502  Anum_pg_trigger_tgname,
1503  BTEqualStrategyNumber, F_NAMEEQ,
1504  PointerGetDatum(stmt->subname));
1505  tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1506  NULL, 2, key);
1507  if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1508  {
1509  Form_pg_trigger trigform;
1510 
1511  trigform = (Form_pg_trigger) GETSTRUCT(tuple);
1512  tgoid = trigform->oid;
1513 
1514  /*
1515  * If the trigger descends from a trigger on a parent partitioned
1516  * table, reject the rename. We don't allow a trigger in a partition
1517  * to differ in name from that of its parent: that would lead to an
1518  * inconsistency that pg_dump would not reproduce.
1519  */
1520  if (OidIsValid(trigform->tgparentid))
1521  ereport(ERROR,
1522  errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1523  errmsg("cannot rename trigger \"%s\" on table \"%s\"",
1524  stmt->subname, RelationGetRelationName(targetrel)),
1525  errhint("Rename the trigger on the partitioned table \"%s\" instead.",
1526  get_rel_name(get_partition_parent(relid, false))));
1527 
1528 
1529  /* Rename the trigger on this relation ... */
1530  renametrig_internal(tgrel, targetrel, tuple, stmt->newname,
1531  stmt->subname);
1532 
1533  /* ... and if it is partitioned, recurse to its partitions */
1534  if (targetrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1535  {
1536  PartitionDesc partdesc = RelationGetPartitionDesc(targetrel, true);
1537 
1538  for (int i = 0; i < partdesc->nparts; i++)
1539  {
1540  Oid partitionId = partdesc->oids[i];
1541 
1542  renametrig_partition(tgrel, partitionId, trigform->oid,
1543  stmt->newname, stmt->subname);
1544  }
1545  }
1546  }
1547  else
1548  {
1549  ereport(ERROR,
1550  (errcode(ERRCODE_UNDEFINED_OBJECT),
1551  errmsg("trigger \"%s\" for table \"%s\" does not exist",
1552  stmt->subname, RelationGetRelationName(targetrel))));
1553  }
1554 
1555  ObjectAddressSet(address, TriggerRelationId, tgoid);
1556 
1557  systable_endscan(tgscan);
1558 
1559  table_close(tgrel, RowExclusiveLock);
1560 
1561  /*
1562  * Close rel, but keep exclusive lock!
1563  */
1564  relation_close(targetrel, NoLock);
1565 
1566  return address;
1567 }
1568 
1569 /*
1570  * Subroutine for renametrig -- perform the actual work of renaming one
1571  * trigger on one table.
1572  *
1573  * If the trigger has a name different from the expected one, raise a
1574  * NOTICE about it.
1575  */
1576 static void
1578  const char *newname, const char *expected_name)
1579 {
1580  HeapTuple tuple;
1581  Form_pg_trigger tgform;
1582  ScanKeyData key[2];
1583  SysScanDesc tgscan;
1584 
1585  /* If the trigger already has the new name, nothing to do. */
1586  tgform = (Form_pg_trigger) GETSTRUCT(trigtup);
1587  if (strcmp(NameStr(tgform->tgname), newname) == 0)
1588  return;
1589 
1590  /*
1591  * Before actually trying the rename, search for triggers with the same
1592  * name. The update would fail with an ugly message in that case, and it
1593  * is better to throw a nicer error.
1594  */
1595  ScanKeyInit(&key[0],
1596  Anum_pg_trigger_tgrelid,
1597  BTEqualStrategyNumber, F_OIDEQ,
1598  ObjectIdGetDatum(RelationGetRelid(targetrel)));
1599  ScanKeyInit(&key[1],
1600  Anum_pg_trigger_tgname,
1601  BTEqualStrategyNumber, F_NAMEEQ,
1602  PointerGetDatum(newname));
1603  tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1604  NULL, 2, key);
1605  if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1606  ereport(ERROR,
1608  errmsg("trigger \"%s\" for relation \"%s\" already exists",
1609  newname, RelationGetRelationName(targetrel))));
1610  systable_endscan(tgscan);
1611 
1612  /*
1613  * The target name is free; update the existing pg_trigger tuple with it.
1614  */
1615  tuple = heap_copytuple(trigtup); /* need a modifiable copy */
1616  tgform = (Form_pg_trigger) GETSTRUCT(tuple);
1617 
1618  /*
1619  * If the trigger has a name different from what we expected, let the user
1620  * know. (We can proceed anyway, since we must have reached here following
1621  * a tgparentid link.)
1622  */
1623  if (strcmp(NameStr(tgform->tgname), expected_name) != 0)
1624  ereport(NOTICE,
1625  errmsg("renamed trigger \"%s\" on relation \"%s\"",
1626  NameStr(tgform->tgname),
1627  RelationGetRelationName(targetrel)));
1628 
1629  namestrcpy(&tgform->tgname, newname);
1630 
1631  CatalogTupleUpdate(tgrel, &tuple->t_self, tuple);
1632 
1633  InvokeObjectPostAlterHook(TriggerRelationId, tgform->oid, 0);
1634 
1635  /*
1636  * Invalidate relation's relcache entry so that other backends (and this
1637  * one too!) are sent SI message to make them rebuild relcache entries.
1638  * (Ideally this should happen automatically...)
1639  */
1640  CacheInvalidateRelcache(targetrel);
1641 }
1642 
1643 /*
1644  * Subroutine for renametrig -- Helper for recursing to partitions when
1645  * renaming triggers on a partitioned table.
1646  */
1647 static void
1648 renametrig_partition(Relation tgrel, Oid partitionId, Oid parentTriggerOid,
1649  const char *newname, const char *expected_name)
1650 {
1651  SysScanDesc tgscan;
1652  ScanKeyData key;
1653  HeapTuple tuple;
1654 
1655  /*
1656  * Given a relation and the OID of a trigger on parent relation, find the
1657  * corresponding trigger in the child and rename that trigger to the given
1658  * name.
1659  */
1660  ScanKeyInit(&key,
1661  Anum_pg_trigger_tgrelid,
1662  BTEqualStrategyNumber, F_OIDEQ,
1663  ObjectIdGetDatum(partitionId));
1664  tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1665  NULL, 1, &key);
1666  while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1667  {
1668  Form_pg_trigger tgform = (Form_pg_trigger) GETSTRUCT(tuple);
1669  Relation partitionRel;
1670 
1671  if (tgform->tgparentid != parentTriggerOid)
1672  continue; /* not our trigger */
1673 
1674  partitionRel = table_open(partitionId, NoLock);
1675 
1676  /* Rename the trigger on this partition */
1677  renametrig_internal(tgrel, partitionRel, tuple, newname, expected_name);
1678 
1679  /* And if this relation is partitioned, recurse to its partitions */
1680  if (partitionRel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1681  {
1682  PartitionDesc partdesc = RelationGetPartitionDesc(partitionRel,
1683  true);
1684 
1685  for (int i = 0; i < partdesc->nparts; i++)
1686  {
1687  Oid partoid = partdesc->oids[i];
1688 
1689  renametrig_partition(tgrel, partoid, tgform->oid, newname,
1690  NameStr(tgform->tgname));
1691  }
1692  }
1693  table_close(partitionRel, NoLock);
1694 
1695  /* There should be at most one matching tuple */
1696  break;
1697  }
1698  systable_endscan(tgscan);
1699 }
1700 
1701 /*
1702  * EnableDisableTrigger()
1703  *
1704  * Called by ALTER TABLE ENABLE/DISABLE [ REPLICA | ALWAYS ] TRIGGER
1705  * to change 'tgenabled' field for the specified trigger(s)
1706  *
1707  * rel: relation to process (caller must hold suitable lock on it)
1708  * tgname: name of trigger to process, or NULL to scan all triggers
1709  * tgparent: if not zero, process only triggers with this tgparentid
1710  * fires_when: new value for tgenabled field. In addition to generic
1711  * enablement/disablement, this also defines when the trigger
1712  * should be fired in session replication roles.
1713  * skip_system: if true, skip "system" triggers (constraint triggers)
1714  * recurse: if true, recurse to partitions
1715  *
1716  * Caller should have checked permissions for the table; here we also
1717  * enforce that superuser privilege is required to alter the state of
1718  * system triggers
1719  */
1720 void
1721 EnableDisableTrigger(Relation rel, const char *tgname, Oid tgparent,
1722  char fires_when, bool skip_system, bool recurse,
1723  LOCKMODE lockmode)
1724 {
1725  Relation tgrel;
1726  int nkeys;
1727  ScanKeyData keys[2];
1728  SysScanDesc tgscan;
1729  HeapTuple tuple;
1730  bool found;
1731  bool changed;
1732 
1733  /* Scan the relevant entries in pg_triggers */
1734  tgrel = table_open(TriggerRelationId, RowExclusiveLock);
1735 
1736  ScanKeyInit(&keys[0],
1737  Anum_pg_trigger_tgrelid,
1738  BTEqualStrategyNumber, F_OIDEQ,
1740  if (tgname)
1741  {
1742  ScanKeyInit(&keys[1],
1743  Anum_pg_trigger_tgname,
1744  BTEqualStrategyNumber, F_NAMEEQ,
1745  CStringGetDatum(tgname));
1746  nkeys = 2;
1747  }
1748  else
1749  nkeys = 1;
1750 
1751  tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1752  NULL, nkeys, keys);
1753 
1754  found = changed = false;
1755 
1756  while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1757  {
1758  Form_pg_trigger oldtrig = (Form_pg_trigger) GETSTRUCT(tuple);
1759 
1760  if (OidIsValid(tgparent) && tgparent != oldtrig->tgparentid)
1761  continue;
1762 
1763  if (oldtrig->tgisinternal)
1764  {
1765  /* system trigger ... ok to process? */
1766  if (skip_system)
1767  continue;
1768  if (!superuser())
1769  ereport(ERROR,
1770  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1771  errmsg("permission denied: \"%s\" is a system trigger",
1772  NameStr(oldtrig->tgname))));
1773  }
1774 
1775  found = true;
1776 
1777  if (oldtrig->tgenabled != fires_when)
1778  {
1779  /* need to change this one ... make a copy to scribble on */
1780  HeapTuple newtup = heap_copytuple(tuple);
1781  Form_pg_trigger newtrig = (Form_pg_trigger) GETSTRUCT(newtup);
1782 
1783  newtrig->tgenabled = fires_when;
1784 
1785  CatalogTupleUpdate(tgrel, &newtup->t_self, newtup);
1786 
1787  heap_freetuple(newtup);
1788 
1789  changed = true;
1790  }
1791 
1792  /*
1793  * When altering FOR EACH ROW triggers on a partitioned table, do the
1794  * same on the partitions as well, unless ONLY is specified.
1795  *
1796  * Note that we recurse even if we didn't change the trigger above,
1797  * because the partitions' copy of the trigger may have a different
1798  * value of tgenabled than the parent's trigger and thus might need to
1799  * be changed.
1800  */
1801  if (recurse &&
1802  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
1803  (TRIGGER_FOR_ROW(oldtrig->tgtype)))
1804  {
1805  PartitionDesc partdesc = RelationGetPartitionDesc(rel, true);
1806  int i;
1807 
1808  for (i = 0; i < partdesc->nparts; i++)
1809  {
1810  Relation part;
1811 
1812  part = relation_open(partdesc->oids[i], lockmode);
1813  /* Match on child triggers' tgparentid, not their name */
1814  EnableDisableTrigger(part, NULL, oldtrig->oid,
1815  fires_when, skip_system, recurse,
1816  lockmode);
1817  table_close(part, NoLock); /* keep lock till commit */
1818  }
1819  }
1820 
1821  InvokeObjectPostAlterHook(TriggerRelationId,
1822  oldtrig->oid, 0);
1823  }
1824 
1825  systable_endscan(tgscan);
1826 
1827  table_close(tgrel, RowExclusiveLock);
1828 
1829  if (tgname && !found)
1830  ereport(ERROR,
1831  (errcode(ERRCODE_UNDEFINED_OBJECT),
1832  errmsg("trigger \"%s\" for table \"%s\" does not exist",
1833  tgname, RelationGetRelationName(rel))));
1834 
1835  /*
1836  * If we changed anything, broadcast a SI inval message to force each
1837  * backend (including our own!) to rebuild relation's relcache entry.
1838  * Otherwise they will fail to apply the change promptly.
1839  */
1840  if (changed)
1842 }
1843 
1844 
1845 /*
1846  * Build trigger data to attach to the given relcache entry.
1847  *
1848  * Note that trigger data attached to a relcache entry must be stored in
1849  * CacheMemoryContext to ensure it survives as long as the relcache entry.
1850  * But we should be running in a less long-lived working context. To avoid
1851  * leaking cache memory if this routine fails partway through, we build a
1852  * temporary TriggerDesc in working memory and then copy the completed
1853  * structure into cache memory.
1854  */
1855 void
1857 {
1858  TriggerDesc *trigdesc;
1859  int numtrigs;
1860  int maxtrigs;
1861  Trigger *triggers;
1862  Relation tgrel;
1863  ScanKeyData skey;
1864  SysScanDesc tgscan;
1865  HeapTuple htup;
1866  MemoryContext oldContext;
1867  int i;
1868 
1869  /*
1870  * Allocate a working array to hold the triggers (the array is extended if
1871  * necessary)
1872  */
1873  maxtrigs = 16;
1874  triggers = (Trigger *) palloc(maxtrigs * sizeof(Trigger));
1875  numtrigs = 0;
1876 
1877  /*
1878  * Note: since we scan the triggers using TriggerRelidNameIndexId, we will
1879  * be reading the triggers in name order, except possibly during
1880  * emergency-recovery operations (ie, IgnoreSystemIndexes). This in turn
1881  * ensures that triggers will be fired in name order.
1882  */
1883  ScanKeyInit(&skey,
1884  Anum_pg_trigger_tgrelid,
1885  BTEqualStrategyNumber, F_OIDEQ,
1886  ObjectIdGetDatum(RelationGetRelid(relation)));
1887 
1888  tgrel = table_open(TriggerRelationId, AccessShareLock);
1889  tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1890  NULL, 1, &skey);
1891 
1892  while (HeapTupleIsValid(htup = systable_getnext(tgscan)))
1893  {
1894  Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
1895  Trigger *build;
1896  Datum datum;
1897  bool isnull;
1898 
1899  if (numtrigs >= maxtrigs)
1900  {
1901  maxtrigs *= 2;
1902  triggers = (Trigger *) repalloc(triggers, maxtrigs * sizeof(Trigger));
1903  }
1904  build = &(triggers[numtrigs]);
1905 
1906  build->tgoid = pg_trigger->oid;
1908  NameGetDatum(&pg_trigger->tgname)));
1909  build->tgfoid = pg_trigger->tgfoid;
1910  build->tgtype = pg_trigger->tgtype;
1911  build->tgenabled = pg_trigger->tgenabled;
1912  build->tgisinternal = pg_trigger->tgisinternal;
1913  build->tgisclone = OidIsValid(pg_trigger->tgparentid);
1914  build->tgconstrrelid = pg_trigger->tgconstrrelid;
1915  build->tgconstrindid = pg_trigger->tgconstrindid;
1916  build->tgconstraint = pg_trigger->tgconstraint;
1917  build->tgdeferrable = pg_trigger->tgdeferrable;
1918  build->tginitdeferred = pg_trigger->tginitdeferred;
1919  build->tgnargs = pg_trigger->tgnargs;
1920  /* tgattr is first var-width field, so OK to access directly */
1921  build->tgnattr = pg_trigger->tgattr.dim1;
1922  if (build->tgnattr > 0)
1923  {
1924  build->tgattr = (int16 *) palloc(build->tgnattr * sizeof(int16));
1925  memcpy(build->tgattr, &(pg_trigger->tgattr.values),
1926  build->tgnattr * sizeof(int16));
1927  }
1928  else
1929  build->tgattr = NULL;
1930  if (build->tgnargs > 0)
1931  {
1932  bytea *val;
1933  char *p;
1934 
1936  Anum_pg_trigger_tgargs,
1937  tgrel->rd_att, &isnull));
1938  if (isnull)
1939  elog(ERROR, "tgargs is null in trigger for relation \"%s\"",
1940  RelationGetRelationName(relation));
1941  p = (char *) VARDATA_ANY(val);
1942  build->tgargs = (char **) palloc(build->tgnargs * sizeof(char *));
1943  for (i = 0; i < build->tgnargs; i++)
1944  {
1945  build->tgargs[i] = pstrdup(p);
1946  p += strlen(p) + 1;
1947  }
1948  }
1949  else
1950  build->tgargs = NULL;
1951 
1952  datum = fastgetattr(htup, Anum_pg_trigger_tgoldtable,
1953  tgrel->rd_att, &isnull);
1954  if (!isnull)
1955  build->tgoldtable =
1957  else
1958  build->tgoldtable = NULL;
1959 
1960  datum = fastgetattr(htup, Anum_pg_trigger_tgnewtable,
1961  tgrel->rd_att, &isnull);
1962  if (!isnull)
1963  build->tgnewtable =
1965  else
1966  build->tgnewtable = NULL;
1967 
1968  datum = fastgetattr(htup, Anum_pg_trigger_tgqual,
1969  tgrel->rd_att, &isnull);
1970  if (!isnull)
1971  build->tgqual = TextDatumGetCString(datum);
1972  else
1973  build->tgqual = NULL;
1974 
1975  numtrigs++;
1976  }
1977 
1978  systable_endscan(tgscan);
1979  table_close(tgrel, AccessShareLock);
1980 
1981  /* There might not be any triggers */
1982  if (numtrigs == 0)
1983  {
1984  pfree(triggers);
1985  return;
1986  }
1987 
1988  /* Build trigdesc */
1989  trigdesc = (TriggerDesc *) palloc0(sizeof(TriggerDesc));
1990  trigdesc->triggers = triggers;
1991  trigdesc->numtriggers = numtrigs;
1992  for (i = 0; i < numtrigs; i++)
1993  SetTriggerFlags(trigdesc, &(triggers[i]));
1994 
1995  /* Copy completed trigdesc into cache storage */
1997  relation->trigdesc = CopyTriggerDesc(trigdesc);
1998  MemoryContextSwitchTo(oldContext);
1999 
2000  /* Release working memory */
2001  FreeTriggerDesc(trigdesc);
2002 }
2003 
2004 /*
2005  * Update the TriggerDesc's hint flags to include the specified trigger
2006  */
2007 static void
2009 {
2010  int16 tgtype = trigger->tgtype;
2011 
2012  trigdesc->trig_insert_before_row |=
2013  TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2014  TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
2015  trigdesc->trig_insert_after_row |=
2016  TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2017  TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
2018  trigdesc->trig_insert_instead_row |=
2019  TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2020  TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_INSERT);
2021  trigdesc->trig_insert_before_statement |=
2022  TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2023  TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_INSERT);
2024  trigdesc->trig_insert_after_statement |=
2025  TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2026  TRIGGER_TYPE_AFTER, TRIGGER_TYPE_INSERT);
2027  trigdesc->trig_update_before_row |=
2028  TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2029  TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
2030  trigdesc->trig_update_after_row |=
2031  TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2032  TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
2033  trigdesc->trig_update_instead_row |=
2034  TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2035  TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_UPDATE);
2036  trigdesc->trig_update_before_statement |=
2037  TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2038  TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_UPDATE);
2039  trigdesc->trig_update_after_statement |=
2040  TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2041  TRIGGER_TYPE_AFTER, TRIGGER_TYPE_UPDATE);
2042  trigdesc->trig_delete_before_row |=
2043  TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2044  TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
2045  trigdesc->trig_delete_after_row |=
2046  TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2047  TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
2048  trigdesc->trig_delete_instead_row |=
2049  TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_ROW,
2050  TRIGGER_TYPE_INSTEAD, TRIGGER_TYPE_DELETE);
2051  trigdesc->trig_delete_before_statement |=
2052  TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2053  TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_DELETE);
2054  trigdesc->trig_delete_after_statement |=
2055  TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2056  TRIGGER_TYPE_AFTER, TRIGGER_TYPE_DELETE);
2057  /* there are no row-level truncate triggers */
2058  trigdesc->trig_truncate_before_statement |=
2059  TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2060  TRIGGER_TYPE_BEFORE, TRIGGER_TYPE_TRUNCATE);
2061  trigdesc->trig_truncate_after_statement |=
2062  TRIGGER_TYPE_MATCHES(tgtype, TRIGGER_TYPE_STATEMENT,
2063  TRIGGER_TYPE_AFTER, TRIGGER_TYPE_TRUNCATE);
2064 
2065  trigdesc->trig_insert_new_table |=
2066  (TRIGGER_FOR_INSERT(tgtype) &&
2067  TRIGGER_USES_TRANSITION_TABLE(trigger->tgnewtable));
2068  trigdesc->trig_update_old_table |=
2069  (TRIGGER_FOR_UPDATE(tgtype) &&
2070  TRIGGER_USES_TRANSITION_TABLE(trigger->tgoldtable));
2071  trigdesc->trig_update_new_table |=
2072  (TRIGGER_FOR_UPDATE(tgtype) &&
2073  TRIGGER_USES_TRANSITION_TABLE(trigger->tgnewtable));
2074  trigdesc->trig_delete_old_table |=
2075  (TRIGGER_FOR_DELETE(tgtype) &&
2076  TRIGGER_USES_TRANSITION_TABLE(trigger->tgoldtable));
2077 }
2078 
2079 /*
2080  * Copy a TriggerDesc data structure.
2081  *
2082  * The copy is allocated in the current memory context.
2083  */
2084 TriggerDesc *
2086 {
2087  TriggerDesc *newdesc;
2088  Trigger *trigger;
2089  int i;
2090 
2091  if (trigdesc == NULL || trigdesc->numtriggers <= 0)
2092  return NULL;
2093 
2094  newdesc = (TriggerDesc *) palloc(sizeof(TriggerDesc));
2095  memcpy(newdesc, trigdesc, sizeof(TriggerDesc));
2096 
2097  trigger = (Trigger *) palloc(trigdesc->numtriggers * sizeof(Trigger));
2098  memcpy(trigger, trigdesc->triggers,
2099  trigdesc->numtriggers * sizeof(Trigger));
2100  newdesc->triggers = trigger;
2101 
2102  for (i = 0; i < trigdesc->numtriggers; i++)
2103  {
2104  trigger->tgname = pstrdup(trigger->tgname);
2105  if (trigger->tgnattr > 0)
2106  {
2107  int16 *newattr;
2108 
2109  newattr = (int16 *) palloc(trigger->tgnattr * sizeof(int16));
2110  memcpy(newattr, trigger->tgattr,
2111  trigger->tgnattr * sizeof(int16));
2112  trigger->tgattr = newattr;
2113  }
2114  if (trigger->tgnargs > 0)
2115  {
2116  char **newargs;
2117  int16 j;
2118 
2119  newargs = (char **) palloc(trigger->tgnargs * sizeof(char *));
2120  for (j = 0; j < trigger->tgnargs; j++)
2121  newargs[j] = pstrdup(trigger->tgargs[j]);
2122  trigger->tgargs = newargs;
2123  }
2124  if (trigger->tgqual)
2125  trigger->tgqual = pstrdup(trigger->tgqual);
2126  if (trigger->tgoldtable)
2127  trigger->tgoldtable = pstrdup(trigger->tgoldtable);
2128  if (trigger->tgnewtable)
2129  trigger->tgnewtable = pstrdup(trigger->tgnewtable);
2130  trigger++;
2131  }
2132 
2133  return newdesc;
2134 }
2135 
2136 /*
2137  * Free a TriggerDesc data structure.
2138  */
2139 void
2141 {
2142  Trigger *trigger;
2143  int i;
2144 
2145  if (trigdesc == NULL)
2146  return;
2147 
2148  trigger = trigdesc->triggers;
2149  for (i = 0; i < trigdesc->numtriggers; i++)
2150  {
2151  pfree(trigger->tgname);
2152  if (trigger->tgnattr > 0)
2153  pfree(trigger->tgattr);
2154  if (trigger->tgnargs > 0)
2155  {
2156  while (--(trigger->tgnargs) >= 0)
2157  pfree(trigger->tgargs[trigger->tgnargs]);
2158  pfree(trigger->tgargs);
2159  }
2160  if (trigger->tgqual)
2161  pfree(trigger->tgqual);
2162  if (trigger->tgoldtable)
2163  pfree(trigger->tgoldtable);
2164  if (trigger->tgnewtable)
2165  pfree(trigger->tgnewtable);
2166  trigger++;
2167  }
2168  pfree(trigdesc->triggers);
2169  pfree(trigdesc);
2170 }
2171 
2172 /*
2173  * Compare two TriggerDesc structures for logical equality.
2174  */
2175 #ifdef NOT_USED
2176 bool
2177 equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
2178 {
2179  int i,
2180  j;
2181 
2182  /*
2183  * We need not examine the hint flags, just the trigger array itself; if
2184  * we have the same triggers with the same types, the flags should match.
2185  *
2186  * As of 7.3 we assume trigger set ordering is significant in the
2187  * comparison; so we just compare corresponding slots of the two sets.
2188  *
2189  * Note: comparing the stringToNode forms of the WHEN clauses means that
2190  * parse column locations will affect the result. This is okay as long as
2191  * this function is only used for detecting exact equality, as for example
2192  * in checking for staleness of a cache entry.
2193  */
2194  if (trigdesc1 != NULL)
2195  {
2196  if (trigdesc2 == NULL)
2197  return false;
2198  if (trigdesc1->numtriggers != trigdesc2->numtriggers)
2199  return false;
2200  for (i = 0; i < trigdesc1->numtriggers; i++)
2201  {
2202  Trigger *trig1 = trigdesc1->triggers + i;
2203  Trigger *trig2 = trigdesc2->triggers + i;
2204 
2205  if (trig1->tgoid != trig2->tgoid)
2206  return false;
2207  if (strcmp(trig1->tgname, trig2->tgname) != 0)
2208  return false;
2209  if (trig1->tgfoid != trig2->tgfoid)
2210  return false;
2211  if (trig1->tgtype != trig2->tgtype)
2212  return false;
2213  if (trig1->tgenabled != trig2->tgenabled)
2214  return false;
2215  if (trig1->tgisinternal != trig2->tgisinternal)
2216  return false;
2217  if (trig1->tgisclone != trig2->tgisclone)
2218  return false;
2219  if (trig1->tgconstrrelid != trig2->tgconstrrelid)
2220  return false;
2221  if (trig1->tgconstrindid != trig2->tgconstrindid)
2222  return false;
2223  if (trig1->tgconstraint != trig2->tgconstraint)
2224  return false;
2225  if (trig1->tgdeferrable != trig2->tgdeferrable)
2226  return false;
2227  if (trig1->tginitdeferred != trig2->tginitdeferred)
2228  return false;
2229  if (trig1->tgnargs != trig2->tgnargs)
2230  return false;
2231  if (trig1->tgnattr != trig2->tgnattr)
2232  return false;
2233  if (trig1->tgnattr > 0 &&
2234  memcmp(trig1->tgattr, trig2->tgattr,
2235  trig1->tgnattr * sizeof(int16)) != 0)
2236  return false;
2237  for (j = 0; j < trig1->tgnargs; j++)
2238  if (strcmp(trig1->tgargs[j], trig2->tgargs[j]) != 0)
2239  return false;
2240  if (trig1->tgqual == NULL && trig2->tgqual == NULL)
2241  /* ok */ ;
2242  else if (trig1->tgqual == NULL || trig2->tgqual == NULL)
2243  return false;
2244  else if (strcmp(trig1->tgqual, trig2->tgqual) != 0)
2245  return false;
2246  if (trig1->tgoldtable == NULL && trig2->tgoldtable == NULL)
2247  /* ok */ ;
2248  else if (trig1->tgoldtable == NULL || trig2->tgoldtable == NULL)
2249  return false;
2250  else if (strcmp(trig1->tgoldtable, trig2->tgoldtable) != 0)
2251  return false;
2252  if (trig1->tgnewtable == NULL && trig2->tgnewtable == NULL)
2253  /* ok */ ;
2254  else if (trig1->tgnewtable == NULL || trig2->tgnewtable == NULL)
2255  return false;
2256  else if (strcmp(trig1->tgnewtable, trig2->tgnewtable) != 0)
2257  return false;
2258  }
2259  }
2260  else if (trigdesc2 != NULL)
2261  return false;
2262  return true;
2263 }
2264 #endif /* NOT_USED */
2265 
2266 /*
2267  * Check if there is a row-level trigger with transition tables that prevents
2268  * a table from becoming an inheritance child or partition. Return the name
2269  * of the first such incompatible trigger, or NULL if there is none.
2270  */
2271 const char *
2273 {
2274  if (trigdesc != NULL)
2275  {
2276  int i;
2277 
2278  for (i = 0; i < trigdesc->numtriggers; ++i)
2279  {
2280  Trigger *trigger = &trigdesc->triggers[i];
2281 
2282  if (trigger->tgoldtable != NULL || trigger->tgnewtable != NULL)
2283  return trigger->tgname;
2284  }
2285  }
2286 
2287  return NULL;
2288 }
2289 
2290 /*
2291  * Call a trigger function.
2292  *
2293  * trigdata: trigger descriptor.
2294  * tgindx: trigger's index in finfo and instr arrays.
2295  * finfo: array of cached trigger function call information.
2296  * instr: optional array of EXPLAIN ANALYZE instrumentation state.
2297  * per_tuple_context: memory context to execute the function in.
2298  *
2299  * Returns the tuple (or NULL) as returned by the function.
2300  */
2301 static HeapTuple
2303  int tgindx,
2304  FmgrInfo *finfo,
2305  Instrumentation *instr,
2306  MemoryContext per_tuple_context)
2307 {
2308  LOCAL_FCINFO(fcinfo, 0);
2309  PgStat_FunctionCallUsage fcusage;
2310  Datum result;
2311  MemoryContext oldContext;
2312 
2313  /*
2314  * Protect against code paths that may fail to initialize transition table
2315  * info.
2316  */
2317  Assert(((TRIGGER_FIRED_BY_INSERT(trigdata->tg_event) ||
2318  TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event) ||
2319  TRIGGER_FIRED_BY_DELETE(trigdata->tg_event)) &&
2320  TRIGGER_FIRED_AFTER(trigdata->tg_event) &&
2321  !(trigdata->tg_event & AFTER_TRIGGER_DEFERRABLE) &&
2322  !(trigdata->tg_event & AFTER_TRIGGER_INITDEFERRED)) ||
2323  (trigdata->tg_oldtable == NULL && trigdata->tg_newtable == NULL));
2324 
2325  finfo += tgindx;
2326 
2327  /*
2328  * We cache fmgr lookup info, to avoid making the lookup again on each
2329  * call.
2330  */
2331  if (finfo->fn_oid == InvalidOid)
2332  fmgr_info(trigdata->tg_trigger->tgfoid, finfo);
2333 
2334  Assert(finfo->fn_oid == trigdata->tg_trigger->tgfoid);
2335 
2336  /*
2337  * If doing EXPLAIN ANALYZE, start charging time to this trigger.
2338  */
2339  if (instr)
2340  InstrStartNode(instr + tgindx);
2341 
2342  /*
2343  * Do the function evaluation in the per-tuple memory context, so that
2344  * leaked memory will be reclaimed once per tuple. Note in particular that
2345  * any new tuple created by the trigger function will live till the end of
2346  * the tuple cycle.
2347  */
2348  oldContext = MemoryContextSwitchTo(per_tuple_context);
2349 
2350  /*
2351  * Call the function, passing no arguments but setting a context.
2352  */
2353  InitFunctionCallInfoData(*fcinfo, finfo, 0,
2354  InvalidOid, (Node *) trigdata, NULL);
2355 
2356  pgstat_init_function_usage(fcinfo, &fcusage);
2357 
2358  MyTriggerDepth++;
2359  PG_TRY();
2360  {
2361  result = FunctionCallInvoke(fcinfo);
2362  }
2363  PG_FINALLY();
2364  {
2365  MyTriggerDepth--;
2366  }
2367  PG_END_TRY();
2368 
2369  pgstat_end_function_usage(&fcusage, true);
2370 
2371  MemoryContextSwitchTo(oldContext);
2372 
2373  /*
2374  * Trigger protocol allows function to return a null pointer, but NOT to
2375  * set the isnull result flag.
2376  */
2377  if (fcinfo->isnull)
2378  ereport(ERROR,
2379  (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2380  errmsg("trigger function %u returned null value",
2381  fcinfo->flinfo->fn_oid)));
2382 
2383  /*
2384  * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
2385  * one "tuple returned" (really the number of firings).
2386  */
2387  if (instr)
2388  InstrStopNode(instr + tgindx, 1);
2389 
2390  return (HeapTuple) DatumGetPointer(result);
2391 }
2392 
2393 void
2395 {
2396  TriggerDesc *trigdesc;
2397  int i;
2398  TriggerData LocTriggerData = {0};
2399 
2400  trigdesc = relinfo->ri_TrigDesc;
2401 
2402  if (trigdesc == NULL)
2403  return;
2404  if (!trigdesc->trig_insert_before_statement)
2405  return;
2406 
2407  /* no-op if we already fired BS triggers in this context */
2409  CMD_INSERT))
2410  return;
2411 
2412  LocTriggerData.type = T_TriggerData;
2413  LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
2415  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2416  for (i = 0; i < trigdesc->numtriggers; i++)
2417  {
2418  Trigger *trigger = &trigdesc->triggers[i];
2419  HeapTuple newtuple;
2420 
2421  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2422  TRIGGER_TYPE_STATEMENT,
2423  TRIGGER_TYPE_BEFORE,
2424  TRIGGER_TYPE_INSERT))
2425  continue;
2426  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2427  NULL, NULL, NULL))
2428  continue;
2429 
2430  LocTriggerData.tg_trigger = trigger;
2431  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2432  i,
2433  relinfo->ri_TrigFunctions,
2434  relinfo->ri_TrigInstrument,
2435  GetPerTupleMemoryContext(estate));
2436 
2437  if (newtuple)
2438  ereport(ERROR,
2439  (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2440  errmsg("BEFORE STATEMENT trigger cannot return a value")));
2441  }
2442 }
2443 
2444 void
2446  TransitionCaptureState *transition_capture)
2447 {
2448  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2449 
2450  if (trigdesc && trigdesc->trig_insert_after_statement)
2451  AfterTriggerSaveEvent(estate, relinfo, NULL, NULL,
2453  false, NULL, NULL, NIL, NULL, transition_capture,
2454  false);
2455 }
2456 
2457 bool
2459  TupleTableSlot *slot)
2460 {
2461  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2462  HeapTuple newtuple = NULL;
2463  bool should_free;
2464  TriggerData LocTriggerData = {0};
2465  int i;
2466 
2467  LocTriggerData.type = T_TriggerData;
2468  LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
2471  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2472  for (i = 0; i < trigdesc->numtriggers; i++)
2473  {
2474  Trigger *trigger = &trigdesc->triggers[i];
2475  HeapTuple oldtuple;
2476 
2477  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2478  TRIGGER_TYPE_ROW,
2479  TRIGGER_TYPE_BEFORE,
2480  TRIGGER_TYPE_INSERT))
2481  continue;
2482  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2483  NULL, NULL, slot))
2484  continue;
2485 
2486  if (!newtuple)
2487  newtuple = ExecFetchSlotHeapTuple(slot, true, &should_free);
2488 
2489  LocTriggerData.tg_trigslot = slot;
2490  LocTriggerData.tg_trigtuple = oldtuple = newtuple;
2491  LocTriggerData.tg_trigger = trigger;
2492  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2493  i,
2494  relinfo->ri_TrigFunctions,
2495  relinfo->ri_TrigInstrument,
2496  GetPerTupleMemoryContext(estate));
2497  if (newtuple == NULL)
2498  {
2499  if (should_free)
2500  heap_freetuple(oldtuple);
2501  return false; /* "do nothing" */
2502  }
2503  else if (newtuple != oldtuple)
2504  {
2505  ExecForceStoreHeapTuple(newtuple, slot, false);
2506 
2507  /*
2508  * After a tuple in a partition goes through a trigger, the user
2509  * could have changed the partition key enough that the tuple no
2510  * longer fits the partition. Verify that.
2511  */
2512  if (trigger->tgisclone &&
2513  !ExecPartitionCheck(relinfo, slot, estate, false))
2514  ereport(ERROR,
2515  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2516  errmsg("moving row to another partition during a BEFORE FOR EACH ROW trigger is not supported"),
2517  errdetail("Before executing trigger \"%s\", the row was to be in partition \"%s.%s\".",
2518  trigger->tgname,
2521 
2522  if (should_free)
2523  heap_freetuple(oldtuple);
2524 
2525  /* signal tuple should be re-fetched if used */
2526  newtuple = NULL;
2527  }
2528  }
2529 
2530  return true;
2531 }
2532 
2533 void
2535  TupleTableSlot *slot, List *recheckIndexes,
2536  TransitionCaptureState *transition_capture)
2537 {
2538  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2539 
2540  if ((trigdesc && trigdesc->trig_insert_after_row) ||
2541  (transition_capture && transition_capture->tcs_insert_new_table))
2542  AfterTriggerSaveEvent(estate, relinfo, NULL, NULL,
2544  true, NULL, slot,
2545  recheckIndexes, NULL,
2546  transition_capture,
2547  false);
2548 }
2549 
2550 bool
2552  TupleTableSlot *slot)
2553 {
2554  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2555  HeapTuple newtuple = NULL;
2556  bool should_free;
2557  TriggerData LocTriggerData = {0};
2558  int i;
2559 
2560  LocTriggerData.type = T_TriggerData;
2561  LocTriggerData.tg_event = TRIGGER_EVENT_INSERT |
2564  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2565  for (i = 0; i < trigdesc->numtriggers; i++)
2566  {
2567  Trigger *trigger = &trigdesc->triggers[i];
2568  HeapTuple oldtuple;
2569 
2570  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2571  TRIGGER_TYPE_ROW,
2572  TRIGGER_TYPE_INSTEAD,
2573  TRIGGER_TYPE_INSERT))
2574  continue;
2575  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2576  NULL, NULL, slot))
2577  continue;
2578 
2579  if (!newtuple)
2580  newtuple = ExecFetchSlotHeapTuple(slot, true, &should_free);
2581 
2582  LocTriggerData.tg_trigslot = slot;
2583  LocTriggerData.tg_trigtuple = oldtuple = newtuple;
2584  LocTriggerData.tg_trigger = trigger;
2585  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2586  i,
2587  relinfo->ri_TrigFunctions,
2588  relinfo->ri_TrigInstrument,
2589  GetPerTupleMemoryContext(estate));
2590  if (newtuple == NULL)
2591  {
2592  if (should_free)
2593  heap_freetuple(oldtuple);
2594  return false; /* "do nothing" */
2595  }
2596  else if (newtuple != oldtuple)
2597  {
2598  ExecForceStoreHeapTuple(newtuple, slot, false);
2599 
2600  if (should_free)
2601  heap_freetuple(oldtuple);
2602 
2603  /* signal tuple should be re-fetched if used */
2604  newtuple = NULL;
2605  }
2606  }
2607 
2608  return true;
2609 }
2610 
2611 void
2613 {
2614  TriggerDesc *trigdesc;
2615  int i;
2616  TriggerData LocTriggerData = {0};
2617 
2618  trigdesc = relinfo->ri_TrigDesc;
2619 
2620  if (trigdesc == NULL)
2621  return;
2622  if (!trigdesc->trig_delete_before_statement)
2623  return;
2624 
2625  /* no-op if we already fired BS triggers in this context */
2627  CMD_DELETE))
2628  return;
2629 
2630  LocTriggerData.type = T_TriggerData;
2631  LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
2633  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2634  for (i = 0; i < trigdesc->numtriggers; i++)
2635  {
2636  Trigger *trigger = &trigdesc->triggers[i];
2637  HeapTuple newtuple;
2638 
2639  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2640  TRIGGER_TYPE_STATEMENT,
2641  TRIGGER_TYPE_BEFORE,
2642  TRIGGER_TYPE_DELETE))
2643  continue;
2644  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2645  NULL, NULL, NULL))
2646  continue;
2647 
2648  LocTriggerData.tg_trigger = trigger;
2649  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2650  i,
2651  relinfo->ri_TrigFunctions,
2652  relinfo->ri_TrigInstrument,
2653  GetPerTupleMemoryContext(estate));
2654 
2655  if (newtuple)
2656  ereport(ERROR,
2657  (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2658  errmsg("BEFORE STATEMENT trigger cannot return a value")));
2659  }
2660 }
2661 
2662 void
2664  TransitionCaptureState *transition_capture)
2665 {
2666  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2667 
2668  if (trigdesc && trigdesc->trig_delete_after_statement)
2669  AfterTriggerSaveEvent(estate, relinfo, NULL, NULL,
2671  false, NULL, NULL, NIL, NULL, transition_capture,
2672  false);
2673 }
2674 
2675 /*
2676  * Execute BEFORE ROW DELETE triggers.
2677  *
2678  * True indicates caller can proceed with the delete. False indicates caller
2679  * need to suppress the delete and additionally if requested, we need to pass
2680  * back the concurrently updated tuple if any.
2681  */
2682 bool
2684  ResultRelInfo *relinfo,
2685  ItemPointer tupleid,
2686  HeapTuple fdw_trigtuple,
2687  TupleTableSlot **epqslot,
2688  TM_Result *tmresult,
2689  TM_FailureData *tmfd)
2690 {
2691  TupleTableSlot *slot = ExecGetTriggerOldSlot(estate, relinfo);
2692  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2693  bool result = true;
2694  TriggerData LocTriggerData = {0};
2695  HeapTuple trigtuple;
2696  bool should_free = false;
2697  int i;
2698 
2699  Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2700  if (fdw_trigtuple == NULL)
2701  {
2702  TupleTableSlot *epqslot_candidate = NULL;
2703 
2704  if (!GetTupleForTrigger(estate, epqstate, relinfo, tupleid,
2705  LockTupleExclusive, slot, &epqslot_candidate,
2706  tmresult, tmfd))
2707  return false;
2708 
2709  /*
2710  * If the tuple was concurrently updated and the caller of this
2711  * function requested for the updated tuple, skip the trigger
2712  * execution.
2713  */
2714  if (epqslot_candidate != NULL && epqslot != NULL)
2715  {
2716  *epqslot = epqslot_candidate;
2717  return false;
2718  }
2719 
2720  trigtuple = ExecFetchSlotHeapTuple(slot, true, &should_free);
2721  }
2722  else
2723  {
2724  trigtuple = fdw_trigtuple;
2725  ExecForceStoreHeapTuple(trigtuple, slot, false);
2726  }
2727 
2728  LocTriggerData.type = T_TriggerData;
2729  LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
2732  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2733  for (i = 0; i < trigdesc->numtriggers; i++)
2734  {
2735  HeapTuple newtuple;
2736  Trigger *trigger = &trigdesc->triggers[i];
2737 
2738  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2739  TRIGGER_TYPE_ROW,
2740  TRIGGER_TYPE_BEFORE,
2741  TRIGGER_TYPE_DELETE))
2742  continue;
2743  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2744  NULL, slot, NULL))
2745  continue;
2746 
2747  LocTriggerData.tg_trigslot = slot;
2748  LocTriggerData.tg_trigtuple = trigtuple;
2749  LocTriggerData.tg_trigger = trigger;
2750  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2751  i,
2752  relinfo->ri_TrigFunctions,
2753  relinfo->ri_TrigInstrument,
2754  GetPerTupleMemoryContext(estate));
2755  if (newtuple == NULL)
2756  {
2757  result = false; /* tell caller to suppress delete */
2758  break;
2759  }
2760  if (newtuple != trigtuple)
2761  heap_freetuple(newtuple);
2762  }
2763  if (should_free)
2764  heap_freetuple(trigtuple);
2765 
2766  return result;
2767 }
2768 
2769 /*
2770  * Note: is_crosspart_update must be true if the DELETE is being performed
2771  * as part of a cross-partition update.
2772  */
2773 void
2775  ResultRelInfo *relinfo,
2776  ItemPointer tupleid,
2777  HeapTuple fdw_trigtuple,
2778  TransitionCaptureState *transition_capture,
2779  bool is_crosspart_update)
2780 {
2781  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2782 
2783  if ((trigdesc && trigdesc->trig_delete_after_row) ||
2784  (transition_capture && transition_capture->tcs_delete_old_table))
2785  {
2786  TupleTableSlot *slot = ExecGetTriggerOldSlot(estate, relinfo);
2787 
2788  Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2789  if (fdw_trigtuple == NULL)
2790  GetTupleForTrigger(estate,
2791  NULL,
2792  relinfo,
2793  tupleid,
2795  slot,
2796  NULL,
2797  NULL,
2798  NULL);
2799  else
2800  ExecForceStoreHeapTuple(fdw_trigtuple, slot, false);
2801 
2802  AfterTriggerSaveEvent(estate, relinfo, NULL, NULL,
2804  true, slot, NULL, NIL, NULL,
2805  transition_capture,
2806  is_crosspart_update);
2807  }
2808 }
2809 
2810 bool
2812  HeapTuple trigtuple)
2813 {
2814  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2815  TupleTableSlot *slot = ExecGetTriggerOldSlot(estate, relinfo);
2816  TriggerData LocTriggerData = {0};
2817  int i;
2818 
2819  LocTriggerData.type = T_TriggerData;
2820  LocTriggerData.tg_event = TRIGGER_EVENT_DELETE |
2823  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2824 
2825  ExecForceStoreHeapTuple(trigtuple, slot, false);
2826 
2827  for (i = 0; i < trigdesc->numtriggers; i++)
2828  {
2829  HeapTuple rettuple;
2830  Trigger *trigger = &trigdesc->triggers[i];
2831 
2832  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2833  TRIGGER_TYPE_ROW,
2834  TRIGGER_TYPE_INSTEAD,
2835  TRIGGER_TYPE_DELETE))
2836  continue;
2837  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2838  NULL, slot, NULL))
2839  continue;
2840 
2841  LocTriggerData.tg_trigslot = slot;
2842  LocTriggerData.tg_trigtuple = trigtuple;
2843  LocTriggerData.tg_trigger = trigger;
2844  rettuple = ExecCallTriggerFunc(&LocTriggerData,
2845  i,
2846  relinfo->ri_TrigFunctions,
2847  relinfo->ri_TrigInstrument,
2848  GetPerTupleMemoryContext(estate));
2849  if (rettuple == NULL)
2850  return false; /* Delete was suppressed */
2851  if (rettuple != trigtuple)
2852  heap_freetuple(rettuple);
2853  }
2854  return true;
2855 }
2856 
2857 void
2859 {
2860  TriggerDesc *trigdesc;
2861  int i;
2862  TriggerData LocTriggerData = {0};
2863  Bitmapset *updatedCols;
2864 
2865  trigdesc = relinfo->ri_TrigDesc;
2866 
2867  if (trigdesc == NULL)
2868  return;
2869  if (!trigdesc->trig_update_before_statement)
2870  return;
2871 
2872  /* no-op if we already fired BS triggers in this context */
2874  CMD_UPDATE))
2875  return;
2876 
2877  /* statement-level triggers operate on the parent table */
2878  Assert(relinfo->ri_RootResultRelInfo == NULL);
2879 
2880  updatedCols = ExecGetAllUpdatedCols(relinfo, estate);
2881 
2882  LocTriggerData.type = T_TriggerData;
2883  LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
2885  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2886  LocTriggerData.tg_updatedcols = updatedCols;
2887  for (i = 0; i < trigdesc->numtriggers; i++)
2888  {
2889  Trigger *trigger = &trigdesc->triggers[i];
2890  HeapTuple newtuple;
2891 
2892  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2893  TRIGGER_TYPE_STATEMENT,
2894  TRIGGER_TYPE_BEFORE,
2895  TRIGGER_TYPE_UPDATE))
2896  continue;
2897  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2898  updatedCols, NULL, NULL))
2899  continue;
2900 
2901  LocTriggerData.tg_trigger = trigger;
2902  newtuple = ExecCallTriggerFunc(&LocTriggerData,
2903  i,
2904  relinfo->ri_TrigFunctions,
2905  relinfo->ri_TrigInstrument,
2906  GetPerTupleMemoryContext(estate));
2907 
2908  if (newtuple)
2909  ereport(ERROR,
2910  (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2911  errmsg("BEFORE STATEMENT trigger cannot return a value")));
2912  }
2913 }
2914 
2915 void
2917  TransitionCaptureState *transition_capture)
2918 {
2919  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2920 
2921  /* statement-level triggers operate on the parent table */
2922  Assert(relinfo->ri_RootResultRelInfo == NULL);
2923 
2924  if (trigdesc && trigdesc->trig_update_after_statement)
2925  AfterTriggerSaveEvent(estate, relinfo, NULL, NULL,
2927  false, NULL, NULL, NIL,
2928  ExecGetAllUpdatedCols(relinfo, estate),
2929  transition_capture,
2930  false);
2931 }
2932 
2933 bool
2935  ResultRelInfo *relinfo,
2936  ItemPointer tupleid,
2937  HeapTuple fdw_trigtuple,
2938  TupleTableSlot *newslot,
2939  TM_Result *tmresult,
2940  TM_FailureData *tmfd)
2941 {
2942  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2943  TupleTableSlot *oldslot = ExecGetTriggerOldSlot(estate, relinfo);
2944  HeapTuple newtuple = NULL;
2945  HeapTuple trigtuple;
2946  bool should_free_trig = false;
2947  bool should_free_new = false;
2948  TriggerData LocTriggerData = {0};
2949  int i;
2950  Bitmapset *updatedCols;
2951  LockTupleMode lockmode;
2952 
2953  /* Determine lock mode to use */
2954  lockmode = ExecUpdateLockMode(estate, relinfo);
2955 
2956  Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid));
2957  if (fdw_trigtuple == NULL)
2958  {
2959  TupleTableSlot *epqslot_candidate = NULL;
2960 
2961  /* get a copy of the on-disk tuple we are planning to update */
2962  if (!GetTupleForTrigger(estate, epqstate, relinfo, tupleid,
2963  lockmode, oldslot, &epqslot_candidate,
2964  tmresult, tmfd))
2965  return false; /* cancel the update action */
2966 
2967  /*
2968  * In READ COMMITTED isolation level it's possible that target tuple
2969  * was changed due to concurrent update. In that case we have a raw
2970  * subplan output tuple in epqslot_candidate, and need to form a new
2971  * insertable tuple using ExecGetUpdateNewTuple to replace the one we
2972  * received in newslot. Neither we nor our callers have any further
2973  * interest in the passed-in tuple, so it's okay to overwrite newslot
2974  * with the newer data.
2975  */
2976  if (epqslot_candidate != NULL)
2977  {
2978  TupleTableSlot *epqslot_clean;
2979 
2980  epqslot_clean = ExecGetUpdateNewTuple(relinfo, epqslot_candidate,
2981  oldslot);
2982 
2983  /*
2984  * Typically, the caller's newslot was also generated by
2985  * ExecGetUpdateNewTuple, so that epqslot_clean will be the same
2986  * slot and copying is not needed. But do the right thing if it
2987  * isn't.
2988  */
2989  if (unlikely(newslot != epqslot_clean))
2990  ExecCopySlot(newslot, epqslot_clean);
2991 
2992  /*
2993  * At this point newslot contains a virtual tuple that may
2994  * reference some fields of oldslot's tuple in some disk buffer.
2995  * If that tuple is in a different page than the original target
2996  * tuple, then our only pin on that buffer is oldslot's, and we're
2997  * about to release it. Hence we'd better materialize newslot to
2998  * ensure it doesn't contain references into an unpinned buffer.
2999  * (We'd materialize it below anyway, but too late for safety.)
3000  */
3001  ExecMaterializeSlot(newslot);
3002  }
3003 
3004  /*
3005  * Here we convert oldslot to a materialized slot holding trigtuple.
3006  * Neither slot passed to the triggers will hold any buffer pin.
3007  */
3008  trigtuple = ExecFetchSlotHeapTuple(oldslot, true, &should_free_trig);
3009  }
3010  else
3011  {
3012  /* Put the FDW-supplied tuple into oldslot to unify the cases */
3013  ExecForceStoreHeapTuple(fdw_trigtuple, oldslot, false);
3014  trigtuple = fdw_trigtuple;
3015  }
3016 
3017  LocTriggerData.type = T_TriggerData;
3018  LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
3021  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
3022  updatedCols = ExecGetAllUpdatedCols(relinfo, estate);
3023  LocTriggerData.tg_updatedcols = updatedCols;
3024  for (i = 0; i < trigdesc->numtriggers; i++)
3025  {
3026  Trigger *trigger = &trigdesc->triggers[i];
3027  HeapTuple oldtuple;
3028 
3029  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
3030  TRIGGER_TYPE_ROW,
3031  TRIGGER_TYPE_BEFORE,
3032  TRIGGER_TYPE_UPDATE))
3033  continue;
3034  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
3035  updatedCols, oldslot, newslot))
3036  continue;
3037 
3038  if (!newtuple)
3039  newtuple = ExecFetchSlotHeapTuple(newslot, true, &should_free_new);
3040 
3041  LocTriggerData.tg_trigslot = oldslot;
3042  LocTriggerData.tg_trigtuple = trigtuple;
3043  LocTriggerData.tg_newtuple = oldtuple = newtuple;
3044  LocTriggerData.tg_newslot = newslot;
3045  LocTriggerData.tg_trigger = trigger;
3046  newtuple = ExecCallTriggerFunc(&LocTriggerData,
3047  i,
3048  relinfo->ri_TrigFunctions,
3049  relinfo->ri_TrigInstrument,
3050  GetPerTupleMemoryContext(estate));
3051 
3052  if (newtuple == NULL)
3053  {
3054  if (should_free_trig)
3055  heap_freetuple(trigtuple);
3056  if (should_free_new)
3057  heap_freetuple(oldtuple);
3058  return false; /* "do nothing" */
3059  }
3060  else if (newtuple != oldtuple)
3061  {
3062  ExecForceStoreHeapTuple(newtuple, newslot, false);
3063 
3064  /*
3065  * If the tuple returned by the trigger / being stored, is the old
3066  * row version, and the heap tuple passed to the trigger was
3067  * allocated locally, materialize the slot. Otherwise we might
3068  * free it while still referenced by the slot.
3069  */
3070  if (should_free_trig && newtuple == trigtuple)
3071  ExecMaterializeSlot(newslot);
3072 
3073  if (should_free_new)
3074  heap_freetuple(oldtuple);
3075 
3076  /* signal tuple should be re-fetched if used */
3077  newtuple = NULL;
3078  }
3079  }
3080  if (should_free_trig)
3081  heap_freetuple(trigtuple);
3082 
3083  return true;
3084 }
3085 
3086 /*
3087  * Note: 'src_partinfo' and 'dst_partinfo', when non-NULL, refer to the source
3088  * and destination partitions, respectively, of a cross-partition update of
3089  * the root partitioned table mentioned in the query, given by 'relinfo'.
3090  * 'tupleid' in that case refers to the ctid of the "old" tuple in the source
3091  * partition, and 'newslot' contains the "new" tuple in the destination
3092  * partition. This interface allows to support the requirements of
3093  * ExecCrossPartitionUpdateForeignKey(); is_crosspart_update must be true in
3094  * that case.
3095  */
3096 void
3098  ResultRelInfo *src_partinfo,
3099  ResultRelInfo *dst_partinfo,
3100  ItemPointer tupleid,
3101  HeapTuple fdw_trigtuple,
3102  TupleTableSlot *newslot,
3103  List *recheckIndexes,
3104  TransitionCaptureState *transition_capture,
3105  bool is_crosspart_update)
3106 {
3107  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
3108 
3109  if ((trigdesc && trigdesc->trig_update_after_row) ||
3110  (transition_capture &&
3111  (transition_capture->tcs_update_old_table ||
3112  transition_capture->tcs_update_new_table)))
3113  {
3114  /*
3115  * Note: if the UPDATE is converted into a DELETE+INSERT as part of
3116  * update-partition-key operation, then this function is also called
3117  * separately for DELETE and INSERT to capture transition table rows.
3118  * In such case, either old tuple or new tuple can be NULL.
3119  */
3120  TupleTableSlot *oldslot;
3121  ResultRelInfo *tupsrc;
3122 
3123  Assert((src_partinfo != NULL && dst_partinfo != NULL) ||
3124  !is_crosspart_update);
3125 
3126  tupsrc = src_partinfo ? src_partinfo : relinfo;
3127  oldslot = ExecGetTriggerOldSlot(estate, tupsrc);
3128 
3129  if (fdw_trigtuple == NULL && ItemPointerIsValid(tupleid))
3130  GetTupleForTrigger(estate,
3131  NULL,
3132  tupsrc,
3133  tupleid,
3135  oldslot,
3136  NULL,
3137  NULL,
3138  NULL);
3139  else if (fdw_trigtuple != NULL)
3140  ExecForceStoreHeapTuple(fdw_trigtuple, oldslot, false);
3141  else
3142  ExecClearTuple(oldslot);
3143 
3144  AfterTriggerSaveEvent(estate, relinfo,
3145  src_partinfo, dst_partinfo,
3147  true,
3148  oldslot, newslot, recheckIndexes,
3149  ExecGetAllUpdatedCols(relinfo, estate),
3150  transition_capture,
3151  is_crosspart_update);
3152  }
3153 }
3154 
3155 bool
3157  HeapTuple trigtuple, TupleTableSlot *newslot)
3158 {
3159  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
3160  TupleTableSlot *oldslot = ExecGetTriggerOldSlot(estate, relinfo);
3161  HeapTuple newtuple = NULL;
3162  bool should_free;
3163  TriggerData LocTriggerData = {0};
3164  int i;
3165 
3166  LocTriggerData.type = T_TriggerData;
3167  LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE |
3170  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
3171 
3172  ExecForceStoreHeapTuple(trigtuple, oldslot, false);
3173 
3174  for (i = 0; i < trigdesc->numtriggers; i++)
3175  {
3176  Trigger *trigger = &trigdesc->triggers[i];
3177  HeapTuple oldtuple;
3178 
3179  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
3180  TRIGGER_TYPE_ROW,
3181  TRIGGER_TYPE_INSTEAD,
3182  TRIGGER_TYPE_UPDATE))
3183  continue;
3184  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
3185  NULL, oldslot, newslot))
3186  continue;
3187 
3188  if (!newtuple)
3189  newtuple = ExecFetchSlotHeapTuple(newslot, true, &should_free);
3190 
3191  LocTriggerData.tg_trigslot = oldslot;
3192  LocTriggerData.tg_trigtuple = trigtuple;
3193  LocTriggerData.tg_newslot = newslot;
3194  LocTriggerData.tg_newtuple = oldtuple = newtuple;
3195 
3196  LocTriggerData.tg_trigger = trigger;
3197  newtuple = ExecCallTriggerFunc(&LocTriggerData,
3198  i,
3199  relinfo->ri_TrigFunctions,
3200  relinfo->ri_TrigInstrument,
3201  GetPerTupleMemoryContext(estate));
3202  if (newtuple == NULL)
3203  {
3204  return false; /* "do nothing" */
3205  }
3206  else if (newtuple != oldtuple)
3207  {
3208  ExecForceStoreHeapTuple(newtuple, newslot, false);
3209 
3210  if (should_free)
3211  heap_freetuple(oldtuple);
3212 
3213  /* signal tuple should be re-fetched if used */
3214  newtuple = NULL;
3215  }
3216  }
3217 
3218  return true;
3219 }
3220 
3221 void
3223 {
3224  TriggerDesc *trigdesc;
3225  int i;
3226  TriggerData LocTriggerData = {0};
3227 
3228  trigdesc = relinfo->ri_TrigDesc;
3229 
3230  if (trigdesc == NULL)
3231  return;
3232  if (!trigdesc->trig_truncate_before_statement)
3233  return;
3234 
3235  LocTriggerData.type = T_TriggerData;
3236  LocTriggerData.tg_event = TRIGGER_EVENT_TRUNCATE |
3238  LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
3239 
3240  for (i = 0; i < trigdesc->numtriggers; i++)
3241  {
3242  Trigger *trigger = &trigdesc->triggers[i];
3243  HeapTuple newtuple;
3244 
3245  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
3246  TRIGGER_TYPE_STATEMENT,
3247  TRIGGER_TYPE_BEFORE,
3248  TRIGGER_TYPE_TRUNCATE))
3249  continue;
3250  if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
3251  NULL, NULL, NULL))
3252  continue;
3253 
3254  LocTriggerData.tg_trigger = trigger;
3255  newtuple = ExecCallTriggerFunc(&LocTriggerData,
3256  i,
3257  relinfo->ri_TrigFunctions,
3258  relinfo->ri_TrigInstrument,
3259  GetPerTupleMemoryContext(estate));
3260 
3261  if (newtuple)
3262  ereport(ERROR,
3263  (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
3264  errmsg("BEFORE STATEMENT trigger cannot return a value")));
3265  }
3266 }
3267 
3268 void
3270 {
3271  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
3272 
3273  if (trigdesc && trigdesc->trig_truncate_after_statement)
3274  AfterTriggerSaveEvent(estate, relinfo,
3275  NULL, NULL,
3277  false, NULL, NULL, NIL, NULL, NULL,
3278  false);
3279 }
3280 
3281 
3282 /*
3283  * Fetch tuple into "oldslot", dealing with locking and EPQ if necessary
3284  */
3285 static bool
3287  EPQState *epqstate,
3288  ResultRelInfo *relinfo,
3289  ItemPointer tid,
3290  LockTupleMode lockmode,
3291  TupleTableSlot *oldslot,
3292  TupleTableSlot **epqslot,
3293  TM_Result *tmresultp,
3294  TM_FailureData *tmfdp)
3295 {
3296  Relation relation = relinfo->ri_RelationDesc;
3297 
3298  if (epqslot != NULL)
3299  {
3300  TM_Result test;
3301  TM_FailureData tmfd;
3302  int lockflags = 0;
3303 
3304  *epqslot = NULL;
3305 
3306  /* caller must pass an epqstate if EvalPlanQual is possible */
3307  Assert(epqstate != NULL);
3308 
3309  /*
3310  * lock tuple for update
3311  */
3313  lockflags |= TUPLE_LOCK_FLAG_FIND_LAST_VERSION;
3314  test = table_tuple_lock(relation, tid, estate->es_snapshot, oldslot,
3315  estate->es_output_cid,
3316  lockmode, LockWaitBlock,
3317  lockflags,
3318  &tmfd);
3319 
3320  /* Let the caller know about the status of this operation */
3321  if (tmresultp)
3322  *tmresultp = test;
3323  if (tmfdp)
3324  *tmfdp = tmfd;
3325 
3326  switch (test)
3327  {
3328  case TM_SelfModified:
3329 
3330  /*
3331  * The target tuple was already updated or deleted by the
3332  * current command, or by a later command in the current
3333  * transaction. We ignore the tuple in the former case, and
3334  * throw error in the latter case, for the same reasons
3335  * enumerated in ExecUpdate and ExecDelete in
3336  * nodeModifyTable.c.
3337  */
3338  if (tmfd.cmax != estate->es_output_cid)
3339  ereport(ERROR,
3340  (errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
3341  errmsg("tuple to be updated was already modified by an operation triggered by the current command"),
3342  errhint("Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
3343 
3344  /* treat it as deleted; do not process */
3345  return false;
3346 
3347  case TM_Ok:
3348  if (tmfd.traversed)
3349  {
3350  /*
3351  * Recheck the tuple using EPQ. For MERGE, we leave this
3352  * to the caller (it must do additional rechecking, and
3353  * might end up executing a different action entirely).
3354  */
3355  if (estate->es_plannedstmt->commandType == CMD_MERGE)
3356  {
3357  if (tmresultp)
3358  *tmresultp = TM_Updated;
3359  return false;
3360  }
3361 
3362  *epqslot = EvalPlanQual(epqstate,
3363  relation,
3364  relinfo->ri_RangeTableIndex,
3365  oldslot);
3366 
3367  /*
3368  * If PlanQual failed for updated tuple - we must not
3369  * process this tuple!
3370  */
3371  if (TupIsNull(*epqslot))
3372  {
3373  *epqslot = NULL;
3374  return false;
3375  }
3376  }
3377  break;
3378 
3379  case TM_Updated:
3381  ereport(ERROR,
3383  errmsg("could not serialize access due to concurrent update")));
3384  elog(ERROR, "unexpected table_tuple_lock status: %u", test);
3385  break;
3386 
3387  case TM_Deleted:
3389  ereport(ERROR,
3391  errmsg("could not serialize access due to concurrent delete")));
3392  /* tuple was deleted */
3393  return false;
3394 
3395  case TM_Invisible:
3396  elog(ERROR, "attempted to lock invisible tuple");
3397  break;
3398 
3399  default:
3400  elog(ERROR, "unrecognized table_tuple_lock status: %u", test);
3401  return false; /* keep compiler quiet */
3402  }
3403  }
3404  else
3405  {
3406  /*
3407  * We expect the tuple to be present, thus very simple error handling
3408  * suffices.
3409  */
3410  if (!table_tuple_fetch_row_version(relation, tid, SnapshotAny,
3411  oldslot))
3412  elog(ERROR, "failed to fetch tuple for trigger");
3413  }
3414 
3415  return true;
3416 }
3417 
3418 /*
3419  * Is trigger enabled to fire?
3420  */
3421 static bool
3423  Trigger *trigger, TriggerEvent event,
3424  Bitmapset *modifiedCols,
3425  TupleTableSlot *oldslot, TupleTableSlot *newslot)
3426 {
3427  /* Check replication-role-dependent enable state */
3429  {
3430  if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
3431  trigger->tgenabled == TRIGGER_DISABLED)
3432  return false;
3433  }
3434  else /* ORIGIN or LOCAL role */
3435  {
3436  if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
3437  trigger->tgenabled == TRIGGER_DISABLED)
3438  return false;
3439  }
3440 
3441  /*
3442  * Check for column-specific trigger (only possible for UPDATE, and in
3443  * fact we *must* ignore tgattr for other event types)
3444  */
3445  if (trigger->tgnattr > 0 && TRIGGER_FIRED_BY_UPDATE(event))
3446  {
3447  int i;
3448  bool modified;
3449 
3450  modified = false;
3451  for (i = 0; i < trigger->tgnattr; i++)
3452  {
3454  modifiedCols))
3455  {
3456  modified = true;
3457  break;
3458  }
3459  }
3460  if (!modified)
3461  return false;
3462  }
3463 
3464  /* Check for WHEN clause */
3465  if (trigger->tgqual)
3466  {
3467  ExprState **predicate;
3468  ExprContext *econtext;
3469  MemoryContext oldContext;
3470  int i;
3471 
3472  Assert(estate != NULL);
3473 
3474  /*
3475  * trigger is an element of relinfo->ri_TrigDesc->triggers[]; find the
3476  * matching element of relinfo->ri_TrigWhenExprs[]
3477  */
3478  i = trigger - relinfo->ri_TrigDesc->triggers;
3479  predicate = &relinfo->ri_TrigWhenExprs[i];
3480 
3481  /*
3482  * If first time through for this WHEN expression, build expression
3483  * nodetrees for it. Keep them in the per-query memory context so
3484  * they'll survive throughout the query.
3485  */
3486  if (*predicate == NULL)
3487  {
3488  Node *tgqual;
3489 
3490  oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
3491  tgqual = stringToNode(trigger->tgqual);
3492  /* Change references to OLD and NEW to INNER_VAR and OUTER_VAR */
3495  /* ExecPrepareQual wants implicit-AND form */
3496  tgqual = (Node *) make_ands_implicit((Expr *) tgqual);
3497  *predicate = ExecPrepareQual((List *) tgqual, estate);
3498  MemoryContextSwitchTo(oldContext);
3499  }
3500 
3501  /*
3502  * We will use the EState's per-tuple context for evaluating WHEN
3503  * expressions (creating it if it's not already there).
3504  */
3505  econtext = GetPerTupleExprContext(estate);
3506 
3507  /*
3508  * Finally evaluate the expression, making the old and/or new tuples
3509  * available as INNER_VAR/OUTER_VAR respectively.
3510  */
3511  econtext->ecxt_innertuple = oldslot;
3512  econtext->ecxt_outertuple = newslot;
3513  if (!ExecQual(*predicate, econtext))
3514  return false;
3515  }
3516 
3517  return true;
3518 }
3519 
3520 
3521 /* ----------
3522  * After-trigger stuff
3523  *
3524  * The AfterTriggersData struct holds data about pending AFTER trigger events
3525  * during the current transaction tree. (BEFORE triggers are fired
3526  * immediately so we don't need any persistent state about them.) The struct
3527  * and most of its subsidiary data are kept in TopTransactionContext; however
3528  * some data that can be discarded sooner appears in the CurTransactionContext
3529  * of the relevant subtransaction. Also, the individual event records are
3530  * kept in a separate sub-context of TopTransactionContext. This is done
3531  * mainly so that it's easy to tell from a memory context dump how much space
3532  * is being eaten by trigger events.
3533  *
3534  * Because the list of pending events can grow large, we go to some
3535  * considerable effort to minimize per-event memory consumption. The event
3536  * records are grouped into chunks and common data for similar events in the
3537  * same chunk is only stored once.
3538  *
3539  * XXX We need to be able to save the per-event data in a file if it grows too
3540  * large.
3541  * ----------
3542  */
3543 
3544 /* Per-trigger SET CONSTRAINT status */
3546 {
3550 
3552 
3553 /*
3554  * SET CONSTRAINT intra-transaction status.
3555  *
3556  * We make this a single palloc'd object so it can be copied and freed easily.
3557  *
3558  * all_isset and all_isdeferred are used to keep track
3559  * of SET CONSTRAINTS ALL {DEFERRED, IMMEDIATE}.
3560  *
3561  * trigstates[] stores per-trigger tgisdeferred settings.
3562  */
3564 {
3567  int numstates; /* number of trigstates[] entries in use */
3568  int numalloc; /* allocated size of trigstates[] */
3571 
3573 
3574 
3575 /*
3576  * Per-trigger-event data
3577  *
3578  * The actual per-event data, AfterTriggerEventData, includes DONE/IN_PROGRESS
3579  * status bits, up to two tuple CTIDs, and optionally two OIDs of partitions.
3580  * Each event record also has an associated AfterTriggerSharedData that is
3581  * shared across all instances of similar events within a "chunk".
3582  *
3583  * For row-level triggers, we arrange not to waste storage on unneeded ctid
3584  * fields. Updates of regular tables use two; inserts and deletes of regular
3585  * tables use one; foreign tables always use zero and save the tuple(s) to a
3586  * tuplestore. AFTER_TRIGGER_FDW_FETCH directs AfterTriggerExecute() to
3587  * retrieve a fresh tuple or pair of tuples from that tuplestore, while
3588  * AFTER_TRIGGER_FDW_REUSE directs it to use the most-recently-retrieved
3589  * tuple(s). This permits storing tuples once regardless of the number of
3590  * row-level triggers on a foreign table.
3591  *
3592  * When updates on partitioned tables cause rows to move between partitions,
3593  * the OIDs of both partitions are stored too, so that the tuples can be
3594  * fetched; such entries are marked AFTER_TRIGGER_CP_UPDATE (for "cross-
3595  * partition update").
3596  *
3597  * Note that we need triggers on foreign tables to be fired in exactly the
3598  * order they were queued, so that the tuples come out of the tuplestore in
3599  * the right order. To ensure that, we forbid deferrable (constraint)
3600  * triggers on foreign tables. This also ensures that such triggers do not
3601  * get deferred into outer trigger query levels, meaning that it's okay to
3602  * destroy the tuplestore at the end of the query level.
3603  *
3604  * Statement-level triggers always bear AFTER_TRIGGER_1CTID, though they
3605  * require no ctid field. We lack the flag bit space to neatly represent that
3606  * distinct case, and it seems unlikely to be worth much trouble.
3607  *
3608  * Note: ats_firing_id is initially zero and is set to something else when
3609  * AFTER_TRIGGER_IN_PROGRESS is set. It indicates which trigger firing
3610  * cycle the trigger will be fired in (or was fired in, if DONE is set).
3611  * Although this is mutable state, we can keep it in AfterTriggerSharedData
3612  * because all instances of the same type of event in a given event list will
3613  * be fired at the same time, if they were queued between the same firing
3614  * cycles. So we need only ensure that ats_firing_id is zero when attaching
3615  * a new event to an existing AfterTriggerSharedData record.
3616  */
3618 
3619 #define AFTER_TRIGGER_OFFSET 0x07FFFFFF /* must be low-order bits */
3620 #define AFTER_TRIGGER_DONE 0x80000000
3621 #define AFTER_TRIGGER_IN_PROGRESS 0x40000000
3622 /* bits describing the size and tuple sources of this event */
3623 #define AFTER_TRIGGER_FDW_REUSE 0x00000000
3624 #define AFTER_TRIGGER_FDW_FETCH 0x20000000
3625 #define AFTER_TRIGGER_1CTID 0x10000000
3626 #define AFTER_TRIGGER_2CTID 0x30000000
3627 #define AFTER_TRIGGER_CP_UPDATE 0x08000000
3628 #define AFTER_TRIGGER_TUP_BITS 0x38000000
3630 
3632 {
3633  TriggerEvent ats_event; /* event type indicator, see trigger.h */
3634  Oid ats_tgoid; /* the trigger's ID */
3635  Oid ats_relid; /* the relation it's on */
3636  CommandId ats_firing_id; /* ID for firing cycle */
3637  struct AfterTriggersTableData *ats_table; /* transition table access */
3638  Bitmapset *ats_modifiedcols; /* modified columns */
3640 
3642 
3644 {
3645  TriggerFlags ate_flags; /* status bits and offset to shared data */
3646  ItemPointerData ate_ctid1; /* inserted, deleted, or old updated tuple */
3647  ItemPointerData ate_ctid2; /* new updated tuple */
3648 
3649  /*
3650  * During a cross-partition update of a partitioned table, we also store
3651  * the OIDs of source and destination partitions that are needed to fetch
3652  * the old (ctid1) and the new tuple (ctid2) from, respectively.
3653  */
3657 
3658 /* AfterTriggerEventData, minus ate_src_part, ate_dst_part */
3660 {
3665 
3666 /* AfterTriggerEventData, minus ate_*_part and ate_ctid2 */
3668 {
3669  TriggerFlags ate_flags; /* status bits and offset to shared data */
3670  ItemPointerData ate_ctid1; /* inserted, deleted, or old updated tuple */
3672 
3673 /* AfterTriggerEventData, minus ate_*_part, ate_ctid1 and ate_ctid2 */
3675 {
3676  TriggerFlags ate_flags; /* status bits and offset to shared data */
3678 
3679 #define SizeofTriggerEvent(evt) \
3680  (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_CP_UPDATE ? \
3681  sizeof(AfterTriggerEventData) : \
3682  (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_2CTID ? \
3683  sizeof(AfterTriggerEventDataNoOids) : \
3684  (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_1CTID ? \
3685  sizeof(AfterTriggerEventDataOneCtid) : \
3686  sizeof(AfterTriggerEventDataZeroCtids))))
3687 
3688 #define GetTriggerSharedData(evt) \
3689  ((AfterTriggerShared) ((char *) (evt) + ((evt)->ate_flags & AFTER_TRIGGER_OFFSET)))
3690 
3691 /*
3692  * To avoid palloc overhead, we keep trigger events in arrays in successively-
3693  * larger chunks (a slightly more sophisticated version of an expansible
3694  * array). The space between CHUNK_DATA_START and freeptr is occupied by
3695  * AfterTriggerEventData records; the space between endfree and endptr is
3696  * occupied by AfterTriggerSharedData records.
3697  */
3699 {
3700  struct AfterTriggerEventChunk *next; /* list link */
3701  char *freeptr; /* start of free space in chunk */
3702  char *endfree; /* end of free space in chunk */
3703  char *endptr; /* end of chunk */
3704  /* event data follows here */
3706 
3707 #define CHUNK_DATA_START(cptr) ((char *) (cptr) + MAXALIGN(sizeof(AfterTriggerEventChunk)))
3708 
3709 /* A list of events */
3711 {
3714  char *tailfree; /* freeptr of tail chunk */
3716 
3717 /* Macros to help in iterating over a list of events */
3718 #define for_each_chunk(cptr, evtlist) \
3719  for (cptr = (evtlist).head; cptr != NULL; cptr = cptr->next)
3720 #define for_each_event(eptr, cptr) \
3721  for (eptr = (AfterTriggerEvent) CHUNK_DATA_START(cptr); \
3722  (char *) eptr < (cptr)->freeptr; \
3723  eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
3724 /* Use this if no special per-chunk processing is needed */
3725 #define for_each_event_chunk(eptr, cptr, evtlist) \
3726  for_each_chunk(cptr, evtlist) for_each_event(eptr, cptr)
3727 
3728 /* Macros for iterating from a start point that might not be list start */
3729 #define for_each_chunk_from(cptr) \
3730  for (; cptr != NULL; cptr = cptr->next)
3731 #define for_each_event_from(eptr, cptr) \
3732  for (; \
3733  (char *) eptr < (cptr)->freeptr; \
3734  eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
3735 
3736 
3737 /*
3738  * All per-transaction data for the AFTER TRIGGERS module.
3739  *
3740  * AfterTriggersData has the following fields:
3741  *
3742  * firing_counter is incremented for each call of afterTriggerInvokeEvents.
3743  * We mark firable events with the current firing cycle's ID so that we can
3744  * tell which ones to work on. This ensures sane behavior if a trigger
3745  * function chooses to do SET CONSTRAINTS: the inner SET CONSTRAINTS will
3746  * only fire those events that weren't already scheduled for firing.
3747  *
3748  * state keeps track of the transaction-local effects of SET CONSTRAINTS.
3749  * This is saved and restored across failed subtransactions.
3750  *
3751  * events is the current list of deferred events. This is global across
3752  * all subtransactions of the current transaction. In a subtransaction
3753  * abort, we know that the events added by the subtransaction are at the
3754  * end of the list, so it is relatively easy to discard them. The event
3755  * list chunks themselves are stored in event_cxt.
3756  *
3757  * query_depth is the current depth of nested AfterTriggerBeginQuery calls
3758  * (-1 when the stack is empty).
3759  *
3760  * query_stack[query_depth] is the per-query-level data, including these fields:
3761  *
3762  * events is a list of AFTER trigger events queued by the current query.
3763  * None of these are valid until the matching AfterTriggerEndQuery call
3764  * occurs. At that point we fire immediate-mode triggers, and append any
3765  * deferred events to the main events list.
3766  *
3767  * fdw_tuplestore is a tuplestore containing the foreign-table tuples
3768  * needed by events queued by the current query. (Note: we use just one
3769  * tuplestore even though more than one foreign table might be involved.
3770  * This is okay because tuplestores don't really care what's in the tuples
3771  * they store; but it's possible that someday it'd break.)
3772  *
3773  * tables is a List of AfterTriggersTableData structs for target tables
3774  * of the current query (see below).
3775  *
3776  * maxquerydepth is just the allocated length of query_stack.
3777  *
3778  * trans_stack holds per-subtransaction data, including these fields:
3779  *
3780  * state is NULL or a pointer to a saved copy of the SET CONSTRAINTS
3781  * state data. Each subtransaction level that modifies that state first
3782  * saves a copy, which we use to restore the state if we abort.
3783  *
3784  * events is a copy of the events head/tail pointers,
3785  * which we use to restore those values during subtransaction abort.
3786  *
3787  * query_depth is the subtransaction-start-time value of query_depth,
3788  * which we similarly use to clean up at subtransaction abort.
3789  *
3790  * firing_counter is the subtransaction-start-time value of firing_counter.
3791  * We use this to recognize which deferred triggers were fired (or marked
3792  * for firing) within an aborted subtransaction.
3793  *
3794  * We use GetCurrentTransactionNestLevel() to determine the correct array
3795  * index in trans_stack. maxtransdepth is the number of allocated entries in
3796  * trans_stack. (By not keeping our own stack pointer, we can avoid trouble
3797  * in cases where errors during subxact abort cause multiple invocations
3798  * of AfterTriggerEndSubXact() at the same nesting depth.)
3799  *
3800  * We create an AfterTriggersTableData struct for each target table of the
3801  * current query, and each operation mode (INSERT/UPDATE/DELETE), that has
3802  * either transition tables or statement-level triggers. This is used to
3803  * hold the relevant transition tables, as well as info tracking whether
3804  * we already queued the statement triggers. (We use that info to prevent
3805  * firing the same statement triggers more than once per statement, or really
3806  * once per transition table set.) These structs, along with the transition
3807  * table tuplestores, live in the (sub)transaction's CurTransactionContext.
3808  * That's sufficient lifespan because we don't allow transition tables to be
3809  * used by deferrable triggers, so they only need to survive until
3810  * AfterTriggerEndQuery.
3811  */
3815 
3816 typedef struct AfterTriggersData
3817 {
3818  CommandId firing_counter; /* next firing ID to assign */
3819  SetConstraintState state; /* the active S C state */
3820  AfterTriggerEventList events; /* deferred-event list */
3821  MemoryContext event_cxt; /* memory context for events, if any */
3822 
3823  /* per-query-level data: */
3824  AfterTriggersQueryData *query_stack; /* array of structs shown below */
3825  int query_depth; /* current index in above array */
3826  int maxquerydepth; /* allocated len of above array */
3827 
3828  /* per-subtransaction-level data: */
3829  AfterTriggersTransData *trans_stack; /* array of structs shown below */
3830  int maxtransdepth; /* allocated len of above array */
3832 
3834 {
3835  AfterTriggerEventList events; /* events pending from this query */
3836  Tuplestorestate *fdw_tuplestore; /* foreign tuples for said events */
3837  List *tables; /* list of AfterTriggersTableData, see below */
3838 };
3839 
3841 {
3842  /* these fields are just for resetting at subtrans abort: */
3843  SetConstraintState state; /* saved S C state, or NULL if not yet saved */
3844  AfterTriggerEventList events; /* saved list pointer */
3845  int query_depth; /* saved query_depth */
3846  CommandId firing_counter; /* saved firing_counter */
3847 };
3848 
3850 {
3851  /* relid + cmdType form the lookup key for these structs: */
3852  Oid relid; /* target table's OID */
3853  CmdType cmdType; /* event type, CMD_INSERT/UPDATE/DELETE */
3854  bool closed; /* true when no longer OK to add tuples */
3855  bool before_trig_done; /* did we already queue BS triggers? */
3856  bool after_trig_done; /* did we already queue AS triggers? */
3857  AfterTriggerEventList after_trig_events; /* if so, saved list pointer */
3858 
3859  /*
3860  * We maintain separate transition tables for UPDATE/INSERT/DELETE since
3861  * MERGE can run all three actions in a single statement. Note that UPDATE
3862  * needs both old and new transition tables whereas INSERT needs only new,
3863  * and DELETE needs only old.
3864  */
3865 
3866  /* "old" transition table for UPDATE, if any */
3868  /* "new" transition table for UPDATE, if any */
3870  /* "old" transition table for DELETE, if any */
3872  /* "new" transition table for INSERT, if any */
3874 
3875  TupleTableSlot *storeslot; /* for converting to tuplestore's format */
3876 };
3877 
3879 
3880 static void AfterTriggerExecute(EState *estate,
3881  AfterTriggerEvent event,
3882  ResultRelInfo *relInfo,
3883  ResultRelInfo *src_relInfo,
3884  ResultRelInfo *dst_relInfo,
3885  TriggerDesc *trigdesc,
3886  FmgrInfo *finfo,
3887  Instrumentation *instr,
3888  MemoryContext per_tuple_context,
3889  TupleTableSlot *trig_tuple_slot1,
3890  TupleTableSlot *trig_tuple_slot2);
3892  CmdType cmdType);
3894  TupleDesc tupdesc);
3896  TupleTableSlot *oldslot,
3897  TupleTableSlot *newslot,
3898  TransitionCaptureState *transition_capture);
3899 static void TransitionTableAddTuple(EState *estate,
3900  TransitionCaptureState *transition_capture,
3901  ResultRelInfo *relinfo,
3902  TupleTableSlot *slot,
3903  TupleTableSlot *original_insert_tuple,
3904  Tuplestorestate *tuplestore);
3906 static SetConstraintState SetConstraintStateCreate(int numalloc);
3909  Oid tgoid, bool tgisdeferred);
3910 static void cancel_prior_stmt_triggers(Oid relid, CmdType cmdType, int tgevent);
3911 
3912 
3913 /*
3914  * Get the FDW tuplestore for the current trigger query level, creating it
3915  * if necessary.
3916  */
3917 static Tuplestorestate *
3919 {
3920  Tuplestorestate *ret;
3921 
3923  if (ret == NULL)
3924  {
3925  MemoryContext oldcxt;
3926  ResourceOwner saveResourceOwner;
3927 
3928  /*
3929  * Make the tuplestore valid until end of subtransaction. We really
3930  * only need it until AfterTriggerEndQuery().
3931  */
3933  saveResourceOwner = CurrentResourceOwner;
3935 
3936  ret = tuplestore_begin_heap(false, false, work_mem);
3937 
3938  CurrentResourceOwner = saveResourceOwner;
3939  MemoryContextSwitchTo(oldcxt);
3940 
3942  }
3943 
3944  return ret;
3945 }
3946 
3947 /* ----------
3948  * afterTriggerCheckState()
3949  *
3950  * Returns true if the trigger event is actually in state DEFERRED.
3951  * ----------
3952  */
3953 static bool
3955 {
3956  Oid tgoid = evtshared->ats_tgoid;
3958  int i;
3959 
3960  /*
3961  * For not-deferrable triggers (i.e. normal AFTER ROW triggers and
3962  * constraints declared NOT DEFERRABLE), the state is always false.
3963  */
3964  if ((evtshared->ats_event & AFTER_TRIGGER_DEFERRABLE) == 0)
3965  return false;
3966 
3967  /*
3968  * If constraint state exists, SET CONSTRAINTS might have been executed
3969  * either for this trigger or for all triggers.
3970  */
3971  if (state != NULL)
3972  {
3973  /* Check for SET CONSTRAINTS for this specific trigger. */
3974  for (i = 0; i < state->numstates; i++)
3975  {
3976  if (state->trigstates[i].sct_tgoid == tgoid)
3977  return state->trigstates[i].sct_tgisdeferred;
3978  }
3979 
3980  /* Check for SET CONSTRAINTS ALL. */
3981  if (state->all_isset)
3982  return state->all_isdeferred;
3983  }
3984 
3985  /*
3986  * Otherwise return the default state for the trigger.
3987  */
3988  return ((evtshared->ats_event & AFTER_TRIGGER_INITDEFERRED) != 0);
3989 }
3990 
3991 /* ----------
3992  * afterTriggerCopyBitmap()
3993  *
3994  * Copy bitmap into AfterTriggerEvents memory context, which is where the after
3995  * trigger events are kept.
3996  * ----------
3997  */
3998 static Bitmapset *
4000 {
4001  Bitmapset *dst;
4002  MemoryContext oldcxt;
4003 
4004  if (src == NULL)
4005  return NULL;
4006 
4007  /* Create event context if we didn't already */
4008  if (afterTriggers.event_cxt == NULL)
4011  "AfterTriggerEvents",
4013 
4015 
4016  dst = bms_copy(src);
4017 
4018  MemoryContextSwitchTo(oldcxt);
4019 
4020  return dst;
4021 }
4022 
4023 /* ----------
4024  * afterTriggerAddEvent()
4025  *
4026  * Add a new trigger event to the specified queue.
4027  * The passed-in event data is copied.
4028  * ----------
4029  */
4030 static void
4032  AfterTriggerEvent event, AfterTriggerShared evtshared)
4033 {
4034  Size eventsize = SizeofTriggerEvent(event);
4035  Size needed = eventsize + sizeof(AfterTriggerSharedData);
4037  AfterTriggerShared newshared;
4038  AfterTriggerEvent newevent;
4039 
4040  /*
4041  * If empty list or not enough room in the tail chunk, make a new chunk.
4042  * We assume here that a new shared record will always be needed.
4043  */
4044  chunk = events->tail;
4045  if (chunk == NULL ||
4046  chunk->endfree - chunk->freeptr < needed)
4047  {
4048  Size chunksize;
4049 
4050  /* Create event context if we didn't already */
4051  if (afterTriggers.event_cxt == NULL)
4054  "AfterTriggerEvents",
4056 
4057  /*
4058  * Chunk size starts at 1KB and is allowed to increase up to 1MB.
4059  * These numbers are fairly arbitrary, though there is a hard limit at
4060  * AFTER_TRIGGER_OFFSET; else we couldn't link event records to their
4061  * shared records using the available space in ate_flags. Another
4062  * constraint is that if the chunk size gets too huge, the search loop
4063  * below would get slow given a (not too common) usage pattern with
4064  * many distinct event types in a chunk. Therefore, we double the
4065  * preceding chunk size only if there weren't too many shared records
4066  * in the preceding chunk; otherwise we halve it. This gives us some
4067  * ability to adapt to the actual usage pattern of the current query
4068  * while still having large chunk sizes in typical usage. All chunk
4069  * sizes used should be MAXALIGN multiples, to ensure that the shared
4070  * records will be aligned safely.
4071  */
4072 #define MIN_CHUNK_SIZE 1024
4073 #define MAX_CHUNK_SIZE (1024*1024)
4074 
4075 #if MAX_CHUNK_SIZE > (AFTER_TRIGGER_OFFSET+1)
4076 #error MAX_CHUNK_SIZE must not exceed AFTER_TRIGGER_OFFSET
4077 #endif
4078 
4079  if (chunk == NULL)
4080  chunksize = MIN_CHUNK_SIZE;
4081  else
4082  {
4083  /* preceding chunk size... */
4084  chunksize = chunk->endptr - (char *) chunk;
4085  /* check number of shared records in preceding chunk */
4086  if ((chunk->endptr - chunk->endfree) <=
4087  (100 * sizeof(AfterTriggerSharedData)))
4088  chunksize *= 2; /* okay, double it */
4089  else
4090  chunksize /= 2; /* too many shared records */
4091  chunksize = Min(chunksize, MAX_CHUNK_SIZE);
4092  }
4094  chunk->next = NULL;
4095  chunk->freeptr = CHUNK_DATA_START(chunk);
4096  chunk->endptr = chunk->endfree = (char *) chunk + chunksize;
4097  Assert(chunk->endfree - chunk->freeptr >= needed);
4098 
4099  if (events->head == NULL)
4100  events->head = chunk;
4101  else
4102  events->tail->next = chunk;
4103  events->tail = chunk;
4104  /* events->tailfree is now out of sync, but we'll fix it below */
4105  }
4106 
4107  /*
4108  * Try to locate a matching shared-data record already in the chunk. If
4109  * none, make a new one.
4110  */
4111  for (newshared = ((AfterTriggerShared) chunk->endptr) - 1;
4112  (char *) newshared >= chunk->endfree;
4113  newshared--)
4114  {
4115  if (newshared->ats_tgoid == evtshared->ats_tgoid &&
4116  newshared->ats_relid == evtshared->ats_relid &&
4117  newshared->ats_event == evtshared->ats_event &&
4118  newshared->ats_table == evtshared->ats_table &&
4119  newshared->ats_firing_id == 0)
4120  break;
4121  }
4122  if ((char *) newshared < chunk->endfree)
4123  {
4124  *newshared = *evtshared;
4125  newshared->ats_firing_id = 0; /* just to be sure */
4126  chunk->endfree = (char *) newshared;
4127  }
4128 
4129  /* Insert the data */
4130  newevent = (AfterTriggerEvent) chunk->freeptr;
4131  memcpy(newevent, event, eventsize);
4132  /* ... and link the new event to its shared record */
4133  newevent->ate_flags &= ~AFTER_TRIGGER_OFFSET;
4134  newevent->ate_flags |= (char *) newshared - (char *) newevent;
4135 
4136  chunk->freeptr += eventsize;
4137  events->tailfree = chunk->freeptr;
4138 }
4139 
4140 /* ----------
4141  * afterTriggerFreeEventList()
4142  *
4143  * Free all the event storage in the given list.
4144  * ----------
4145  */
4146 static void
4148 {
4150 
4151  while ((chunk = events->head) != NULL)
4152  {
4153  events->head = chunk->next;
4154  pfree(chunk);
4155  }
4156  events->tail = NULL;
4157  events->tailfree = NULL;
4158 }
4159 
4160 /* ----------
4161  * afterTriggerRestoreEventList()
4162  *
4163  * Restore an event list to its prior length, removing all the events
4164  * added since it had the value old_events.
4165  * ----------
4166  */
4167 static void
4169  const AfterTriggerEventList *old_events)
4170 {
4172  AfterTriggerEventChunk *next_chunk;
4173 
4174  if (old_events->tail == NULL)
4175  {
4176  /* restoring to a completely empty state, so free everything */
4177  afterTriggerFreeEventList(events);
4178  }
4179  else
4180  {
4181  *events = *old_events;
4182  /* free any chunks after the last one we want to keep */
4183  for (chunk = events->tail->next; chunk != NULL; chunk = next_chunk)
4184  {
4185  next_chunk = chunk->next;
4186  pfree(chunk);
4187  }
4188  /* and clean up the tail chunk to be the right length */
4189  events->tail->next = NULL;
4190  events->tail->freeptr = events->tailfree;
4191 
4192  /*
4193  * We don't make any effort to remove now-unused shared data records.
4194  * They might still be useful, anyway.
4195  */
4196  }
4197 }
4198 
4199 /* ----------
4200  * afterTriggerDeleteHeadEventChunk()
4201  *
4202  * Remove the first chunk of events from the query level's event list.
4203  * Keep any event list pointers elsewhere in the query level's data
4204  * structures in sync.
4205  * ----------
4206  */
4207 static void
4209 {
4210  AfterTriggerEventChunk *target = qs->events.head;
4211  ListCell *lc;
4212 
4213  Assert(target && target->next);
4214 
4215  /*
4216  * First, update any pointers in the per-table data, so that they won't be
4217  * dangling. Resetting obsoleted pointers to NULL will make
4218  * cancel_prior_stmt_triggers start from the list head, which is fine.
4219  */
4220  foreach(lc, qs->tables)
4221  {
4223 
4224  if (table->after_trig_done &&
4225  table->after_trig_events.tail == target)
4226  {
4227  table->after_trig_events.head = NULL;
4228  table->after_trig_events.tail = NULL;
4229  table->after_trig_events.tailfree = NULL;
4230  }
4231  }
4232 
4233  /* Now we can flush the head chunk */
4234  qs->events.head = target->next;
4235  pfree(target);
4236 }
4237 
4238 
4239 /* ----------
4240  * AfterTriggerExecute()
4241  *
4242  * Fetch the required tuples back from the heap and fire one
4243  * single trigger function.
4244  *
4245  * Frequently, this will be fired many times in a row for triggers of
4246  * a single relation. Therefore, we cache the open relation and provide
4247  * fmgr lookup cache space at the caller level. (For triggers fired at
4248  * the end of a query, we can even piggyback on the executor's state.)
4249  *
4250  * When fired for a cross-partition update of a partitioned table, the old
4251  * tuple is fetched using 'src_relInfo' (the source leaf partition) and
4252  * the new tuple using 'dst_relInfo' (the destination leaf partition), though
4253  * both are converted into the root partitioned table's format before passing
4254  * to the trigger function.
4255  *
4256  * event: event currently being fired.
4257  * relInfo: result relation for event.
4258  * src_relInfo: source partition of a cross-partition update
4259  * dst_relInfo: its destination partition
4260  * trigdesc: working copy of rel's trigger info.
4261  * finfo: array of fmgr lookup cache entries (one per trigger in trigdesc).
4262  * instr: array of EXPLAIN ANALYZE instrumentation nodes (one per trigger),
4263  * or NULL if no instrumentation is wanted.
4264  * per_tuple_context: memory context to call trigger function in.
4265  * trig_tuple_slot1: scratch slot for tg_trigtuple (foreign tables only)
4266  * trig_tuple_slot2: scratch slot for tg_newtuple (foreign tables only)
4267  * ----------
4268  */
4269 static void
4271  AfterTriggerEvent event,
4272  ResultRelInfo *relInfo,
4273  ResultRelInfo *src_relInfo,
4274  ResultRelInfo *dst_relInfo,
4275  TriggerDesc *trigdesc,
4276  FmgrInfo *finfo, Instrumentation *instr,
4277  MemoryContext per_tuple_context,
4278  TupleTableSlot *trig_tuple_slot1,
4279  TupleTableSlot *trig_tuple_slot2)
4280 {
4281  Relation rel = relInfo->ri_RelationDesc;
4282  Relation src_rel = src_relInfo->ri_RelationDesc;
4283  Relation dst_rel = dst_relInfo->ri_RelationDesc;
4284  AfterTriggerShared evtshared = GetTriggerSharedData(event);
4285  Oid tgoid = evtshared->ats_tgoid;
4286  TriggerData LocTriggerData = {0};
4287  HeapTuple rettuple;
4288  int tgindx;
4289  bool should_free_trig = false;
4290  bool should_free_new = false;
4291 
4292  /*
4293  * Locate trigger in trigdesc. It might not be present, and in fact the
4294  * trigdesc could be NULL, if the trigger was dropped since the event was
4295  * queued. In that case, silently do nothing.
4296  */
4297  if (trigdesc == NULL)
4298  return;
4299  for (tgindx = 0; tgindx < trigdesc->numtriggers; tgindx++)
4300  {
4301  if (trigdesc->triggers[tgindx].tgoid == tgoid)
4302  {
4303  LocTriggerData.tg_trigger = &(trigdesc->triggers[tgindx]);
4304  break;
4305  }
4306  }
4307  if (LocTriggerData.tg_trigger == NULL)
4308  return;
4309 
4310  /*
4311  * If doing EXPLAIN ANALYZE, start charging time to this trigger. We want
4312  * to include time spent re-fetching tuples in the trigger cost.
4313  */
4314  if (instr)
4315  InstrStartNode(instr + tgindx);
4316 
4317  /*
4318  * Fetch the required tuple(s).
4319  */
4320  switch (event->ate_flags & AFTER_TRIGGER_TUP_BITS)
4321  {
4323  {
4324  Tuplestorestate *fdw_tuplestore = GetCurrentFDWTuplestore();
4325 
4326  if (!tuplestore_gettupleslot(fdw_tuplestore, true, false,
4327  trig_tuple_slot1))
4328  elog(ERROR, "failed to fetch tuple1 for AFTER trigger");
4329 
4330  if ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) ==
4332  !tuplestore_gettupleslot(fdw_tuplestore, true, false,
4333  trig_tuple_slot2))
4334  elog(ERROR, "failed to fetch tuple2 for AFTER trigger");
4335  }
4336  /* fall through */
4338 
4339  /*
4340  * Store tuple in the slot so that tg_trigtuple does not reference
4341  * tuplestore memory. (It is formally possible for the trigger
4342  * function to queue trigger events that add to the same
4343  * tuplestore, which can push other tuples out of memory.) The
4344  * distinction is academic, because we start with a minimal tuple
4345  * that is stored as a heap tuple, constructed in different memory
4346  * context, in the slot anyway.
4347  */
4348  LocTriggerData.tg_trigslot = trig_tuple_slot1;
4349  LocTriggerData.tg_trigtuple =
4350  ExecFetchSlotHeapTuple(trig_tuple_slot1, true, &should_free_trig);
4351 
4352  if ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) ==
4354  {
4355  LocTriggerData.tg_newslot = trig_tuple_slot2;
4356  LocTriggerData.tg_newtuple =
4357  ExecFetchSlotHeapTuple(trig_tuple_slot2, true, &should_free_new);
4358  }
4359  else
4360  {
4361  LocTriggerData.tg_newtuple = NULL;
4362  }
4363  break;
4364 
4365  default:
4366  if (ItemPointerIsValid(&(event->ate_ctid1)))
4367  {
4368  TupleTableSlot *src_slot = ExecGetTriggerOldSlot(estate,
4369  src_relInfo);
4370 
4371  if (!table_tuple_fetch_row_version(src_rel,
4372  &(event->ate_ctid1),
4373  SnapshotAny,
4374  src_slot))
4375  elog(ERROR, "failed to fetch tuple1 for AFTER trigger");
4376 
4377  /*
4378  * Store the tuple fetched from the source partition into the
4379  * target (root partitioned) table slot, converting if needed.
4380  */
4381  if (src_relInfo != relInfo)
4382  {
4383  TupleConversionMap *map = ExecGetChildToRootMap(src_relInfo);
4384 
4385  LocTriggerData.tg_trigslot = ExecGetTriggerOldSlot(estate, relInfo);
4386  if (map)
4387  {
4389  src_slot,
4390  LocTriggerData.tg_trigslot);
4391  }
4392  else
4393  ExecCopySlot(LocTriggerData.tg_trigslot, src_slot);
4394  }
4395  else
4396  LocTriggerData.tg_trigslot = src_slot;
4397  LocTriggerData.tg_trigtuple =
4398  ExecFetchSlotHeapTuple(LocTriggerData.tg_trigslot, false, &should_free_trig);
4399  }
4400  else
4401  {
4402  LocTriggerData.tg_trigtuple = NULL;
4403  }
4404 
4405  /* don't touch ctid2 if not there */
4407  (event->ate_flags & AFTER_TRIGGER_CP_UPDATE)) &&
4408  ItemPointerIsValid(&(event->ate_ctid2)))
4409  {
4410  TupleTableSlot *dst_slot = ExecGetTriggerNewSlot(estate,
4411  dst_relInfo);
4412 
4413  if (!table_tuple_fetch_row_version(dst_rel,
4414  &(event->ate_ctid2),
4415  SnapshotAny,
4416  dst_slot))
4417  elog(ERROR, "failed to fetch tuple2 for AFTER trigger");
4418 
4419  /*
4420  * Store the tuple fetched from the destination partition into
4421  * the target (root partitioned) table slot, converting if
4422  * needed.
4423  */
4424  if (dst_relInfo != relInfo)
4425  {
4426  TupleConversionMap *map = ExecGetChildToRootMap(dst_relInfo);
4427 
4428  LocTriggerData.tg_newslot = ExecGetTriggerNewSlot(estate, relInfo);
4429  if (map)
4430  {
4432  dst_slot,
4433  LocTriggerData.tg_newslot);
4434  }
4435  else
4436  ExecCopySlot(LocTriggerData.tg_newslot, dst_slot);
4437  }
4438  else
4439  LocTriggerData.tg_newslot = dst_slot;
4440  LocTriggerData.tg_newtuple =
4441  ExecFetchSlotHeapTuple(LocTriggerData.tg_newslot, false, &should_free_new);
4442  }
4443  else
4444  {
4445  LocTriggerData.tg_newtuple = NULL;
4446  }
4447  }
4448 
4449  /*
4450  * Set up the tuplestore information to let the trigger have access to
4451  * transition tables. When we first make a transition table available to
4452  * a trigger, mark it "closed" so that it cannot change anymore. If any
4453  * additional events of the same type get queued in the current trigger
4454  * query level, they'll go into new transition tables.
4455  */
4456  LocTriggerData.tg_oldtable = LocTriggerData.tg_newtable = NULL;
4457  if (evtshared->ats_table)
4458  {
4459  if (LocTriggerData.tg_trigger->tgoldtable)
4460  {
4461  if (TRIGGER_FIRED_BY_UPDATE(evtshared->ats_event))
4462  LocTriggerData.tg_oldtable = evtshared->ats_table->old_upd_tuplestore;
4463  else
4464  LocTriggerData.tg_oldtable = evtshared->ats_table->old_del_tuplestore;
4465  evtshared->ats_table->closed = true;
4466  }
4467 
4468  if (LocTriggerData.tg_trigger->tgnewtable)
4469  {
4470  if (TRIGGER_FIRED_BY_INSERT(evtshared->ats_event))
4471  LocTriggerData.tg_newtable = evtshared->ats_table->new_ins_tuplestore;
4472  else
4473  LocTriggerData.tg_newtable = evtshared->ats_table->new_upd_tuplestore;
4474  evtshared->ats_table->closed = true;
4475  }
4476  }
4477 
4478  /*
4479  * Setup the remaining trigger information
4480  */
4481  LocTriggerData.type = T_TriggerData;
4482  LocTriggerData.tg_event =
4484  LocTriggerData.tg_relation = rel;
4485  if (TRIGGER_FOR_UPDATE(LocTriggerData.tg_trigger->tgtype))
4486  LocTriggerData.tg_updatedcols = evtshared->ats_modifiedcols;
4487 
4488  MemoryContextReset(per_tuple_context);
4489 
4490  /*
4491  * Call the trigger and throw away any possibly returned updated tuple.
4492  * (Don't let ExecCallTriggerFunc measure EXPLAIN time.)
4493  */
4494  rettuple = ExecCallTriggerFunc(&LocTriggerData,
4495  tgindx,
4496  finfo,
4497  NULL,
4498  per_tuple_context);
4499  if (rettuple != NULL &&
4500  rettuple != LocTriggerData.tg_trigtuple &&
4501  rettuple != LocTriggerData.tg_newtuple)
4502  heap_freetuple(rettuple);
4503 
4504  /*
4505  * Release resources
4506  */
4507  if (should_free_trig)
4508  heap_freetuple(LocTriggerData.tg_trigtuple);
4509  if (should_free_new)
4510  heap_freetuple(LocTriggerData.tg_newtuple);
4511 
4512  /* don't clear slots' contents if foreign table */
4513  if (trig_tuple_slot1 == NULL)
4514  {
4515  if (LocTriggerData.tg_trigslot)
4516  ExecClearTuple(LocTriggerData.tg_trigslot);
4517  if (LocTriggerData.tg_newslot)
4518  ExecClearTuple(LocTriggerData.tg_newslot);
4519  }
4520 
4521  /*
4522  * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
4523  * one "tuple returned" (really the number of firings).
4524  */
4525  if (instr)
4526  InstrStopNode(instr + tgindx, 1);
4527 }
4528 
4529 
4530 /*
4531  * afterTriggerMarkEvents()
4532  *
4533  * Scan the given event list for not yet invoked events. Mark the ones
4534  * that can be invoked now with the current firing ID.
4535  *
4536  * If move_list isn't NULL, events that are not to be invoked now are
4537  * transferred to move_list.
4538  *
4539  * When immediate_only is true, do not invoke currently-deferred triggers.
4540  * (This will be false only at main transaction exit.)
4541  *
4542  * Returns true if any invokable events were found.
4543  */
4544 static bool
4546  AfterTriggerEventList *move_list,
4547  bool immediate_only)
4548 {
4549  bool found = false;
4550  bool deferred_found = false;
4551  AfterTriggerEvent event;
4553 
4554  for_each_event_chunk(event, chunk, *events)
4555  {
4556  AfterTriggerShared evtshared = GetTriggerSharedData(event);
4557  bool defer_it = false;
4558 
4559  if (!(event->ate_flags &
4561  {
4562  /*
4563  * This trigger hasn't been called or scheduled yet. Check if we
4564  * should call it now.
4565  */
4566  if (immediate_only && afterTriggerCheckState(evtshared))
4567  {
4568  defer_it = true;
4569  }
4570  else
4571  {
4572  /*
4573  * Mark it as to be fired in this firing cycle.
4574  */
4576  event->ate_flags |= AFTER_TRIGGER_IN_PROGRESS;
4577  found = true;
4578  }
4579  }
4580 
4581  /*
4582  * If it's deferred, move it to move_list, if requested.
4583  */
4584  if (defer_it && move_list != NULL)
4585  {
4586  deferred_found = true;
4587  /* add it to move_list */
4588  afterTriggerAddEvent(move_list, event, evtshared);
4589  /* mark original copy "done" so we don't do it again */
4590  event->ate_flags |= AFTER_TRIGGER_DONE;
4591  }
4592  }
4593 
4594  /*
4595  * We could allow deferred triggers if, before the end of the
4596  * security-restricted operation, we were to verify that a SET CONSTRAINTS
4597  * ... IMMEDIATE has fired all such triggers. For now, don't bother.
4598  */
4599  if (deferred_found && InSecurityRestrictedOperation())
4600  ereport(ERROR,
4601  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4602  errmsg("cannot fire deferred trigger within security-restricted operation")));
4603 
4604  return found;
4605 }
4606 
4607 /*
4608  * afterTriggerInvokeEvents()
4609  *
4610  * Scan the given event list for events that are marked as to be fired
4611  * in the current firing cycle, and fire them.
4612  *
4613  * If estate isn't NULL, we use its result relation info to avoid repeated
4614  * openings and closing of trigger target relations. If it is NULL, we
4615  * make one locally to cache the info in case there are multiple trigger
4616  * events per rel.
4617  *
4618  * When delete_ok is true, it's safe to delete fully-processed events.
4619  * (We are not very tense about that: we simply reset a chunk to be empty
4620  * if all its events got fired. The objective here is just to avoid useless
4621  * rescanning of events when a trigger queues new events during transaction
4622  * end, so it's not necessary to worry much about the case where only
4623  * some events are fired.)
4624  *
4625  * Returns true if no unfired events remain in the list (this allows us
4626  * to avoid repeating afterTriggerMarkEvents).
4627  */
4628 static bool
4630  CommandId firing_id,
4631  EState *estate,
4632  bool delete_ok)
4633 {
4634  bool all_fired = true;
4636  MemoryContext per_tuple_context;
4637  bool local_estate = false;
4638  ResultRelInfo *rInfo = NULL;
4639  Relation rel = NULL;
4640  TriggerDesc *trigdesc = NULL;
4641  FmgrInfo *finfo = NULL;
4642  Instrumentation *instr = NULL;
4643  TupleTableSlot *slot1 = NULL,
4644  *slot2 = NULL;
4645 
4646  /* Make a local EState if need be */
4647  if (estate == NULL)
4648  {
4649  estate = CreateExecutorState();
4650  local_estate = true;
4651  }
4652 
4653  /* Make a per-tuple memory context for trigger function calls */
4654  per_tuple_context =
4656  "AfterTriggerTupleContext",
4658 
4659  for_each_chunk(chunk, *events)
4660  {
4661  AfterTriggerEvent event;
4662  bool all_fired_in_chunk = true;
4663 
4664  for_each_event(event, chunk)
4665  {
4666  AfterTriggerShared evtshared = GetTriggerSharedData(event);
4667 
4668  /*
4669  * Is it one for me to fire?
4670  */
4671  if ((event->ate_flags & AFTER_TRIGGER_IN_PROGRESS) &&
4672  evtshared->ats_firing_id == firing_id)
4673  {
4674  ResultRelInfo *src_rInfo,
4675  *dst_rInfo;
4676 
4677  /*
4678  * So let's fire it... but first, find the correct relation if
4679  * this is not the same relation as before.
4680  */
4681  if (rel == NULL || RelationGetRelid(rel) != evtshared->ats_relid)
4682  {
4683  rInfo = ExecGetTriggerResultRel(estate, evtshared->ats_relid,
4684  NULL);
4685  rel = rInfo->ri_RelationDesc;
4686  /* Catch calls with insufficient relcache refcounting */
4688  trigdesc = rInfo->ri_TrigDesc;
4689  /* caution: trigdesc could be NULL here */
4690  finfo = rInfo->ri_TrigFunctions;
4691  instr = rInfo->ri_TrigInstrument;
4692  if (slot1 != NULL)
4693  {
4696  slot1 = slot2 = NULL;
4697  }
4698  if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
4699  {
4700  slot1 = MakeSingleTupleTableSlot(rel->rd_att,
4702  slot2 = MakeSingleTupleTableSlot(rel->rd_att,
4704  }
4705  }
4706 
4707  /*
4708  * Look up source and destination partition result rels of a
4709  * cross-partition update event.
4710  */
4711  if ((event->ate_flags & AFTER_TRIGGER_TUP_BITS) ==
4713  {
4714  Assert(OidIsValid(event->ate_src_part) &&
4715  OidIsValid(event->ate_dst_part));
4716  src_rInfo = ExecGetTriggerResultRel(estate,
4717  event->ate_src_part,
4718  rInfo);
4719  dst_rInfo = ExecGetTriggerResultRel(estate,
4720  event->ate_dst_part,
4721  rInfo);
4722  }
4723  else
4724  src_rInfo = dst_rInfo = rInfo;
4725 
4726  /*
4727  * Fire it. Note that the AFTER_TRIGGER_IN_PROGRESS flag is
4728  * still set, so recursive examinations of the event list
4729  * won't try to re-fire it.
4730  */
4731  AfterTriggerExecute(estate, event, rInfo,
4732  src_rInfo, dst_rInfo,
4733  trigdesc, finfo, instr,
4734  per_tuple_context, slot1, slot2);
4735 
4736  /*
4737  * Mark the event as done.
4738  */
4739  event->ate_flags &= ~AFTER_TRIGGER_IN_PROGRESS;
4740  event->ate_flags |= AFTER_TRIGGER_DONE;
4741  }
4742  else if (!(event->ate_flags & AFTER_TRIGGER_DONE))
4743  {
4744  /* something remains to be done */
4745  all_fired = all_fired_in_chunk = false;
4746  }
4747  }
4748 
4749  /* Clear the chunk if delete_ok and nothing left of interest */
4750  if (delete_ok && all_fired_in_chunk)
4751  {
4752  chunk->freeptr = CHUNK_DATA_START(chunk);
4753  chunk->endfree = chunk->endptr;
4754 
4755  /*
4756  * If it's last chunk, must sync event list's tailfree too. Note
4757  * that delete_ok must NOT be passed as true if there could be
4758  * additional AfterTriggerEventList values pointing at this event
4759  * list, since we'd fail to fix their copies of tailfree.
4760  */
4761  if (chunk == events->tail)
4762  events->tailfree = chunk->freeptr;
4763  }
4764  }
4765  if (slot1 != NULL)
4766  {
4769  }
4770 
4771  /* Release working resources */
4772  MemoryContextDelete(per_tuple_context);
4773 
4774  if (local_estate)
4775  {
4776  ExecCloseResultRelations(estate);
4777  ExecResetTupleTable(estate->es_tupleTable, false);
4778  FreeExecutorState(estate);
4779  }
4780 
4781  return all_fired;
4782 }
4783 
4784 
4785 /*
4786  * GetAfterTriggersTableData
4787  *
4788  * Find or create an AfterTriggersTableData struct for the specified
4789  * trigger event (relation + operation type). Ignore existing structs
4790  * marked "closed"; we don't want to put any additional tuples into them,
4791  * nor change their stmt-triggers-fired state.
4792  *
4793  * Note: the AfterTriggersTableData list is allocated in the current
4794  * (sub)transaction's CurTransactionContext. This is OK because
4795  * we don't need it to live past AfterTriggerEndQuery.
4796  */
4797 static AfterTriggersTableData *
4799 {
4800  AfterTriggersTableData *table;
4802  MemoryContext oldcxt;
4803  ListCell *lc;
4804 
4805  /* Caller should have ensured query_depth is OK. */
4809 
4810  foreach(lc, qs->tables)
4811  {
4812  table = (AfterTriggersTableData *) lfirst(lc);
4813  if (table->relid == relid && table->cmdType == cmdType &&
4814  !table->closed)
4815  return table;
4816  }
4817 
4819 
4821  table->relid = relid;
4822  table->cmdType = cmdType;
4823  qs->tables = lappend(qs->tables, table);
4824 
4825  MemoryContextSwitchTo(oldcxt);
4826 
4827  return table;
4828 }
4829 
4830 /*
4831  * Returns a TupleTableSlot suitable for holding the tuples to be put
4832  * into AfterTriggersTableData's transition table tuplestores.
4833  */
4834 static TupleTableSlot *
4836  TupleDesc tupdesc)
4837 {
4838  /* Create it if not already done. */
4839  if (!table->storeslot)
4840  {
4841  MemoryContext oldcxt;
4842 
4843  /*
4844  * We need this slot only until AfterTriggerEndQuery, but making it
4845  * last till end-of-subxact is good enough. It'll be freed by
4846  * AfterTriggerFreeQuery(). However, the passed-in tupdesc might have
4847  * a different lifespan, so we'd better make a copy of that.
4848  */
4850  tupdesc = CreateTupleDescCopy(tupdesc);
4851  table->storeslot = MakeSingleTupleTableSlot(tupdesc, &TTSOpsVirtual);
4852  MemoryContextSwitchTo(oldcxt);
4853  }
4854 
4855  return table->storeslot;
4856 }
4857 
4858 /*
4859  * MakeTransitionCaptureState
4860  *
4861  * Make a TransitionCaptureState object for the given TriggerDesc, target
4862  * relation, and operation type. The TCS object holds all the state needed
4863  * to decide whether to capture tuples in transition tables.
4864  *
4865  * If there are no triggers in 'trigdesc' that request relevant transition
4866  * tables, then return NULL.
4867  *
4868  * The resulting object can be passed to the ExecAR* functions. When
4869  * dealing with child tables, the caller can set tcs_original_insert_tuple
4870  * to avoid having to reconstruct the original tuple in the root table's
4871  * format.
4872  *
4873  * Note that we copy the flags from a parent table into this struct (rather
4874  * than subsequently using the relation's TriggerDesc directly) so that we can
4875  * use it to control collection of transition tuples from child tables.
4876  *
4877  * Per SQL spec, all operations of the same kind (INSERT/UPDATE/DELETE)
4878  * on the same table during one query should share one transition table.
4879  * Therefore, the Tuplestores are owned by an AfterTriggersTableData struct
4880  * looked up using the table OID + CmdType, and are merely referenced by
4881  * the TransitionCaptureState objects we hand out to callers.
4882  */
4885 {
4887  bool need_old_upd,
4888  need_new_upd,
4889  need_old_del,
4890  need_new_ins;
4891  AfterTriggersTableData *table;
4892  MemoryContext oldcxt;
4893  ResourceOwner saveResourceOwner;
4894 
4895  if (trigdesc == NULL)
4896  return NULL;
4897 
4898  /* Detect which table(s) we need. */
4899  switch (cmdType)
4900  {
4901  case CMD_INSERT:
4902  need_old_upd = need_old_del = need_new_upd = false;
4903  need_new_ins = trigdesc->trig_insert_new_table;
4904  break;
4905  case CMD_UPDATE:
4906  need_old_upd = trigdesc->trig_update_old_table;
4907  need_new_upd = trigdesc->trig_update_new_table;
4908  need_old_del = need_new_ins = false;
4909  break;
4910  case CMD_DELETE:
4911  need_old_del = trigdesc->trig_delete_old_table;
4912  need_old_upd = need_new_upd = need_new_ins = false;
4913  break;
4914  case CMD_MERGE:
4915  need_old_upd = trigdesc->trig_update_old_table;
4916  need_new_upd = trigdesc->trig_update_new_table;
4917  need_old_del = trigdesc->trig_delete_old_table;
4918  need_new_ins = trigdesc->trig_insert_new_table;
4919  break;
4920  default:
4921  elog(ERROR, "unexpected CmdType: %d", (int) cmdType);
4922  /* keep compiler quiet */
4923  need_old_upd = need_new_upd = need_old_del = need_new_ins = false;
4924  break;
4925  }
4926  if (!need_old_upd && !need_new_upd && !need_new_ins && !need_old_del)
4927  return NULL;
4928 
4929  /* Check state, like AfterTriggerSaveEvent. */
4930  if (afterTriggers.query_depth < 0)
4931  elog(ERROR, "MakeTransitionCaptureState() called outside of query");
4932 
4933  /* Be sure we have enough space to record events at this query depth. */
4936 
4937  /*
4938  * Find or create an AfterTriggersTableData struct to hold the
4939  * tuplestore(s). If there's a matching struct but it's marked closed,
4940  * ignore it; we need a newer one.
4941  *
4942  * Note: the AfterTriggersTableData list, as well as the tuplestores, are
4943  * allocated in the current (sub)transaction's CurTransactionContext, and
4944  * the tuplestores are managed by the (sub)transaction's resource owner.
4945  * This is sufficient lifespan because we do not allow triggers using
4946  * transition tables to be deferrable; they will be fired during
4947  * AfterTriggerEndQuery, after which it's okay to delete the data.
4948  */
4949  table = GetAfterTriggersTableData(relid, cmdType);
4950 
4951  /* Now create required tuplestore(s), if we don't have them already. */
4953  saveResourceOwner = CurrentResourceOwner;
4955 
4956  if (need_old_upd && table->old_upd_tuplestore == NULL)
4957  table->old_upd_tuplestore = tuplestore_begin_heap(false, false, work_mem);
4958  if (need_new_upd && table->new_upd_tuplestore == NULL)
4959  table->new_upd_tuplestore = tuplestore_begin_heap(false, false, work_mem);
4960  if (need_old_del && table->old_del_tuplestore == NULL)
4961  table->old_del_tuplestore = tuplestore_begin_heap(false, false, work_mem);
4962  if (need_new_ins && table->new_ins_tuplestore == NULL)
4963  table->new_ins_tuplestore = tuplestore_begin_heap(false, false, work_mem);
4964 
4965  CurrentResourceOwner = saveResourceOwner;
4966  MemoryContextSwitchTo(oldcxt);
4967 
4968  /* Now build the TransitionCaptureState struct, in caller's context */
4970  state->tcs_delete_old_table = trigdesc->trig_delete_old_table;
4971  state->tcs_update_old_table = trigdesc->trig_update_old_table;
4972  state->tcs_update_new_table = trigdesc->trig_update_new_table;
4973  state->tcs_insert_new_table = trigdesc->trig_insert_new_table;
4974  state->tcs_private = table;
4975 
4976  return state;
4977 }
4978 
4979 
4980 /* ----------
4981  * AfterTriggerBeginXact()
4982  *
4983  * Called at transaction start (either BEGIN or implicit for single
4984  * statement outside of transaction block).
4985  * ----------
4986  */
4987 void
4989 {
4990  /*
4991  * Initialize after-trigger state structure to empty
4992  */
4993  afterTriggers.firing_counter = (CommandId) 1; /* mustn't be 0 */
4995 
4996  /*
4997  * Verify that there is no leftover state remaining. If these assertions
4998  * trip, it means that AfterTriggerEndXact wasn't called or didn't clean
4999  * up properly.
5000  */
5001  Assert(afterTriggers.state == NULL);
5002  Assert(afterTriggers.query_stack == NULL);
5004  Assert(afterTriggers.event_cxt == NULL);
5005  Assert(afterTriggers.events.head == NULL);
5006  Assert(afterTriggers.trans_stack == NULL);
5008 }
5009 
5010 
5011 /* ----------
5012  * AfterTriggerBeginQuery()
5013  *
5014  * Called just before we start processing a single query within a
5015  * transaction (or subtransaction). Most of the real work gets deferred
5016  * until somebody actually tries to queue a trigger event.
5017  * ----------
5018  */
5019 void
5021 {
5022  /* Increase the query stack depth */
5024 }
5025 
5026 
5027 /* ----------
5028  * AfterTriggerEndQuery()
5029  *
5030  * Called after one query has been completely processed. At this time
5031  * we invoke all AFTER IMMEDIATE trigger events queued by the query, and
5032  * transfer deferred trigger events to the global deferred-trigger list.
5033  *
5034  * Note that this must be called BEFORE closing down the executor
5035  * with ExecutorEnd, because we make use of the EState's info about
5036  * target relations. Normally it is called from ExecutorFinish.
5037  * ----------
5038  */
5039 void
5041 {
5043 
5044  /* Must be inside a query, too */
5046 
5047  /*
5048  * If we never even got as far as initializing the event stack, there
5049  * certainly won't be any events, so exit quickly.
5050  */
5052  {
5054  return;
5055  }
5056 
5057  /*
5058  * Process all immediate-mode triggers queued by the query, and move the
5059  * deferred ones to the main list of deferred events.
5060  *
5061  * Notice that we decide which ones will be fired, and put the deferred
5062  * ones on the main list, before anything is actually fired. This ensures
5063  * reasonably sane behavior if a trigger function does SET CONSTRAINTS ...
5064  * IMMEDIATE: all events we have decided to defer will be available for it
5065  * to fire.
5066  *
5067  * We loop in case a trigger queues more events at the same query level.
5068  * Ordinary trigger functions, including all PL/pgSQL trigger functions,
5069  * will instead fire any triggers in a dedicated query level. Foreign key
5070  * enforcement triggers do add to the current query level, thanks to their
5071  * passing fire_triggers = false to SPI_execute_snapshot(). Other
5072  * C-language triggers might do likewise.
5073  *
5074  * If we find no firable events, we don't have to increment
5075  * firing_counter.
5076  */
5078 
5079  for (;;)
5080  {
5082  {
5083  CommandId firing_id = afterTriggers.firing_counter++;
5084  AfterTriggerEventChunk *oldtail = qs->events.tail;
5085 
5086  if (afterTriggerInvokeEvents(&qs->events, firing_id, estate, false))
5087  break; /* all fired */
5088 
5089  /*
5090  * Firing a trigger could result in query_stack being repalloc'd,
5091  * so we must recalculate qs after each afterTriggerInvokeEvents
5092  * call. Furthermore, it's unsafe to pass delete_ok = true here,
5093  * because that could cause afterTriggerInvokeEvents to try to
5094  * access qs->events after the stack has been repalloc'd.
5095  */
5097 
5098  /*
5099  * We'll need to scan the events list again. To reduce the cost
5100  * of doing so, get rid of completely-fired chunks. We know that
5101  * all events were marked IN_PROGRESS or DONE at the conclusion of
5102  * afterTriggerMarkEvents, so any still-interesting events must
5103  * have been added after that, and so must be in the chunk that
5104  * was then the tail chunk, or in later chunks. So, zap all
5105  * chunks before oldtail. This is approximately the same set of
5106  * events we would have gotten rid of by passing delete_ok = true.
5107  */
5108  Assert(oldtail != NULL);
5109  while (qs->events.head != oldtail)
5111  }
5112  else
5113  break;
5114  }
5115 
5116  /* Release query-level-local storage, including tuplestores if any */
5118 
5120 }
5121 
5122 
5123 /*
5124  * AfterTriggerFreeQuery
5125  * Release subsidiary storage for a trigger query level.
5126  * This includes closing down tuplestores.
5127  * Note: it's important for this to be safe if interrupted by an error
5128  * and then called again for the same query level.
5129  */
5130 static void
5132 {
5133  Tuplestorestate *ts;
5134  List *tables;
5135  ListCell *lc;
5136 
5137  /* Drop the trigger events */
5139 
5140  /* Drop FDW tuplestore if any */
5141  ts = qs->fdw_tuplestore;
5142  qs->fdw_tuplestore = NULL;
5143  if (ts)
5144  tuplestore_end(ts);
5145 
5146  /* Release per-table subsidiary storage */
5147  tables = qs->tables;
5148  foreach(lc, tables)
5149  {
5151 
5152  ts = table->old_upd_tuplestore;
5153  table->old_upd_tuplestore = NULL;
5154  if (ts)
5155  tuplestore_end(ts);
5156  ts = table->new_upd_tuplestore;
5157  table->new_upd_tuplestore = NULL;
5158  if (ts)
5159  tuplestore_end(ts);
5160  ts = table->old_del_tuplestore;
5161  table->old_del_tuplestore = NULL;
5162  if (ts)
5163  tuplestore_end(ts);
5164  ts = table->new_ins_tuplestore;
5165  table->new_ins_tuplestore = NULL;
5166  if (ts)
5167  tuplestore_end(ts);
5168  if (table->storeslot)
5169  {
5170  TupleTableSlot *slot = table->storeslot;
5171 
5172  table->storeslot = NULL;
5174  }
5175  }
5176 
5177  /*
5178  * Now free the AfterTriggersTableData structs and list cells. Reset list
5179  * pointer first; if list_free_deep somehow gets an error, better to leak
5180  * that storage than have an infinite loop.
5181  */
5182  qs->tables = NIL;
5183  list_free_deep(tables);
5184 }
5185 
5186 
5187 /* ----------
5188  * AfterTriggerFireDeferred()
5189  *
5190  * Called just before the current transaction is committed. At this
5191  * time we invoke all pending DEFERRED triggers.
5192  *
5193  * It is possible for other modules to queue additional deferred triggers
5194  * during pre-commit processing; therefore xact.c may have to call this
5195  * multiple times.
5196  * ----------
5197  */
5198 void
5200 {
5201  AfterTriggerEventList *events;
5202  bool snap_pushed = false;
5203 
5204  /* Must not be inside a query */
5206 
5207  /*
5208  * If there are any triggers to fire, make sure we have set a snapshot for
5209  * them to use. (Since PortalRunUtility doesn't set a snap for COMMIT, we
5210  * can't assume ActiveSnapshot is valid on entry.)
5211  */
5212  events = &afterTriggers.events;
5213  if (events->head != NULL)
5214  {
5216  snap_pushed = true;
5217  }
5218 
5219  /*
5220  * Run all the remaining triggers. Loop until they are all gone, in case
5221  * some trigger queues more for us to do.
5222  */
5223  while (afterTriggerMarkEvents(events, NULL, false))
5224  {
5225  CommandId firing_id = afterTriggers.firing_counter++;
5226 
5227  if (afterTriggerInvokeEvents(events, firing_id, NULL, true))
5228  break; /* all fired */
5229  }
5230 
5231  /*
5232  * We don't bother freeing the event list, since it will go away anyway
5233  * (and more efficiently than via pfree) in AfterTriggerEndXact.
5234  */
5235 
5236  if (snap_pushed)
5238 }
5239 
5240 
5241 /* ----------
5242  * AfterTriggerEndXact()
5243  *
5244  * The current transaction is finishing.
5245  *
5246  * Any unfired triggers are canceled so we simply throw
5247  * away anything we know.
5248  *
5249  * Note: it is possible for this to be called repeatedly in case of
5250  * error during transaction abort; therefore, do not complain if
5251  * already closed down.
5252  * ----------
5253  */
5254 void
5255 AfterTriggerEndXact(bool isCommit)
5256 {
5257  /*
5258  * Forget the pending-events list.
5259  *
5260  * Since all the info is in TopTransactionContext or children thereof, we
5261  * don't really need to do anything to reclaim memory. However, the
5262  * pending-events list could be large, and so it's useful to discard it as
5263  * soon as possible --- especially if we are aborting because we ran out
5264  * of memory for the list!
5265  */
5267  {
5269  afterTriggers.event_cxt = NULL;
5270  afterTriggers.events.head = NULL;
5271  afterTriggers.events.tail = NULL;
5272  afterTriggers.events.tailfree = NULL;
5273  }
5274 
5275  /*
5276  * Forget any subtransaction state as well. Since this can't be very
5277  * large, we let the eventual reset of TopTransactionContext free the
5278  * memory instead of doing it here.
5279  */
5280  afterTriggers.trans_stack = NULL;
5282 
5283 
5284  /*
5285  * Forget the query stack and constraint-related state information. As
5286  * with the subtransaction state information, we don't bother freeing the
5287  * memory here.
5288  */
5289  afterTriggers.query_stack = NULL;
5291  afterTriggers.state = NULL;
5292 
5293  /* No more afterTriggers manipulation until next transaction starts. */
5295 }
5296 
5297 /*
5298  * AfterTriggerBeginSubXact()
5299  *
5300  * Start a subtransaction.
5301  */
5302 void
5304 {
5305  int my_level = GetCurrentTransactionNestLevel();
5306 
5307  /*
5308  * Allocate more space in the trans_stack if needed. (Note: because the
5309  * minimum nest level of a subtransaction is 2, we waste the first couple
5310  * entries of the array; not worth the notational effort to avoid it.)
5311  */
5312  while (my_level >= afterTriggers.maxtransdepth)
5313  {
5314  if (afterTriggers.maxtransdepth == 0)
5315  {
5316  /* Arbitrarily initialize for max of 8 subtransaction levels */
5319  8 * sizeof(AfterTriggersTransData));
5321  }
5322  else
5323  {
5324  /* repalloc will keep the stack in the same context */
5325  int new_alloc = afterTriggers.maxtransdepth * 2;
5326 
5329  new_alloc * sizeof(AfterTriggersTransData));
5330  afterTriggers.maxtransdepth = new_alloc;
5331  }
5332  }
5333 
5334  /*
5335  * Push the current information into the stack. The SET CONSTRAINTS state
5336  * is not saved until/unless changed. Likewise, we don't make a
5337  * per-subtransaction event context until needed.
5338  */
5339  afterTriggers.trans_stack[my_level].state = NULL;
5343 }
5344 
5345 /*
5346  * AfterTriggerEndSubXact()
5347  *
5348  * The current subtransaction is ending.
5349  */
5350 void
5352 {
5353  int my_level = GetCurrentTransactionNestLevel();
5355  AfterTriggerEvent event;
5357  CommandId subxact_firing_id;
5358 
5359  /*
5360  * Pop the prior state if needed.
5361  */
5362  if (isCommit)
5363  {
5364  Assert(my_level < afterTriggers.maxtransdepth);
5365  /* If we saved a prior state, we don't need it anymore */
5366  state = afterTriggers.trans_stack[my_level].state;
5367  if (state != NULL)
5368  pfree(state);
5369  /* this avoids double pfree if error later: */
5370  afterTriggers.trans_stack[my_level].state = NULL;
5373  }
5374  else
5375  {
5376  /*
5377  * Aborting. It is possible subxact start failed before calling
5378  * AfterTriggerBeginSubXact, in which case we mustn't risk touching
5379  * trans_stack levels that aren't there.
5380  */
5381  if (my_level >= afterTriggers.maxtransdepth)
5382  return;
5383 
5384  /*
5385  * Release query-level storage for queries being aborted, and restore
5386  * query_depth to its pre-subxact value. This assumes that a
5387  * subtransaction will not add events to query levels started in a
5388  * earlier transaction state.
5389  */
5391  {
5395  }
5398 
5399  /*
5400  * Restore the global deferred-event list to its former length,
5401  * discarding any events queued by the subxact.
5402  */
5404  &afterTriggers.trans_stack[my_level].events);
5405 
5406  /*
5407  * Restore the trigger state. If the saved state is NULL, then this
5408  * subxact didn't save it, so it doesn't need restoring.
5409  */
5410  state = afterTriggers.trans_stack[my_level].state;
5411  if (state != NULL)
5412  {
5415  }
5416  /* this avoids double pfree if error later: */
5417  afterTriggers.trans_stack[my_level].state = NULL;
5418 
5419  /*
5420  * Scan for any remaining deferred events that were marked DONE or IN
5421  * PROGRESS by this subxact or a child, and un-mark them. We can
5422  * recognize such events because they have a firing ID greater than or
5423  * equal to the firing_counter value we saved at subtransaction start.
5424  * (This essentially assumes that the current subxact includes all
5425  * subxacts started after it.)
5426  */
5427  subxact_firing_id = afterTriggers.trans_stack[my_level].firing_counter;
5429  {
5430  AfterTriggerShared evtshared = GetTriggerSharedData(event);
5431 
5432  if (event->ate_flags &
5434  {
5435  if (evtshared->ats_firing_id >= subxact_firing_id)
5436  event->ate_flags &=
5438  }
5439  }
5440  }
5441 }
5442 
5443 /*
5444  * Get the transition table for the given event and depending on whether we are
5445  * processing the old or the new tuple.
5446  */
5447 static Tuplestorestate *
5449  TupleTableSlot *oldslot,
5450  TupleTableSlot *newslot,
5451  TransitionCaptureState *transition_capture)
5452 {
5453  Tuplestorestate *tuplestore = NULL;
5454  bool delete_old_table = transition_capture->tcs_delete_old_table;
5455  bool update_old_table = transition_capture->tcs_update_old_table;
5456  bool update_new_table = transition_capture->tcs_update_new_table;
5457  bool insert_new_table = transition_capture->tcs_insert_new_table;
5458 
5459  /*
5460  * For INSERT events NEW should be non-NULL, for DELETE events OLD should
5461  * be non-NULL, whereas for UPDATE events normally both OLD and NEW are
5462  * non-NULL. But for UPDATE events fired for capturing transition tuples
5463  * during UPDATE partition-key row movement, OLD is NULL when the event is
5464  * for a row being inserted, whereas NEW is NULL when the event is for a
5465  * row being deleted.
5466  */
5467  Assert(!(event == TRIGGER_EVENT_DELETE && delete_old_table &&
5468  TupIsNull(oldslot)));
5469  Assert(!(event == TRIGGER_EVENT_INSERT && insert_new_table &&
5470  TupIsNull(newslot)));
5471 
5472  if (!TupIsNull(oldslot))
5473  {
5474  Assert(TupIsNull(newslot));
5475  if (event == TRIGGER_EVENT_DELETE && delete_old_table)
5476  tuplestore = transition_capture->tcs_private->old_del_tuplestore;
5477  else if (event == TRIGGER_EVENT_UPDATE && update_old_table)
5478  tuplestore = transition_capture->tcs_private->old_upd_tuplestore;
5479  }
5480  else if (!TupIsNull(newslot))
5481  {
5482  Assert(TupIsNull(oldslot));
5483  if (event == TRIGGER_EVENT_INSERT && insert_new_table)
5484  tuplestore = transition_capture->tcs_private->new_ins_tuplestore;
5485  else if (event == TRIGGER_EVENT_UPDATE && update_new_table)
5486  tuplestore = transition_capture->tcs_private->new_upd_tuplestore;
5487  }
5488 
5489  return tuplestore;
5490 }
5491 
5492 /*
5493  * Add the given heap tuple to the given tuplestore, applying the conversion
5494  * map if necessary.
5495  *
5496  * If original_insert_tuple is given, we can add that tuple without conversion.
5497  */
5498 static void
5500  TransitionCaptureState *transition_capture,
5501  ResultRelInfo *relinfo,
5502  TupleTableSlot *slot,
5503  TupleTableSlot *original_insert_tuple,
5504  Tuplestorestate *tuplestore)
5505 {
5506  TupleConversionMap *map;
5507 
5508  /*
5509  * Nothing needs to be done if we don't have a tuplestore.
5510  */
5511  if (tuplestore == NULL)
5512  return;
5513 
5514  if (original_insert_tuple)
5515  tuplestore_puttupleslot(tuplestore, original_insert_tuple);
5516  else if ((map = ExecGetChildToRootMap(relinfo)) != NULL)
5517  {
5518  AfterTriggersTableData *table = transition_capture->tcs_private;
5519  TupleTableSlot *storeslot;
5520 
5521  storeslot = GetAfterTriggersStoreSlot(table, map->outdesc);
5522  execute_attr_map_slot(map->attrMap, slot, storeslot);
5523  tuplestore_puttupleslot(tuplestore, storeslot);
5524  }
5525  else
5526  tuplestore_puttupleslot(tuplestore, slot);
5527 }
5528 
5529 /* ----------
5530  * AfterTriggerEnlargeQueryState()
5531  *
5532  * Prepare the necessary state so that we can record AFTER trigger events
5533  * queued by a query. It is allowed to have nested queries within a
5534  * (sub)transaction, so we need to have separate state for each query
5535  * nesting level.
5536  * ----------
5537  */
5538 static void
5540 {
5541  int init_depth = afterTriggers.maxquerydepth;
5542 
5544 
5545  if (afterTriggers.maxquerydepth == 0)
5546  {
5547  int new_alloc = Max(afterTriggers.query_depth + 1, 8);
5548 
5551  new_alloc * sizeof(AfterTriggersQueryData));
5552  afterTriggers.maxquerydepth = new_alloc;
5553  }
5554  else
5555  {
5556  /* repalloc will keep the stack in the same context */
5557  int old_alloc = afterTriggers.maxquerydepth;
5558  int new_alloc = Max(afterTriggers.query_depth + 1,
5559  old_alloc * 2);
5560 
5563  new_alloc * sizeof(AfterTriggersQueryData));
5564  afterTriggers.maxquerydepth = new_alloc;
5565  }
5566 
5567  /* Initialize new array entries to empty */
5568  while (init_depth < afterTriggers.maxquerydepth)
5569  {
5571 
5572  qs->events.head = NULL;
5573  qs->events.tail = NULL;
5574  qs->events.tailfree = NULL;
5575  qs->fdw_tuplestore = NULL;
5576  qs->tables = NIL;
5577 
5578  ++init_depth;
5579  }
5580 }
5581 
5582 /*
5583  * Create an empty SetConstraintState with room for numalloc trigstates
5584  */
5585 static SetConstraintState
5587 {
5589 
5590  /* Behave sanely with numalloc == 0 */
5591  if (numalloc <= 0)
5592  numalloc = 1;
5593 
5594  /*
5595  * We assume that zeroing will correctly initialize the state values.
5596  */
5599  offsetof(SetConstraintStateData, trigstates) +
5600  numalloc * sizeof(SetConstraintTriggerData));
5601 
5602  state->numalloc = numalloc;
5603 
5604  return state;
5605 }
5606 
5607 /*
5608  * Copy a SetConstraintState
5609  */
5610 static SetConstraintState
5612 {
5614 
5616 
5617  state->all_isset = origstate->all_isset;
5618  state->all_isdeferred = origstate->all_isdeferred;
5619  state->numstates = origstate->numstates;
5620  memcpy(state->trigstates, origstate->trigstates,
5621  origstate->numstates * sizeof(SetConstraintTriggerData));
5622 
5623  return state;
5624 }
5625 
5626 /*
5627  * Add a per-trigger item to a SetConstraintState. Returns possibly-changed
5628  * pointer to the state object (it will change if we have to repalloc).
5629  */
5630 static SetConstraintState
5632  Oid tgoid, bool tgisdeferred)
5633 {
5634  if (state->numstates >= state->numalloc)
5635  {
5636  int newalloc = state->numalloc * 2;
5637 
5638  newalloc = Max(newalloc, 8); /* in case original has size 0 */
5640  repalloc(state,
5641  offsetof(SetConstraintStateData, trigstates) +
5642  newalloc * sizeof(SetConstraintTriggerData));
5643  state->numalloc = newalloc;
5644  Assert(state->numstates < state->numalloc);
5645  }
5646 
5647  state->trigstates[state->numstates].sct_tgoid = tgoid;
5648  state->trigstates[state->numstates].sct_tgisdeferred = tgisdeferred;
5649  state->numstates++;
5650 
5651  return state;
5652 }
5653 
5654 /* ----------
5655  * AfterTriggerSetState()
5656  *
5657  * Execute the SET CONSTRAINTS ... utility command.
5658  * ----------
5659  */
5660 void
5662 {
5663  int my_level = GetCurrentTransactionNestLevel();
5664 
5665  /* If we haven't already done so, initialize our state. */
5666  if (afterTriggers.state == NULL)
5668 
5669  /*
5670  * If in a subtransaction, and we didn't save the current state already,
5671  * save it so it can be restored if the subtransaction aborts.
5672  */
5673  if (my_level > 1 &&
5674  afterTriggers.trans_stack[my_level].state == NULL)
5675  {
5676  afterTriggers.trans_stack[my_level].state =
5678  }
5679 
5680  /*
5681  * Handle SET CONSTRAINTS ALL ...
5682  */
5683  if (stmt->constraints == NIL)
5684  {
5685  /*
5686  * Forget any previous SET CONSTRAINTS commands in this transaction.
5687  */
5689 
5690  /*
5691  * Set the per-transaction ALL state to known.
5692  */
5693  afterTriggers.state->all_isset = true;
5694  afterTriggers.state->all_isdeferred = stmt->deferred;
5695  }
5696  else
5697  {
5698  Relation conrel;
5699  Relation tgrel;
5700  List *conoidlist = NIL;
5701  List *tgoidlist = NIL;
5702  ListCell *lc;
5703 
5704  /*
5705  * Handle SET CONSTRAINTS constraint-name [, ...]
5706  *
5707  * First, identify all the named constraints and make a list of their
5708  * OIDs. Since, unlike the SQL spec, we allow multiple constraints of
5709  * the same name within a schema, the specifications are not
5710  * necessarily unique. Our strategy is to target all matching
5711  * constraints within the first search-path schema that has any
5712  * matches, but disregard matches in schemas beyond the first match.
5713  * (This is a bit odd but it's the historical behavior.)
5714  *
5715  * A constraint in a partitioned table may have corresponding
5716  * constraints in the partitions. Grab those too.
5717  */
5718  conrel = table_open(ConstraintRelationId, AccessShareLock);
5719 
5720  foreach(lc, stmt->constraints)
5721  {
5722  RangeVar *constraint = lfirst(lc);
5723  bool found;
5724  List *namespacelist;
5725  ListCell *nslc;
5726 
5727  if (constraint->catalogname)
5728  {
5729  if (strcmp(constraint->catalogname, get_database_name(MyDatabaseId)) != 0)
5730  ereport(ERROR,
5731  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5732  errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
5733  constraint->catalogname, constraint->schemaname,
5734  constraint->relname)));
5735  }
5736 
5737  /*
5738  * If we're given the schema name with the constraint, look only
5739  * in that schema. If given a bare constraint name, use the
5740  * search path to find the first matching constraint.
5741  */
5742  if (constraint->schemaname)
5743  {
5744  Oid namespaceId = LookupExplicitNamespace(constraint->schemaname,
5745  false);
5746 
5747  namespacelist = list_make1_oid(namespaceId);
5748  }
5749  else
5750  {
5751  namespacelist = fetch_search_path(true);
5752  }
5753 
5754  found = false;
5755  foreach(nslc, namespacelist)
5756  {
5757  Oid namespaceId = lfirst_oid(nslc);
5758  SysScanDesc conscan;
5759  ScanKeyData skey[2];
5760  HeapTuple tup;
5761 
5762  ScanKeyInit(&skey[0],
5763  Anum_pg_constraint_conname,
5764  BTEqualStrategyNumber, F_NAMEEQ,
5765  CStringGetDatum(constraint->relname));
5766  ScanKeyInit(&skey[1],
5767  Anum_pg_constraint_connamespace,
5768  BTEqualStrategyNumber, F_OIDEQ,
5769  ObjectIdGetDatum(namespaceId));
5770 
5771  conscan = systable_beginscan(conrel, ConstraintNameNspIndexId,
5772  true, NULL, 2, skey);
5773 
5774  while (HeapTupleIsValid(tup = systable_getnext(conscan)))
5775  {
5777 
5778  if (con->condeferrable)
5779  conoidlist = lappend_oid(conoidlist, con->oid);
5780  else if (stmt->deferred)
5781  ereport(ERROR,
5782  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
5783  errmsg("constraint \"%s\" is not deferrable",
5784  constraint->relname)));
5785  found = true;
5786  }
5787 
5788  systable_endscan(conscan);
5789 
5790  /*
5791  * Once we've found a matching constraint we do not search
5792  * later parts of the search path.
5793  */
5794  if (found)
5795  break;
5796  }
5797 
5798  list_free(namespacelist);
5799 
5800  /*
5801  * Not found ?
5802  */
5803  if (!found)
5804  ereport(ERROR,
5805  (errcode(ERRCODE_UNDEFINED_OBJECT),
5806  errmsg("constraint \"%s\" does not exist",
5807  constraint->relname)));
5808  }
5809 
5810  /*
5811  * Scan for any possible descendants of the constraints. We append
5812  * whatever we find to the same list that we're scanning; this has the
5813  * effect that we create new scans for those, too, so if there are
5814  * further descendents, we'll also catch them.
5815  */
5816  foreach(lc, conoidlist)
5817  {
5818  Oid parent = lfirst_oid(lc);
5819  ScanKeyData key;
5820  SysScanDesc scan;
5821  HeapTuple tuple;
5822 
5823  ScanKeyInit(&key,
5824  Anum_pg_constraint_conparentid,
5825  BTEqualStrategyNumber, F_OIDEQ,
5826  ObjectIdGetDatum(parent));
5827 
5828  scan = systable_beginscan(conrel, ConstraintParentIndexId, true, NULL, 1, &key);
5829 
5830  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
5831  {
5833 
5834  conoidlist = lappend_oid(conoidlist, con->oid);
5835  }
5836 
5837  systable_endscan(scan);
5838  }
5839 
5840  table_close(conrel, AccessShareLock);
5841 
5842  /*
5843  * Now, locate the trigger(s) implementing each of these constraints,
5844  * and make a list of their OIDs.
5845  */
5846  tgrel = table_open(TriggerRelationId, AccessShareLock);
5847 
5848  foreach(lc, conoidlist)
5849  {
5850  Oid conoid = lfirst_oid(lc);
5851  ScanKeyData skey;
5852  SysScanDesc tgscan;
5853  HeapTuple htup;
5854 
5855  ScanKeyInit(&skey,
5856  Anum_pg_trigger_tgconstraint,
5857  BTEqualStrategyNumber, F_OIDEQ,
5858  ObjectIdGetDatum(conoid));
5859 
5860  tgscan = systable_beginscan(tgrel, TriggerConstraintIndexId, true,
5861  NULL, 1, &skey);
5862 
5863  while (HeapTupleIsValid(htup = systable_getnext(tgscan)))
5864  {
5865  Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
5866 
5867  /*
5868  * Silently skip triggers that are marked as non-deferrable in
5869  * pg_trigger. This is not an error condition, since a
5870  * deferrable RI constraint may have some non-deferrable
5871  * actions.
5872  */
5873  if (pg_trigger->tgdeferrable)
5874  tgoidlist = lappend_oid(tgoidlist, pg_trigger->oid);
5875  }
5876 
5877  systable_endscan(tgscan);
5878  }
5879 
5880  table_close(tgrel, AccessShareLock);
5881 
5882  /*
5883  * Now we can set the trigger states of individual triggers for this
5884  * xact.
5885  */
5886  foreach(lc, tgoidlist)
5887  {
5888  Oid tgoid = lfirst_oid(lc);
5890  bool found = false;
5891  int i;
5892 
5893  for (i = 0; i < state->numstates; i++)
5894  {
5895  if (state->trigstates[i].sct_tgoid == tgoid)
5896  {
5897  state->trigstates[i].sct_tgisdeferred = stmt->deferred;
5898  found = true;
5899  break;
5900  }
5901  }
5902  if (!found)
5903  {
5905  SetConstraintStateAddItem(state, tgoid, stmt->deferred);
5906  }
5907  }
5908  }
5909 
5910  /*
5911  * SQL99 requires that when a constraint is set to IMMEDIATE, any deferred
5912  * checks against that constraint must be made when the SET CONSTRAINTS
5913  * command is executed -- i.e. the effects of the SET CONSTRAINTS command
5914  * apply retroactively. We've updated the constraints state, so scan the
5915  * list of previously deferred events to fire any that have now become
5916  * immediate.
5917  *
5918  * Obviously, if this was SET ... DEFERRED then it can't have converted
5919  * any unfired events to immediate, so we need do nothing in that case.
5920  */
5921  if (!stmt->deferred)
5922  {
5924  bool snapshot_set = false;
5925 
5926  while (afterTriggerMarkEvents(events, NULL, true))
5927  {
5928  CommandId firing_id = afterTriggers.firing_counter++;
5929 
5930  /*
5931  * Make sure a snapshot has been established in case trigger
5932  * functions need one. Note that we avoid setting a snapshot if
5933  * we don't find at least one trigger that has to be fired now.
5934  * This is so that BEGIN; SET CONSTRAINTS ...; SET TRANSACTION
5935  * ISOLATION LEVEL SERIALIZABLE; ... works properly. (If we are
5936  * at the start of a transaction it's not possible for any trigger
5937  * events to be queued yet.)
5938  */
5939  if (!snapshot_set)
5940  {
5942  snapshot_set = true;
5943  }
5944 
5945  /*
5946  * We can delete fired events if we are at top transaction level,
5947  * but we'd better not if inside a subtransaction, since the
5948  * subtransaction could later get rolled back.
5949  */
5950  if (afterTriggerInvokeEvents(events, firing_id, NULL,
5951  !IsSubTransaction()))
5952  break; /* all fired */
5953  }
5954 
5955  if (snapshot_set)
5957  }
5958 }
5959 
5960 /* ----------
5961  * AfterTriggerPendingOnRel()
5962  * Test to see if there are any pending after-trigger events for rel.
5963  *
5964  * This is used by TRUNCATE, CLUSTER, ALTER TABLE, etc to detect whether
5965  * it is unsafe to perform major surgery on a relation. Note that only
5966  * local pending events are examined. We assume that having exclusive lock
5967  * on a rel guarantees there are no unserviced events in other backends ---
5968  * but having a lock does not prevent there being such events in our own.
5969  *
5970  * In some scenarios it'd be reasonable to remove pending events (more
5971  * specifically, mark them DONE by the current subxact) but without a lot
5972  * of knowledge of the trigger semantics we can't do this in general.
5973  * ----------
5974  */
5975 bool
5977 {
5978  AfterTriggerEvent event;
5980  int depth;
5981 
5982  /* Scan queued events */
5984  {
5985  AfterTriggerShared evtshared = GetTriggerSharedData(event);
5986 
5987  /*
5988  * We can ignore completed events. (Even if a DONE flag is rolled
5989  * back by subxact abort, it's OK because the effects of the TRUNCATE
5990  * or whatever must get rolled back too.)
5991  */
5992  if (event->ate_flags & AFTER_TRIGGER_DONE)
5993  continue;
5994 
5995  if (evtshared->ats_relid == relid)
5996  return true;
5997  }
5998 
5999  /*
6000  * Also scan events queued by incomplete queries. This could only matter
6001  * if TRUNCATE/etc is executed by a function or trigger within an updating
6002  * query on the same relation, which is pretty perverse, but let's check.
6003  */
6004  for (depth = 0; depth <= afterTriggers.query_depth && depth < afterTriggers.maxquerydepth; depth++)
6005  {
6007  {
6008  AfterTriggerShared evtshared = GetTriggerSharedData(event);
6009 
6010  if (event->ate_flags & AFTER_TRIGGER_DONE)
6011  continue;
6012 
6013  if (evtshared->ats_relid == relid)
6014  return true;
6015  }
6016  }
6017 
6018  return false;
6019 }
6020 
6021 /* ----------
6022  * AfterTriggerSaveEvent()
6023  *
6024  * Called by ExecA[RS]...Triggers() to queue up the triggers that should
6025  * be fired for an event.
6026  *
6027  * NOTE: this is called whenever there are any triggers associated with
6028  * the event (even if they are disabled). This function decides which
6029  * triggers actually need to be queued. It is also called after each row,
6030  * even if there are no triggers for that event, if there are any AFTER
6031  * STATEMENT triggers for the statement which use transition tables, so that
6032  * the transition tuplestores can be built. Furthermore, if the transition
6033  * capture is happening for UPDATEd rows being moved to another partition due
6034  * to the partition-key being changed, then this function is called once when
6035  * the row is deleted (to capture OLD row), and once when the row is inserted
6036  * into another partition (to capture NEW row). This is done separately because
6037  * DELETE and INSERT happen on different tables.
6038  *
6039  * Transition tuplestores are built now, rather than when events are pulled
6040  * off of the queue because AFTER ROW triggers are allowed to select from the
6041  * transition tables for the statement.
6042  *
6043  * This contains special support to queue the update events for the case where
6044  * a partitioned table undergoing a cross-partition update may have foreign
6045  * keys pointing into it. Normally, a partitioned table's row triggers are
6046  * not fired because the leaf partition(s) which are modified as a result of
6047  * the operation on the partitioned table contain the same triggers which are
6048  * fired instead. But that general scheme can cause problematic behavior with
6049  * foreign key triggers during cross-partition updates, which are implemented
6050  * as DELETE on the source partition followed by INSERT into the destination
6051  * partition. Specifically, firing DELETE triggers would lead to the wrong
6052  * foreign key action to be enforced considering that the original command is
6053  * UPDATE; in this case, this function is called with relinfo as the
6054  * partitioned table, and src_partinfo and dst_partinfo referring to the
6055  * source and target leaf partitions, respectively.
6056  *
6057  * is_crosspart_update is true either when a DELETE event is fired on the
6058  * source partition (which is to be ignored) or an UPDATE event is fired on
6059  * the root partitioned table.
6060  * ----------
6061  */
6062 static void
6064  ResultRelInfo *src_partinfo,
6065  ResultRelInfo *dst_partinfo,
6066  int event, bool row_trigger,
6067  TupleTableSlot *oldslot, TupleTableSlot *newslot,
6068  List *recheckIndexes, Bitmapset *modifiedCols,
6069  TransitionCaptureState *transition_capture,
6070  bool is_crosspart_update)
6071 {
6072  Relation rel = relinfo->ri_RelationDesc;
6073  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
6074  AfterTriggerEventData new_event;
6075  AfterTriggerSharedData new_shared;
6076  char relkind = rel->rd_rel->relkind;
6077  int tgtype_event;
6078  int tgtype_level;
6079  int i;
6080  Tuplestorestate *fdw_tuplestore = NULL;
6081 
6082  /*
6083  * Check state. We use a normal test not Assert because it is possible to
6084  * reach here in the wrong state given misconfigured RI triggers, in
6085  * particular deferring a cascade action trigger.
6086  */
6087  if (afterTriggers.query_depth < 0)
6088  elog(ERROR, "AfterTriggerSaveEvent() called outside of query");
6089 
6090  /* Be sure we have enough space to record events at this query depth. */
6093 
6094  /*
6095  * If the directly named relation has any triggers with transition tables,
6096  * then we need to capture transition tuples.
6097  */
6098  if (row_trigger && transition_capture != NULL)
6099  {
6100  TupleTableSlot *original_insert_tuple = transition_capture->tcs_original_insert_tuple;
6101 
6102  /*
6103  * Capture the old tuple in the appropriate transition table based on
6104  * the event.
6105  */
6106  if (!TupIsNull(oldslot))
6107  {
6108  Tuplestorestate *old_tuplestore;
6109 
6110  old_tuplestore = GetAfterTriggersTransitionTable(event,
6111  oldslot,
6112  NULL,
6113  transition_capture);
6114  TransitionTableAddTuple(estate, transition_capture, relinfo,
6115  oldslot, NULL, old_tuplestore);
6116  }
6117 
6118  /*
6119  * Capture the new tuple in the appropriate transition table based on
6120  * the event.
6121  */
6122  if (!TupIsNull(newslot))
6123  {
6124  Tuplestorestate *new_tuplestore;
6125 
6126  new_tuplestore = GetAfterTriggersTransitionTable(event,
6127  NULL,
6128  newslot,
6129  transition_capture);
6130  TransitionTableAddTuple(estate, transition_capture, relinfo,
6131  newslot, original_insert_tuple, new_tuplestore);
6132  }
6133 
6134  /*
6135  * If transition tables are the only reason we're here, return. As
6136  * mentioned above, we can also be here during update tuple routing in
6137  * presence of transition tables, in which case this function is
6138  * called separately for OLD and NEW, so we expect exactly one of them
6139  * to be NULL.
6140  */
6141  if (trigdesc == NULL ||
6142  (event == TRIGGER_EVENT_DELETE && !trigdesc->trig_delete_after_row) ||
6143  (event == TRIGGER_EVENT_INSERT && !trigdesc->trig_insert_after_row) ||
6144  (event == TRIGGER_EVENT_UPDATE && !trigdesc->trig_update_after_row) ||
6145  (event == TRIGGER_EVENT_UPDATE && (TupIsNull(oldslot) ^ TupIsNull(newslot))))
6146  return;
6147  }
6148 
6149  /*
6150  * We normally don't see partitioned tables here for row level triggers
6151  * except in the special case of a cross-partition update. In that case,
6152  * nodeModifyTable.c:ExecCrossPartitionUpdateForeignKey() calls here to
6153  * queue an update event on the root target partitioned table, also
6154  * passing the source and destination partitions and their tuples.
6155  */
6156  Assert(!row_trigger ||
6157  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE ||
6158  (is_crosspart_update &&
6159  TRIGGER_FIRED_BY_UPDATE(event) &&
6160  src_partinfo != NULL && dst_partinfo != NULL));
6161 
6162  /*
6163  * Validate the event code and collect the associated tuple CTIDs.
6164  *
6165  * The event code will be used both as a bitmask and an array offset, so
6166  * validation is important to make sure we don't walk off the edge of our
6167  * arrays.
6168  *
6169  * Also, if we're considering statement-level triggers, check whether we
6170  * already queued a set of them for this event, and cancel the prior set
6171  * if so. This preserves the behavior that statement-level triggers fire
6172  * just once per statement and fire after row-level triggers.
6173  */
6174  switch (event)
6175  {
6176  case TRIGGER_EVENT_INSERT:
6177  tgtype_event = TRIGGER_TYPE_INSERT;
6178  if (row_trigger)
6179  {
6180  Assert(oldslot == NULL);
6181  Assert(newslot != NULL);
6182  ItemPointerCopy(&(newslot->tts_tid), &(new_event.ate_ctid1));
6183  ItemPointerSetInvalid(&(new_event.ate_ctid2));
6184  }
6185  else
6186  {
6187  Assert(oldslot == NULL);
6188  Assert(newslot == NULL);
6189  ItemPointerSetInvalid(&(new_event.ate_ctid1));
6190  ItemPointerSetInvalid(&(new_event.ate_ctid2));
6192  CMD_INSERT, event);
6193  }
6194  break;
6195  case TRIGGER_EVENT_DELETE:
6196  tgtype_event = TRIGGER_TYPE_DELETE;
6197  if (row_trigger)
6198  {
6199  Assert(oldslot != NULL);
6200  Assert(newslot == NULL);
6201  ItemPointerCopy(&(oldslot->tts_tid), &(new_event.ate_ctid1));
6202  ItemPointerSetInvalid(&(new_event.ate_ctid2));
6203  }
6204  else
6205  {
6206  Assert(oldslot == NULL);
6207  Assert(newslot == NULL);
6208  ItemPointerSetInvalid(&(new_event.ate_ctid1));
6209  ItemPointerSetInvalid(&(new_event.ate_ctid2));
6211  CMD_DELETE, event);
6212  }
6213  break;
6214  case TRIGGER_EVENT_UPDATE:
6215  tgtype_event = TRIGGER_TYPE_UPDATE;
6216  if (row_trigger)
6217  {
6218  Assert(oldslot != NULL);
6219  Assert(newslot != NULL);
6220  ItemPointerCopy(&(oldslot->tts_tid), &(new_event.ate_ctid1));
6221  ItemPointerCopy(&(newslot->tts_tid), &(new_event.ate_ctid2));
6222 
6223  /*
6224  * Also remember the OIDs of partitions to fetch these tuples
6225  * out of later in AfterTriggerExecute().
6226  */
6227  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6228  {
6229  Assert(src_partinfo != NULL && dst_partinfo != NULL);
6230  new_event.ate_src_part =
6231  RelationGetRelid(src_partinfo->ri_RelationDesc);
6232  new_event.ate_dst_part =
6233  RelationGetRelid(dst_partinfo->ri_RelationDesc);
6234  }
6235  }
6236  else
6237  {
6238  Assert(oldslot == NULL);
6239  Assert(newslot == NULL);
6240  ItemPointerSetInvalid(&(new_event.ate_ctid1));
6241  ItemPointerSetInvalid(&(new_event.ate_ctid2));
6243  CMD_UPDATE, event);
6244  }
6245  break;
6247  tgtype_event = TRIGGER_TYPE_TRUNCATE;
6248  Assert(oldslot == NULL);
6249  Assert(newslot == NULL);
6250  ItemPointerSetInvalid(&(new_event.ate_ctid1));
6251  ItemPointerSetInvalid(&(new_event.ate_ctid2));
6252  break;
6253  default:
6254  elog(ERROR, "invalid after-trigger event code: %d", event);
6255  tgtype_event = 0; /* keep compiler quiet */
6256  break;
6257  }
6258 
6259  /* Determine flags */
6260  if (!(relkind == RELKIND_FOREIGN_TABLE && row_trigger))
6261  {
6262  if (row_trigger && event == TRIGGER_EVENT_UPDATE)
6263  {
6264  if (relkind == RELKIND_PARTITIONED_TABLE)
6265  new_event.ate_flags = AFTER_TRIGGER_CP_UPDATE;
6266  else
6267  new_event.ate_flags = AFTER_TRIGGER_2CTID;
6268  }
6269  else
6270  new_event.ate_flags = AFTER_TRIGGER_1CTID;
6271  }
6272 
6273  /* else, we'll initialize ate_flags for each trigger */
6274 
6275  tgtype_level = (row_trigger ? TRIGGER_TYPE_ROW : TRIGGER_TYPE_STATEMENT);
6276 
6277  /*
6278  * Must convert/copy the source and destination partition tuples into the
6279  * root partitioned table's format/slot, because the processing in the
6280  * loop below expects both oldslot and newslot tuples to be in that form.
6281  */
6282  if (row_trigger && rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6283  {
6284  TupleTableSlot *rootslot;
6285  TupleConversionMap *map;
6286 
6287  rootslot = ExecGetTriggerOldSlot(estate, relinfo);
6288  map = ExecGetChildToRootMap(src_partinfo);
6289  if (map)
6290  oldslot = execute_attr_map_slot(map->attrMap,
6291  oldslot,
6292  rootslot);
6293  else
6294  oldslot = ExecCopySlot(rootslot, oldslot);
6295 
6296  rootslot = ExecGetTriggerNewSlot(estate, relinfo);
6297  map = ExecGetChildToRootMap(dst_partinfo);
6298  if (map)
6299  newslot = execute_attr_map_slot(map->attrMap,
6300  newslot,
6301  rootslot);
6302  else
6303  newslot = ExecCopySlot(rootslot, newslot);
6304  }
6305 
6306  for (i = 0; i < trigdesc->numtriggers; i++)
6307  {
6308  Trigger *trigger = &trigdesc->triggers[i];
6309 
6310  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
6311  tgtype_level,
6312  TRIGGER_TYPE_AFTER,
6313  tgtype_event))
6314  continue;
6315  if (!TriggerEnabled(estate, relinfo, trigger, event,
6316  modifiedCols, oldslot, newslot))
6317  continue;
6318 
6319  if (relkind == RELKIND_FOREIGN_TABLE && row_trigger)
6320  {
6321  if (fdw_tuplestore == NULL)
6322  {
6323  fdw_tuplestore = GetCurrentFDWTuplestore();
6324  new_event.ate_flags = AFTER_TRIGGER_FDW_FETCH;
6325  }
6326  else
6327  /* subsequent event for the same tuple */
6328  new_event.ate_flags = AFTER_TRIGGER_FDW_REUSE;
6329  }
6330 
6331  /*
6332  * If the trigger is a foreign key enforcement trigger, there are
6333  * certain cases where we can skip queueing the event because we can
6334  * tell by inspection that the FK constraint will still pass. There
6335  * are also some cases during cross-partition updates of a partitioned
6336  * table where queuing the event can be skipped.
6337  */
6338  if (TRIGGER_FIRED_BY_UPDATE(event) || TRIGGER_FIRED_BY_DELETE(event))
6339  {
6340  switch (RI_FKey_trigger_type(trigger->tgfoid))
6341  {
6342  case RI_TRIGGER_PK:
6343 
6344  /*
6345  * For cross-partitioned updates of partitioned PK table,
6346  * skip the event fired by the component delete on the
6347  * source leaf partition unless the constraint originates
6348  * in the partition itself (!tgisclone), because the
6349  * update event that will be fired on the root
6350  * (partitioned) target table will be used to perform the
6351  * necessary foreign key enforcement action.
6352  */
6353  if (is_crosspart_update &&
6354  TRIGGER_FIRED_BY_DELETE(event) &&
6355  trigger->tgisclone)
6356  continue;
6357 
6358  /* Update or delete on trigger's PK table */
6359  if (!RI_FKey_pk_upd_check_required(trigger, rel,
6360  oldslot, newslot))
6361  {
6362  /* skip queuing this event */
6363  continue;
6364  }
6365  break;
6366 
6367  case RI_TRIGGER_FK:
6368 
6369  /*
6370  * Update on trigger's FK table. We can skip the update
6371  * event fired on a partitioned table during a
6372  * cross-partition of that table, because the insert event
6373  * that is fired on the destination leaf partition would
6374  * suffice to perform the necessary foreign key check.
6375  * Moreover, RI_FKey_fk_upd_check_required() expects to be
6376  * passed a tuple that contains system attributes, most of
6377  * which are not present in the virtual slot belonging to
6378  * a partitioned table.
6379  */
6380  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE ||
6381  !RI_FKey_fk_upd_check_required(trigger, rel,
6382  oldslot, newslot))
6383  {
6384  /* skip queuing this event */
6385  continue;
6386  }
6387  break;
6388 
6389  case RI_TRIGGER_NONE:
6390 
6391  /*
6392  * Not an FK trigger. No need to queue the update event
6393  * fired during a cross-partitioned update of a
6394  * partitioned table, because the same row trigger must be
6395  * present in the leaf partition(s) that are affected as
6396  * part of this update and the events fired on them are
6397  * queued instead.
6398  */
6399  if (row_trigger &&
6400  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6401  continue;
6402  break;
6403  }
6404  }
6405 
6406  /*
6407  * If the trigger is a deferred unique constraint check trigger, only
6408  * queue it if the unique constraint was potentially violated, which
6409  * we know from index insertion time.
6410  */
6411  if (trigger->tgfoid == F_UNIQUE_KEY_RECHECK)
6412  {
6413  if (!list_member_oid(recheckIndexes, trigger->tgconstrindid))
6414  continue; /* Uniqueness definitely not violated */
6415  }
6416 
6417  /*
6418  * Fill in event structure and add it to the current query's queue.
6419  * Note we set ats_table to NULL whenever this trigger doesn't use
6420  * transition tables, to improve sharability of the shared event data.
6421  */
6422  new_shared.ats_event =
6423  (event & TRIGGER_EVENT_OPMASK) |
6424  (row_trigger ? TRIGGER_EVENT_ROW : 0) |
6425  (trigger->tgdeferrable ? AFTER_TRIGGER_DEFERRABLE : 0) |
6426  (trigger->tginitdeferred ? AFTER_TRIGGER_INITDEFERRED : 0);
6427  new_shared.ats_tgoid = trigger->tgoid;
6428  new_shared.ats_relid = RelationGetRelid(rel);
6429  new_shared.ats_firing_id = 0;
6430  if ((trigger->tgoldtable || trigger->tgnewtable) &&
6431  transition_capture != NULL)
6432  new_shared.ats_table = transition_capture->tcs_private;
6433  else
6434  new_shared.ats_table = NULL;
6435  new_shared.ats_modifiedcols = afterTriggerCopyBitmap(modifiedCols);
6436 
6438  &new_event, &new_shared);
6439  }
6440 
6441  /*
6442  * Finally, spool any foreign tuple(s). The tuplestore squashes them to
6443  * minimal tuples, so this loses any system columns. The executor lost
6444  * those columns before us, for an unrelated reason, so this is fine.
6445  */
6446  if (fdw_tuplestore)
6447  {
6448  if (oldslot != NULL)
6449  tuplestore_puttupleslot(fdw_tuplestore, oldslot);
6450  if (newslot != NULL)
6451  tuplestore_puttupleslot(fdw_tuplestore, newslot);
6452  }
6453 }
6454 
6455 /*
6456  * Detect whether we already queued BEFORE STATEMENT triggers for the given
6457  * relation + operation, and set the flag so the next call will report "true".
6458  */
6459 static bool
6461 {
6462  bool result;
6463  AfterTriggersTableData *table;
6464 
6465  /* Check state, like AfterTriggerSaveEvent. */
6466  if (afterTriggers.query_depth < 0)
6467  elog(ERROR, "before_stmt_triggers_fired() called outside of query");
6468 
6469  /* Be sure we have enough space to record events at this query depth. */
6472 
6473  /*
6474  * We keep this state in the AfterTriggersTableData that also holds
6475  * transition tables for the relation + operation. In this way, if we are
6476  * forced to make a new set of transition tables because more tuples get
6477  * entered after we've already fired triggers, we will allow a new set of
6478  * statement triggers to get queued.
6479  */
6480  table = GetAfterTriggersTableData(relid, cmdType);
6481  result = table->before_trig_done;
6482  table->before_trig_done = true;
6483  return result;
6484 }
6485 
6486 /*
6487  * If we previously queued a set of AFTER STATEMENT triggers for the given
6488  * relation + operation, and they've not been fired yet, cancel them. The
6489  * caller will queue a fresh set that's after any row-level triggers that may
6490  * have been queued by the current sub-statement, preserving (as much as
6491  * possible) the property that AFTER ROW triggers fire before AFTER STATEMENT
6492  * triggers, and that the latter only fire once. This deals with the
6493  * situation where several FK enforcement triggers sequentially queue triggers
6494  * for the same table into the same trigger query level. We can't fully
6495  * prevent odd behavior though: if there are AFTER ROW triggers taking
6496  * transition tables, we don't want to change the transition tables once the
6497  * first such trigger has seen them. In such a case, any additional events
6498  * will result in creating new transition tables and allowing new firings of
6499  * statement triggers.
6500  *
6501  * This also saves the current event list location so that a later invocation
6502  * of this function can cheaply find the triggers we're about to queue and
6503  * cancel them.
6504  */
6505 static void
6506 cancel_prior_stmt_triggers(Oid relid, CmdType cmdType, int tgevent)
6507 {
6508  AfterTriggersTableData *table;
6510 
6511  /*
6512  * We keep this state in the AfterTriggersTableData that also holds
6513  * transition tables for the relation + operation. In this way, if we are
6514  * forced to make a new set of transition tables because more tuples get
6515  * entered after we've already fired triggers, we will allow a new set of
6516  * statement triggers to get queued without canceling the old ones.
6517  */
6518  table = GetAfterTriggersTableData(relid, cmdType);
6519 
6520  if (table->after_trig_done)
6521  {
6522  /*
6523  * We want to start scanning from the tail location that existed just
6524  * before we inserted any statement triggers. But the events list
6525  * might've been entirely empty then, in which case scan from the
6526  * current head.
6527  */
6528  AfterTriggerEvent event;
6530 
6531  if (table->after_trig_events.tail)
6532  {
6533  chunk = table->after_trig_events.tail;
6534  event = (AfterTriggerEvent) table->after_trig_events.tailfree;
6535  }
6536  else
6537  {
6538  chunk = qs->events.head;
6539  event = NULL;
6540  }
6541 
6543  {
6544  if (event == NULL)
6546  for_each_event_from(event, chunk)
6547  {
6548  AfterTriggerShared evtshared = GetTriggerSharedData(event);
6549 
6550  /*
6551  * Exit loop when we reach events that aren't AS triggers for
6552  * the target relation.
6553  */
6554  if (evtshared->ats_relid != relid)
6555  goto done;
6556  if ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) != tgevent)
6557  goto done;
6558  if (!TRIGGER_FIRED_FOR_STATEMENT(evtshared->ats_event))
6559  goto done;
6560  if (!TRIGGER_FIRED_AFTER(evtshared->ats_event))
6561  goto done;
6562  /* OK, mark it DONE */
6563  event->ate_flags &= ~AFTER_TRIGGER_IN_PROGRESS;
6564  event->ate_flags |= AFTER_TRIGGER_DONE;
6565  }
6566  /* signal we must reinitialize event ptr for next chunk */
6567  event = NULL;
6568  }
6569  }
6570 done:
6571 
6572  /* In any case, save current insertion point for next time */
6573  table->after_trig_done = true;
6574  table->after_trig_events = qs->events;
6575 }
6576 
6577 /*
6578  * GUC assign_hook for session_replication_role
6579  */
6580 void
6582 {
6583  /*
6584  * Must flush the plan cache when changing replication role; but don't
6585  * flush unnecessarily.
6586  */
6588  ResetPlanCache();
6589 }
6590 
6591 /*
6592  * SQL function pg_trigger_depth()
6593  */
6594 Datum
6596 {
6598 }
AclResult
Definition: acl.h:182
@ ACLCHECK_OK
Definition: acl.h:183
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2700
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3888
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4142
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4091
#define InvalidAttrNumber
Definition: attnum.h:23
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:122
static Datum values[MAXATTR]
Definition: bootstrap.c:150
#define CStringGetTextDatum(s)
Definition: builtins.h:97
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define NameStr(name)
Definition: c.h:746
unsigned int uint32
Definition: c.h:506
#define Min(x, y)
Definition: c.h:1004
signed short int16
Definition: c.h:493
#define Max(x, y)
Definition: c.h:998
#define Assert(condition)
Definition: c.h:858
#define FLEXIBLE_ARRAY_MEMBER
Definition: c.h:398
#define unlikely(x)
Definition: c.h:311
uint32 CommandId
Definition: c.h:666
#define OidIsValid(objectId)
Definition: c.h:775
size_t Size
Definition: c.h:605
bool IsSystemRelation(Relation relation)
Definition: catalog.c:73
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:412
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
Definition: catalog.c:85
char * get_database_name(Oid dbid)
Definition: dbcommands.c:3166
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1553
@ DEPENDENCY_AUTO
Definition: dependency.h:34
@ DEPENDENCY_INTERNAL
Definition: dependency.h:35
@ DEPENDENCY_PARTITION_PRI
Definition: dependency.h:36
@ DEPENDENCY_PARTITION_SEC
Definition: dependency.h:37
@ DEPENDENCY_NORMAL
Definition: dependency.h:33
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define PG_TRY(...)
Definition: elog.h:370
#define PG_END_TRY(...)
Definition: elog.h:395
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define NOTICE
Definition: elog.h:35
#define PG_FINALLY(...)
Definition: elog.h:387
#define ereport(elevel,...)
Definition: elog.h:149
ExprState * ExecPrepareQual(List *qual, EState *estate)
Definition: execExpr.c:767
LockTupleMode ExecUpdateLockMode(EState *estate, ResultRelInfo *relinfo)
Definition: execMain.c:2351
TupleTableSlot * EvalPlanQual(EPQState *epqstate, Relation relation, Index rti, TupleTableSlot *inputslot)
Definition: execMain.c:2470
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
Definition: execMain.c:1792
void ExecCloseResultRelations(EState *estate)
Definition: execMain.c:1517
ResultRelInfo * ExecGetTriggerResultRel(EState *estate, Oid relid, ResultRelInfo *rootRelInfo)
Definition: execMain.c:1296
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
Definition: execTuples.c:1278
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:1341
HeapTuple ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree)
Definition: execTuples.c:1731
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:86
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1325
void ExecForceStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:1556
Bitmapset * ExecGetAllUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition: execUtils.c:1324
TupleTableSlot * ExecGetTriggerOldSlot(EState *estate, ResultRelInfo *relInfo)
Definition: execUtils.c:1138
EState * CreateExecutorState(void)
Definition: execUtils.c:88
TupleTableSlot * ExecGetTriggerNewSlot(EState *estate, ResultRelInfo *relInfo)
Definition: execUtils.c:1160
void FreeExecutorState(EState *estate)
Definition: execUtils.c:189
TupleConversionMap * ExecGetChildToRootMap(ResultRelInfo *resultRelInfo)
Definition: execUtils.c:1206
#define GetPerTupleExprContext(estate)
Definition: executor.h:550
#define GetPerTupleMemoryContext(estate)
Definition: executor.h:555
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:413
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
#define DatumGetByteaPP(X)
Definition: fmgr.h:291
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:642
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:172
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:596
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:503
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:384
bool allowSystemTableMods
Definition: globals.c:128
int work_mem
Definition: globals.c:129
Oid MyDatabaseId
Definition: globals.c:92
#define newval
uint64 chunk
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:776
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1116
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1434
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
static Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:749
#define stmt
Definition: indent_codes.h:59
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
long val
Definition: informix.c:670
void InstrStartNode(Instrumentation *instr)
Definition: instrument.c:68
void InstrStopNode(Instrumentation *instr, double nTuples)
Definition: instrument.c:84
int2vector * buildint2vector(const int16 *int2s, int n)
Definition: int.c:114
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1360
void CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
Definition: inval.c:1396
int j
Definition: isn.c:74
int i
Definition: isn.c:73
static void ItemPointerSetInvalid(ItemPointerData *pointer)
Definition: itemptr.h:184
static void ItemPointerCopy(const ItemPointerData *fromPointer, ItemPointerData *toPointer)
Definition: itemptr.h:172
static bool ItemPointerIsValid(const ItemPointerData *pointer)
Definition: itemptr.h:83
List * lappend(List *list, void *datum)
Definition: list.c:339
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
void list_free(List *list)
Definition: list.c:1546
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:722
void list_free_deep(List *list)
Definition: list.c:1560
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:108
int LOCKMODE
Definition: lockdefs.h:26
#define NoLock
Definition: lockdefs.h:34
#define AccessExclusiveLock
Definition: lockdefs.h:43
#define ShareRowExclusiveLock
Definition: lockdefs.h:41
#define AccessShareLock
Definition: lockdefs.h:36
#define RowExclusiveLock
Definition: lockdefs.h:38
@ LockWaitBlock
Definition: lockoptions.h:39
LockTupleMode
Definition: lockoptions.h:50
@ LockTupleExclusive
Definition: lockoptions.h:58
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3366
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:2003
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1928
Oid get_func_rettype(Oid funcid)
Definition: lsyscache.c:1655
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:389
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:737
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
MemoryContext TopTransactionContext
Definition: mcxt.c:154
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc0(Size size)
Definition: mcxt.c:1347
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1215
MemoryContext CurTransactionContext
Definition: mcxt.c:155
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
MemoryContext CacheMemoryContext
Definition: mcxt.c:152
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
void * palloc(Size size)
Definition: mcxt.c:1317
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:170
bool InSecurityRestrictedOperation(void)
Definition: miscinit.c:662
Oid GetUserId(void)
Definition: miscinit.c:514
Datum nameout(PG_FUNCTION_ARGS)
Definition: name.c:71
void namestrcpy(Name name, const char *str)
Definition: name.c:233
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:3370
List * fetch_search_path(bool includeImplicit)
Definition: namespace.c:4809
char * NameListToString(const List *names)
Definition: namespace.c:3579
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:426
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:80
TupleTableSlot * ExecGetUpdateNewTuple(ResultRelInfo *relinfo, TupleTableSlot *planSlot, TupleTableSlot *oldSlot)
#define copyObject(obj)
Definition: nodes.h:224
CmdType
Definition: nodes.h:263
@ CMD_MERGE
Definition: nodes.h:269
@ CMD_INSERT
Definition: nodes.h:267
@ CMD_DELETE
Definition: nodes.h:268
@ CMD_UPDATE
Definition: nodes.h:266
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
Definition: objectaccess.h:175
ObjectType get_relkind_objtype(char relkind)
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
char * nodeToString(const void *obj)
Definition: outfuncs.c:791
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
void assign_expr_collations(ParseState *pstate, Node *expr)
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
Definition: parse_func.c:2144
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:72
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:39
@ EXPR_KIND_TRIGGER_WHEN
Definition: parse_node.h:77
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, int lockmode, Alias *alias, bool inh, bool inFromCl)
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
int attnameAttNum(Relation rd, const char *attname, bool sysColOK)
@ OBJECT_FUNCTION
Definition: parsenodes.h:2280
#define ACL_EXECUTE
Definition: parsenodes.h:83
#define ACL_TRIGGER
Definition: parsenodes.h:82
PartitionDesc RelationGetPartitionDesc(Relation rel, bool omit_detached)
Definition: partdesc.c:71
List * map_partition_varattnos(List *expr, int fromrel_varno, Relation to_rel, Relation from_rel)
Definition: partition.c:222
Oid get_partition_parent(Oid relid, bool even_if_detached)
Definition: partition.c:53
int16 attnum
Definition: pg_attribute.h:74
void * arg
int errdetail_relkind_not_supported(char relkind)
Definition: pg_class.c:24
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define NAMEDATALEN
Oid CreateConstraintEntry(const char *constraintName, Oid constraintNamespace, char constraintType, bool isDeferrable, bool isDeferred, bool isValidated, Oid parentConstrId, Oid relId, const int16 *constraintKey, int constraintNKeys, int constraintNTotalKeys, Oid domainId, Oid indexRelId, Oid foreignRelId, const int16 *foreignKey, const Oid *pfEqOp, const Oid *ppEqOp, const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, const int16 *fkDeleteSetCols, int numFkDeleteSetCols, char foreignMatchType, const Oid *exclOp, Node *conExpr, const char *conBin, bool conIsLocal, int conInhCount, bool conNoInherit, bool is_internal)
Definition: pg_constraint.c:48
FormData_pg_constraint * Form_pg_constraint
const void size_t len
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:46
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:352
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:302
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
Definition: pg_inherits.c:255
bool has_superclass(Oid relationId)
Definition: pg_inherits.c:377
#define lfirst(lc)
Definition: pg_list.h:172
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define list_make1_oid(x1)
Definition: pg_list.h:242
#define lfirst_oid(lc)
Definition: pg_list.h:174
FormData_pg_trigger * Form_pg_trigger
Definition: pg_trigger.h:80
#define ERRCODE_T_R_SERIALIZATION_FAILURE
Definition: pgbench.c:76
void pgstat_init_function_usage(FunctionCallInfo fcinfo, PgStat_FunctionCallUsage *fcu)
void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize)
void ResetPlanCache(void)
Definition: plancache.c:2187
#define snprintf
Definition: port.h:238
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
static char * DatumGetCString(Datum X)
Definition: postgres.h:335
uintptr_t Datum
Definition: postgres.h:64
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:172
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Datum NameGetDatum(const NameData *X)
Definition: postgres.h:373
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
static void test(void)
#define PRS2_OLD_VARNO
Definition: primnodes.h:244
#define PRS2_NEW_VARNO
Definition: primnodes.h:245
#define OUTER_VAR
Definition: primnodes.h:237
#define INNER_VAR
Definition: primnodes.h:236
MemoryContextSwitchTo(old_ctx)
void * stringToNode(const char *str)
Definition: read.c:90
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:489
#define RelationGetRelid(relation)
Definition: rel.h:505
#define RelationGetDescr(relation)
Definition: rel.h:531
#define RelationGetRelationName(relation)
Definition: rel.h:539
#define RelationGetNamespace(relation)
Definition: rel.h:546
ResourceOwner CurrentResourceOwner
Definition: resowner.c:165
ResourceOwner CurTransactionResourceOwner
Definition: resowner.c:166
void ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
Definition: rewriteManip.c:674
bool RI_FKey_pk_upd_check_required(Trigger *trigger, Relation pk_rel, TupleTableSlot *oldslot, TupleTableSlot *newslot)
Definition: ri_triggers.c:1226
bool RI_FKey_fk_upd_check_required(Trigger *trigger, Relation fk_rel, TupleTableSlot *oldslot, TupleTableSlot *newslot)
Definition: ri_triggers.c:1258
int RI_FKey_trigger_type(Oid tgfoid)
Definition: ri_triggers.c:3001
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:216
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:648
void PopActiveSnapshot(void)
Definition: snapmgr.c:743
#define SnapshotAny
Definition: snapmgr.h:33
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:205
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:47
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
struct AfterTriggerEventChunk * next
Definition: trigger.c:3700
ItemPointerData ate_ctid1
Definition: trigger.c:3662
ItemPointerData ate_ctid2
Definition: trigger.c:3663
ItemPointerData ate_ctid1
Definition: trigger.c:3670
ItemPointerData ate_ctid2
Definition: trigger.c:3647
TriggerFlags ate_flags
Definition: trigger.c:3645
ItemPointerData ate_ctid1
Definition: trigger.c:3646
AfterTriggerEventChunk * head
Definition: trigger.c:3712
AfterTriggerEventChunk * tail
Definition: trigger.c:3713
TriggerEvent ats_event
Definition: trigger.c:3633
struct AfterTriggersTableData * ats_table
Definition: trigger.c:3637
CommandId ats_firing_id
Definition: trigger.c:3636
Bitmapset * ats_modifiedcols
Definition: trigger.c:3638
SetConstraintState state
Definition: trigger.c:3819
AfterTriggersQueryData * query_stack
Definition: trigger.c:3824
MemoryContext event_cxt
Definition: trigger.c:3821
CommandId firing_counter
Definition: trigger.c:3818
AfterTriggersTransData * trans_stack
Definition: trigger.c:3829
AfterTriggerEventList events
Definition: trigger.c:3820
Tuplestorestate * fdw_tuplestore
Definition: trigger.c:3836
AfterTriggerEventList events
Definition: trigger.c:3835
TupleTableSlot * storeslot
Definition: trigger.c:3875
Tuplestorestate * old_upd_tuplestore
Definition: trigger.c:3867
Tuplestorestate * new_upd_tuplestore
Definition: trigger.c:3869
Tuplestorestate * old_del_tuplestore
Definition: trigger.c:3871
Tuplestorestate * new_ins_tuplestore
Definition: trigger.c:3873
AfterTriggerEventList after_trig_events
Definition: trigger.c:3857
AfterTriggerEventList events
Definition: trigger.c:3844
SetConstraintState state
Definition: trigger.c:3843
CommandId firing_counter
Definition: trigger.c:3846
Node * whenClause
Definition: parsenodes.h:3021
PlannedStmt * es_plannedstmt
Definition: execnodes.h:633
MemoryContext es_query_cxt
Definition: execnodes.h:667
List * es_tupleTable
Definition: execnodes.h:669
CommandId es_output_cid
Definition: execnodes.h:639
Snapshot es_snapshot
Definition: execnodes.h:624
TupleTableSlot * ecxt_innertuple
Definition: execnodes.h:257
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:259
Definition: fmgr.h:57
Oid fn_oid
Definition: fmgr.h:59
ItemPointerData t_self
Definition: htup.h:65
Definition: pg_list.h:54
Definition: nodes.h:129
const char * p_sourcetext
Definition: parse_node.h:193
List * p_rtable
Definition: parse_node.h:194
CmdType commandType
Definition: plannodes.h:52
char * relname
Definition: primnodes.h:82
char * catalogname
Definition: primnodes.h:76
char * schemaname
Definition: primnodes.h:79
TriggerDesc * trigdesc
Definition: rel.h:117
TupleDesc rd_att
Definition: rel.h:112
Oid rd_id
Definition: rel.h:113
Form_pg_class rd_rel
Definition: rel.h:111
struct ResultRelInfo * ri_RootResultRelInfo
Definition: execnodes.h:582
Instrumentation * ri_TrigInstrument
Definition: execnodes.h:495
Relation ri_RelationDesc
Definition: execnodes.h:456
TriggerDesc * ri_TrigDesc
Definition: execnodes.h:486
Index ri_RangeTableIndex
Definition: execnodes.h:453
ExprState ** ri_TrigWhenExprs
Definition: execnodes.h:492
FmgrInfo * ri_TrigFunctions
Definition: execnodes.h:489
SetConstraintTriggerData trigstates[FLEXIBLE_ARRAY_MEMBER]
Definition: trigger.c:3569
bool traversed
Definition: tableam.h:153
CommandId cmax
Definition: tableam.h:152
struct AfterTriggersTableData * tcs_private
Definition: trigger.h:81
TupleTableSlot * tcs_original_insert_tuple
Definition: trigger.h:76
Tuplestorestate * tg_oldtable
Definition: trigger.h:41
NodeTag type
Definition: trigger.h:33
Relation tg_relation
Definition: trigger.h:35
const Bitmapset * tg_updatedcols
Definition: trigger.h:43
Tuplestorestate * tg_newtable
Definition: trigger.h:42
TriggerEvent tg_event
Definition: trigger.h:34
TupleTableSlot * tg_trigslot
Definition: trigger.h:39
HeapTuple tg_newtuple
Definition: trigger.h:37
TupleTableSlot * tg_newslot
Definition: trigger.h:40
Trigger * tg_trigger
Definition: trigger.h:38
HeapTuple tg_trigtuple
Definition: trigger.h:36
int numtriggers
Definition: reltrigger.h:50
bool trig_delete_before_row
Definition: reltrigger.h:66
bool trig_update_instead_row
Definition: reltrigger.h:63
Trigger * triggers
Definition: reltrigger.h:49
bool trig_delete_instead_row
Definition: reltrigger.h:68
bool trig_update_after_row
Definition: reltrigger.h:62
bool trig_insert_instead_row
Definition: reltrigger.h:58
bool trig_update_new_table
Definition: reltrigger.h:77
bool trig_insert_after_row
Definition: reltrigger.h:57
bool trig_update_after_statement
Definition: reltrigger.h:65
bool trig_update_before_row
Definition: reltrigger.h:61
bool trig_truncate_before_statement
Definition: reltrigger.h:72
bool trig_insert_new_table
Definition: reltrigger.h:75
bool trig_update_before_statement
Definition: reltrigger.h:64
bool trig_truncate_after_statement
Definition: reltrigger.h:73
bool trig_insert_before_statement
Definition: reltrigger.h:59
bool trig_delete_old_table
Definition: reltrigger.h:78
bool trig_delete_after_row
Definition: reltrigger.h:67
bool trig_insert_before_row
Definition: reltrigger.h:56
bool trig_delete_after_statement
Definition: reltrigger.h:70
bool trig_delete_before_statement
Definition: reltrigger.h:69
bool trig_update_old_table
Definition: reltrigger.h:76
bool trig_insert_after_statement
Definition: reltrigger.h:60
char tgenabled
Definition: reltrigger.h:30
Oid tgoid
Definition: reltrigger.h:25
char * tgoldtable
Definition: reltrigger.h:43
char * tgnewtable
Definition: reltrigger.h:44
Oid tgconstrindid
Definition: reltrigger.h:34
Oid tgconstraint
Definition: reltrigger.h:35
Oid tgconstrrelid
Definition: reltrigger.h:33
char * tgname
Definition: reltrigger.h:27
Oid tgfoid
Definition: reltrigger.h:28
int16 tgnargs
Definition: reltrigger.h:38
char * tgqual
Definition: reltrigger.h:42
int16 tgnattr
Definition: reltrigger.h:39
bool tgdeferrable
Definition: reltrigger.h:36
bool tginitdeferred
Definition: reltrigger.h:37
bool tgisinternal
Definition: reltrigger.h:31
char ** tgargs
Definition: reltrigger.h:41
int16 tgtype
Definition: reltrigger.h:29
int16 * tgattr
Definition: reltrigger.h:40
bool tgisclone
Definition: reltrigger.h:32
AttrMap * attrMap
Definition: tupconvert.h:28
TupleDesc outdesc
Definition: tupconvert.h:27
ItemPointerData tts_tid
Definition: tuptable.h:129
Definition: primnodes.h:248
ParseLoc location
Definition: primnodes.h:293
AttrNumber varattno
Definition: primnodes.h:260
int varno
Definition: primnodes.h:255
Definition: c.h:715
Definition: regguts.h:323
Definition: c.h:687
bool superuser(void)
Definition: superuser.c:46
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:86
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
Relation table_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: table.c:83
TM_Result
Definition: tableam.h:80
@ TM_Ok
Definition: tableam.h:85
@ TM_Deleted
Definition: tableam.h:100
@ TM_Updated
Definition: tableam.h:97
@ TM_SelfModified
Definition: tableam.h:91
@ TM_Invisible
Definition: tableam.h:88
static TM_Result table_tuple_lock(Relation rel, ItemPointer tid, Snapshot snapshot, TupleTableSlot *slot, CommandId cid, LockTupleMode mode, LockWaitPolicy wait_policy, uint8 flags, TM_FailureData *tmfd)
Definition: tableam.h:1580
#define TUPLE_LOCK_FLAG_FIND_LAST_VERSION
Definition: tableam.h:268
static bool table_tuple_fetch_row_version(Relation rel, ItemPointer tid, Snapshot snapshot, TupleTableSlot *slot)
Definition: tableam.h:1288
static SetConstraintState SetConstraintStateCopy(SetConstraintState origstate)
Definition: trigger.c:5611
struct AfterTriggerSharedData AfterTriggerSharedData
static void cancel_prior_stmt_triggers(Oid relid, CmdType cmdType, int tgevent)
Definition: trigger.c:6506
static AfterTriggersData afterTriggers
Definition: trigger.c:3878
#define AFTER_TRIGGER_FDW_FETCH
Definition: trigger.c:3624
bool ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot *newslot, TM_Result *tmresult, TM_FailureData *tmfd)
Definition: trigger.c:2934
struct AfterTriggerEventData AfterTriggerEventData
static SetConstraintState SetConstraintStateAddItem(SetConstraintState state, Oid tgoid, bool tgisdeferred)
Definition: trigger.c:5631
#define AFTER_TRIGGER_IN_PROGRESS
Definition: trigger.c:3621
static void renametrig_internal(Relation tgrel, Relation targetrel, HeapTuple trigtup, const char *newname, const char *expected_name)
Definition: trigger.c:1577
#define AFTER_TRIGGER_OFFSET
Definition: trigger.c:3619
void AfterTriggerBeginXact(void)
Definition: trigger.c:4988
void ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TransitionCaptureState *transition_capture, bool is_crosspart_update)
Definition: trigger.c:2774
void ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2394
static void afterTriggerDeleteHeadEventChunk(AfterTriggersQueryData *qs)
Definition: trigger.c:4208
static AfterTriggersTableData * GetAfterTriggersTableData(Oid relid, CmdType cmdType)
Definition: trigger.c:4798
#define CHUNK_DATA_START(cptr)
Definition: trigger.c:3707
static void RangeVarCallbackForRenameTrigger(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: trigger.c:1415
bool ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2458
void AfterTriggerEndSubXact(bool isCommit)
Definition: trigger.c:5351
static Tuplestorestate * GetCurrentFDWTuplestore(void)
Definition: trigger.c:3918
uint32 TriggerFlags
Definition: trigger.c:3617
void ExecBSTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:3222
#define AFTER_TRIGGER_TUP_BITS
Definition: trigger.c:3628
static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo, Trigger *trigger, TriggerEvent event, Bitmapset *modifiedCols, TupleTableSlot *oldslot, TupleTableSlot *newslot)
Definition: trigger.c:3422
void FreeTriggerDesc(TriggerDesc *trigdesc)
Definition: trigger.c:2140
bool ExecIRDeleteTriggers(EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple)
Definition: trigger.c:2811
#define AFTER_TRIGGER_1CTID
Definition: trigger.c:3625
Datum pg_trigger_depth(PG_FUNCTION_ARGS)
Definition: trigger.c:6595
static Bitmapset * afterTriggerCopyBitmap(Bitmapset *src)
Definition: trigger.c:3999
void ExecBSDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2612
#define MAX_CHUNK_SIZE
void EnableDisableTrigger(Relation rel, const char *tgname, Oid tgparent, char fires_when, bool skip_system, bool recurse, LOCKMODE lockmode)
Definition: trigger.c:1721
static void AfterTriggerFreeQuery(AfterTriggersQueryData *qs)
Definition: trigger.c:5131
static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata, int tgindx, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context)
Definition: trigger.c:2302
static void afterTriggerFreeEventList(AfterTriggerEventList *events)
Definition: trigger.c:4147
bool ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2551
#define GetTriggerSharedData(evt)
Definition: trigger.c:3688
TriggerDesc * CopyTriggerDesc(TriggerDesc *trigdesc)
Definition: trigger.c:2085
static int MyTriggerDepth
Definition: trigger.c:66
#define for_each_chunk_from(cptr)
Definition: trigger.c:3729
static bool afterTriggerMarkEvents(AfterTriggerEventList *events, AfterTriggerEventList *move_list, bool immediate_only)
Definition: trigger.c:4545
static Tuplestorestate * GetAfterTriggersTransitionTable(int event, TupleTableSlot *oldslot, TupleTableSlot *newslot, TransitionCaptureState *transition_capture)
Definition: trigger.c:5448
void ExecASTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:3269
static bool afterTriggerInvokeEvents(AfterTriggerEventList *events, CommandId firing_id, EState *estate, bool delete_ok)
Definition: trigger.c:4629
const char * FindTriggerIncompatibleWithInheritance(TriggerDesc *trigdesc)
Definition: trigger.c:2272
void ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo, ResultRelInfo *src_partinfo, ResultRelInfo *dst_partinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot *newslot, List *recheckIndexes, TransitionCaptureState *transition_capture, bool is_crosspart_update)
Definition: trigger.c:3097
struct AfterTriggerSharedData * AfterTriggerShared
Definition: trigger.c:3629
void AfterTriggerSetState(ConstraintsSetStmt *stmt)
Definition: trigger.c:5661
Oid get_trigger_oid(Oid relid, const char *trigname, bool missing_ok)
Definition: trigger.c:1365
ObjectAddress CreateTrigger(CreateTrigStmt *stmt, const char *queryString, Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid, Oid funcoid, Oid parentTriggerOid, Node *whenClause, bool isInternal, bool in_partition)
Definition: trigger.c:158
static bool before_stmt_triggers_fired(Oid relid, CmdType cmdType)
Definition: trigger.c:6460
static void afterTriggerAddEvent(AfterTriggerEventList *events, AfterTriggerEvent event, AfterTriggerShared evtshared)
Definition: trigger.c:4031
struct SetConstraintTriggerData * SetConstraintTrigger
Definition: trigger.c:3551
struct AfterTriggersData AfterTriggersData
struct AfterTriggerEventDataNoOids AfterTriggerEventDataNoOids
#define AFTER_TRIGGER_2CTID
Definition: trigger.c:3626
#define SizeofTriggerEvent(evt)
Definition: trigger.c:3679
int SessionReplicationRole
Definition: trigger.c:63
static bool afterTriggerCheckState(AfterTriggerShared evtshared)
Definition: trigger.c:3954
struct AfterTriggerEventChunk AfterTriggerEventChunk
static void AfterTriggerExecute(EState *estate, AfterTriggerEvent event, ResultRelInfo *relInfo, ResultRelInfo *src_relInfo, ResultRelInfo *dst_relInfo, TriggerDesc *trigdesc, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context, TupleTableSlot *trig_tuple_slot1, TupleTableSlot *trig_tuple_slot2)
Definition: trigger.c:4270
void ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo, TransitionCaptureState *transition_capture)
Definition: trigger.c:2916
static SetConstraintState SetConstraintStateCreate(int numalloc)
Definition: trigger.c:5586
void ExecASDeleteTriggers(EState *estate, ResultRelInfo *relinfo, TransitionCaptureState *transition_capture)
Definition: trigger.c:2663
bool ExecBRDeleteTriggers(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot **epqslot, TM_Result *tmresult, TM_FailureData *tmfd)
Definition: trigger.c:2683
ObjectAddress renametrig(RenameStmt *stmt)
Definition: trigger.c:1462
void AfterTriggerFireDeferred(void)
Definition: trigger.c:5199
void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot, List *recheckIndexes, TransitionCaptureState *transition_capture)
Definition: trigger.c:2534
struct SetConstraintTriggerData SetConstraintTriggerData
void TriggerSetParentTrigger(Relation trigRel, Oid childTrigId, Oid parentTrigId, Oid childTableId)
Definition: trigger.c:1215
static void afterTriggerRestoreEventList(AfterTriggerEventList *events, const AfterTriggerEventList *old_events)
Definition: trigger.c:4168
static void SetTriggerFlags(TriggerDesc *trigdesc, Trigger *trigger)
Definition: trigger.c:2008
#define for_each_event_from(eptr, cptr)
Definition: trigger.c:3731
#define MIN_CHUNK_SIZE
static void TransitionTableAddTuple(EState *estate, TransitionCaptureState *transition_capture, ResultRelInfo *relinfo, TupleTableSlot *slot, TupleTableSlot *original_insert_tuple, Tuplestorestate *tuplestore)
Definition: trigger.c:5499
static void renametrig_partition(Relation tgrel, Oid partitionId, Oid parentTriggerOid, const char *newname, const char *expected_name)
Definition: trigger.c:1648
struct AfterTriggerEventDataZeroCtids AfterTriggerEventDataZeroCtids
TransitionCaptureState * MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType)
Definition: trigger.c:4884
void ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo, TransitionCaptureState *transition_capture)
Definition: trigger.c:2445
ObjectAddress CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid, Oid funcoid, Oid parentTriggerOid, Node *whenClause, bool isInternal, bool in_partition, char trigger_fires_when)
Definition: trigger.c:175
void assign_session_replication_role(int newval, void *extra)
Definition: trigger.c:6581
bool ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple, TupleTableSlot *newslot)
Definition: trigger.c:3156
void AfterTriggerEndXact(bool isCommit)
Definition: trigger.c:5255
struct AfterTriggerEventDataOneCtid AfterTriggerEventDataOneCtid
bool AfterTriggerPendingOnRel(Oid relid)
Definition: trigger.c:5976
struct SetConstraintStateData SetConstraintStateData
#define AFTER_TRIGGER_FDW_REUSE
Definition: trigger.c:3623
void RelationBuildTriggers(Relation relation)
Definition: trigger.c:1856
void AfterTriggerBeginSubXact(void)
Definition: trigger.c:5303
static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, ResultRelInfo *src_partinfo, ResultRelInfo *dst_partinfo, int event, bool row_trigger, TupleTableSlot *oldslot, TupleTableSlot *newslot, List *recheckIndexes, Bitmapset *modifiedCols, TransitionCaptureState *transition_capture, bool is_crosspart_update)
Definition: trigger.c:6063
static bool GetTupleForTrigger(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tid, LockTupleMode lockmode, TupleTableSlot *oldslot, TupleTableSlot **epqslot, TM_Result *tmresultp, TM_FailureData *tmfdp)
Definition: trigger.c:3286
struct AfterTriggerEventList AfterTriggerEventList
static TupleTableSlot * GetAfterTriggersStoreSlot(AfterTriggersTableData *table, TupleDesc tupdesc)
Definition: trigger.c:4835
#define AFTER_TRIGGER_CP_UPDATE
Definition: trigger.c:3627
void AfterTriggerEndQuery(EState *estate)
Definition: trigger.c:5040
void RemoveTriggerById(Oid trigOid)
Definition: trigger.c:1286
#define AFTER_TRIGGER_DONE
Definition: trigger.c:3620
#define for_each_event_chunk(eptr, cptr, evtlist)
Definition: trigger.c:3725
SetConstraintStateData * SetConstraintState
Definition: trigger.c:3572
static void AfterTriggerEnlargeQueryState(void)
Definition: trigger.c:5539
#define for_each_event(eptr, cptr)
Definition: trigger.c:3720
struct AfterTriggerEventData * AfterTriggerEvent
Definition: trigger.c:3641
#define for_each_chunk(cptr, evtlist)
Definition: trigger.c:3718
void ExecBSUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
Definition: trigger.c:2858
void AfterTriggerBeginQuery(void)
Definition: trigger.c:5020
#define AFTER_TRIGGER_DEFERRABLE
Definition: trigger.h:107
uint32 TriggerEvent
Definition: trigger.h:29
#define TRIGGER_FIRED_FOR_STATEMENT(event)
Definition: trigger.h:125
#define TRIGGER_EVENT_UPDATE
Definition: trigger.h:94
#define RI_TRIGGER_FK
Definition: trigger.h:283
#define TRIGGER_FIRED_BY_DELETE(event)
Definition: trigger.h:113
#define SESSION_REPLICATION_ROLE_REPLICA
Definition: trigger.h:141
#define TRIGGER_EVENT_DELETE
Definition: trigger.h:93
#define TRIGGER_FIRES_ON_ORIGIN
Definition: trigger.h:149
#define TRIGGER_EVENT_OPMASK
Definition: trigger.h:96
#define TRIGGER_DISABLED
Definition: trigger.h:152
#define RI_TRIGGER_NONE
Definition: trigger.h:284
#define TRIGGER_FIRES_ON_REPLICA
Definition: trigger.h:151
#define AFTER_TRIGGER_INITDEFERRED
Definition: trigger.h:108
#define TRIGGER_EVENT_INSTEAD
Definition: trigger.h:102
#define TRIGGER_EVENT_ROW
Definition: trigger.h:98
#define TRIGGER_FIRED_AFTER(event)
Definition: trigger.h:131
#define TRIGGER_EVENT_BEFORE
Definition: trigger.h:100
#define TRIGGER_FIRED_BY_INSERT(event)
Definition: trigger.h:110
#define SESSION_REPLICATION_ROLE_ORIGIN
Definition: trigger.h:140
#define TRIGGER_EVENT_INSERT
Definition: trigger.h:92
#define TRIGGER_FIRED_BY_UPDATE(event)
Definition: trigger.h:116
#define TRIGGER_EVENT_TRUNCATE
Definition: trigger.h:95
#define RI_TRIGGER_PK
Definition: trigger.h:282
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
Definition: tupconvert.c:192
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:133
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)
Definition: tuplestore.c:1120
void tuplestore_puttupleslot(Tuplestorestate *state, TupleTableSlot *slot)
Definition: tuplestore.c:740
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:328
void tuplestore_end(Tuplestorestate *state)
Definition: tuplestore.c:490
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:454
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: tuptable.h:509
#define TupIsNull(slot)
Definition: tuptable.h:306
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition: tuptable.h:472
#define strVal(v)
Definition: value.h:82
List * pull_var_clause(Node *node, int flags)
Definition: var.c:607
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
Datum byteain(PG_FUNCTION_ARGS)
Definition: varlena.c:290
const char * name
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:927
void CommandCounterIncrement(void)
Definition: xact.c:1098
bool IsSubTransaction(void)
Definition: xact.c:5031
#define IsolationUsesXactSnapshot()
Definition: xact.h:51