1 /*-------------------------------------------------------------------------
4 * Declarations for trigger handling.
6 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
9 * src/include/commands/trigger.h
11 *-------------------------------------------------------------------------
16 #include "catalog/objectaddress.h"
17 #include "nodes/execnodes.h"
18 #include "nodes/parsenodes.h"
21 * TriggerData is the node type that is passed as fmgr "context" info
22 * when a function is called by the trigger manager.
25 #define CALLED_AS_TRIGGER(fcinfo) \
26 ((fcinfo)->context != NULL && IsA((fcinfo)->context, TriggerData))
28 typedef uint32 TriggerEvent
;
30 typedef struct TriggerData
33 TriggerEvent tg_event
;
35 HeapTuple tg_trigtuple
;
36 HeapTuple tg_newtuple
;
38 TupleTableSlot
*tg_trigslot
;
39 TupleTableSlot
*tg_newslot
;
40 Tuplestorestate
*tg_oldtable
;
41 Tuplestorestate
*tg_newtable
;
45 * The state for capturing old and new tuples into transition tables for a
46 * single ModifyTable node (or other operation source, e.g. copy.c).
48 * This is per-caller to avoid conflicts in setting tcs_map or
49 * tcs_original_insert_tuple. Note, however, that the pointed-to
50 * private data may be shared across multiple callers.
52 struct AfterTriggersTableData
; /* private in trigger.c */
54 typedef struct TransitionCaptureState
57 * Is there at least one trigger specifying each transition relation on
58 * the relation explicitly named in the DML statement or COPY command?
59 * Note: in current usage, these flags could be part of the private state,
60 * but it seems possibly useful to let callers see them.
62 bool tcs_delete_old_table
;
63 bool tcs_update_old_table
;
64 bool tcs_update_new_table
;
65 bool tcs_insert_new_table
;
68 * For UPDATE and DELETE, AfterTriggerSaveEvent may need to convert the
69 * new and old tuples from a child table's format to the format of the
70 * relation named in a query so that it is compatible with the transition
71 * tuplestores. The caller must store the conversion map here if so.
73 TupleConversionMap
*tcs_map
;
76 * For INSERT and COPY, it would be wasteful to convert tuples from child
77 * format to parent format after they have already been converted in the
78 * opposite direction during routing. In that case we bypass conversion
79 * and allow the inserting code (copy.c and nodeModifyTable.c) to provide
80 * a slot containing the original tuple directly.
82 TupleTableSlot
*tcs_original_insert_tuple
;
85 * Private data including the tuplestore(s) into which to insert tuples.
87 struct AfterTriggersTableData
*tcs_private
;
88 } TransitionCaptureState
;
91 * TriggerEvent bit flags
93 * Note that we assume different event types (INSERT/DELETE/UPDATE/TRUNCATE)
94 * can't be OR'd together in a single TriggerEvent. This is unlike the
95 * situation for pg_trigger rows, so pg_trigger.tgtype uses a different
98 #define TRIGGER_EVENT_INSERT 0x00000000
99 #define TRIGGER_EVENT_DELETE 0x00000001
100 #define TRIGGER_EVENT_UPDATE 0x00000002
101 #define TRIGGER_EVENT_TRUNCATE 0x00000003
102 #define TRIGGER_EVENT_OPMASK 0x00000003
104 #define TRIGGER_EVENT_ROW 0x00000004
106 #define TRIGGER_EVENT_BEFORE 0x00000008
107 #define TRIGGER_EVENT_AFTER 0x00000000
108 #define TRIGGER_EVENT_INSTEAD 0x00000010
109 #define TRIGGER_EVENT_TIMINGMASK 0x00000018
111 /* More TriggerEvent flags, used only within trigger.c */
113 #define AFTER_TRIGGER_DEFERRABLE 0x00000020
114 #define AFTER_TRIGGER_INITDEFERRED 0x00000040
116 #define TRIGGER_FIRED_BY_INSERT(event) \
117 (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_INSERT)
119 #define TRIGGER_FIRED_BY_DELETE(event) \
120 (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_DELETE)
122 #define TRIGGER_FIRED_BY_UPDATE(event) \
123 (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_UPDATE)
125 #define TRIGGER_FIRED_BY_TRUNCATE(event) \
126 (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_TRUNCATE)
128 #define TRIGGER_FIRED_FOR_ROW(event) \
129 ((event) & TRIGGER_EVENT_ROW)
131 #define TRIGGER_FIRED_FOR_STATEMENT(event) \
132 (!TRIGGER_FIRED_FOR_ROW(event))
134 #define TRIGGER_FIRED_BEFORE(event) \
135 (((event) & TRIGGER_EVENT_TIMINGMASK) == TRIGGER_EVENT_BEFORE)
137 #define TRIGGER_FIRED_AFTER(event) \
138 (((event) & TRIGGER_EVENT_TIMINGMASK) == TRIGGER_EVENT_AFTER)
140 #define TRIGGER_FIRED_INSTEAD(event) \
141 (((event) & TRIGGER_EVENT_TIMINGMASK) == TRIGGER_EVENT_INSTEAD)
144 * Definitions for replication role based firing.
146 #define SESSION_REPLICATION_ROLE_ORIGIN 0
147 #define SESSION_REPLICATION_ROLE_REPLICA 1
148 #define SESSION_REPLICATION_ROLE_LOCAL 2
149 extern PGDLLIMPORT
int SessionReplicationRole
;
152 * States at which a trigger can be fired. These are the
153 * possible values for pg_trigger.tgenabled.
155 #define TRIGGER_FIRES_ON_ORIGIN 'O'
156 #define TRIGGER_FIRES_ALWAYS 'A'
157 #define TRIGGER_FIRES_ON_REPLICA 'R'
158 #define TRIGGER_DISABLED 'D'
160 extern ObjectAddress
CreateTrigger(CreateTrigStmt
*stmt
, const char *queryString
,
161 Oid relOid
, Oid refRelOid
, Oid constraintOid
, Oid indexOid
,
162 Oid funcoid
, Oid parentTriggerOid
, Node
*whenClause
,
163 bool isInternal
, bool in_partition
);
164 extern ObjectAddress
CreateTriggerFiringOn(CreateTrigStmt
*stmt
, const char *queryString
,
165 Oid relOid
, Oid refRelOid
, Oid constraintOid
,
166 Oid indexOid
, Oid funcoid
, Oid parentTriggerOid
,
167 Node
*whenClause
, bool isInternal
, bool in_partition
,
168 char trigger_fires_when
);
170 extern void RemoveTriggerById(Oid trigOid
);
171 extern Oid
get_trigger_oid(Oid relid
, const char *name
, bool missing_ok
);
173 extern ObjectAddress
renametrig(RenameStmt
*stmt
);
175 extern void EnableDisableTriggerNew(Relation rel
, const char *tgname
,
176 char fires_when
, bool skip_system
, bool recurse
,
178 extern void EnableDisableTrigger(Relation rel
, const char *tgname
,
179 char fires_when
, bool skip_system
, LOCKMODE lockmode
);
181 extern void RelationBuildTriggers(Relation relation
);
183 extern TriggerDesc
*CopyTriggerDesc(TriggerDesc
*trigdesc
);
185 extern const char *FindTriggerIncompatibleWithInheritance(TriggerDesc
*trigdesc
);
187 extern TransitionCaptureState
*MakeTransitionCaptureState(TriggerDesc
*trigdesc
,
188 Oid relid
, CmdType cmdType
);
190 extern void FreeTriggerDesc(TriggerDesc
*trigdesc
);
192 extern void ExecBSInsertTriggers(EState
*estate
,
193 ResultRelInfo
*relinfo
);
194 extern void ExecASInsertTriggers(EState
*estate
,
195 ResultRelInfo
*relinfo
,
196 TransitionCaptureState
*transition_capture
);
197 extern bool ExecBRInsertTriggers(EState
*estate
,
198 ResultRelInfo
*relinfo
,
199 TupleTableSlot
*slot
);
200 extern void ExecARInsertTriggers(EState
*estate
,
201 ResultRelInfo
*relinfo
,
202 TupleTableSlot
*slot
,
203 List
*recheckIndexes
,
204 TransitionCaptureState
*transition_capture
);
205 extern bool ExecIRInsertTriggers(EState
*estate
,
206 ResultRelInfo
*relinfo
,
207 TupleTableSlot
*slot
);
208 extern void ExecBSDeleteTriggers(EState
*estate
,
209 ResultRelInfo
*relinfo
);
210 extern void ExecASDeleteTriggers(EState
*estate
,
211 ResultRelInfo
*relinfo
,
212 TransitionCaptureState
*transition_capture
);
213 extern bool ExecBRDeleteTriggers(EState
*estate
,
215 ResultRelInfo
*relinfo
,
217 HeapTuple fdw_trigtuple
,
218 TupleTableSlot
**epqslot
);
219 extern void ExecARDeleteTriggers(EState
*estate
,
220 ResultRelInfo
*relinfo
,
222 HeapTuple fdw_trigtuple
,
223 TransitionCaptureState
*transition_capture
);
224 extern bool ExecIRDeleteTriggers(EState
*estate
,
225 ResultRelInfo
*relinfo
,
226 HeapTuple trigtuple
);
227 extern void ExecBSUpdateTriggers(EState
*estate
,
228 ResultRelInfo
*relinfo
);
229 extern void ExecASUpdateTriggers(EState
*estate
,
230 ResultRelInfo
*relinfo
,
231 TransitionCaptureState
*transition_capture
);
232 extern bool ExecBRUpdateTriggers(EState
*estate
,
234 ResultRelInfo
*relinfo
,
236 HeapTuple fdw_trigtuple
,
237 TupleTableSlot
*slot
);
238 extern void ExecARUpdateTriggers(EState
*estate
,
239 ResultRelInfo
*relinfo
,
241 HeapTuple fdw_trigtuple
,
242 TupleTableSlot
*slot
,
243 List
*recheckIndexes
,
244 TransitionCaptureState
*transition_capture
);
245 extern bool ExecIRUpdateTriggers(EState
*estate
,
246 ResultRelInfo
*relinfo
,
248 TupleTableSlot
*slot
);
249 extern void ExecBSTruncateTriggers(EState
*estate
,
250 ResultRelInfo
*relinfo
);
251 extern void ExecASTruncateTriggers(EState
*estate
,
252 ResultRelInfo
*relinfo
);
254 extern void AfterTriggerBeginXact(void);
255 extern void AfterTriggerBeginQuery(void);
256 extern void AfterTriggerEndQuery(EState
*estate
);
257 extern void AfterTriggerFireDeferred(void);
258 extern void AfterTriggerEndXact(bool isCommit
);
259 extern void AfterTriggerBeginSubXact(void);
260 extern void AfterTriggerEndSubXact(bool isCommit
);
261 extern void AfterTriggerSetState(ConstraintsSetStmt
*stmt
);
262 extern bool AfterTriggerPendingOnRel(Oid relid
);
266 * in utils/adt/ri_triggers.c
268 extern bool RI_FKey_pk_upd_check_required(Trigger
*trigger
, Relation pk_rel
,
269 TupleTableSlot
*old_slot
, TupleTableSlot
*new_slot
);
270 extern bool RI_FKey_fk_upd_check_required(Trigger
*trigger
, Relation fk_rel
,
271 TupleTableSlot
*old_slot
, TupleTableSlot
*new_slot
);
272 extern bool RI_Initial_Check(Trigger
*trigger
,
273 Relation fk_rel
, Relation pk_rel
);
274 extern void RI_PartitionRemove_Check(Trigger
*trigger
, Relation fk_rel
,
277 /* result values for RI_FKey_trigger_type: */
278 #define RI_TRIGGER_PK 1 /* is a trigger on the PK relation */
279 #define RI_TRIGGER_FK 2 /* is a trigger on the FK relation */
280 #define RI_TRIGGER_NONE 0 /* is not an RI trigger function */
282 extern int RI_FKey_trigger_type(Oid tgfoid
);
284 #endif /* TRIGGER_H */