PostgreSQL Source Code git master
Loading...
Searching...
No Matches
trigger.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * trigger.c
4 * PostgreSQL TRIGGERs support code.
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 * IDENTIFICATION
10 * src/backend/commands/trigger.c
11 *
12 *-------------------------------------------------------------------------
13 */
14#include "postgres.h"
15
16#include "access/genam.h"
17#include "access/htup_details.h"
18#include "access/relation.h"
19#include "access/sysattr.h"
20#include "access/table.h"
21#include "access/tableam.h"
22#include "access/tupconvert.h"
23#include "access/xact.h"
24#include "catalog/catalog.h"
25#include "catalog/dependency.h"
26#include "catalog/indexing.h"
28#include "catalog/partition.h"
30#include "catalog/pg_inherits.h"
31#include "catalog/pg_proc.h"
32#include "catalog/pg_trigger.h"
33#include "catalog/pg_type.h"
34#include "commands/trigger.h"
35#include "executor/executor.h"
36#include "executor/instrument.h"
37#include "miscadmin.h"
38#include "nodes/bitmapset.h"
39#include "nodes/makefuncs.h"
40#include "optimizer/optimizer.h"
41#include "parser/parse_clause.h"
43#include "parser/parse_func.h"
46#include "pgstat.h"
49#include "storage/lmgr.h"
50#include "utils/acl.h"
51#include "utils/builtins.h"
52#include "utils/fmgroids.h"
53#include "utils/guc_hooks.h"
54#include "utils/inval.h"
55#include "utils/lsyscache.h"
56#include "utils/memutils.h"
57#include "utils/plancache.h"
58#include "utils/rel.h"
59#include "utils/snapmgr.h"
60#include "utils/syscache.h"
61#include "utils/tuplestore.h"
62
63
64/* GUC variables */
66
67/* How many levels deep into trigger execution are we? */
68static int MyTriggerDepth = 0;
69
70/* Local function prototypes */
72 HeapTuple trigtup, const char *newname,
73 const char *expected_name);
75 Oid parentTriggerOid, const char *newname,
76 const char *expected_name);
77static void SetTriggerFlags(TriggerDesc *trigdesc, Trigger *trigger);
78static bool GetTupleForTrigger(EState *estate,
79 EPQState *epqstate,
81 ItemPointer tid,
82 LockTupleMode lockmode,
84 bool do_epq_recheck,
88static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
93 int tgindx,
94 FmgrInfo *finfo,
100 int event, bool row_trigger,
103 TransitionCaptureState *transition_capture,
105static void AfterTriggerEnlargeQueryState(void);
106static bool before_stmt_triggers_fired(Oid relid, CmdType cmdType);
108
109
110/*
111 * Create a trigger. Returns the address of the created trigger.
112 *
113 * queryString is the source text of the CREATE TRIGGER command.
114 * This must be supplied if a whenClause is specified, else it can be NULL.
115 *
116 * relOid, if nonzero, is the relation on which the trigger should be
117 * created. If zero, the name provided in the statement will be looked up.
118 *
119 * refRelOid, if nonzero, is the relation to which the constraint trigger
120 * refers. If zero, the constraint relation name provided in the statement
121 * will be looked up as needed.
122 *
123 * constraintOid, if nonzero, says that this trigger is being created
124 * internally to implement that constraint. A suitable pg_depend entry will
125 * be made to link the trigger to that constraint. constraintOid is zero when
126 * executing a user-entered CREATE TRIGGER command. (For CREATE CONSTRAINT
127 * TRIGGER, we build a pg_constraint entry internally.)
128 *
129 * indexOid, if nonzero, is the OID of an index associated with the constraint.
130 * We do nothing with this except store it into pg_trigger.tgconstrindid;
131 * but when creating a trigger for a deferrable unique constraint on a
132 * partitioned table, its children are looked up. Note we don't cope with
133 * invalid indexes in that case.
134 *
135 * funcoid, if nonzero, is the OID of the function to invoke. When this is
136 * given, stmt->funcname is ignored.
137 *
138 * parentTriggerOid, if nonzero, is a trigger that begets this one; so that
139 * if that trigger is dropped, this one should be too. There are two cases
140 * when a nonzero value is passed for this: 1) when this function recurses to
141 * create the trigger on partitions, 2) when creating child foreign key
142 * triggers; see CreateFKCheckTrigger() and createForeignKeyActionTriggers().
143 *
144 * If whenClause is passed, it is an already-transformed expression for
145 * WHEN. In this case, we ignore any that may come in stmt->whenClause.
146 *
147 * If isInternal is true then this is an internally-generated trigger.
148 * This argument sets the tgisinternal field of the pg_trigger entry, and
149 * if true causes us to modify the given trigger name to ensure uniqueness.
150 *
151 * When isInternal is not true we require ACL_TRIGGER permissions on the
152 * relation, as well as ACL_EXECUTE on the trigger function. For internal
153 * triggers the caller must apply any required permission checks.
154 *
155 * When called on partitioned tables, this function recurses to create the
156 * trigger on all the partitions, except if isInternal is true, in which
157 * case caller is expected to execute recursion on its own. in_partition
158 * indicates such a recursive call; outside callers should pass "false"
159 * (but see CloneRowTriggersToPartition).
160 */
162CreateTrigger(const CreateTrigStmt *stmt, const char *queryString,
163 Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid,
164 Oid funcoid, Oid parentTriggerOid, Node *whenClause,
165 bool isInternal, bool in_partition)
166{
167 return
168 CreateTriggerFiringOn(stmt, queryString, relOid, refRelOid,
169 constraintOid, indexOid, funcoid,
170 parentTriggerOid, whenClause, isInternal,
172}
173
174/*
175 * Like the above; additionally the firing condition
176 * (always/origin/replica/disabled) can be specified.
177 */
179CreateTriggerFiringOn(const CreateTrigStmt *stmt, const char *queryString,
182 Node *whenClause, bool isInternal, bool in_partition,
184{
185 int16 tgtype;
186 int ncolumns;
187 int16 *columns;
188 int2vector *tgattr;
190 char *qual;
192 bool nulls[Natts_pg_trigger];
193 Relation rel;
197 HeapTuple tuple = NULL;
201 char *trigname;
205 char *oldtablename = NULL;
206 char *newtablename = NULL;
208 bool trigger_exists = false;
210 bool existing_isInternal = false;
211 bool existing_isClone = false;
212
213 if (OidIsValid(relOid))
214 rel = table_open(relOid, ShareRowExclusiveLock);
215 else
216 rel = table_openrv(stmt->relation, ShareRowExclusiveLock);
217
218 /*
219 * Triggers must be on tables or views, and there are additional
220 * relation-type-specific restrictions.
221 */
222 if (rel->rd_rel->relkind == RELKIND_RELATION)
223 {
224 /* Tables can't have INSTEAD OF triggers */
225 if (stmt->timing != TRIGGER_TYPE_BEFORE &&
226 stmt->timing != TRIGGER_TYPE_AFTER)
229 errmsg("\"%s\" is a table",
231 errdetail("Tables cannot have INSTEAD OF triggers.")));
232 }
233 else if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
234 {
235 /* Partitioned tables can't have INSTEAD OF triggers */
236 if (stmt->timing != TRIGGER_TYPE_BEFORE &&
237 stmt->timing != TRIGGER_TYPE_AFTER)
240 errmsg("\"%s\" is a table",
242 errdetail("Tables cannot have INSTEAD OF triggers.")));
243
244 /*
245 * FOR EACH ROW triggers have further restrictions
246 */
247 if (stmt->row)
248 {
249 /*
250 * Disallow use of transition tables.
251 *
252 * Note that we have another restriction about transition tables
253 * in partitions; search for 'has_superclass' below for an
254 * explanation. The check here is just to protect from the fact
255 * that if we allowed it here, the creation would succeed for a
256 * partitioned table with no partitions, but would be blocked by
257 * the other restriction when the first partition was created,
258 * which is very unfriendly behavior.
259 */
260 if (stmt->transitionRels != NIL)
263 errmsg("\"%s\" is a partitioned table",
265 errdetail("ROW triggers with transition tables are not supported on partitioned tables.")));
266 }
267 }
268 else if (rel->rd_rel->relkind == RELKIND_VIEW)
269 {
270 /*
271 * Views can have INSTEAD OF triggers (which we check below are
272 * row-level), or statement-level BEFORE/AFTER triggers.
273 */
274 if (stmt->timing != TRIGGER_TYPE_INSTEAD && stmt->row)
277 errmsg("\"%s\" is a view",
279 errdetail("Views cannot have row-level BEFORE or AFTER triggers.")));
280 /* Disallow TRUNCATE triggers on VIEWs */
281 if (TRIGGER_FOR_TRUNCATE(stmt->events))
284 errmsg("\"%s\" is a view",
286 errdetail("Views cannot have TRUNCATE triggers.")));
287 }
288 else if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
289 {
290 if (stmt->timing != TRIGGER_TYPE_BEFORE &&
291 stmt->timing != TRIGGER_TYPE_AFTER)
294 errmsg("\"%s\" is a foreign table",
296 errdetail("Foreign tables cannot have INSTEAD OF triggers.")));
297
298 /*
299 * We disallow constraint triggers to protect the assumption that
300 * triggers on FKs can't be deferred. See notes with AfterTriggers
301 * data structures, below.
302 */
303 if (stmt->isconstraint)
306 errmsg("\"%s\" is a foreign table",
308 errdetail("Foreign tables cannot have constraint triggers.")));
309 }
310 else
313 errmsg("relation \"%s\" cannot have triggers",
316
317 /*
318 * Conflict log tables are used internally for logical replication
319 * conflict logging and should not have triggers, as it could disrupt
320 * conflict logging.
321 */
325 errmsg("cannot create trigger on conflict log table \"%s\"",
327 errdetail("Conflict log tables are system-managed tables for logical replication conflicts.")));
328
332 errmsg("permission denied: \"%s\" is a system catalog",
334
335 if (stmt->isconstraint)
336 {
337 /*
338 * We must take a lock on the target relation to protect against
339 * concurrent drop. It's not clear that AccessShareLock is strong
340 * enough, but we certainly need at least that much... otherwise, we
341 * might end up creating a pg_constraint entry referencing a
342 * nonexistent table.
343 */
345 {
348 }
349 else if (stmt->constrrel != NULL)
351 false);
352 }
353
354 /* permission checks */
355 if (!isInternal)
356 {
359 if (aclresult != ACLCHECK_OK)
362
364 {
367 if (aclresult != ACLCHECK_OK)
370 }
371 }
372
373 /*
374 * When called on a partitioned table to create a FOR EACH ROW trigger
375 * that's not internal, we create one trigger for each partition, too.
376 *
377 * For that, we'd better hold lock on all of them ahead of time.
378 */
379 partition_recurse = !isInternal && stmt->row &&
380 rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE;
384
385 /* Compute tgtype */
386 TRIGGER_CLEAR_TYPE(tgtype);
387 if (stmt->row)
388 TRIGGER_SETT_ROW(tgtype);
389 tgtype |= stmt->timing;
390 tgtype |= stmt->events;
391
392 /* Disallow ROW-level TRUNCATE triggers */
393 if (TRIGGER_FOR_ROW(tgtype) && TRIGGER_FOR_TRUNCATE(tgtype))
396 errmsg("TRUNCATE FOR EACH ROW triggers are not supported")));
397
398 /* INSTEAD triggers must be row-level, and can't have WHEN or columns */
399 if (TRIGGER_FOR_INSTEAD(tgtype))
400 {
401 if (!TRIGGER_FOR_ROW(tgtype))
404 errmsg("INSTEAD OF triggers must be FOR EACH ROW")));
405 if (stmt->whenClause)
408 errmsg("INSTEAD OF triggers cannot have WHEN conditions")));
409 if (stmt->columns != NIL)
412 errmsg("INSTEAD OF triggers cannot have column lists")));
413 }
414
415 /*
416 * We don't yet support naming ROW transition variables, but the parser
417 * recognizes the syntax so we can give a nicer message here.
418 *
419 * Per standard, REFERENCING TABLE names are only allowed on AFTER
420 * triggers. Per standard, REFERENCING ROW names are not allowed with FOR
421 * EACH STATEMENT. Per standard, each OLD/NEW, ROW/TABLE permutation is
422 * only allowed once. Per standard, OLD may not be specified when
423 * creating a trigger only for INSERT, and NEW may not be specified when
424 * creating a trigger only for DELETE.
425 *
426 * Notice that the standard allows an AFTER ... FOR EACH ROW trigger to
427 * reference both ROW and TABLE transition data.
428 */
429 if (stmt->transitionRels != NIL)
430 {
431 List *varList = stmt->transitionRels;
432 ListCell *lc;
433
434 foreach(lc, varList)
435 {
437
438 if (!(tt->isTable))
441 errmsg("ROW variable naming in the REFERENCING clause is not supported"),
442 errhint("Use OLD TABLE or NEW TABLE for naming transition tables.")));
443
444 /*
445 * Because of the above test, we omit further ROW-related testing
446 * below. If we later allow naming OLD and NEW ROW variables,
447 * adjustments will be needed below.
448 */
449
450 if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
453 errmsg("\"%s\" is a foreign table",
455 errdetail("Triggers on foreign tables cannot have transition tables.")));
456
457 if (rel->rd_rel->relkind == RELKIND_VIEW)
460 errmsg("\"%s\" is a view",
462 errdetail("Triggers on views cannot have transition tables.")));
463
464 /*
465 * We currently don't allow row-level triggers with transition
466 * tables on partition or inheritance children. Such triggers
467 * would somehow need to see tuples converted to the format of the
468 * table they're attached to, and it's not clear which subset of
469 * tuples each child should see. See also the prohibitions in
470 * ATExecAttachPartition() and ATExecAddInherit().
471 */
472 if (TRIGGER_FOR_ROW(tgtype) && has_superclass(rel->rd_id))
473 {
474 /* Use appropriate error message. */
475 if (rel->rd_rel->relispartition)
478 errmsg("ROW triggers with transition tables are not supported on partitions")));
479 else
482 errmsg("ROW triggers with transition tables are not supported on inheritance children")));
483 }
484
485 if (stmt->timing != TRIGGER_TYPE_AFTER)
488 errmsg("transition table name can only be specified for an AFTER trigger")));
489
490 if (TRIGGER_FOR_TRUNCATE(tgtype))
493 errmsg("TRUNCATE triggers with transition tables are not supported")));
494
495 /*
496 * We currently don't allow multi-event triggers ("INSERT OR
497 * UPDATE") with transition tables, because it's not clear how to
498 * handle INSERT ... ON CONFLICT statements which can fire both
499 * INSERT and UPDATE triggers. We show the inserted tuples to
500 * INSERT triggers and the updated tuples to UPDATE triggers, but
501 * it's not yet clear what INSERT OR UPDATE trigger should see.
502 * This restriction could be lifted if we can decide on the right
503 * semantics in a later release.
504 */
505 if (((TRIGGER_FOR_INSERT(tgtype) ? 1 : 0) +
506 (TRIGGER_FOR_UPDATE(tgtype) ? 1 : 0) +
507 (TRIGGER_FOR_DELETE(tgtype) ? 1 : 0)) != 1)
510 errmsg("transition tables cannot be specified for triggers with more than one event")));
511
512 /*
513 * We currently don't allow column-specific triggers with
514 * transition tables. Per spec, that seems to require
515 * accumulating separate transition tables for each combination of
516 * columns, which is a lot of work for a rather marginal feature.
517 */
518 if (stmt->columns != NIL)
521 errmsg("transition tables cannot be specified for triggers with column lists")));
522
523 /*
524 * We disallow constraint triggers with transition tables, to
525 * protect the assumption that such triggers can't be deferred.
526 * See notes with AfterTriggers data structures, below.
527 *
528 * Currently this is enforced by the grammar, so just Assert here.
529 */
530 Assert(!stmt->isconstraint);
531
532 if (tt->isNew)
533 {
534 if (!(TRIGGER_FOR_INSERT(tgtype) ||
535 TRIGGER_FOR_UPDATE(tgtype)))
538 errmsg("NEW TABLE can only be specified for an INSERT or UPDATE trigger")));
539
540 if (newtablename != NULL)
543 errmsg("NEW TABLE cannot be specified multiple times")));
544
545 newtablename = tt->name;
546 }
547 else
548 {
549 if (!(TRIGGER_FOR_DELETE(tgtype) ||
550 TRIGGER_FOR_UPDATE(tgtype)))
553 errmsg("OLD TABLE can only be specified for a DELETE or UPDATE trigger")));
554
555 if (oldtablename != NULL)
558 errmsg("OLD TABLE cannot be specified multiple times")));
559
560 oldtablename = tt->name;
561 }
562 }
563
564 if (newtablename != NULL && oldtablename != NULL &&
568 errmsg("OLD TABLE name and NEW TABLE name cannot be the same")));
569 }
570
571 /*
572 * Parse the WHEN clause, if any and we weren't passed an already
573 * transformed one.
574 *
575 * Note that as a side effect, we fill whenRtable when parsing. If we got
576 * an already parsed clause, this does not occur, which is what we want --
577 * no point in adding redundant dependencies below.
578 */
579 if (!whenClause && stmt->whenClause)
580 {
581 ParseState *pstate;
583 List *varList;
584 ListCell *lc;
585
586 /* Set up a pstate to parse with */
587 pstate = make_parsestate(NULL);
588 pstate->p_sourcetext = queryString;
589
590 /*
591 * Set up nsitems for OLD and NEW references.
592 *
593 * 'OLD' must always have varno equal to 1 and 'NEW' equal to 2.
594 */
597 makeAlias("old", NIL),
598 false, false);
599 addNSItemToQuery(pstate, nsitem, false, true, true);
602 makeAlias("new", NIL),
603 false, false);
604 addNSItemToQuery(pstate, nsitem, false, true, true);
605
606 /* Transform expression. Copy to be sure we don't modify original */
607 whenClause = transformWhereClause(pstate,
608 copyObject(stmt->whenClause),
610 "WHEN");
611 /* we have to fix its collations too */
612 assign_expr_collations(pstate, whenClause);
613
614 /*
615 * Check for disallowed references to OLD/NEW.
616 *
617 * NB: pull_var_clause is okay here only because we don't allow
618 * subselects in WHEN clauses; it would fail to examine the contents
619 * of subselects.
620 */
621 varList = pull_var_clause(whenClause, 0);
622 foreach(lc, varList)
623 {
624 Var *var = (Var *) lfirst(lc);
625
626 switch (var->varno)
627 {
628 case PRS2_OLD_VARNO:
629 if (!TRIGGER_FOR_ROW(tgtype))
632 errmsg("statement trigger's WHEN condition cannot reference column values"),
633 parser_errposition(pstate, var->location)));
634 if (TRIGGER_FOR_INSERT(tgtype))
637 errmsg("INSERT trigger's WHEN condition cannot reference OLD values"),
638 parser_errposition(pstate, var->location)));
639 /* system columns are okay here */
640 break;
641 case PRS2_NEW_VARNO:
642 if (!TRIGGER_FOR_ROW(tgtype))
645 errmsg("statement trigger's WHEN condition cannot reference column values"),
646 parser_errposition(pstate, var->location)));
647 if (TRIGGER_FOR_DELETE(tgtype))
650 errmsg("DELETE trigger's WHEN condition cannot reference NEW values"),
651 parser_errposition(pstate, var->location)));
652 if (var->varattno < 0 && TRIGGER_FOR_BEFORE(tgtype))
655 errmsg("BEFORE trigger's WHEN condition cannot reference NEW system columns"),
656 parser_errposition(pstate, var->location)));
657 if (TRIGGER_FOR_BEFORE(tgtype) &&
658 var->varattno == 0 &&
659 RelationGetDescr(rel)->constr &&
660 (RelationGetDescr(rel)->constr->has_generated_stored ||
661 RelationGetDescr(rel)->constr->has_generated_virtual))
664 errmsg("BEFORE trigger's WHEN condition cannot reference NEW generated columns"),
665 errdetail("A whole-row reference is used and the table contains generated columns."),
666 parser_errposition(pstate, var->location)));
667 if (TRIGGER_FOR_BEFORE(tgtype) &&
668 var->varattno > 0 &&
669 TupleDescAttr(RelationGetDescr(rel), var->varattno - 1)->attgenerated)
672 errmsg("BEFORE trigger's WHEN condition cannot reference NEW generated columns"),
673 errdetail("Column \"%s\" is a generated column.",
674 NameStr(TupleDescAttr(RelationGetDescr(rel), var->varattno - 1)->attname)),
675 parser_errposition(pstate, var->location)));
676 break;
677 default:
678 /* can't happen without add_missing_from, so just elog */
679 elog(ERROR, "trigger WHEN condition cannot contain references to other relations");
680 break;
681 }
682 }
683
684 /* we'll need the rtable for recordDependencyOnExpr */
685 whenRtable = pstate->p_rtable;
686
687 qual = nodeToString(whenClause);
688
689 free_parsestate(pstate);
690 }
691 else if (!whenClause)
692 {
693 whenClause = NULL;
694 whenRtable = NIL;
695 qual = NULL;
696 }
697 else
698 {
699 qual = nodeToString(whenClause);
700 whenRtable = NIL;
701 }
702
703 /*
704 * Find and validate the trigger function.
705 */
706 if (!OidIsValid(funcoid))
707 funcoid = LookupFuncName(stmt->funcname, 0, NULL, false);
708 if (!isInternal)
709 {
711 if (aclresult != ACLCHECK_OK)
713 NameListToString(stmt->funcname));
714 }
716 if (funcrettype != TRIGGEROID)
719 errmsg("function %s must return type %s",
720 NameListToString(stmt->funcname), "trigger")));
721
722 /*
723 * Scan pg_trigger to see if there is already a trigger of the same name.
724 * Skip this for internally generated triggers, since we'll modify the
725 * name to be unique below.
726 *
727 * NOTE that this is cool only because we have ShareRowExclusiveLock on
728 * the relation, so the trigger set won't be changing underneath us.
729 */
731 if (!isInternal)
732 {
735
736 ScanKeyInit(&skeys[0],
740
741 ScanKeyInit(&skeys[1],
744 CStringGetDatum(stmt->trigname));
745
747 NULL, 2, skeys);
748
749 /* There should be at most one matching tuple */
751 {
753
754 trigoid = oldtrigger->oid;
755 existing_constraint_oid = oldtrigger->tgconstraint;
756 existing_isInternal = oldtrigger->tgisinternal;
758 trigger_exists = true;
759 /* copy the tuple to use in CatalogTupleUpdate() */
760 tuple = heap_copytuple(tuple);
761 }
763 }
764
765 if (!trigger_exists)
766 {
767 /* Generate the OID for the new trigger. */
770 }
771 else
772 {
773 /*
774 * If OR REPLACE was specified, we'll replace the old trigger;
775 * otherwise complain about the duplicate name.
776 */
777 if (!stmt->replace)
780 errmsg("trigger \"%s\" for relation \"%s\" already exists",
781 stmt->trigname, RelationGetRelationName(rel))));
782
783 /*
784 * An internal trigger or a child trigger (isClone) cannot be replaced
785 * by a user-defined trigger. However, skip this test when
786 * in_partition, because then we're recursing from a partitioned table
787 * and the check was made at the parent level.
788 */
793 errmsg("trigger \"%s\" for relation \"%s\" is an internal or a child trigger",
794 stmt->trigname, RelationGetRelationName(rel))));
795
796 /*
797 * It is not allowed to replace with a constraint trigger; gram.y
798 * should have enforced this already.
799 */
800 Assert(!stmt->isconstraint);
801
802 /*
803 * It is not allowed to replace an existing constraint trigger,
804 * either. (The reason for these restrictions is partly that it seems
805 * difficult to deal with pending trigger events in such cases, and
806 * partly that the command might imply changing the constraint's
807 * properties as well, which doesn't seem nice.)
808 */
812 errmsg("trigger \"%s\" for relation \"%s\" is a constraint trigger",
813 stmt->trigname, RelationGetRelationName(rel))));
814 }
815
816 /*
817 * If it's a user-entered CREATE CONSTRAINT TRIGGER command, make a
818 * corresponding pg_constraint entry.
819 */
820 if (stmt->isconstraint && !OidIsValid(constraintOid))
821 {
822 /* Internal callers should have made their own constraints */
827 stmt->deferrable,
828 stmt->initdeferred,
829 true, /* Is Enforced */
830 true,
831 InvalidOid, /* no parent */
832 RelationGetRelid(rel),
833 NULL, /* no conkey */
834 0,
835 0,
836 InvalidOid, /* no domain */
837 InvalidOid, /* no index */
838 InvalidOid, /* no foreign key */
839 NULL,
840 NULL,
841 NULL,
842 NULL,
843 0,
844 ' ',
845 ' ',
846 NULL,
847 0,
848 ' ',
849 NULL, /* no exclusion */
850 NULL, /* no check constraint */
851 NULL,
852 true, /* islocal */
853 0, /* inhcount */
854 true, /* noinherit */
855 false, /* conperiod */
856 isInternal); /* is_internal */
857 }
858
859 /*
860 * If trigger is internally generated, modify the provided trigger name to
861 * ensure uniqueness by appending the trigger OID. (Callers will usually
862 * supply a simple constant trigger name in these cases.)
863 */
864 if (isInternal)
865 {
867 "%s_%u", stmt->trigname, trigoid);
868 trigname = internaltrigname;
869 }
870 else
871 {
872 /* user-defined trigger; use the specified trigger name as-is */
873 trigname = stmt->trigname;
874 }
875
876 /*
877 * Build the new pg_trigger tuple.
878 */
879 memset(nulls, false, sizeof(nulls));
880
885 CStringGetDatum(trigname));
895
896 if (stmt->args)
897 {
898 ListCell *le;
899 char *args;
900 int16 nargs = list_length(stmt->args);
901 int len = 0;
902
903 foreach(le, stmt->args)
904 {
905 char *ar = strVal(lfirst(le));
906
907 len += strlen(ar) + 4;
908 for (; *ar; ar++)
909 {
910 if (*ar == '\\')
911 len++;
912 }
913 }
914 args = (char *) palloc(len + 1);
915 args[0] = '\0';
916 foreach(le, stmt->args)
917 {
918 char *s = strVal(lfirst(le));
919 char *d = args + strlen(args);
920
921 while (*s)
922 {
923 if (*s == '\\')
924 *d++ = '\\';
925 *d++ = *s++;
926 }
927 strcpy(d, "\\000");
928 }
931 CStringGetDatum(args));
932 }
933 else
934 {
937 CStringGetDatum(""));
938 }
939
940 /* build column number array if it's a column-specific trigger */
941 ncolumns = list_length(stmt->columns);
942 if (ncolumns == 0)
943 columns = NULL;
944 else
945 {
946 ListCell *cell;
947 int i = 0;
948
949 columns = (int16 *) palloc(ncolumns * sizeof(int16));
950 foreach(cell, stmt->columns)
951 {
952 char *name = strVal(lfirst(cell));
954 int j;
955
956 /* Lookup column name. System columns are not allowed */
957 attnum = attnameAttNum(rel, name, false);
961 errmsg("column \"%s\" of relation \"%s\" does not exist",
963
964 /* Check for duplicates */
965 for (j = i - 1; j >= 0; j--)
966 {
967 if (columns[j] == attnum)
970 errmsg("column \"%s\" specified more than once",
971 name)));
972 }
973
974 columns[i++] = attnum;
975 }
976 }
977 tgattr = buildint2vector(columns, ncolumns);
979
980 /* set tgqual if trigger has WHEN clause */
981 if (qual)
983 else
984 nulls[Anum_pg_trigger_tgqual - 1] = true;
985
986 if (oldtablename)
989 else
990 nulls[Anum_pg_trigger_tgoldtable - 1] = true;
991 if (newtablename)
994 else
995 nulls[Anum_pg_trigger_tgnewtable - 1] = true;
996
997 /*
998 * Insert or replace tuple in pg_trigger.
999 */
1000 if (!trigger_exists)
1001 {
1002 tuple = heap_form_tuple(tgrel->rd_att, values, nulls);
1003 CatalogTupleInsert(tgrel, tuple);
1004 }
1005 else
1006 {
1008
1009 newtup = heap_form_tuple(tgrel->rd_att, values, nulls);
1012 }
1013
1014 heap_freetuple(tuple); /* free either original or new tuple */
1016
1020 if (oldtablename)
1022 if (newtablename)
1024
1025 /*
1026 * Update relation's pg_class entry; if necessary; and if not, send an SI
1027 * message to make other backends (and this one) rebuild relcache entries.
1028 */
1032 if (!HeapTupleIsValid(tuple))
1033 elog(ERROR, "cache lookup failed for relation %u",
1034 RelationGetRelid(rel));
1035 if (!((Form_pg_class) GETSTRUCT(tuple))->relhastriggers)
1036 {
1037 ((Form_pg_class) GETSTRUCT(tuple))->relhastriggers = true;
1038
1039 CatalogTupleUpdate(pgrel, &tuple->t_self, tuple);
1040
1042 }
1043 else
1045
1046 heap_freetuple(tuple);
1048
1049 /*
1050 * If we're replacing a trigger, flush all the old dependencies before
1051 * recording new ones.
1052 */
1053 if (trigger_exists)
1055
1056 /*
1057 * Record dependencies for trigger. Always place a normal dependency on
1058 * the function.
1059 */
1060 myself.classId = TriggerRelationId;
1061 myself.objectId = trigoid;
1062 myself.objectSubId = 0;
1063
1065 referenced.objectId = funcoid;
1066 referenced.objectSubId = 0;
1068
1070 {
1071 /*
1072 * Internally-generated trigger for a constraint, so make it an
1073 * internal dependency of the constraint. We can skip depending on
1074 * the relation(s), as there'll be an indirect dependency via the
1075 * constraint.
1076 */
1078 referenced.objectId = constraintOid;
1079 referenced.objectSubId = 0;
1081 }
1082 else
1083 {
1084 /*
1085 * User CREATE TRIGGER, so place dependencies. We make trigger be
1086 * auto-dropped if its relation is dropped or if the FK relation is
1087 * dropped. (Auto drop is compatible with our pre-7.3 behavior.)
1088 */
1090 referenced.objectId = RelationGetRelid(rel);
1091 referenced.objectSubId = 0;
1093
1095 {
1097 referenced.objectId = constrrelid;
1098 referenced.objectSubId = 0;
1100 }
1101 /* Not possible to have an index dependency in this case */
1102 Assert(!OidIsValid(indexOid));
1103
1104 /*
1105 * If it's a user-specified constraint trigger, make the constraint
1106 * internally dependent on the trigger instead of vice versa.
1107 */
1109 {
1111 referenced.objectId = constraintOid;
1112 referenced.objectSubId = 0;
1114 }
1115
1116 /*
1117 * If it's a partition trigger, create the partition dependencies.
1118 */
1120 {
1125 }
1126 }
1127
1128 /* If column-specific trigger, add normal dependencies on columns */
1129 if (columns != NULL)
1130 {
1131 int i;
1132
1134 referenced.objectId = RelationGetRelid(rel);
1135 for (i = 0; i < ncolumns; i++)
1136 {
1137 referenced.objectSubId = columns[i];
1139 }
1140 }
1141
1142 /*
1143 * If it has a WHEN clause, add dependencies on objects mentioned in the
1144 * expression (eg, functions, as well as any columns used).
1145 */
1146 if (whenRtable != NIL)
1149
1150 /* Post creation hook for new trigger */
1152 isInternal);
1153
1154 /*
1155 * Lastly, create the trigger on child relations, if needed.
1156 */
1158 {
1159 PartitionDesc partdesc = RelationGetPartitionDesc(rel, true);
1160 int i;
1163
1165 "part trig clone",
1167
1168 /*
1169 * We don't currently expect to be called with a valid indexOid. If
1170 * that ever changes then we'll need to write code here to find the
1171 * corresponding child index.
1172 */
1173 Assert(!OidIsValid(indexOid));
1174
1176
1177 /* Iterate to create the trigger on each existing partition */
1178 for (i = 0; i < partdesc->nparts; i++)
1179 {
1182 Node *qual;
1183
1185
1186 /*
1187 * Initialize our fabricated parse node by copying the original
1188 * one, then resetting fields that we pass separately.
1189 */
1191 childStmt->funcname = NIL;
1192 childStmt->whenClause = NULL;
1193
1194 /* If there is a WHEN clause, create a modified copy of it */
1195 qual = copyObject(whenClause);
1196 qual = (Node *)
1198 childTbl, rel);
1199 qual = (Node *)
1201 childTbl, rel);
1202
1203 CreateTriggerFiringOn(childStmt, queryString,
1204 partdesc->oids[i], refRelOid,
1206 funcoid, trigoid, qual,
1208
1210
1212 }
1213
1216 }
1217
1218 /* Keep lock on target rel until end of xact */
1219 table_close(rel, NoLock);
1220
1221 return myself;
1222}
1223
1224/*
1225 * TriggerSetParentTrigger
1226 * Set a partition's trigger as child of its parent trigger,
1227 * or remove the linkage if parentTrigId is InvalidOid.
1228 *
1229 * This updates the constraint's pg_trigger row to show it as inherited, and
1230 * adds PARTITION dependencies to prevent the trigger from being deleted
1231 * on its own. Alternatively, reverse that.
1232 */
1233void
1238{
1240 ScanKeyData skey[1];
1242 HeapTuple tuple,
1243 newtup;
1246
1247 /*
1248 * Find the trigger to delete.
1249 */
1250 ScanKeyInit(&skey[0],
1254
1256 NULL, 1, skey);
1257
1258 tuple = systable_getnext(tgscan);
1259 if (!HeapTupleIsValid(tuple))
1260 elog(ERROR, "could not find tuple for trigger %u", childTrigId);
1261 newtup = heap_copytuple(tuple);
1264 {
1265 /* don't allow setting parent for a constraint that already has one */
1266 if (OidIsValid(trigForm->tgparentid))
1267 elog(ERROR, "trigger %u already has a parent trigger",
1268 childTrigId);
1269
1270 trigForm->tgparentid = parentTrigId;
1271
1273
1275
1278
1281 }
1282 else
1283 {
1284 trigForm->tgparentid = InvalidOid;
1285
1287
1294 }
1295
1298}
1299
1300
1301/*
1302 * Guts of trigger deletion.
1303 */
1304void
1306{
1309 ScanKeyData skey[1];
1310 HeapTuple tup;
1311 Oid relid;
1312 Relation rel;
1313
1315
1316 /*
1317 * Find the trigger to delete.
1318 */
1319 ScanKeyInit(&skey[0],
1322 ObjectIdGetDatum(trigOid));
1323
1325 NULL, 1, skey);
1326
1328 if (!HeapTupleIsValid(tup))
1329 elog(ERROR, "could not find tuple for trigger %u", trigOid);
1330
1331 /*
1332 * Open and exclusive-lock the relation the trigger belongs to.
1333 */
1334 relid = ((Form_pg_trigger) GETSTRUCT(tup))->tgrelid;
1335
1336 rel = table_open(relid, AccessExclusiveLock);
1337
1338 if (rel->rd_rel->relkind != RELKIND_RELATION &&
1339 rel->rd_rel->relkind != RELKIND_VIEW &&
1340 rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
1341 rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
1342 ereport(ERROR,
1344 errmsg("relation \"%s\" cannot have triggers",
1346 errdetail_relkind_not_supported(rel->rd_rel->relkind)));
1347
1349 ereport(ERROR,
1351 errmsg("permission denied: \"%s\" is a system catalog",
1353
1354 /*
1355 * Delete the pg_trigger tuple.
1356 */
1357 CatalogTupleDelete(tgrel, &tup->t_self);
1358
1361
1362 /*
1363 * We do not bother to try to determine whether any other triggers remain,
1364 * which would be needed in order to decide whether it's safe to clear the
1365 * relation's relhastriggers. (In any case, there might be a concurrent
1366 * process adding new triggers.) Instead, just force a relcache inval to
1367 * make other backends (and this one too!) rebuild their relcache entries.
1368 * There's no great harm in leaving relhastriggers true even if there are
1369 * no triggers left.
1370 */
1372
1373 /* Keep lock on trigger's rel until end of xact */
1374 table_close(rel, NoLock);
1375}
1376
1377/*
1378 * get_trigger_oid - Look up a trigger by name to find its OID.
1379 *
1380 * If missing_ok is false, throw an error if trigger not found. If
1381 * true, just return InvalidOid.
1382 */
1383Oid
1384get_trigger_oid(Oid relid, const char *trigname, bool missing_ok)
1385{
1387 ScanKeyData skey[2];
1389 HeapTuple tup;
1390 Oid oid;
1391
1392 /*
1393 * Find the trigger, verify permissions, set up object address
1394 */
1396
1397 ScanKeyInit(&skey[0],
1400 ObjectIdGetDatum(relid));
1401 ScanKeyInit(&skey[1],
1404 CStringGetDatum(trigname));
1405
1407 NULL, 2, skey);
1408
1410
1411 if (!HeapTupleIsValid(tup))
1412 {
1413 if (!missing_ok)
1414 ereport(ERROR,
1416 errmsg("trigger \"%s\" for table \"%s\" does not exist",
1417 trigname, get_rel_name(relid))));
1418 oid = InvalidOid;
1419 }
1420 else
1421 {
1422 oid = ((Form_pg_trigger) GETSTRUCT(tup))->oid;
1423 }
1424
1427 return oid;
1428}
1429
1430/*
1431 * Perform permissions and integrity checks before acquiring a relation lock.
1432 */
1433static void
1435 void *arg)
1436{
1437 HeapTuple tuple;
1439
1440 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
1441 if (!HeapTupleIsValid(tuple))
1442 return; /* concurrently dropped */
1443 form = (Form_pg_class) GETSTRUCT(tuple);
1444
1445 /* only tables and views can have triggers */
1446 if (form->relkind != RELKIND_RELATION && form->relkind != RELKIND_VIEW &&
1447 form->relkind != RELKIND_FOREIGN_TABLE &&
1448 form->relkind != RELKIND_PARTITIONED_TABLE)
1449 ereport(ERROR,
1451 errmsg("relation \"%s\" cannot have triggers",
1452 rv->relname),
1454
1455 /* you must own the table to rename one of its triggers */
1458
1459 /*
1460 * Conflict log tables are used internally for logical replication
1461 * conflict logging and should not have triggers, as it could disrupt
1462 * conflict logging.
1463 */
1465 ereport(ERROR,
1467 errmsg("cannot rename trigger on conflict log table \"%s\"",
1468 rv->relname),
1469 errdetail("Conflict log tables are system-managed tables for logical replication conflicts.")));
1470
1471 if (!allowSystemTableMods && IsSystemClass(relid, form))
1472 ereport(ERROR,
1474 errmsg("permission denied: \"%s\" is a system catalog",
1475 rv->relname)));
1476
1477 ReleaseSysCache(tuple);
1478}
1479
1480/*
1481 * renametrig - changes the name of a trigger on a relation
1482 *
1483 * trigger name is changed in trigger catalog.
1484 * No record of the previous name is kept.
1485 *
1486 * get proper relrelation from relation catalog (if not arg)
1487 * scan trigger catalog
1488 * for name conflict (within rel)
1489 * for original trigger (if not arg)
1490 * modify tgname in trigger tuple
1491 * update row in catalog
1492 */
1495{
1496 Oid tgoid;
1499 HeapTuple tuple;
1501 ScanKeyData key[2];
1502 Oid relid;
1503 ObjectAddress address;
1504
1505 /*
1506 * Look up name, check permissions, and acquire lock (which we will NOT
1507 * release until end of transaction).
1508 */
1510 0,
1512 NULL);
1513
1514 /* Have lock already, so just need to build relcache entry. */
1515 targetrel = relation_open(relid, NoLock);
1516
1517 /*
1518 * On partitioned tables, this operation recurses to partitions. Lock all
1519 * tables upfront.
1520 */
1521 if (targetrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1523
1525
1526 /*
1527 * Search for the trigger to modify.
1528 */
1529 ScanKeyInit(&key[0],
1532 ObjectIdGetDatum(relid));
1533 ScanKeyInit(&key[1],
1536 PointerGetDatum(stmt->subname));
1538 NULL, 2, key);
1540 {
1542
1544 tgoid = trigform->oid;
1545
1546 /*
1547 * If the trigger descends from a trigger on a parent partitioned
1548 * table, reject the rename. We don't allow a trigger in a partition
1549 * to differ in name from that of its parent: that would lead to an
1550 * inconsistency that pg_dump would not reproduce.
1551 */
1552 if (OidIsValid(trigform->tgparentid))
1553 ereport(ERROR,
1555 errmsg("cannot rename trigger \"%s\" on table \"%s\"",
1557 errhint("Rename the trigger on the partitioned table \"%s\" instead.",
1558 get_rel_name(get_partition_parent(relid, false))));
1559
1560
1561 /* Rename the trigger on this relation ... */
1562 renametrig_internal(tgrel, targetrel, tuple, stmt->newname,
1563 stmt->subname);
1564
1565 /* ... and if it is partitioned, recurse to its partitions */
1566 if (targetrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1567 {
1569
1570 for (int i = 0; i < partdesc->nparts; i++)
1571 {
1572 Oid partitionId = partdesc->oids[i];
1573
1575 stmt->newname, stmt->subname);
1576 }
1577 }
1578 }
1579 else
1580 {
1581 ereport(ERROR,
1583 errmsg("trigger \"%s\" for table \"%s\" does not exist",
1585 }
1586
1587 ObjectAddressSet(address, TriggerRelationId, tgoid);
1588
1590
1592
1593 /*
1594 * Close rel, but keep exclusive lock!
1595 */
1597
1598 return address;
1599}
1600
1601/*
1602 * Subroutine for renametrig -- perform the actual work of renaming one
1603 * trigger on one table.
1604 *
1605 * If the trigger has a name different from the expected one, raise a
1606 * NOTICE about it.
1607 */
1608static void
1610 const char *newname, const char *expected_name)
1611{
1612 HeapTuple tuple;
1614 ScanKeyData key[2];
1616
1617 /* If the trigger already has the new name, nothing to do. */
1619 if (strcmp(NameStr(tgform->tgname), newname) == 0)
1620 return;
1621
1622 /*
1623 * Before actually trying the rename, search for triggers with the same
1624 * name. The update would fail with an ugly message in that case, and it
1625 * is better to throw a nicer error.
1626 */
1627 ScanKeyInit(&key[0],
1631 ScanKeyInit(&key[1],
1634 PointerGetDatum(newname));
1636 NULL, 2, key);
1638 ereport(ERROR,
1640 errmsg("trigger \"%s\" for relation \"%s\" already exists",
1643
1644 /*
1645 * The target name is free; update the existing pg_trigger tuple with it.
1646 */
1647 tuple = heap_copytuple(trigtup); /* need a modifiable copy */
1648 tgform = (Form_pg_trigger) GETSTRUCT(tuple);
1649
1650 /*
1651 * If the trigger has a name different from what we expected, let the user
1652 * know. (We can proceed anyway, since we must have reached here following
1653 * a tgparentid link.)
1654 */
1655 if (strcmp(NameStr(tgform->tgname), expected_name) != 0)
1657 errmsg("renamed trigger \"%s\" on relation \"%s\"",
1658 NameStr(tgform->tgname),
1660
1661 namestrcpy(&tgform->tgname, newname);
1662
1663 CatalogTupleUpdate(tgrel, &tuple->t_self, tuple);
1664
1666
1667 /*
1668 * Invalidate relation's relcache entry so that other backends (and this
1669 * one too!) are sent SI message to make them rebuild relcache entries.
1670 * (Ideally this should happen automatically...)
1671 */
1673}
1674
1675/*
1676 * Subroutine for renametrig -- Helper for recursing to partitions when
1677 * renaming triggers on a partitioned table.
1678 */
1679static void
1681 const char *newname, const char *expected_name)
1682{
1684 ScanKeyData key;
1685 HeapTuple tuple;
1686
1687 /*
1688 * Given a relation and the OID of a trigger on parent relation, find the
1689 * corresponding trigger in the child and rename that trigger to the given
1690 * name.
1691 */
1692 ScanKeyInit(&key,
1697 NULL, 1, &key);
1698 while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1699 {
1702
1703 if (tgform->tgparentid != parentTriggerOid)
1704 continue; /* not our trigger */
1705
1707
1708 /* Rename the trigger on this partition */
1710
1711 /* And if this relation is partitioned, recurse to its partitions */
1712 if (partitionRel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1713 {
1715 true);
1716
1717 for (int i = 0; i < partdesc->nparts; i++)
1718 {
1719 Oid partoid = partdesc->oids[i];
1720
1721 renametrig_partition(tgrel, partoid, tgform->oid, newname,
1722 NameStr(tgform->tgname));
1723 }
1724 }
1726
1727 /* There should be at most one matching tuple */
1728 break;
1729 }
1731}
1732
1733/*
1734 * EnableDisableTrigger()
1735 *
1736 * Called by ALTER TABLE ENABLE/DISABLE [ REPLICA | ALWAYS ] TRIGGER
1737 * to change 'tgenabled' field for the specified trigger(s)
1738 *
1739 * rel: relation to process (caller must hold suitable lock on it)
1740 * tgname: name of trigger to process, or NULL to scan all triggers
1741 * tgparent: if not zero, process only triggers with this tgparentid
1742 * fires_when: new value for tgenabled field. In addition to generic
1743 * enablement/disablement, this also defines when the trigger
1744 * should be fired in session replication roles.
1745 * skip_system: if true, skip "system" triggers (constraint triggers)
1746 * recurse: if true, recurse to partitions
1747 *
1748 * Caller should have checked permissions for the table; here we also
1749 * enforce that superuser privilege is required to alter the state of
1750 * system triggers
1751 */
1752void
1754 char fires_when, bool skip_system, bool recurse,
1755 LOCKMODE lockmode)
1756{
1758 int nkeys;
1759 ScanKeyData keys[2];
1761 HeapTuple tuple;
1762 bool found;
1763 bool changed;
1764
1765 /* Scan the relevant entries in pg_triggers */
1767
1768 ScanKeyInit(&keys[0],
1772 if (tgname)
1773 {
1774 ScanKeyInit(&keys[1],
1777 CStringGetDatum(tgname));
1778 nkeys = 2;
1779 }
1780 else
1781 nkeys = 1;
1782
1784 NULL, nkeys, keys);
1785
1786 found = changed = false;
1787
1788 while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
1789 {
1791
1792 if (OidIsValid(tgparent) && tgparent != oldtrig->tgparentid)
1793 continue;
1794
1795 if (oldtrig->tgisinternal)
1796 {
1797 /* system trigger ... ok to process? */
1798 if (skip_system)
1799 continue;
1800 if (!superuser())
1801 ereport(ERROR,
1803 errmsg("permission denied: \"%s\" is a system trigger",
1804 NameStr(oldtrig->tgname))));
1805 }
1806
1807 found = true;
1808
1809 if (oldtrig->tgenabled != fires_when)
1810 {
1811 /* need to change this one ... make a copy to scribble on */
1814
1815 newtrig->tgenabled = fires_when;
1816
1818
1820
1821 changed = true;
1822 }
1823
1824 /*
1825 * When altering FOR EACH ROW triggers on a partitioned table, do the
1826 * same on the partitions as well, unless ONLY is specified.
1827 *
1828 * Note that we recurse even if we didn't change the trigger above,
1829 * because the partitions' copy of the trigger may have a different
1830 * value of tgenabled than the parent's trigger and thus might need to
1831 * be changed.
1832 */
1833 if (recurse &&
1834 rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
1835 (TRIGGER_FOR_ROW(oldtrig->tgtype)))
1836 {
1837 PartitionDesc partdesc = RelationGetPartitionDesc(rel, true);
1838 int i;
1839
1840 for (i = 0; i < partdesc->nparts; i++)
1841 {
1842 Relation part;
1843
1844 part = relation_open(partdesc->oids[i], lockmode);
1845 /* Match on child triggers' tgparentid, not their name */
1847 fires_when, skip_system, recurse,
1848 lockmode);
1849 table_close(part, NoLock); /* keep lock till commit */
1850 }
1851 }
1852
1854 oldtrig->oid, 0);
1855 }
1856
1858
1860
1861 if (tgname && !found)
1862 ereport(ERROR,
1864 errmsg("trigger \"%s\" for table \"%s\" does not exist",
1865 tgname, RelationGetRelationName(rel))));
1866
1867 /*
1868 * If we changed anything, broadcast a SI inval message to force each
1869 * backend (including our own!) to rebuild relation's relcache entry.
1870 * Otherwise they will fail to apply the change promptly.
1871 */
1872 if (changed)
1874}
1875
1876
1877/*
1878 * Build trigger data to attach to the given relcache entry.
1879 *
1880 * Note that trigger data attached to a relcache entry must be stored in
1881 * CacheMemoryContext to ensure it survives as long as the relcache entry.
1882 * But we should be running in a less long-lived working context. To avoid
1883 * leaking cache memory if this routine fails partway through, we build a
1884 * temporary TriggerDesc in working memory and then copy the completed
1885 * structure into cache memory.
1886 */
1887void
1889{
1890 TriggerDesc *trigdesc;
1891 int numtrigs;
1892 int maxtrigs;
1893 Trigger *triggers;
1897 HeapTuple htup;
1899 int i;
1900
1901 /*
1902 * Allocate a working array to hold the triggers (the array is extended if
1903 * necessary)
1904 */
1905 maxtrigs = 16;
1906 triggers = (Trigger *) palloc(maxtrigs * sizeof(Trigger));
1907 numtrigs = 0;
1908
1909 /*
1910 * Note: since we scan the triggers using TriggerRelidNameIndexId, we will
1911 * be reading the triggers in name order, except possibly during
1912 * emergency-recovery operations (ie, IgnoreSystemIndexes). This in turn
1913 * ensures that triggers will be fired in name order.
1914 */
1919
1922 NULL, 1, &skey);
1923
1925 {
1927 Trigger *build;
1928 Datum datum;
1929 bool isnull;
1930
1931 if (numtrigs >= maxtrigs)
1932 {
1933 maxtrigs *= 2;
1934 triggers = (Trigger *) repalloc(triggers, maxtrigs * sizeof(Trigger));
1935 }
1936 build = &(triggers[numtrigs]);
1937
1938 build->tgoid = pg_trigger->oid;
1940 NameGetDatum(&pg_trigger->tgname)));
1941 build->tgfoid = pg_trigger->tgfoid;
1942 build->tgtype = pg_trigger->tgtype;
1943 build->tgenabled = pg_trigger->tgenabled;
1944 build->tgisinternal = pg_trigger->tgisinternal;
1945 build->tgisclone = OidIsValid(pg_trigger->tgparentid);
1946 build->tgconstrrelid = pg_trigger->tgconstrrelid;
1947 build->tgconstrindid = pg_trigger->tgconstrindid;
1948 build->tgconstraint = pg_trigger->tgconstraint;
1949 build->tgdeferrable = pg_trigger->tgdeferrable;
1950 build->tginitdeferred = pg_trigger->tginitdeferred;
1951 build->tgnargs = pg_trigger->tgnargs;
1952 /* tgattr is first var-width field, so OK to access directly */
1953 build->tgnattr = pg_trigger->tgattr.dim1;
1954 if (build->tgnattr > 0)
1955 {
1956 build->tgattr = (int16 *) palloc(build->tgnattr * sizeof(int16));
1957 memcpy(build->tgattr, &(pg_trigger->tgattr.values),
1958 build->tgnattr * sizeof(int16));
1959 }
1960 else
1961 build->tgattr = NULL;
1962 if (build->tgnargs > 0)
1963 {
1964 bytea *val;
1965 char *p;
1966
1969 tgrel->rd_att, &isnull));
1970 if (isnull)
1971 elog(ERROR, "tgargs is null in trigger for relation \"%s\"",
1972 RelationGetRelationName(relation));
1973 p = (char *) VARDATA_ANY(val);
1974 build->tgargs = (char **) palloc(build->tgnargs * sizeof(char *));
1975 for (i = 0; i < build->tgnargs; i++)
1976 {
1977 build->tgargs[i] = pstrdup(p);
1978 p += strlen(p) + 1;
1979 }
1980 }
1981 else
1982 build->tgargs = NULL;
1983
1985 tgrel->rd_att, &isnull);
1986 if (!isnull)
1987 build->tgoldtable =
1989 else
1990 build->tgoldtable = NULL;
1991
1993 tgrel->rd_att, &isnull);
1994 if (!isnull)
1995 build->tgnewtable =
1997 else
1998 build->tgnewtable = NULL;
1999
2000 datum = fastgetattr(htup, Anum_pg_trigger_tgqual,
2001 tgrel->rd_att, &isnull);
2002 if (!isnull)
2003 build->tgqual = TextDatumGetCString(datum);
2004 else
2005 build->tgqual = NULL;
2006
2007 numtrigs++;
2008 }
2009
2012
2013 /* There might not be any triggers */
2014 if (numtrigs == 0)
2015 {
2016 pfree(triggers);
2017 return;
2018 }
2019
2020 /* Build trigdesc */
2021 trigdesc = palloc0_object(TriggerDesc);
2022 trigdesc->triggers = triggers;
2023 trigdesc->numtriggers = numtrigs;
2024 for (i = 0; i < numtrigs; i++)
2025 SetTriggerFlags(trigdesc, &(triggers[i]));
2026
2027 /* Copy completed trigdesc into cache storage */
2029 relation->trigdesc = CopyTriggerDesc(trigdesc);
2031
2032 /* Release working memory */
2033 FreeTriggerDesc(trigdesc);
2034}
2035
2036/*
2037 * Update the TriggerDesc's hint flags to include the specified trigger
2038 */
2039static void
2041{
2042 int16 tgtype = trigger->tgtype;
2043
2044 trigdesc->trig_insert_before_row |=
2047 trigdesc->trig_insert_after_row |=
2050 trigdesc->trig_insert_instead_row |=
2053 trigdesc->trig_insert_before_statement |=
2056 trigdesc->trig_insert_after_statement |=
2059 trigdesc->trig_update_before_row |=
2062 trigdesc->trig_update_after_row |=
2065 trigdesc->trig_update_instead_row |=
2068 trigdesc->trig_update_before_statement |=
2071 trigdesc->trig_update_after_statement |=
2074 trigdesc->trig_delete_before_row |=
2077 trigdesc->trig_delete_after_row |=
2080 trigdesc->trig_delete_instead_row |=
2083 trigdesc->trig_delete_before_statement |=
2086 trigdesc->trig_delete_after_statement |=
2089 /* there are no row-level truncate triggers */
2096
2097 trigdesc->trig_insert_new_table |=
2098 (TRIGGER_FOR_INSERT(tgtype) &&
2100 trigdesc->trig_update_old_table |=
2101 (TRIGGER_FOR_UPDATE(tgtype) &&
2103 trigdesc->trig_update_new_table |=
2104 (TRIGGER_FOR_UPDATE(tgtype) &&
2106 trigdesc->trig_delete_old_table |=
2107 (TRIGGER_FOR_DELETE(tgtype) &&
2109}
2110
2111/*
2112 * Copy a TriggerDesc data structure.
2113 *
2114 * The copy is allocated in the current memory context.
2115 */
2118{
2121 int i;
2122
2123 if (trigdesc == NULL || trigdesc->numtriggers <= 0)
2124 return NULL;
2125
2127 memcpy(newdesc, trigdesc, sizeof(TriggerDesc));
2128
2129 trigger = (Trigger *) palloc(trigdesc->numtriggers * sizeof(Trigger));
2130 memcpy(trigger, trigdesc->triggers,
2131 trigdesc->numtriggers * sizeof(Trigger));
2132 newdesc->triggers = trigger;
2133
2134 for (i = 0; i < trigdesc->numtriggers; i++)
2135 {
2136 trigger->tgname = pstrdup(trigger->tgname);
2137 if (trigger->tgnattr > 0)
2138 {
2139 int16 *newattr;
2140
2141 newattr = (int16 *) palloc(trigger->tgnattr * sizeof(int16));
2142 memcpy(newattr, trigger->tgattr,
2143 trigger->tgnattr * sizeof(int16));
2144 trigger->tgattr = newattr;
2145 }
2146 if (trigger->tgnargs > 0)
2147 {
2148 char **newargs;
2149 int16 j;
2150
2151 newargs = (char **) palloc(trigger->tgnargs * sizeof(char *));
2152 for (j = 0; j < trigger->tgnargs; j++)
2153 newargs[j] = pstrdup(trigger->tgargs[j]);
2154 trigger->tgargs = newargs;
2155 }
2156 if (trigger->tgqual)
2157 trigger->tgqual = pstrdup(trigger->tgqual);
2158 if (trigger->tgoldtable)
2159 trigger->tgoldtable = pstrdup(trigger->tgoldtable);
2160 if (trigger->tgnewtable)
2161 trigger->tgnewtable = pstrdup(trigger->tgnewtable);
2162 trigger++;
2163 }
2164
2165 return newdesc;
2166}
2167
2168/*
2169 * Free a TriggerDesc data structure.
2170 */
2171void
2173{
2175 int i;
2176
2177 if (trigdesc == NULL)
2178 return;
2179
2180 trigger = trigdesc->triggers;
2181 for (i = 0; i < trigdesc->numtriggers; i++)
2182 {
2183 pfree(trigger->tgname);
2184 if (trigger->tgnattr > 0)
2185 pfree(trigger->tgattr);
2186 if (trigger->tgnargs > 0)
2187 {
2188 while (--(trigger->tgnargs) >= 0)
2189 pfree(trigger->tgargs[trigger->tgnargs]);
2190 pfree(trigger->tgargs);
2191 }
2192 if (trigger->tgqual)
2193 pfree(trigger->tgqual);
2194 if (trigger->tgoldtable)
2195 pfree(trigger->tgoldtable);
2196 if (trigger->tgnewtable)
2197 pfree(trigger->tgnewtable);
2198 trigger++;
2199 }
2200 pfree(trigdesc->triggers);
2201 pfree(trigdesc);
2202}
2203
2204/*
2205 * Compare two TriggerDesc structures for logical equality.
2206 */
2207#ifdef NOT_USED
2208bool
2210{
2211 int i,
2212 j;
2213
2214 /*
2215 * We need not examine the hint flags, just the trigger array itself; if
2216 * we have the same triggers with the same types, the flags should match.
2217 *
2218 * As of 7.3 we assume trigger set ordering is significant in the
2219 * comparison; so we just compare corresponding slots of the two sets.
2220 *
2221 * Note: comparing the stringToNode forms of the WHEN clauses means that
2222 * parse column locations will affect the result. This is okay as long as
2223 * this function is only used for detecting exact equality, as for example
2224 * in checking for staleness of a cache entry.
2225 */
2226 if (trigdesc1 != NULL)
2227 {
2228 if (trigdesc2 == NULL)
2229 return false;
2230 if (trigdesc1->numtriggers != trigdesc2->numtriggers)
2231 return false;
2232 for (i = 0; i < trigdesc1->numtriggers; i++)
2233 {
2234 Trigger *trig1 = trigdesc1->triggers + i;
2235 Trigger *trig2 = trigdesc2->triggers + i;
2236
2237 if (trig1->tgoid != trig2->tgoid)
2238 return false;
2239 if (strcmp(trig1->tgname, trig2->tgname) != 0)
2240 return false;
2241 if (trig1->tgfoid != trig2->tgfoid)
2242 return false;
2243 if (trig1->tgtype != trig2->tgtype)
2244 return false;
2245 if (trig1->tgenabled != trig2->tgenabled)
2246 return false;
2247 if (trig1->tgisinternal != trig2->tgisinternal)
2248 return false;
2249 if (trig1->tgisclone != trig2->tgisclone)
2250 return false;
2251 if (trig1->tgconstrrelid != trig2->tgconstrrelid)
2252 return false;
2253 if (trig1->tgconstrindid != trig2->tgconstrindid)
2254 return false;
2255 if (trig1->tgconstraint != trig2->tgconstraint)
2256 return false;
2257 if (trig1->tgdeferrable != trig2->tgdeferrable)
2258 return false;
2259 if (trig1->tginitdeferred != trig2->tginitdeferred)
2260 return false;
2261 if (trig1->tgnargs != trig2->tgnargs)
2262 return false;
2263 if (trig1->tgnattr != trig2->tgnattr)
2264 return false;
2265 if (trig1->tgnattr > 0 &&
2266 memcmp(trig1->tgattr, trig2->tgattr,
2267 trig1->tgnattr * sizeof(int16)) != 0)
2268 return false;
2269 for (j = 0; j < trig1->tgnargs; j++)
2270 if (strcmp(trig1->tgargs[j], trig2->tgargs[j]) != 0)
2271 return false;
2272 if (trig1->tgqual == NULL && trig2->tgqual == NULL)
2273 /* ok */ ;
2274 else if (trig1->tgqual == NULL || trig2->tgqual == NULL)
2275 return false;
2276 else if (strcmp(trig1->tgqual, trig2->tgqual) != 0)
2277 return false;
2278 if (trig1->tgoldtable == NULL && trig2->tgoldtable == NULL)
2279 /* ok */ ;
2280 else if (trig1->tgoldtable == NULL || trig2->tgoldtable == NULL)
2281 return false;
2282 else if (strcmp(trig1->tgoldtable, trig2->tgoldtable) != 0)
2283 return false;
2284 if (trig1->tgnewtable == NULL && trig2->tgnewtable == NULL)
2285 /* ok */ ;
2286 else if (trig1->tgnewtable == NULL || trig2->tgnewtable == NULL)
2287 return false;
2288 else if (strcmp(trig1->tgnewtable, trig2->tgnewtable) != 0)
2289 return false;
2290 }
2291 }
2292 else if (trigdesc2 != NULL)
2293 return false;
2294 return true;
2295}
2296#endif /* NOT_USED */
2297
2298/*
2299 * Check if there is a row-level trigger with transition tables that prevents
2300 * a table from becoming an inheritance child or partition. Return the name
2301 * of the first such incompatible trigger, or NULL if there is none.
2302 */
2303const char *
2305{
2306 if (trigdesc != NULL)
2307 {
2308 int i;
2309
2310 for (i = 0; i < trigdesc->numtriggers; ++i)
2311 {
2312 Trigger *trigger = &trigdesc->triggers[i];
2313
2314 if (!TRIGGER_FOR_ROW(trigger->tgtype))
2315 continue;
2316 if (trigger->tgoldtable != NULL || trigger->tgnewtable != NULL)
2317 return trigger->tgname;
2318 }
2319 }
2320
2321 return NULL;
2322}
2323
2324/*
2325 * Call a trigger function.
2326 *
2327 * trigdata: trigger descriptor.
2328 * tgindx: trigger's index in finfo and instr arrays.
2329 * finfo: array of cached trigger function call information.
2330 * instr: optional array of EXPLAIN ANALYZE instrumentation state.
2331 * per_tuple_context: memory context to execute the function in.
2332 *
2333 * Returns the tuple (or NULL) as returned by the function.
2334 */
2335static HeapTuple
2337 int tgindx,
2338 FmgrInfo *finfo,
2341{
2342 LOCAL_FCINFO(fcinfo, 0);
2344 Datum result;
2346
2347 /*
2348 * Protect against code paths that may fail to initialize transition table
2349 * info.
2350 */
2352 TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event) ||
2353 TRIGGER_FIRED_BY_DELETE(trigdata->tg_event)) &&
2354 TRIGGER_FIRED_AFTER(trigdata->tg_event) &&
2355 !(trigdata->tg_event & AFTER_TRIGGER_DEFERRABLE) &&
2356 !(trigdata->tg_event & AFTER_TRIGGER_INITDEFERRED)) ||
2357 (trigdata->tg_oldtable == NULL && trigdata->tg_newtable == NULL));
2358
2359 finfo += tgindx;
2360
2361 /*
2362 * We cache fmgr lookup info, to avoid making the lookup again on each
2363 * call.
2364 */
2365 if (finfo->fn_oid == InvalidOid)
2366 fmgr_info(trigdata->tg_trigger->tgfoid, finfo);
2367
2368 Assert(finfo->fn_oid == trigdata->tg_trigger->tgfoid);
2369
2370 /*
2371 * If doing EXPLAIN ANALYZE, start charging time to this trigger.
2372 */
2373 if (instr)
2374 InstrStartTrigger(instr + tgindx);
2375
2376 /*
2377 * Do the function evaluation in the per-tuple memory context, so that
2378 * leaked memory will be reclaimed once per tuple. Note in particular that
2379 * any new tuple created by the trigger function will live till the end of
2380 * the tuple cycle.
2381 */
2383
2384 /*
2385 * Call the function, passing no arguments but setting a context.
2386 */
2387 InitFunctionCallInfoData(*fcinfo, finfo, 0,
2388 InvalidOid, (Node *) trigdata, NULL);
2389
2391
2393 PG_TRY();
2394 {
2395 result = FunctionCallInvoke(fcinfo);
2396 }
2397 PG_FINALLY();
2398 {
2400 }
2401 PG_END_TRY();
2402
2404
2406
2407 /*
2408 * Trigger protocol allows function to return a null pointer, but NOT to
2409 * set the isnull result flag.
2410 */
2411 if (fcinfo->isnull)
2412 ereport(ERROR,
2414 errmsg("trigger function %u returned null value",
2415 fcinfo->flinfo->fn_oid)));
2416
2417 /*
2418 * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
2419 * the firing of the trigger.
2420 */
2421 if (instr)
2422 InstrStopTrigger(instr + tgindx, 1);
2423
2425}
2426
2427void
2429{
2430 TriggerDesc *trigdesc;
2431 int i;
2433
2434 trigdesc = relinfo->ri_TrigDesc;
2435
2436 if (trigdesc == NULL)
2437 return;
2438 if (!trigdesc->trig_insert_before_statement)
2439 return;
2440
2441 /* no-op if we already fired BS triggers in this context */
2443 CMD_INSERT))
2444 return;
2445
2449 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2450 for (i = 0; i < trigdesc->numtriggers; i++)
2451 {
2452 Trigger *trigger = &trigdesc->triggers[i];
2453 HeapTuple newtuple;
2454
2455 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2459 continue;
2460 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2461 NULL, NULL, NULL))
2462 continue;
2463
2464 LocTriggerData.tg_trigger = trigger;
2466 i,
2467 relinfo->ri_TrigFunctions,
2468 relinfo->ri_TrigInstrument,
2469 GetPerTupleMemoryContext(estate));
2470
2471 if (newtuple)
2472 ereport(ERROR,
2474 errmsg("BEFORE STATEMENT trigger cannot return a value")));
2475 }
2476}
2477
2478void
2480 TransitionCaptureState *transition_capture)
2481{
2482 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2483
2484 if (trigdesc && trigdesc->trig_insert_after_statement)
2487 false, NULL, NULL, NIL, NULL, transition_capture,
2488 false);
2489}
2490
2491bool
2493 TupleTableSlot *slot)
2494{
2495 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2496 HeapTuple newtuple = NULL;
2497 bool should_free;
2499 int i;
2500
2505 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2506 for (i = 0; i < trigdesc->numtriggers; i++)
2507 {
2508 Trigger *trigger = &trigdesc->triggers[i];
2509 HeapTuple oldtuple;
2510
2511 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2515 continue;
2516 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2517 NULL, NULL, slot))
2518 continue;
2519
2520 if (!newtuple)
2521 newtuple = ExecFetchSlotHeapTuple(slot, true, &should_free);
2522
2523 LocTriggerData.tg_trigslot = slot;
2524 LocTriggerData.tg_trigtuple = oldtuple = newtuple;
2525 LocTriggerData.tg_trigger = trigger;
2527 i,
2528 relinfo->ri_TrigFunctions,
2529 relinfo->ri_TrigInstrument,
2530 GetPerTupleMemoryContext(estate));
2531 if (newtuple == NULL)
2532 {
2533 if (should_free)
2534 heap_freetuple(oldtuple);
2535 return false; /* "do nothing" */
2536 }
2537 else if (newtuple != oldtuple)
2538 {
2539 newtuple = check_modified_virtual_generated(RelationGetDescr(relinfo->ri_RelationDesc), newtuple);
2540
2541 ExecForceStoreHeapTuple(newtuple, slot, false);
2542
2543 /*
2544 * After a tuple in a partition goes through a trigger, the user
2545 * could have changed the partition key enough that the tuple no
2546 * longer fits the partition. Verify that.
2547 */
2548 if (trigger->tgisclone &&
2549 !ExecPartitionCheck(relinfo, slot, estate, false))
2550 ereport(ERROR,
2552 errmsg("moving row to another partition during a BEFORE FOR EACH ROW trigger is not supported"),
2553 errdetail("Before executing trigger \"%s\", the row was to be in partition \"%s.%s\".",
2554 trigger->tgname,
2556 RelationGetRelationName(relinfo->ri_RelationDesc))));
2557
2558 if (should_free)
2559 heap_freetuple(oldtuple);
2560
2561 /* signal tuple should be re-fetched if used */
2562 newtuple = NULL;
2563 }
2564 }
2565
2566 return true;
2567}
2568
2569void
2572 TransitionCaptureState *transition_capture)
2573{
2574 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2575
2576 if (relinfo->ri_FdwRoutine && transition_capture &&
2577 transition_capture->tcs_insert_new_table)
2578 {
2579 Assert(relinfo->ri_RootResultRelInfo);
2580 ereport(ERROR,
2582 errmsg("cannot collect transition tuples from child foreign tables")));
2583 }
2584
2585 if ((trigdesc && trigdesc->trig_insert_after_row) ||
2586 (transition_capture && transition_capture->tcs_insert_new_table))
2589 true, NULL, slot,
2591 transition_capture,
2592 false);
2593}
2594
2595bool
2597 TupleTableSlot *slot)
2598{
2599 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2600 HeapTuple newtuple = NULL;
2601 bool should_free;
2603 int i;
2604
2609 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2610 for (i = 0; i < trigdesc->numtriggers; i++)
2611 {
2612 Trigger *trigger = &trigdesc->triggers[i];
2613 HeapTuple oldtuple;
2614
2615 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2619 continue;
2620 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2621 NULL, NULL, slot))
2622 continue;
2623
2624 if (!newtuple)
2625 newtuple = ExecFetchSlotHeapTuple(slot, true, &should_free);
2626
2627 LocTriggerData.tg_trigslot = slot;
2628 LocTriggerData.tg_trigtuple = oldtuple = newtuple;
2629 LocTriggerData.tg_trigger = trigger;
2631 i,
2632 relinfo->ri_TrigFunctions,
2633 relinfo->ri_TrigInstrument,
2634 GetPerTupleMemoryContext(estate));
2635 if (newtuple == NULL)
2636 {
2637 if (should_free)
2638 heap_freetuple(oldtuple);
2639 return false; /* "do nothing" */
2640 }
2641 else if (newtuple != oldtuple)
2642 {
2643 ExecForceStoreHeapTuple(newtuple, slot, false);
2644
2645 if (should_free)
2646 heap_freetuple(oldtuple);
2647
2648 /* signal tuple should be re-fetched if used */
2649 newtuple = NULL;
2650 }
2651 }
2652
2653 return true;
2654}
2655
2656void
2658{
2659 TriggerDesc *trigdesc;
2660 int i;
2662
2663 trigdesc = relinfo->ri_TrigDesc;
2664
2665 if (trigdesc == NULL)
2666 return;
2667 if (!trigdesc->trig_delete_before_statement)
2668 return;
2669
2670 /* no-op if we already fired BS triggers in this context */
2672 CMD_DELETE))
2673 return;
2674
2678 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2679 for (i = 0; i < trigdesc->numtriggers; i++)
2680 {
2681 Trigger *trigger = &trigdesc->triggers[i];
2682 HeapTuple newtuple;
2683
2684 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2688 continue;
2689 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2690 NULL, NULL, NULL))
2691 continue;
2692
2693 LocTriggerData.tg_trigger = trigger;
2695 i,
2696 relinfo->ri_TrigFunctions,
2697 relinfo->ri_TrigInstrument,
2698 GetPerTupleMemoryContext(estate));
2699
2700 if (newtuple)
2701 ereport(ERROR,
2703 errmsg("BEFORE STATEMENT trigger cannot return a value")));
2704 }
2705}
2706
2707void
2709 TransitionCaptureState *transition_capture)
2710{
2711 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2712
2713 if (trigdesc && trigdesc->trig_delete_after_statement)
2716 false, NULL, NULL, NIL, NULL, transition_capture,
2717 false);
2718}
2719
2720/*
2721 * Execute BEFORE ROW DELETE triggers.
2722 *
2723 * True indicates caller can proceed with the delete. False indicates caller
2724 * need to suppress the delete and additionally if requested, we need to pass
2725 * back the concurrently updated tuple if any.
2726 */
2727bool
2734 TM_FailureData *tmfd,
2735 bool is_merge_delete)
2736{
2738 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2739 bool result = true;
2742 bool should_free = false;
2743 int i;
2744
2746 if (fdw_trigtuple == NULL)
2747 {
2749
2750 /*
2751 * Get a copy of the on-disk tuple we are planning to delete. In
2752 * general, if the tuple has been concurrently updated, we should
2753 * recheck it using EPQ. However, if this is a MERGE DELETE action,
2754 * we skip this EPQ recheck and leave it to the caller (it must do
2755 * additional rechecking, and might end up executing a different
2756 * action entirely).
2757 */
2758 if (!GetTupleForTrigger(estate, epqstate, relinfo, tupleid,
2760 &epqslot_candidate, tmresult, tmfd))
2761 return false;
2762
2763 /*
2764 * If the tuple was concurrently updated and the caller of this
2765 * function requested for the updated tuple, skip the trigger
2766 * execution.
2767 */
2768 if (epqslot_candidate != NULL && epqslot != NULL)
2769 {
2771 return false;
2772 }
2773
2775 }
2776 else
2777 {
2779 ExecForceStoreHeapTuple(trigtuple, slot, false);
2780 }
2781
2786 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2787 for (i = 0; i < trigdesc->numtriggers; i++)
2788 {
2789 HeapTuple newtuple;
2790 Trigger *trigger = &trigdesc->triggers[i];
2791
2792 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2796 continue;
2797 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2798 NULL, slot, NULL))
2799 continue;
2800
2801 LocTriggerData.tg_trigslot = slot;
2802 LocTriggerData.tg_trigtuple = trigtuple;
2803 LocTriggerData.tg_trigger = trigger;
2805 i,
2806 relinfo->ri_TrigFunctions,
2807 relinfo->ri_TrigInstrument,
2808 GetPerTupleMemoryContext(estate));
2809 if (newtuple == NULL)
2810 {
2811 result = false; /* tell caller to suppress delete */
2812 break;
2813 }
2814 if (newtuple != trigtuple)
2815 heap_freetuple(newtuple);
2816 }
2817 if (should_free)
2819
2820 return result;
2821}
2822
2823/*
2824 * Note: is_crosspart_update must be true if the DELETE is being performed
2825 * as part of a cross-partition update.
2826 */
2827void
2832 TransitionCaptureState *transition_capture,
2834{
2835 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2836
2837 if (relinfo->ri_FdwRoutine && transition_capture &&
2838 transition_capture->tcs_delete_old_table)
2839 {
2840 Assert(relinfo->ri_RootResultRelInfo);
2841 ereport(ERROR,
2843 errmsg("cannot collect transition tuples from child foreign tables")));
2844 }
2845
2846 if ((trigdesc && trigdesc->trig_delete_after_row) ||
2847 (transition_capture && transition_capture->tcs_delete_old_table))
2848 {
2850
2852 if (fdw_trigtuple == NULL)
2853 GetTupleForTrigger(estate,
2854 NULL,
2855 relinfo,
2856 tupleid,
2858 slot,
2859 false,
2860 NULL,
2861 NULL,
2862 NULL);
2863 else
2865
2868 true, slot, NULL, NIL, NULL,
2869 transition_capture,
2871 }
2872}
2873
2874bool
2877{
2878 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2881 int i;
2882
2887 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2888
2889 ExecForceStoreHeapTuple(trigtuple, slot, false);
2890
2891 for (i = 0; i < trigdesc->numtriggers; i++)
2892 {
2894 Trigger *trigger = &trigdesc->triggers[i];
2895
2896 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2900 continue;
2901 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2902 NULL, slot, NULL))
2903 continue;
2904
2905 LocTriggerData.tg_trigslot = slot;
2906 LocTriggerData.tg_trigtuple = trigtuple;
2907 LocTriggerData.tg_trigger = trigger;
2909 i,
2910 relinfo->ri_TrigFunctions,
2911 relinfo->ri_TrigInstrument,
2912 GetPerTupleMemoryContext(estate));
2913 if (rettuple == NULL)
2914 return false; /* Delete was suppressed */
2915 if (rettuple != trigtuple)
2917 }
2918 return true;
2919}
2920
2921void
2923{
2924 TriggerDesc *trigdesc;
2925 int i;
2927 Bitmapset *updatedCols;
2928
2929 trigdesc = relinfo->ri_TrigDesc;
2930
2931 if (trigdesc == NULL)
2932 return;
2933 if (!trigdesc->trig_update_before_statement)
2934 return;
2935
2936 /* no-op if we already fired BS triggers in this context */
2938 CMD_UPDATE))
2939 return;
2940
2941 /* statement-level triggers operate on the parent table */
2942 Assert(relinfo->ri_RootResultRelInfo == NULL);
2943
2944 updatedCols = ExecGetAllUpdatedCols(relinfo, estate);
2945
2949 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
2950 LocTriggerData.tg_updatedcols = updatedCols;
2951 for (i = 0; i < trigdesc->numtriggers; i++)
2952 {
2953 Trigger *trigger = &trigdesc->triggers[i];
2954 HeapTuple newtuple;
2955
2956 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
2960 continue;
2961 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
2962 updatedCols, NULL, NULL))
2963 continue;
2964
2965 LocTriggerData.tg_trigger = trigger;
2967 i,
2968 relinfo->ri_TrigFunctions,
2969 relinfo->ri_TrigInstrument,
2970 GetPerTupleMemoryContext(estate));
2971
2972 if (newtuple)
2973 ereport(ERROR,
2975 errmsg("BEFORE STATEMENT trigger cannot return a value")));
2976 }
2977}
2978
2979void
2981 TransitionCaptureState *transition_capture)
2982{
2983 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
2984
2985 /* statement-level triggers operate on the parent table */
2986 Assert(relinfo->ri_RootResultRelInfo == NULL);
2987
2988 if (trigdesc && trigdesc->trig_update_after_statement)
2991 false, NULL, NULL, NIL,
2993 transition_capture,
2994 false);
2995}
2996
2997bool
3004 TM_FailureData *tmfd,
3005 bool is_merge_update)
3006{
3007 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
3009 HeapTuple newtuple = NULL;
3011 bool should_free_trig = false;
3012 bool should_free_new = false;
3014 int i;
3015 Bitmapset *updatedCols;
3016 LockTupleMode lockmode;
3017
3018 /* Determine lock mode to use */
3019 lockmode = ExecUpdateLockMode(estate, relinfo);
3020
3022 if (fdw_trigtuple == NULL)
3023 {
3025
3026 /*
3027 * Get a copy of the on-disk tuple we are planning to update. In
3028 * general, if the tuple has been concurrently updated, we should
3029 * recheck it using EPQ. However, if this is a MERGE UPDATE action,
3030 * we skip this EPQ recheck and leave it to the caller (it must do
3031 * additional rechecking, and might end up executing a different
3032 * action entirely).
3033 */
3034 if (!GetTupleForTrigger(estate, epqstate, relinfo, tupleid,
3035 lockmode, oldslot, !is_merge_update,
3036 &epqslot_candidate, tmresult, tmfd))
3037 return false; /* cancel the update action */
3038
3039 /*
3040 * In READ COMMITTED isolation level it's possible that target tuple
3041 * was changed due to concurrent update. In that case we have a raw
3042 * subplan output tuple in epqslot_candidate, and need to form a new
3043 * insertable tuple using ExecGetUpdateNewTuple to replace the one we
3044 * received in newslot. Neither we nor our callers have any further
3045 * interest in the passed-in tuple, so it's okay to overwrite newslot
3046 * with the newer data.
3047 */
3048 if (epqslot_candidate != NULL)
3049 {
3051
3053 oldslot);
3054
3055 /*
3056 * Typically, the caller's newslot was also generated by
3057 * ExecGetUpdateNewTuple, so that epqslot_clean will be the same
3058 * slot and copying is not needed. But do the right thing if it
3059 * isn't.
3060 */
3063
3064 /*
3065 * At this point newslot contains a virtual tuple that may
3066 * reference some fields of oldslot's tuple in some disk buffer.
3067 * If that tuple is in a different page than the original target
3068 * tuple, then our only pin on that buffer is oldslot's, and we're
3069 * about to release it. Hence we'd better materialize newslot to
3070 * ensure it doesn't contain references into an unpinned buffer.
3071 * (We'd materialize it below anyway, but too late for safety.)
3072 */
3074 }
3075
3076 /*
3077 * Here we convert oldslot to a materialized slot holding trigtuple.
3078 * Neither slot passed to the triggers will hold any buffer pin.
3079 */
3081 }
3082 else
3083 {
3084 /* Put the FDW-supplied tuple into oldslot to unify the cases */
3087 }
3088
3093 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
3094 updatedCols = ExecGetAllUpdatedCols(relinfo, estate);
3095 LocTriggerData.tg_updatedcols = updatedCols;
3096 for (i = 0; i < trigdesc->numtriggers; i++)
3097 {
3098 Trigger *trigger = &trigdesc->triggers[i];
3099 HeapTuple oldtuple;
3100
3101 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
3105 continue;
3106 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
3107 updatedCols, oldslot, newslot))
3108 continue;
3109
3110 if (!newtuple)
3112
3113 LocTriggerData.tg_trigslot = oldslot;
3114 LocTriggerData.tg_trigtuple = trigtuple;
3115 LocTriggerData.tg_newtuple = oldtuple = newtuple;
3116 LocTriggerData.tg_newslot = newslot;
3117 LocTriggerData.tg_trigger = trigger;
3119 i,
3120 relinfo->ri_TrigFunctions,
3121 relinfo->ri_TrigInstrument,
3122 GetPerTupleMemoryContext(estate));
3123
3124 if (newtuple == NULL)
3125 {
3126 if (should_free_trig)
3128 if (should_free_new)
3129 heap_freetuple(oldtuple);
3130 return false; /* "do nothing" */
3131 }
3132 else if (newtuple != oldtuple)
3133 {
3134 newtuple = check_modified_virtual_generated(RelationGetDescr(relinfo->ri_RelationDesc), newtuple);
3135
3136 ExecForceStoreHeapTuple(newtuple, newslot, false);
3137
3138 /*
3139 * If the tuple returned by the trigger / being stored, is the old
3140 * row version, and the heap tuple passed to the trigger was
3141 * allocated locally, materialize the slot. Otherwise we might
3142 * free it while still referenced by the slot.
3143 */
3144 if (should_free_trig && newtuple == trigtuple)
3146
3147 if (should_free_new)
3148 heap_freetuple(oldtuple);
3149
3150 /* signal tuple should be re-fetched if used */
3151 newtuple = NULL;
3152 }
3153 }
3154 if (should_free_trig)
3156
3157 return true;
3158}
3159
3160/*
3161 * Note: 'src_partinfo' and 'dst_partinfo', when non-NULL, refer to the source
3162 * and destination partitions, respectively, of a cross-partition update of
3163 * the root partitioned table mentioned in the query, given by 'relinfo'.
3164 * 'tupleid' in that case refers to the ctid of the "old" tuple in the source
3165 * partition, and 'newslot' contains the "new" tuple in the destination
3166 * partition. This interface allows to support the requirements of
3167 * ExecCrossPartitionUpdateForeignKey(); is_crosspart_update must be true in
3168 * that case.
3169 */
3170void
3178 TransitionCaptureState *transition_capture,
3180{
3181 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
3182
3183 if (relinfo->ri_FdwRoutine && transition_capture &&
3184 (transition_capture->tcs_update_old_table ||
3185 transition_capture->tcs_update_new_table))
3186 {
3187 Assert(relinfo->ri_RootResultRelInfo);
3188 ereport(ERROR,
3190 errmsg("cannot collect transition tuples from child foreign tables")));
3191 }
3192
3193 if ((trigdesc && trigdesc->trig_update_after_row) ||
3194 (transition_capture &&
3195 (transition_capture->tcs_update_old_table ||
3196 transition_capture->tcs_update_new_table)))
3197 {
3198 /*
3199 * Note: if the UPDATE is converted into a DELETE+INSERT as part of
3200 * update-partition-key operation, then this function is also called
3201 * separately for DELETE and INSERT to capture transition table rows.
3202 * In such case, either old tuple or new tuple can be NULL.
3203 */
3206
3209
3212
3214 GetTupleForTrigger(estate,
3215 NULL,
3216 tupsrc,
3217 tupleid,
3219 oldslot,
3220 false,
3221 NULL,
3222 NULL,
3223 NULL);
3224 else if (fdw_trigtuple != NULL)
3226 else
3228
3232 true,
3235 transition_capture,
3237 }
3238}
3239
3240bool
3243{
3244 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
3246 HeapTuple newtuple = NULL;
3247 bool should_free;
3249 int i;
3250
3255 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
3256
3258
3259 for (i = 0; i < trigdesc->numtriggers; i++)
3260 {
3261 Trigger *trigger = &trigdesc->triggers[i];
3262 HeapTuple oldtuple;
3263
3264 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
3268 continue;
3269 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
3270 NULL, oldslot, newslot))
3271 continue;
3272
3273 if (!newtuple)
3274 newtuple = ExecFetchSlotHeapTuple(newslot, true, &should_free);
3275
3276 LocTriggerData.tg_trigslot = oldslot;
3277 LocTriggerData.tg_trigtuple = trigtuple;
3278 LocTriggerData.tg_newslot = newslot;
3279 LocTriggerData.tg_newtuple = oldtuple = newtuple;
3280
3281 LocTriggerData.tg_trigger = trigger;
3283 i,
3284 relinfo->ri_TrigFunctions,
3285 relinfo->ri_TrigInstrument,
3286 GetPerTupleMemoryContext(estate));
3287 if (newtuple == NULL)
3288 {
3289 return false; /* "do nothing" */
3290 }
3291 else if (newtuple != oldtuple)
3292 {
3293 ExecForceStoreHeapTuple(newtuple, newslot, false);
3294
3295 if (should_free)
3296 heap_freetuple(oldtuple);
3297
3298 /* signal tuple should be re-fetched if used */
3299 newtuple = NULL;
3300 }
3301 }
3302
3303 return true;
3304}
3305
3306void
3308{
3309 TriggerDesc *trigdesc;
3310 int i;
3312
3313 trigdesc = relinfo->ri_TrigDesc;
3314
3315 if (trigdesc == NULL)
3316 return;
3317 if (!trigdesc->trig_truncate_before_statement)
3318 return;
3319
3323 LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
3324
3325 for (i = 0; i < trigdesc->numtriggers; i++)
3326 {
3327 Trigger *trigger = &trigdesc->triggers[i];
3328 HeapTuple newtuple;
3329
3330 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
3334 continue;
3335 if (!TriggerEnabled(estate, relinfo, trigger, LocTriggerData.tg_event,
3336 NULL, NULL, NULL))
3337 continue;
3338
3339 LocTriggerData.tg_trigger = trigger;
3341 i,
3342 relinfo->ri_TrigFunctions,
3343 relinfo->ri_TrigInstrument,
3344 GetPerTupleMemoryContext(estate));
3345
3346 if (newtuple)
3347 ereport(ERROR,
3349 errmsg("BEFORE STATEMENT trigger cannot return a value")));
3350 }
3351}
3352
3353void
3355{
3356 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
3357
3358 if (trigdesc && trigdesc->trig_truncate_after_statement)
3360 NULL, NULL,
3362 false, NULL, NULL, NIL, NULL, NULL,
3363 false);
3364}
3365
3366
3367/*
3368 * Fetch tuple into "oldslot", dealing with locking and EPQ if necessary
3369 */
3370static bool
3372 EPQState *epqstate,
3374 ItemPointer tid,
3375 LockTupleMode lockmode,
3377 bool do_epq_recheck,
3381{
3382 Relation relation = relinfo->ri_RelationDesc;
3383
3384 if (epqslot != NULL)
3385 {
3387 TM_FailureData tmfd;
3388 int lockflags = 0;
3389
3390 *epqslot = NULL;
3391
3392 /* caller must pass an epqstate if EvalPlanQual is possible */
3393 Assert(epqstate != NULL);
3394
3395 /*
3396 * lock tuple for update
3397 */
3400 test = table_tuple_lock(relation, tid, estate->es_snapshot, oldslot,
3401 estate->es_output_cid,
3402 lockmode, LockWaitBlock,
3403 lockflags,
3404 &tmfd);
3405
3406 /* Let the caller know about the status of this operation */
3407 if (tmresultp)
3408 *tmresultp = test;
3409 if (tmfdp)
3410 *tmfdp = tmfd;
3411
3412 switch (test)
3413 {
3414 case TM_SelfModified:
3415
3416 /*
3417 * The target tuple was already updated or deleted by the
3418 * current command, or by a later command in the current
3419 * transaction. We ignore the tuple in the former case, and
3420 * throw error in the latter case, for the same reasons
3421 * enumerated in ExecUpdate and ExecDelete in
3422 * nodeModifyTable.c.
3423 */
3424 if (tmfd.cmax != estate->es_output_cid)
3425 ereport(ERROR,
3427 errmsg("tuple to be updated was already modified by an operation triggered by the current command"),
3428 errhint("Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
3429
3430 /* treat it as deleted; do not process */
3431 return false;
3432
3433 case TM_Ok:
3434 if (tmfd.traversed)
3435 {
3436 /*
3437 * Recheck the tuple using EPQ, if requested. Otherwise,
3438 * just return that it was concurrently updated.
3439 */
3440 if (do_epq_recheck)
3441 {
3442 *epqslot = EvalPlanQual(epqstate,
3443 relation,
3444 relinfo->ri_RangeTableIndex,
3445 oldslot);
3446
3447 /*
3448 * If PlanQual failed for updated tuple - we must not
3449 * process this tuple!
3450 */
3451 if (TupIsNull(*epqslot))
3452 {
3453 *epqslot = NULL;
3454 return false;
3455 }
3456 }
3457 else
3458 {
3459 if (tmresultp)
3461 return false;
3462 }
3463 }
3464 break;
3465
3466 case TM_Updated:
3468 ereport(ERROR,
3470 errmsg("could not serialize access due to concurrent update")));
3471 elog(ERROR, "unexpected table_tuple_lock status: %u", test);
3472 break;
3473
3474 case TM_Deleted:
3476 ereport(ERROR,
3478 errmsg("could not serialize access due to concurrent delete")));
3479 /* tuple was deleted */
3480 return false;
3481
3482 case TM_Invisible:
3483 elog(ERROR, "attempted to lock invisible tuple");
3484 break;
3485
3486 default:
3487 elog(ERROR, "unrecognized table_tuple_lock status: %u", test);
3488 return false; /* keep compiler quiet */
3489 }
3490 }
3491 else
3492 {
3493 /*
3494 * We expect the tuple to be present, thus very simple error handling
3495 * suffices.
3496 */
3497 if (!table_tuple_fetch_row_version(relation, tid, SnapshotAny,
3498 oldslot))
3499 elog(ERROR, "failed to fetch tuple for trigger");
3500 }
3501
3502 return true;
3503}
3504
3505/*
3506 * Is trigger enabled to fire?
3507 */
3508static bool
3513{
3514 /* Check replication-role-dependent enable state */
3516 {
3517 if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
3518 trigger->tgenabled == TRIGGER_DISABLED)
3519 return false;
3520 }
3521 else /* ORIGIN or LOCAL role */
3522 {
3523 if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
3524 trigger->tgenabled == TRIGGER_DISABLED)
3525 return false;
3526 }
3527
3528 /*
3529 * Check for column-specific trigger (only possible for UPDATE, and in
3530 * fact we *must* ignore tgattr for other event types)
3531 */
3532 if (trigger->tgnattr > 0 && TRIGGER_FIRED_BY_UPDATE(event))
3533 {
3534 int i;
3535 bool modified;
3536
3537 modified = false;
3538 for (i = 0; i < trigger->tgnattr; i++)
3539 {
3541 modifiedCols))
3542 {
3543 modified = true;
3544 break;
3545 }
3546 }
3547 if (!modified)
3548 return false;
3549 }
3550
3551 /* Check for WHEN clause */
3552 if (trigger->tgqual)
3553 {
3555 ExprContext *econtext;
3557 int i;
3558
3559 Assert(estate != NULL);
3560
3561 /*
3562 * trigger is an element of relinfo->ri_TrigDesc->triggers[]; find the
3563 * matching element of relinfo->ri_TrigWhenExprs[]
3564 */
3565 i = trigger - relinfo->ri_TrigDesc->triggers;
3566 predicate = &relinfo->ri_TrigWhenExprs[i];
3567
3568 /*
3569 * If first time through for this WHEN expression, build expression
3570 * nodetrees for it. Keep them in the per-query memory context so
3571 * they'll survive throughout the query.
3572 */
3573 if (*predicate == NULL)
3574 {
3575 Node *tgqual;
3576
3578 tgqual = stringToNode(trigger->tgqual);
3579 tgqual = expand_generated_columns_in_expr(tgqual, relinfo->ri_RelationDesc, PRS2_OLD_VARNO);
3580 tgqual = expand_generated_columns_in_expr(tgqual, relinfo->ri_RelationDesc, PRS2_NEW_VARNO);
3581 /* Change references to OLD and NEW to INNER_VAR and OUTER_VAR */
3584 /* ExecPrepareQual wants implicit-AND form */
3585 tgqual = (Node *) make_ands_implicit((Expr *) tgqual);
3586 *predicate = ExecPrepareQual((List *) tgqual, estate);
3588 }
3589
3590 /*
3591 * We will use the EState's per-tuple context for evaluating WHEN
3592 * expressions (creating it if it's not already there).
3593 */
3594 econtext = GetPerTupleExprContext(estate);
3595
3596 /*
3597 * Finally evaluate the expression, making the old and/or new tuples
3598 * available as INNER_VAR/OUTER_VAR respectively.
3599 */
3600 econtext->ecxt_innertuple = oldslot;
3601 econtext->ecxt_outertuple = newslot;
3602 if (!ExecQual(*predicate, econtext))
3603 return false;
3604 }
3605
3606 return true;
3607}
3608
3609
3610/* ----------
3611 * After-trigger stuff
3612 *
3613 * The AfterTriggersData struct holds data about pending AFTER trigger events
3614 * during the current transaction tree. (BEFORE triggers are fired
3615 * immediately so we don't need any persistent state about them.) The struct
3616 * and most of its subsidiary data are kept in TopTransactionContext; however
3617 * some data that can be discarded sooner appears in the CurTransactionContext
3618 * of the relevant subtransaction. Also, the individual event records are
3619 * kept in a separate sub-context of TopTransactionContext. This is done
3620 * mainly so that it's easy to tell from a memory context dump how much space
3621 * is being eaten by trigger events.
3622 *
3623 * Because the list of pending events can grow large, we go to some
3624 * considerable effort to minimize per-event memory consumption. The event
3625 * records are grouped into chunks and common data for similar events in the
3626 * same chunk is only stored once.
3627 *
3628 * XXX We need to be able to save the per-event data in a file if it grows too
3629 * large.
3630 * ----------
3631 */
3632
3633/* Per-trigger SET CONSTRAINT status */
3639
3641
3642/*
3643 * SET CONSTRAINT intra-transaction status.
3644 *
3645 * We make this a single palloc'd object so it can be copied and freed easily.
3646 *
3647 * all_isset and all_isdeferred are used to keep track
3648 * of SET CONSTRAINTS ALL {DEFERRED, IMMEDIATE}.
3649 *
3650 * trigstates[] stores per-trigger tgisdeferred settings.
3651 */
3653{
3656 int numstates; /* number of trigstates[] entries in use */
3657 int numalloc; /* allocated size of trigstates[] */
3660
3662
3663
3664/*
3665 * Per-trigger-event data
3666 *
3667 * The actual per-event data, AfterTriggerEventData, includes DONE/IN_PROGRESS
3668 * status bits, up to two tuple CTIDs, and optionally two OIDs of partitions.
3669 * Each event record also has an associated AfterTriggerSharedData that is
3670 * shared across all instances of similar events within a "chunk".
3671 *
3672 * For row-level triggers, we arrange not to waste storage on unneeded ctid
3673 * fields. Updates of regular tables use two; inserts and deletes of regular
3674 * tables use one; foreign tables always use zero and save the tuple(s) to a
3675 * tuplestore. AFTER_TRIGGER_FDW_FETCH directs AfterTriggerExecute() to
3676 * retrieve a fresh tuple or pair of tuples from that tuplestore, while
3677 * AFTER_TRIGGER_FDW_REUSE directs it to use the most-recently-retrieved
3678 * tuple(s). This permits storing tuples once regardless of the number of
3679 * row-level triggers on a foreign table.
3680 *
3681 * When updates on partitioned tables cause rows to move between partitions,
3682 * the OIDs of both partitions are stored too, so that the tuples can be
3683 * fetched; such entries are marked AFTER_TRIGGER_CP_UPDATE (for "cross-
3684 * partition update").
3685 *
3686 * Note that we need triggers on foreign tables to be fired in exactly the
3687 * order they were queued, so that the tuples come out of the tuplestore in
3688 * the right order. To ensure that, we forbid deferrable (constraint)
3689 * triggers on foreign tables. This also ensures that such triggers do not
3690 * get deferred into outer trigger query levels, meaning that it's okay to
3691 * destroy the tuplestore at the end of the query level.
3692 *
3693 * Statement-level triggers always bear AFTER_TRIGGER_1CTID, though they
3694 * require no ctid field. We lack the flag bit space to neatly represent that
3695 * distinct case, and it seems unlikely to be worth much trouble.
3696 *
3697 * Note: ats_firing_id is initially zero and is set to something else when
3698 * AFTER_TRIGGER_IN_PROGRESS is set. It indicates which trigger firing
3699 * cycle the trigger will be fired in (or was fired in, if DONE is set).
3700 * Although this is mutable state, we can keep it in AfterTriggerSharedData
3701 * because all instances of the same type of event in a given event list will
3702 * be fired at the same time, if they were queued between the same firing
3703 * cycles. So we need only ensure that ats_firing_id is zero when attaching
3704 * a new event to an existing AfterTriggerSharedData record.
3705 */
3707
3708#define AFTER_TRIGGER_OFFSET 0x07FFFFFF /* must be low-order bits */
3709#define AFTER_TRIGGER_DONE 0x80000000
3710#define AFTER_TRIGGER_IN_PROGRESS 0x40000000
3711/* bits describing the size and tuple sources of this event */
3712#define AFTER_TRIGGER_FDW_REUSE 0x00000000
3713#define AFTER_TRIGGER_FDW_FETCH 0x20000000
3714#define AFTER_TRIGGER_1CTID 0x10000000
3715#define AFTER_TRIGGER_2CTID 0x30000000
3716#define AFTER_TRIGGER_CP_UPDATE 0x08000000
3717#define AFTER_TRIGGER_TUP_BITS 0x38000000
3719
3721{
3722 TriggerEvent ats_event; /* event type indicator, see trigger.h */
3723 Oid ats_tgoid; /* the trigger's ID */
3724 Oid ats_relid; /* the relation it's on */
3725 Oid ats_rolid; /* role to execute the trigger */
3726 CommandId ats_firing_id; /* ID for firing cycle */
3727 struct AfterTriggersTableData *ats_table; /* transition table access */
3728 Bitmapset *ats_modifiedcols; /* modified columns */
3730
3732
3734{
3735 TriggerFlags ate_flags; /* status bits and offset to shared data */
3736 ItemPointerData ate_ctid1; /* inserted, deleted, or old updated tuple */
3737 ItemPointerData ate_ctid2; /* new updated tuple */
3738
3739 /*
3740 * During a cross-partition update of a partitioned table, we also store
3741 * the OIDs of source and destination partitions that are needed to fetch
3742 * the old (ctid1) and the new tuple (ctid2) from, respectively.
3743 */
3747
3748/* AfterTriggerEventData, minus ate_src_part, ate_dst_part */
3755
3756/* AfterTriggerEventData, minus ate_*_part and ate_ctid2 */
3758{
3759 TriggerFlags ate_flags; /* status bits and offset to shared data */
3760 ItemPointerData ate_ctid1; /* inserted, deleted, or old updated tuple */
3762
3763/* AfterTriggerEventData, minus ate_*_part, ate_ctid1 and ate_ctid2 */
3765{
3766 TriggerFlags ate_flags; /* status bits and offset to shared data */
3768
3769#define SizeofTriggerEvent(evt) \
3770 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_CP_UPDATE ? \
3771 sizeof(AfterTriggerEventData) : \
3772 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_2CTID ? \
3773 sizeof(AfterTriggerEventDataNoOids) : \
3774 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_1CTID ? \
3775 sizeof(AfterTriggerEventDataOneCtid) : \
3776 sizeof(AfterTriggerEventDataZeroCtids))))
3777
3778#define GetTriggerSharedData(evt) \
3779 ((AfterTriggerShared) ((char *) (evt) + ((evt)->ate_flags & AFTER_TRIGGER_OFFSET)))
3780
3781/*
3782 * To avoid palloc overhead, we keep trigger events in arrays in successively-
3783 * larger chunks (a slightly more sophisticated version of an expansible
3784 * array). The space between CHUNK_DATA_START and freeptr is occupied by
3785 * AfterTriggerEventData records; the space between endfree and endptr is
3786 * occupied by AfterTriggerSharedData records.
3787 */
3789{
3790 struct AfterTriggerEventChunk *next; /* list link */
3791 char *freeptr; /* start of free space in chunk */
3792 char *endfree; /* end of free space in chunk */
3793 char *endptr; /* end of chunk */
3794 /* event data follows here */
3796
3797#define CHUNK_DATA_START(cptr) ((char *) (cptr) + MAXALIGN(sizeof(AfterTriggerEventChunk)))
3798
3799/* A list of events */
3806
3807/* Macros to help in iterating over a list of events */
3808#define for_each_chunk(cptr, evtlist) \
3809 for (cptr = (evtlist).head; cptr != NULL; cptr = cptr->next)
3810#define for_each_event(eptr, cptr) \
3811 for (eptr = (AfterTriggerEvent) CHUNK_DATA_START(cptr); \
3812 (char *) eptr < (cptr)->freeptr; \
3813 eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
3814/* Use this if no special per-chunk processing is needed */
3815#define for_each_event_chunk(eptr, cptr, evtlist) \
3816 for_each_chunk(cptr, evtlist) for_each_event(eptr, cptr)
3817
3818/* Macros for iterating from a start point that might not be list start */
3819#define for_each_chunk_from(cptr) \
3820 for (; cptr != NULL; cptr = cptr->next)
3821#define for_each_event_from(eptr, cptr) \
3822 for (; \
3823 (char *) eptr < (cptr)->freeptr; \
3824 eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
3825
3826
3827/*
3828 * All per-transaction data for the AFTER TRIGGERS module.
3829 *
3830 * AfterTriggersData has the following fields:
3831 *
3832 * firing_counter is incremented for each call of afterTriggerInvokeEvents.
3833 * We mark firable events with the current firing cycle's ID so that we can
3834 * tell which ones to work on. This ensures sane behavior if a trigger
3835 * function chooses to do SET CONSTRAINTS: the inner SET CONSTRAINTS will
3836 * only fire those events that weren't already scheduled for firing.
3837 *
3838 * state keeps track of the transaction-local effects of SET CONSTRAINTS.
3839 * This is saved and restored across failed subtransactions.
3840 *
3841 * events is the current list of deferred events. This is global across
3842 * all subtransactions of the current transaction. In a subtransaction
3843 * abort, we know that the events added by the subtransaction are at the
3844 * end of the list, so it is relatively easy to discard them. The event
3845 * list chunks themselves are stored in event_cxt.
3846 *
3847 * query_depth is the current depth of nested AfterTriggerBeginQuery calls
3848 * (-1 when the stack is empty).
3849 *
3850 * query_stack[query_depth] is the per-query-level data, including these fields:
3851 *
3852 * events is a list of AFTER trigger events queued by the current query.
3853 * None of these are valid until the matching AfterTriggerEndQuery call
3854 * occurs. At that point we fire immediate-mode triggers, and append any
3855 * deferred events to the main events list.
3856 *
3857 * fdw_tuplestore is a tuplestore containing the foreign-table tuples
3858 * needed by events queued by the current query. (Note: we use just one
3859 * tuplestore even though more than one foreign table might be involved.
3860 * This is okay because tuplestores don't really care what's in the tuples
3861 * they store; but it's possible that someday it'd break.)
3862 *
3863 * tables is a List of AfterTriggersTableData structs for target tables
3864 * of the current query (see below).
3865 *
3866 * maxquerydepth is just the allocated length of query_stack.
3867 *
3868 * trans_stack holds per-subtransaction data, including these fields:
3869 *
3870 * state is NULL or a pointer to a saved copy of the SET CONSTRAINTS
3871 * state data. Each subtransaction level that modifies that state first
3872 * saves a copy, which we use to restore the state if we abort.
3873 *
3874 * events is a copy of the events head/tail pointers,
3875 * which we use to restore those values during subtransaction abort.
3876 *
3877 * query_depth is the subtransaction-start-time value of query_depth,
3878 * which we similarly use to clean up at subtransaction abort.
3879 *
3880 * firing_counter is the subtransaction-start-time value of firing_counter.
3881 * We use this to recognize which deferred triggers were fired (or marked
3882 * for firing) within an aborted subtransaction.
3883 *
3884 * We use GetCurrentTransactionNestLevel() to determine the correct array
3885 * index in trans_stack. maxtransdepth is the number of allocated entries in
3886 * trans_stack. (By not keeping our own stack pointer, we can avoid trouble
3887 * in cases where errors during subxact abort cause multiple invocations
3888 * of AfterTriggerEndSubXact() at the same nesting depth.)
3889 *
3890 * We create an AfterTriggersTableData struct for each target table of the
3891 * current query, and each operation mode (INSERT/UPDATE/DELETE), that has
3892 * either transition tables or statement-level triggers. This is used to
3893 * hold the relevant transition tables, as well as info tracking whether
3894 * we already queued the statement triggers. (We use that info to prevent
3895 * firing the same statement triggers more than once per statement, or really
3896 * once per transition table set.) These structs, along with the transition
3897 * table tuplestores, live in the (sub)transaction's CurTransactionContext.
3898 * That's sufficient lifespan because we don't allow transition tables to be
3899 * used by deferrable triggers, so they only need to survive until
3900 * AfterTriggerEndQuery.
3901 */
3905
3906typedef struct AfterTriggersData
3907{
3908 CommandId firing_counter; /* next firing ID to assign */
3909 SetConstraintState state; /* the active S C state */
3910 AfterTriggerEventList events; /* deferred-event list */
3911 MemoryContext event_cxt; /* memory context for events, if any */
3912
3913 /* per-query-level data: */
3914 AfterTriggersQueryData *query_stack; /* array of structs shown below */
3915 int query_depth; /* current index in above array */
3916 int maxquerydepth; /* allocated len of above array */
3917
3918 /* per-subtransaction-level data: */
3919 AfterTriggersTransData *trans_stack; /* array of structs shown below */
3920 int maxtransdepth; /* allocated len of above array */
3921
3922 List *batch_callbacks; /* List of AfterTriggerCallbackItem; for
3923 * deferred constraints */
3924 bool firing_batch_callbacks; /* true when in
3925 * FireAfterTriggerBatchCallbacks() */
3926
3927 /*
3928 * Incremented around the trigger-firing loops in AfterTriggerEndQuery,
3929 * AfterTriggerFireDeferred, and AfterTriggerSetState. Used by
3930 * AfterTriggerIsActive() to signal that after-trigger firing is active.
3931 */
3934
3936{
3937 AfterTriggerEventList events; /* events pending from this query */
3938 Tuplestorestate *fdw_tuplestore; /* foreign tuples for said events */
3939 List *tables; /* list of AfterTriggersTableData, see below */
3940 List *batch_callbacks; /* List of AfterTriggerCallbackItem */
3941};
3942
3944{
3945 /* these fields are just for resetting at subtrans abort: */
3946 SetConstraintState state; /* saved S C state, or NULL if not yet saved */
3947 AfterTriggerEventList events; /* saved list pointer */
3948 int query_depth; /* saved query_depth */
3949 CommandId firing_counter; /* saved firing_counter */
3950};
3951
3953{
3954 /* relid + cmdType form the lookup key for these structs: */
3955 Oid relid; /* target table's OID */
3956 CmdType cmdType; /* event type, CMD_INSERT/UPDATE/DELETE */
3957 bool closed; /* true when no longer OK to add tuples */
3958 bool before_trig_done; /* did we already queue BS triggers? */
3959 bool after_trig_done; /* did we already queue AS triggers? */
3960 AfterTriggerEventList after_trig_events; /* if so, saved list pointer */
3961
3962 /* "old" transition table for UPDATE/DELETE, if any */
3964 /* "new" transition table for INSERT/UPDATE, if any */
3966
3967 TupleTableSlot *storeslot; /* for converting to tuplestore's format */
3968};
3969
3970/* Entry in afterTriggers.batch_callbacks */
3976
3978
3979static void AfterTriggerExecute(EState *estate,
3980 AfterTriggerEvent event,
3984 TriggerDesc *trigdesc,
3985 FmgrInfo *finfo,
3991 CmdType cmdType);
3993 TupleDesc tupdesc);
3997 TransitionCaptureState *transition_capture);
3998static void TransitionTableAddTuple(EState *estate,
3999 int event,
4000 TransitionCaptureState *transition_capture,
4002 TupleTableSlot *slot,
4004 Tuplestorestate *tuplestore);
4006static SetConstraintState SetConstraintStateCreate(int numalloc);
4009 Oid tgoid, bool tgisdeferred);
4010static void cancel_prior_stmt_triggers(Oid relid, CmdType cmdType, int tgevent);
4011
4012static void FireAfterTriggerBatchCallbacks(List *callbacks);
4013
4014/*
4015 * Get the FDW tuplestore for the current trigger query level, creating it
4016 * if necessary.
4017 */
4018static Tuplestorestate *
4020{
4021 Tuplestorestate *ret;
4022
4024 if (ret == NULL)
4025 {
4028
4029 /*
4030 * Make the tuplestore valid until end of subtransaction. We really
4031 * only need it until AfterTriggerEndQuery().
4032 */
4036
4037 ret = tuplestore_begin_heap(false, false, work_mem);
4038
4041
4043 }
4044
4045 return ret;
4046}
4047
4048/* ----------
4049 * afterTriggerCheckState()
4050 *
4051 * Returns true if the trigger event is actually in state DEFERRED.
4052 * ----------
4053 */
4054static bool
4056{
4057 Oid tgoid = evtshared->ats_tgoid;
4059 int i;
4060
4061 /*
4062 * For not-deferrable triggers (i.e. normal AFTER ROW triggers and
4063 * constraints declared NOT DEFERRABLE), the state is always false.
4064 */
4065 if ((evtshared->ats_event & AFTER_TRIGGER_DEFERRABLE) == 0)
4066 return false;
4067
4068 /*
4069 * If constraint state exists, SET CONSTRAINTS might have been executed
4070 * either for this trigger or for all triggers.
4071 */
4072 if (state != NULL)
4073 {
4074 /* Check for SET CONSTRAINTS for this specific trigger. */
4075 for (i = 0; i < state->numstates; i++)
4076 {
4077 if (state->trigstates[i].sct_tgoid == tgoid)
4078 return state->trigstates[i].sct_tgisdeferred;
4079 }
4080
4081 /* Check for SET CONSTRAINTS ALL. */
4082 if (state->all_isset)
4083 return state->all_isdeferred;
4084 }
4085
4086 /*
4087 * Otherwise return the default state for the trigger.
4088 */
4089 return ((evtshared->ats_event & AFTER_TRIGGER_INITDEFERRED) != 0);
4090}
4091
4092/* ----------
4093 * afterTriggerCopyBitmap()
4094 *
4095 * Copy bitmap into AfterTriggerEvents memory context, which is where the after
4096 * trigger events are kept.
4097 * ----------
4098 */
4099static Bitmapset *
4101{
4102 Bitmapset *dst;
4104
4105 if (src == NULL)
4106 return NULL;
4107
4109
4110 dst = bms_copy(src);
4111
4113
4114 return dst;
4115}
4116
4117/* ----------
4118 * afterTriggerAddEvent()
4119 *
4120 * Add a new trigger event to the specified queue.
4121 * The passed-in event data is copied.
4122 * ----------
4123 */
4124static void
4127{
4133
4134 /*
4135 * If empty list or not enough room in the tail chunk, make a new chunk.
4136 * We assume here that a new shared record will always be needed.
4137 */
4138 chunk = events->tail;
4139 if (chunk == NULL ||
4140 chunk->endfree - chunk->freeptr < needed)
4141 {
4143
4144 /* Create event context if we didn't already */
4148 "AfterTriggerEvents",
4150
4151 /*
4152 * Chunk size starts at 1KB and is allowed to increase up to 1MB.
4153 * These numbers are fairly arbitrary, though there is a hard limit at
4154 * AFTER_TRIGGER_OFFSET; else we couldn't link event records to their
4155 * shared records using the available space in ate_flags. Another
4156 * constraint is that if the chunk size gets too huge, the search loop
4157 * below would get slow given a (not too common) usage pattern with
4158 * many distinct event types in a chunk. Therefore, we double the
4159 * preceding chunk size only if there weren't too many shared records
4160 * in the preceding chunk; otherwise we halve it. This gives us some
4161 * ability to adapt to the actual usage pattern of the current query
4162 * while still having large chunk sizes in typical usage. All chunk
4163 * sizes used should be MAXALIGN multiples, to ensure that the shared
4164 * records will be aligned safely.
4165 */
4166#define MIN_CHUNK_SIZE 1024
4167#define MAX_CHUNK_SIZE (1024*1024)
4168
4169#if MAX_CHUNK_SIZE > (AFTER_TRIGGER_OFFSET+1)
4170#error MAX_CHUNK_SIZE must not exceed AFTER_TRIGGER_OFFSET
4171#endif
4172
4173 if (chunk == NULL)
4175 else
4176 {
4177 /* preceding chunk size... */
4178 chunksize = chunk->endptr - (char *) chunk;
4179 /* check number of shared records in preceding chunk */
4180 if ((chunk->endptr - chunk->endfree) <=
4181 (100 * sizeof(AfterTriggerSharedData)))
4182 chunksize *= 2; /* okay, double it */
4183 else
4184 chunksize /= 2; /* too many shared records */
4186 }
4188 chunk->next = NULL;
4189 chunk->freeptr = CHUNK_DATA_START(chunk);
4190 chunk->endptr = chunk->endfree = (char *) chunk + chunksize;
4191 Assert(chunk->endfree - chunk->freeptr >= needed);
4192
4193 if (events->tail == NULL)
4194 {
4195 Assert(events->head == NULL);
4196 events->head = chunk;
4197 }
4198 else
4199 events->tail->next = chunk;
4200 events->tail = chunk;
4201 /* events->tailfree is now out of sync, but we'll fix it below */
4202 }
4203
4204 /*
4205 * Try to locate a matching shared-data record already in the chunk. If
4206 * none, make a new one. The search begins with the most recently added
4207 * record, since newer ones are most likely to match.
4208 */
4209 for (newshared = (AfterTriggerShared) chunk->endfree;
4210 (char *) newshared < chunk->endptr;
4211 newshared++)
4212 {
4213 /* compare fields roughly by probability of them being different */
4214 if (newshared->ats_tgoid == evtshared->ats_tgoid &&
4215 newshared->ats_event == evtshared->ats_event &&
4216 newshared->ats_firing_id == 0 &&
4217 newshared->ats_table == evtshared->ats_table &&
4218 newshared->ats_relid == evtshared->ats_relid &&
4219 newshared->ats_rolid == evtshared->ats_rolid &&
4220 bms_equal(newshared->ats_modifiedcols,
4221 evtshared->ats_modifiedcols))
4222 break;
4223 }
4224 if ((char *) newshared >= chunk->endptr)
4225 {
4226 newshared = ((AfterTriggerShared) chunk->endfree) - 1;
4227 *newshared = *evtshared;
4228 /* now we must make a suitably-long-lived copy of the bitmap */
4229 newshared->ats_modifiedcols = afterTriggerCopyBitmap(evtshared->ats_modifiedcols);
4230 newshared->ats_firing_id = 0; /* just to be sure */
4231 chunk->endfree = (char *) newshared;
4232 }
4233
4234 /* Insert the data */
4235 newevent = (AfterTriggerEvent) chunk->freeptr;
4236 memcpy(newevent, event, eventsize);
4237 /* ... and link the new event to its shared record */
4238 newevent->ate_flags &= ~AFTER_TRIGGER_OFFSET;
4239 newevent->ate_flags |= (char *) newshared - (char *) newevent;
4240
4241 chunk->freeptr += eventsize;
4242 events->tailfree = chunk->freeptr;
4243}
4244
4245/* ----------
4246 * afterTriggerFreeEventList()
4247 *
4248 * Free all the event storage in the given list.
4249 * ----------
4250 */
4251static void
4253{
4255
4256 while ((chunk = events->head) != NULL)
4257 {
4258 events->head = chunk->next;
4259 pfree(chunk);
4260 }
4261 events->tail = NULL;
4262 events->tailfree = NULL;
4263}
4264
4265/* ----------
4266 * afterTriggerRestoreEventList()
4267 *
4268 * Restore an event list to its prior length, removing all the events
4269 * added since it had the value old_events.
4270 * ----------
4271 */
4272static void
4275{
4278
4279 if (old_events->tail == NULL)
4280 {
4281 /* restoring to a completely empty state, so free everything */
4283 }
4284 else
4285 {
4286 *events = *old_events;
4287 /* free any chunks after the last one we want to keep */
4288 for (chunk = events->tail->next; chunk != NULL; chunk = next_chunk)
4289 {
4290 next_chunk = chunk->next;
4291 pfree(chunk);
4292 }
4293 /* and clean up the tail chunk to be the right length */
4294 events->tail->next = NULL;
4295 events->tail->freeptr = events->tailfree;
4296
4297 /*
4298 * We don't make any effort to remove now-unused shared data records.
4299 * They might still be useful, anyway.
4300 */
4301 }
4302}
4303
4304/* ----------
4305 * afterTriggerDeleteHeadEventChunk()
4306 *
4307 * Remove the first chunk of events from the query level's event list.
4308 * Keep any event list pointers elsewhere in the query level's data
4309 * structures in sync.
4310 * ----------
4311 */
4312static void
4314{
4315 AfterTriggerEventChunk *target = qs->events.head;
4316 ListCell *lc;
4317
4318 Assert(target && target->next);
4319
4320 /*
4321 * First, update any pointers in the per-table data, so that they won't be
4322 * dangling. Resetting obsoleted pointers to NULL will make
4323 * cancel_prior_stmt_triggers start from the list head, which is fine.
4324 */
4325 foreach(lc, qs->tables)
4326 {
4328
4329 if (table->after_trig_done &&
4330 table->after_trig_events.tail == target)
4331 {
4332 table->after_trig_events.head = NULL;
4333 table->after_trig_events.tail = NULL;
4334 table->after_trig_events.tailfree = NULL;
4335 }
4336 }
4337
4338 /* Now we can flush the head chunk */
4339 qs->events.head = target->next;
4340 pfree(target);
4341}
4342
4343
4344/* ----------
4345 * AfterTriggerExecute()
4346 *
4347 * Fetch the required tuples back from the heap and fire one
4348 * single trigger function.
4349 *
4350 * Frequently, this will be fired many times in a row for triggers of
4351 * a single relation. Therefore, we cache the open relation and provide
4352 * fmgr lookup cache space at the caller level. (For triggers fired at
4353 * the end of a query, we can even piggyback on the executor's state.)
4354 *
4355 * When fired for a cross-partition update of a partitioned table, the old
4356 * tuple is fetched using 'src_relInfo' (the source leaf partition) and
4357 * the new tuple using 'dst_relInfo' (the destination leaf partition), though
4358 * both are converted into the root partitioned table's format before passing
4359 * to the trigger function.
4360 *
4361 * event: event currently being fired.
4362 * relInfo: result relation for event.
4363 * src_relInfo: source partition of a cross-partition update
4364 * dst_relInfo: its destination partition
4365 * trigdesc: working copy of rel's trigger info.
4366 * finfo: array of fmgr lookup cache entries (one per trigger in trigdesc).
4367 * instr: array of EXPLAIN ANALYZE instrumentation nodes (one per trigger),
4368 * or NULL if no instrumentation is wanted.
4369 * per_tuple_context: memory context to call trigger function in.
4370 * trig_tuple_slot1: scratch slot for tg_trigtuple (foreign tables only)
4371 * trig_tuple_slot2: scratch slot for tg_newtuple (foreign tables only)
4372 * ----------
4373 */
4374static void
4376 AfterTriggerEvent event,
4380 TriggerDesc *trigdesc,
4381 FmgrInfo *finfo, TriggerInstrumentation *instr,
4385{
4386 Relation rel = relInfo->ri_RelationDesc;
4387 Relation src_rel = src_relInfo->ri_RelationDesc;
4388 Relation dst_rel = dst_relInfo->ri_RelationDesc;
4390 Oid tgoid = evtshared->ats_tgoid;
4393 int save_sec_context;
4395 int tgindx;
4396 bool should_free_trig = false;
4397 bool should_free_new = false;
4398
4399 /*
4400 * Locate trigger in trigdesc. It might not be present, and in fact the
4401 * trigdesc could be NULL, if the trigger was dropped since the event was
4402 * queued. In that case, silently do nothing.
4403 */
4404 if (trigdesc == NULL)
4405 return;
4406 for (tgindx = 0; tgindx < trigdesc->numtriggers; tgindx++)
4407 {
4408 if (trigdesc->triggers[tgindx].tgoid == tgoid)
4409 {
4410 LocTriggerData.tg_trigger = &(trigdesc->triggers[tgindx]);
4411 break;
4412 }
4413 }
4414 if (LocTriggerData.tg_trigger == NULL)
4415 return;
4416
4417 /*
4418 * If doing EXPLAIN ANALYZE, start charging time to this trigger. We want
4419 * to include time spent re-fetching tuples in the trigger cost.
4420 */
4421 if (instr)
4422 InstrStartTrigger(instr + tgindx);
4423
4424 /*
4425 * Fetch the required tuple(s).
4426 */
4427 switch (event->ate_flags & AFTER_TRIGGER_TUP_BITS)
4428 {
4430 {
4431 Tuplestorestate *fdw_tuplestore = GetCurrentFDWTuplestore();
4432
4433 if (!tuplestore_gettupleslot(fdw_tuplestore, true, false,
4435 elog(ERROR, "failed to fetch tuple1 for AFTER trigger");
4436
4437 if ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) ==
4439 !tuplestore_gettupleslot(fdw_tuplestore, true, false,
4441 elog(ERROR, "failed to fetch tuple2 for AFTER trigger");
4442 }
4445
4446 /*
4447 * Store tuple in the slot so that tg_trigtuple does not reference
4448 * tuplestore memory. (It is formally possible for the trigger
4449 * function to queue trigger events that add to the same
4450 * tuplestore, which can push other tuples out of memory.) The
4451 * distinction is academic, because we start with a minimal tuple
4452 * that is stored as a heap tuple, constructed in different memory
4453 * context, in the slot anyway.
4454 */
4455 LocTriggerData.tg_trigslot = trig_tuple_slot1;
4456 LocTriggerData.tg_trigtuple =
4458
4459 if ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) ==
4461 {
4462 LocTriggerData.tg_newslot = trig_tuple_slot2;
4463 LocTriggerData.tg_newtuple =
4465 }
4466 else
4467 {
4468 LocTriggerData.tg_newtuple = NULL;
4469 }
4470 break;
4471
4472 default:
4473 if (ItemPointerIsValid(&(event->ate_ctid1)))
4474 {
4476 src_relInfo);
4477
4479 &(event->ate_ctid1),
4481 src_slot))
4482 elog(ERROR, "failed to fetch tuple1 for AFTER trigger");
4483
4484 /*
4485 * Store the tuple fetched from the source partition into the
4486 * target (root partitioned) table slot, converting if needed.
4487 */
4488 if (src_relInfo != relInfo)
4489 {
4491
4492 LocTriggerData.tg_trigslot = ExecGetTriggerOldSlot(estate, relInfo);
4493 if (map)
4494 {
4496 src_slot,
4497 LocTriggerData.tg_trigslot);
4498 }
4499 else
4500 ExecCopySlot(LocTriggerData.tg_trigslot, src_slot);
4501 }
4502 else
4503 LocTriggerData.tg_trigslot = src_slot;
4504 LocTriggerData.tg_trigtuple =
4506 }
4507 else
4508 {
4509 LocTriggerData.tg_trigtuple = NULL;
4510 }
4511
4512 /* don't touch ctid2 if not there */
4514 (event->ate_flags & AFTER_TRIGGER_CP_UPDATE)) &&
4515 ItemPointerIsValid(&(event->ate_ctid2)))
4516 {
4518 dst_relInfo);
4519
4521 &(event->ate_ctid2),
4523 dst_slot))
4524 elog(ERROR, "failed to fetch tuple2 for AFTER trigger");
4525
4526 /*
4527 * Store the tuple fetched from the destination partition into
4528 * the target (root partitioned) table slot, converting if
4529 * needed.
4530 */
4531 if (dst_relInfo != relInfo)
4532 {
4534
4535 LocTriggerData.tg_newslot = ExecGetTriggerNewSlot(estate, relInfo);
4536 if (map)
4537 {
4539 dst_slot,
4540 LocTriggerData.tg_newslot);
4541 }
4542 else
4544 }
4545 else
4546 LocTriggerData.tg_newslot = dst_slot;
4547 LocTriggerData.tg_newtuple =
4549 }
4550 else
4551 {
4552 LocTriggerData.tg_newtuple = NULL;
4553 }
4554 }
4555
4556 /*
4557 * Set up the tuplestore information to let the trigger have access to
4558 * transition tables. When we first make a transition table available to
4559 * a trigger, mark it "closed" so that it cannot change anymore. If any
4560 * additional events of the same type get queued in the current trigger
4561 * query level, they'll go into new transition tables.
4562 */
4563 LocTriggerData.tg_oldtable = LocTriggerData.tg_newtable = NULL;
4564 if (evtshared->ats_table)
4565 {
4566 if (LocTriggerData.tg_trigger->tgoldtable)
4567 {
4568 LocTriggerData.tg_oldtable = evtshared->ats_table->old_tuplestore;
4569 evtshared->ats_table->closed = true;
4570 }
4571
4572 if (LocTriggerData.tg_trigger->tgnewtable)
4573 {
4574 LocTriggerData.tg_newtable = evtshared->ats_table->new_tuplestore;
4575 evtshared->ats_table->closed = true;
4576 }
4577 }
4578
4579 /*
4580 * Setup the remaining trigger information
4581 */
4583 LocTriggerData.tg_event =
4585 LocTriggerData.tg_relation = rel;
4586 if (TRIGGER_FOR_UPDATE(LocTriggerData.tg_trigger->tgtype))
4587 LocTriggerData.tg_updatedcols = evtshared->ats_modifiedcols;
4588
4590
4591 /*
4592 * If necessary, become the role that was active when the trigger got
4593 * queued. Note that the role might have been dropped since the trigger
4594 * was queued, but if that is a problem, we will get an error later.
4595 * Checking here would still leave a race condition.
4596 */
4597 GetUserIdAndSecContext(&save_rolid, &save_sec_context);
4598 if (save_rolid != evtshared->ats_rolid)
4600 save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
4601
4602 /*
4603 * Call the trigger and throw away any possibly returned updated tuple.
4604 * (Don't let ExecCallTriggerFunc measure EXPLAIN time.)
4605 */
4607 tgindx,
4608 finfo,
4609 NULL,
4611 if (rettuple != NULL &&
4612 rettuple != LocTriggerData.tg_trigtuple &&
4613 rettuple != LocTriggerData.tg_newtuple)
4615
4616 /* Restore the current role if necessary */
4617 if (save_rolid != evtshared->ats_rolid)
4618 SetUserIdAndSecContext(save_rolid, save_sec_context);
4619
4620 /*
4621 * Release resources
4622 */
4623 if (should_free_trig)
4624 heap_freetuple(LocTriggerData.tg_trigtuple);
4625 if (should_free_new)
4626 heap_freetuple(LocTriggerData.tg_newtuple);
4627
4628 /* don't clear slots' contents if foreign table */
4629 if (trig_tuple_slot1 == NULL)
4630 {
4631 if (LocTriggerData.tg_trigslot)
4632 ExecClearTuple(LocTriggerData.tg_trigslot);
4633 if (LocTriggerData.tg_newslot)
4634 ExecClearTuple(LocTriggerData.tg_newslot);
4635 }
4636
4637 /*
4638 * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
4639 * the firing of the trigger.
4640 */
4641 if (instr)
4642 InstrStopTrigger(instr + tgindx, 1);
4643}
4644
4645
4646/*
4647 * afterTriggerMarkEvents()
4648 *
4649 * Scan the given event list for not yet invoked events. Mark the ones
4650 * that can be invoked now with the current firing ID.
4651 *
4652 * If move_list isn't NULL, events that are not to be invoked now are
4653 * transferred to move_list.
4654 *
4655 * When immediate_only is true, do not invoke currently-deferred triggers.
4656 * (This will be false only at main transaction exit.)
4657 *
4658 * Returns true if any invokable events were found.
4659 */
4660static bool
4663 bool immediate_only)
4664{
4665 bool found = false;
4666 bool deferred_found = false;
4667 AfterTriggerEvent event;
4669
4670 for_each_event_chunk(event, chunk, *events)
4671 {
4673 bool defer_it = false;
4674
4675 if (!(event->ate_flags &
4677 {
4678 /*
4679 * This trigger hasn't been called or scheduled yet. Check if we
4680 * should call it now.
4681 */
4683 {
4684 defer_it = true;
4685 }
4686 else
4687 {
4688 /*
4689 * Mark it as to be fired in this firing cycle.
4690 */
4691 evtshared->ats_firing_id = afterTriggers.firing_counter;
4692 event->ate_flags |= AFTER_TRIGGER_IN_PROGRESS;
4693 found = true;
4694 }
4695 }
4696
4697 /*
4698 * If it's deferred, move it to move_list, if requested.
4699 */
4700 if (defer_it && move_list != NULL)
4701 {
4702 deferred_found = true;
4703 /* add it to move_list */
4705 /* mark original copy "done" so we don't do it again */
4706 event->ate_flags |= AFTER_TRIGGER_DONE;
4707 }
4708 }
4709
4710 /*
4711 * We could allow deferred triggers if, before the end of the
4712 * security-restricted operation, we were to verify that a SET CONSTRAINTS
4713 * ... IMMEDIATE has fired all such triggers. For now, don't bother.
4714 */
4716 ereport(ERROR,
4718 errmsg("cannot fire deferred trigger within security-restricted operation")));
4719
4720 return found;
4721}
4722
4723/*
4724 * afterTriggerInvokeEvents()
4725 *
4726 * Scan the given event list for events that are marked as to be fired
4727 * in the current firing cycle, and fire them.
4728 *
4729 * If estate isn't NULL, we use its result relation info to avoid repeated
4730 * openings and closing of trigger target relations. If it is NULL, we
4731 * make one locally to cache the info in case there are multiple trigger
4732 * events per rel.
4733 *
4734 * When delete_ok is true, it's safe to delete fully-processed events.
4735 * (We are not very tense about that: we simply reset a chunk to be empty
4736 * if all its events got fired. The objective here is just to avoid useless
4737 * rescanning of events when a trigger queues new events during transaction
4738 * end, so it's not necessary to worry much about the case where only
4739 * some events are fired.)
4740 *
4741 * Returns true if no unfired events remain in the list (this allows us
4742 * to avoid repeating afterTriggerMarkEvents).
4743 */
4744static bool
4747 EState *estate,
4748 bool delete_ok)
4749{
4750 bool all_fired = true;
4753 bool local_estate = false;
4755 Relation rel = NULL;
4756 TriggerDesc *trigdesc = NULL;
4757 FmgrInfo *finfo = NULL;
4760 *slot2 = NULL;
4761
4762 /* Make a local EState if need be */
4763 if (estate == NULL)
4764 {
4765 estate = CreateExecutorState();
4766 local_estate = true;
4767 }
4768
4769 /* Make a per-tuple memory context for trigger function calls */
4772 "AfterTriggerTupleContext",
4774
4775 for_each_chunk(chunk, *events)
4776 {
4777 AfterTriggerEvent event;
4778 bool all_fired_in_chunk = true;
4779
4780 for_each_event(event, chunk)
4781 {
4783
4784 /*
4785 * Is it one for me to fire?
4786 */
4787 if ((event->ate_flags & AFTER_TRIGGER_IN_PROGRESS) &&
4788 evtshared->ats_firing_id == firing_id)
4789 {
4791 *dst_rInfo;
4792
4793 /*
4794 * So let's fire it... but first, find the correct relation if
4795 * this is not the same relation as before.
4796 */
4797 if (rel == NULL || RelationGetRelid(rel) != evtshared->ats_relid)
4798 {
4799 rInfo = ExecGetTriggerResultRel(estate, evtshared->ats_relid,
4800 NULL);
4801 rel = rInfo->ri_RelationDesc;
4802 /* Catch calls with insufficient relcache refcounting */
4804 trigdesc = rInfo->ri_TrigDesc;
4805 /* caution: trigdesc could be NULL here */
4806 finfo = rInfo->ri_TrigFunctions;
4807 instr = rInfo->ri_TrigInstrument;
4808 if (slot1 != NULL)
4809 {
4812 slot1 = slot2 = NULL;
4813 }
4814 if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
4815 {
4820 }
4821 }
4822
4823 /*
4824 * Look up source and destination partition result rels of a
4825 * cross-partition update event.
4826 */
4827 if ((event->ate_flags & AFTER_TRIGGER_TUP_BITS) ==
4829 {
4830 Assert(OidIsValid(event->ate_src_part) &&
4831 OidIsValid(event->ate_dst_part));
4833 event->ate_src_part,
4834 rInfo);
4836 event->ate_dst_part,
4837 rInfo);
4838 }
4839 else
4841
4842 /*
4843 * Fire it. Note that the AFTER_TRIGGER_IN_PROGRESS flag is
4844 * still set, so recursive examinations of the event list
4845 * won't try to re-fire it.
4846 */
4847 AfterTriggerExecute(estate, event, rInfo,
4849 trigdesc, finfo, instr,
4851
4852 /*
4853 * Mark the event as done.
4854 */
4855 event->ate_flags &= ~AFTER_TRIGGER_IN_PROGRESS;
4856 event->ate_flags |= AFTER_TRIGGER_DONE;
4857 }
4858 else if (!(event->ate_flags & AFTER_TRIGGER_DONE))
4859 {
4860 /* something remains to be done */
4861 all_fired = all_fired_in_chunk = false;
4862 }
4863 }
4864
4865 /* Clear the chunk if delete_ok and nothing left of interest */
4867 {
4868 chunk->freeptr = CHUNK_DATA_START(chunk);
4869 chunk->endfree = chunk->endptr;
4870
4871 /*
4872 * If it's last chunk, must sync event list's tailfree too. Note
4873 * that delete_ok must NOT be passed as true if there could be
4874 * additional AfterTriggerEventList values pointing at this event
4875 * list, since we'd fail to fix their copies of tailfree.
4876 */
4877 if (chunk == events->tail)
4878 events->tailfree = chunk->freeptr;
4879 }
4880 }
4881 if (slot1 != NULL)
4882 {
4885 }
4886
4887 /* Release working resources */
4889
4890 if (local_estate)
4891 {
4893 ExecResetTupleTable(estate->es_tupleTable, false);
4894 FreeExecutorState(estate);
4895 }
4896
4897 return all_fired;
4898}
4899
4900
4901/*
4902 * GetAfterTriggersTableData
4903 *
4904 * Find or create an AfterTriggersTableData struct for the specified
4905 * trigger event (relation + operation type). Ignore existing structs
4906 * marked "closed"; we don't want to put any additional tuples into them,
4907 * nor change their stmt-triggers-fired state.
4908 *
4909 * Note: the AfterTriggersTableData list is allocated in the current
4910 * (sub)transaction's CurTransactionContext. This is OK because
4911 * we don't need it to live past AfterTriggerEndQuery.
4912 */
4915{
4919 ListCell *lc;
4920
4921 /* At this level, cmdType should not be, eg, CMD_MERGE */
4922 Assert(cmdType == CMD_INSERT ||
4923 cmdType == CMD_UPDATE ||
4924 cmdType == CMD_DELETE);
4925
4926 /* Caller should have ensured query_depth is OK. */
4930
4931 foreach(lc, qs->tables)
4932 {
4934 if (table->relid == relid && table->cmdType == cmdType &&
4935 !table->closed)
4936 return table;
4937 }
4938
4940
4942 table->relid = relid;
4943 table->cmdType = cmdType;
4944 qs->tables = lappend(qs->tables, table);
4945
4947
4948 return table;
4949}
4950
4951/*
4952 * Returns a TupleTableSlot suitable for holding the tuples to be put
4953 * into AfterTriggersTableData's transition table tuplestores.
4954 */
4955static TupleTableSlot *
4957 TupleDesc tupdesc)
4958{
4959 /* Create it if not already done. */
4960 if (!table->storeslot)
4961 {
4963
4964 /*
4965 * We need this slot only until AfterTriggerEndQuery, but making it
4966 * last till end-of-subxact is good enough. It'll be freed by
4967 * AfterTriggerFreeQuery(). However, the passed-in tupdesc might have
4968 * a different lifespan, so we'd better make a copy of that.
4969 */
4971 tupdesc = CreateTupleDescCopy(tupdesc);
4972 table->storeslot = MakeSingleTupleTableSlot(tupdesc, &TTSOpsVirtual);
4974 }
4975
4976 return table->storeslot;
4977}
4978
4979/*
4980 * MakeTransitionCaptureState
4981 *
4982 * Make a TransitionCaptureState object for the given TriggerDesc, target
4983 * relation, and operation type. The TCS object holds all the state needed
4984 * to decide whether to capture tuples in transition tables.
4985 *
4986 * If there are no triggers in 'trigdesc' that request relevant transition
4987 * tables, then return NULL.
4988 *
4989 * The resulting object can be passed to the ExecAR* functions. When
4990 * dealing with child tables, the caller can set tcs_original_insert_tuple
4991 * to avoid having to reconstruct the original tuple in the root table's
4992 * format.
4993 *
4994 * Note that we copy the flags from a parent table into this struct (rather
4995 * than subsequently using the relation's TriggerDesc directly) so that we can
4996 * use it to control collection of transition tuples from child tables.
4997 *
4998 * Per SQL spec, all operations of the same kind (INSERT/UPDATE/DELETE)
4999 * on the same table during one query should share one transition table.
5000 * Therefore, the Tuplestores are owned by an AfterTriggersTableData struct
5001 * looked up using the table OID + CmdType, and are merely referenced by
5002 * the TransitionCaptureState objects we hand out to callers.
5003 */
5006{
5008 bool need_old_upd,
5017
5018 if (trigdesc == NULL)
5019 return NULL;
5020
5021 /* Detect which table(s) we need. */
5022 switch (cmdType)
5023 {
5024 case CMD_INSERT:
5027 break;
5028 case CMD_UPDATE:
5031 need_old_del = need_new_ins = false;
5032 break;
5033 case CMD_DELETE:
5036 break;
5037 case CMD_MERGE:
5042 break;
5043 default:
5044 elog(ERROR, "unexpected CmdType: %d", (int) cmdType);
5045 /* keep compiler quiet */
5047 break;
5048 }
5050 return NULL;
5051
5052 /* Check state, like AfterTriggerSaveEvent. */
5053 if (afterTriggers.query_depth < 0)
5054 elog(ERROR, "MakeTransitionCaptureState() called outside of query");
5055
5056 /* Be sure we have enough space to record events at this query depth. */
5059
5060 /*
5061 * Find or create AfterTriggersTableData struct(s) to hold the
5062 * tuplestore(s). If there's a matching struct but it's marked closed,
5063 * ignore it; we need a newer one.
5064 *
5065 * Note: MERGE must use the same AfterTriggersTableData structs as INSERT,
5066 * UPDATE, and DELETE, so that any MERGE'd tuples are added to the same
5067 * tuplestores as tuples from any INSERT, UPDATE, or DELETE commands
5068 * running in the same top-level command (e.g., in a writable CTE).
5069 *
5070 * Note: the AfterTriggersTableData list, as well as the tuplestores, are
5071 * allocated in the current (sub)transaction's CurTransactionContext, and
5072 * the tuplestores are managed by the (sub)transaction's resource owner.
5073 * This is sufficient lifespan because we do not allow triggers using
5074 * transition tables to be deferrable; they will be fired during
5075 * AfterTriggerEndQuery, after which it's okay to delete the data.
5076 */
5077 if (need_new_ins)
5079 else
5080 ins_table = NULL;
5081
5084 else
5085 upd_table = NULL;
5086
5087 if (need_old_del)
5089 else
5090 del_table = NULL;
5091
5092 /* Now create required tuplestore(s), if we don't have them already. */
5096
5097 if (need_old_upd && upd_table->old_tuplestore == NULL)
5098 upd_table->old_tuplestore = tuplestore_begin_heap(false, false, work_mem);
5099 if (need_new_upd && upd_table->new_tuplestore == NULL)
5100 upd_table->new_tuplestore = tuplestore_begin_heap(false, false, work_mem);
5101 if (need_old_del && del_table->old_tuplestore == NULL)
5102 del_table->old_tuplestore = tuplestore_begin_heap(false, false, work_mem);
5103 if (need_new_ins && ins_table->new_tuplestore == NULL)
5104 ins_table->new_tuplestore = tuplestore_begin_heap(false, false, work_mem);
5105
5108
5109 /* Now build the TransitionCaptureState struct, in caller's context */
5111 state->tcs_delete_old_table = need_old_del;
5112 state->tcs_update_old_table = need_old_upd;
5113 state->tcs_update_new_table = need_new_upd;
5114 state->tcs_insert_new_table = need_new_ins;
5115 state->tcs_insert_private = ins_table;
5116 state->tcs_update_private = upd_table;
5117 state->tcs_delete_private = del_table;
5118
5119 return state;
5120}
5121
5122
5123/* ----------
5124 * AfterTriggerBeginXact()
5125 *
5126 * Called at transaction start (either BEGIN or implicit for single
5127 * statement outside of transaction block).
5128 * ----------
5129 */
5130void
5132{
5133 /*
5134 * Initialize after-trigger state structure to empty
5135 */
5136 afterTriggers.firing_counter = (CommandId) 1; /* mustn't be 0 */
5141
5142 /*
5143 * Verify that there is no leftover state remaining. If these assertions
5144 * trip, it means that AfterTriggerEndXact wasn't called or didn't clean
5145 * up properly.
5146 */
5154}
5155
5156
5157/* ----------
5158 * AfterTriggerBeginQuery()
5159 *
5160 * Called just before we start processing a single query within a
5161 * transaction (or subtransaction). Most of the real work gets deferred
5162 * until somebody actually tries to queue a trigger event.
5163 * ----------
5164 */
5165void
5167{
5168 /* Increase the query stack depth */
5170}
5171
5172
5173/* ----------
5174 * AfterTriggerEndQuery()
5175 *
5176 * Called after one query has been completely processed. At this time
5177 * we invoke all AFTER IMMEDIATE trigger events queued by the query, and
5178 * transfer deferred trigger events to the global deferred-trigger list.
5179 *
5180 * Note that this must be called BEFORE closing down the executor
5181 * with ExecutorEnd, because we make use of the EState's info about
5182 * target relations. Normally it is called from ExecutorFinish.
5183 * ----------
5184 */
5185void
5187{
5189
5190 /* Must be inside a query, too */
5192
5193 /*
5194 * If we never even got as far as initializing the event stack, there
5195 * certainly won't be any events, so exit quickly.
5196 */
5198 {
5200 return;
5201 }
5202
5203 /*
5204 * Process all immediate-mode triggers queued by the query, and move the
5205 * deferred ones to the main list of deferred events.
5206 *
5207 * Notice that we decide which ones will be fired, and put the deferred
5208 * ones on the main list, before anything is actually fired. This ensures
5209 * reasonably sane behavior if a trigger function does SET CONSTRAINTS ...
5210 * IMMEDIATE: all events we have decided to defer will be available for it
5211 * to fire.
5212 *
5213 * We loop in case a trigger queues more events at the same query level.
5214 * Ordinary trigger functions, including all PL/pgSQL trigger functions,
5215 * will instead fire any triggers in a dedicated query level. Foreign key
5216 * enforcement triggers do add to the current query level, thanks to their
5217 * passing fire_triggers = false to SPI_execute_snapshot(). Other
5218 * C-language triggers might do likewise.
5219 *
5220 * If we find no firable events, we don't have to increment
5221 * firing_counter.
5222 */
5224
5226 for (;;)
5227 {
5228 if (afterTriggerMarkEvents(&qs->events, &afterTriggers.events, true))
5229 {
5231 AfterTriggerEventChunk *oldtail = qs->events.tail;
5232
5233 if (afterTriggerInvokeEvents(&qs->events, firing_id, estate, false))
5234 break; /* all fired */
5235
5236 /*
5237 * Firing a trigger could result in query_stack being repalloc'd,
5238 * so we must recalculate qs after each afterTriggerInvokeEvents
5239 * call. Furthermore, it's unsafe to pass delete_ok = true here,
5240 * because that could cause afterTriggerInvokeEvents to try to
5241 * access qs->events after the stack has been repalloc'd.
5242 */
5244
5245 /*
5246 * We'll need to scan the events list again. To reduce the cost
5247 * of doing so, get rid of completely-fired chunks. We know that
5248 * all events were marked IN_PROGRESS or DONE at the conclusion of
5249 * afterTriggerMarkEvents, so any still-interesting events must
5250 * have been added after that, and so must be in the chunk that
5251 * was then the tail chunk, or in later chunks. So, zap all
5252 * chunks before oldtail. This is approximately the same set of
5253 * events we would have gotten rid of by passing delete_ok = true.
5254 */
5255 Assert(oldtail != NULL);
5256 while (qs->events.head != oldtail)
5258 }
5259 else
5260 break;
5261 }
5262
5263 /*
5264 * Fire batch callbacks before releasing query-level storage and before
5265 * decrementing query_depth. Callbacks may do real work (index probes,
5266 * error reporting).
5267 *
5268 * Recompute qs first: the loop above refreshes it after each
5269 * afterTriggerInvokeEvents() call (see comment there), but the "all
5270 * fired" break exits without doing so, leaving qs potentially stale here.
5271 */
5273 FireAfterTriggerBatchCallbacks(qs->batch_callbacks);
5274
5275 /* Release query-level-local storage, including tuplestores if any */
5277
5280}
5281
5282
5283/*
5284 * AfterTriggerFreeQuery
5285 * Release subsidiary storage for a trigger query level.
5286 * This includes closing down tuplestores.
5287 * Note: it's important for this to be safe if interrupted by an error
5288 * and then called again for the same query level.
5289 */
5290static void
5292{
5293 Tuplestorestate *ts;
5294 List *tables;
5295 ListCell *lc;
5296
5297 /* Drop the trigger events */
5298 afterTriggerFreeEventList(&qs->events);
5299
5300 /* Drop FDW tuplestore if any */
5301 ts = qs->fdw_tuplestore;
5302 qs->fdw_tuplestore = NULL;
5303 if (ts)
5304 tuplestore_end(ts);
5305
5306 /* Release per-table subsidiary storage */
5307 tables = qs->tables;
5308 foreach(lc, tables)
5309 {
5311
5312 ts = table->old_tuplestore;
5313 table->old_tuplestore = NULL;
5314 if (ts)
5315 tuplestore_end(ts);
5316 ts = table->new_tuplestore;
5317 table->new_tuplestore = NULL;
5318 if (ts)
5319 tuplestore_end(ts);
5320 if (table->storeslot)
5321 {
5322 TupleTableSlot *slot = table->storeslot;
5323
5324 table->storeslot = NULL;
5326 }
5327 }
5328
5329 /*
5330 * Now free the AfterTriggersTableData structs and list cells. Reset list
5331 * pointer first; if list_free_deep somehow gets an error, better to leak
5332 * that storage than have an infinite loop.
5333 */
5334 qs->tables = NIL;
5335 list_free_deep(tables);
5336
5337 list_free_deep(qs->batch_callbacks);
5338 qs->batch_callbacks = NIL;
5339}
5340
5341
5342/* ----------
5343 * AfterTriggerFireDeferred()
5344 *
5345 * Called just before the current transaction is committed. At this
5346 * time we invoke all pending DEFERRED triggers.
5347 *
5348 * It is possible for other modules to queue additional deferred triggers
5349 * during pre-commit processing; therefore xact.c may have to call this
5350 * multiple times.
5351 * ----------
5352 */
5353void
5355{
5356 AfterTriggerEventList *events;
5357 bool snap_pushed = false;
5358
5359 /* Must not be inside a query */
5361
5362 /*
5363 * If there are any triggers to fire, make sure we have set a snapshot for
5364 * them to use. (Since PortalRunUtility doesn't set a snap for COMMIT, we
5365 * can't assume ActiveSnapshot is valid on entry.)
5366 */
5367 events = &afterTriggers.events;
5368 if (events->head != NULL)
5369 {
5371 snap_pushed = true;
5372 }
5373
5374 /*
5375 * Run all the remaining triggers. Loop until they are all gone, in case
5376 * some trigger queues more for us to do.
5377 */
5379 while (afterTriggerMarkEvents(events, NULL, false))
5380 {
5382
5383 if (afterTriggerInvokeEvents(events, firing_id, NULL, true))
5384 break; /* all fired */
5385 }
5386
5387 /* Flush any fast-path batches accumulated by the triggers just fired. */
5389
5391
5392 /*
5393 * We don't bother freeing the event list or batch_callbacks, since they
5394 * will go away anyway (and more efficiently than via pfree) in
5395 * AfterTriggerEndXact.
5396 */
5397
5398 if (snap_pushed)
5400}
5401
5402
5403/* ----------
5404 * AfterTriggerEndXact()
5405 *
5406 * The current transaction is finishing.
5407 *
5408 * Any unfired triggers are canceled so we simply throw
5409 * away anything we know.
5410 *
5411 * Note: it is possible for this to be called repeatedly in case of
5412 * error during transaction abort; therefore, do not complain if
5413 * already closed down.
5414 * ----------
5415 */
5416void
5418{
5419 /*
5420 * Forget the pending-events list.
5421 *
5422 * Since all the info is in TopTransactionContext or children thereof, we
5423 * don't really need to do anything to reclaim memory. However, the
5424 * pending-events list could be large, and so it's useful to discard it as
5425 * soon as possible --- especially if we are aborting because we ran out
5426 * of memory for the list!
5427 */
5429 {
5435 }
5436
5437 /*
5438 * Forget any subtransaction state as well. Since this can't be very
5439 * large, we let the eventual reset of TopTransactionContext free the
5440 * memory instead of doing it here.
5441 */
5444
5445
5446 /*
5447 * Forget the query stack and constraint-related state information. As
5448 * with the subtransaction state information, we don't bother freeing the
5449 * memory here.
5450 */
5454
5455 /* No more afterTriggers manipulation until next transaction starts. */
5457
5459
5463}
5464
5465/*
5466 * AfterTriggerBeginSubXact()
5467 *
5468 * Start a subtransaction.
5469 */
5470void
5472{
5473 int my_level = GetCurrentTransactionNestLevel();
5474
5475 /*
5476 * Allocate more space in the trans_stack if needed. (Note: because the
5477 * minimum nest level of a subtransaction is 2, we waste the first couple
5478 * entries of the array; not worth the notational effort to avoid it.)
5479 */
5480 while (my_level >= afterTriggers.maxtransdepth)
5481 {
5483 {
5484 /* Arbitrarily initialize for max of 8 subtransaction levels */
5487 8 * sizeof(AfterTriggersTransData));
5489 }
5490 else
5491 {
5492 /* repalloc will keep the stack in the same context */
5494
5499 }
5500 }
5501
5502 /*
5503 * Push the current information into the stack. The SET CONSTRAINTS state
5504 * is not saved until/unless changed. Likewise, we don't make a
5505 * per-subtransaction event context until needed.
5506 */
5507 afterTriggers.trans_stack[my_level].state = NULL;
5511}
5512
5513/*
5514 * AfterTriggerEndSubXact()
5515 *
5516 * The current subtransaction is ending.
5517 */
5518void
5520{
5521 int my_level = GetCurrentTransactionNestLevel();
5523 AfterTriggerEvent event;
5526
5527 /*
5528 * Pop the prior state if needed.
5529 */
5530 if (isCommit)
5531 {
5533 /* If we saved a prior state, we don't need it anymore */
5535 if (state != NULL)
5536 pfree(state);
5537 /* this avoids double pfree if error later: */
5538 afterTriggers.trans_stack[my_level].state = NULL;
5541 }
5542 else
5543 {
5544 /*
5545 * Aborting. It is possible subxact start failed before calling
5546 * AfterTriggerBeginSubXact, in which case we mustn't risk touching
5547 * trans_stack levels that aren't there.
5548 */
5549 if (my_level >= afterTriggers.maxtransdepth)
5550 return;
5551
5552 /*
5553 * Release query-level storage for queries being aborted, and restore
5554 * query_depth to its pre-subxact value. This assumes that a
5555 * subtransaction will not add events to query levels started in a
5556 * earlier transaction state.
5557 */
5559 {
5563 }
5566
5567 /*
5568 * Restore the global deferred-event list to its former length,
5569 * discarding any events queued by the subxact.
5570 */
5572 &afterTriggers.trans_stack[my_level].events);
5573
5574 /*
5575 * Restore the trigger state. If the saved state is NULL, then this
5576 * subxact didn't save it, so it doesn't need restoring.
5577 */
5579 if (state != NULL)
5580 {
5583 }
5584 /* this avoids double pfree if error later: */
5585 afterTriggers.trans_stack[my_level].state = NULL;
5586
5587 /*
5588 * Scan for any remaining deferred events that were marked DONE or IN
5589 * PROGRESS by this subxact or a child, and un-mark them. We can
5590 * recognize such events because they have a firing ID greater than or
5591 * equal to the firing_counter value we saved at subtransaction start.
5592 * (This essentially assumes that the current subxact includes all
5593 * subxacts started after it.)
5594 */
5597 {
5599
5600 if (event->ate_flags &
5602 {
5603 if (evtshared->ats_firing_id >= subxact_firing_id)
5604 event->ate_flags &=
5606 }
5607 }
5608 }
5609
5610 /* Reset in case a callback threw an error while firing. */
5612}
5613
5614/*
5615 * Get the transition table for the given event and depending on whether we are
5616 * processing the old or the new tuple.
5617 */
5618static Tuplestorestate *
5622 TransitionCaptureState *transition_capture)
5623{
5624 Tuplestorestate *tuplestore = NULL;
5625 bool delete_old_table = transition_capture->tcs_delete_old_table;
5626 bool update_old_table = transition_capture->tcs_update_old_table;
5627 bool update_new_table = transition_capture->tcs_update_new_table;
5628 bool insert_new_table = transition_capture->tcs_insert_new_table;
5629
5630 /*
5631 * For INSERT events NEW should be non-NULL, for DELETE events OLD should
5632 * be non-NULL, whereas for UPDATE events normally both OLD and NEW are
5633 * non-NULL. But for UPDATE events fired for capturing transition tuples
5634 * during UPDATE partition-key row movement, OLD is NULL when the event is
5635 * for a row being inserted, whereas NEW is NULL when the event is for a
5636 * row being deleted.
5637 */
5639 TupIsNull(oldslot)));
5641 TupIsNull(newslot)));
5642
5643 if (!TupIsNull(oldslot))
5644 {
5646 if (event == TRIGGER_EVENT_DELETE && delete_old_table)
5647 tuplestore = transition_capture->tcs_delete_private->old_tuplestore;
5648 else if (event == TRIGGER_EVENT_UPDATE && update_old_table)
5649 tuplestore = transition_capture->tcs_update_private->old_tuplestore;
5650 }
5651 else if (!TupIsNull(newslot))
5652 {
5654 if (event == TRIGGER_EVENT_INSERT && insert_new_table)
5655 tuplestore = transition_capture->tcs_insert_private->new_tuplestore;
5656 else if (event == TRIGGER_EVENT_UPDATE && update_new_table)
5657 tuplestore = transition_capture->tcs_update_private->new_tuplestore;
5658 }
5659
5660 return tuplestore;
5661}
5662
5663/*
5664 * Add the given heap tuple to the given tuplestore, applying the conversion
5665 * map if necessary.
5666 *
5667 * If original_insert_tuple is given, we can add that tuple without conversion.
5668 */
5669static void
5671 int event,
5672 TransitionCaptureState *transition_capture,
5674 TupleTableSlot *slot,
5676 Tuplestorestate *tuplestore)
5677{
5678 TupleConversionMap *map;
5679
5680 /*
5681 * Nothing needs to be done if we don't have a tuplestore.
5682 */
5683 if (tuplestore == NULL)
5684 return;
5685
5688 else if ((map = ExecGetChildToRootMap(relinfo)) != NULL)
5689 {
5691 TupleTableSlot *storeslot;
5692
5693 switch (event)
5694 {
5696 table = transition_capture->tcs_insert_private;
5697 break;
5699 table = transition_capture->tcs_update_private;
5700 break;
5702 table = transition_capture->tcs_delete_private;
5703 break;
5704 default:
5705 elog(ERROR, "invalid after-trigger event code: %d", event);
5706 table = NULL; /* keep compiler quiet */
5707 break;
5708 }
5709
5710 storeslot = GetAfterTriggersStoreSlot(table, map->outdesc);
5711 execute_attr_map_slot(map->attrMap, slot, storeslot);
5712 tuplestore_puttupleslot(tuplestore, storeslot);
5713 }
5714 else
5715 tuplestore_puttupleslot(tuplestore, slot);
5716}
5717
5718/* ----------
5719 * AfterTriggerEnlargeQueryState()
5720 *
5721 * Prepare the necessary state so that we can record AFTER trigger events
5722 * queued by a query. It is allowed to have nested queries within a
5723 * (sub)transaction, so we need to have separate state for each query
5724 * nesting level.
5725 * ----------
5726 */
5727static void
5729{
5731
5733
5735 {
5736 int new_alloc = Max(afterTriggers.query_depth + 1, 8);
5737
5742 }
5743 else
5744 {
5745 /* repalloc will keep the stack in the same context */
5748 old_alloc * 2);
5749
5754 }
5755
5756 /* Initialize new array entries to empty */
5758 {
5760
5761 qs->events.head = NULL;
5762 qs->events.tail = NULL;
5763 qs->events.tailfree = NULL;
5764 qs->fdw_tuplestore = NULL;
5765 qs->tables = NIL;
5766 qs->batch_callbacks = NIL;
5767
5768 ++init_depth;
5769 }
5770}
5771
5772/*
5773 * Create an empty SetConstraintState with room for numalloc trigstates
5774 */
5775static SetConstraintState
5777{
5779
5780 /* Behave sanely with numalloc == 0 */
5781 if (numalloc <= 0)
5782 numalloc = 1;
5783
5784 /*
5785 * We assume that zeroing will correctly initialize the state values.
5786 */
5789 offsetof(SetConstraintStateData, trigstates) +
5790 numalloc * sizeof(SetConstraintTriggerData));
5791
5792 state->numalloc = numalloc;
5793
5794 return state;
5795}
5796
5797/*
5798 * Copy a SetConstraintState
5799 */
5800static SetConstraintState
5802{
5804
5806
5807 state->all_isset = origstate->all_isset;
5808 state->all_isdeferred = origstate->all_isdeferred;
5809 state->numstates = origstate->numstates;
5810 memcpy(state->trigstates, origstate->trigstates,
5811 origstate->numstates * sizeof(SetConstraintTriggerData));
5812
5813 return state;
5814}
5815
5816/*
5817 * Add a per-trigger item to a SetConstraintState. Returns possibly-changed
5818 * pointer to the state object (it will change if we have to repalloc).
5819 */
5820static SetConstraintState
5822 Oid tgoid, bool tgisdeferred)
5823{
5824 if (state->numstates >= state->numalloc)
5825 {
5826 int newalloc = state->numalloc * 2;
5827
5828 newalloc = Max(newalloc, 8); /* in case original has size 0 */
5831 offsetof(SetConstraintStateData, trigstates) +
5833 state->numalloc = newalloc;
5834 Assert(state->numstates < state->numalloc);
5835 }
5836
5837 state->trigstates[state->numstates].sct_tgoid = tgoid;
5838 state->trigstates[state->numstates].sct_tgisdeferred = tgisdeferred;
5839 state->numstates++;
5840
5841 return state;
5842}
5843
5844/* ----------
5845 * AfterTriggerSetState()
5846 *
5847 * Execute the SET CONSTRAINTS ... utility command.
5848 * ----------
5849 */
5850void
5852{
5853 int my_level = GetCurrentTransactionNestLevel();
5854
5855 /* If we haven't already done so, initialize our state. */
5856 if (afterTriggers.state == NULL)
5858
5859 /*
5860 * If in a subtransaction, and we didn't save the current state already,
5861 * save it so it can be restored if the subtransaction aborts.
5862 */
5863 if (my_level > 1 &&
5864 afterTriggers.trans_stack[my_level].state == NULL)
5865 {
5866 afterTriggers.trans_stack[my_level].state =
5868 }
5869
5870 /*
5871 * Handle SET CONSTRAINTS ALL ...
5872 */
5873 if (stmt->constraints == NIL)
5874 {
5875 /*
5876 * Forget any previous SET CONSTRAINTS commands in this transaction.
5877 */
5879
5880 /*
5881 * Set the per-transaction ALL state to known.
5882 */
5885 }
5886 else
5887 {
5890 List *conoidlist = NIL;
5891 List *tgoidlist = NIL;
5892 ListCell *lc;
5893
5894 /*
5895 * Handle SET CONSTRAINTS constraint-name [, ...]
5896 *
5897 * First, identify all the named constraints and make a list of their
5898 * OIDs. Since, unlike the SQL spec, we allow multiple constraints of
5899 * the same name within a schema, the specifications are not
5900 * necessarily unique. Our strategy is to target all matching
5901 * constraints within the first search-path schema that has any
5902 * matches, but disregard matches in schemas beyond the first match.
5903 * (This is a bit odd but it's the historical behavior.)
5904 *
5905 * A constraint in a partitioned table may have corresponding
5906 * constraints in the partitions. Grab those too.
5907 */
5909
5910 foreach(lc, stmt->constraints)
5911 {
5912 RangeVar *constraint = lfirst(lc);
5913 bool found;
5915 ListCell *nslc;
5916
5917 if (constraint->catalogname)
5918 {
5919 if (strcmp(constraint->catalogname, get_database_name(MyDatabaseId)) != 0)
5920 ereport(ERROR,
5922 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
5923 constraint->catalogname, constraint->schemaname,
5924 constraint->relname)));
5925 }
5926
5927 /*
5928 * If we're given the schema name with the constraint, look only
5929 * in that schema. If given a bare constraint name, use the
5930 * search path to find the first matching constraint.
5931 */
5932 if (constraint->schemaname)
5933 {
5935 false);
5936
5938 }
5939 else
5940 {
5942 }
5943
5944 found = false;
5945 foreach(nslc, namespacelist)
5946 {
5949 ScanKeyData skey[2];
5950 HeapTuple tup;
5951
5952 ScanKeyInit(&skey[0],
5955 CStringGetDatum(constraint->relname));
5956 ScanKeyInit(&skey[1],
5960
5962 true, NULL, 2, skey);
5963
5965 {
5967
5968 if (con->condeferrable)
5969 conoidlist = lappend_oid(conoidlist, con->oid);
5970 else if (stmt->deferred)
5971 ereport(ERROR,
5973 errmsg("constraint \"%s\" is not deferrable",
5974 constraint->relname)));
5975 found = true;
5976 }
5977
5979
5980 /*
5981 * Once we've found a matching constraint we do not search
5982 * later parts of the search path.
5983 */
5984 if (found)
5985 break;
5986 }
5987
5989
5990 /*
5991 * Not found ?
5992 */
5993 if (!found)
5994 ereport(ERROR,
5996 errmsg("constraint \"%s\" does not exist",
5997 constraint->relname)));
5998 }
5999
6000 /*
6001 * Scan for any possible descendants of the constraints. We append
6002 * whatever we find to the same list that we're scanning; this has the
6003 * effect that we create new scans for those, too, so if there are
6004 * further descendents, we'll also catch them.
6005 */
6006 foreach(lc, conoidlist)
6007 {
6008 Oid parent = lfirst_oid(lc);
6009 ScanKeyData key;
6010 SysScanDesc scan;
6011 HeapTuple tuple;
6012
6013 ScanKeyInit(&key,
6016 ObjectIdGetDatum(parent));
6017
6018 scan = systable_beginscan(conrel, ConstraintParentIndexId, true, NULL, 1, &key);
6019
6020 while (HeapTupleIsValid(tuple = systable_getnext(scan)))
6021 {
6023
6024 conoidlist = lappend_oid(conoidlist, con->oid);
6025 }
6026
6027 systable_endscan(scan);
6028 }
6029
6031
6032 /*
6033 * Now, locate the trigger(s) implementing each of these constraints,
6034 * and make a list of their OIDs.
6035 */
6037
6038 foreach(lc, conoidlist)
6039 {
6040 Oid conoid = lfirst_oid(lc);
6043 HeapTuple htup;
6044
6048 ObjectIdGetDatum(conoid));
6049
6051 NULL, 1, &skey);
6052
6054 {
6056
6057 /*
6058 * Silently skip triggers that are marked as non-deferrable in
6059 * pg_trigger. This is not an error condition, since a
6060 * deferrable RI constraint may have some non-deferrable
6061 * actions.
6062 */
6063 if (pg_trigger->tgdeferrable)
6065 }
6066
6068 }
6069
6071
6072 /*
6073 * Now we can set the trigger states of individual triggers for this
6074 * xact.
6075 */
6076 foreach(lc, tgoidlist)
6077 {
6078 Oid tgoid = lfirst_oid(lc);
6080 bool found = false;
6081 int i;
6082
6083 for (i = 0; i < state->numstates; i++)
6084 {
6085 if (state->trigstates[i].sct_tgoid == tgoid)
6086 {
6087 state->trigstates[i].sct_tgisdeferred = stmt->deferred;
6088 found = true;
6089 break;
6090 }
6091 }
6092 if (!found)
6093 {
6095 SetConstraintStateAddItem(state, tgoid, stmt->deferred);
6096 }
6097 }
6098 }
6099
6100 /*
6101 * SQL99 requires that when a constraint is set to IMMEDIATE, any deferred
6102 * checks against that constraint must be made when the SET CONSTRAINTS
6103 * command is executed -- i.e. the effects of the SET CONSTRAINTS command
6104 * apply retroactively. We've updated the constraints state, so scan the
6105 * list of previously deferred events to fire any that have now become
6106 * immediate.
6107 *
6108 * Obviously, if this was SET ... DEFERRED then it can't have converted
6109 * any unfired events to immediate, so we need do nothing in that case.
6110 */
6111 if (!stmt->deferred)
6112 {
6114 bool snapshot_set = false;
6115
6117 while (afterTriggerMarkEvents(events, NULL, true))
6118 {
6120
6121 /*
6122 * Make sure a snapshot has been established in case trigger
6123 * functions need one. Note that we avoid setting a snapshot if
6124 * we don't find at least one trigger that has to be fired now.
6125 * This is so that BEGIN; SET CONSTRAINTS ...; SET TRANSACTION
6126 * ISOLATION LEVEL SERIALIZABLE; ... works properly. (If we are
6127 * at the start of a transaction it's not possible for any trigger
6128 * events to be queued yet.)
6129 */
6130 if (!snapshot_set)
6131 {
6133 snapshot_set = true;
6134 }
6135
6136 /*
6137 * We can delete fired events if we are at top transaction level,
6138 * but we'd better not if inside a subtransaction, since the
6139 * subtransaction could later get rolled back.
6140 */
6142 !IsSubTransaction()))
6143 break; /* all fired */
6144 }
6145
6146 /*
6147 * Flush any fast-path batches accumulated by the triggers just fired.
6148 */
6153
6154 if (snapshot_set)
6156 }
6157}
6158
6159/* ----------
6160 * AfterTriggerPendingOnRel()
6161 * Test to see if there are any pending after-trigger events for rel.
6162 *
6163 * This is used by TRUNCATE, CLUSTER, ALTER TABLE, etc to detect whether
6164 * it is unsafe to perform major surgery on a relation. Note that only
6165 * local pending events are examined. We assume that having exclusive lock
6166 * on a rel guarantees there are no unserviced events in other backends ---
6167 * but having a lock does not prevent there being such events in our own.
6168 *
6169 * In some scenarios it'd be reasonable to remove pending events (more
6170 * specifically, mark them DONE by the current subxact) but without a lot
6171 * of knowledge of the trigger semantics we can't do this in general.
6172 * ----------
6173 */
6174bool
6176{
6177 AfterTriggerEvent event;
6179 int depth;
6180
6181 /* Scan queued events */
6183 {
6185
6186 /*
6187 * We can ignore completed events. (Even if a DONE flag is rolled
6188 * back by subxact abort, it's OK because the effects of the TRUNCATE
6189 * or whatever must get rolled back too.)
6190 */
6191 if (event->ate_flags & AFTER_TRIGGER_DONE)
6192 continue;
6193
6194 if (evtshared->ats_relid == relid)
6195 return true;
6196 }
6197
6198 /*
6199 * Also scan events queued by incomplete queries. This could only matter
6200 * if TRUNCATE/etc is executed by a function or trigger within an updating
6201 * query on the same relation, which is pretty perverse, but let's check.
6202 */
6203 for (depth = 0; depth <= afterTriggers.query_depth && depth < afterTriggers.maxquerydepth; depth++)
6204 {
6206 {
6208
6209 if (event->ate_flags & AFTER_TRIGGER_DONE)
6210 continue;
6211
6212 if (evtshared->ats_relid == relid)
6213 return true;
6214 }
6215 }
6216
6217 return false;
6218}
6219
6220/* ----------
6221 * AfterTriggerSaveEvent()
6222 *
6223 * Called by ExecA[RS]...Triggers() to queue up the triggers that should
6224 * be fired for an event.
6225 *
6226 * NOTE: this is called whenever there are any triggers associated with
6227 * the event (even if they are disabled). This function decides which
6228 * triggers actually need to be queued. It is also called after each row,
6229 * even if there are no triggers for that event, if there are any AFTER
6230 * STATEMENT triggers for the statement which use transition tables, so that
6231 * the transition tuplestores can be built. Furthermore, if the transition
6232 * capture is happening for UPDATEd rows being moved to another partition due
6233 * to the partition-key being changed, then this function is called once when
6234 * the row is deleted (to capture OLD row), and once when the row is inserted
6235 * into another partition (to capture NEW row). This is done separately because
6236 * DELETE and INSERT happen on different tables.
6237 *
6238 * Transition tuplestores are built now, rather than when events are pulled
6239 * off of the queue because AFTER ROW triggers are allowed to select from the
6240 * transition tables for the statement.
6241 *
6242 * This contains special support to queue the update events for the case where
6243 * a partitioned table undergoing a cross-partition update may have foreign
6244 * keys pointing into it. Normally, a partitioned table's row triggers are
6245 * not fired because the leaf partition(s) which are modified as a result of
6246 * the operation on the partitioned table contain the same triggers which are
6247 * fired instead. But that general scheme can cause problematic behavior with
6248 * foreign key triggers during cross-partition updates, which are implemented
6249 * as DELETE on the source partition followed by INSERT into the destination
6250 * partition. Specifically, firing DELETE triggers would lead to the wrong
6251 * foreign key action to be enforced considering that the original command is
6252 * UPDATE; in this case, this function is called with relinfo as the
6253 * partitioned table, and src_partinfo and dst_partinfo referring to the
6254 * source and target leaf partitions, respectively.
6255 *
6256 * is_crosspart_update is true either when a DELETE event is fired on the
6257 * source partition (which is to be ignored) or an UPDATE event is fired on
6258 * the root partitioned table.
6259 * ----------
6260 */
6261static void
6265 int event, bool row_trigger,
6268 TransitionCaptureState *transition_capture,
6270{
6271 Relation rel = relinfo->ri_RelationDesc;
6272 TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
6275 char relkind = rel->rd_rel->relkind;
6276 int tgtype_event;
6277 int tgtype_level;
6278 int i;
6279 Tuplestorestate *fdw_tuplestore = NULL;
6280
6281 /*
6282 * Check state. We use a normal test not Assert because it is possible to
6283 * reach here in the wrong state given misconfigured RI triggers, in
6284 * particular deferring a cascade action trigger.
6285 */
6286 if (afterTriggers.query_depth < 0)
6287 elog(ERROR, "AfterTriggerSaveEvent() called outside of query");
6288
6289 /* Be sure we have enough space to record events at this query depth. */
6292
6293 /*
6294 * If the directly named relation has any triggers with transition tables,
6295 * then we need to capture transition tuples.
6296 */
6297 if (row_trigger && transition_capture != NULL)
6298 {
6300
6301 /*
6302 * Capture the old tuple in the appropriate transition table based on
6303 * the event.
6304 */
6305 if (!TupIsNull(oldslot))
6306 {
6307 Tuplestorestate *old_tuplestore;
6308
6309 old_tuplestore = GetAfterTriggersTransitionTable(event,
6310 oldslot,
6311 NULL,
6312 transition_capture);
6313 TransitionTableAddTuple(estate, event, transition_capture, relinfo,
6314 oldslot, NULL, old_tuplestore);
6315 }
6316
6317 /*
6318 * Capture the new tuple in the appropriate transition table based on
6319 * the event.
6320 */
6321 if (!TupIsNull(newslot))
6322 {
6323 Tuplestorestate *new_tuplestore;
6324
6325 new_tuplestore = GetAfterTriggersTransitionTable(event,
6326 NULL,
6327 newslot,
6328 transition_capture);
6329 TransitionTableAddTuple(estate, event, transition_capture, relinfo,
6330 newslot, original_insert_tuple, new_tuplestore);
6331 }
6332
6333 /*
6334 * If transition tables are the only reason we're here, return. As
6335 * mentioned above, we can also be here during update tuple routing in
6336 * presence of transition tables, in which case this function is
6337 * called separately for OLD and NEW, so we expect exactly one of them
6338 * to be NULL.
6339 */
6340 if (trigdesc == NULL ||
6341 (event == TRIGGER_EVENT_DELETE && !trigdesc->trig_delete_after_row) ||
6342 (event == TRIGGER_EVENT_INSERT && !trigdesc->trig_insert_after_row) ||
6343 (event == TRIGGER_EVENT_UPDATE && !trigdesc->trig_update_after_row) ||
6345 return;
6346 }
6347
6348 /*
6349 * We normally don't see partitioned tables here for row level triggers
6350 * except in the special case of a cross-partition update. In that case,
6351 * nodeModifyTable.c:ExecCrossPartitionUpdateForeignKey() calls here to
6352 * queue an update event on the root target partitioned table, also
6353 * passing the source and destination partitions and their tuples.
6354 */
6356 rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE ||
6358 TRIGGER_FIRED_BY_UPDATE(event) &&
6360
6361 /*
6362 * Validate the event code and collect the associated tuple CTIDs.
6363 *
6364 * The event code will be used both as a bitmask and an array offset, so
6365 * validation is important to make sure we don't walk off the edge of our
6366 * arrays.
6367 *
6368 * Also, if we're considering statement-level triggers, check whether we
6369 * already queued a set of them for this event, and cancel the prior set
6370 * if so. This preserves the behavior that statement-level triggers fire
6371 * just once per statement and fire after row-level triggers.
6372 */
6373 switch (event)
6374 {
6377 if (row_trigger)
6378 {
6379 Assert(oldslot == NULL);
6380 Assert(newslot != NULL);
6381 ItemPointerCopy(&(newslot->tts_tid), &(new_event.ate_ctid1));
6382 ItemPointerSetInvalid(&(new_event.ate_ctid2));
6383 }
6384 else
6385 {
6386 Assert(oldslot == NULL);
6387 Assert(newslot == NULL);
6388 ItemPointerSetInvalid(&(new_event.ate_ctid1));
6389 ItemPointerSetInvalid(&(new_event.ate_ctid2));
6391 CMD_INSERT, event);
6392 }
6393 break;
6396 if (row_trigger)
6397 {
6398 Assert(oldslot != NULL);
6399 Assert(newslot == NULL);
6400 ItemPointerCopy(&(oldslot->tts_tid), &(new_event.ate_ctid1));
6401 ItemPointerSetInvalid(&(new_event.ate_ctid2));
6402 }
6403 else
6404 {
6405 Assert(oldslot == NULL);
6406 Assert(newslot == NULL);
6407 ItemPointerSetInvalid(&(new_event.ate_ctid1));
6408 ItemPointerSetInvalid(&(new_event.ate_ctid2));
6410 CMD_DELETE, event);
6411 }
6412 break;
6415 if (row_trigger)
6416 {
6417 Assert(oldslot != NULL);
6418 Assert(newslot != NULL);
6419 ItemPointerCopy(&(oldslot->tts_tid), &(new_event.ate_ctid1));
6420 ItemPointerCopy(&(newslot->tts_tid), &(new_event.ate_ctid2));
6421
6422 /*
6423 * Also remember the OIDs of partitions to fetch these tuples
6424 * out of later in AfterTriggerExecute().
6425 */
6426 if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6427 {
6429 new_event.ate_src_part =
6430 RelationGetRelid(src_partinfo->ri_RelationDesc);
6431 new_event.ate_dst_part =
6432 RelationGetRelid(dst_partinfo->ri_RelationDesc);
6433 }
6434 }
6435 else
6436 {
6437 Assert(oldslot == NULL);
6438 Assert(newslot == NULL);
6439 ItemPointerSetInvalid(&(new_event.ate_ctid1));
6440 ItemPointerSetInvalid(&(new_event.ate_ctid2));
6442 CMD_UPDATE, event);
6443 }
6444 break;
6447 Assert(oldslot == NULL);
6448 Assert(newslot == NULL);
6449 ItemPointerSetInvalid(&(new_event.ate_ctid1));
6450 ItemPointerSetInvalid(&(new_event.ate_ctid2));
6451 break;
6452 default:
6453 elog(ERROR, "invalid after-trigger event code: %d", event);
6454 tgtype_event = 0; /* keep compiler quiet */
6455 break;
6456 }
6457
6458 /* Determine flags */
6459 if (!(relkind == RELKIND_FOREIGN_TABLE && row_trigger))
6460 {
6461 if (row_trigger && event == TRIGGER_EVENT_UPDATE)
6462 {
6463 if (relkind == RELKIND_PARTITIONED_TABLE)
6465 else
6466 new_event.ate_flags = AFTER_TRIGGER_2CTID;
6467 }
6468 else
6469 new_event.ate_flags = AFTER_TRIGGER_1CTID;
6470 }
6471
6472 /* else, we'll initialize ate_flags for each trigger */
6473
6475
6476 /*
6477 * Must convert/copy the source and destination partition tuples into the
6478 * root partitioned table's format/slot, because the processing in the
6479 * loop below expects both oldslot and newslot tuples to be in that form.
6480 */
6481 if (row_trigger && rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6482 {
6484 TupleConversionMap *map;
6485
6488 if (map)
6490 oldslot,
6491 rootslot);
6492 else
6494
6497 if (map)
6499 newslot,
6500 rootslot);
6501 else
6503 }
6504
6505 for (i = 0; i < trigdesc->numtriggers; i++)
6506 {
6507 Trigger *trigger = &trigdesc->triggers[i];
6508
6509 if (!TRIGGER_TYPE_MATCHES(trigger->tgtype,
6512 tgtype_event))
6513 continue;
6514 if (!TriggerEnabled(estate, relinfo, trigger, event,
6516 continue;
6517
6518 if (relkind == RELKIND_FOREIGN_TABLE && row_trigger)
6519 {
6520 if (fdw_tuplestore == NULL)
6521 {
6522 fdw_tuplestore = GetCurrentFDWTuplestore();
6524 }
6525 else
6526 /* subsequent event for the same tuple */
6528 }
6529
6530 /*
6531 * If the trigger is a foreign key enforcement trigger, there are
6532 * certain cases where we can skip queueing the event because we can
6533 * tell by inspection that the FK constraint will still pass. There
6534 * are also some cases during cross-partition updates of a partitioned
6535 * table where queuing the event can be skipped.
6536 */
6538 {
6539 switch (RI_FKey_trigger_type(trigger->tgfoid))
6540 {
6541 case RI_TRIGGER_PK:
6542
6543 /*
6544 * For cross-partitioned updates of partitioned PK table,
6545 * skip the event fired by the component delete on the
6546 * source leaf partition unless the constraint originates
6547 * in the partition itself (!tgisclone), because the
6548 * update event that will be fired on the root
6549 * (partitioned) target table will be used to perform the
6550 * necessary foreign key enforcement action.
6551 */
6552 if (is_crosspart_update &&
6553 TRIGGER_FIRED_BY_DELETE(event) &&
6554 trigger->tgisclone)
6555 continue;
6556
6557 /* Update or delete on trigger's PK table */
6559 oldslot, newslot))
6560 {
6561 /* skip queuing this event */
6562 continue;
6563 }
6564 break;
6565
6566 case RI_TRIGGER_FK:
6567
6568 /*
6569 * Update on trigger's FK table. We can skip the update
6570 * event fired on a partitioned table during a
6571 * cross-partition of that table, because the insert event
6572 * that is fired on the destination leaf partition would
6573 * suffice to perform the necessary foreign key check.
6574 * Moreover, RI_FKey_fk_upd_check_required() expects to be
6575 * passed a tuple that contains system attributes, most of
6576 * which are not present in the virtual slot belonging to
6577 * a partitioned table.
6578 */
6579 if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE ||
6581 oldslot, newslot))
6582 {
6583 /* skip queuing this event */
6584 continue;
6585 }
6586 break;
6587
6588 case RI_TRIGGER_NONE:
6589
6590 /*
6591 * Not an FK trigger. No need to queue the update event
6592 * fired during a cross-partitioned update of a
6593 * partitioned table, because the same row trigger must be
6594 * present in the leaf partition(s) that are affected as
6595 * part of this update and the events fired on them are
6596 * queued instead.
6597 */
6598 if (row_trigger &&
6599 rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
6600 continue;
6601 break;
6602 }
6603 }
6604
6605 /*
6606 * If the trigger is a deferred unique constraint check trigger, only
6607 * queue it if the unique constraint was potentially violated, which
6608 * we know from index insertion time.
6609 */
6610 if (trigger->tgfoid == F_UNIQUE_KEY_RECHECK)
6611 {
6612 if (!list_member_oid(recheckIndexes, trigger->tgconstrindid))
6613 continue; /* Uniqueness definitely not violated */
6614 }
6615
6616 /*
6617 * Fill in event structure and add it to the current query's queue.
6618 * Note we set ats_table to NULL whenever this trigger doesn't use
6619 * transition tables, to improve sharability of the shared event data.
6620 */
6621 new_shared.ats_event =
6622 (event & TRIGGER_EVENT_OPMASK) |
6624 (trigger->tgdeferrable ? AFTER_TRIGGER_DEFERRABLE : 0) |
6625 (trigger->tginitdeferred ? AFTER_TRIGGER_INITDEFERRED : 0);
6626 new_shared.ats_tgoid = trigger->tgoid;
6627 new_shared.ats_relid = RelationGetRelid(rel);
6628 new_shared.ats_rolid = GetUserId();
6629 new_shared.ats_firing_id = 0;
6630 if ((trigger->tgoldtable || trigger->tgnewtable) &&
6631 transition_capture != NULL)
6632 {
6633 switch (event)
6634 {
6636 new_shared.ats_table = transition_capture->tcs_insert_private;
6637 break;
6639 new_shared.ats_table = transition_capture->tcs_update_private;
6640 break;
6642 new_shared.ats_table = transition_capture->tcs_delete_private;
6643 break;
6644 default:
6645 /* Must be TRUNCATE, see switch above */
6646 new_shared.ats_table = NULL;
6647 break;
6648 }
6649 }
6650 else
6651 new_shared.ats_table = NULL;
6652 new_shared.ats_modifiedcols = modifiedCols;
6653
6656 }
6657
6658 /*
6659 * Finally, spool any foreign tuple(s). The tuplestore squashes them to
6660 * minimal tuples, so this loses any system columns. The executor lost
6661 * those columns before us, for an unrelated reason, so this is fine.
6662 */
6663 if (fdw_tuplestore)
6664 {
6665 if (oldslot != NULL)
6666 tuplestore_puttupleslot(fdw_tuplestore, oldslot);
6667 if (newslot != NULL)
6668 tuplestore_puttupleslot(fdw_tuplestore, newslot);
6669 }
6670}
6671
6672/*
6673 * Detect whether we already queued BEFORE STATEMENT triggers for the given
6674 * relation + operation, and set the flag so the next call will report "true".
6675 */
6676static bool
6678{
6679 bool result;
6681
6682 /* Check state, like AfterTriggerSaveEvent. */
6683 if (afterTriggers.query_depth < 0)
6684 elog(ERROR, "before_stmt_triggers_fired() called outside of query");
6685
6686 /* Be sure we have enough space to record events at this query depth. */
6689
6690 /*
6691 * We keep this state in the AfterTriggersTableData that also holds
6692 * transition tables for the relation + operation. In this way, if we are
6693 * forced to make a new set of transition tables because more tuples get
6694 * entered after we've already fired triggers, we will allow a new set of
6695 * statement triggers to get queued.
6696 */
6697 table = GetAfterTriggersTableData(relid, cmdType);
6698 result = table->before_trig_done;
6699 table->before_trig_done = true;
6700 return result;
6701}
6702
6703/*
6704 * If we previously queued a set of AFTER STATEMENT triggers for the given
6705 * relation + operation, and they've not been fired yet, cancel them. The
6706 * caller will queue a fresh set that's after any row-level triggers that may
6707 * have been queued by the current sub-statement, preserving (as much as
6708 * possible) the property that AFTER ROW triggers fire before AFTER STATEMENT
6709 * triggers, and that the latter only fire once. This deals with the
6710 * situation where several FK enforcement triggers sequentially queue triggers
6711 * for the same table into the same trigger query level. We can't fully
6712 * prevent odd behavior though: if there are AFTER ROW triggers taking
6713 * transition tables, we don't want to change the transition tables once the
6714 * first such trigger has seen them. In such a case, any additional events
6715 * will result in creating new transition tables and allowing new firings of
6716 * statement triggers.
6717 *
6718 * This also saves the current event list location so that a later invocation
6719 * of this function can cheaply find the triggers we're about to queue and
6720 * cancel them.
6721 */
6722static void
6724{
6727
6728 /*
6729 * We keep this state in the AfterTriggersTableData that also holds
6730 * transition tables for the relation + operation. In this way, if we are
6731 * forced to make a new set of transition tables because more tuples get
6732 * entered after we've already fired triggers, we will allow a new set of
6733 * statement triggers to get queued without canceling the old ones.
6734 */
6735 table = GetAfterTriggersTableData(relid, cmdType);
6736
6737 if (table->after_trig_done)
6738 {
6739 /*
6740 * We want to start scanning from the tail location that existed just
6741 * before we inserted any statement triggers. But the events list
6742 * might've been entirely empty then, in which case scan from the
6743 * current head.
6744 */
6745 AfterTriggerEvent event;
6747
6748 if (table->after_trig_events.tail)
6749 {
6750 chunk = table->after_trig_events.tail;
6751 event = (AfterTriggerEvent) table->after_trig_events.tailfree;
6752 }
6753 else
6754 {
6755 chunk = qs->events.head;
6756 event = NULL;
6757 }
6758
6759 for_each_chunk_from(chunk)
6760 {
6761 if (event == NULL)
6762 event = (AfterTriggerEvent) CHUNK_DATA_START(chunk);
6763 for_each_event_from(event, chunk)
6764 {
6766
6767 /*
6768 * Exit loop when we reach events that aren't AS triggers for
6769 * the target relation.
6770 */
6771 if (evtshared->ats_relid != relid)
6772 goto done;
6773 if ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) != tgevent)
6774 goto done;
6775 if (!TRIGGER_FIRED_FOR_STATEMENT(evtshared->ats_event))
6776 goto done;
6777 if (!TRIGGER_FIRED_AFTER(evtshared->ats_event))
6778 goto done;
6779 /* OK, mark it DONE */
6780 event->ate_flags &= ~AFTER_TRIGGER_IN_PROGRESS;
6781 event->ate_flags |= AFTER_TRIGGER_DONE;
6782 }
6783 /* signal we must reinitialize event ptr for next chunk */
6784 event = NULL;
6785 }
6786 }
6787done:
6788
6789 /* In any case, save current insertion point for next time */
6790 table->after_trig_done = true;
6791 table->after_trig_events = qs->events;
6792}
6793
6794/*
6795 * GUC assign_hook for session_replication_role
6796 */
6797void
6799{
6800 /*
6801 * Must flush the plan cache when changing replication role; but don't
6802 * flush unnecessarily.
6803 */
6806}
6807
6808/*
6809 * SQL function pg_trigger_depth()
6810 */
6811Datum
6816
6817/*
6818 * Check whether a trigger modified a virtual generated column and replace the
6819 * value with null if so.
6820 *
6821 * We need to check this so that we don't end up storing a non-null value in a
6822 * virtual generated column.
6823 *
6824 * We don't need to check for stored generated columns, since those will be
6825 * overwritten later anyway.
6826 */
6827static HeapTuple
6829{
6830 if (!(tupdesc->constr && tupdesc->constr->has_generated_virtual))
6831 return tuple;
6832
6833 for (int i = 0; i < tupdesc->natts; i++)
6834 {
6835 if (TupleDescAttr(tupdesc, i)->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
6836 {
6837 if (!heap_attisnull(tuple, i + 1, tupdesc))
6838 {
6839 int replCol = i + 1;
6840 Datum replValue = 0;
6841 bool replIsnull = true;
6842
6843 tuple = heap_modify_tuple_by_cols(tuple, tupdesc, 1, &replCol, &replValue, &replIsnull);
6844 }
6845 }
6846 }
6847
6848 return tuple;
6849}
6850
6851/*
6852 * RegisterAfterTriggerBatchCallback
6853 * Register a function to be called when the current trigger-firing
6854 * batch completes.
6855 *
6856 * Must be called from within a trigger function's execution context
6857 * (i.e., while afterTriggers state is active).
6858 *
6859 * The callback list is cleared after invocation, so the caller must
6860 * re-register for each new batch if needed.
6861 */
6862void
6864 void *arg)
6865{
6868
6869 /*
6870 * Allocate in TopTransactionContext so the item survives for the duration
6871 * of the batch, which may span multiple trigger invocations.
6872 *
6873 * Must be called while afterTriggers is active; callbacks registered
6874 * outside a trigger-firing context would never fire.
6875 */
6879 item = palloc(sizeof(AfterTriggerCallbackItem));
6880 item->callback = callback;
6881 item->arg = arg;
6882 if (afterTriggers.query_depth >= 0)
6883 {
6886
6887 qs->batch_callbacks = lappend(qs->batch_callbacks, item);
6888 }
6889 else
6893}
6894
6895/*
6896 * FireAfterTriggerBatchCallbacks
6897 * Invoke all callbacks in the given list.
6898 *
6899 * Memory cleanup of the list and its items is handled by the caller
6900 * (AfterTriggerFreeQuery for query-level callbacks, AfterTriggerEndXact
6901 * for top-level deferred callbacks).
6902 */
6903static void
6905{
6906 ListCell *lc;
6907
6910 foreach(lc, callbacks)
6911 {
6913
6914 item->callback(item->arg);
6915 }
6917}
6918
6919/*
6920 * AfterTriggerIsActive
6921 * Returns true if we're inside the after-trigger framework where
6922 * registered batch callbacks will actually be invoked.
6923 *
6924 * This is false during validateForeignKeyConstraint(), which calls
6925 * RI trigger functions directly outside the after-trigger framework.
6926 */
6927bool
6929{
6930 return afterTriggers.firing_depth > 0;
6931}
AclResult
Definition acl.h:183
@ ACLCHECK_OK
Definition acl.h:184
@ ACLCHECK_NOT_OWNER
Definition acl.h:186
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition aclchk.c:2672
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition aclchk.c:3902
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition aclchk.c:4156
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition aclchk.c:4105
#define InvalidAttrNumber
Definition attnum.h:23
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:143
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:645
Bitmapset * bms_copy(const Bitmapset *a)
Definition bitmapset.c:123
static Datum values[MAXATTR]
Definition bootstrap.c:190
#define CStringGetTextDatum(s)
Definition builtins.h:98
#define TextDatumGetCString(d)
Definition builtins.h:99
Datum byteain(PG_FUNCTION_ARGS)
Definition bytea.c:201
#define NameStr(name)
Definition c.h:894
#define Min(x, y)
Definition c.h:1131
#define Max(x, y)
Definition c.h:1125
#define Assert(condition)
Definition c.h:1002
#define FLEXIBLE_ARRAY_MEMBER
Definition c.h:617
int16_t int16
Definition c.h:678
#define unlikely(x)
Definition c.h:497
uint32_t uint32
Definition c.h:683
#define pg_fallthrough
Definition c.h:220
uint32 CommandId
Definition c.h:809
#define OidIsValid(objectId)
Definition c.h:917
size_t Size
Definition c.h:748
bool IsConflictLogTableClass(Form_pg_class reltuple)
Definition catalog.c:242
bool IsSystemRelation(Relation relation)
Definition catalog.c:74
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition catalog.c:475
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
Definition catalog.c:86
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
@ DEPENDENCY_AUTO
Definition dependency.h:34
@ DEPENDENCY_INTERNAL
Definition dependency.h:35
@ DEPENDENCY_PARTITION_PRI
Definition dependency.h:36
@ DEPENDENCY_PARTITION_SEC
Definition dependency.h:37
@ DEPENDENCY_NORMAL
Definition dependency.h:33
Datum arg
Definition elog.c:1323
int errcode(int sqlerrcode)
Definition elog.c:875
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define PG_TRY(...)
Definition elog.h:374
#define PG_END_TRY(...)
Definition elog.h:399
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define NOTICE
Definition elog.h:36
#define PG_FINALLY(...)
Definition elog.h:391
#define ereport(elevel,...)
Definition elog.h:152
ExprState * ExecPrepareQual(List *qual, EState *estate)
Definition execExpr.c:793
LockTupleMode ExecUpdateLockMode(EState *estate, ResultRelInfo *relinfo)
Definition execMain.c:2596
ResultRelInfo * ExecGetTriggerResultRel(EState *estate, Oid relid, ResultRelInfo *rootRelInfo)
Definition execMain.c:1409
bool ExecPartitionCheck(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool emitError)
Definition execMain.c:1922
TupleTableSlot * EvalPlanQual(EPQState *epqstate, Relation relation, Index rti, TupleTableSlot *inputslot)
Definition execMain.c:2715
void ExecCloseResultRelations(EState *estate)
Definition execMain.c:1641
void ExecResetTupleTable(List *tupleTable, bool shouldFree)
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
const TupleTableSlotOps TTSOpsVirtual
Definition execTuples.c:84
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
HeapTuple ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree)
const TupleTableSlotOps TTSOpsMinimalTuple
Definition execTuples.c:86
void ExecForceStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot, bool shouldFree)
TupleTableSlot * ExecGetTriggerNewSlot(EState *estate, ResultRelInfo *relInfo)
Definition execUtils.c:1252
TupleConversionMap * ExecGetChildToRootMap(ResultRelInfo *resultRelInfo)
Definition execUtils.c:1326
TupleTableSlot * ExecGetTriggerOldSlot(EState *estate, ResultRelInfo *relInfo)
Definition execUtils.c:1230
void FreeExecutorState(EState *estate)
Definition execUtils.c:197
Bitmapset * ExecGetAllUpdatedCols(ResultRelInfo *relinfo, EState *estate)
Definition execUtils.c:1444
EState * CreateExecutorState(void)
Definition execUtils.c:90
#define GetPerTupleExprContext(estate)
Definition executor.h:665
#define GetPerTupleMemoryContext(estate)
Definition executor.h:670
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition executor.h:527
#define palloc_object(type)
Definition fe_memutils.h:89
#define palloc0_object(type)
Definition fe_memutils.h:90
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition fmgr.c:129
#define DatumGetByteaPP(X)
Definition fmgr.h:292
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition fmgr.h:150
#define DirectFunctionCall1(func, arg1)
Definition fmgr.h:688
#define LOCAL_FCINFO(name, nargs)
Definition fmgr.h:110
#define FunctionCallInvoke(fcinfo)
Definition fmgr.h:172
#define PG_RETURN_INT32(x)
Definition fmgr.h:355
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:604
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:515
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition genam.c:388
bool allowSystemTableMods
Definition globals.c:132
int work_mem
Definition globals.c:133
Oid MyDatabaseId
Definition globals.c:96
#define newval
HeapTuple heap_copytuple(HeapTuple tuple)
Definition heaptuple.c:686
HeapTuple heap_modify_tuple_by_cols(HeapTuple tuple, TupleDesc tupleDesc, int nCols, const int *replCols, const Datum *replValues, const bool *replIsnull)
Definition heaptuple.c:1186
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1025
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition heaptuple.c:456
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1372
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
static Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
#define stmt
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
Definition indexing.c:313
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition indexing.c:233
void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid)
Definition indexing.c:365
long val
Definition informix.c:689
void InstrStartTrigger(TriggerInstrumentation *tginstr)
Definition instrument.c:265
void InstrStopTrigger(TriggerInstrumentation *tginstr, int64 firings)
Definition instrument.c:271
int2vector * buildint2vector(const int16 *int2s, int n)
Definition int.c:114
void CacheInvalidateRelcache(Relation relation)
Definition inval.c:1632
void CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
Definition inval.c:1666
int j
Definition isn.c:78
int i
Definition isn.c:77
static void ItemPointerSetInvalid(ItemPointerData *pointer)
Definition itemptr.h:184
static void ItemPointerCopy(const ItemPointerData *fromPointer, ItemPointerData *toPointer)
Definition itemptr.h:172
static bool ItemPointerIsValid(const ItemPointerData *pointer)
Definition itemptr.h:83
List * lappend(List *list, void *datum)
Definition list.c:339
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
void list_free(List *list)
Definition list.c:1546
bool list_member_oid(const List *list, Oid datum)
Definition list.c:722
void list_free_deep(List *list)
Definition list.c:1560
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition lmgr.c:107
int LOCKMODE
Definition lockdefs.h:26
#define NoLock
Definition lockdefs.h:34
#define AccessExclusiveLock
Definition lockdefs.h:43
#define ShareRowExclusiveLock
Definition lockdefs.h:41
#define AccessShareLock
Definition lockdefs.h:36
#define RowExclusiveLock
Definition lockdefs.h:38
@ LockWaitBlock
Definition lockoptions.h:40
LockTupleMode
Definition lockoptions.h:51
@ LockTupleExclusive
Definition lockoptions.h:59
char * get_rel_name(Oid relid)
Definition lsyscache.c:2242
char * get_database_name(Oid dbid)
Definition lsyscache.c:1392
char get_rel_relkind(Oid relid)
Definition lsyscache.c:2317
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3682
Oid get_func_rettype(Oid funcid)
Definition lsyscache.c:1969
Alias * makeAlias(const char *aliasname, List *colnames)
Definition makefuncs.c:438
List * make_ands_implicit(Expr *clause)
Definition makefuncs.c:810
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition mcxt.c:1235
void MemoryContextReset(MemoryContext context)
Definition mcxt.c:406
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition mcxt.c:1269
MemoryContext TopTransactionContext
Definition mcxt.c:172
char * pstrdup(const char *in)
Definition mcxt.c:1910
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1635
void pfree(void *pointer)
Definition mcxt.c:1619
void * palloc(Size size)
Definition mcxt.c:1390
MemoryContext CurTransactionContext
Definition mcxt.c:173
MemoryContext CurrentMemoryContext
Definition mcxt.c:161
MemoryContext CacheMemoryContext
Definition mcxt.c:170
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:475
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
#define ALLOCSET_SMALL_SIZES
Definition memutils.h:170
#define SECURITY_LOCAL_USERID_CHANGE
Definition miscadmin.h:321
void GetUserIdAndSecContext(Oid *userid, int *sec_context)
Definition miscinit.c:613
bool InSecurityRestrictedOperation(void)
Definition miscinit.c:640
Oid GetUserId(void)
Definition miscinit.c:470
void SetUserIdAndSecContext(Oid userid, int sec_context)
Definition miscinit.c:620
Datum nameout(PG_FUNCTION_ARGS)
Definition name.c:71
void namestrcpy(Name name, const char *str)
Definition name.c:233
Datum namein(PG_FUNCTION_ARGS)
Definition name.c:48
char * NameListToString(const List *names)
Definition namespace.c:3666
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition namespace.c:3457
List * fetch_search_path(bool includeImplicit)
Definition namespace.c:4891
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition namespace.c:442
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition namespace.h:98
TupleTableSlot * ExecGetUpdateNewTuple(ResultRelInfo *relinfo, TupleTableSlot *planSlot, TupleTableSlot *oldSlot)
#define copyObject(obj)
Definition nodes.h:230
CmdType
Definition nodes.h:271
@ CMD_MERGE
Definition nodes.h:277
@ CMD_INSERT
Definition nodes.h:275
@ CMD_DELETE
Definition nodes.h:276
@ CMD_UPDATE
Definition nodes.h:274
static char * errmsg
#define InvokeObjectPostAlterHook(classId, objectId, subId)
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
ObjectType get_relkind_objtype(char relkind)
#define ObjectAddressSet(addr, class_id, object_id)
char * nodeToString(const void *obj)
Definition outfuncs.c:811
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
void assign_expr_collations(ParseState *pstate, Node *expr)
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool missing_ok)
void free_parsestate(ParseState *pstate)
Definition parse_node.c:72
int parser_errposition(ParseState *pstate, int location)
Definition parse_node.c:106
ParseState * make_parsestate(ParseState *parentParseState)
Definition parse_node.c:39
@ EXPR_KIND_TRIGGER_WHEN
Definition parse_node.h:78
void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
ParseNamespaceItem * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, LOCKMODE lockmode, Alias *alias, bool inh, bool inFromCl)
int attnameAttNum(Relation rd, const char *attname, bool sysColOK)
@ OBJECT_FUNCTION
#define ACL_EXECUTE
Definition parsenodes.h:83
#define ACL_TRIGGER
Definition parsenodes.h:82
PartitionDesc RelationGetPartitionDesc(Relation rel, bool omit_detached)
Definition partdesc.c:71
List * map_partition_varattnos(List *expr, int fromrel_varno, Relation to_rel, Relation from_rel)
Definition partition.c:222
Oid get_partition_parent(Oid relid, bool even_if_detached)
Definition partition.c:53
int16 attnum
int errdetail_relkind_not_supported(char relkind)
Definition pg_class.c:24
FormData_pg_class * Form_pg_class
Definition pg_class.h:160
#define NAMEDATALEN
Oid CreateConstraintEntry(const char *constraintName, Oid constraintNamespace, char constraintType, bool isDeferrable, bool isDeferred, bool isEnforced, bool isValidated, Oid parentConstrId, Oid relId, const int16 *constraintKey, int constraintNKeys, int constraintNTotalKeys, Oid domainId, Oid indexRelId, Oid foreignRelId, const int16 *foreignKey, const Oid *pfEqOp, const Oid *ppEqOp, const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, const int16 *fkDeleteSetCols, int numFkDeleteSetCols, char foreignMatchType, const Oid *exclOp, Node *conExpr, const char *conBin, bool conIsLocal, int16 conInhCount, bool conNoInherit, bool conPeriod, bool is_internal)
END_CATALOG_STRUCT typedef FormData_pg_constraint * Form_pg_constraint
const void size_t len
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition pg_depend.c:51
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition pg_depend.c:364
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition pg_depend.c:314
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
bool has_superclass(Oid relationId)
#define lfirst(lc)
Definition pg_list.h:172
#define lfirst_node(type, lc)
Definition pg_list.h:176
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
#define list_make1_oid(x1)
Definition pg_list.h:274
#define lfirst_oid(lc)
Definition pg_list.h:174
static const struct lconv_member_info table[]
END_CATALOG_STRUCT typedef FormData_pg_trigger * Form_pg_trigger
Definition pg_trigger.h:84
#define ERRCODE_T_R_SERIALIZATION_FAILURE
Definition pgbench.c:77
void pgstat_init_function_usage(FunctionCallInfo fcinfo, PgStat_FunctionCallUsage *fcu)
void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize)
void ResetPlanCache(void)
Definition plancache.c:2328
#define snprintf
Definition port.h:261
static Datum Int16GetDatum(int16 X)
Definition postgres.h:172
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
static char * DatumGetCString(Datum X)
Definition postgres.h:365
static Datum NameGetDatum(const NameData *X)
Definition postgres.h:406
uint64_t Datum
Definition postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
static Datum CStringGetDatum(const char *X)
Definition postgres.h:383
#define PointerGetDatum(X)
Definition postgres.h:354
static Datum CharGetDatum(char X)
Definition postgres.h:132
#define InvalidOid
unsigned int Oid
static void test(void)
static int fb(int x)
#define PRS2_OLD_VARNO
Definition primnodes.h:251
#define PRS2_NEW_VARNO
Definition primnodes.h:252
#define OUTER_VAR
Definition primnodes.h:244
#define INNER_VAR
Definition primnodes.h:243
void * stringToNode(const char *str)
Definition read.c:90
#define RelationHasReferenceCountZero(relation)
Definition rel.h:500
#define RelationGetRelid(relation)
Definition rel.h:516
#define RelationGetDescr(relation)
Definition rel.h:542
#define RelationGetRelationName(relation)
Definition rel.h:550
#define RelationGetNamespace(relation)
Definition rel.h:557
ResourceOwner CurrentResourceOwner
Definition resowner.c:173
ResourceOwner CurTransactionResourceOwner
Definition resowner.c:174
Node * expand_generated_columns_in_expr(Node *node, Relation rel, int rt_index)
void ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
bool RI_FKey_pk_upd_check_required(Trigger *trigger, Relation pk_rel, TupleTableSlot *oldslot, TupleTableSlot *newslot)
bool RI_FKey_fk_upd_check_required(Trigger *trigger, Relation fk_rel, TupleTableSlot *oldslot, TupleTableSlot *newslot)
int RI_FKey_trigger_type(Oid tgfoid)
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition scankey.c:76
Snapshot GetTransactionSnapshot(void)
Definition snapmgr.c:272
void PushActiveSnapshot(Snapshot snapshot)
Definition snapmgr.c:682
void PopActiveSnapshot(void)
Definition snapmgr.c:775
#define SnapshotAny
Definition snapmgr.h:33
void relation_close(Relation relation, LOCKMODE lockmode)
Definition relation.c:206
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition relation.c:48
#define BTEqualStrategyNumber
Definition stratnum.h:31
#define ERRCODE_DUPLICATE_OBJECT
Definition streamutil.c:30
AfterTriggerBatchCallback callback
Definition trigger.c:3973
struct AfterTriggerEventChunk * next
Definition trigger.c:3790
ItemPointerData ate_ctid1
Definition trigger.c:3752
ItemPointerData ate_ctid2
Definition trigger.c:3753
ItemPointerData ate_ctid1
Definition trigger.c:3760
ItemPointerData ate_ctid2
Definition trigger.c:3737
TriggerFlags ate_flags
Definition trigger.c:3735
ItemPointerData ate_ctid1
Definition trigger.c:3736
AfterTriggerEventChunk * head
Definition trigger.c:3802
AfterTriggerEventChunk * tail
Definition trigger.c:3803
TriggerEvent ats_event
Definition trigger.c:3722
struct AfterTriggersTableData * ats_table
Definition trigger.c:3727
CommandId ats_firing_id
Definition trigger.c:3726
Bitmapset * ats_modifiedcols
Definition trigger.c:3728
SetConstraintState state
Definition trigger.c:3909
AfterTriggersQueryData * query_stack
Definition trigger.c:3914
MemoryContext event_cxt
Definition trigger.c:3911
List * batch_callbacks
Definition trigger.c:3922
bool firing_batch_callbacks
Definition trigger.c:3924
CommandId firing_counter
Definition trigger.c:3908
AfterTriggersTransData * trans_stack
Definition trigger.c:3919
AfterTriggerEventList events
Definition trigger.c:3910
Tuplestorestate * fdw_tuplestore
Definition trigger.c:3938
AfterTriggerEventList events
Definition trigger.c:3937
Tuplestorestate * new_tuplestore
Definition trigger.c:3965
TupleTableSlot * storeslot
Definition trigger.c:3967
Tuplestorestate * old_tuplestore
Definition trigger.c:3963
AfterTriggerEventList after_trig_events
Definition trigger.c:3960
AfterTriggerEventList events
Definition trigger.c:3947
SetConstraintState state
Definition trigger.c:3946
CommandId firing_counter
Definition trigger.c:3949
MemoryContext es_query_cxt
Definition execnodes.h:747
List * es_tupleTable
Definition execnodes.h:749
CommandId es_output_cid
Definition execnodes.h:719
Snapshot es_snapshot
Definition execnodes.h:697
TupleTableSlot * ecxt_innertuple
Definition execnodes.h:289
TupleTableSlot * ecxt_outertuple
Definition execnodes.h:291
Oid fn_oid
Definition fmgr.h:59
ItemPointerData t_self
Definition htup.h:65
Definition pg_list.h:54
Definition nodes.h:133
const char * p_sourcetext
Definition parse_node.h:214
List * p_rtable
Definition parse_node.h:215
char * relname
Definition primnodes.h:84
char * catalogname
Definition primnodes.h:78
char * schemaname
Definition primnodes.h:81
TriggerDesc * trigdesc
Definition rel.h:117
TupleDesc rd_att
Definition rel.h:112
Oid rd_id
Definition rel.h:113
Form_pg_class rd_rel
Definition rel.h:111
SetConstraintTriggerData trigstates[FLEXIBLE_ARRAY_MEMBER]
Definition trigger.c:3658
CommandId cmax
Definition tableam.h:173
TupleTableSlot * tcs_original_insert_tuple
Definition trigger.h:76
struct AfterTriggersTableData * tcs_insert_private
Definition trigger.h:81
struct AfterTriggersTableData * tcs_update_private
Definition trigger.h:82
struct AfterTriggersTableData * tcs_delete_private
Definition trigger.h:83
Tuplestorestate * tg_oldtable
Definition trigger.h:41
NodeTag type
Definition trigger.h:33
Tuplestorestate * tg_newtable
Definition trigger.h:42
TriggerEvent tg_event
Definition trigger.h:34
Trigger * tg_trigger
Definition trigger.h:38
int numtriggers
Definition reltrigger.h:50
bool trig_delete_before_row
Definition reltrigger.h:66
bool trig_update_instead_row
Definition reltrigger.h:63
Trigger * triggers
Definition reltrigger.h:49
bool trig_delete_instead_row
Definition reltrigger.h:68
bool trig_update_after_row
Definition reltrigger.h:62
bool trig_insert_instead_row
Definition reltrigger.h:58
bool trig_update_new_table
Definition reltrigger.h:77
bool trig_insert_after_row
Definition reltrigger.h:57
bool trig_update_after_statement
Definition reltrigger.h:65
bool trig_update_before_row
Definition reltrigger.h:61
bool trig_truncate_before_statement
Definition reltrigger.h:72
bool trig_insert_new_table
Definition reltrigger.h:75
bool trig_update_before_statement
Definition reltrigger.h:64
bool trig_truncate_after_statement
Definition reltrigger.h:73
bool trig_insert_before_statement
Definition reltrigger.h:59
bool trig_delete_old_table
Definition reltrigger.h:78
bool trig_delete_after_row
Definition reltrigger.h:67
bool trig_insert_before_row
Definition reltrigger.h:56
bool trig_delete_after_statement
Definition reltrigger.h:70
bool trig_delete_before_statement
Definition reltrigger.h:69
bool trig_update_old_table
Definition reltrigger.h:76
bool trig_insert_after_statement
Definition reltrigger.h:60
Oid tgoid
Definition reltrigger.h:25
char * tgname
Definition reltrigger.h:27
Oid tgfoid
Definition reltrigger.h:28
bool has_generated_virtual
Definition tupdesc.h:47
AttrMap * attrMap
Definition tupconvert.h:28
TupleDesc outdesc
Definition tupconvert.h:27
TupleConstr * constr
Definition tupdesc.h:159
ParseLoc location
Definition primnodes.h:311
AttrNumber varattno
Definition primnodes.h:275
int varno
Definition primnodes.h:270
Definition c.h:835
bool superuser(void)
Definition superuser.c:47
#define FirstLowInvalidHeapAttributeNumber
Definition sysattr.h:27
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221
#define SearchSysCacheCopy1(cacheId, key1)
Definition syscache.h:91
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40
Relation table_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition table.c:83
TM_Result
Definition tableam.h:95
@ TM_Ok
Definition tableam.h:100
@ TM_Deleted
Definition tableam.h:115
@ TM_Updated
Definition tableam.h:112
@ TM_SelfModified
Definition tableam.h:106
@ TM_Invisible
Definition tableam.h:103
static TM_Result table_tuple_lock(Relation rel, ItemPointer tid, Snapshot snapshot, TupleTableSlot *slot, CommandId cid, LockTupleMode mode, LockWaitPolicy wait_policy, uint8 flags, TM_FailureData *tmfd)
Definition tableam.h:1646
#define TUPLE_LOCK_FLAG_FIND_LAST_VERSION
Definition tableam.h:299
static bool table_tuple_fetch_row_version(Relation rel, ItemPointer tid, Snapshot snapshot, TupleTableSlot *slot)
Definition tableam.h:1344
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
static SetConstraintState SetConstraintStateCopy(SetConstraintState origstate)
Definition trigger.c:5801
static void cancel_prior_stmt_triggers(Oid relid, CmdType cmdType, int tgevent)
Definition trigger.c:6723
static AfterTriggersData afterTriggers
Definition trigger.c:3977
#define AFTER_TRIGGER_FDW_FETCH
Definition trigger.c:3713
static SetConstraintState SetConstraintStateAddItem(SetConstraintState state, Oid tgoid, bool tgisdeferred)
Definition trigger.c:5821
#define AFTER_TRIGGER_IN_PROGRESS
Definition trigger.c:3710
static void renametrig_internal(Relation tgrel, Relation targetrel, HeapTuple trigtup, const char *newname, const char *expected_name)
Definition trigger.c:1609
bool ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot *newslot, TM_Result *tmresult, TM_FailureData *tmfd, bool is_merge_update)
Definition trigger.c:2998
TransitionCaptureState * MakeTransitionCaptureState(TriggerDesc *trigdesc, Oid relid, CmdType cmdType)
Definition trigger.c:5005
static void FireAfterTriggerBatchCallbacks(List *callbacks)
Definition trigger.c:6904
static bool GetTupleForTrigger(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tid, LockTupleMode lockmode, TupleTableSlot *oldslot, bool do_epq_recheck, TupleTableSlot **epqslot, TM_Result *tmresultp, TM_FailureData *tmfdp)
Definition trigger.c:3371
void AfterTriggerBeginXact(void)
Definition trigger.c:5131
void ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TransitionCaptureState *transition_capture, bool is_crosspart_update)
Definition trigger.c:2828
void ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
Definition trigger.c:2428
static void afterTriggerDeleteHeadEventChunk(AfterTriggersQueryData *qs)
Definition trigger.c:4313
static AfterTriggersTableData * GetAfterTriggersTableData(Oid relid, CmdType cmdType)
Definition trigger.c:4914
static Bitmapset * afterTriggerCopyBitmap(Bitmapset *src)
Definition trigger.c:4100
#define CHUNK_DATA_START(cptr)
Definition trigger.c:3797
static void RangeVarCallbackForRenameTrigger(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
Definition trigger.c:1434
bool ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition trigger.c:2492
void AfterTriggerEndSubXact(bool isCommit)
Definition trigger.c:5519
uint32 TriggerFlags
Definition trigger.c:3706
void ExecBSTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
Definition trigger.c:3307
void RegisterAfterTriggerBatchCallback(AfterTriggerBatchCallback callback, void *arg)
Definition trigger.c:6863
#define AFTER_TRIGGER_TUP_BITS
Definition trigger.c:3717
static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo, Trigger *trigger, TriggerEvent event, Bitmapset *modifiedCols, TupleTableSlot *oldslot, TupleTableSlot *newslot)
Definition trigger.c:3509
void FreeTriggerDesc(TriggerDesc *trigdesc)
Definition trigger.c:2172
bool ExecIRDeleteTriggers(EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple)
Definition trigger.c:2875
#define AFTER_TRIGGER_1CTID
Definition trigger.c:3714
bool AfterTriggerIsActive(void)
Definition trigger.c:6928
Datum pg_trigger_depth(PG_FUNCTION_ARGS)
Definition trigger.c:6812
void ExecBSDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
Definition trigger.c:2657
#define MAX_CHUNK_SIZE
ObjectAddress CreateTriggerFiringOn(const CreateTrigStmt *stmt, const char *queryString, Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid, Oid funcoid, Oid parentTriggerOid, Node *whenClause, bool isInternal, bool in_partition, char trigger_fires_when)
Definition trigger.c:179
void EnableDisableTrigger(Relation rel, const char *tgname, Oid tgparent, char fires_when, bool skip_system, bool recurse, LOCKMODE lockmode)
Definition trigger.c:1753
static void AfterTriggerFreeQuery(AfterTriggersQueryData *qs)
Definition trigger.c:5291
static void afterTriggerFreeEventList(AfterTriggerEventList *events)
Definition trigger.c:4252
const char * FindTriggerIncompatibleWithInheritance(TriggerDesc *trigdesc)
Definition trigger.c:2304
bool ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
Definition trigger.c:2596
#define GetTriggerSharedData(evt)
Definition trigger.c:3778
static int MyTriggerDepth
Definition trigger.c:68
#define for_each_chunk_from(cptr)
Definition trigger.c:3819
static bool afterTriggerMarkEvents(AfterTriggerEventList *events, AfterTriggerEventList *move_list, bool immediate_only)
Definition trigger.c:4661
static Tuplestorestate * GetAfterTriggersTransitionTable(int event, TupleTableSlot *oldslot, TupleTableSlot *newslot, TransitionCaptureState *transition_capture)
Definition trigger.c:5619
void ExecASTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
Definition trigger.c:3354
static bool afterTriggerInvokeEvents(AfterTriggerEventList *events, CommandId firing_id, EState *estate, bool delete_ok)
Definition trigger.c:4745
void ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo, ResultRelInfo *src_partinfo, ResultRelInfo *dst_partinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot *newslot, List *recheckIndexes, TransitionCaptureState *transition_capture, bool is_crosspart_update)
Definition trigger.c:3171
struct AfterTriggerSharedData * AfterTriggerShared
Definition trigger.c:3718
void AfterTriggerSetState(ConstraintsSetStmt *stmt)
Definition trigger.c:5851
bool ExecBRDeleteTriggers(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot **epqslot, TM_Result *tmresult, TM_FailureData *tmfd, bool is_merge_delete)
Definition trigger.c:2728
Oid get_trigger_oid(Oid relid, const char *trigname, bool missing_ok)
Definition trigger.c:1384
static void AfterTriggerExecute(EState *estate, AfterTriggerEvent event, ResultRelInfo *relInfo, ResultRelInfo *src_relInfo, ResultRelInfo *dst_relInfo, TriggerDesc *trigdesc, FmgrInfo *finfo, TriggerInstrumentation *instr, MemoryContext per_tuple_context, TupleTableSlot *trig_tuple_slot1, TupleTableSlot *trig_tuple_slot2)
Definition trigger.c:4375
static bool before_stmt_triggers_fired(Oid relid, CmdType cmdType)
Definition trigger.c:6677
static void afterTriggerAddEvent(AfterTriggerEventList *events, AfterTriggerEvent event, AfterTriggerShared evtshared)
Definition trigger.c:4125
struct SetConstraintTriggerData * SetConstraintTrigger
Definition trigger.c:3640
#define AFTER_TRIGGER_2CTID
Definition trigger.c:3715
#define SizeofTriggerEvent(evt)
Definition trigger.c:3769
int SessionReplicationRole
Definition trigger.c:65
static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata, int tgindx, FmgrInfo *finfo, TriggerInstrumentation *instr, MemoryContext per_tuple_context)
Definition trigger.c:2336
static bool afterTriggerCheckState(AfterTriggerShared evtshared)
Definition trigger.c:4055
void ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo, TransitionCaptureState *transition_capture)
Definition trigger.c:2980
static SetConstraintState SetConstraintStateCreate(int numalloc)
Definition trigger.c:5776
void ExecASDeleteTriggers(EState *estate, ResultRelInfo *relinfo, TransitionCaptureState *transition_capture)
Definition trigger.c:2708
ObjectAddress renametrig(RenameStmt *stmt)
Definition trigger.c:1494
void AfterTriggerFireDeferred(void)
Definition trigger.c:5354
static void TransitionTableAddTuple(EState *estate, int event, TransitionCaptureState *transition_capture, ResultRelInfo *relinfo, TupleTableSlot *slot, TupleTableSlot *original_insert_tuple, Tuplestorestate *tuplestore)
Definition trigger.c:5670
void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot, List *recheckIndexes, TransitionCaptureState *transition_capture)
Definition trigger.c:2570
void TriggerSetParentTrigger(Relation trigRel, Oid childTrigId, Oid parentTrigId, Oid childTableId)
Definition trigger.c:1234
static void afterTriggerRestoreEventList(AfterTriggerEventList *events, const AfterTriggerEventList *old_events)
Definition trigger.c:4273
static void SetTriggerFlags(TriggerDesc *trigdesc, Trigger *trigger)
Definition trigger.c:2040
#define for_each_event_from(eptr, cptr)
Definition trigger.c:3821
#define MIN_CHUNK_SIZE
static void renametrig_partition(Relation tgrel, Oid partitionId, Oid parentTriggerOid, const char *newname, const char *expected_name)
Definition trigger.c:1680
void ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo, TransitionCaptureState *transition_capture)
Definition trigger.c:2479
static Tuplestorestate * GetCurrentFDWTuplestore(void)
Definition trigger.c:4019
TriggerDesc * CopyTriggerDesc(TriggerDesc *trigdesc)
Definition trigger.c:2117
void assign_session_replication_role(int newval, void *extra)
Definition trigger.c:6798
bool ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple, TupleTableSlot *newslot)
Definition trigger.c:3241
void AfterTriggerEndXact(bool isCommit)
Definition trigger.c:5417
bool AfterTriggerPendingOnRel(Oid relid)
Definition trigger.c:6175
#define AFTER_TRIGGER_FDW_REUSE
Definition trigger.c:3712
void RelationBuildTriggers(Relation relation)
Definition trigger.c:1888
void AfterTriggerBeginSubXact(void)
Definition trigger.c:5471
static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, ResultRelInfo *src_partinfo, ResultRelInfo *dst_partinfo, int event, bool row_trigger, TupleTableSlot *oldslot, TupleTableSlot *newslot, List *recheckIndexes, Bitmapset *modifiedCols, TransitionCaptureState *transition_capture, bool is_crosspart_update)
Definition trigger.c:6262
static HeapTuple check_modified_virtual_generated(TupleDesc tupdesc, HeapTuple tuple)
Definition trigger.c:6828
ObjectAddress CreateTrigger(const CreateTrigStmt *stmt, const char *queryString, Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid, Oid funcoid, Oid parentTriggerOid, Node *whenClause, bool isInternal, bool in_partition)
Definition trigger.c:162
static TupleTableSlot * GetAfterTriggersStoreSlot(AfterTriggersTableData *table, TupleDesc tupdesc)
Definition trigger.c:4956
#define AFTER_TRIGGER_CP_UPDATE
Definition trigger.c:3716
void AfterTriggerEndQuery(EState *estate)
Definition trigger.c:5186
void RemoveTriggerById(Oid trigOid)
Definition trigger.c:1305
#define AFTER_TRIGGER_DONE
Definition trigger.c:3709
#define for_each_event_chunk(eptr, cptr, evtlist)
Definition trigger.c:3815
SetConstraintStateData * SetConstraintState
Definition trigger.c:3661
static void AfterTriggerEnlargeQueryState(void)
Definition trigger.c:5728
#define for_each_event(eptr, cptr)
Definition trigger.c:3810
struct AfterTriggerEventData * AfterTriggerEvent
Definition trigger.c:3731
#define for_each_chunk(cptr, evtlist)
Definition trigger.c:3808
void ExecBSUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
Definition trigger.c:2922
void AfterTriggerBeginQuery(void)
Definition trigger.c:5166
#define AFTER_TRIGGER_DEFERRABLE
Definition trigger.h:109
uint32 TriggerEvent
Definition trigger.h:29
#define TRIGGER_FIRED_FOR_STATEMENT(event)
Definition trigger.h:127
#define TRIGGER_EVENT_UPDATE
Definition trigger.h:96
#define RI_TRIGGER_FK
Definition trigger.h:287
#define TRIGGER_FIRED_BY_DELETE(event)
Definition trigger.h:115
#define SESSION_REPLICATION_ROLE_REPLICA
Definition trigger.h:143
#define TRIGGER_EVENT_DELETE
Definition trigger.h:95
#define TRIGGER_FIRES_ON_ORIGIN
Definition trigger.h:151
#define TRIGGER_EVENT_OPMASK
Definition trigger.h:98
#define TRIGGER_DISABLED
Definition trigger.h:154
#define RI_TRIGGER_NONE
Definition trigger.h:288
#define TRIGGER_FIRES_ON_REPLICA
Definition trigger.h:153
#define AFTER_TRIGGER_INITDEFERRED
Definition trigger.h:110
#define TRIGGER_EVENT_INSTEAD
Definition trigger.h:104
#define TRIGGER_EVENT_ROW
Definition trigger.h:100
#define TRIGGER_FIRED_AFTER(event)
Definition trigger.h:133
#define TRIGGER_EVENT_BEFORE
Definition trigger.h:102
#define TRIGGER_FIRED_BY_INSERT(event)
Definition trigger.h:112
#define SESSION_REPLICATION_ROLE_ORIGIN
Definition trigger.h:142
void(* AfterTriggerBatchCallback)(void *arg)
Definition trigger.h:307
#define TRIGGER_EVENT_INSERT
Definition trigger.h:94
#define TRIGGER_FIRED_BY_UPDATE(event)
Definition trigger.h:118
#define TRIGGER_EVENT_TRUNCATE
Definition trigger.h:97
#define RI_TRIGGER_PK
Definition trigger.h:286
TupleTableSlot * execute_attr_map_slot(AttrMap *attrMap, TupleTableSlot *in_slot, TupleTableSlot *out_slot)
Definition tupconvert.c:193
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition tupdesc.c:242
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)
void tuplestore_puttupleslot(Tuplestorestate *state, TupleTableSlot *slot)
Definition tuplestore.c:743
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition tuplestore.c:331
void tuplestore_end(Tuplestorestate *state)
Definition tuplestore.c:493
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition tuptable.h:476
#define TupIsNull(slot)
Definition tuptable.h:325
static TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition tuptable.h:544
static void ExecMaterializeSlot(TupleTableSlot *slot)
Definition tuptable.h:495
#define strVal(v)
Definition value.h:82
List * pull_var_clause(Node *node, int flags)
Definition var.c:653
static char * VARDATA_ANY(const void *PTR)
Definition varatt.h:486
const char * name
int GetCurrentTransactionNestLevel(void)
Definition xact.c:931
void CommandCounterIncrement(void)
Definition xact.c:1130
bool IsSubTransaction(void)
Definition xact.c:5098
#define IsolationUsesXactSnapshot()
Definition xact.h:52