1/*-------------------------------------------------------------------------
2 *
3 * trigger.h
4 * Declarations for trigger handling.
5 *
6 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 * src/include/commands/trigger.h
10 *
11 *-------------------------------------------------------------------------
12 */
13#ifndef TRIGGER_H
14#define TRIGGER_H
15
16#include "catalog/objectaddress.h"
17#include "nodes/execnodes.h"
18#include "nodes/parsenodes.h"
19
20/*
21 * TriggerData is the node type that is passed as fmgr "context" info
22 * when a function is called by the trigger manager.
23 */
24
25#define CALLED_AS_TRIGGER(fcinfo) \
26 ((fcinfo)->context != NULL && IsA((fcinfo)->context, TriggerData))
27
28typedef uint32 TriggerEvent;
29
30typedef struct TriggerData
31{
32 NodeTag type;
33 TriggerEvent tg_event;
34 Relation tg_relation;
35 HeapTuple tg_trigtuple;
36 HeapTuple tg_newtuple;
37 Trigger *tg_trigger;
38 TupleTableSlot *tg_trigslot;
39 TupleTableSlot *tg_newslot;
40 Tuplestorestate *tg_oldtable;
41 Tuplestorestate *tg_newtable;
42} TriggerData;
43
44/*
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).
47 *
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.
51 */
52struct AfterTriggersTableData; /* private in trigger.c */
53
54typedef struct TransitionCaptureState
55{
56 /*
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.
61 */
62 bool tcs_delete_old_table;
63 bool tcs_update_old_table;
64 bool tcs_update_new_table;
65 bool tcs_insert_new_table;
66
67 /*
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.
72 */
73 TupleConversionMap *tcs_map;
74
75 /*
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.
81 */
82 TupleTableSlot *tcs_original_insert_tuple;
83
84 /*
85 * Private data including the tuplestore(s) into which to insert tuples.
86 */
87 struct AfterTriggersTableData *tcs_private;
88} TransitionCaptureState;
89
90/*
91 * TriggerEvent bit flags
92 *
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
96 * representation!
97 */
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
103
104#define TRIGGER_EVENT_ROW 0x00000004
105
106#define TRIGGER_EVENT_BEFORE 0x00000008
107#define TRIGGER_EVENT_AFTER 0x00000000
108#define TRIGGER_EVENT_INSTEAD 0x00000010
109#define TRIGGER_EVENT_TIMINGMASK 0x00000018
110
111/* More TriggerEvent flags, used only within trigger.c */
112
113#define AFTER_TRIGGER_DEFERRABLE 0x00000020
114#define AFTER_TRIGGER_INITDEFERRED 0x00000040
115
116#define TRIGGER_FIRED_BY_INSERT(event) \
117 (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_INSERT)
118
119#define TRIGGER_FIRED_BY_DELETE(event) \
120 (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_DELETE)
121
122#define TRIGGER_FIRED_BY_UPDATE(event) \
123 (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_UPDATE)
124
125#define TRIGGER_FIRED_BY_TRUNCATE(event) \
126 (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_TRUNCATE)
127
128#define TRIGGER_FIRED_FOR_ROW(event) \
129 ((event) & TRIGGER_EVENT_ROW)
130
131#define TRIGGER_FIRED_FOR_STATEMENT(event) \
132 (!TRIGGER_FIRED_FOR_ROW(event))
133
134#define TRIGGER_FIRED_BEFORE(event) \
135 (((event) & TRIGGER_EVENT_TIMINGMASK) == TRIGGER_EVENT_BEFORE)
136
137#define TRIGGER_FIRED_AFTER(event) \
138 (((event) & TRIGGER_EVENT_TIMINGMASK) == TRIGGER_EVENT_AFTER)
139
140#define TRIGGER_FIRED_INSTEAD(event) \
141 (((event) & TRIGGER_EVENT_TIMINGMASK) == TRIGGER_EVENT_INSTEAD)
142
143/*
144 * Definitions for replication role based firing.
145 */
146#define SESSION_REPLICATION_ROLE_ORIGIN 0
147#define SESSION_REPLICATION_ROLE_REPLICA 1
148#define SESSION_REPLICATION_ROLE_LOCAL 2
149extern PGDLLIMPORT int SessionReplicationRole;
150
151/*
152 * States at which a trigger can be fired. These are the
153 * possible values for pg_trigger.tgenabled.
154 */
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'
159
160extern 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
165extern void RemoveTriggerById(Oid trigOid);
166extern Oid get_trigger_oid(Oid relid, const char *name, bool missing_ok);
167
168extern ObjectAddress renametrig(RenameStmt *stmt);
169
170extern void EnableDisableTrigger(Relation rel, const char *tgname,
171 char fires_when, bool skip_system, LOCKMODE lockmode);
172
173extern void RelationBuildTriggers(Relation relation);
174
175extern TriggerDesc *CopyTriggerDesc(TriggerDesc *trigdesc);
176
177extern const char *FindTriggerIncompatibleWithInheritance(TriggerDesc *trigdesc);
178
179extern TransitionCaptureState *MakeTransitionCaptureState(TriggerDesc *trigdesc,
180 Oid relid, CmdType cmdType);
181
182extern void FreeTriggerDesc(TriggerDesc *trigdesc);
183
184extern void ExecBSInsertTriggers(EState *estate,
185 ResultRelInfo *relinfo);
186extern void ExecASInsertTriggers(EState *estate,
187 ResultRelInfo *relinfo,
188 TransitionCaptureState *transition_capture);
189extern bool ExecBRInsertTriggers(EState *estate,
190 ResultRelInfo *relinfo,
191 TupleTableSlot *slot);
192extern void ExecARInsertTriggers(EState *estate,
193 ResultRelInfo *relinfo,
194 TupleTableSlot *slot,
195 List *recheckIndexes,
196 TransitionCaptureState *transition_capture);
197extern bool ExecIRInsertTriggers(EState *estate,
198 ResultRelInfo *relinfo,
199 TupleTableSlot *slot);
200extern void ExecBSDeleteTriggers(EState *estate,
201 ResultRelInfo *relinfo);
202extern void ExecASDeleteTriggers(EState *estate,
203 ResultRelInfo *relinfo,
204 TransitionCaptureState *transition_capture);
205extern bool ExecBRDeleteTriggers(EState *estate,
206 EPQState *epqstate,
207 ResultRelInfo *relinfo,
208 ItemPointer tupleid,
209 HeapTuple fdw_trigtuple,
210 TupleTableSlot **epqslot);
211extern void ExecARDeleteTriggers(EState *estate,
212 ResultRelInfo *relinfo,
213 ItemPointer tupleid,
214 HeapTuple fdw_trigtuple,
215 TransitionCaptureState *transition_capture);
216extern bool ExecIRDeleteTriggers(EState *estate,
217 ResultRelInfo *relinfo,
218 HeapTuple trigtuple);
219extern void ExecBSUpdateTriggers(EState *estate,
220 ResultRelInfo *relinfo);
221extern void ExecASUpdateTriggers(EState *estate,
222 ResultRelInfo *relinfo,
223 TransitionCaptureState *transition_capture);
224extern bool ExecBRUpdateTriggers(EState *estate,
225 EPQState *epqstate,
226 ResultRelInfo *relinfo,
227 ItemPointer tupleid,
228 HeapTuple fdw_trigtuple,
229 TupleTableSlot *slot);
230extern void ExecARUpdateTriggers(EState *estate,
231 ResultRelInfo *relinfo,
232 ItemPointer tupleid,
233 HeapTuple fdw_trigtuple,
234 TupleTableSlot *slot,
235 List *recheckIndexes,
236 TransitionCaptureState *transition_capture);
237extern bool ExecIRUpdateTriggers(EState *estate,
238 ResultRelInfo *relinfo,
239 HeapTuple trigtuple,
240 TupleTableSlot *slot);
241extern void ExecBSTruncateTriggers(EState *estate,
242 ResultRelInfo *relinfo);
243extern void ExecASTruncateTriggers(EState *estate,
244 ResultRelInfo *relinfo);
245
246extern void AfterTriggerBeginXact(void);
247extern void AfterTriggerBeginQuery(void);
248extern void AfterTriggerEndQuery(EState *estate);
249extern void AfterTriggerFireDeferred(void);
250extern void AfterTriggerEndXact(bool isCommit);
251extern void AfterTriggerBeginSubXact(void);
252extern void AfterTriggerEndSubXact(bool isCommit);
253extern void AfterTriggerSetState(ConstraintsSetStmt *stmt);
254extern bool AfterTriggerPendingOnRel(Oid relid);
255
256
257/*
258 * in utils/adt/ri_triggers.c
259 */
260extern bool RI_FKey_pk_upd_check_required(Trigger *trigger, Relation pk_rel,
261 TupleTableSlot *old_slot, TupleTableSlot *new_slot);
262extern bool RI_FKey_fk_upd_check_required(Trigger *trigger, Relation fk_rel,
263 TupleTableSlot *old_slot, TupleTableSlot *new_slot);
264extern bool RI_Initial_Check(Trigger *trigger,
265 Relation fk_rel, Relation pk_rel);
266extern void RI_PartitionRemove_Check(Trigger *trigger, Relation fk_rel,
267 Relation pk_rel);
268
269/* result values for RI_FKey_trigger_type: */
270#define RI_TRIGGER_PK 1 /* is a trigger on the PK relation */
271#define RI_TRIGGER_FK 2 /* is a trigger on the FK relation */
272#define RI_TRIGGER_NONE 0 /* is not an RI trigger function */
273
274extern int RI_FKey_trigger_type(Oid tgfoid);
275
276#endif /* TRIGGER_H */
277