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