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