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  false, /* conperiod */
838  isInternal); /* is_internal */
839  }
840 
841  /*
842  * If trigger is internally generated, modify the provided trigger name to
843  * ensure uniqueness by appending the trigger OID. (Callers will usually
844  * supply a simple constant trigger name in these cases.)
845  */
846  if (isInternal)
847  {
848  snprintf(internaltrigname, sizeof(internaltrigname),
849  "%s_%u", stmt->trigname, trigoid);
850  trigname = internaltrigname;
851  }
852  else
853  {
854  /* user-defined trigger; use the specified trigger name as-is */
855  trigname = stmt->trigname;
856  }
857 
858  /*
859  * Build the new pg_trigger tuple.
860  */
861  memset(nulls, false, sizeof(nulls));
862 
863  values[Anum_pg_trigger_oid - 1] = ObjectIdGetDatum(trigoid);
864  values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
865  values[Anum_pg_trigger_tgparentid - 1] = ObjectIdGetDatum(parentTriggerOid);
866  values[Anum_pg_trigger_tgname - 1] = DirectFunctionCall1(namein,
867  CStringGetDatum(trigname));
868  values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid);
869  values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype);
870  values[Anum_pg_trigger_tgenabled - 1] = trigger_fires_when;
871  values[Anum_pg_trigger_tgisinternal - 1] = BoolGetDatum(isInternal);
872  values[Anum_pg_trigger_tgconstrrelid - 1] = ObjectIdGetDatum(constrrelid);
873  values[Anum_pg_trigger_tgconstrindid - 1] = ObjectIdGetDatum(indexOid);
874  values[Anum_pg_trigger_tgconstraint - 1] = ObjectIdGetDatum(constraintOid);
875  values[Anum_pg_trigger_tgdeferrable - 1] = BoolGetDatum(stmt->deferrable);
876  values[Anum_pg_trigger_tginitdeferred - 1] = BoolGetDatum(stmt->initdeferred);
877 
878  if (stmt->args)
879  {
880  ListCell *le;
881  char *args;
882  int16 nargs = list_length(stmt->args);
883  int len = 0;
884 
885  foreach(le, stmt->args)
886  {
887  char *ar = strVal(lfirst(le));
888 
889  len += strlen(ar) + 4;
890  for (; *ar; ar++)
891  {
892  if (*ar == '\\')
893  len++;
894  }
895  }
896  args = (char *) palloc(len + 1);
897  args[0] = '\0';
898  foreach(le, stmt->args)
899  {
900  char *s = strVal(lfirst(le));
901  char *d = args + strlen(args);
902 
903  while (*s)
904  {
905  if (*s == '\\')
906  *d++ = '\\';
907  *d++ = *s++;
908  }
909  strcpy(d, "\\000");
910  }
911  values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(nargs);
912  values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
914  }
915  else
916  {
917  values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(0);
918  values[Anum_pg_trigger_tgargs - 1] = DirectFunctionCall1(byteain,
919  CStringGetDatum(""));
920  }
921 
922  /* build column number array if it's a column-specific trigger */
923  ncolumns = list_length(stmt->columns);
924  if (ncolumns == 0)
925  columns = NULL;
926  else
927  {
928  ListCell *cell;
929  int i = 0;
930 
931  columns = (int16 *) palloc(ncolumns * sizeof(int16));
932  foreach(cell, stmt->columns)
933  {
934  char *name = strVal(lfirst(cell));
935  int16 attnum;
936  int j;
937 
938  /* Lookup column name. System columns are not allowed */
939  attnum = attnameAttNum(rel, name, false);
940  if (attnum == InvalidAttrNumber)
941  ereport(ERROR,
942  (errcode(ERRCODE_UNDEFINED_COLUMN),
943  errmsg("column \"%s\" of relation \"%s\" does not exist",
944  name, RelationGetRelationName(rel))));
945 
946  /* Check for duplicates */
947  for (j = i - 1; j >= 0; j--)
948  {
949  if (columns[j] == attnum)
950  ereport(ERROR,
951  (errcode(ERRCODE_DUPLICATE_COLUMN),
952  errmsg("column \"%s\" specified more than once",
953  name)));
954  }
955 
956  columns[i++] = attnum;
957  }
958  }
959  tgattr = buildint2vector(columns, ncolumns);
960  values[Anum_pg_trigger_tgattr - 1] = PointerGetDatum(tgattr);
961 
962  /* set tgqual if trigger has WHEN clause */
963  if (qual)
964  values[Anum_pg_trigger_tgqual - 1] = CStringGetTextDatum(qual);
965  else
966  nulls[Anum_pg_trigger_tgqual - 1] = true;
967 
968  if (oldtablename)
969  values[Anum_pg_trigger_tgoldtable - 1] = DirectFunctionCall1(namein,
970  CStringGetDatum(oldtablename));
971  else
972  nulls[Anum_pg_trigger_tgoldtable - 1] = true;
973  if (newtablename)
974  values[Anum_pg_trigger_tgnewtable - 1] = DirectFunctionCall1(namein,
975  CStringGetDatum(newtablename));
976  else
977  nulls[Anum_pg_trigger_tgnewtable - 1] = true;
978 
979  /*
980  * Insert or replace tuple in pg_trigger.
981  */
982  if (!trigger_exists)
983  {
984  tuple = heap_form_tuple(tgrel->rd_att, values, nulls);
985  CatalogTupleInsert(tgrel, tuple);
986  }
987  else
988  {
989  HeapTuple newtup;
990 
991  newtup = heap_form_tuple(tgrel->rd_att, values, nulls);
992  CatalogTupleUpdate(tgrel, &tuple->t_self, newtup);
993  heap_freetuple(newtup);
994  }
995 
996  heap_freetuple(tuple); /* free either original or new tuple */
998 
999  pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
1000  pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1]));
1001  pfree(DatumGetPointer(values[Anum_pg_trigger_tgattr - 1]));
1002  if (oldtablename)
1003  pfree(DatumGetPointer(values[Anum_pg_trigger_tgoldtable - 1]));
1004  if (newtablename)
1005  pfree(DatumGetPointer(values[Anum_pg_trigger_tgnewtable - 1]));
1006 
1007  /*
1008  * Update relation's pg_class entry; if necessary; and if not, send an SI
1009  * message to make other backends (and this one) rebuild relcache entries.
1010  */
1011  pgrel = table_open(RelationRelationId, RowExclusiveLock);
1012  tuple = SearchSysCacheCopy1(RELOID,
1014  if (!HeapTupleIsValid(tuple))
1015  elog(ERROR, "cache lookup failed for relation %u",
1016  RelationGetRelid(rel));
1017  if (!((Form_pg_class) GETSTRUCT(tuple))->relhastriggers)
1018  {
1019  ((Form_pg_class) GETSTRUCT(tuple))->relhastriggers = true;
1020 
1021  CatalogTupleUpdate(pgrel, &tuple->t_self, tuple);
1022 
1024  }
1025  else
1027 
1028  heap_freetuple(tuple);
1029  table_close(pgrel, RowExclusiveLock);
1030 
1031  /*
1032  * If we're replacing a trigger, flush all the old dependencies before
1033  * recording new ones.
1034  */
1035  if (trigger_exists)
1036  deleteDependencyRecordsFor(TriggerRelationId, trigoid, true);
1037 
1038  /*
1039  * Record dependencies for trigger. Always place a normal dependency on
1040  * the function.
1041  */
1042  myself.classId = TriggerRelationId;
1043  myself.objectId = trigoid;
1044  myself.objectSubId = 0;
1045 
1046  referenced.classId = ProcedureRelationId;
1047  referenced.objectId = funcoid;
1048  referenced.objectSubId = 0;
1049  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1050 
1051  if (isInternal && OidIsValid(constraintOid))
1052  {
1053  /*
1054  * Internally-generated trigger for a constraint, so make it an
1055  * internal dependency of the constraint. We can skip depending on
1056  * the relation(s), as there'll be an indirect dependency via the
1057  * constraint.
1058  */
1059  referenced.classId = ConstraintRelationId;
1060  referenced.objectId = constraintOid;
1061  referenced.objectSubId = 0;
1062  recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
1063  }
1064  else
1065  {
1066  /*
1067  * User CREATE TRIGGER, so place dependencies. We make trigger be
1068  * auto-dropped if its relation is dropped or if the FK relation is
1069  * dropped. (Auto drop is compatible with our pre-7.3 behavior.)
1070  */
1071  referenced.classId = RelationRelationId;
1072  referenced.objectId = RelationGetRelid(rel);
1073  referenced.objectSubId = 0;
1074  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1075 
1076  if (OidIsValid(constrrelid))
1077  {
1078  referenced.classId = RelationRelationId;
1079  referenced.objectId = constrrelid;
1080  referenced.objectSubId = 0;
1081  recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1082  }
1083  /* Not possible to have an index dependency in this case */
1084  Assert(!OidIsValid(indexOid));
1085 
1086  /*
1087  * If it's a user-specified constraint trigger, make the constraint
1088  * internally dependent on the trigger instead of vice versa.
1089  */
1090  if (OidIsValid(constraintOid))
1091  {
1092  referenced.classId = ConstraintRelationId;
1093  referenced.objectId = constraintOid;
1094  referenced.objectSubId = 0;
1095  recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
1096  }
1097 
1098  /*
1099  * If it's a partition trigger, create the partition dependencies.
1100  */
1101  if (OidIsValid(parentTriggerOid))
1102  {
1103  ObjectAddressSet(referenced, TriggerRelationId, parentTriggerOid);
1104  recordDependencyOn(&myself, &referenced, DEPENDENCY_PARTITION_PRI);
1105  ObjectAddressSet(referenced, RelationRelationId, RelationGetRelid(rel));
1106  recordDependencyOn(&myself, &referenced, DEPENDENCY_PARTITION_SEC);
1107  }
1108  }
1109 
1110  /* If column-specific trigger, add normal dependencies on columns */
1111  if (columns != NULL)
1112  {
1113  int i;
1114 
1115  referenced.classId = RelationRelationId;
1116  referenced.objectId = RelationGetRelid(rel);
1117  for (i = 0; i < ncolumns; i++)
1118  {
1119  referenced.objectSubId = columns[i];
1120  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1121  }
1122  }
1123 
1124  /*
1125  * If it has a WHEN clause, add dependencies on objects mentioned in the
1126  * expression (eg, functions, as well as any columns used).
1127  */
1128  if (whenRtable != NIL)
1129  recordDependencyOnExpr(&myself, whenClause, whenRtable,
1131 
1132  /* Post creation hook for new trigger */
1133  InvokeObjectPostCreateHookArg(TriggerRelationId, trigoid, 0,
1134  isInternal);
1135 
1136  /*
1137  * Lastly, create the trigger on child relations, if needed.
1138  */
1139  if (partition_recurse)
1140  {
1141  PartitionDesc partdesc = RelationGetPartitionDesc(rel, true);
1142  int i;
1143  MemoryContext oldcxt,
1144  perChildCxt;
1145 
1147  "part trig clone",
1149 
1150  /*
1151  * We don't currently expect to be called with a valid indexOid. If
1152  * that ever changes then we'll need to write code here to find the
1153  * corresponding child index.
1154  */
1155  Assert(!OidIsValid(indexOid));
1156 
1157  oldcxt = MemoryContextSwitchTo(perChildCxt);
1158 
1159  /* Iterate to create the trigger on each existing partition */
1160  for (i = 0; i < partdesc->nparts; i++)
1161  {
1162  CreateTrigStmt *childStmt;
1163  Relation childTbl;
1164  Node *qual;
1165 
1166  childTbl = table_open(partdesc->oids[i], ShareRowExclusiveLock);
1167 
1168  /*
1169  * Initialize our fabricated parse node by copying the original
1170  * one, then resetting fields that we pass separately.
1171  */
1172  childStmt = (CreateTrigStmt *) copyObject(stmt);
1173  childStmt->funcname = NIL;
1174  childStmt->whenClause = NULL;
1175 
1176  /* If there is a WHEN clause, create a modified copy of it */
1177  qual = copyObject(whenClause);
1178  qual = (Node *)
1180  childTbl, rel);
1181  qual = (Node *)
1183  childTbl, rel);
1184 
1185  CreateTriggerFiringOn(childStmt, queryString,
1186  partdesc->oids[i], refRelOid,
1188  funcoid, trigoid, qual,
1189  isInternal, true, trigger_fires_when);
1190 
1191  table_close(childTbl, NoLock);
1192 
1193  MemoryContextReset(perChildCxt);
1194  }
1195 
1196  MemoryContextSwitchTo(oldcxt);
1197  MemoryContextDelete(perChildCxt);
1198  }
1199 
1200  /* Keep lock on target rel until end of xact */
1201  table_close(rel, NoLock);
1202 
1203  return myself;
1204 }
1205 
1206 /*
1207  * TriggerSetParentTrigger
1208  * Set a partition's trigger as child of its parent trigger,
1209  * or remove the linkage if parentTrigId is InvalidOid.
1210  *
1211  * This updates the constraint's pg_trigger row to show it as inherited, and
1212  * adds PARTITION dependencies to prevent the trigger from being deleted
1213  * on its own. Alternatively, reverse that.
1214  */
1215 void
1217  Oid childTrigId,
1218  Oid parentTrigId,
1219  Oid childTableId)
1220 {
1221  SysScanDesc tgscan;
1222  ScanKeyData skey[1];
1223  Form_pg_trigger trigForm;
1224  HeapTuple tuple,
1225  newtup;
1226  ObjectAddress depender;
1227  ObjectAddress referenced;
1228 
1229  /*
1230  * Find the trigger to delete.
1231  */
1232  ScanKeyInit(&skey[0],
1233  Anum_pg_trigger_oid,
1234  BTEqualStrategyNumber, F_OIDEQ,
1235  ObjectIdGetDatum(childTrigId));
1236 
1237  tgscan = systable_beginscan(trigRel, TriggerOidIndexId, true,
1238  NULL, 1, skey);
1239 
1240  tuple = systable_getnext(tgscan);
1241  if (!HeapTupleIsValid(tuple))
1242  elog(ERROR, "could not find tuple for trigger %u", childTrigId);
1243  newtup = heap_copytuple(tuple);
1244  trigForm = (Form_pg_trigger) GETSTRUCT(newtup);
1245  if (OidIsValid(parentTrigId))
1246  {
1247  /* don't allow setting parent for a constraint that already has one */
1248  if (OidIsValid(trigForm->tgparentid))
1249  elog(ERROR, "trigger %u already has a parent trigger",
1250  childTrigId);
1251 
1252  trigForm->tgparentid = parentTrigId;
1253 
1254  CatalogTupleUpdate(trigRel, &tuple->t_self, newtup);
1255 
1256  ObjectAddressSet(depender, TriggerRelationId, childTrigId);
1257 
1258  ObjectAddressSet(referenced, TriggerRelationId, parentTrigId);
1259  recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_PRI);
1260 
1261  ObjectAddressSet(referenced, RelationRelationId, childTableId);
1262  recordDependencyOn(&depender, &referenced, DEPENDENCY_PARTITION_SEC);
1263  }
1264  else
1265  {
1266  trigForm->tgparentid = InvalidOid;
1267 
1268  CatalogTupleUpdate(trigRel, &tuple->t_self, newtup);
1269 
1270  deleteDependencyRecordsForClass(TriggerRelationId, childTrigId,
1271  TriggerRelationId,
1273  deleteDependencyRecordsForClass(TriggerRelationId, childTrigId,
1274  RelationRelationId,
1276  }
1277 
1278  heap_freetuple(newtup);
1279  systable_endscan(tgscan);
1280 }
1281 
1282 
1283 /*
1284  * Guts of trigger deletion.
1285  */
1286 void
1288 {
1289  Relation tgrel;
1290  SysScanDesc tgscan;
1291  ScanKeyData skey[1];
1292  HeapTuple tup;
1293  Oid relid;
1294  Relation rel;
1295 
1296  tgrel = table_open(TriggerRelationId, RowExclusiveLock);
1297 
1298  /*
1299  * Find the trigger to delete.
1300  */
1301  ScanKeyInit(&skey[0],
1302  Anum_pg_trigger_oid,
1303  BTEqualStrategyNumber, F_OIDEQ,
1304  ObjectIdGetDatum(trigOid));
1305 
1306  tgscan = systable_beginscan(tgrel, TriggerOidIndexId, true,
1307  NULL, 1, skey);
1308 
1309  tup = systable_getnext(tgscan);
1310  if (!HeapTupleIsValid(tup))
1311  elog(ERROR, "could not find tuple for trigger %u", trigOid);
1312 
1313  /*
1314  * Open and exclusive-lock the relation the trigger belongs to.
1315  */
1316  relid = ((Form_pg_trigger) GETSTRUCT(tup))->tgrelid;
1317 
1318  rel = table_open(relid, AccessExclusiveLock);
1319 
1320  if (rel->rd_rel->relkind != RELKIND_RELATION &&
1321  rel->rd_rel->relkind != RELKIND_VIEW &&
1322  rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
1323  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1324  ereport(ERROR,
1325  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1326  errmsg("relation \"%s\" cannot have triggers",
1328  errdetail_relkind_not_supported(rel->rd_rel->relkind)));
1329 
1331  ereport(ERROR,
1332  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1333  errmsg("permission denied: \"%s\" is a system catalog",
1334  RelationGetRelationName(rel))));
1335 
1336  /*
1337  * Delete the pg_trigger tuple.
1338  */
1339  CatalogTupleDelete(tgrel, &tup->t_self);
1340 
1341  systable_endscan(tgscan);
1342  table_close(tgrel, RowExclusiveLock);
1343 
1344  /*
1345  * We do not bother to try to determine whether any other triggers remain,
1346  * which would be needed in order to decide whether it's safe to clear the
1347  * relation's relhastriggers. (In any case, there might be a concurrent
1348  * process adding new triggers.) Instead, just force a relcache inval to
1349  * make other backends (and this one too!) rebuild their relcache entries.
1350  * There's no great harm in leaving relhastriggers true even if there are
1351  * no triggers left.
1352  */
1354 
1355  /* Keep lock on trigger's rel until end of xact */
1356  table_close(rel, NoLock);
1357 }
1358 
1359 /*
1360  * get_trigger_oid - Look up a trigger by name to find its OID.
1361  *
1362  * If missing_ok is false, throw an error if trigger not found. If
1363  * true, just return InvalidOid.
1364  */
1365 Oid
1366 get_trigger_oid(Oid relid, const char *trigname, bool missing_ok)
1367 {
1368  Relation tgrel;
1369  ScanKeyData skey[2];
1370  SysScanDesc tgscan;
1371  HeapTuple tup;
1372  Oid oid;
1373 
1374  /*
1375  * Find the trigger, verify permissions, set up object address
1376  */
1377  tgrel = table_open(TriggerRelationId, AccessShareLock);
1378 
1379  ScanKeyInit(&skey[0],
1380  Anum_pg_trigger_tgrelid,
1381  BTEqualStrategyNumber, F_OIDEQ,
1382  ObjectIdGetDatum(relid));
1383  ScanKeyInit(&skey[1],
1384  Anum_pg_trigger_tgname,
1385  BTEqualStrategyNumber, F_NAMEEQ,
1386  CStringGetDatum(trigname));
1387 
1388  tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1389  NULL, 2, skey);
1390 
1391  tup = systable_getnext(tgscan);
1392 
1393  if (!HeapTupleIsValid(tup))
1394  {
1395  if (!missing_ok)
1396  ereport(ERROR,
1397  (errcode(ERRCODE_UNDEFINED_OBJECT),
1398  errmsg("trigger \"%s\" for table \"%s\" does not exist",
1399  trigname, get_rel_name(relid))));
1400  oid = InvalidOid;
1401  }
1402  else
1403  {
1404  oid = ((Form_pg_trigger) GETSTRUCT(tup))->oid;
1405  }
1406 
1407  systable_endscan(tgscan);
1408  table_close(tgrel, AccessShareLock);
1409  return oid;
1410 }
1411 
1412 /*
1413  * Perform permissions and integrity checks before acquiring a relation lock.
1414  */
1415 static void
1417  void *arg)
1418 {
1419  HeapTuple tuple;
1420  Form_pg_class form;
1421 
1422  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1423  if (!HeapTupleIsValid(tuple))
1424  return; /* concurrently dropped */
1425  form = (Form_pg_class) GETSTRUCT(tuple);
1426 
1427  /* only tables and views can have triggers */
1428  if (form->relkind != RELKIND_RELATION && form->relkind != RELKIND_VIEW &&
1429  form->relkind != RELKIND_FOREIGN_TABLE &&
1430  form->relkind != RELKIND_PARTITIONED_TABLE)
1431  ereport(ERROR,
1432  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1433  errmsg("relation \"%s\" cannot have triggers",
1434  rv->relname),
1435  errdetail_relkind_not_supported(form->relkind)));
1436 
1437  /* you must own the table to rename one of its triggers */
1438  if (!object_ownercheck(RelationRelationId, relid, GetUserId()))
1440  if (!allowSystemTableMods && IsSystemClass(relid, form))
1441  ereport(ERROR,
1442  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1443  errmsg("permission denied: \"%s\" is a system catalog",
1444  rv->relname)));
1445 
1446  ReleaseSysCache(tuple);
1447 }
1448 
1449 /*
1450  * renametrig - changes the name of a trigger on a relation
1451  *
1452  * trigger name is changed in trigger catalog.
1453  * No record of the previous name is kept.
1454  *
1455  * get proper relrelation from relation catalog (if not arg)
1456  * scan trigger catalog
1457  * for name conflict (within rel)
1458  * for original trigger (if not arg)
1459  * modify tgname in trigger tuple
1460  * update row in catalog
1461  */
1464 {
1465  Oid tgoid;
1466  Relation targetrel;
1467  Relation tgrel;
1468  HeapTuple tuple;
1469  SysScanDesc tgscan;
1470  ScanKeyData key[2];
1471  Oid relid;
1472  ObjectAddress address;
1473 
1474  /*
1475  * Look up name, check permissions, and acquire lock (which we will NOT
1476  * release until end of transaction).
1477  */
1479  0,
1481  NULL);
1482 
1483  /* Have lock already, so just need to build relcache entry. */
1484  targetrel = relation_open(relid, NoLock);
1485 
1486  /*
1487  * On partitioned tables, this operation recurses to partitions. Lock all
1488  * tables upfront.
1489  */
1490  if (targetrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1491  (void) find_all_inheritors(relid, AccessExclusiveLock, NULL);
1492 
1493  tgrel = table_open(TriggerRelationId, RowExclusiveLock);
1494 
1495  /*
1496  * Search for the trigger to modify.
1497  */
1498  ScanKeyInit(&key[0],
1499  Anum_pg_trigger_tgrelid,
1500  BTEqualStrategyNumber, F_OIDEQ,
1501  ObjectIdGetDatum(relid));
1502  ScanKeyInit(&key[1],
1503  Anum_pg_trigger_tgname,
1504  BTEqualStrategyNumber, F_NAMEEQ,
1505  PointerGetDatum(stmt->subname));
1506  tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
1507  NULL, 2, key);
1508  if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1509  {
1510  Form_pg_trigger trigform;
1511 
1512  trigform = (Form_pg_trigger) GETSTRUCT(tuple);
1513  tgoid = trigform->oid;
1514 
1515  /*
1516  * If the trigger descends from a trigger on a parent partitioned
1517  * table, reject the rename. We don't allow a trigger in a partition
1518  * to differ in name from that of its parent: that would lead to an
1519  * inconsistency that pg_dump would not reproduce.
1520  */
1521  if (OidIsValid(trigform->tgparentid))
1522  ereport(ERROR,
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.
4294  */
4295  for (tgindx = 0; tgindx < trigdesc->numtriggers; tgindx++)
4296  {
4297  if (trigdesc->triggers[tgindx].tgoid == tgoid)
4298  {
4299  LocTriggerData.tg_trigger = &(trigdesc->triggers[tgindx]);
4300  break;
4301  }
4302  }
4303  if (LocTriggerData.tg_trigger == NULL)
4304  elog(ERROR, "could not find trigger %u", tgoid);
4305 
4306  /*
4307  * If doing EXPLAIN ANALYZE, start charging time to this trigger. We want
4308  * to include time spent re-fetching tuples in the trigger cost.
4309  */
4310  if (instr)
4311  InstrStartNode(instr + tgindx);
4312 
4313  /*
4314  * Fetch the required tuple(s).
4315  */
4316  switch (event->ate_flags & AFTER_TRIGGER_TUP_BITS)
4317  {
4319  {
4320  Tuplestorestate *fdw_tuplestore = GetCurrentFDWTuplestore();
4321 
4322  if (!tuplestore_gettupleslot(fdw_tuplestore, true, false,
4323  trig_tuple_slot1))
4324  elog(ERROR, "failed to fetch tuple1 for AFTER trigger");
4325 
4326  if ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) ==
4328  !tuplestore_gettupleslot(fdw_tuplestore, true, false,
4329  trig_tuple_slot2))
4330  elog(ERROR, "failed to fetch tuple2 for AFTER trigger");
4331  }
4332  /* fall through */
4334 
4335  /*
4336  * Store tuple in the slot so that tg_trigtuple does not reference
4337  * tuplestore memory. (It is formally possible for the trigger
4338  * function to queue trigger events that add to the same
4339  * tuplestore, which can push other tuples out of memory.) The
4340  * distinction is academic, because we start with a minimal tuple
4341  * that is stored as a heap tuple, constructed in different memory
4342  * context, in the slot anyway.
4343  */
4344  LocTriggerData.tg_trigslot = trig_tuple_slot1;
4345  LocTriggerData.tg_trigtuple =
4346  ExecFetchSlotHeapTuple(trig_tuple_slot1, true, &should_free_trig);
4347 
4348  if ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) ==
4350  {
4351  LocTriggerData.tg_newslot = trig_tuple_slot2;
4352  LocTriggerData.tg_newtuple =
4353  ExecFetchSlotHeapTuple(trig_tuple_slot2, true, &should_free_new);
4354  }
4355  else
4356  {
4357  LocTriggerData.tg_newtuple = NULL;
4358  }
4359  break;
4360 
4361  default:
4362  if (ItemPointerIsValid(&(event->ate_ctid1)))
4363  {
4364  TupleTableSlot *src_slot = ExecGetTriggerOldSlot(estate,
4365  src_relInfo);
4366 
4367  if (!table_tuple_fetch_row_version(src_rel,
4368  &(event->ate_ctid1),
4369  SnapshotAny,
4370  src_slot))
4371  elog(ERROR, "failed to fetch tuple1 for AFTER trigger");
4372 
4373  /*
4374  * Store the tuple fetched from the source partition into the
4375  * target (root partitioned) table slot, converting if needed.
4376  */
4377  if (src_relInfo != relInfo)
4378  {
4379  TupleConversionMap *map = ExecGetChildToRootMap(src_relInfo);
4380 
4381  LocTriggerData.tg_trigslot = ExecGetTriggerOldSlot(estate, relInfo);
4382  if (map)
4383  {
4385  src_slot,
4386  LocTriggerData.tg_trigslot);
4387  }
4388  else
4389  ExecCopySlot(LocTriggerData.tg_trigslot, src_slot);
4390  }
4391  else
4392  LocTriggerData.tg_trigslot = src_slot;
4393  LocTriggerData.tg_trigtuple =
4394  ExecFetchSlotHeapTuple(LocTriggerData.tg_trigslot, false, &should_free_trig);
4395  }
4396  else
4397  {
4398  LocTriggerData.tg_trigtuple = NULL;
4399  }
4400 
4401  /* don't touch ctid2 if not there */
4403  (event->ate_flags & AFTER_TRIGGER_CP_UPDATE)) &&
4404  ItemPointerIsValid(&(event->ate_ctid2)))
4405  {
4406  TupleTableSlot *dst_slot = ExecGetTriggerNewSlot(estate,
4407  dst_relInfo);
4408 
4409  if (!table_tuple_fetch_row_version(dst_rel,
4410  &(event->ate_ctid2),
4411  SnapshotAny,
4412  dst_slot))
4413  elog(ERROR, "failed to fetch tuple2 for AFTER trigger");
4414 
4415  /*
4416  * Store the tuple fetched from the destination partition into
4417  * the target (root partitioned) table slot, converting if
4418  * needed.
4419  */
4420  if (dst_relInfo != relInfo)
4421  {
4422  TupleConversionMap *map = ExecGetChildToRootMap(dst_relInfo);
4423 
4424  LocTriggerData.tg_newslot = ExecGetTriggerNewSlot(estate, relInfo);
4425  if (map)
4426  {
4428  dst_slot,
4429  LocTriggerData.tg_newslot);
4430  }
4431  else
4432  ExecCopySlot(LocTriggerData.tg_newslot, dst_slot);
4433  }
4434  else
4435  LocTriggerData.tg_newslot = dst_slot;
4436  LocTriggerData.tg_newtuple =
4437  ExecFetchSlotHeapTuple(LocTriggerData.tg_newslot, false, &should_free_new);
4438  }
4439  else
4440  {
4441  LocTriggerData.tg_newtuple = NULL;
4442  }
4443  }
4444 
4445  /*
4446  * Set up the tuplestore information to let the trigger have access to
4447  * transition tables. When we first make a transition table available to
4448  * a trigger, mark it "closed" so that it cannot change anymore. If any
4449  * additional events of the same type get queued in the current trigger
4450  * query level, they'll go into new transition tables.
4451  */
4452  LocTriggerData.tg_oldtable = LocTriggerData.tg_newtable = NULL;
4453  if (evtshared->ats_table)
4454  {
4455  if (LocTriggerData.tg_trigger->tgoldtable)
4456  {
4457  if (TRIGGER_FIRED_BY_UPDATE(evtshared->ats_event))
4458  LocTriggerData.tg_oldtable = evtshared->ats_table->old_upd_tuplestore;
4459  else
4460  LocTriggerData.tg_oldtable = evtshared->ats_table->old_del_tuplestore;
4461  evtshared->ats_table->closed = true;
4462  }
4463 
4464  if (LocTriggerData.tg_trigger->tgnewtable)
4465  {
4466  if (TRIGGER_FIRED_BY_INSERT(evtshared->ats_event))
4467  LocTriggerData.tg_newtable = evtshared->ats_table->new_ins_tuplestore;
4468  else
4469  LocTriggerData.tg_newtable = evtshared->ats_table->new_upd_tuplestore;
4470  evtshared->ats_table->closed = true;
4471  }
4472  }
4473 
4474  /*
4475  * Setup the remaining trigger information
4476  */
4477  LocTriggerData.type = T_TriggerData;
4478  LocTriggerData.tg_event =
4480  LocTriggerData.tg_relation = rel;
4481  if (TRIGGER_FOR_UPDATE(LocTriggerData.tg_trigger->tgtype))
4482  LocTriggerData.tg_updatedcols = evtshared->ats_modifiedcols;
4483 
4484  MemoryContextReset(per_tuple_context);
4485 
4486  /*
4487  * Call the trigger and throw away any possibly returned updated tuple.
4488  * (Don't let ExecCallTriggerFunc measure EXPLAIN time.)
4489  */
4490  rettuple = ExecCallTriggerFunc(&LocTriggerData,
4491  tgindx,
4492  finfo,
4493  NULL,
4494  per_tuple_context);
4495  if (rettuple != NULL &&
4496  rettuple != LocTriggerData.tg_trigtuple &&
4497  rettuple != LocTriggerData.tg_newtuple)
4498  heap_freetuple(rettuple);
4499 
4500  /*
4501  * Release resources
4502  */
4503  if (should_free_trig)
4504  heap_freetuple(LocTriggerData.tg_trigtuple);
4505  if (should_free_new)
4506  heap_freetuple(LocTriggerData.tg_newtuple);
4507 
4508  /* don't clear slots' contents if foreign table */
4509  if (trig_tuple_slot1 == NULL)
4510  {
4511  if (LocTriggerData.tg_trigslot)
4512  ExecClearTuple(LocTriggerData.tg_trigslot);
4513  if (LocTriggerData.tg_newslot)
4514  ExecClearTuple(LocTriggerData.tg_newslot);
4515  }
4516 
4517  /*
4518  * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
4519  * one "tuple returned" (really the number of firings).
4520  */
4521  if (instr)
4522  InstrStopNode(instr + tgindx, 1);
4523 }
4524 
4525 
4526 /*
4527  * afterTriggerMarkEvents()
4528  *
4529  * Scan the given event list for not yet invoked events. Mark the ones
4530  * that can be invoked now with the current firing ID.
4531  *
4532  * If move_list isn't NULL, events that are not to be invoked now are
4533  * transferred to move_list.
4534  *
4535  * When immediate_only is true, do not invoke currently-deferred triggers.
4536  * (This will be false only at main transaction exit.)
4537  *
4538  * Returns true if any invokable events were found.
4539  */
4540 static bool
4542  AfterTriggerEventList *move_list,
4543  bool immediate_only)
4544 {
4545  bool found = false;
4546  bool deferred_found = false;
4547  AfterTriggerEvent event;
4549 
4550  for_each_event_chunk(event, chunk, *events)
4551  {
4552  AfterTriggerShared evtshared = GetTriggerSharedData(event);
4553  bool defer_it = false;
4554 
4555  if (!(event->ate_flags &
4557  {
4558  /*
4559  * This trigger hasn't been called or scheduled yet. Check if we
4560  * should call it now.
4561  */
4562  if (immediate_only && afterTriggerCheckState(evtshared))
4563  {
4564  defer_it = true;
4565  }
4566  else
4567  {
4568  /*
4569  * Mark it as to be fired in this firing cycle.
4570  */
4572  event->ate_flags |= AFTER_TRIGGER_IN_PROGRESS;
4573  found = true;
4574  }
4575  }
4576 
4577  /*
4578  * If it's deferred, move it to move_list, if requested.
4579  */
4580  if (defer_it && move_list != NULL)
4581  {
4582  deferred_found = true;
4583  /* add it to move_list */
4584  afterTriggerAddEvent(move_list, event, evtshared);
4585  /* mark original copy "done" so we don't do it again */
4586  event->ate_flags |= AFTER_TRIGGER_DONE;
4587  }
4588  }
4589 
4590  /*
4591  * We could allow deferred triggers if, before the end of the
4592  * security-restricted operation, we were to verify that a SET CONSTRAINTS
4593  * ... IMMEDIATE has fired all such triggers. For now, don't bother.
4594  */
4595  if (deferred_found && InSecurityRestrictedOperation())
4596  ereport(ERROR,
4597  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4598  errmsg("cannot fire deferred trigger within security-restricted operation")));
4599 
4600  return found;
4601 }
4602 
4603 /*
4604  * afterTriggerInvokeEvents()
4605  *
4606  * Scan the given event list for events that are marked as to be fired
4607  * in the current firing cycle, and fire them.
4608  *
4609  * If estate isn't NULL, we use its result relation info to avoid repeated
4610  * openings and closing of trigger target relations. If it is NULL, we
4611  * make one locally to cache the info in case there are multiple trigger
4612  * events per rel.
4613  *
4614  * When delete_ok is true, it's safe to delete fully-processed events.
4615  * (We are not very tense about that: we simply reset a chunk to be empty
4616  * if all its events got fired. The objective here is just to avoid useless
4617  * rescanning of events when a trigger queues new events during transaction
4618  * end, so it's not necessary to worry much about the case where only
4619  * some events are fired.)
4620  *
4621  * Returns true if no unfired events remain in the list (this allows us
4622  * to avoid repeating afterTriggerMarkEvents).
4623  */
4624 static bool
4626  CommandId firing_id,
4627  EState *estate,
4628  bool delete_ok)
4629 {
4630  bool all_fired = true;
4632  MemoryContext per_tuple_context;
4633  bool local_estate = false;
4634  ResultRelInfo *rInfo = NULL;
4635  Relation rel = NULL;
4636  TriggerDesc *trigdesc = NULL;
4637  FmgrInfo *finfo = NULL;
4638  Instrumentation *instr = NULL;
4639  TupleTableSlot *slot1 = NULL,
4640  *slot2 = NULL;
4641 
4642  /* Make a local EState if need be */
4643  if (estate == NULL)
4644  {
4645  estate = CreateExecutorState();
4646  local_estate = true;
4647  }
4648 
4649  /* Make a per-tuple memory context for trigger function calls */
4650  per_tuple_context =
4652  "AfterTriggerTupleContext",
4654 
4655  for_each_chunk(chunk, *events)
4656  {
4657  AfterTriggerEvent event;
4658  bool all_fired_in_chunk = true;
4659 
4660  for_each_event(event, chunk)
4661  {
4662  AfterTriggerShared evtshared = GetTriggerSharedData(event);
4663 
4664  /*
4665  * Is it one for me to fire?
4666  */
4667  if ((event->ate_flags & AFTER_TRIGGER_IN_PROGRESS) &&
4668  evtshared->ats_firing_id == firing_id)
4669  {
4670  ResultRelInfo *src_rInfo,
4671  *dst_rInfo;
4672 
4673  /*
4674  * So let's fire it... but first, find the correct relation if
4675  * this is not the same relation as before.
4676  */
4677  if (rel == NULL || RelationGetRelid(rel) != evtshared->ats_relid)
4678  {
4679  rInfo = ExecGetTriggerResultRel(estate, evtshared->ats_relid,
4680  NULL);
4681  rel = rInfo->ri_RelationDesc;
4682  /* Catch calls with insufficient relcache refcounting */
4684  trigdesc = rInfo->ri_TrigDesc;
4685  finfo = rInfo->ri_TrigFunctions;
4686  instr = rInfo->ri_TrigInstrument;
4687  if (slot1 != NULL)
4688  {
4691  slot1 = slot2 = NULL;
4692  }
4693  if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
4694  {
4695  slot1 = MakeSingleTupleTableSlot(rel->rd_att,
4697  slot2 = MakeSingleTupleTableSlot(rel->rd_att,
4699  }
4700  if (trigdesc == NULL) /* should not happen */
4701  elog(ERROR, "relation %u has no triggers",
4702  evtshared->ats_relid);
4703  }
4704 
4705  /*
4706  * Look up source and destination partition result rels of a
4707  * cross-partition update event.
4708  */
4709  if ((event->ate_flags & AFTER_TRIGGER_TUP_BITS) ==
4711  {
4712  Assert(OidIsValid(event->ate_src_part) &&
4713  OidIsValid(event->ate_dst_part));
4714  src_rInfo = ExecGetTriggerResultRel(estate,
4715  event->ate_src_part,
4716  rInfo);
4717  dst_rInfo = ExecGetTriggerResultRel(estate,
4718  event->ate_dst_part,
4719  rInfo);
4720  }
4721  else
4722  src_rInfo = dst_rInfo = rInfo;
4723 
4724  /*
4725  * Fire it. Note that the AFTER_TRIGGER_IN_PROGRESS flag is
4726  * still set, so recursive examinations of the event list
4727  * won't try to re-fire it.
4728  */
4729  AfterTriggerExecute(estate, event, rInfo,
4730  src_rInfo, dst_rInfo,
4731  trigdesc, finfo, instr,
4732  per_tuple_context, slot1, slot2);
4733 
4734  /*
4735  * Mark the event as done.
4736  */
4737  event->ate_flags &= ~AFTER_TRIGGER_IN_PROGRESS;
4738  event->ate_flags |= AFTER_TRIGGER_DONE;
4739  }
4740  else if (!(event->ate_flags & AFTER_TRIGGER_DONE))
4741  {
4742  /* something remains to be done */
4743  all_fired = all_fired_in_chunk = false;
4744  }
4745  }
4746 
4747  /* Clear the chunk if delete_ok and nothing left of interest */
4748  if (delete_ok && all_fired_in_chunk)
4749  {
4750  chunk->freeptr = CHUNK_DATA_START(chunk);
4751  chunk->endfree = chunk->endptr;
4752 
4753  /*
4754  * If it's last chunk, must sync event list's tailfree too. Note
4755  * that delete_ok must NOT be passed as true if there could be
4756  * additional AfterTriggerEventList values pointing at this event
4757  * list, since we'd fail to fix their copies of tailfree.
4758  */
4759  if (chunk == events->tail)
4760  events->tailfree = chunk->freeptr;
4761  }
4762  }
4763  if (slot1 != NULL)
4764  {
4767  }
4768 
4769  /* Release working resources */
4770  MemoryContextDelete(per_tuple_context);
4771 
4772  if (local_estate)
4773  {
4774  ExecCloseResultRelations(estate);
4775  ExecResetTupleTable(estate->es_tupleTable, false);
4776  FreeExecutorState(estate);
4777  }
4778 
4779  return all_fired;
4780 }
4781 
4782 
4783 /*
4784  * GetAfterTriggersTableData
4785  *
4786  * Find or create an AfterTriggersTableData struct for the specified
4787  * trigger event (relation + operation type). Ignore existing structs
4788  * marked "closed"; we don't want to put any additional tuples into them,
4789  * nor change their stmt-triggers-fired state.
4790  *
4791  * Note: the AfterTriggersTableData list is allocated in the current
4792  * (sub)transaction's CurTransactionContext. This is OK because
4793  * we don't need it to live past AfterTriggerEndQuery.
4794  */
4795 static AfterTriggersTableData *
4797 {
4798  AfterTriggersTableData *table;
4800  MemoryContext oldcxt;
4801  ListCell *lc;
4802 
4803  /* Caller should have ensured query_depth is OK. */
4807 
4808  foreach(lc, qs->tables)
4809  {
4810  table = (AfterTriggersTableData *) lfirst(lc);
4811  if (table->relid == relid && table->cmdType == cmdType &&
4812  !table->closed)
4813  return table;
4814  }
4815 
4817 
4819  table->relid = relid;
4820  table->cmdType = cmdType;
4821  qs->tables = lappend(qs->tables, table);
4822 
4823  MemoryContextSwitchTo(oldcxt);
4824 
4825  return table;
4826 }
4827 
4828 /*
4829  * Returns a TupleTableSlot suitable for holding the tuples to be put
4830  * into AfterTriggersTableData's transition table tuplestores.
4831  */
4832 static TupleTableSlot *
4834  TupleDesc tupdesc)
4835 {
4836  /* Create it if not already done. */
4837  if (!table->storeslot)
4838  {
4839  MemoryContext oldcxt;
4840 
4841  /*
4842  * We need this slot only until AfterTriggerEndQuery, but making it
4843  * last till end-of-subxact is good enough. It'll be freed by
4844  * AfterTriggerFreeQuery(). However, the passed-in tupdesc might have
4845  * a different lifespan, so we'd better make a copy of that.
4846  */
4848  tupdesc = CreateTupleDescCopy(tupdesc);
4849  table->storeslot = MakeSingleTupleTableSlot(tupdesc, &TTSOpsVirtual);
4850  MemoryContextSwitchTo(oldcxt);
4851  }
4852 
4853  return table->storeslot;
4854 }
4855 
4856 /*
4857  * MakeTransitionCaptureState
4858  *
4859  * Make a TransitionCaptureState object for the given TriggerDesc, target
4860  * relation, and operation type. The TCS object holds all the state needed
4861  * to decide whether to capture tuples in transition tables.
4862  *
4863  * If there are no triggers in 'trigdesc' that request relevant transition
4864  * tables, then return NULL.
4865  *
4866  * The resulting object can be passed to the ExecAR* functions. When
4867  * dealing with child tables, the caller can set tcs_original_insert_tuple
4868  * to avoid having to reconstruct the original tuple in the root table's
4869  * format.
4870  *
4871  * Note that we copy the flags from a parent table into this struct (rather
4872  * than subsequently using the relation's TriggerDesc directly) so that we can
4873  * use it to control collection of transition tuples from child tables.
4874  *
4875  * Per SQL spec, all operations of the same kind (INSERT/UPDATE/DELETE)
4876  * on the same table during one query should share one transition table.
4877  * Therefore, the Tuplestores are owned by an AfterTriggersTableData struct
4878  * looked up using the table OID + CmdType, and are merely referenced by
4879  * the TransitionCaptureState objects we hand out to callers.
4880  */
4883 {
4885  bool need_old_upd,
4886  need_new_upd,
4887  need_old_del,
4888  need_new_ins;
4889  AfterTriggersTableData *table;
4890  MemoryContext oldcxt;
4891  ResourceOwner saveResourceOwner;
4892 
4893  if (trigdesc == NULL)
4894  return NULL;
4895 
4896  /* Detect which table(s) we need. */
4897  switch (cmdType)
4898  {
4899  case CMD_INSERT:
4900  need_old_upd = need_old_del = need_new_upd = false;
4901  need_new_ins = trigdesc->trig_insert_new_table;
4902  break;
4903  case CMD_UPDATE:
4904  need_old_upd = trigdesc->trig_update_old_table;
4905  need_new_upd = trigdesc->trig_update_new_table;
4906  need_old_del = need_new_ins = false;
4907  break;
4908  case CMD_DELETE:
4909  need_old_del = trigdesc->trig_delete_old_table;
4910  need_old_upd = need_new_upd = need_new_ins = false;
4911  break;
4912  case CMD_MERGE:
4913  need_old_upd = trigdesc->trig_update_old_table;
4914  need_new_upd = trigdesc->trig_update_new_table;
4915  need_old_del = trigdesc->trig_delete_old_table;
4916  need_new_ins = trigdesc->trig_insert_new_table;
4917  break;
4918  default:
4919  elog(ERROR, "unexpected CmdType: %d", (int) cmdType);
4920  /* keep compiler quiet */
4921  need_old_upd = need_new_upd = need_old_del = need_new_ins = false;
4922  break;
4923  }
4924  if (!need_old_upd && !need_new_upd && !need_new_ins && !need_old_del)
4925  return NULL;
4926 
4927  /* Check state, like AfterTriggerSaveEvent. */
4928  if (afterTriggers.query_depth < 0)
4929  elog(ERROR, "MakeTransitionCaptureState() called outside of query");
4930 
4931  /* Be sure we have enough space to record events at this query depth. */
4934 
4935  /*
4936  * Find or create an AfterTriggersTableData struct to hold the
4937  * tuplestore(s). If there's a matching struct but it's marked closed,
4938  * ignore it; we need a newer one.
4939  *
4940  * Note: the AfterTriggersTableData list, as well as the tuplestores, are
4941  * allocated in the current (sub)transaction's CurTransactionContext, and
4942  * the tuplestores are managed by the (sub)transaction's resource owner.
4943  * This is sufficient lifespan because we do not allow triggers using
4944  * transition tables to be deferrable; they will be fired during
4945  * AfterTriggerEndQuery, after which it's okay to delete the data.
4946  */
4947  table = GetAfterTriggersTableData(relid, cmdType);
4948 
4949  /* Now create required tuplestore(s), if we don't have them already. */
4951  saveResourceOwner = CurrentResourceOwner;
4953 
4954  if (need_old_upd && table->old_upd_tuplestore == NULL)
4955  table->old_upd_tuplestore = tuplestore_begin_heap(false, false, work_mem);
4956  if (need_new_upd && table->new_upd_tuplestore == NULL)
4957  table->new_upd_tuplestore = tuplestore_begin_heap(false, false, work_mem);
4958  if (need_old_del && table->old_del_tuplestore == NULL)
4959  table->old_del_tuplestore = tuplestore_begin_heap(false, false, work_mem);
4960  if (need_new_ins && table->new_ins_tuplestore == NULL)
4961  table->new_ins_tuplestore = tuplestore_begin_heap(false, false, work_mem);
4962 
4963  CurrentResourceOwner = saveResourceOwner;
4964  MemoryContextSwitchTo(oldcxt);
4965 
4966  /* Now build the TransitionCaptureState struct, in caller's context */
4968  state->tcs_delete_old_table = trigdesc->trig_delete_old_table;
4969  state->tcs_update_old_table = trigdesc->trig_update_old_table;
4970  state->tcs_update_new_table = trigdesc->trig_update_new_table;
4971  state->tcs_insert_new_table = trigdesc->trig_insert_new_table;
4972  state->tcs_private = table;
4973 
4974  return state;
4975 }
4976 
4977 
4978 /* ----------
4979  * AfterTriggerBeginXact()
4980  *
4981  * Called at transaction start (either BEGIN or implicit for single
4982  * statement outside of transaction block).
4983  * ----------
4984  */
4985 void
4987 {
4988  /*
4989  * Initialize after-trigger state structure to empty
4990  */
4991  afterTriggers.firing_counter = (CommandId) 1; /* mustn't be 0 */
4993 
4994  /*
4995  * Verify that there is no leftover state remaining. If these assertions
4996  * trip, it means that AfterTriggerEndXact wasn't called or didn't clean
4997  * up properly.
4998  */
4999  Assert(afterTriggers.state == NULL);
5000  Assert(afterTriggers.query_stack == NULL);
5002  Assert(afterTriggers.event_cxt == NULL);
5003  Assert(afterTriggers.events.head == NULL);
5004  Assert(afterTriggers.trans_stack == NULL);
5006 }
5007 
5008 
5009 /* ----------
5010  * AfterTriggerBeginQuery()
5011  *
5012  * Called just before we start processing a single query within a
5013  * transaction (or subtransaction). Most of the real work gets deferred
5014  * until somebody actually tries to queue a trigger event.
5015  * ----------
5016  */
5017 void
5019 {
5020  /* Increase the query stack depth */
5022 }
5023 
5024 
5025 /* ----------
5026  * AfterTriggerEndQuery()
5027  *
5028  * Called after one query has been completely processed. At this time
5029  * we invoke all AFTER IMMEDIATE trigger events queued by the query, and
5030  * transfer deferred trigger events to the global deferred-trigger list.
5031  *
5032  * Note that this must be called BEFORE closing down the executor
5033  * with ExecutorEnd, because we make use of the EState's info about
5034  * target relations. Normally it is called from ExecutorFinish.
5035  * ----------
5036  */
5037 void
5039 {
5041 
5042  /* Must be inside a query, too */
5044 
5045  /*
5046  * If we never even got as far as initializing the event stack, there
5047  * certainly won't be any events, so exit quickly.
5048  */
5050  {
5052  return;
5053  }
5054 
5055  /*
5056  * Process all immediate-mode triggers queued by the query, and move the
5057  * deferred ones to the main list of deferred events.
5058  *
5059  * Notice that we decide which ones will be fired, and put the deferred
5060  * ones on the main list, before anything is actually fired. This ensures
5061  * reasonably sane behavior if a trigger function does SET CONSTRAINTS ...
5062  * IMMEDIATE: all events we have decided to defer will be available for it
5063  * to fire.
5064  *
5065  * We loop in case a trigger queues more events at the same query level.
5066  * Ordinary trigger functions, including all PL/pgSQL trigger functions,
5067  * will instead fire any triggers in a dedicated query level. Foreign key
5068  * enforcement triggers do add to the current query level, thanks to their
5069  * passing fire_triggers = false to SPI_execute_snapshot(). Other
5070  * C-language triggers might do likewise.
5071  *
5072  * If we find no firable events, we don't have to increment
5073  * firing_counter.
5074  */
5076 
5077  for (;;)
5078  {
5080  {
5081  CommandId firing_id = afterTriggers.firing_counter++;
5082  AfterTriggerEventChunk *oldtail = qs->events.tail;
5083 
5084  if (afterTriggerInvokeEvents(&qs->events, firing_id, estate, false))
5085  break; /* all fired */
5086 
5087  /*
5088  * Firing a trigger could result in query_stack being repalloc'd,
5089  * so we must recalculate qs after each afterTriggerInvokeEvents
5090  * call. Furthermore, it's unsafe to pass delete_ok = true here,
5091  * because that could cause afterTriggerInvokeEvents to try to
5092  * access qs->events after the stack has been repalloc'd.
5093  */
5095 
5096  /*
5097  * We'll need to scan the events list again. To reduce the cost
5098  * of doing so, get rid of completely-fired chunks. We know that
5099  * all events were marked IN_PROGRESS or DONE at the conclusion of
5100  * afterTriggerMarkEvents, so any still-interesting events must
5101  * have been added after that, and so must be in the chunk that
5102  * was then the tail chunk, or in later chunks. So, zap all
5103  * chunks before oldtail. This is approximately the same set of
5104  * events we would have gotten rid of by passing delete_ok = true.
5105  */
5106  Assert(oldtail != NULL);
5107  while (qs->events.head != oldtail)
5109  }
5110  else
5111  break;
5112  }
5113 
5114  /* Release query-level-local storage, including tuplestores if any */
5116 
5118 }
5119 
5120 
5121 /*
5122  * AfterTriggerFreeQuery
5123  * Release subsidiary storage for a trigger query level.
5124  * This includes closing down tuplestores.
5125  * Note: it's important for this to be safe if interrupted by an error
5126  * and then called again for the same query level.
5127  */
5128 static void
5130 {
5131  Tuplestorestate *ts;
5132  List *tables;
5133  ListCell *lc;
5134 
5135  /* Drop the trigger events */
5137 
5138  /* Drop FDW tuplestore if any */
5139  ts = qs->fdw_tuplestore;
5140  qs->fdw_tuplestore = NULL;
5141  if (ts)
5142  tuplestore_end(ts);
5143 
5144  /* Release per-table subsidiary storage */
5145  tables = qs->tables;
5146  foreach(lc, tables)
5147  {
5149 
5150  ts = table->old_upd_tuplestore;
5151  table->old_upd_tuplestore = NULL;
5152  if (ts)
5153  tuplestore_end(ts);
5154  ts = table->new_upd_tuplestore;
5155  table->new_upd_tuplestore = NULL;
5156  if (ts)
5157  tuplestore_end(ts);
5158  ts = table->old_del_tuplestore;
5159  table->old_del_tuplestore = NULL;
5160  if (ts)
5161  tuplestore_end(ts);
5162  ts = table->new_ins_tuplestore;
5163  table->new_ins_tuplestore = NULL;
5164  if (ts)
5165  tuplestore_end(ts);
5166  if (table->storeslot)
5167  {
5168  TupleTableSlot *slot = table->storeslot;
5169 
5170  table->storeslot = NULL;
5172  }
5173  }
5174 
5175  /*
5176  * Now free the AfterTriggersTableData structs and list cells. Reset list
5177  * pointer first; if list_free_deep somehow gets an error, better to leak
5178  * that storage than have an infinite loop.
5179  */
5180  qs->tables = NIL;
5181  list_free_deep(tables);
5182 }
5183 
5184 
5185 /* ----------
5186  * AfterTriggerFireDeferred()
5187  *
5188  * Called just before the current transaction is committed. At this
5189  * time we invoke all pending DEFERRED triggers.
5190  *
5191  * It is possible for other modules to queue additional deferred triggers
5192  * during pre-commit processing; therefore xact.c may have to call this
5193  * multiple times.
5194  * ----------
5195  */
5196 void
5198 {
5199  AfterTriggerEventList *events;
5200  bool snap_pushed = false;
5201 
5202  /* Must not be inside a query */
5204 
5205  /*
5206  * If there are any triggers to fire, make sure we have set a snapshot for
5207  * them to use. (Since PortalRunUtility doesn't set a snap for COMMIT, we
5208  * can't assume ActiveSnapshot is valid on entry.)
5209  */
5210  events = &afterTriggers.events;
5211  if (events->head != NULL)
5212  {
5214  snap_pushed = true;
5215  }
5216 
5217  /*
5218  * Run all the remaining triggers. Loop until they are all gone, in case
5219  * some trigger queues more for us to do.
5220  */
5221  while (afterTriggerMarkEvents(events, NULL, false))
5222  {
5223  CommandId firing_id = afterTriggers.firing_counter++;
5224 
5225  if (afterTriggerInvokeEvents(events, firing_id, NULL, true))
5226  break; /* all fired */
5227  }
5228 
5229  /*
5230  * We don't bother freeing the event list, since it will go away anyway
5231  * (and more efficiently than via pfree) in AfterTriggerEndXact.
5232  */
5233 
5234  if (snap_pushed)
5236 }
5237 
5238 
5239 /* ----------
5240  * AfterTriggerEndXact()
5241  *
5242  * The current transaction is finishing.
5243  *
5244  * Any unfired triggers are canceled so we simply throw
5245  * away anything we know.
5246  *
5247  * Note: it is possible for this to be called repeatedly in case of
5248  * error during transaction abort; therefore, do not complain if
5249  * already closed down.
5250  * ----------
5251  */
5252 void
5253 AfterTriggerEndXact(bool isCommit)
5254 {
5255  /*
5256  * Forget the pending-events list.
5257  *
5258  * Since all the info is in TopTransactionContext or children thereof, we
5259  * don't really need to do anything to reclaim memory. However, the
5260  * pending-events list could be large, and so it's useful to discard it as
5261  * soon as possible --- especially if we are aborting because we ran out
5262  * of memory for the list!
5263  */
5265  {
5267  afterTriggers.event_cxt = NULL;
5268  afterTriggers.events.head = NULL;
5269  afterTriggers.events.tail = NULL;
5270  afterTriggers.events.tailfree = NULL;
5271  }
5272 
5273  /*
5274  * Forget any subtransaction state as well. Since this can't be very
5275  * large, we let the eventual reset of TopTransactionContext free the
5276  * memory instead of doing it here.
5277  */
5278  afterTriggers.trans_stack = NULL;
5280 
5281 
5282  /*
5283  * Forget the query stack and constraint-related state information. As
5284  * with the subtransaction state information, we don't bother freeing the
5285  * memory here.
5286  */
5287  afterTriggers.query_stack = NULL;
5289  afterTriggers.state = NULL;
5290 
5291  /* No more afterTriggers manipulation until next transaction starts. */
5293 }
5294 
5295 /*
5296  * AfterTriggerBeginSubXact()
5297  *
5298  * Start a subtransaction.
5299  */
5300 void
5302 {
5303  int my_level = GetCurrentTransactionNestLevel();
5304 
5305  /*
5306  * Allocate more space in the trans_stack if needed. (Note: because the
5307  * minimum nest level of a subtransaction is 2, we waste the first couple
5308  * entries of the array; not worth the notational effort to avoid it.)
5309  */
5310  while (my_level >= afterTriggers.maxtransdepth)
5311  {
5312  if (afterTriggers.maxtransdepth == 0)
5313  {
5314  /* Arbitrarily initialize for max of 8 subtransaction levels */
5317  8 * sizeof(AfterTriggersTransData));
5319  }
5320  else
5321  {
5322  /* repalloc will keep the stack in the same context */
5323  int new_alloc = afterTriggers.maxtransdepth * 2;
5324 
5327  new_alloc * sizeof(AfterTriggersTransData));
5328  afterTriggers.maxtransdepth = new_alloc;
5329  }
5330  }
5331 
5332  /*
5333  * Push the current information into the stack. The SET CONSTRAINTS state
5334  * is not saved until/unless changed. Likewise, we don't make a
5335  * per-subtransaction event context until needed.
5336  */
5337  afterTriggers.trans_stack[my_level].state = NULL;
5341 }
5342 
5343 /*
5344  * AfterTriggerEndSubXact()
5345  *
5346  * The current subtransaction is ending.
5347  */
5348 void
5350 {
5351  int my_level = GetCurrentTransactionNestLevel();
5353  AfterTriggerEvent event;
5355  CommandId subxact_firing_id;
5356 
5357  /*
5358  * Pop the prior state if needed.
5359  */
5360  if (isCommit)
5361  {
5362  Assert(my_level < afterTriggers.maxtransdepth);
5363  /* If we saved a prior state, we don't need it anymore */
5364  state = afterTriggers.trans_stack[my_level].state;
5365  if (state != NULL)
5366  pfree(state);
5367  /* this avoids double pfree if error later: */
5368  afterTriggers.trans_stack[my_level].state = NULL;
5371  }
5372  else
5373  {
5374  /*
5375  * Aborting. It is possible subxact start failed before calling
5376  * AfterTriggerBeginSubXact, in which case we mustn't risk touching
5377  * trans_stack levels that aren't there.
5378  */
5379  if (my_level >= afterTriggers.maxtransdepth)
5380  return;
5381 
5382  /*
5383  * Release query-level storage for queries being aborted, and restore
5384  * query_depth to its pre-subxact value. This assumes that a
5385  * subtransaction will not add events to query levels started in a
5386  * earlier transaction state.
5387  */
5389  {
5393  }
5396 
5397  /*
5398  * Restore the global deferred-event list to its former length,
5399  * discarding any events queued by the subxact.
5400  */
5402  &afterTriggers.trans_stack[my_level].events);
5403 
5404  /*
5405  * Restore the trigger state. If the saved state is NULL, then this
5406  * subxact didn't save it, so it doesn't need restoring.
5407  */
5408  state = afterTriggers.trans_stack[my_level].state;
5409  if (state != NULL)
5410  {
5413  }
5414  /* this avoids double pfree if error later: */
5415  afterTriggers.trans_stack[my_level].state = NULL;
5416 
5417  /*
5418  * Scan for any remaining deferred events that were marked DONE or IN
5419  * PROGRESS by this subxact or a child, and un-mark them. We can
5420  * recognize such events because they have a firing ID greater than or
5421  * equal to the firing_counter value we saved at subtransaction start.
5422  * (This essentially assumes that the current subxact includes all
5423  * subxacts started after it.)
5424  */
5425  subxact_firing_id = afterTriggers.trans_stack[my_level].firing_counter;
5427  {
5428  AfterTriggerShared evtshared = GetTriggerSharedData(event);
5429 
5430  if (event->ate_flags &
5432  {
5433  if (evtshared->ats_firing_id >= subxact_firing_id)
5434  event->ate_flags &=
5436  }
5437  }
5438  }
5439 }
5440 
5441 /*
5442  * Get the transition table for the given event and depending on whether we are
5443  * processing the old or the new tuple.
5444  */
5445 static Tuplestorestate *
5447  TupleTableSlot *oldslot,
5448  TupleTableSlot *newslot,
5449  TransitionCaptureState *transition_capture)
5450 {
5451  Tuplestorestate *tuplestore = NULL;
5452  bool delete_old_table = transition_capture->tcs_delete_old_table;
5453  bool update_old_table = transition_capture->tcs_update_old_table;
5454  bool update_new_table = transition_capture->tcs_update_new_table;
5455  bool insert_new_table = transition_capture->tcs_insert_new_table;
5456 
5457  /*
5458  * For INSERT events NEW should be non-NULL, for DELETE events OLD should
5459  * be non-NULL, whereas for UPDATE events normally both OLD and NEW are
5460  * non-NULL. But for UPDATE events fired for capturing transition tuples
5461  * during UPDATE partition-key row movement, OLD is NULL when the event is
5462  * for a row being inserted, whereas NEW is NULL when the event is for a
5463  * row being deleted.
5464  */
5465  Assert(!(event == TRIGGER_EVENT_DELETE && delete_old_table &&
5466  TupIsNull(oldslot)));
5467  Assert(!(event == TRIGGER_EVENT_INSERT && insert_new_table &&
5468  TupIsNull(newslot)));
5469 
5470  if (!TupIsNull(oldslot))
5471  {
5472  Assert(TupIsNull(newslot));
5473  if (event == TRIGGER_EVENT_DELETE && delete_old_table)
5474  tuplestore = transition_capture->tcs_private->old_del_tuplestore;
5475  else if (event == TRIGGER_EVENT_UPDATE && update_old_table)
5476  tuplestore = transition_capture->tcs_private->old_upd_tuplestore;
5477  }
5478  else if (!TupIsNull(newslot))
5479  {
5480  Assert(TupIsNull(oldslot));
5481  if (event == TRIGGER_EVENT_INSERT && insert_new_table)
5482  tuplestore = transition_capture->tcs_private->new_ins_tuplestore;
5483  else if (event == TRIGGER_EVENT_UPDATE && update_new_table)
5484  tuplestore = transition_capture->tcs_private->new_upd_tuplestore;
5485  }
5486 
5487  return tuplestore;
5488 }
5489 
5490 /*
5491  * Add the given heap tuple to the given tuplestore, applying the conversion
5492  * map if necessary.
5493  *
5494  * If original_insert_tuple is given, we can add that tuple without conversion.
5495  */
5496 static void
5498  TransitionCaptureState *transition_capture,
5499  ResultRelInfo *relinfo,
5500  TupleTableSlot *slot,
5501  TupleTableSlot *original_insert_tuple,
5502  Tuplestorestate *tuplestore)
5503 {
5504  TupleConversionMap *map;
5505 
5506  /*
5507  * Nothing needs to be done if we don't have a tuplestore.
5508  */
5509  if (tuplestore == NULL)
5510  return;
5511 
5512  if (original_insert_tuple)
5513  tuplestore_puttupleslot(tuplestore, original_insert_tuple);
5514  else if ((map = ExecGetChildToRootMap(relinfo)) != NULL)
5515  {
5516  AfterTriggersTableData *table = transition_capture->tcs_private;
5517  TupleTableSlot *storeslot;
5518 
5519  storeslot = GetAfterTriggersStoreSlot(table, map->outdesc);
5520  execute_attr_map_slot(map->attrMap, slot, storeslot);
5521  tuplestore_puttupleslot(tuplestore, storeslot);
5522  }
5523  else
5524  tuplestore_puttupleslot(tuplestore, slot);
5525 }
5526 
5527 /* ----------
5528  * AfterTriggerEnlargeQueryState()
5529  *
5530  * Prepare the necessary state so that we can record AFTER trigger events
5531  * queued by a query. It is allowed to have nested queries within a
5532  * (sub)transaction, so we need to have separate state for each query
5533  * nesting level.
5534  * ----------
5535  */
5536 static void
5538 {
5539  int init_depth = afterTriggers.maxquerydepth;
5540 
5542 
5543  if (afterTriggers.maxquerydepth == 0)
5544  {
5545  int new_alloc = Max(afterTriggers.query_depth + 1, 8);
5546 
5549  new_alloc * sizeof(AfterTriggersQueryData));
5550  afterTriggers.maxquerydepth = new_alloc;
5551  }
5552  else
5553  {
5554  /* repalloc will keep the stack in the same context */
5555  int old_alloc = afterTriggers.maxquerydepth;
5556  int new_alloc = Max(afterTriggers.query_depth + 1,
5557  old_alloc * 2);
5558 
5561  new_alloc * sizeof(AfterTriggersQueryData));
5562  afterTriggers.maxquerydepth = new_alloc;
5563  }
5564 
5565  /* Initialize new array entries to empty */
5566  while (init_depth < afterTriggers.maxquerydepth)
5567  {
5569 
5570  qs->events.head = NULL;
5571  qs->events.tail = NULL;
5572  qs->events.tailfree = NULL;
5573  qs->fdw_tuplestore = NULL;
5574  qs->tables = NIL;
5575 
5576  ++init_depth;
5577  }
5578 }
5579 
5580 /*
5581  * Create an empty SetConstraintState with room for numalloc trigstates
5582  */
5583 static SetConstraintState
5585 {
5587 
5588  /* Behave sanely with numalloc == 0 */
5589  if (numalloc <= 0)
5590  numalloc = 1;
5591 
5592  /*
5593  * We assume that zeroing will correctly initialize the state values.
5594  */
5597  offsetof(SetConstraintStateData, trigstates) +
5598  numalloc * sizeof(SetConstraintTriggerData));
5599 
5600  state->numalloc = numalloc;
5601 
5602  return state;
5603 }
5604 
5605 /*
5606  * Copy a SetConstraintState
5607  */
5608 static SetConstraintState
5610 {
5612 
5614 
5615  state->all_isset = origstate->all_isset;
5616  state->all_isdeferred = origstate->all_isdeferred;
5617  state->numstates = origstate->numstates;
5618  memcpy(state->trigstates, origstate->trigstates,
5619  origstate->numstates * sizeof(SetConstraintTriggerData));
5620 
5621  return state;
5622 }
5623 
5624 /*
5625  * Add a per-trigger item to a SetConstraintState. Returns possibly-changed
5626  * pointer to the state object (it will change if we have to repalloc).
5627  */
5628 static SetConstraintState
5630  Oid tgoid, bool tgisdeferred)
5631 {
5632  if (state->numstates >= state->numalloc)
5633  {
5634  int newalloc = state->numalloc * 2;
5635 
5636  newalloc = Max(newalloc, 8); /* in case original has size 0 */
5638  repalloc(state,
5639  offsetof(SetConstraintStateData, trigstates) +
5640  newalloc * sizeof(SetConstraintTriggerData));
5641  state->numalloc = newalloc;
5642  Assert(state->numstates < state->numalloc);
5643  }
5644 
5645  state->trigstates[state->numstates].sct_tgoid = tgoid;
5646  state->trigstates[state->numstates].sct_tgisdeferred = tgisdeferred;
5647  state->numstates++;
5648 
5649  return state;
5650 }
5651 
5652 /* ----------
5653  * AfterTriggerSetState()
5654  *
5655  * Execute the SET CONSTRAINTS ... utility command.
5656  * ----------
5657  */
5658 void
5660 {
5661  int my_level = GetCurrentTransactionNestLevel();
5662 
5663  /* If we haven't already done so, initialize our state. */
5664  if (afterTriggers.state == NULL)
5666 
5667  /*
5668  * If in a subtransaction, and we didn't save the current state already,
5669  * save it so it can be restored if the subtransaction aborts.
5670  */
5671  if (my_level > 1 &&
5672  afterTriggers.trans_stack[my_level].state == NULL)
5673  {
5674  afterTriggers.trans_stack[my_level].state =
5676  }
5677 
5678  /*
5679  * Handle SET CONSTRAINTS ALL ...
5680  */
5681  if (stmt->constraints == NIL)
5682  {
5683  /*
5684  * Forget any previous SET CONSTRAINTS commands in this transaction.
5685  */
5687 
5688  /*
5689  * Set the per-transaction ALL state to known.
5690  */
5691  afterTriggers.state->all_isset = true;
5692  afterTriggers.state->all_isdeferred = stmt->deferred;
5693  }
5694  else
5695  {
5696  Relation conrel;
5697  Relation tgrel;
5698  List *conoidlist = NIL;
5699  List *tgoidlist = NIL;
5700  ListCell *lc;
5701 
5702  /*
5703  * Handle SET CONSTRAINTS constraint-name [, ...]
5704  *
5705  * First, identify all the named constraints and make a list of their
5706  * OIDs. Since, unlike the SQL spec, we allow multiple constraints of
5707  * the same name within a schema, the specifications are not
5708  * necessarily unique. Our strategy is to target all matching
5709  * constraints within the first search-path schema that has any
5710  * matches, but disregard matches in schemas beyond the first match.
5711  * (This is a bit odd but it's the historical behavior.)
5712  *
5713  * A constraint in a partitioned table may have corresponding
5714  * constraints in the partitions. Grab those too.
5715  */
5716  conrel = table_open(ConstraintRelationId, AccessShareLock);
5717 
5718  foreach(lc, stmt->constraints)
5719  {
5720  RangeVar *constraint = lfirst(lc);
5721  bool found;
5722  List *namespacelist;
5723  ListCell *nslc;
5724 
5725  if (constraint->catalogname)
5726  {
5727  if (strcmp(constraint->catalogname, get_database_name(MyDatabaseId)) != 0)
5728  ereport(ERROR,
5729  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5730  errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
5731  constraint->catalogname, constraint->schemaname,
5732  constraint->relname)));
5733  }
5734 
5735  /*
5736  * If we're given the schema name with the constraint, look only
5737  * in that schema. If given a bare constraint name, use the
5738  * search path to find the first matching constraint.
5739  */
5740  if (constraint->schemaname)
5741  {
5742  Oid namespaceId = LookupExplicitNamespace(constraint->schemaname,
5743  false);
5744 
5745  namespacelist = list_make1_oid(namespaceId);
5746  }
5747  else
5748  {
5749  namespacelist = fetch_search_path(true);
5750  }
5751 
5752  found = false;
5753  foreach(nslc, namespacelist)
5754  {
5755  Oid namespaceId = lfirst_oid(nslc);
5756  SysScanDesc conscan;
5757  ScanKeyData skey[2];
5758  HeapTuple tup;
5759 
5760  ScanKeyInit(&skey[0],
5761  Anum_pg_constraint_conname,
5762  BTEqualStrategyNumber, F_NAMEEQ,
5763  CStringGetDatum(constraint->relname));
5764  ScanKeyInit(&skey[1],
5765  Anum_pg_constraint_connamespace,
5766  BTEqualStrategyNumber, F_OIDEQ,
5767  ObjectIdGetDatum(namespaceId));
5768 
5769  conscan = systable_beginscan(conrel, ConstraintNameNspIndexId,
5770  true, NULL, 2, skey);
5771 
5772  while (HeapTupleIsValid(tup = systable_getnext(conscan)))
5773  {
5775 
5776  if (con->condeferrable)
5777  conoidlist = lappend_oid(conoidlist, con->oid);
5778  else if (stmt->deferred)
5779  ereport(ERROR,
5780  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
5781  errmsg("constraint \"%s\" is not deferrable",
5782  constraint->relname)));
5783  found = true;
5784  }
5785 
5786  systable_endscan(conscan);
5787 
5788  /*
5789  * Once we've found a matching constraint we do not search
5790  * later parts of the search path.
5791  */
5792  if (found)
5793  break;
5794  }
5795 
5796  list_free(namespacelist);
5797 
5798  /*
5799  * Not found ?
5800  */
5801  if (!found)
5802  ereport(ERROR,
5803  (errcode(ERRCODE_UNDEFINED_OBJECT),
5804  errmsg("constraint \"%s\" does not exist",
5805  constraint->relname)));
5806  }
5807 
5808  /*
5809  * Scan for any possible descendants of the constraints. We append
5810  * whatever we find to the same list that we're scanning; this has the
5811  * effect that we create new scans for those, too, so if there are
5812  * further descendents, we'll also catch them.
5813  */
5814  foreach(lc, conoidlist)
5815  {
5816  Oid parent = lfirst_oid(lc);
5817  ScanKeyData key;
5818  SysScanDesc scan;
5819  HeapTuple tuple;
5820 
5821  ScanKeyInit(&key,
5822  Anum_pg_constraint_conparentid,
5823  BTEqualStrategyNumber, F_OIDEQ,
5824  ObjectIdGetDatum(parent));
5825 
5826  scan = systable_beginscan(conrel, ConstraintParentIndexId, true, NULL, 1, &key);
5827 
5828  while (HeapTupleIsValid(tuple = systable_getnext(scan)))
5829  {
5831 
5832  conoidlist = lappend_oid(conoidlist, con->oid);
5833  }
5834 
5835  systable_endscan(scan);
5836  }
5837 
5838  table_close(conrel, AccessShareLock);
5839 
5840  /*
5841  * Now, locate the trigger(s) implementing each of these constraints,
5842  * and make a list of their OIDs.
5843  */
5844  tgrel = table_open(TriggerRelationId, AccessShareLock);
5845 
5846  foreach(lc, conoidlist)
5847  {
5848  Oid conoid = lfirst_oid(lc);
5849  ScanKeyData skey;
5850  SysScanDesc tgscan;
5851  HeapTuple htup;
5852 
5853  ScanKeyInit(&skey,
5854  Anum_pg_trigger_tgconstraint,
5855  BTEqualStrategyNumber, F_OIDEQ,
5856  ObjectIdGetDatum(conoid));
5857 
5858  tgscan = systable_beginscan(tgrel, TriggerConstraintIndexId, true,
5859  NULL, 1, &skey);
5860 
5861  while (HeapTupleIsValid(htup = systable_getnext(tgscan)))
5862  {
5863  Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
5864 
5865  /*
5866  * Silently skip triggers that are marked as non-deferrable in
5867  * pg_trigger. This is not an error condition, since a
5868  * deferrable RI constraint may have some non-deferrable
5869  * actions.
5870  */
5871  if (pg_trigger->tgdeferrable)
5872  tgoidlist = lappend_oid(tgoidlist, pg_trigger->oid);
5873  }
5874 
5875  systable_endscan(tgscan);
5876  }
5877 
5878  table_close(tgrel, AccessShareLock);
5879 
5880  /*
5881  * Now we can set the trigger states of individual triggers for this
5882  * xact.
5883  */
5884  foreach(lc, tgoidlist)
5885  {
5886  Oid tgoid = lfirst_oid(lc);
5888  bool found = false;
5889  int i;
5890 
5891  for (i = 0; i < state->numstates; i++)
5892  {
5893  if (state->trigstates[i].sct_tgoid == tgoid)
5894  {
5895  state->trigstates[i].sct_tgisdeferred = stmt->deferred;
5896  found = true;
5897  break;
5898  }
5899  }
5900  if (!found)
5901  {
5903  SetConstraintStateAddItem(state, tgoid, stmt->deferred);
5904  }
5905  }
5906  }
5907 
5908  /*
5909  * SQL99 requires that when a constraint is set to IMMEDIATE, any deferred
5910  * checks against that constraint must be made when the SET CONSTRAINTS
5911  * command is executed -- i.e. the effects of the SET CONSTRAINTS command
5912  * apply retroactively. We've updated the constraints state, so scan the
5913  * list of previously deferred events to fire any that have now become
5914  * immediate.
5915  *
5916  * Obviously, if this was SET ... DEFERRED then it can't have converted
5917  * any unfired events to immediate, so we need do nothing in that case.
5918  */
5919  if (!stmt->deferred)
5920  {
5922  bool snapshot_set = false;
5923 
5924  while (afterTriggerMarkEvents(events, NULL, true))
5925  {
5926  CommandId firing_id = afterTriggers.firing_counter++;
5927 
5928  /*
5929  * Make sure a snapshot has been established in case trigger
5930  * functions need one. Note that we avoid setting a snapshot if
5931  * we don't find at least one trigger that has to be fired now.
5932  * This is so that BEGIN; SET CONSTRAINTS ...; SET TRANSACTION
5933  * ISOLATION LEVEL SERIALIZABLE; ... works properly. (If we are
5934  * at the start of a transaction it's not possible for any trigger
5935  * events to be queued yet.)
5936  */
5937  if (!snapshot_set)
5938  {
5940  snapshot_set = true;
5941  }
5942 
5943  /*
5944  * We can delete fired events if we are at top transaction level,
5945  * but we'd better not if inside a subtransaction, since the
5946  * subtransaction could later get rolled back.
5947  */
5948  if (afterTriggerInvokeEvents(events, firing_id, NULL,
5949  !IsSubTransaction()))
5950  break; /* all fired */
5951  }
5952 
5953  if (snapshot_set)
5955  }
5956 }
5957 
5958 /* ----------
5959  * AfterTriggerPendingOnRel()
5960  * Test to see if there are any pending after-trigger events for rel.
5961  *
5962  * This is used by TRUNCATE, CLUSTER, ALTER TABLE, etc to detect whether
5963  * it is unsafe to perform major surgery on a relation. Note that only
5964  * local pending events are examined. We assume that having exclusive lock
5965  * on a rel guarantees there are no unserviced events in other backends ---
5966  * but having a lock does not prevent there being such events in our own.
5967  *
5968  * In some scenarios it'd be reasonable to remove pending events (more
5969  * specifically, mark them DONE by the current subxact) but without a lot
5970  * of knowledge of the trigger semantics we can't do this in general.
5971  * ----------
5972  */
5973 bool
5975 {
5976  AfterTriggerEvent event;
5978  int depth;
5979 
5980  /* Scan queued events */
5982  {
5983  AfterTriggerShared evtshared = GetTriggerSharedData(event);
5984 
5985  /*
5986  * We can ignore completed events. (Even if a DONE flag is rolled
5987  * back by subxact abort, it's OK because the effects of the TRUNCATE
5988  * or whatever must get rolled back too.)
5989  */
5990  if (event->ate_flags & AFTER_TRIGGER_DONE)
5991  continue;
5992 
5993  if (evtshared->ats_relid == relid)
5994  return true;
5995  }
5996 
5997  /*
5998  * Also scan events queued by incomplete queries. This could only matter
5999  * if TRUNCATE/etc is executed by a function or trigger within an updating
6000  * query on the same relation, which is pretty perverse, but let's check.
6001  */
6002  for (depth = 0; depth <= afterTriggers.query_depth && depth < afterTriggers.maxquerydepth; depth++)
6003  {
6005  {
6006  AfterTriggerShared evtshared = GetTriggerSharedData(event);
6007 
6008  if (event->ate_flags & AFTER_TRIGGER_DONE)
6009  continue;
6010 
6011  if (evtshared->ats_relid == relid)
6012  return true;
6013  }
6014  }
6015 
6016  return false;
6017 }
6018 
6019 /* ----------
6020  * AfterTriggerSaveEvent()
6021  *
6022  * Called by ExecA[RS]...Triggers() to queue up the triggers that should
6023  * be fired for an event.
6024  *
6025  * NOTE: this is called whenever there are any triggers associated with
6026  * the event (even if they are disabled). This function decides which
6027  * triggers actually need to be queued. It is also called after each row,
6028  * even if there are no triggers for that event, if there are any AFTER
6029  * STATEMENT triggers for the statement which use transition tables, so that
6030  * the transition tuplestores can be built. Furthermore, if the transition
6031  * capture is happening for UPDATEd rows being moved to another partition due
6032  * to the partition-key being changed, then this function is called once when
6033  * the row is deleted (to capture OLD row), and once when the row is inserted
6034  * into another partition (to capture NEW row). This is done separately because
6035  * DELETE and INSERT happen on different tables.
6036  *
6037  * Transition tuplestores are built now, rather than when events are pulled
6038  * off of the queue because AFTER ROW triggers are allowed to select from the
6039  * transition tables for the statement.
6040  *
6041  * This contains special support to queue the update events for the case where
6042  * a partitioned table undergoing a cross-partition update may have foreign
6043  * keys pointing into it. Normally, a partitioned table's row triggers are
6044  * not fired because the leaf partition(s) which are modified as a result of
6045  * the operation on the partitioned table contain the same triggers which are
6046  * fired instead. But that general scheme can cause problematic behavior with
6047  * foreign key triggers during cross-partition updates, which are implemented
6048  * as DELETE on the source partition followed by INSERT into the destination
6049  * partition. Specifically, firing DELETE triggers would lead to the wrong
6050  * foreign key action to be enforced considering that the original command is
6051  * UPDATE; in this case, this function is called with relinfo as the
6052  * partitioned table, and src_partinfo and dst_partinfo referring to the
6053  * source and target leaf partitions, respectively.
6054  *
6055  * is_crosspart_update is true either when a DELETE event is fired on the
6056  * source partition (which is to be ignored) or an UPDATE event is fired on
6057  * the root partitioned table.
6058  * ----------
6059  */
6060 static void
6062  ResultRelInfo *src_partinfo,
6063  ResultRelInfo *dst_partinfo,
6064  int event, bool row_trigger,
6065  TupleTableSlot *oldslot, TupleTableSlot *newslot,
6066  List *recheckIndexes, Bitmapset *modifiedCols,
6067  TransitionCaptureState *transition_capture,
6068  bool is_crosspart_update)
6069 {
6070  Relation rel = relinfo->ri_RelationDesc;
6071  TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
6072  AfterTriggerEventData new_event;
6073  AfterTriggerSharedData new_shared;
6074  char relkind = rel->rd_rel->relkind;
6075  int tgtype_event;
6076  int tgtype_level;
6077  int i;
6078  Tuplestorestate *fdw_tuplestore = NULL;
6079 
6080  /*
6081  * Check state. We use a normal test not Assert because it is possible to
6082  * reach here in the wrong state given misconfigured RI triggers, in
6083  * particular deferring a cascade action trigger.
6084  */
6085  if (afterTriggers.query_depth < 0)
6086  elog(ERROR, "AfterTriggerSaveEvent() called outside of query");
6087 
6088  /* Be sure we have enough space to record events at this query depth. */
6091 
6092  /*
6093  * If the directly named relation has any triggers with transition tables,
6094  * then we need to capture transition tuples.
6095  */
6096  if (row_trigger && transition_capture != NULL)
6097  {
6098  TupleTableSlot *original_insert_tuple = transition_capture->tcs_original_insert_tuple;
6099 
6100  /*
6101  * Capture the old tuple in the appropriate transition table based on
6102  * the event.
6103  */
6104  if (!TupIsNull(oldslot))
6105  {
6106  Tuplestorestate *old_tuplestore;
6107 
6108  old_tuplestore = GetAfterTriggersTransitionTable(event,
6109  oldslot,
6110  NULL,
6111  transition_capture);
6112  TransitionTableAddTuple(estate, transition_capture, relinfo,
6113  oldslot, NULL, old_tuplestore);
6114  }
6115 
6116  /*
6117  * Capture the new tuple in the appropriate transition table based on
6118  * the event.
6119  */
6120  if (!TupIsNull(newslot))
6121  {
6122  Tuplestorestate *new_tuplestore;
6123 
6124  new_tuplestore = GetAfterTriggersTransitionTable(event,
6125  NULL,
6126  newslot,
6127  transition_capture);
6128  TransitionTableAddTuple(estate, transition_capture, relinfo,
6129  newslot, original_insert_tuple, new_tuplestore);
6130  }
6131 
6132  /*
6133  * If transition tables are the only reason we're here, return. As
6134  * mentioned above, we can also be here during update tuple routing in
6135  * presence of transition tables, in which case this function is
6136  * called separately for OLD and NEW, so we expect exactly one of them
6137  * to be NULL.
6138  */
6139  if (trigdesc == NULL ||
6140  (event == TRIGGER_EVENT_DELETE && !trigdesc->trig_delete_after_row) ||
6141  (event == TRIGGER_EVENT_INSERT && !trigdesc->trig_insert_after_row) ||
6142  (event == TRIGGER_EVENT_UPDATE && !trigdesc->trig_update_after_row) ||
6143  (event == TRIGGER_EVENT_UPDATE && (TupIsNull(oldslot) ^ TupIsNull(newslot))))
6144  return;
6145  }
6146 
6147  /*
6148  * We normally don't see partitioned tables here for row level triggers
6149  * except in the special case of a cross-partition update. In that case,
6150  * nodeModifyTable.c:ExecCrossPartitionUpdateForeignKey() calls here to
6151  * queue an update event on the root target partitioned table, also
6152  * passing the source and destination partitions and their tuples.
6153  */
6154  Assert(!row_trigger ||
6155  rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE ||
6156  (is_crosspart_update &&
6157  TRIGGER_FIRED_BY_UPDATE(event) &&
6158  src_partinfo != NULL && dst_partinfo != NULL));
6159 
6160  /*
6161  * Validate the event code and collect the associated tuple CTIDs.
6162  *
6163  * The event code will be used both as a bitmask and an array offset, so
6164  * validation is important to make sure we don't walk off the edge of our
6165  * arrays.
6166  *
6167  * Also, if we're considering statement-level triggers, check whether we
6168  * already queued a set of them for this event, and cancel the prior set
6169  * if so. This preserves the behavior that statement-level triggers fire
6170  * just once per statement and fire after row-level triggers.
6171  */
6172  switch (event)
6173  {
6174  case TRIGGER_EVENT_INSERT:
6175  tgtype_event = TRIGGER_TYPE_INSERT;
6176  if (row_trigger)
6177  {
6178  Assert(oldslot == NULL);
6179  Assert(newslot != NULL);
6180  ItemPointerCopy(&(newslot->tts_tid), &(new_event.ate_ctid1));
6181  ItemPointerSetInvalid(&(new_event.ate_ctid2));
6182  }
6183  else
6184  {
6185  Assert(oldslot == NULL);
6186  Assert(newslot == NULL);
6187  ItemPointerSetInvalid(&(new_event.ate_ctid1));
6188  ItemPointerSetInvalid(&(new_event.ate_ctid2));
6190  CMD_INSERT, event);
6191  }
6192  break;
6193  case TRIGGER_EVENT_DELETE:
6194  tgtype_event = TRIGGER_TYPE_DELETE;
6195  if (row_trigger)
6196  {
6197  Assert(oldslot != NULL);
6198  Assert(newslot == NULL);
6199  ItemPointerCopy(&(oldslot->tts_tid), &(new_event.ate_ctid1));
6200  ItemPointerSetInvalid(&(new_event.ate_ctid2));
6201  }
6202  else
6203  {
6204  Assert(oldslot == NULL);
6205  Assert(newslot == NULL);
6206  ItemPointerSetInvalid(&(new_event.ate_ctid1));
6207  ItemPointerSetInvalid(&(new_event.ate_ctid2));
6209  CMD_DELETE, event);
6210  }
6211  break;
6212  case TRIGGER_EVENT_UPDATE:
6213  tgtype_event = TRIGGER_TYPE_UPDATE;
6214  if (row_trigger)
6215  {
6216  Assert(oldslot != NULL);
6217  Assert(newslot != NULL);
6218  ItemPointerCopy(&(oldslot->tts_tid), &(new_event.ate_ctid1));
6219  ItemPointerCopy(&(newslot->tts_tid), &(new_event.ate_ctid2));
6220 
6221  /*
6222  * Also remember the OIDs of partitions to fetch these tuples
6223  * out of later in AfterTriggerExecute().
6224  */
6225  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6226  {
6227  Assert(src_partinfo != NULL && dst_partinfo != NULL);
6228  new_event.ate_src_part =
6229  RelationGetRelid(src_partinfo->ri_RelationDesc);
6230  new_event.ate_dst_part =
6231  RelationGetRelid(dst_partinfo->ri_RelationDesc);
6232  }
6233  }
6234  else
6235  {
6236  Assert(oldslot == NULL);
6237  Assert(newslot == NULL);
6238  ItemPointerSetInvalid(&(new_event.ate_ctid1));
6239  ItemPointerSetInvalid(&(new_event.ate_ctid2));
6241  CMD_UPDATE, event);
6242  }
6243  break;
6245  tgtype_event = TRIGGER_TYPE_TRUNCATE;
6246  Assert(oldslot == NULL);
6247  Assert(newslot == NULL);
6248  ItemPointerSetInvalid(&(new_event.ate_ctid1));
6249  ItemPointerSetInvalid(&(new_event.ate_ctid2));
6250  break;
6251  default:
6252  elog(ERROR, "invalid after-trigger event code: %d", event);
6253  tgtype_event = 0; /* keep compiler quiet */
6254  break;
6255  }
6256 
6257  /* Determine flags */
6258  if (!(relkind == RELKIND_FOREIGN_TABLE && row_trigger))
6259  {
6260  if (row_trigger && event == TRIGGER_EVENT_UPDATE)
6261  {
6262  if (relkind == RELKIND_PARTITIONED_TABLE)
6263  new_event.ate_flags = AFTER_TRIGGER_CP_UPDATE;
6264  else
6265  new_event.ate_flags = AFTER_TRIGGER_2CTID;
6266  }
6267  else
6268  new_event.ate_flags = AFTER_TRIGGER_1CTID;
6269  }
6270 
6271  /* else, we'll initialize ate_flags for each trigger */
6272 
6273  tgtype_level = (row_trigger ? TRIGGER_TYPE_ROW : TRIGGER_TYPE_STATEMENT);
6274 
6275  /*
6276  * Must convert/copy the source and destination partition tuples into the
6277  * root partitioned table's format/slot, because the processing in the
6278  * loop below expects both oldslot and newslot tuples to be in that form.
6279  */
6280  if (row_trigger && rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6281  {
6282  TupleTableSlot *rootslot;
6283  TupleConversionMap *map;
6284 
6285  rootslot = ExecGetTriggerOldSlot(estate, relinfo);
6286  map = ExecGetChildToRootMap(src_partinfo);
6287  if (map)
6288  oldslot = execute_attr_map_slot(map->attrMap,
6289  oldslot,
6290  rootslot);
6291  else
6292  oldslot = ExecCopySlot(rootslot, oldslot);
6293 
6294  rootslot = ExecGetTriggerNewSlot(estate, relinfo);
6295  map = ExecGetChildToRootMap(dst_partinfo);
6296  if (map)
6297  newslot = execute_attr_map_slot(map->attrMap,
6298  newslot,
6299  rootslot);
6300  else
6301  newslot = ExecCopySlot(rootslot, newslot);
6302  }
6303 
6304  for (i = 0; i < trigdesc->numtriggers; i++)
6305  {
6306  Trigger *trigger = &trigdesc->triggers[i];
6307 
6308  if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
6309  tgtype_level,
6310  TRIGGER_TYPE_AFTER,
6311  tgtype_event))
6312  continue;
6313  if (!TriggerEnabled(estate, relinfo, trigger, event,
6314  modifiedCols, oldslot, newslot))
6315  continue;
6316 
6317  if (relkind == RELKIND_FOREIGN_TABLE && row_trigger)
6318  {
6319  if (fdw_tuplestore == NULL)
6320  {
6321  fdw_tuplestore = GetCurrentFDWTuplestore();
6322  new_event.ate_flags = AFTER_TRIGGER_FDW_FETCH;
6323  }
6324  else
6325  /* subsequent event for the same tuple */
6326  new_event.ate_flags = AFTER_TRIGGER_FDW_REUSE;
6327  }
6328 
6329  /*
6330  * If the trigger is a foreign key enforcement trigger, there are
6331  * certain cases where we can skip queueing the event because we can
6332  * tell by inspection that the FK constraint will still pass. There
6333  * are also some cases during cross-partition updates of a partitioned
6334  * table where queuing the event can be skipped.
6335  */
6336  if (TRIGGER_FIRED_BY_UPDATE(event) || TRIGGER_FIRED_BY_DELETE(event))
6337  {
6338  switch (RI_FKey_trigger_type(trigger->tgfoid))
6339  {
6340  case RI_TRIGGER_PK:
6341 
6342  /*
6343  * For cross-partitioned updates of partitioned PK table,
6344  * skip the event fired by the component delete on the
6345  * source leaf partition unless the constraint originates
6346  * in the partition itself (!tgisclone), because the
6347  * update event that will be fired on the root
6348  * (partitioned) target table will be used to perform the
6349  * necessary foreign key enforcement action.
6350  */
6351  if (is_crosspart_update &&
6352  TRIGGER_FIRED_BY_DELETE(event) &&
6353  trigger->tgisclone)
6354  continue;
6355 
6356  /* Update or delete on trigger's PK table */
6357  if (!RI_FKey_pk_upd_check_required(trigger, rel,
6358  oldslot, newslot))
6359  {
6360  /* skip queuing this event */
6361  continue;
6362  }
6363  break;
6364 
6365  case RI_TRIGGER_FK:
6366 
6367  /*
6368  * Update on trigger's FK table. We can skip the update
6369  * event fired on a partitioned table during a
6370  * cross-partition of that table, because the insert event
6371  * that is fired on the destination leaf partition would
6372  * suffice to perform the necessary foreign key check.
6373  * Moreover, RI_FKey_fk_upd_check_required() expects to be
6374  * passed a tuple that contains system attributes, most of
6375  * which are not present in the virtual slot belonging to
6376  * a partitioned table.
6377  */
6378  if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE ||
6379  !RI_FKey_fk_upd_check_required(trigger, rel,
6380  oldslot, newslot))
6381  {
6382  /* skip queuing this event */
6383  continue;
6384  }
6385  break;
6386 
6387  case RI_TRIGGER_NONE:
6388 
6389  /*
6390  * Not an FK trigger. No need to queue the update event
6391  * fired during a cross-partitioned update of a
6392  * partitioned table, because the same row trigger must be
6393  * present in the leaf partition(s) that are affected as
6394  * part of this update and the events fired on them are
6395  * queued instead.
6396  */
6397  if (row_trigger &&
6398  rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6399  continue;
6400  break;
6401  }
6402  }
6403 
6404  /*
6405  * If the trigger is a deferred unique constraint check trigger, only
6406  * queue it if the unique constraint was potentially violated, which
6407  * we know from index insertion time.
6408  */
6409  if (trigger->tgfoid == F_UNIQUE_KEY_RECHECK)
6410  {
6411  if (!list_member_oid(recheckIndexes, trigger->tgconstrindid))
6412  continue; /* Uniqueness definitely not violated */
6413  }
6414 
6415  /*
6416  * Fill in event structure and add it to the current query's queue.
6417  * Note we set ats_table to NULL whenever this trigger doesn't use
6418  * transition tables, to improve sharability of the shared event data.
6419  */
6420  new_shared.ats_event =
6421  (event & TRIGGER_EVENT_OPMASK) |
6422  (row_trigger ? TRIGGER_EVENT_ROW : 0) |
6423  (trigger->tgdeferrable ? AFTER_TRIGGER_DEFERRABLE : 0) |
6424  (trigger->tginitdeferred ? AFTER_TRIGGER_INITDEFERRED : 0);
6425  new_shared.ats_tgoid = trigger->tgoid;
6426  new_shared.ats_relid = RelationGetRelid(rel);
6427  new_shared.ats_firing_id = 0;
6428  if ((trigger->tgoldtable || trigger->tgnewtable) &&
6429  transition_capture != NULL)
6430  new_shared.ats_table = transition_capture->tcs_private;
6431  else
6432  new_shared.ats_table = NULL;
6433  new_shared.ats_modifiedcols = afterTriggerCopyBitmap(modifiedCols);
6434 
6436  &new_event, &new_shared);
6437  }
6438 
6439  /*
6440  * Finally, spool any foreign tuple(s). The tuplestore squashes them to
6441  * minimal tuples, so this loses any system columns. The executor lost
6442  * those columns before us, for an unrelated reason, so this is fine.
6443  */
6444  if (fdw_tuplestore)
6445  {
6446  if (oldslot != NULL)
6447  tuplestore_puttupleslot(fdw_tuplestore, oldslot);
6448  if (newslot != NULL)
6449  tuplestore_puttupleslot(fdw_tuplestore, newslot);
6450  }
6451 }
6452 
6453 /*
6454  * Detect whether we already queued BEFORE STATEMENT triggers for the given
6455  * relation + operation, and set the flag so the next call will report "true".
6456  */
6457 static bool
6459 {
6460  bool result;
6461  AfterTriggersTableData *table;
6462 
6463  /* Check state, like AfterTriggerSaveEvent. */
6464  if (afterTriggers.query_depth < 0)
6465  elog(ERROR, "before_stmt_triggers_fired() called outside of query");
6466 
6467  /* Be sure we have enough space to record events at this query depth. */
6470 
6471  /*
6472  * We keep this state in the AfterTriggersTableData that also holds
6473  * transition tables for the relation + operation. In this way, if we are
6474  * forced to make a new set of transition tables because more tuples get
6475  * entered after we've already fired triggers, we will allow a new set of
6476  * statement triggers to get queued.
6477  */
6478  table = GetAfterTriggersTableData(relid, cmdType);
6479  result = table->before_trig_done;
6480  table->before_trig_done = true;
6481  return result;
6482 }
6483 
6484 /*
6485  * If we previously queued a set of AFTER STATEMENT triggers for the given
6486  * relation + operation, and they've not been fired yet, cancel them. The
6487  * caller will queue a fresh set that's after any row-level triggers that may
6488  * have been queued by the current sub-statement, preserving (as much as
6489  * possible) the property that AFTER ROW triggers fire before AFTER STATEMENT
6490  * triggers, and that the latter only fire once. This deals with the
6491  * situation where several FK enforcement triggers sequentially queue triggers
6492  * for the same table into the same trigger query level. We can't fully
6493  * prevent odd behavior though: if there are AFTER ROW triggers taking
6494  * transition tables, we don't want to change the transition tables once the
6495  * first such trigger has seen them. In such a case, any additional events
6496  * will result in creating new transition tables and allowing new firings of
6497  * statement triggers.
6498  *
6499  * This also saves the current event list location so that a later invocation
6500  * of this function can cheaply find the triggers we're about to queue and
6501  * cancel them.
6502  */
6503 static void
6504 cancel_prior_stmt_triggers(Oid relid, CmdType cmdType, int tgevent)
6505 {
6506  AfterTriggersTableData *table;
6508 
6509  /*
6510  * We keep this state in the AfterTriggersTableData that also holds
6511  * transition tables for the relation + operation. In this way, if we are
6512  * forced to make a new set of transition tables because more tuples get
6513  * entered after we've already fired triggers, we will allow a new set of
6514  * statement triggers to get queued without canceling the old ones.
6515  */
6516  table = GetAfterTriggersTableData(relid, cmdType);
6517 
6518  if (table->after_trig_done)
6519  {
6520  /*
6521  * We want to start scanning from the tail location that existed just
6522  * before we inserted any statement triggers. But the events list
6523  * might've been entirely empty then, in which case scan from the
6524  * current head.
6525  */
6526  AfterTriggerEvent event;
6528 
6529  if (table->after_trig_events.tail)
6530  {
6531  chunk = table->after_trig_events.tail;
6532  event = (AfterTriggerEvent) table->after_trig_events.tailfree;
6533  }
6534  else
6535  {
6536  chunk = qs->events.head;
6537  event = NULL;
6538  }
6539 
6541  {
6542  if (event == NULL)
6544  for_each_event_from(event, chunk)
6545  {
6546  AfterTriggerShared evtshared = GetTriggerSharedData(event);
6547 
6548  /*
6549  * Exit loop when we reach events that aren't AS triggers for
6550  * the target relation.
6551  */
6552  if (evtshared->ats_relid != relid)
6553  goto done;
6554  if ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) != tgevent)
6555  goto done;
6556  if (!TRIGGER_FIRED_FOR_STATEMENT(evtshared->ats_event))
6557  goto done;
6558  if (!TRIGGER_FIRED_AFTER(evtshared->ats_event))
6559  goto done;
6560  /* OK, mark it DONE */
6561  event->ate_flags &= ~AFTER_TRIGGER_IN_PROGRESS;
6562  event->ate_flags |= AFTER_TRIGGER_DONE;
6563  }
6564  /* signal we must reinitialize event ptr for next chunk */
6565  event = NULL;
6566  }
6567  }
6568 done:
6569 
6570  /* In any case, save current insertion point for next time */
6571  table->after_trig_done = true;
6572  table->after_trig_events = qs->events;
6573 }
6574 
6575 /*
6576  * GUC assign_hook for session_replication_role
6577  */
6578 void
6580 {
6581  /*
6582  * Must flush the plan cache when changing replication role; but don't
6583  * flush unnecessarily.
6584  */
6586  ResetPlanCache();
6587 }
6588 
6589 /*
6590  * SQL function pg_trigger_depth()
6591  */
6592 Datum
6594 {
6596 }
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:2688
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3876
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4130
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4079
#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:152
#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:391
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
Definition: catalog.c:85
char * get_database_name(Oid dbid)
Definition: dbcommands.c:3153
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1551
@ 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:1205
int errhint(const char *fmt,...)
Definition: elog.c:1319
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#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:127
int work_mem
Definition: globals.c:128
Oid MyDatabaseId
Definition: globals.c:91
#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:1695
void pfree(void *pointer)
Definition: mcxt.c:1520
void * palloc0(Size size)
Definition: mcxt.c:1346
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1214
MemoryContext CurTransactionContext
Definition: mcxt.c:155
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1540
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1180
MemoryContext CacheMemoryContext
Definition: mcxt.c:152
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
void * palloc(Size size)
Definition: mcxt.c:1316
#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:4795
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:2143
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:2282
#define ACL_EXECUTE
Definition: parsenodes.h:83
#define ACL_TRIGGER
Definition: parsenodes.h:82
PartitionDesc RelationGetPartitionDesc(Relation rel, bool omit_detached)
Definition: partdesc.c:70
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 conPeriod, bool is_internal)
Definition: pg_constraint.c:51
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:44
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:350
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:300
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:1310
bool RI_FKey_fk_upd_check_required(Trigger *trigger, Relation fk_rel, TupleTableSlot *oldslot, TupleTableSlot *newslot)
Definition: ri_triggers.c:1342
int RI_FKey_trigger_type(Oid tgfoid)
Definition: ri_triggers.c:3123
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:3027
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:1590
#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:1298
static SetConstraintState SetConstraintStateCopy(SetConstraintState origstate)
Definition: trigger.c:5609
struct AfterTriggerSharedData AfterTriggerSharedData
static void cancel_prior_stmt_triggers(Oid relid, CmdType cmdType, int tgevent)
Definition: trigger.c:6504
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:5629
#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:4986
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:4796
#define CHUNK_DATA_START(cptr)
Definition: trigger.c:3707
static void RangeVarCallbackForRenameTrigger(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition: trigger.c:1416
bool ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition: trigger.c:2458
void AfterTriggerEndSubXact(bool isCommit)
Definition: trigger.c:5349
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:6593
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:5129
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:4541
static Tuplestorestate * GetAfterTriggersTransitionTable(int event, TupleTableSlot *oldslot, TupleTableSlot *newslot, TransitionCaptureState *transition_capture)
Definition: trigger.c:5446
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:4625
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:5659
Oid get_trigger_oid(Oid relid, const char *trigname, bool missing_ok)
Definition: trigger.c:1366
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:6458
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:5584
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:1463
void AfterTriggerFireDeferred(void)
Definition: trigger.c:5197
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:1216
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:5497
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:4882
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:6579
bool ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple, TupleTableSlot *newslot)
Definition: trigger.c:3156
void AfterTriggerEndXact(bool isCommit)
Definition: trigger.c:5253
struct AfterTriggerEventDataOneCtid AfterTriggerEventDataOneCtid
bool AfterTriggerPendingOnRel(Oid relid)
Definition: trigger.c:5974
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:5301
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:6061
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:4833
#define AFTER_TRIGGER_CP_UPDATE
Definition: trigger.c:3627
void AfterTriggerEndQuery(EState *estate)
Definition: trigger.c:5038
void RemoveTriggerById(Oid trigOid)
Definition: trigger.c:1287
#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:5537
#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:5018
#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:1078
void tuplestore_puttupleslot(Tuplestorestate *state, TupleTableSlot *slot)
Definition: tuplestore.c:708
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
void tuplestore_end(Tuplestorestate *state)
Definition: tuplestore.c:453
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:926
void CommandCounterIncrement(void)
Definition: xact.c:1097
bool IsSubTransaction(void)
Definition: xact.c:4988
#define IsolationUsesXactSnapshot()
Definition: xact.h:51