1 /*-------------------------------------------------------------------------
4 * PostgreSQL TRIGGERs support code.
6 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
12 *-------------------------------------------------------------------------
16 #include "access/genam.h"
17 #include "access/heapam.h"
18 #include "access/sysattr.h"
19 #include "access/xact.h"
20 #include "catalog/catalog.h"
21 #include "catalog/dependency.h"
22 #include "catalog/indexing.h"
23 #include "catalog/pg_constraint.h"
24 #include "catalog/pg_proc.h"
25 #include "catalog/pg_trigger.h"
26 #include "catalog/pg_type.h"
27 #include "commands/dbcommands.h"
28 #include "commands/defrem.h"
29 #include "commands/trigger.h"
30 #include "executor/executor.h"
31 #include "executor/instrument.h"
32 #include "miscadmin.h"
33 #include "nodes/makefuncs.h"
34 #include "parser/parse_func.h"
36 #include "storage/bufmgr.h"
37 #include "tcop/utility.h"
38 #include "utils/acl.h"
39 #include "utils/builtins.h"
40 #include "utils/fmgroids.h"
41 #include "utils/inval.h"
42 #include "utils/lsyscache.h"
43 #include "utils/memutils.h"
44 #include "utils/snapmgr.h"
45 #include "utils/syscache.h"
46 #include "utils/tqual.h"
50 int SessionReplicationRole
= SESSION_REPLICATION_ROLE_ORIGIN
;
53 /* Local function prototypes */
54 static void ConvertTriggerToFK(CreateTrigStmt
*stmt
, Oid funcoid
);
55 static void InsertTrigger(TriggerDesc
*trigdesc
, Trigger
*trigger
, int indx
);
56 static HeapTuple
GetTupleForTrigger(EState
*estate
,
57 ResultRelInfo
*relinfo
,
59 TupleTableSlot
**newSlot
);
60 static HeapTuple
ExecCallTriggerFunc(TriggerData
*trigdata
,
63 Instrumentation
*instr
,
64 MemoryContext per_tuple_context
);
65 static void AfterTriggerSaveEvent(ResultRelInfo
*relinfo
, int event
,
66 bool row_trigger
, HeapTuple oldtup
, HeapTuple newtup
);
70 * Create a trigger. Returns the OID of the created trigger.
72 * constraintOid, if nonzero, says that this trigger is being created
73 * internally to implement that constraint. A suitable pg_depend entry will
74 * be made to link the trigger to that constraint. constraintOid is zero when
75 * executing a user-entered CREATE TRIGGER command.
77 * Note: can return InvalidOid if we decided to not create a trigger at all,
78 * but a foreign-key constraint. This is a kluge for backwards compatibility.
81 CreateTrigger(CreateTrigStmt
*stmt
, Oid constraintOid
)
85 Datum values
[Natts_pg_trigger
];
86 char nulls
[Natts_pg_trigger
];
94 Oid fargtypes
[1]; /* dummy */
100 char constrtrigname
[NAMEDATALEN
];
103 Oid constrrelid
= InvalidOid
;
104 ObjectAddress myself
,
107 rel
= heap_openrv(stmt
->relation
, AccessExclusiveLock
);
109 if (rel
->rd_rel
->relkind
!= RELKIND_RELATION
)
111 (errcode(ERRCODE_WRONG_OBJECT_TYPE
),
112 errmsg("\"%s\" is not a table",
113 RelationGetRelationName(rel
))));
115 if (!allowSystemTableMods
&& IsSystemRelation(rel
))
117 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
118 errmsg("permission denied: \"%s\" is a system catalog",
119 RelationGetRelationName(rel
))));
121 /* permission checks */
123 if (stmt
->isconstraint
)
125 /* constraint trigger */
126 aclresult
= pg_class_aclcheck(RelationGetRelid(rel
), GetUserId(),
128 if (aclresult
!= ACLCHECK_OK
)
129 aclcheck_error(aclresult
, ACL_KIND_CLASS
,
130 RelationGetRelationName(rel
));
132 if (stmt
->constrrel
!= NULL
)
134 constrrelid
= RangeVarGetRelid(stmt
->constrrel
, false);
136 aclresult
= pg_class_aclcheck(constrrelid
, GetUserId(),
138 if (aclresult
!= ACLCHECK_OK
)
139 aclcheck_error(aclresult
, ACL_KIND_CLASS
,
140 get_rel_name(constrrelid
));
145 /* regular trigger */
146 aclresult
= pg_class_aclcheck(RelationGetRelid(rel
), GetUserId(),
148 if (aclresult
!= ACLCHECK_OK
)
149 aclcheck_error(aclresult
, ACL_KIND_CLASS
,
150 RelationGetRelationName(rel
));
154 TRIGGER_CLEAR_TYPE(tgtype
);
156 TRIGGER_SETT_BEFORE(tgtype
);
158 TRIGGER_SETT_ROW(tgtype
);
160 for (i
= 0; stmt
->actions
[i
]; i
++)
162 switch (stmt
->actions
[i
])
165 if (TRIGGER_FOR_INSERT(tgtype
))
167 (errcode(ERRCODE_SYNTAX_ERROR
),
168 errmsg("multiple INSERT events specified")));
169 TRIGGER_SETT_INSERT(tgtype
);
172 if (TRIGGER_FOR_DELETE(tgtype
))
174 (errcode(ERRCODE_SYNTAX_ERROR
),
175 errmsg("multiple DELETE events specified")));
176 TRIGGER_SETT_DELETE(tgtype
);
179 if (TRIGGER_FOR_UPDATE(tgtype
))
181 (errcode(ERRCODE_SYNTAX_ERROR
),
182 errmsg("multiple UPDATE events specified")));
183 TRIGGER_SETT_UPDATE(tgtype
);
186 if (TRIGGER_FOR_TRUNCATE(tgtype
))
188 (errcode(ERRCODE_SYNTAX_ERROR
),
189 errmsg("multiple TRUNCATE events specified")));
190 TRIGGER_SETT_TRUNCATE(tgtype
);
191 /* Disallow ROW-level TRUNCATE triggers */
194 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
195 errmsg("TRUNCATE FOR EACH ROW triggers are not supported")));
198 elog(ERROR
, "unrecognized trigger event: %d",
199 (int) stmt
->actions
[i
]);
205 * Find and validate the trigger function.
207 funcoid
= LookupFuncName(stmt
->funcname
, 0, fargtypes
, false);
208 funcrettype
= get_func_rettype(funcoid
);
209 if (funcrettype
!= TRIGGEROID
)
212 * We allow OPAQUE just so we can load old dump files. When we see a
213 * trigger function declared OPAQUE, change it to TRIGGER.
215 if (funcrettype
== OPAQUEOID
)
218 (errmsg("changing return type of function %s from \"opaque\" to \"trigger\"",
219 NameListToString(stmt
->funcname
))));
220 SetFunctionReturnType(funcoid
, TRIGGEROID
);
224 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION
),
225 errmsg("function %s must return type \"trigger\"",
226 NameListToString(stmt
->funcname
))));
230 * If the command is a user-entered CREATE CONSTRAINT TRIGGER command that
231 * references one of the built-in RI_FKey trigger functions, assume it is
232 * from a dump of a pre-7.3 foreign key constraint, and take steps to
233 * convert this legacy representation into a regular foreign key
234 * constraint. Ugly, but necessary for loading old dump files.
236 if (stmt
->isconstraint
&& !OidIsValid(constraintOid
) &&
237 list_length(stmt
->args
) >= 6 &&
238 (list_length(stmt
->args
) % 2) == 0 &&
239 RI_FKey_trigger_type(funcoid
) != RI_TRIGGER_NONE
)
241 /* Keep lock on target rel until end of xact */
242 heap_close(rel
, NoLock
);
244 ConvertTriggerToFK(stmt
, funcoid
);
250 * Generate the trigger's OID now, so that we can use it in the name if
253 tgrel
= heap_open(TriggerRelationId
, RowExclusiveLock
);
255 trigoid
= GetNewOid(tgrel
);
258 * If trigger is for an RI constraint, the passed-in name is the
259 * constraint name; save that and build a unique trigger name to avoid
260 * collisions with user-selected trigger names.
262 if (OidIsValid(constraintOid
))
264 snprintf(constrtrigname
, sizeof(constrtrigname
),
265 "RI_ConstraintTrigger_%u", trigoid
);
266 trigname
= constrtrigname
;
267 constrname
= stmt
->trigname
;
269 else if (stmt
->isconstraint
)
271 /* constraint trigger: trigger name is also constraint name */
272 trigname
= stmt
->trigname
;
273 constrname
= stmt
->trigname
;
277 /* regular trigger: use empty constraint name */
278 trigname
= stmt
->trigname
;
283 * Scan pg_trigger for existing triggers on relation. We do this mainly
284 * because we must count them; a secondary benefit is to give a nice error
285 * message if there's already a trigger of the same name. (The unique
286 * index on tgrelid/tgname would complain anyway.)
288 * NOTE that this is cool only because we have AccessExclusiveLock on the
289 * relation, so the trigger set won't be changing underneath us.
292 Anum_pg_trigger_tgrelid
,
293 BTEqualStrategyNumber
, F_OIDEQ
,
294 ObjectIdGetDatum(RelationGetRelid(rel
)));
295 tgscan
= systable_beginscan(tgrel
, TriggerRelidNameIndexId
, true,
296 SnapshotNow
, 1, &key
);
297 while (HeapTupleIsValid(tuple
= systable_getnext(tgscan
)))
299 Form_pg_trigger pg_trigger
= (Form_pg_trigger
) GETSTRUCT(tuple
);
301 if (namestrcmp(&(pg_trigger
->tgname
), trigname
) == 0)
303 (errcode(ERRCODE_DUPLICATE_OBJECT
),
304 errmsg("trigger \"%s\" for relation \"%s\" already exists",
305 trigname
, stmt
->relation
->relname
)));
308 systable_endscan(tgscan
);
311 * Build the new pg_trigger tuple.
313 memset(nulls
, ' ', Natts_pg_trigger
* sizeof(char));
315 values
[Anum_pg_trigger_tgrelid
- 1] = ObjectIdGetDatum(RelationGetRelid(rel
));
316 values
[Anum_pg_trigger_tgname
- 1] = DirectFunctionCall1(namein
,
317 CStringGetDatum(trigname
));
318 values
[Anum_pg_trigger_tgfoid
- 1] = ObjectIdGetDatum(funcoid
);
319 values
[Anum_pg_trigger_tgtype
- 1] = Int16GetDatum(tgtype
);
320 values
[Anum_pg_trigger_tgenabled
- 1] = CharGetDatum(TRIGGER_FIRES_ON_ORIGIN
);
321 values
[Anum_pg_trigger_tgisconstraint
- 1] = BoolGetDatum(stmt
->isconstraint
);
322 values
[Anum_pg_trigger_tgconstrname
- 1] = DirectFunctionCall1(namein
,
323 CStringGetDatum(constrname
));
324 values
[Anum_pg_trigger_tgconstrrelid
- 1] = ObjectIdGetDatum(constrrelid
);
325 values
[Anum_pg_trigger_tgconstraint
- 1] = ObjectIdGetDatum(constraintOid
);
326 values
[Anum_pg_trigger_tgdeferrable
- 1] = BoolGetDatum(stmt
->deferrable
);
327 values
[Anum_pg_trigger_tginitdeferred
- 1] = BoolGetDatum(stmt
->initdeferred
);
333 int16 nargs
= list_length(stmt
->args
);
336 foreach(le
, stmt
->args
)
338 char *ar
= strVal(lfirst(le
));
340 len
+= strlen(ar
) + 4;
347 args
= (char *) palloc(len
+ 1);
349 foreach(le
, stmt
->args
)
351 char *s
= strVal(lfirst(le
));
352 char *d
= args
+ strlen(args
);
362 values
[Anum_pg_trigger_tgnargs
- 1] = Int16GetDatum(nargs
);
363 values
[Anum_pg_trigger_tgargs
- 1] = DirectFunctionCall1(byteain
,
364 CStringGetDatum(args
));
368 values
[Anum_pg_trigger_tgnargs
- 1] = Int16GetDatum(0);
369 values
[Anum_pg_trigger_tgargs
- 1] = DirectFunctionCall1(byteain
,
370 CStringGetDatum(""));
373 /* tgattr is currently always a zero-length array */
374 tgattr
= buildint2vector(NULL
, 0);
375 values
[Anum_pg_trigger_tgattr
- 1] = PointerGetDatum(tgattr
);
377 tuple
= heap_formtuple(tgrel
->rd_att
, values
, nulls
);
379 /* force tuple to have the desired OID */
380 HeapTupleSetOid(tuple
, trigoid
);
383 * Insert tuple into pg_trigger.
385 simple_heap_insert(tgrel
, tuple
);
387 CatalogUpdateIndexes(tgrel
, tuple
);
389 heap_freetuple(tuple
);
390 heap_close(tgrel
, RowExclusiveLock
);
392 pfree(DatumGetPointer(values
[Anum_pg_trigger_tgname
- 1]));
393 pfree(DatumGetPointer(values
[Anum_pg_trigger_tgargs
- 1]));
396 * Update relation's pg_class entry. Crucial side-effect: other backends
397 * (and this one too!) are sent SI message to make them rebuild relcache
400 pgrel
= heap_open(RelationRelationId
, RowExclusiveLock
);
401 tuple
= SearchSysCacheCopy(RELOID
,
402 ObjectIdGetDatum(RelationGetRelid(rel
)),
404 if (!HeapTupleIsValid(tuple
))
405 elog(ERROR
, "cache lookup failed for relation %u",
406 RelationGetRelid(rel
));
408 ((Form_pg_class
) GETSTRUCT(tuple
))->reltriggers
= found
+ 1;
410 simple_heap_update(pgrel
, &tuple
->t_self
, tuple
);
412 CatalogUpdateIndexes(pgrel
, tuple
);
414 heap_freetuple(tuple
);
415 heap_close(pgrel
, RowExclusiveLock
);
418 * We used to try to update the rel's relcache entry here, but that's
419 * fairly pointless since it will happen as a byproduct of the upcoming
420 * CommandCounterIncrement...
424 * Record dependencies for trigger. Always place a normal dependency on
427 myself
.classId
= TriggerRelationId
;
428 myself
.objectId
= trigoid
;
429 myself
.objectSubId
= 0;
431 referenced
.classId
= ProcedureRelationId
;
432 referenced
.objectId
= funcoid
;
433 referenced
.objectSubId
= 0;
434 recordDependencyOn(&myself
, &referenced
, DEPENDENCY_NORMAL
);
436 if (OidIsValid(constraintOid
))
439 * It's for a constraint, so make it an internal dependency of the
440 * constraint. We can skip depending on the relations, as there'll be
441 * an indirect dependency via the constraint.
443 referenced
.classId
= ConstraintRelationId
;
444 referenced
.objectId
= constraintOid
;
445 referenced
.objectSubId
= 0;
446 recordDependencyOn(&myself
, &referenced
, DEPENDENCY_INTERNAL
);
451 * Regular CREATE TRIGGER, so place dependencies. We make trigger be
452 * auto-dropped if its relation is dropped or if the FK relation is
453 * dropped. (Auto drop is compatible with our pre-7.3 behavior.)
455 referenced
.classId
= RelationRelationId
;
456 referenced
.objectId
= RelationGetRelid(rel
);
457 referenced
.objectSubId
= 0;
458 recordDependencyOn(&myself
, &referenced
, DEPENDENCY_AUTO
);
459 if (constrrelid
!= InvalidOid
)
461 referenced
.classId
= RelationRelationId
;
462 referenced
.objectId
= constrrelid
;
463 referenced
.objectSubId
= 0;
464 recordDependencyOn(&myself
, &referenced
, DEPENDENCY_AUTO
);
468 /* Keep lock on target rel until end of xact */
469 heap_close(rel
, NoLock
);
476 * Convert legacy (pre-7.3) CREATE CONSTRAINT TRIGGER commands into
477 * full-fledged foreign key constraints.
479 * The conversion is complex because a pre-7.3 foreign key involved three
480 * separate triggers, which were reported separately in dumps. While the
481 * single trigger on the referencing table adds no new information, we need
482 * to know the trigger functions of both of the triggers on the referenced
483 * table to build the constraint declaration. Also, due to lack of proper
484 * dependency checking pre-7.3, it is possible that the source database had
485 * an incomplete set of triggers resulting in an only partially enforced
486 * FK constraint. (This would happen if one of the tables had been dropped
487 * and re-created, but only if the DB had been affected by a 7.0 pg_dump bug
488 * that caused loss of tgconstrrelid information.) We choose to translate to
489 * an FK constraint only when we've seen all three triggers of a set. This is
490 * implemented by storing unmatched items in a list in TopMemoryContext.
491 * We match triggers together by comparing the trigger arguments (which
492 * include constraint name, table and column names, so should be good enough).
496 List
*args
; /* list of (T_String) Values or NIL */
497 Oid funcoids
[3]; /* OIDs of trigger functions */
498 /* The three function OIDs are stored in the order update, delete, child */
502 ConvertTriggerToFK(CreateTrigStmt
*stmt
, Oid funcoid
)
504 static List
*info_list
= NIL
;
506 static const char *const funcdescr
[3] = {
507 gettext_noop("Found referenced table's UPDATE trigger."),
508 gettext_noop("Found referenced table's DELETE trigger."),
509 gettext_noop("Found referencing table's trigger.")
515 char fk_matchtype
= FKCONSTR_MATCH_UNSPECIFIED
;
516 List
*fk_attrs
= NIL
;
517 List
*pk_attrs
= NIL
;
520 OldTriggerInfo
*info
= NULL
;
524 /* Parse out the trigger arguments */
525 constr_name
= strVal(linitial(stmt
->args
));
526 fk_table_name
= strVal(lsecond(stmt
->args
));
527 pk_table_name
= strVal(lthird(stmt
->args
));
529 foreach(l
, stmt
->args
)
531 Value
*arg
= (Value
*) lfirst(l
);
534 if (i
< 4) /* skip constraint and table names */
536 if (i
== 4) /* handle match type */
538 if (strcmp(strVal(arg
), "FULL") == 0)
539 fk_matchtype
= FKCONSTR_MATCH_FULL
;
541 fk_matchtype
= FKCONSTR_MATCH_UNSPECIFIED
;
545 fk_attrs
= lappend(fk_attrs
, arg
);
547 pk_attrs
= lappend(pk_attrs
, arg
);
550 /* Prepare description of constraint for use in messages */
551 initStringInfo(&buf
);
552 appendStringInfo(&buf
, "FOREIGN KEY %s(",
553 quote_identifier(fk_table_name
));
557 Value
*arg
= (Value
*) lfirst(l
);
560 appendStringInfoChar(&buf
, ',');
561 appendStringInfoString(&buf
, quote_identifier(strVal(arg
)));
563 appendStringInfo(&buf
, ") REFERENCES %s(",
564 quote_identifier(pk_table_name
));
568 Value
*arg
= (Value
*) lfirst(l
);
571 appendStringInfoChar(&buf
, ',');
572 appendStringInfoString(&buf
, quote_identifier(strVal(arg
)));
574 appendStringInfoChar(&buf
, ')');
576 /* Identify class of trigger --- update, delete, or referencing-table */
579 case F_RI_FKEY_CASCADE_UPD
:
580 case F_RI_FKEY_RESTRICT_UPD
:
581 case F_RI_FKEY_SETNULL_UPD
:
582 case F_RI_FKEY_SETDEFAULT_UPD
:
583 case F_RI_FKEY_NOACTION_UPD
:
587 case F_RI_FKEY_CASCADE_DEL
:
588 case F_RI_FKEY_RESTRICT_DEL
:
589 case F_RI_FKEY_SETNULL_DEL
:
590 case F_RI_FKEY_SETDEFAULT_DEL
:
591 case F_RI_FKEY_NOACTION_DEL
:
600 /* See if we have a match to this trigger */
601 foreach(l
, info_list
)
603 info
= (OldTriggerInfo
*) lfirst(l
);
604 if (info
->funcoids
[funcnum
] == InvalidOid
&&
605 equal(info
->args
, stmt
->args
))
607 info
->funcoids
[funcnum
] = funcoid
;
614 /* First trigger of set, so create a new list entry */
615 MemoryContext oldContext
;
618 (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
619 constr_name
, buf
.data
),
620 errdetail(funcdescr
[funcnum
])));
621 oldContext
= MemoryContextSwitchTo(TopMemoryContext
);
622 info
= (OldTriggerInfo
*) palloc0(sizeof(OldTriggerInfo
));
623 info
->args
= copyObject(stmt
->args
);
624 info
->funcoids
[funcnum
] = funcoid
;
625 info_list
= lappend(info_list
, info
);
626 MemoryContextSwitchTo(oldContext
);
628 else if (info
->funcoids
[0] == InvalidOid
||
629 info
->funcoids
[1] == InvalidOid
||
630 info
->funcoids
[2] == InvalidOid
)
632 /* Second trigger of set */
634 (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
635 constr_name
, buf
.data
),
636 errdetail(funcdescr
[funcnum
])));
640 /* OK, we have a set, so make the FK constraint ALTER TABLE cmd */
641 AlterTableStmt
*atstmt
= makeNode(AlterTableStmt
);
642 AlterTableCmd
*atcmd
= makeNode(AlterTableCmd
);
643 FkConstraint
*fkcon
= makeNode(FkConstraint
);
646 (errmsg("converting trigger group into constraint \"%s\" %s",
647 constr_name
, buf
.data
),
648 errdetail(funcdescr
[funcnum
])));
651 /* This trigger is on the FK table */
652 atstmt
->relation
= stmt
->relation
;
654 fkcon
->pktable
= stmt
->constrrel
;
657 /* Work around ancient pg_dump bug that omitted constrrel */
658 fkcon
->pktable
= makeRangeVar(NULL
, pk_table_name
, -1);
663 /* This trigger is on the PK table */
664 fkcon
->pktable
= stmt
->relation
;
666 atstmt
->relation
= stmt
->constrrel
;
669 /* Work around ancient pg_dump bug that omitted constrrel */
670 atstmt
->relation
= makeRangeVar(NULL
, fk_table_name
, -1);
673 atstmt
->cmds
= list_make1(atcmd
);
674 atstmt
->relkind
= OBJECT_TABLE
;
675 atcmd
->subtype
= AT_AddConstraint
;
676 atcmd
->def
= (Node
*) fkcon
;
677 if (strcmp(constr_name
, "<unnamed>") == 0)
678 fkcon
->constr_name
= NULL
;
680 fkcon
->constr_name
= constr_name
;
681 fkcon
->fk_attrs
= fk_attrs
;
682 fkcon
->pk_attrs
= pk_attrs
;
683 fkcon
->fk_matchtype
= fk_matchtype
;
684 switch (info
->funcoids
[0])
686 case F_RI_FKEY_NOACTION_UPD
:
687 fkcon
->fk_upd_action
= FKCONSTR_ACTION_NOACTION
;
689 case F_RI_FKEY_CASCADE_UPD
:
690 fkcon
->fk_upd_action
= FKCONSTR_ACTION_CASCADE
;
692 case F_RI_FKEY_RESTRICT_UPD
:
693 fkcon
->fk_upd_action
= FKCONSTR_ACTION_RESTRICT
;
695 case F_RI_FKEY_SETNULL_UPD
:
696 fkcon
->fk_upd_action
= FKCONSTR_ACTION_SETNULL
;
698 case F_RI_FKEY_SETDEFAULT_UPD
:
699 fkcon
->fk_upd_action
= FKCONSTR_ACTION_SETDEFAULT
;
702 /* can't get here because of earlier checks */
703 elog(ERROR
, "confused about RI update function");
705 switch (info
->funcoids
[1])
707 case F_RI_FKEY_NOACTION_DEL
:
708 fkcon
->fk_del_action
= FKCONSTR_ACTION_NOACTION
;
710 case F_RI_FKEY_CASCADE_DEL
:
711 fkcon
->fk_del_action
= FKCONSTR_ACTION_CASCADE
;
713 case F_RI_FKEY_RESTRICT_DEL
:
714 fkcon
->fk_del_action
= FKCONSTR_ACTION_RESTRICT
;
716 case F_RI_FKEY_SETNULL_DEL
:
717 fkcon
->fk_del_action
= FKCONSTR_ACTION_SETNULL
;
719 case F_RI_FKEY_SETDEFAULT_DEL
:
720 fkcon
->fk_del_action
= FKCONSTR_ACTION_SETDEFAULT
;
723 /* can't get here because of earlier checks */
724 elog(ERROR
, "confused about RI delete function");
726 fkcon
->deferrable
= stmt
->deferrable
;
727 fkcon
->initdeferred
= stmt
->initdeferred
;
729 /* ... and execute it */
730 ProcessUtility((Node
*) atstmt
,
731 "(generated ALTER TABLE ADD FOREIGN KEY command)",
732 NULL
, false, None_Receiver
, NULL
);
734 /* Remove the matched item from the list */
735 info_list
= list_delete_ptr(info_list
, info
);
737 /* We leak the copied args ... not worth worrying about */
743 * DropTrigger - drop an individual trigger by name
746 DropTrigger(Oid relid
, const char *trigname
, DropBehavior behavior
,
753 ObjectAddress object
;
756 * Find the trigger, verify permissions, set up object address
758 tgrel
= heap_open(TriggerRelationId
, AccessShareLock
);
760 ScanKeyInit(&skey
[0],
761 Anum_pg_trigger_tgrelid
,
762 BTEqualStrategyNumber
, F_OIDEQ
,
763 ObjectIdGetDatum(relid
));
765 ScanKeyInit(&skey
[1],
766 Anum_pg_trigger_tgname
,
767 BTEqualStrategyNumber
, F_NAMEEQ
,
768 CStringGetDatum(trigname
));
770 tgscan
= systable_beginscan(tgrel
, TriggerRelidNameIndexId
, true,
771 SnapshotNow
, 2, skey
);
773 tup
= systable_getnext(tgscan
);
775 if (!HeapTupleIsValid(tup
))
779 (errcode(ERRCODE_UNDEFINED_OBJECT
),
780 errmsg("trigger \"%s\" for table \"%s\" does not exist",
781 trigname
, get_rel_name(relid
))));
784 (errmsg("trigger \"%s\" for table \"%s\" does not exist, skipping",
785 trigname
, get_rel_name(relid
))));
787 systable_endscan(tgscan
);
788 heap_close(tgrel
, AccessShareLock
);
792 if (!pg_class_ownercheck(relid
, GetUserId()))
793 aclcheck_error(ACLCHECK_NOT_OWNER
, ACL_KIND_CLASS
,
794 get_rel_name(relid
));
796 object
.classId
= TriggerRelationId
;
797 object
.objectId
= HeapTupleGetOid(tup
);
798 object
.objectSubId
= 0;
800 systable_endscan(tgscan
);
801 heap_close(tgrel
, AccessShareLock
);
806 performDeletion(&object
, behavior
);
810 * Guts of trigger deletion.
813 RemoveTriggerById(Oid trigOid
)
823 Form_pg_class classForm
;
825 tgrel
= heap_open(TriggerRelationId
, RowExclusiveLock
);
828 * Find the trigger to delete.
830 ScanKeyInit(&skey
[0],
831 ObjectIdAttributeNumber
,
832 BTEqualStrategyNumber
, F_OIDEQ
,
833 ObjectIdGetDatum(trigOid
));
835 tgscan
= systable_beginscan(tgrel
, TriggerOidIndexId
, true,
836 SnapshotNow
, 1, skey
);
838 tup
= systable_getnext(tgscan
);
839 if (!HeapTupleIsValid(tup
))
840 elog(ERROR
, "could not find tuple for trigger %u", trigOid
);
843 * Open and exclusive-lock the relation the trigger belongs to.
845 relid
= ((Form_pg_trigger
) GETSTRUCT(tup
))->tgrelid
;
847 rel
= heap_open(relid
, AccessExclusiveLock
);
849 if (rel
->rd_rel
->relkind
!= RELKIND_RELATION
)
851 (errcode(ERRCODE_WRONG_OBJECT_TYPE
),
852 errmsg("\"%s\" is not a table",
853 RelationGetRelationName(rel
))));
855 if (!allowSystemTableMods
&& IsSystemRelation(rel
))
857 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
858 errmsg("permission denied: \"%s\" is a system catalog",
859 RelationGetRelationName(rel
))));
862 * Delete the pg_trigger tuple.
864 simple_heap_delete(tgrel
, &tup
->t_self
);
866 systable_endscan(tgscan
);
867 heap_close(tgrel
, RowExclusiveLock
);
870 * Update relation's pg_class entry. Crucial side-effect: other backends
871 * (and this one too!) are sent SI message to make them rebuild relcache
874 * Note this is OK only because we have AccessExclusiveLock on the rel, so
875 * no one else is creating/deleting triggers on this rel at the same time.
877 pgrel
= heap_open(RelationRelationId
, RowExclusiveLock
);
878 tuple
= SearchSysCacheCopy(RELOID
,
879 ObjectIdGetDatum(relid
),
881 if (!HeapTupleIsValid(tuple
))
882 elog(ERROR
, "cache lookup failed for relation %u", relid
);
883 classForm
= (Form_pg_class
) GETSTRUCT(tuple
);
885 if (classForm
->reltriggers
== 0) /* should not happen */
886 elog(ERROR
, "relation \"%s\" has reltriggers = 0",
887 RelationGetRelationName(rel
));
888 classForm
->reltriggers
--;
890 simple_heap_update(pgrel
, &tuple
->t_self
, tuple
);
892 CatalogUpdateIndexes(pgrel
, tuple
);
894 heap_freetuple(tuple
);
896 heap_close(pgrel
, RowExclusiveLock
);
898 /* Keep lock on trigger's rel until end of xact */
899 heap_close(rel
, NoLock
);
903 * renametrig - changes the name of a trigger on a relation
905 * trigger name is changed in trigger catalog.
906 * No record of the previous name is kept.
908 * get proper relrelation from relation catalog (if not arg)
909 * scan trigger catalog
910 * for name conflict (within rel)
911 * for original trigger (if not arg)
912 * modify tgname in trigger tuple
913 * update row in catalog
916 renametrig(Oid relid
,
927 * Grab an exclusive lock on the target table, which we will NOT release
928 * until end of transaction.
930 targetrel
= heap_open(relid
, AccessExclusiveLock
);
933 * Scan pg_trigger twice for existing triggers on relation. We do this in
934 * order to ensure a trigger does not exist with newname (The unique index
935 * on tgrelid/tgname would complain anyway) and to ensure a trigger does
936 * exist with oldname.
938 * NOTE that this is cool only because we have AccessExclusiveLock on the
939 * relation, so the trigger set won't be changing underneath us.
941 tgrel
= heap_open(TriggerRelationId
, RowExclusiveLock
);
944 * First pass -- look for name conflict
947 Anum_pg_trigger_tgrelid
,
948 BTEqualStrategyNumber
, F_OIDEQ
,
949 ObjectIdGetDatum(relid
));
951 Anum_pg_trigger_tgname
,
952 BTEqualStrategyNumber
, F_NAMEEQ
,
953 PointerGetDatum(newname
));
954 tgscan
= systable_beginscan(tgrel
, TriggerRelidNameIndexId
, true,
955 SnapshotNow
, 2, key
);
956 if (HeapTupleIsValid(tuple
= systable_getnext(tgscan
)))
958 (errcode(ERRCODE_DUPLICATE_OBJECT
),
959 errmsg("trigger \"%s\" for relation \"%s\" already exists",
960 newname
, RelationGetRelationName(targetrel
))));
961 systable_endscan(tgscan
);
964 * Second pass -- look for trigger existing with oldname and update
967 Anum_pg_trigger_tgrelid
,
968 BTEqualStrategyNumber
, F_OIDEQ
,
969 ObjectIdGetDatum(relid
));
971 Anum_pg_trigger_tgname
,
972 BTEqualStrategyNumber
, F_NAMEEQ
,
973 PointerGetDatum(oldname
));
974 tgscan
= systable_beginscan(tgrel
, TriggerRelidNameIndexId
, true,
975 SnapshotNow
, 2, key
);
976 if (HeapTupleIsValid(tuple
= systable_getnext(tgscan
)))
979 * Update pg_trigger tuple with new tgname.
981 tuple
= heap_copytuple(tuple
); /* need a modifiable copy */
983 namestrcpy(&((Form_pg_trigger
) GETSTRUCT(tuple
))->tgname
, newname
);
985 simple_heap_update(tgrel
, &tuple
->t_self
, tuple
);
987 /* keep system catalog indexes current */
988 CatalogUpdateIndexes(tgrel
, tuple
);
991 * Invalidate relation's relcache entry so that other backends (and
992 * this one too!) are sent SI message to make them rebuild relcache
993 * entries. (Ideally this should happen automatically...)
995 CacheInvalidateRelcache(targetrel
);
1000 (errcode(ERRCODE_UNDEFINED_OBJECT
),
1001 errmsg("trigger \"%s\" for table \"%s\" does not exist",
1002 oldname
, RelationGetRelationName(targetrel
))));
1005 systable_endscan(tgscan
);
1007 heap_close(tgrel
, RowExclusiveLock
);
1010 * Close rel, but keep exclusive lock!
1012 heap_close(targetrel
, NoLock
);
1017 * EnableDisableTrigger()
1019 * Called by ALTER TABLE ENABLE/DISABLE TRIGGER
1020 * to change 'tgenabled' field for the specified trigger(s)
1022 * rel: relation to process (caller must hold suitable lock on it)
1023 * tgname: trigger to process, or NULL to scan all triggers
1024 * enable: new value for tgenabled field
1025 * skip_system: if true, skip "system" triggers (constraint triggers)
1027 * Caller should have checked permissions for the table; here we also
1028 * enforce that superuser privilege is required to alter the state of
1032 EnableDisableTrigger(Relation rel
, const char *tgname
,
1033 char fires_when
, bool skip_system
)
1037 ScanKeyData keys
[2];
1043 /* Scan the relevant entries in pg_triggers */
1044 tgrel
= heap_open(TriggerRelationId
, RowExclusiveLock
);
1046 ScanKeyInit(&keys
[0],
1047 Anum_pg_trigger_tgrelid
,
1048 BTEqualStrategyNumber
, F_OIDEQ
,
1049 ObjectIdGetDatum(RelationGetRelid(rel
)));
1052 ScanKeyInit(&keys
[1],
1053 Anum_pg_trigger_tgname
,
1054 BTEqualStrategyNumber
, F_NAMEEQ
,
1055 CStringGetDatum(tgname
));
1061 tgscan
= systable_beginscan(tgrel
, TriggerRelidNameIndexId
, true,
1062 SnapshotNow
, nkeys
, keys
);
1064 found
= changed
= false;
1066 while (HeapTupleIsValid(tuple
= systable_getnext(tgscan
)))
1068 Form_pg_trigger oldtrig
= (Form_pg_trigger
) GETSTRUCT(tuple
);
1070 if (OidIsValid(oldtrig
->tgconstraint
))
1072 /* system trigger ... ok to process? */
1077 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
1078 errmsg("permission denied: \"%s\" is a system trigger",
1079 NameStr(oldtrig
->tgname
))));
1084 if (oldtrig
->tgenabled
!= fires_when
)
1086 /* need to change this one ... make a copy to scribble on */
1087 HeapTuple newtup
= heap_copytuple(tuple
);
1088 Form_pg_trigger newtrig
= (Form_pg_trigger
) GETSTRUCT(newtup
);
1090 newtrig
->tgenabled
= fires_when
;
1092 simple_heap_update(tgrel
, &newtup
->t_self
, newtup
);
1094 /* Keep catalog indexes current */
1095 CatalogUpdateIndexes(tgrel
, newtup
);
1097 heap_freetuple(newtup
);
1103 systable_endscan(tgscan
);
1105 heap_close(tgrel
, RowExclusiveLock
);
1107 if (tgname
&& !found
)
1109 (errcode(ERRCODE_UNDEFINED_OBJECT
),
1110 errmsg("trigger \"%s\" for table \"%s\" does not exist",
1111 tgname
, RelationGetRelationName(rel
))));
1114 * If we changed anything, broadcast a SI inval message to force each
1115 * backend (including our own!) to rebuild relation's relcache entry.
1116 * Otherwise they will fail to apply the change promptly.
1119 CacheInvalidateRelcache(rel
);
1124 * Build trigger data to attach to the given relcache entry.
1126 * Note that trigger data attached to a relcache entry must be stored in
1127 * CacheMemoryContext to ensure it survives as long as the relcache entry.
1128 * But we should be running in a less long-lived working context. To avoid
1129 * leaking cache memory if this routine fails partway through, we build a
1130 * temporary TriggerDesc in working memory and then copy the completed
1131 * structure into cache memory.
1134 RelationBuildTriggers(Relation relation
)
1136 TriggerDesc
*trigdesc
;
1137 int ntrigs
= relation
->rd_rel
->reltriggers
;
1144 MemoryContext oldContext
;
1146 Assert(ntrigs
> 0); /* else I should not have been called */
1148 triggers
= (Trigger
*) palloc(ntrigs
* sizeof(Trigger
));
1151 * Note: since we scan the triggers using TriggerRelidNameIndexId, we will
1152 * be reading the triggers in name order, except possibly during
1153 * emergency-recovery operations (ie, IgnoreSystemIndexes). This in turn
1154 * ensures that triggers will be fired in name order.
1157 Anum_pg_trigger_tgrelid
,
1158 BTEqualStrategyNumber
, F_OIDEQ
,
1159 ObjectIdGetDatum(RelationGetRelid(relation
)));
1161 tgrel
= heap_open(TriggerRelationId
, AccessShareLock
);
1162 tgscan
= systable_beginscan(tgrel
, TriggerRelidNameIndexId
, true,
1163 SnapshotNow
, 1, &skey
);
1165 while (HeapTupleIsValid(htup
= systable_getnext(tgscan
)))
1167 Form_pg_trigger pg_trigger
= (Form_pg_trigger
) GETSTRUCT(htup
);
1170 if (found
>= ntrigs
)
1171 elog(ERROR
, "too many trigger records found for relation \"%s\"",
1172 RelationGetRelationName(relation
));
1173 build
= &(triggers
[found
]);
1175 build
->tgoid
= HeapTupleGetOid(htup
);
1176 build
->tgname
= DatumGetCString(DirectFunctionCall1(nameout
,
1177 NameGetDatum(&pg_trigger
->tgname
)));
1178 build
->tgfoid
= pg_trigger
->tgfoid
;
1179 build
->tgtype
= pg_trigger
->tgtype
;
1180 build
->tgenabled
= pg_trigger
->tgenabled
;
1181 build
->tgisconstraint
= pg_trigger
->tgisconstraint
;
1182 build
->tgconstrrelid
= pg_trigger
->tgconstrrelid
;
1183 build
->tgconstraint
= pg_trigger
->tgconstraint
;
1184 build
->tgdeferrable
= pg_trigger
->tgdeferrable
;
1185 build
->tginitdeferred
= pg_trigger
->tginitdeferred
;
1186 build
->tgnargs
= pg_trigger
->tgnargs
;
1187 /* tgattr is first var-width field, so OK to access directly */
1188 build
->tgnattr
= pg_trigger
->tgattr
.dim1
;
1189 if (build
->tgnattr
> 0)
1191 build
->tgattr
= (int2
*) palloc(build
->tgnattr
* sizeof(int2
));
1192 memcpy(build
->tgattr
, &(pg_trigger
->tgattr
.values
),
1193 build
->tgnattr
* sizeof(int2
));
1196 build
->tgattr
= NULL
;
1197 if (build
->tgnargs
> 0)
1204 val
= DatumGetByteaP(fastgetattr(htup
,
1205 Anum_pg_trigger_tgargs
,
1206 tgrel
->rd_att
, &isnull
));
1208 elog(ERROR
, "tgargs is null in trigger for relation \"%s\"",
1209 RelationGetRelationName(relation
));
1210 p
= (char *) VARDATA(val
);
1211 build
->tgargs
= (char **) palloc(build
->tgnargs
* sizeof(char *));
1212 for (i
= 0; i
< build
->tgnargs
; i
++)
1214 build
->tgargs
[i
] = pstrdup(p
);
1219 build
->tgargs
= NULL
;
1224 systable_endscan(tgscan
);
1225 heap_close(tgrel
, AccessShareLock
);
1227 if (found
!= ntrigs
)
1228 elog(ERROR
, "%d trigger record(s) not found for relation \"%s\"",
1230 RelationGetRelationName(relation
));
1232 /* Build trigdesc */
1233 trigdesc
= (TriggerDesc
*) palloc0(sizeof(TriggerDesc
));
1234 trigdesc
->triggers
= triggers
;
1235 trigdesc
->numtriggers
= ntrigs
;
1236 for (found
= 0; found
< ntrigs
; found
++)
1237 InsertTrigger(trigdesc
, &(triggers
[found
]), found
);
1239 /* Copy completed trigdesc into cache storage */
1240 oldContext
= MemoryContextSwitchTo(CacheMemoryContext
);
1241 relation
->trigdesc
= CopyTriggerDesc(trigdesc
);
1242 MemoryContextSwitchTo(oldContext
);
1244 /* Release working memory */
1245 FreeTriggerDesc(trigdesc
);
1249 * Insert the given trigger into the appropriate index list(s) for it
1251 * To simplify storage management, we allocate each index list at the max
1252 * possible size (trigdesc->numtriggers) if it's used at all. This does
1253 * not waste space permanently since we're only building a temporary
1254 * trigdesc at this point.
1257 InsertTrigger(TriggerDesc
*trigdesc
, Trigger
*trigger
, int indx
)
1263 if (TRIGGER_FOR_ROW(trigger
->tgtype
))
1266 if (TRIGGER_FOR_BEFORE(trigger
->tgtype
))
1268 n
= trigdesc
->n_before_row
;
1269 t
= trigdesc
->tg_before_row
;
1273 n
= trigdesc
->n_after_row
;
1274 t
= trigdesc
->tg_after_row
;
1279 /* STATEMENT trigger */
1280 if (TRIGGER_FOR_BEFORE(trigger
->tgtype
))
1282 n
= trigdesc
->n_before_statement
;
1283 t
= trigdesc
->tg_before_statement
;
1287 n
= trigdesc
->n_after_statement
;
1288 t
= trigdesc
->tg_after_statement
;
1292 if (TRIGGER_FOR_INSERT(trigger
->tgtype
))
1294 tp
= &(t
[TRIGGER_EVENT_INSERT
]);
1296 *tp
= (int *) palloc(trigdesc
->numtriggers
* sizeof(int));
1297 (*tp
)[n
[TRIGGER_EVENT_INSERT
]] = indx
;
1298 (n
[TRIGGER_EVENT_INSERT
])++;
1301 if (TRIGGER_FOR_DELETE(trigger
->tgtype
))
1303 tp
= &(t
[TRIGGER_EVENT_DELETE
]);
1305 *tp
= (int *) palloc(trigdesc
->numtriggers
* sizeof(int));
1306 (*tp
)[n
[TRIGGER_EVENT_DELETE
]] = indx
;
1307 (n
[TRIGGER_EVENT_DELETE
])++;
1310 if (TRIGGER_FOR_UPDATE(trigger
->tgtype
))
1312 tp
= &(t
[TRIGGER_EVENT_UPDATE
]);
1314 *tp
= (int *) palloc(trigdesc
->numtriggers
* sizeof(int));
1315 (*tp
)[n
[TRIGGER_EVENT_UPDATE
]] = indx
;
1316 (n
[TRIGGER_EVENT_UPDATE
])++;
1319 if (TRIGGER_FOR_TRUNCATE(trigger
->tgtype
))
1321 tp
= &(t
[TRIGGER_EVENT_TRUNCATE
]);
1323 *tp
= (int *) palloc(trigdesc
->numtriggers
* sizeof(int));
1324 (*tp
)[n
[TRIGGER_EVENT_TRUNCATE
]] = indx
;
1325 (n
[TRIGGER_EVENT_TRUNCATE
])++;
1330 * Copy a TriggerDesc data structure.
1332 * The copy is allocated in the current memory context.
1335 CopyTriggerDesc(TriggerDesc
*trigdesc
)
1337 TriggerDesc
*newdesc
;
1344 if (trigdesc
== NULL
|| trigdesc
->numtriggers
<= 0)
1347 newdesc
= (TriggerDesc
*) palloc(sizeof(TriggerDesc
));
1348 memcpy(newdesc
, trigdesc
, sizeof(TriggerDesc
));
1350 trigger
= (Trigger
*) palloc(trigdesc
->numtriggers
* sizeof(Trigger
));
1351 memcpy(trigger
, trigdesc
->triggers
,
1352 trigdesc
->numtriggers
* sizeof(Trigger
));
1353 newdesc
->triggers
= trigger
;
1355 for (i
= 0; i
< trigdesc
->numtriggers
; i
++)
1357 trigger
->tgname
= pstrdup(trigger
->tgname
);
1358 if (trigger
->tgnattr
> 0)
1362 newattr
= (int2
*) palloc(trigger
->tgnattr
* sizeof(int2
));
1363 memcpy(newattr
, trigger
->tgattr
,
1364 trigger
->tgnattr
* sizeof(int2
));
1365 trigger
->tgattr
= newattr
;
1367 if (trigger
->tgnargs
> 0)
1372 newargs
= (char **) palloc(trigger
->tgnargs
* sizeof(char *));
1373 for (j
= 0; j
< trigger
->tgnargs
; j
++)
1374 newargs
[j
] = pstrdup(trigger
->tgargs
[j
]);
1375 trigger
->tgargs
= newargs
;
1380 n
= newdesc
->n_before_statement
;
1381 t
= newdesc
->tg_before_statement
;
1382 for (i
= 0; i
< TRIGGER_NUM_EVENT_CLASSES
; i
++)
1386 tnew
= (int *) palloc(n
[i
] * sizeof(int));
1387 memcpy(tnew
, t
[i
], n
[i
] * sizeof(int));
1393 n
= newdesc
->n_before_row
;
1394 t
= newdesc
->tg_before_row
;
1395 for (i
= 0; i
< TRIGGER_NUM_EVENT_CLASSES
; i
++)
1399 tnew
= (int *) palloc(n
[i
] * sizeof(int));
1400 memcpy(tnew
, t
[i
], n
[i
] * sizeof(int));
1406 n
= newdesc
->n_after_row
;
1407 t
= newdesc
->tg_after_row
;
1408 for (i
= 0; i
< TRIGGER_NUM_EVENT_CLASSES
; i
++)
1412 tnew
= (int *) palloc(n
[i
] * sizeof(int));
1413 memcpy(tnew
, t
[i
], n
[i
] * sizeof(int));
1419 n
= newdesc
->n_after_statement
;
1420 t
= newdesc
->tg_after_statement
;
1421 for (i
= 0; i
< TRIGGER_NUM_EVENT_CLASSES
; i
++)
1425 tnew
= (int *) palloc(n
[i
] * sizeof(int));
1426 memcpy(tnew
, t
[i
], n
[i
] * sizeof(int));
1437 * Free a TriggerDesc data structure.
1440 FreeTriggerDesc(TriggerDesc
*trigdesc
)
1446 if (trigdesc
== NULL
)
1449 t
= trigdesc
->tg_before_statement
;
1450 for (i
= 0; i
< TRIGGER_NUM_EVENT_CLASSES
; i
++)
1453 t
= trigdesc
->tg_before_row
;
1454 for (i
= 0; i
< TRIGGER_NUM_EVENT_CLASSES
; i
++)
1457 t
= trigdesc
->tg_after_row
;
1458 for (i
= 0; i
< TRIGGER_NUM_EVENT_CLASSES
; i
++)
1461 t
= trigdesc
->tg_after_statement
;
1462 for (i
= 0; i
< TRIGGER_NUM_EVENT_CLASSES
; i
++)
1466 trigger
= trigdesc
->triggers
;
1467 for (i
= 0; i
< trigdesc
->numtriggers
; i
++)
1469 pfree(trigger
->tgname
);
1470 if (trigger
->tgnattr
> 0)
1471 pfree(trigger
->tgattr
);
1472 if (trigger
->tgnargs
> 0)
1474 while (--(trigger
->tgnargs
) >= 0)
1475 pfree(trigger
->tgargs
[trigger
->tgnargs
]);
1476 pfree(trigger
->tgargs
);
1480 pfree(trigdesc
->triggers
);
1485 * Compare two TriggerDesc structures for logical equality.
1489 equalTriggerDescs(TriggerDesc
*trigdesc1
, TriggerDesc
*trigdesc2
)
1495 * We need not examine the "index" data, just the trigger array itself; if
1496 * we have the same triggers with the same types, the derived index data
1499 * As of 7.3 we assume trigger set ordering is significant in the
1500 * comparison; so we just compare corresponding slots of the two sets.
1502 if (trigdesc1
!= NULL
)
1504 if (trigdesc2
== NULL
)
1506 if (trigdesc1
->numtriggers
!= trigdesc2
->numtriggers
)
1508 for (i
= 0; i
< trigdesc1
->numtriggers
; i
++)
1510 Trigger
*trig1
= trigdesc1
->triggers
+ i
;
1511 Trigger
*trig2
= trigdesc2
->triggers
+ i
;
1513 if (trig1
->tgoid
!= trig2
->tgoid
)
1515 if (strcmp(trig1
->tgname
, trig2
->tgname
) != 0)
1517 if (trig1
->tgfoid
!= trig2
->tgfoid
)
1519 if (trig1
->tgtype
!= trig2
->tgtype
)
1521 if (trig1
->tgenabled
!= trig2
->tgenabled
)
1523 if (trig1
->tgisconstraint
!= trig2
->tgisconstraint
)
1525 if (trig1
->tgconstrrelid
!= trig2
->tgconstrrelid
)
1527 if (trig1
->tgconstraint
!= trig2
->tgconstraint
)
1529 if (trig1
->tgdeferrable
!= trig2
->tgdeferrable
)
1531 if (trig1
->tginitdeferred
!= trig2
->tginitdeferred
)
1533 if (trig1
->tgnargs
!= trig2
->tgnargs
)
1535 if (trig1
->tgnattr
!= trig2
->tgnattr
)
1537 if (trig1
->tgnattr
> 0 &&
1538 memcmp(trig1
->tgattr
, trig2
->tgattr
,
1539 trig1
->tgnattr
* sizeof(int2
)) != 0)
1541 for (j
= 0; j
< trig1
->tgnargs
; j
++)
1542 if (strcmp(trig1
->tgargs
[j
], trig2
->tgargs
[j
]) != 0)
1546 else if (trigdesc2
!= NULL
)
1550 #endif /* NOT_USED */
1553 * Call a trigger function.
1555 * trigdata: trigger descriptor.
1556 * tgindx: trigger's index in finfo and instr arrays.
1557 * finfo: array of cached trigger function call information.
1558 * instr: optional array of EXPLAIN ANALYZE instrumentation state.
1559 * per_tuple_context: memory context to execute the function in.
1561 * Returns the tuple (or NULL) as returned by the function.
1564 ExecCallTriggerFunc(TriggerData
*trigdata
,
1567 Instrumentation
*instr
,
1568 MemoryContext per_tuple_context
)
1570 FunctionCallInfoData fcinfo
;
1571 PgStat_FunctionCallUsage fcusage
;
1573 MemoryContext oldContext
;
1578 * We cache fmgr lookup info, to avoid making the lookup again on each
1581 if (finfo
->fn_oid
== InvalidOid
)
1582 fmgr_info(trigdata
->tg_trigger
->tgfoid
, finfo
);
1584 Assert(finfo
->fn_oid
== trigdata
->tg_trigger
->tgfoid
);
1587 * If doing EXPLAIN ANALYZE, start charging time to this trigger.
1590 InstrStartNode(instr
+ tgindx
);
1593 * Do the function evaluation in the per-tuple memory context, so that
1594 * leaked memory will be reclaimed once per tuple. Note in particular that
1595 * any new tuple created by the trigger function will live till the end of
1598 oldContext
= MemoryContextSwitchTo(per_tuple_context
);
1601 * Call the function, passing no arguments but setting a context.
1603 InitFunctionCallInfoData(fcinfo
, finfo
, 0, (Node
*) trigdata
, NULL
);
1605 pgstat_init_function_usage(&fcinfo
, &fcusage
);
1607 result
= FunctionCallInvoke(&fcinfo
);
1609 pgstat_end_function_usage(&fcusage
, true);
1611 MemoryContextSwitchTo(oldContext
);
1614 * Trigger protocol allows function to return a null pointer, but NOT to
1615 * set the isnull result flag.
1619 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED
),
1620 errmsg("trigger function %u returned null value",
1621 fcinfo
.flinfo
->fn_oid
)));
1624 * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
1625 * one "tuple returned" (really the number of firings).
1628 InstrStopNode(instr
+ tgindx
, 1);
1630 return (HeapTuple
) DatumGetPointer(result
);
1634 ExecBSInsertTriggers(EState
*estate
, ResultRelInfo
*relinfo
)
1636 TriggerDesc
*trigdesc
;
1640 TriggerData LocTriggerData
;
1642 trigdesc
= relinfo
->ri_TrigDesc
;
1644 if (trigdesc
== NULL
)
1647 ntrigs
= trigdesc
->n_before_statement
[TRIGGER_EVENT_INSERT
];
1648 tgindx
= trigdesc
->tg_before_statement
[TRIGGER_EVENT_INSERT
];
1653 LocTriggerData
.type
= T_TriggerData
;
1654 LocTriggerData
.tg_event
= TRIGGER_EVENT_INSERT
|
1655 TRIGGER_EVENT_BEFORE
;
1656 LocTriggerData
.tg_relation
= relinfo
->ri_RelationDesc
;
1657 LocTriggerData
.tg_trigtuple
= NULL
;
1658 LocTriggerData
.tg_newtuple
= NULL
;
1659 LocTriggerData
.tg_trigtuplebuf
= InvalidBuffer
;
1660 LocTriggerData
.tg_newtuplebuf
= InvalidBuffer
;
1661 for (i
= 0; i
< ntrigs
; i
++)
1663 Trigger
*trigger
= &trigdesc
->triggers
[tgindx
[i
]];
1666 if (SessionReplicationRole
== SESSION_REPLICATION_ROLE_REPLICA
)
1668 if (trigger
->tgenabled
== TRIGGER_FIRES_ON_ORIGIN
||
1669 trigger
->tgenabled
== TRIGGER_DISABLED
)
1672 else /* ORIGIN or LOCAL role */
1674 if (trigger
->tgenabled
== TRIGGER_FIRES_ON_REPLICA
||
1675 trigger
->tgenabled
== TRIGGER_DISABLED
)
1678 LocTriggerData
.tg_trigger
= trigger
;
1679 newtuple
= ExecCallTriggerFunc(&LocTriggerData
,
1681 relinfo
->ri_TrigFunctions
,
1682 relinfo
->ri_TrigInstrument
,
1683 GetPerTupleMemoryContext(estate
));
1687 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED
),
1688 errmsg("BEFORE STATEMENT trigger cannot return a value")));
1693 ExecASInsertTriggers(EState
*estate
, ResultRelInfo
*relinfo
)
1695 TriggerDesc
*trigdesc
= relinfo
->ri_TrigDesc
;
1697 if (trigdesc
&& trigdesc
->n_after_statement
[TRIGGER_EVENT_INSERT
] > 0)
1698 AfterTriggerSaveEvent(relinfo
, TRIGGER_EVENT_INSERT
,
1703 ExecBRInsertTriggers(EState
*estate
, ResultRelInfo
*relinfo
,
1704 HeapTuple trigtuple
)
1706 TriggerDesc
*trigdesc
= relinfo
->ri_TrigDesc
;
1707 int ntrigs
= trigdesc
->n_before_row
[TRIGGER_EVENT_INSERT
];
1708 int *tgindx
= trigdesc
->tg_before_row
[TRIGGER_EVENT_INSERT
];
1709 HeapTuple newtuple
= trigtuple
;
1711 TriggerData LocTriggerData
;
1714 LocTriggerData
.type
= T_TriggerData
;
1715 LocTriggerData
.tg_event
= TRIGGER_EVENT_INSERT
|
1717 TRIGGER_EVENT_BEFORE
;
1718 LocTriggerData
.tg_relation
= relinfo
->ri_RelationDesc
;
1719 LocTriggerData
.tg_newtuple
= NULL
;
1720 LocTriggerData
.tg_newtuplebuf
= InvalidBuffer
;
1721 for (i
= 0; i
< ntrigs
; i
++)
1723 Trigger
*trigger
= &trigdesc
->triggers
[tgindx
[i
]];
1725 if (SessionReplicationRole
== SESSION_REPLICATION_ROLE_REPLICA
)
1727 if (trigger
->tgenabled
== TRIGGER_FIRES_ON_ORIGIN
||
1728 trigger
->tgenabled
== TRIGGER_DISABLED
)
1731 else /* ORIGIN or LOCAL role */
1733 if (trigger
->tgenabled
== TRIGGER_FIRES_ON_REPLICA
||
1734 trigger
->tgenabled
== TRIGGER_DISABLED
)
1737 LocTriggerData
.tg_trigtuple
= oldtuple
= newtuple
;
1738 LocTriggerData
.tg_trigtuplebuf
= InvalidBuffer
;
1739 LocTriggerData
.tg_trigger
= trigger
;
1740 newtuple
= ExecCallTriggerFunc(&LocTriggerData
,
1742 relinfo
->ri_TrigFunctions
,
1743 relinfo
->ri_TrigInstrument
,
1744 GetPerTupleMemoryContext(estate
));
1745 if (oldtuple
!= newtuple
&& oldtuple
!= trigtuple
)
1746 heap_freetuple(oldtuple
);
1747 if (newtuple
== NULL
)
1754 ExecARInsertTriggers(EState
*estate
, ResultRelInfo
*relinfo
,
1755 HeapTuple trigtuple
)
1757 TriggerDesc
*trigdesc
= relinfo
->ri_TrigDesc
;
1759 if (trigdesc
&& trigdesc
->n_after_row
[TRIGGER_EVENT_INSERT
] > 0)
1760 AfterTriggerSaveEvent(relinfo
, TRIGGER_EVENT_INSERT
,
1761 true, NULL
, trigtuple
);
1765 ExecBSDeleteTriggers(EState
*estate
, ResultRelInfo
*relinfo
)
1767 TriggerDesc
*trigdesc
;
1771 TriggerData LocTriggerData
;
1773 trigdesc
= relinfo
->ri_TrigDesc
;
1775 if (trigdesc
== NULL
)
1778 ntrigs
= trigdesc
->n_before_statement
[TRIGGER_EVENT_DELETE
];
1779 tgindx
= trigdesc
->tg_before_statement
[TRIGGER_EVENT_DELETE
];
1784 LocTriggerData
.type
= T_TriggerData
;
1785 LocTriggerData
.tg_event
= TRIGGER_EVENT_DELETE
|
1786 TRIGGER_EVENT_BEFORE
;
1787 LocTriggerData
.tg_relation
= relinfo
->ri_RelationDesc
;
1788 LocTriggerData
.tg_trigtuple
= NULL
;
1789 LocTriggerData
.tg_newtuple
= NULL
;
1790 LocTriggerData
.tg_trigtuplebuf
= InvalidBuffer
;
1791 LocTriggerData
.tg_newtuplebuf
= InvalidBuffer
;
1792 for (i
= 0; i
< ntrigs
; i
++)
1794 Trigger
*trigger
= &trigdesc
->triggers
[tgindx
[i
]];
1797 if (SessionReplicationRole
== SESSION_REPLICATION_ROLE_REPLICA
)
1799 if (trigger
->tgenabled
== TRIGGER_FIRES_ON_ORIGIN
||
1800 trigger
->tgenabled
== TRIGGER_DISABLED
)
1803 else /* ORIGIN or LOCAL role */
1805 if (trigger
->tgenabled
== TRIGGER_FIRES_ON_REPLICA
||
1806 trigger
->tgenabled
== TRIGGER_DISABLED
)
1809 LocTriggerData
.tg_trigger
= trigger
;
1810 newtuple
= ExecCallTriggerFunc(&LocTriggerData
,
1812 relinfo
->ri_TrigFunctions
,
1813 relinfo
->ri_TrigInstrument
,
1814 GetPerTupleMemoryContext(estate
));
1818 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED
),
1819 errmsg("BEFORE STATEMENT trigger cannot return a value")));
1824 ExecASDeleteTriggers(EState
*estate
, ResultRelInfo
*relinfo
)
1826 TriggerDesc
*trigdesc
= relinfo
->ri_TrigDesc
;
1828 if (trigdesc
&& trigdesc
->n_after_statement
[TRIGGER_EVENT_DELETE
] > 0)
1829 AfterTriggerSaveEvent(relinfo
, TRIGGER_EVENT_DELETE
,
1834 ExecBRDeleteTriggers(EState
*estate
, ResultRelInfo
*relinfo
,
1835 ItemPointer tupleid
)
1837 TriggerDesc
*trigdesc
= relinfo
->ri_TrigDesc
;
1838 int ntrigs
= trigdesc
->n_before_row
[TRIGGER_EVENT_DELETE
];
1839 int *tgindx
= trigdesc
->tg_before_row
[TRIGGER_EVENT_DELETE
];
1841 TriggerData LocTriggerData
;
1842 HeapTuple trigtuple
;
1844 TupleTableSlot
*newSlot
;
1847 trigtuple
= GetTupleForTrigger(estate
, relinfo
, tupleid
, &newSlot
);
1848 if (trigtuple
== NULL
)
1851 LocTriggerData
.type
= T_TriggerData
;
1852 LocTriggerData
.tg_event
= TRIGGER_EVENT_DELETE
|
1854 TRIGGER_EVENT_BEFORE
;
1855 LocTriggerData
.tg_relation
= relinfo
->ri_RelationDesc
;
1856 LocTriggerData
.tg_newtuple
= NULL
;
1857 LocTriggerData
.tg_newtuplebuf
= InvalidBuffer
;
1858 for (i
= 0; i
< ntrigs
; i
++)
1860 Trigger
*trigger
= &trigdesc
->triggers
[tgindx
[i
]];
1862 if (SessionReplicationRole
== SESSION_REPLICATION_ROLE_REPLICA
)
1864 if (trigger
->tgenabled
== TRIGGER_FIRES_ON_ORIGIN
||
1865 trigger
->tgenabled
== TRIGGER_DISABLED
)
1868 else /* ORIGIN or LOCAL role */
1870 if (trigger
->tgenabled
== TRIGGER_FIRES_ON_REPLICA
||
1871 trigger
->tgenabled
== TRIGGER_DISABLED
)
1874 LocTriggerData
.tg_trigtuple
= trigtuple
;
1875 LocTriggerData
.tg_trigtuplebuf
= InvalidBuffer
;
1876 LocTriggerData
.tg_trigger
= trigger
;
1877 newtuple
= ExecCallTriggerFunc(&LocTriggerData
,
1879 relinfo
->ri_TrigFunctions
,
1880 relinfo
->ri_TrigInstrument
,
1881 GetPerTupleMemoryContext(estate
));
1882 if (newtuple
== NULL
)
1884 result
= false; /* tell caller to suppress delete */
1887 if (newtuple
!= trigtuple
)
1888 heap_freetuple(newtuple
);
1890 heap_freetuple(trigtuple
);
1896 ExecARDeleteTriggers(EState
*estate
, ResultRelInfo
*relinfo
,
1897 ItemPointer tupleid
)
1899 TriggerDesc
*trigdesc
= relinfo
->ri_TrigDesc
;
1901 if (trigdesc
&& trigdesc
->n_after_row
[TRIGGER_EVENT_DELETE
] > 0)
1903 HeapTuple trigtuple
= GetTupleForTrigger(estate
, relinfo
,
1906 AfterTriggerSaveEvent(relinfo
, TRIGGER_EVENT_DELETE
,
1907 true, trigtuple
, NULL
);
1908 heap_freetuple(trigtuple
);
1913 ExecBSUpdateTriggers(EState
*estate
, ResultRelInfo
*relinfo
)
1915 TriggerDesc
*trigdesc
;
1919 TriggerData LocTriggerData
;
1921 trigdesc
= relinfo
->ri_TrigDesc
;
1923 if (trigdesc
== NULL
)
1926 ntrigs
= trigdesc
->n_before_statement
[TRIGGER_EVENT_UPDATE
];
1927 tgindx
= trigdesc
->tg_before_statement
[TRIGGER_EVENT_UPDATE
];
1932 LocTriggerData
.type
= T_TriggerData
;
1933 LocTriggerData
.tg_event
= TRIGGER_EVENT_UPDATE
|
1934 TRIGGER_EVENT_BEFORE
;
1935 LocTriggerData
.tg_relation
= relinfo
->ri_RelationDesc
;
1936 LocTriggerData
.tg_trigtuple
= NULL
;
1937 LocTriggerData
.tg_newtuple
= NULL
;
1938 LocTriggerData
.tg_trigtuplebuf
= InvalidBuffer
;
1939 LocTriggerData
.tg_newtuplebuf
= InvalidBuffer
;
1940 for (i
= 0; i
< ntrigs
; i
++)
1942 Trigger
*trigger
= &trigdesc
->triggers
[tgindx
[i
]];
1945 if (SessionReplicationRole
== SESSION_REPLICATION_ROLE_REPLICA
)
1947 if (trigger
->tgenabled
== TRIGGER_FIRES_ON_ORIGIN
||
1948 trigger
->tgenabled
== TRIGGER_DISABLED
)
1951 else /* ORIGIN or LOCAL role */
1953 if (trigger
->tgenabled
== TRIGGER_FIRES_ON_REPLICA
||
1954 trigger
->tgenabled
== TRIGGER_DISABLED
)
1957 LocTriggerData
.tg_trigger
= trigger
;
1958 newtuple
= ExecCallTriggerFunc(&LocTriggerData
,
1960 relinfo
->ri_TrigFunctions
,
1961 relinfo
->ri_TrigInstrument
,
1962 GetPerTupleMemoryContext(estate
));
1966 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED
),
1967 errmsg("BEFORE STATEMENT trigger cannot return a value")));
1972 ExecASUpdateTriggers(EState
*estate
, ResultRelInfo
*relinfo
)
1974 TriggerDesc
*trigdesc
= relinfo
->ri_TrigDesc
;
1976 if (trigdesc
&& trigdesc
->n_after_statement
[TRIGGER_EVENT_UPDATE
] > 0)
1977 AfterTriggerSaveEvent(relinfo
, TRIGGER_EVENT_UPDATE
,
1982 ExecBRUpdateTriggers(EState
*estate
, ResultRelInfo
*relinfo
,
1983 ItemPointer tupleid
, HeapTuple newtuple
)
1985 TriggerDesc
*trigdesc
= relinfo
->ri_TrigDesc
;
1986 int ntrigs
= trigdesc
->n_before_row
[TRIGGER_EVENT_UPDATE
];
1987 int *tgindx
= trigdesc
->tg_before_row
[TRIGGER_EVENT_UPDATE
];
1988 TriggerData LocTriggerData
;
1989 HeapTuple trigtuple
;
1991 HeapTuple intuple
= newtuple
;
1992 TupleTableSlot
*newSlot
;
1995 trigtuple
= GetTupleForTrigger(estate
, relinfo
, tupleid
, &newSlot
);
1996 if (trigtuple
== NULL
)
2000 * In READ COMMITTED isolation level it's possible that newtuple was
2001 * changed due to concurrent update.
2003 if (newSlot
!= NULL
)
2004 intuple
= newtuple
= ExecRemoveJunk(estate
->es_junkFilter
, newSlot
);
2006 LocTriggerData
.type
= T_TriggerData
;
2007 LocTriggerData
.tg_event
= TRIGGER_EVENT_UPDATE
|
2009 TRIGGER_EVENT_BEFORE
;
2010 LocTriggerData
.tg_relation
= relinfo
->ri_RelationDesc
;
2011 for (i
= 0; i
< ntrigs
; i
++)
2013 Trigger
*trigger
= &trigdesc
->triggers
[tgindx
[i
]];
2015 if (SessionReplicationRole
== SESSION_REPLICATION_ROLE_REPLICA
)
2017 if (trigger
->tgenabled
== TRIGGER_FIRES_ON_ORIGIN
||
2018 trigger
->tgenabled
== TRIGGER_DISABLED
)
2021 else /* ORIGIN or LOCAL role */
2023 if (trigger
->tgenabled
== TRIGGER_FIRES_ON_REPLICA
||
2024 trigger
->tgenabled
== TRIGGER_DISABLED
)
2027 LocTriggerData
.tg_trigtuple
= trigtuple
;
2028 LocTriggerData
.tg_newtuple
= oldtuple
= newtuple
;
2029 LocTriggerData
.tg_trigtuplebuf
= InvalidBuffer
;
2030 LocTriggerData
.tg_newtuplebuf
= InvalidBuffer
;
2031 LocTriggerData
.tg_trigger
= trigger
;
2032 newtuple
= ExecCallTriggerFunc(&LocTriggerData
,
2034 relinfo
->ri_TrigFunctions
,
2035 relinfo
->ri_TrigInstrument
,
2036 GetPerTupleMemoryContext(estate
));
2037 if (oldtuple
!= newtuple
&& oldtuple
!= intuple
)
2038 heap_freetuple(oldtuple
);
2039 if (newtuple
== NULL
)
2042 heap_freetuple(trigtuple
);
2047 ExecARUpdateTriggers(EState
*estate
, ResultRelInfo
*relinfo
,
2048 ItemPointer tupleid
, HeapTuple newtuple
)
2050 TriggerDesc
*trigdesc
= relinfo
->ri_TrigDesc
;
2052 if (trigdesc
&& trigdesc
->n_after_row
[TRIGGER_EVENT_UPDATE
] > 0)
2054 HeapTuple trigtuple
= GetTupleForTrigger(estate
, relinfo
,
2057 AfterTriggerSaveEvent(relinfo
, TRIGGER_EVENT_UPDATE
,
2058 true, trigtuple
, newtuple
);
2059 heap_freetuple(trigtuple
);
2064 ExecBSTruncateTriggers(EState
*estate
, ResultRelInfo
*relinfo
)
2066 TriggerDesc
*trigdesc
;
2070 TriggerData LocTriggerData
;
2072 trigdesc
= relinfo
->ri_TrigDesc
;
2074 if (trigdesc
== NULL
)
2077 ntrigs
= trigdesc
->n_before_statement
[TRIGGER_EVENT_TRUNCATE
];
2078 tgindx
= trigdesc
->tg_before_statement
[TRIGGER_EVENT_TRUNCATE
];
2083 LocTriggerData
.type
= T_TriggerData
;
2084 LocTriggerData
.tg_event
= TRIGGER_EVENT_TRUNCATE
|
2085 TRIGGER_EVENT_BEFORE
;
2086 LocTriggerData
.tg_relation
= relinfo
->ri_RelationDesc
;
2087 LocTriggerData
.tg_trigtuple
= NULL
;
2088 LocTriggerData
.tg_newtuple
= NULL
;
2089 LocTriggerData
.tg_trigtuplebuf
= InvalidBuffer
;
2090 LocTriggerData
.tg_newtuplebuf
= InvalidBuffer
;
2091 for (i
= 0; i
< ntrigs
; i
++)
2093 Trigger
*trigger
= &trigdesc
->triggers
[tgindx
[i
]];
2096 if (SessionReplicationRole
== SESSION_REPLICATION_ROLE_REPLICA
)
2098 if (trigger
->tgenabled
== TRIGGER_FIRES_ON_ORIGIN
||
2099 trigger
->tgenabled
== TRIGGER_DISABLED
)
2102 else /* ORIGIN or LOCAL role */
2104 if (trigger
->tgenabled
== TRIGGER_FIRES_ON_REPLICA
||
2105 trigger
->tgenabled
== TRIGGER_DISABLED
)
2108 LocTriggerData
.tg_trigger
= trigger
;
2109 newtuple
= ExecCallTriggerFunc(&LocTriggerData
,
2111 relinfo
->ri_TrigFunctions
,
2112 relinfo
->ri_TrigInstrument
,
2113 GetPerTupleMemoryContext(estate
));
2117 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED
),
2118 errmsg("BEFORE STATEMENT trigger cannot return a value")));
2123 ExecASTruncateTriggers(EState
*estate
, ResultRelInfo
*relinfo
)
2125 TriggerDesc
*trigdesc
= relinfo
->ri_TrigDesc
;
2127 if (trigdesc
&& trigdesc
->n_after_statement
[TRIGGER_EVENT_TRUNCATE
] > 0)
2128 AfterTriggerSaveEvent(relinfo
, TRIGGER_EVENT_TRUNCATE
,
2134 GetTupleForTrigger(EState
*estate
, ResultRelInfo
*relinfo
,
2136 TupleTableSlot
**newSlot
)
2138 Relation relation
= relinfo
->ri_RelationDesc
;
2139 HeapTupleData tuple
;
2143 if (newSlot
!= NULL
)
2146 ItemPointerData update_ctid
;
2147 TransactionId update_xmax
;
2152 * lock tuple for update
2155 tuple
.t_self
= *tid
;
2156 test
= heap_lock_tuple(relation
, &tuple
, &buffer
,
2157 &update_ctid
, &update_xmax
,
2158 estate
->es_output_cid
,
2159 LockTupleExclusive
, false);
2162 case HeapTupleSelfUpdated
:
2163 /* treat it as deleted; do not process */
2164 ReleaseBuffer(buffer
);
2167 case HeapTupleMayBeUpdated
:
2170 case HeapTupleUpdated
:
2171 ReleaseBuffer(buffer
);
2172 if (IsXactIsoLevelSerializable
)
2174 (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE
),
2175 errmsg("could not serialize access due to concurrent update")));
2176 else if (!ItemPointerEquals(&update_ctid
, &tuple
.t_self
))
2178 /* it was updated, so look at the updated version */
2179 TupleTableSlot
*epqslot
;
2181 epqslot
= EvalPlanQual(estate
,
2182 relinfo
->ri_RangeTableIndex
,
2185 if (!TupIsNull(epqslot
))
2194 * if tuple was deleted or PlanQual failed for updated tuple -
2195 * we have not process this tuple!
2200 ReleaseBuffer(buffer
);
2201 elog(ERROR
, "unrecognized heap_lock_tuple status: %u", test
);
2202 return NULL
; /* keep compiler quiet */
2210 buffer
= ReadBuffer(relation
, ItemPointerGetBlockNumber(tid
));
2212 page
= BufferGetPage(buffer
);
2213 lp
= PageGetItemId(page
, ItemPointerGetOffsetNumber(tid
));
2215 Assert(ItemIdIsNormal(lp
));
2217 tuple
.t_data
= (HeapTupleHeader
) PageGetItem(page
, lp
);
2218 tuple
.t_len
= ItemIdGetLength(lp
);
2219 tuple
.t_self
= *tid
;
2220 tuple
.t_tableOid
= RelationGetRelid(relation
);
2223 result
= heap_copytuple(&tuple
);
2224 ReleaseBuffer(buffer
);
2231 * After-trigger stuff
2233 * The AfterTriggersData struct holds data about pending AFTER trigger events
2234 * during the current transaction tree. (BEFORE triggers are fired
2235 * immediately so we don't need any persistent state about them.) The struct
2236 * and most of its subsidiary data are kept in TopTransactionContext; however
2237 * the individual event records are kept in separate contexts, to make them
2238 * easy to delete during subtransaction abort.
2240 * Because the list of pending events can grow large, we go to some effort
2241 * to minimize memory consumption. We do not use the generic List mechanism
2242 * but thread the events manually.
2244 * XXX We need to be able to save the per-event data in a file if it grows too
2249 /* Per-trigger SET CONSTRAINT status */
2250 typedef struct SetConstraintTriggerData
2253 bool sct_tgisdeferred
;
2254 } SetConstraintTriggerData
;
2256 typedef struct SetConstraintTriggerData
*SetConstraintTrigger
;
2259 * SET CONSTRAINT intra-transaction status.
2261 * We make this a single palloc'd object so it can be copied and freed easily.
2263 * all_isset and all_isdeferred are used to keep track
2264 * of SET CONSTRAINTS ALL {DEFERRED, IMMEDIATE}.
2266 * trigstates[] stores per-trigger tgisdeferred settings.
2268 typedef struct SetConstraintStateData
2271 bool all_isdeferred
;
2272 int numstates
; /* number of trigstates[] entries in use */
2273 int numalloc
; /* allocated size of trigstates[] */
2274 SetConstraintTriggerData trigstates
[1]; /* VARIABLE LENGTH ARRAY */
2275 } SetConstraintStateData
;
2277 typedef SetConstraintStateData
*SetConstraintState
;
2281 * Per-trigger-event data
2283 * Note: ate_firing_id is meaningful when either AFTER_TRIGGER_DONE
2284 * or AFTER_TRIGGER_IN_PROGRESS is set. It indicates which trigger firing
2285 * cycle the trigger was or will be fired in.
2287 typedef struct AfterTriggerEventData
*AfterTriggerEvent
;
2289 typedef struct AfterTriggerEventData
2291 AfterTriggerEvent ate_next
; /* list link */
2292 TriggerEvent ate_event
; /* event type and status bits */
2293 CommandId ate_firing_id
; /* ID for firing cycle */
2294 Oid ate_tgoid
; /* the trigger's ID */
2295 Oid ate_relid
; /* the relation it's on */
2296 ItemPointerData ate_oldctid
; /* specific tuple(s) involved */
2297 ItemPointerData ate_newctid
;
2298 } AfterTriggerEventData
;
2300 /* A list of events */
2301 typedef struct AfterTriggerEventList
2303 AfterTriggerEvent head
;
2304 AfterTriggerEvent tail
;
2305 } AfterTriggerEventList
;
2309 * All per-transaction data for the AFTER TRIGGERS module.
2311 * AfterTriggersData has the following fields:
2313 * firing_counter is incremented for each call of afterTriggerInvokeEvents.
2314 * We mark firable events with the current firing cycle's ID so that we can
2315 * tell which ones to work on. This ensures sane behavior if a trigger
2316 * function chooses to do SET CONSTRAINTS: the inner SET CONSTRAINTS will
2317 * only fire those events that weren't already scheduled for firing.
2319 * state keeps track of the transaction-local effects of SET CONSTRAINTS.
2320 * This is saved and restored across failed subtransactions.
2322 * events is the current list of deferred events. This is global across
2323 * all subtransactions of the current transaction. In a subtransaction
2324 * abort, we know that the events added by the subtransaction are at the
2325 * end of the list, so it is relatively easy to discard them. The event
2326 * structs themselves are stored in event_cxt if generated by the top-level
2327 * transaction, else in per-subtransaction contexts identified by the
2328 * entries in cxt_stack.
2330 * query_depth is the current depth of nested AfterTriggerBeginQuery calls
2331 * (-1 when the stack is empty).
2333 * query_stack[query_depth] is a list of AFTER trigger events queued by the
2334 * current query (and the query_stack entries below it are lists of trigger
2335 * events queued by calling queries). None of these are valid until the
2336 * matching AfterTriggerEndQuery call occurs. At that point we fire
2337 * immediate-mode triggers, and append any deferred events to the main events
2340 * maxquerydepth is just the allocated length of query_stack.
2342 * state_stack is a stack of pointers to saved copies of the SET CONSTRAINTS
2343 * state data; each subtransaction level that modifies that state first
2344 * saves a copy, which we use to restore the state if we abort.
2346 * events_stack is a stack of copies of the events head/tail pointers,
2347 * which we use to restore those values during subtransaction abort.
2349 * depth_stack is a stack of copies of subtransaction-start-time query_depth,
2350 * which we similarly use to clean up at subtransaction abort.
2352 * firing_stack is a stack of copies of subtransaction-start-time
2353 * firing_counter. We use this to recognize which deferred triggers were
2354 * fired (or marked for firing) within an aborted subtransaction.
2356 * We use GetCurrentTransactionNestLevel() to determine the correct array
2357 * index in these stacks. maxtransdepth is the number of allocated entries in
2358 * each stack. (By not keeping our own stack pointer, we can avoid trouble
2359 * in cases where errors during subxact abort cause multiple invocations
2360 * of AfterTriggerEndSubXact() at the same nesting depth.)
2362 typedef struct AfterTriggersData
2364 CommandId firing_counter
; /* next firing ID to assign */
2365 SetConstraintState state
; /* the active S C state */
2366 AfterTriggerEventList events
; /* deferred-event list */
2367 int query_depth
; /* current query list index */
2368 AfterTriggerEventList
*query_stack
; /* events pending from each query */
2369 int maxquerydepth
; /* allocated len of above array */
2370 MemoryContext event_cxt
; /* top transaction's event context, if any */
2371 MemoryContext
*cxt_stack
; /* per-subtransaction event contexts */
2373 /* these fields are just for resetting at subtrans abort: */
2375 SetConstraintState
*state_stack
; /* stacked S C states */
2376 AfterTriggerEventList
*events_stack
; /* stacked list pointers */
2377 int *depth_stack
; /* stacked query_depths */
2378 CommandId
*firing_stack
; /* stacked firing_counters */
2379 int maxtransdepth
; /* allocated len of above arrays */
2380 } AfterTriggersData
;
2382 typedef AfterTriggersData
*AfterTriggers
;
2384 static AfterTriggers afterTriggers
;
2387 static void AfterTriggerExecute(AfterTriggerEvent event
,
2388 Relation rel
, TriggerDesc
*trigdesc
,
2390 Instrumentation
*instr
,
2391 MemoryContext per_tuple_context
);
2392 static SetConstraintState
SetConstraintStateCreate(int numalloc
);
2393 static SetConstraintState
SetConstraintStateCopy(SetConstraintState state
);
2394 static SetConstraintState
SetConstraintStateAddItem(SetConstraintState state
,
2395 Oid tgoid
, bool tgisdeferred
);
2399 * afterTriggerCheckState()
2401 * Returns true if the trigger identified by tgoid is actually
2402 * in state DEFERRED.
2406 afterTriggerCheckState(Oid tgoid
, TriggerEvent eventstate
)
2408 SetConstraintState state
= afterTriggers
->state
;
2412 * For not-deferrable triggers (i.e. normal AFTER ROW triggers and
2413 * constraints declared NOT DEFERRABLE), the state is always false.
2415 if ((eventstate
& AFTER_TRIGGER_DEFERRABLE
) == 0)
2419 * Check if SET CONSTRAINTS has been executed for this specific trigger.
2421 for (i
= 0; i
< state
->numstates
; i
++)
2423 if (state
->trigstates
[i
].sct_tgoid
== tgoid
)
2424 return state
->trigstates
[i
].sct_tgisdeferred
;
2428 * Check if SET CONSTRAINTS ALL has been executed; if so use that.
2430 if (state
->all_isset
)
2431 return state
->all_isdeferred
;
2434 * Otherwise return the default state for the trigger.
2436 return ((eventstate
& AFTER_TRIGGER_INITDEFERRED
) != 0);
2441 * afterTriggerAddEvent()
2443 * Add a new trigger event to the current query's queue.
2447 afterTriggerAddEvent(AfterTriggerEvent event
)
2449 AfterTriggerEventList
*events
;
2451 Assert(event
->ate_next
== NULL
);
2453 /* Must be inside a query */
2454 Assert(afterTriggers
->query_depth
>= 0);
2456 events
= &afterTriggers
->query_stack
[afterTriggers
->query_depth
];
2457 if (events
->tail
== NULL
)
2459 /* first list entry */
2460 events
->head
= event
;
2461 events
->tail
= event
;
2465 events
->tail
->ate_next
= event
;
2466 events
->tail
= event
;
2472 * AfterTriggerExecute()
2474 * Fetch the required tuples back from the heap and fire one
2475 * single trigger function.
2477 * Frequently, this will be fired many times in a row for triggers of
2478 * a single relation. Therefore, we cache the open relation and provide
2479 * fmgr lookup cache space at the caller level. (For triggers fired at
2480 * the end of a query, we can even piggyback on the executor's state.)
2482 * event: event currently being fired.
2483 * rel: open relation for event.
2484 * trigdesc: working copy of rel's trigger info.
2485 * finfo: array of fmgr lookup cache entries (one per trigger in trigdesc).
2486 * instr: array of EXPLAIN ANALYZE instrumentation nodes (one per trigger),
2487 * or NULL if no instrumentation is wanted.
2488 * per_tuple_context: memory context to call trigger function in.
2492 AfterTriggerExecute(AfterTriggerEvent event
,
2493 Relation rel
, TriggerDesc
*trigdesc
,
2494 FmgrInfo
*finfo
, Instrumentation
*instr
,
2495 MemoryContext per_tuple_context
)
2497 Oid tgoid
= event
->ate_tgoid
;
2498 TriggerData LocTriggerData
;
2499 HeapTupleData oldtuple
;
2500 HeapTupleData newtuple
;
2502 Buffer oldbuffer
= InvalidBuffer
;
2503 Buffer newbuffer
= InvalidBuffer
;
2507 * Locate trigger in trigdesc.
2509 LocTriggerData
.tg_trigger
= NULL
;
2510 for (tgindx
= 0; tgindx
< trigdesc
->numtriggers
; tgindx
++)
2512 if (trigdesc
->triggers
[tgindx
].tgoid
== tgoid
)
2514 LocTriggerData
.tg_trigger
= &(trigdesc
->triggers
[tgindx
]);
2518 if (LocTriggerData
.tg_trigger
== NULL
)
2519 elog(ERROR
, "could not find trigger %u", tgoid
);
2522 * If doing EXPLAIN ANALYZE, start charging time to this trigger. We want
2523 * to include time spent re-fetching tuples in the trigger cost.
2526 InstrStartNode(instr
+ tgindx
);
2529 * Fetch the required OLD and NEW tuples.
2531 LocTriggerData
.tg_trigtuple
= NULL
;
2532 LocTriggerData
.tg_newtuple
= NULL
;
2533 LocTriggerData
.tg_trigtuplebuf
= InvalidBuffer
;
2534 LocTriggerData
.tg_newtuplebuf
= InvalidBuffer
;
2536 if (ItemPointerIsValid(&(event
->ate_oldctid
)))
2538 ItemPointerCopy(&(event
->ate_oldctid
), &(oldtuple
.t_self
));
2539 if (!heap_fetch(rel
, SnapshotAny
, &oldtuple
, &oldbuffer
, false, NULL
))
2540 elog(ERROR
, "failed to fetch old tuple for AFTER trigger");
2541 LocTriggerData
.tg_trigtuple
= &oldtuple
;
2542 LocTriggerData
.tg_trigtuplebuf
= oldbuffer
;
2545 if (ItemPointerIsValid(&(event
->ate_newctid
)))
2547 ItemPointerCopy(&(event
->ate_newctid
), &(newtuple
.t_self
));
2548 if (!heap_fetch(rel
, SnapshotAny
, &newtuple
, &newbuffer
, false, NULL
))
2549 elog(ERROR
, "failed to fetch new tuple for AFTER trigger");
2550 if (LocTriggerData
.tg_trigtuple
!= NULL
)
2552 LocTriggerData
.tg_newtuple
= &newtuple
;
2553 LocTriggerData
.tg_newtuplebuf
= newbuffer
;
2557 LocTriggerData
.tg_trigtuple
= &newtuple
;
2558 LocTriggerData
.tg_trigtuplebuf
= newbuffer
;
2563 * Setup the remaining trigger information
2565 LocTriggerData
.type
= T_TriggerData
;
2566 LocTriggerData
.tg_event
=
2567 event
->ate_event
& (TRIGGER_EVENT_OPMASK
| TRIGGER_EVENT_ROW
);
2568 LocTriggerData
.tg_relation
= rel
;
2570 MemoryContextReset(per_tuple_context
);
2573 * Call the trigger and throw away any possibly returned updated tuple.
2574 * (Don't let ExecCallTriggerFunc measure EXPLAIN time.)
2576 rettuple
= ExecCallTriggerFunc(&LocTriggerData
,
2581 if (rettuple
!= NULL
&& rettuple
!= &oldtuple
&& rettuple
!= &newtuple
)
2582 heap_freetuple(rettuple
);
2587 if (oldbuffer
!= InvalidBuffer
)
2588 ReleaseBuffer(oldbuffer
);
2589 if (newbuffer
!= InvalidBuffer
)
2590 ReleaseBuffer(newbuffer
);
2593 * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
2594 * one "tuple returned" (really the number of firings).
2597 InstrStopNode(instr
+ tgindx
, 1);
2602 * afterTriggerMarkEvents()
2604 * Scan the given event list for not yet invoked events. Mark the ones
2605 * that can be invoked now with the current firing ID.
2607 * If move_list isn't NULL, events that are not to be invoked now are
2608 * removed from the given list and appended to move_list.
2610 * When immediate_only is TRUE, do not invoke currently-deferred triggers.
2611 * (This will be FALSE only at main transaction exit.)
2613 * Returns TRUE if any invokable events were found.
2616 afterTriggerMarkEvents(AfterTriggerEventList
*events
,
2617 AfterTriggerEventList
*move_list
,
2618 bool immediate_only
)
2621 AfterTriggerEvent event
,
2625 event
= events
->head
;
2627 while (event
!= NULL
)
2629 bool defer_it
= false;
2630 AfterTriggerEvent next_event
;
2632 if (!(event
->ate_event
&
2633 (AFTER_TRIGGER_DONE
| AFTER_TRIGGER_IN_PROGRESS
)))
2636 * This trigger hasn't been called or scheduled yet. Check if we
2637 * should call it now.
2639 if (immediate_only
&&
2640 afterTriggerCheckState(event
->ate_tgoid
, event
->ate_event
))
2647 * Mark it as to be fired in this firing cycle.
2649 event
->ate_firing_id
= afterTriggers
->firing_counter
;
2650 event
->ate_event
|= AFTER_TRIGGER_IN_PROGRESS
;
2656 * If it's deferred, move it to move_list, if requested.
2658 next_event
= event
->ate_next
;
2660 if (defer_it
&& move_list
!= NULL
)
2662 /* Delink it from input list */
2664 prev_event
->ate_next
= next_event
;
2666 events
->head
= next_event
;
2667 /* and add it to move_list */
2668 event
->ate_next
= NULL
;
2669 if (move_list
->tail
== NULL
)
2671 /* first list entry */
2672 move_list
->head
= event
;
2673 move_list
->tail
= event
;
2677 move_list
->tail
->ate_next
= event
;
2678 move_list
->tail
= event
;
2683 /* Keep it in input list */
2690 /* Update list tail pointer in case we moved tail event */
2691 events
->tail
= prev_event
;
2697 * afterTriggerInvokeEvents()
2699 * Scan the given event list for events that are marked as to be fired
2700 * in the current firing cycle, and fire them.
2702 * If estate isn't NULL, we use its result relation info to avoid repeated
2703 * openings and closing of trigger target relations. If it is NULL, we
2704 * make one locally to cache the info in case there are multiple trigger
2707 * When delete_ok is TRUE, it's okay to delete fully-processed events.
2708 * The events list pointers are updated.
2712 afterTriggerInvokeEvents(AfterTriggerEventList
*events
,
2713 CommandId firing_id
,
2717 AfterTriggerEvent event
,
2719 MemoryContext per_tuple_context
;
2720 bool local_estate
= false;
2721 Relation rel
= NULL
;
2722 TriggerDesc
*trigdesc
= NULL
;
2723 FmgrInfo
*finfo
= NULL
;
2724 Instrumentation
*instr
= NULL
;
2726 /* Make a local EState if need be */
2729 estate
= CreateExecutorState();
2730 local_estate
= true;
2733 /* Make a per-tuple memory context for trigger function calls */
2735 AllocSetContextCreate(CurrentMemoryContext
,
2736 "AfterTriggerTupleContext",
2737 ALLOCSET_DEFAULT_MINSIZE
,
2738 ALLOCSET_DEFAULT_INITSIZE
,
2739 ALLOCSET_DEFAULT_MAXSIZE
);
2742 event
= events
->head
;
2744 while (event
!= NULL
)
2746 AfterTriggerEvent next_event
;
2749 * Is it one for me to fire?
2751 if ((event
->ate_event
& AFTER_TRIGGER_IN_PROGRESS
) &&
2752 event
->ate_firing_id
== firing_id
)
2755 * So let's fire it... but first, find the correct relation if
2756 * this is not the same relation as before.
2758 if (rel
== NULL
|| RelationGetRelid(rel
) != event
->ate_relid
)
2760 ResultRelInfo
*rInfo
;
2762 rInfo
= ExecGetTriggerResultRel(estate
, event
->ate_relid
);
2763 rel
= rInfo
->ri_RelationDesc
;
2764 trigdesc
= rInfo
->ri_TrigDesc
;
2765 finfo
= rInfo
->ri_TrigFunctions
;
2766 instr
= rInfo
->ri_TrigInstrument
;
2767 if (trigdesc
== NULL
) /* should not happen */
2768 elog(ERROR
, "relation %u has no triggers",
2773 * Fire it. Note that the AFTER_TRIGGER_IN_PROGRESS flag is still
2774 * set, so recursive examinations of the event list won't try to
2777 AfterTriggerExecute(event
, rel
, trigdesc
, finfo
, instr
,
2781 * Mark the event as done.
2783 event
->ate_event
&= ~AFTER_TRIGGER_IN_PROGRESS
;
2784 event
->ate_event
|= AFTER_TRIGGER_DONE
;
2788 * If it's now done, throw it away, if allowed.
2790 * NB: it's possible the trigger call above added more events to the
2791 * queue, or that calls we will do later will want to add more, so we
2792 * have to be careful about maintaining list validity at all points
2795 next_event
= event
->ate_next
;
2797 if ((event
->ate_event
& AFTER_TRIGGER_DONE
) && delete_ok
)
2799 /* Delink it from list and free it */
2801 prev_event
->ate_next
= next_event
;
2803 events
->head
= next_event
;
2808 /* Keep it in list */
2815 /* Update list tail pointer in case we just deleted tail event */
2816 events
->tail
= prev_event
;
2818 /* Release working resources */
2819 MemoryContextDelete(per_tuple_context
);
2825 foreach(l
, estate
->es_trig_target_relations
)
2827 ResultRelInfo
*resultRelInfo
= (ResultRelInfo
*) lfirst(l
);
2829 /* Close indices and then the relation itself */
2830 ExecCloseIndices(resultRelInfo
);
2831 heap_close(resultRelInfo
->ri_RelationDesc
, NoLock
);
2833 FreeExecutorState(estate
);
2839 * AfterTriggerBeginXact()
2841 * Called at transaction start (either BEGIN or implicit for single
2842 * statement outside of transaction block).
2846 AfterTriggerBeginXact(void)
2848 Assert(afterTriggers
== NULL
);
2851 * Build empty after-trigger state structure
2853 afterTriggers
= (AfterTriggers
)
2854 MemoryContextAlloc(TopTransactionContext
,
2855 sizeof(AfterTriggersData
));
2857 afterTriggers
->firing_counter
= FirstCommandId
;
2858 afterTriggers
->state
= SetConstraintStateCreate(8);
2859 afterTriggers
->events
.head
= NULL
;
2860 afterTriggers
->events
.tail
= NULL
;
2861 afterTriggers
->query_depth
= -1;
2863 /* We initialize the query stack to a reasonable size */
2864 afterTriggers
->query_stack
= (AfterTriggerEventList
*)
2865 MemoryContextAlloc(TopTransactionContext
,
2866 8 * sizeof(AfterTriggerEventList
));
2867 afterTriggers
->maxquerydepth
= 8;
2869 /* Context for events is created only when needed */
2870 afterTriggers
->event_cxt
= NULL
;
2872 /* Subtransaction stack is empty until/unless needed */
2873 afterTriggers
->cxt_stack
= NULL
;
2874 afterTriggers
->state_stack
= NULL
;
2875 afterTriggers
->events_stack
= NULL
;
2876 afterTriggers
->depth_stack
= NULL
;
2877 afterTriggers
->firing_stack
= NULL
;
2878 afterTriggers
->maxtransdepth
= 0;
2883 * AfterTriggerBeginQuery()
2885 * Called just before we start processing a single query within a
2886 * transaction (or subtransaction). Set up to record AFTER trigger
2887 * events queued by the query. Note that it is allowed to have
2888 * nested queries within a (sub)transaction.
2892 AfterTriggerBeginQuery(void)
2894 /* Must be inside a transaction */
2895 Assert(afterTriggers
!= NULL
);
2897 /* Increase the query stack depth */
2898 afterTriggers
->query_depth
++;
2901 * Allocate more space in the query stack if needed.
2903 if (afterTriggers
->query_depth
>= afterTriggers
->maxquerydepth
)
2905 /* repalloc will keep the stack in the same context */
2906 int new_alloc
= afterTriggers
->maxquerydepth
* 2;
2908 afterTriggers
->query_stack
= (AfterTriggerEventList
*)
2909 repalloc(afterTriggers
->query_stack
,
2910 new_alloc
* sizeof(AfterTriggerEventList
));
2911 afterTriggers
->maxquerydepth
= new_alloc
;
2914 /* Initialize this query's list to empty */
2915 afterTriggers
->query_stack
[afterTriggers
->query_depth
].head
= NULL
;
2916 afterTriggers
->query_stack
[afterTriggers
->query_depth
].tail
= NULL
;
2921 * AfterTriggerEndQuery()
2923 * Called after one query has been completely processed. At this time
2924 * we invoke all AFTER IMMEDIATE trigger events queued by the query, and
2925 * transfer deferred trigger events to the global deferred-trigger list.
2927 * Note that this should be called just BEFORE closing down the executor
2928 * with ExecutorEnd, because we make use of the EState's info about
2933 AfterTriggerEndQuery(EState
*estate
)
2935 AfterTriggerEventList
*events
;
2937 /* Must be inside a transaction */
2938 Assert(afterTriggers
!= NULL
);
2940 /* Must be inside a query, too */
2941 Assert(afterTriggers
->query_depth
>= 0);
2944 * Process all immediate-mode triggers queued by the query, and move the
2945 * deferred ones to the main list of deferred events.
2947 * Notice that we decide which ones will be fired, and put the deferred
2948 * ones on the main list, before anything is actually fired. This ensures
2949 * reasonably sane behavior if a trigger function does SET CONSTRAINTS ...
2950 * IMMEDIATE: all events we have decided to defer will be available for it
2953 * We loop in case a trigger queues more events.
2955 * If we find no firable events, we don't have to increment
2958 events
= &afterTriggers
->query_stack
[afterTriggers
->query_depth
];
2959 while (afterTriggerMarkEvents(events
, &afterTriggers
->events
, true))
2961 CommandId firing_id
= afterTriggers
->firing_counter
++;
2963 /* OK to delete the immediate events after processing them */
2964 afterTriggerInvokeEvents(events
, firing_id
, estate
, true);
2967 afterTriggers
->query_depth
--;
2972 * AfterTriggerFireDeferred()
2974 * Called just before the current transaction is committed. At this
2975 * time we invoke all pending DEFERRED triggers.
2977 * It is possible for other modules to queue additional deferred triggers
2978 * during pre-commit processing; therefore xact.c may have to call this
2983 AfterTriggerFireDeferred(void)
2985 AfterTriggerEventList
*events
;
2986 bool snap_pushed
= false;
2988 /* Must be inside a transaction */
2989 Assert(afterTriggers
!= NULL
);
2991 /* ... but not inside a query */
2992 Assert(afterTriggers
->query_depth
== -1);
2995 * If there are any triggers to fire, make sure we have set a snapshot for
2996 * them to use. (Since PortalRunUtility doesn't set a snap for COMMIT, we
2997 * can't assume ActiveSnapshot is valid on entry.)
2999 events
= &afterTriggers
->events
;
3000 if (events
->head
!= NULL
)
3002 PushActiveSnapshot(GetTransactionSnapshot());
3007 * Run all the remaining triggers. Loop until they are all gone, in case
3008 * some trigger queues more for us to do.
3010 while (afterTriggerMarkEvents(events
, NULL
, false))
3012 CommandId firing_id
= afterTriggers
->firing_counter
++;
3014 afterTriggerInvokeEvents(events
, firing_id
, NULL
, true);
3018 PopActiveSnapshot();
3020 Assert(events
->head
== NULL
);
3025 * AfterTriggerEndXact()
3027 * The current transaction is finishing.
3029 * Any unfired triggers are canceled so we simply throw
3030 * away anything we know.
3032 * Note: it is possible for this to be called repeatedly in case of
3033 * error during transaction abort; therefore, do not complain if
3034 * already closed down.
3038 AfterTriggerEndXact(bool isCommit
)
3041 * Forget everything we know about AFTER triggers.
3043 * Since all the info is in TopTransactionContext or children thereof, we
3044 * don't really need to do anything to reclaim memory. However, the
3045 * pending-events list could be large, and so it's useful to discard it as
3046 * soon as possible --- especially if we are aborting because we ran out
3047 * of memory for the list!
3049 * (Note: any event_cxts of child subtransactions could also be deleted
3050 * here, but we have no convenient way to find them, so we leave it to
3051 * TopTransactionContext reset to clean them up.)
3053 if (afterTriggers
&& afterTriggers
->event_cxt
)
3054 MemoryContextDelete(afterTriggers
->event_cxt
);
3056 afterTriggers
= NULL
;
3060 * AfterTriggerBeginSubXact()
3062 * Start a subtransaction.
3065 AfterTriggerBeginSubXact(void)
3067 int my_level
= GetCurrentTransactionNestLevel();
3070 * Ignore call if the transaction is in aborted state. (Probably
3071 * shouldn't happen?)
3073 if (afterTriggers
== NULL
)
3077 * Allocate more space in the stacks if needed. (Note: because the
3078 * minimum nest level of a subtransaction is 2, we waste the first couple
3079 * entries of each array; not worth the notational effort to avoid it.)
3081 while (my_level
>= afterTriggers
->maxtransdepth
)
3083 if (afterTriggers
->maxtransdepth
== 0)
3085 MemoryContext old_cxt
;
3087 old_cxt
= MemoryContextSwitchTo(TopTransactionContext
);
3089 #define DEFTRIG_INITALLOC 8
3090 afterTriggers
->cxt_stack
= (MemoryContext
*)
3091 palloc(DEFTRIG_INITALLOC
* sizeof(MemoryContext
));
3092 afterTriggers
->state_stack
= (SetConstraintState
*)
3093 palloc(DEFTRIG_INITALLOC
* sizeof(SetConstraintState
));
3094 afterTriggers
->events_stack
= (AfterTriggerEventList
*)
3095 palloc(DEFTRIG_INITALLOC
* sizeof(AfterTriggerEventList
));
3096 afterTriggers
->depth_stack
= (int *)
3097 palloc(DEFTRIG_INITALLOC
* sizeof(int));
3098 afterTriggers
->firing_stack
= (CommandId
*)
3099 palloc(DEFTRIG_INITALLOC
* sizeof(CommandId
));
3100 afterTriggers
->maxtransdepth
= DEFTRIG_INITALLOC
;
3102 MemoryContextSwitchTo(old_cxt
);
3106 /* repalloc will keep the stacks in the same context */
3107 int new_alloc
= afterTriggers
->maxtransdepth
* 2;
3109 afterTriggers
->cxt_stack
= (MemoryContext
*)
3110 repalloc(afterTriggers
->cxt_stack
,
3111 new_alloc
* sizeof(MemoryContext
));
3112 afterTriggers
->state_stack
= (SetConstraintState
*)
3113 repalloc(afterTriggers
->state_stack
,
3114 new_alloc
* sizeof(SetConstraintState
));
3115 afterTriggers
->events_stack
= (AfterTriggerEventList
*)
3116 repalloc(afterTriggers
->events_stack
,
3117 new_alloc
* sizeof(AfterTriggerEventList
));
3118 afterTriggers
->depth_stack
= (int *)
3119 repalloc(afterTriggers
->depth_stack
,
3120 new_alloc
* sizeof(int));
3121 afterTriggers
->firing_stack
= (CommandId
*)
3122 repalloc(afterTriggers
->firing_stack
,
3123 new_alloc
* sizeof(CommandId
));
3124 afterTriggers
->maxtransdepth
= new_alloc
;
3129 * Push the current information into the stack. The SET CONSTRAINTS state
3130 * is not saved until/unless changed. Likewise, we don't make a
3131 * per-subtransaction event context until needed.
3133 afterTriggers
->cxt_stack
[my_level
] = NULL
;
3134 afterTriggers
->state_stack
[my_level
] = NULL
;
3135 afterTriggers
->events_stack
[my_level
] = afterTriggers
->events
;
3136 afterTriggers
->depth_stack
[my_level
] = afterTriggers
->query_depth
;
3137 afterTriggers
->firing_stack
[my_level
] = afterTriggers
->firing_counter
;
3141 * AfterTriggerEndSubXact()
3143 * The current subtransaction is ending.
3146 AfterTriggerEndSubXact(bool isCommit
)
3148 int my_level
= GetCurrentTransactionNestLevel();
3149 SetConstraintState state
;
3150 AfterTriggerEvent event
;
3151 CommandId subxact_firing_id
;
3154 * Ignore call if the transaction is in aborted state. (Probably
3157 if (afterTriggers
== NULL
)
3161 * Pop the prior state if needed.
3163 Assert(my_level
< afterTriggers
->maxtransdepth
);
3167 /* If we saved a prior state, we don't need it anymore */
3168 state
= afterTriggers
->state_stack
[my_level
];
3171 /* this avoids double pfree if error later: */
3172 afterTriggers
->state_stack
[my_level
] = NULL
;
3173 Assert(afterTriggers
->query_depth
==
3174 afterTriggers
->depth_stack
[my_level
]);
3177 * It's entirely possible that the subxact created an event_cxt but
3178 * there is not anything left in it (because all the triggers were
3179 * fired at end-of-statement). If so, we should release the context
3180 * to prevent memory leakage in a long sequence of subtransactions. We
3181 * can detect whether there's anything of use in the context by seeing
3182 * if anything was added to the global events list since subxact
3183 * start. (This test doesn't catch every case where the context is
3184 * deletable; for instance maybe the only additions were from a
3185 * sub-sub-xact. But it handles the common case.)
3187 if (afterTriggers
->cxt_stack
[my_level
] &&
3188 afterTriggers
->events
.tail
== afterTriggers
->events_stack
[my_level
].tail
)
3190 MemoryContextDelete(afterTriggers
->cxt_stack
[my_level
]);
3191 /* avoid double delete if abort later */
3192 afterTriggers
->cxt_stack
[my_level
] = NULL
;
3198 * Aborting. We don't really need to release the subxact's event_cxt,
3199 * since it will go away anyway when CurTransactionContext gets reset,
3200 * but doing so early in subxact abort helps free space we might need.
3202 * (Note: any event_cxts of child subtransactions could also be
3203 * deleted here, but we have no convenient way to find them, so we
3204 * leave it to CurTransactionContext reset to clean them up.)
3206 if (afterTriggers
->cxt_stack
[my_level
])
3208 MemoryContextDelete(afterTriggers
->cxt_stack
[my_level
]);
3209 /* avoid double delete if repeated aborts */
3210 afterTriggers
->cxt_stack
[my_level
] = NULL
;
3214 * Restore the pointers from the stacks.
3216 afterTriggers
->events
= afterTriggers
->events_stack
[my_level
];
3217 afterTriggers
->query_depth
= afterTriggers
->depth_stack
[my_level
];
3220 * Cleanup the tail of the list.
3222 if (afterTriggers
->events
.tail
!= NULL
)
3223 afterTriggers
->events
.tail
->ate_next
= NULL
;
3226 * Restore the trigger state. If the saved state is NULL, then this
3227 * subxact didn't save it, so it doesn't need restoring.
3229 state
= afterTriggers
->state_stack
[my_level
];
3232 pfree(afterTriggers
->state
);
3233 afterTriggers
->state
= state
;
3235 /* this avoids double pfree if error later: */
3236 afterTriggers
->state_stack
[my_level
] = NULL
;
3239 * Scan for any remaining deferred events that were marked DONE or IN
3240 * PROGRESS by this subxact or a child, and un-mark them. We can
3241 * recognize such events because they have a firing ID greater than or
3242 * equal to the firing_counter value we saved at subtransaction start.
3243 * (This essentially assumes that the current subxact includes all
3244 * subxacts started after it.)
3246 subxact_firing_id
= afterTriggers
->firing_stack
[my_level
];
3247 for (event
= afterTriggers
->events
.head
;
3249 event
= event
->ate_next
)
3251 if (event
->ate_event
&
3252 (AFTER_TRIGGER_DONE
| AFTER_TRIGGER_IN_PROGRESS
))
3254 if (event
->ate_firing_id
>= subxact_firing_id
)
3256 ~(AFTER_TRIGGER_DONE
| AFTER_TRIGGER_IN_PROGRESS
);
3263 * Create an empty SetConstraintState with room for numalloc trigstates
3265 static SetConstraintState
3266 SetConstraintStateCreate(int numalloc
)
3268 SetConstraintState state
;
3270 /* Behave sanely with numalloc == 0 */
3275 * We assume that zeroing will correctly initialize the state values.
3277 state
= (SetConstraintState
)
3278 MemoryContextAllocZero(TopTransactionContext
,
3279 sizeof(SetConstraintStateData
) +
3280 (numalloc
- 1) *sizeof(SetConstraintTriggerData
));
3282 state
->numalloc
= numalloc
;
3288 * Copy a SetConstraintState
3290 static SetConstraintState
3291 SetConstraintStateCopy(SetConstraintState origstate
)
3293 SetConstraintState state
;
3295 state
= SetConstraintStateCreate(origstate
->numstates
);
3297 state
->all_isset
= origstate
->all_isset
;
3298 state
->all_isdeferred
= origstate
->all_isdeferred
;
3299 state
->numstates
= origstate
->numstates
;
3300 memcpy(state
->trigstates
, origstate
->trigstates
,
3301 origstate
->numstates
* sizeof(SetConstraintTriggerData
));
3307 * Add a per-trigger item to a SetConstraintState. Returns possibly-changed
3308 * pointer to the state object (it will change if we have to repalloc).
3310 static SetConstraintState
3311 SetConstraintStateAddItem(SetConstraintState state
,
3312 Oid tgoid
, bool tgisdeferred
)
3314 if (state
->numstates
>= state
->numalloc
)
3316 int newalloc
= state
->numalloc
* 2;
3318 newalloc
= Max(newalloc
, 8); /* in case original has size 0 */
3319 state
= (SetConstraintState
)
3321 sizeof(SetConstraintStateData
) +
3322 (newalloc
- 1) *sizeof(SetConstraintTriggerData
));
3323 state
->numalloc
= newalloc
;
3324 Assert(state
->numstates
< state
->numalloc
);
3327 state
->trigstates
[state
->numstates
].sct_tgoid
= tgoid
;
3328 state
->trigstates
[state
->numstates
].sct_tgisdeferred
= tgisdeferred
;
3335 * AfterTriggerSetState()
3337 * Execute the SET CONSTRAINTS ... utility command.
3341 AfterTriggerSetState(ConstraintsSetStmt
*stmt
)
3343 int my_level
= GetCurrentTransactionNestLevel();
3346 * Ignore call if we aren't in a transaction. (Shouldn't happen?)
3348 if (afterTriggers
== NULL
)
3352 * If in a subtransaction, and we didn't save the current state already,
3353 * save it so it can be restored if the subtransaction aborts.
3356 afterTriggers
->state_stack
[my_level
] == NULL
)
3358 afterTriggers
->state_stack
[my_level
] =
3359 SetConstraintStateCopy(afterTriggers
->state
);
3363 * Handle SET CONSTRAINTS ALL ...
3365 if (stmt
->constraints
== NIL
)
3368 * Forget any previous SET CONSTRAINTS commands in this transaction.
3370 afterTriggers
->state
->numstates
= 0;
3373 * Set the per-transaction ALL state to known.
3375 afterTriggers
->state
->all_isset
= true;
3376 afterTriggers
->state
->all_isdeferred
= stmt
->deferred
;
3382 List
*oidlist
= NIL
;
3385 * Handle SET CONSTRAINTS constraint-name [, ...]
3386 * First lookup all trigger Oid's for the constraint names.
3389 tgrel
= heap_open(TriggerRelationId
, AccessShareLock
);
3391 foreach(l
, stmt
->constraints
)
3393 RangeVar
*constraint
= lfirst(l
);
3398 List
*namespaceSearchList
;
3399 ListCell
*namespaceSearchCell
;
3401 if (constraint
->catalogname
)
3403 if (strcmp(constraint
->catalogname
, get_database_name(MyDatabaseId
)) != 0)
3405 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
3406 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
3407 constraint
->catalogname
, constraint
->schemaname
,
3408 constraint
->relname
)));
3412 * If we're given the schema name with the constraint, look only
3413 * in that schema. If given a bare constraint name, use the
3414 * search path to find the first matching constraint.
3416 if (constraint
->schemaname
)
3418 Oid namespaceId
= LookupExplicitNamespace(constraint
->schemaname
);
3420 namespaceSearchList
= list_make1_oid(namespaceId
);
3424 namespaceSearchList
= fetch_search_path(true);
3428 foreach(namespaceSearchCell
, namespaceSearchList
)
3430 Oid searchNamespaceId
= lfirst_oid(namespaceSearchCell
);
3433 * Setup to scan pg_trigger by tgconstrname ...
3436 Anum_pg_trigger_tgconstrname
,
3437 BTEqualStrategyNumber
, F_NAMEEQ
,
3438 PointerGetDatum(constraint
->relname
));
3440 tgscan
= systable_beginscan(tgrel
, TriggerConstrNameIndexId
, true,
3441 SnapshotNow
, 1, &skey
);
3444 * ... and search for the constraint trigger row
3446 while (HeapTupleIsValid(htup
= systable_getnext(tgscan
)))
3448 Form_pg_trigger pg_trigger
= (Form_pg_trigger
) GETSTRUCT(htup
);
3449 Oid constraintNamespaceId
;
3452 * Foreign key constraints have triggers on both the
3453 * parent and child tables. Since these tables may be in
3454 * different schemas we must pick the child table because
3455 * that table "owns" the constraint.
3457 * Referential triggers on the parent table other than
3458 * NOACTION_DEL and NOACTION_UPD are ignored below, so it
3459 * is possible to not check them here, but it seems safer
3462 if (pg_trigger
->tgfoid
== F_RI_FKEY_NOACTION_DEL
||
3463 pg_trigger
->tgfoid
== F_RI_FKEY_NOACTION_UPD
||
3464 pg_trigger
->tgfoid
== F_RI_FKEY_RESTRICT_UPD
||
3465 pg_trigger
->tgfoid
== F_RI_FKEY_RESTRICT_DEL
||
3466 pg_trigger
->tgfoid
== F_RI_FKEY_CASCADE_UPD
||
3467 pg_trigger
->tgfoid
== F_RI_FKEY_CASCADE_DEL
||
3468 pg_trigger
->tgfoid
== F_RI_FKEY_SETNULL_UPD
||
3469 pg_trigger
->tgfoid
== F_RI_FKEY_SETNULL_DEL
||
3470 pg_trigger
->tgfoid
== F_RI_FKEY_SETDEFAULT_UPD
||
3471 pg_trigger
->tgfoid
== F_RI_FKEY_SETDEFAULT_DEL
)
3472 constraintNamespaceId
= get_rel_namespace(pg_trigger
->tgconstrrelid
);
3474 constraintNamespaceId
= get_rel_namespace(pg_trigger
->tgrelid
);
3477 * If this constraint is not in the schema we're currently
3478 * searching for, keep looking.
3480 if (constraintNamespaceId
!= searchNamespaceId
)
3484 * If we found some, check that they fit the deferrability
3485 * but skip referential action ones, since they are
3486 * silently never deferrable.
3488 if (pg_trigger
->tgfoid
!= F_RI_FKEY_RESTRICT_UPD
&&
3489 pg_trigger
->tgfoid
!= F_RI_FKEY_RESTRICT_DEL
&&
3490 pg_trigger
->tgfoid
!= F_RI_FKEY_CASCADE_UPD
&&
3491 pg_trigger
->tgfoid
!= F_RI_FKEY_CASCADE_DEL
&&
3492 pg_trigger
->tgfoid
!= F_RI_FKEY_SETNULL_UPD
&&
3493 pg_trigger
->tgfoid
!= F_RI_FKEY_SETNULL_DEL
&&
3494 pg_trigger
->tgfoid
!= F_RI_FKEY_SETDEFAULT_UPD
&&
3495 pg_trigger
->tgfoid
!= F_RI_FKEY_SETDEFAULT_DEL
)
3497 if (stmt
->deferred
&& !pg_trigger
->tgdeferrable
)
3499 (errcode(ERRCODE_WRONG_OBJECT_TYPE
),
3500 errmsg("constraint \"%s\" is not deferrable",
3501 constraint
->relname
)));
3502 oidlist
= lappend_oid(oidlist
, HeapTupleGetOid(htup
));
3507 systable_endscan(tgscan
);
3510 * Once we've found a matching constraint we do not search
3511 * later parts of the search path.
3518 list_free(namespaceSearchList
);
3525 (errcode(ERRCODE_UNDEFINED_OBJECT
),
3526 errmsg("constraint \"%s\" does not exist",
3527 constraint
->relname
)));
3529 heap_close(tgrel
, AccessShareLock
);
3532 * Set the trigger states of individual triggers for this xact.
3536 Oid tgoid
= lfirst_oid(l
);
3537 SetConstraintState state
= afterTriggers
->state
;
3541 for (i
= 0; i
< state
->numstates
; i
++)
3543 if (state
->trigstates
[i
].sct_tgoid
== tgoid
)
3545 state
->trigstates
[i
].sct_tgisdeferred
= stmt
->deferred
;
3552 afterTriggers
->state
=
3553 SetConstraintStateAddItem(state
, tgoid
, stmt
->deferred
);
3559 * SQL99 requires that when a constraint is set to IMMEDIATE, any deferred
3560 * checks against that constraint must be made when the SET CONSTRAINTS
3561 * command is executed -- i.e. the effects of the SET CONSTRAINTS command
3562 * apply retroactively. We've updated the constraints state, so scan the
3563 * list of previously deferred events to fire any that have now become
3566 * Obviously, if this was SET ... DEFERRED then it can't have converted
3567 * any unfired events to immediate, so we need do nothing in that case.
3569 if (!stmt
->deferred
)
3571 AfterTriggerEventList
*events
= &afterTriggers
->events
;
3573 while (afterTriggerMarkEvents(events
, NULL
, true))
3575 CommandId firing_id
= afterTriggers
->firing_counter
++;
3578 * We can delete fired events if we are at top transaction level,
3579 * but we'd better not if inside a subtransaction, since the
3580 * subtransaction could later get rolled back.
3582 afterTriggerInvokeEvents(events
, firing_id
, NULL
,
3583 !IsSubTransaction());
3589 * AfterTriggerPendingOnRel()
3590 * Test to see if there are any pending after-trigger events for rel.
3592 * This is used by TRUNCATE, CLUSTER, ALTER TABLE, etc to detect whether
3593 * it is unsafe to perform major surgery on a relation. Note that only
3594 * local pending events are examined. We assume that having exclusive lock
3595 * on a rel guarantees there are no unserviced events in other backends ---
3596 * but having a lock does not prevent there being such events in our own.
3598 * In some scenarios it'd be reasonable to remove pending events (more
3599 * specifically, mark them DONE by the current subxact) but without a lot
3600 * of knowledge of the trigger semantics we can't do this in general.
3604 AfterTriggerPendingOnRel(Oid relid
)
3606 AfterTriggerEvent event
;
3609 /* No-op if we aren't in a transaction. (Shouldn't happen?) */
3610 if (afterTriggers
== NULL
)
3613 /* Scan queued events */
3614 for (event
= afterTriggers
->events
.head
;
3616 event
= event
->ate_next
)
3619 * We can ignore completed events. (Even if a DONE flag is rolled
3620 * back by subxact abort, it's OK because the effects of the TRUNCATE
3621 * or whatever must get rolled back too.)
3623 if (event
->ate_event
& AFTER_TRIGGER_DONE
)
3626 if (event
->ate_relid
== relid
)
3631 * Also scan events queued by incomplete queries. This could only matter
3632 * if TRUNCATE/etc is executed by a function or trigger within an updating
3633 * query on the same relation, which is pretty perverse, but let's check.
3635 for (depth
= 0; depth
<= afterTriggers
->query_depth
; depth
++)
3637 for (event
= afterTriggers
->query_stack
[depth
].head
;
3639 event
= event
->ate_next
)
3641 if (event
->ate_event
& AFTER_TRIGGER_DONE
)
3644 if (event
->ate_relid
== relid
)
3654 * AfterTriggerSaveEvent()
3656 * Called by ExecA[RS]...Triggers() to add the event to the queue.
3658 * NOTE: should be called only if we've determined that an event must
3659 * be added to the queue.
3663 AfterTriggerSaveEvent(ResultRelInfo
*relinfo
, int event
, bool row_trigger
,
3664 HeapTuple oldtup
, HeapTuple newtup
)
3666 Relation rel
= relinfo
->ri_RelationDesc
;
3667 TriggerDesc
*trigdesc
= relinfo
->ri_TrigDesc
;
3668 int my_level
= GetCurrentTransactionNestLevel();
3669 MemoryContext
*cxtptr
;
3670 AfterTriggerEvent new_event
;
3674 ItemPointerData oldctid
;
3675 ItemPointerData newctid
;
3677 if (afterTriggers
== NULL
)
3678 elog(ERROR
, "AfterTriggerSaveEvent() called outside of transaction");
3681 * event is used both as a bitmask and an array offset,
3682 * so make sure we don't walk off the edge of our arrays
3684 Assert(event
>= 0 && event
< TRIGGER_NUM_EVENT_CLASSES
);
3687 * Get the CTID's of OLD and NEW
3690 ItemPointerCopy(&(oldtup
->t_self
), &(oldctid
));
3692 ItemPointerSetInvalid(&(oldctid
));
3694 ItemPointerCopy(&(newtup
->t_self
), &(newctid
));
3696 ItemPointerSetInvalid(&(newctid
));
3699 * Scan the appropriate set of triggers
3703 ntriggers
= trigdesc
->n_after_row
[event
];
3704 tgindx
= trigdesc
->tg_after_row
[event
];
3708 ntriggers
= trigdesc
->n_after_statement
[event
];
3709 tgindx
= trigdesc
->tg_after_statement
[event
];
3712 for (i
= 0; i
< ntriggers
; i
++)
3714 Trigger
*trigger
= &trigdesc
->triggers
[tgindx
[i
]];
3716 /* Ignore disabled triggers */
3717 if (SessionReplicationRole
== SESSION_REPLICATION_ROLE_REPLICA
)
3719 if (trigger
->tgenabled
== TRIGGER_FIRES_ON_ORIGIN
||
3720 trigger
->tgenabled
== TRIGGER_DISABLED
)
3723 else /* ORIGIN or LOCAL role */
3725 if (trigger
->tgenabled
== TRIGGER_FIRES_ON_REPLICA
||
3726 trigger
->tgenabled
== TRIGGER_DISABLED
)
3731 * If this is an UPDATE of a PK table or FK table that does not change
3732 * the PK or FK respectively, we can skip queuing the event: there is
3733 * no need to fire the trigger.
3735 if ((event
& TRIGGER_EVENT_OPMASK
) == TRIGGER_EVENT_UPDATE
)
3737 switch (RI_FKey_trigger_type(trigger
->tgfoid
))
3740 /* Update on PK table */
3741 if (RI_FKey_keyequal_upd_pk(trigger
, rel
, oldtup
, newtup
))
3743 /* key unchanged, so skip queuing this event */
3751 * Update on FK table
3753 * There is one exception when updating FK tables: if the
3754 * updated row was inserted by our own transaction and the
3755 * FK is deferred, we still need to fire the trigger. This
3756 * is because our UPDATE will invalidate the INSERT so the
3757 * end-of-transaction INSERT RI trigger will not do
3758 * anything, so we have to do the check for the UPDATE
3761 if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(oldtup
->t_data
)) &&
3762 RI_FKey_keyequal_upd_fk(trigger
, rel
, oldtup
, newtup
))
3768 case RI_TRIGGER_NONE
:
3769 /* Not an FK trigger */
3775 * If we don't yet have an event context for the current (sub)xact,
3776 * create one. Make it a child of CurTransactionContext to ensure it
3777 * will go away if the subtransaction aborts.
3779 if (my_level
> 1) /* subtransaction? */
3781 Assert(my_level
< afterTriggers
->maxtransdepth
);
3782 cxtptr
= &afterTriggers
->cxt_stack
[my_level
];
3785 cxtptr
= &afterTriggers
->event_cxt
;
3786 if (*cxtptr
== NULL
)
3787 *cxtptr
= AllocSetContextCreate(CurTransactionContext
,
3788 "AfterTriggerEvents",
3789 ALLOCSET_DEFAULT_MINSIZE
,
3790 ALLOCSET_DEFAULT_INITSIZE
,
3791 ALLOCSET_DEFAULT_MAXSIZE
);
3794 * Create a new event.
3796 new_event
= (AfterTriggerEvent
)
3797 MemoryContextAlloc(*cxtptr
, sizeof(AfterTriggerEventData
));
3798 new_event
->ate_next
= NULL
;
3799 new_event
->ate_event
=
3800 (event
& TRIGGER_EVENT_OPMASK
) |
3801 (row_trigger
? TRIGGER_EVENT_ROW
: 0) |
3802 (trigger
->tgdeferrable
? AFTER_TRIGGER_DEFERRABLE
: 0) |
3803 (trigger
->tginitdeferred
? AFTER_TRIGGER_INITDEFERRED
: 0);
3804 new_event
->ate_firing_id
= 0;
3805 new_event
->ate_tgoid
= trigger
->tgoid
;
3806 new_event
->ate_relid
= rel
->rd_id
;
3807 ItemPointerCopy(&oldctid
, &(new_event
->ate_oldctid
));
3808 ItemPointerCopy(&newctid
, &(new_event
->ate_newctid
));
3811 * Add the new event to the queue.
3813 afterTriggerAddEvent(new_event
);