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