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