1 /*------------------------------------------------------------------------- 2 * 3 * trigger.h 4 * Declarations for trigger handling. 5 * 6 * Portions Copyright (c) 1996-2021, 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 28 typedef uint32 TriggerEvent; 29 30 typedef 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 const Bitmapset *tg_updatedcols; 43 } TriggerData; 44 45 /* 46 * The state for capturing old and new tuples into transition tables for a 47 * single ModifyTable node (or other operation source, e.g. copyfrom.c). 48 * 49 * This is per-caller to avoid conflicts in setting 50 * tcs_original_insert_tuple. Note, however, that the pointed-to 51 * private data may be shared across multiple callers. 52 */ 53 struct AfterTriggersTableData; /* private in trigger.c */ 54 55 typedef struct TransitionCaptureState 56 { 57 /* 58 * Is there at least one trigger specifying each transition relation on 59 * the relation explicitly named in the DML statement or COPY command? 60 * Note: in current usage, these flags could be part of the private state, 61 * but it seems possibly useful to let callers see them. 62 */ 63 bool tcs_delete_old_table; 64 bool tcs_update_old_table; 65 bool tcs_update_new_table; 66 bool tcs_insert_new_table; 67 68 /* 69 * For INSERT and COPY, it would be wasteful to convert tuples from child 70 * format to parent format after they have already been converted in the 71 * opposite direction during routing. In that case we bypass conversion 72 * and allow the inserting code (copyfrom.c and nodeModifyTable.c) to 73 * provide a slot containing the original tuple directly. 74 */ 75 TupleTableSlot *tcs_original_insert_tuple; 76 77 /* 78 * Private data including the tuplestore(s) into which to insert tuples. 79 */ 80 struct AfterTriggersTableData *tcs_private; 81 } TransitionCaptureState; 82 83 /* 84 * TriggerEvent bit flags 85 * 86 * Note that we assume different event types (INSERT/DELETE/UPDATE/TRUNCATE) 87 * can't be OR'd together in a single TriggerEvent. This is unlike the 88 * situation for pg_trigger rows, so pg_trigger.tgtype uses a different 89 * representation! 90 */ 91 #define TRIGGER_EVENT_INSERT 0x00000000 92 #define TRIGGER_EVENT_DELETE 0x00000001 93 #define TRIGGER_EVENT_UPDATE 0x00000002 94 #define TRIGGER_EVENT_TRUNCATE 0x00000003 95 #define TRIGGER_EVENT_OPMASK 0x00000003 96 97 #define TRIGGER_EVENT_ROW 0x00000004 98 99 #define TRIGGER_EVENT_BEFORE 0x00000008 100 #define TRIGGER_EVENT_AFTER 0x00000000 101 #define TRIGGER_EVENT_INSTEAD 0x00000010 102 #define TRIGGER_EVENT_TIMINGMASK 0x00000018 103 104 /* More TriggerEvent flags, used only within trigger.c */ 105 106 #define AFTER_TRIGGER_DEFERRABLE 0x00000020 107 #define AFTER_TRIGGER_INITDEFERRED 0x00000040 108 109 #define TRIGGER_FIRED_BY_INSERT(event) \ 110 (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_INSERT) 111 112 #define TRIGGER_FIRED_BY_DELETE(event) \ 113 (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_DELETE) 114 115 #define TRIGGER_FIRED_BY_UPDATE(event) \ 116 (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_UPDATE) 117 118 #define TRIGGER_FIRED_BY_TRUNCATE(event) \ 119 (((event) & TRIGGER_EVENT_OPMASK) == TRIGGER_EVENT_TRUNCATE) 120 121 #define TRIGGER_FIRED_FOR_ROW(event) \ 122 ((event) & TRIGGER_EVENT_ROW) 123 124 #define TRIGGER_FIRED_FOR_STATEMENT(event) \ 125 (!TRIGGER_FIRED_FOR_ROW(event)) 126 127 #define TRIGGER_FIRED_BEFORE(event) \ 128 (((event) & TRIGGER_EVENT_TIMINGMASK) == TRIGGER_EVENT_BEFORE) 129 130 #define TRIGGER_FIRED_AFTER(event) \ 131 (((event) & TRIGGER_EVENT_TIMINGMASK) == TRIGGER_EVENT_AFTER) 132 133 #define TRIGGER_FIRED_INSTEAD(event) \ 134 (((event) & TRIGGER_EVENT_TIMINGMASK) == TRIGGER_EVENT_INSTEAD) 135 136 /* 137 * Definitions for replication role based firing. 138 */ 139 #define SESSION_REPLICATION_ROLE_ORIGIN 0 140 #define SESSION_REPLICATION_ROLE_REPLICA 1 141 #define SESSION_REPLICATION_ROLE_LOCAL 2 142 extern PGDLLIMPORT int SessionReplicationRole; 143 144 /* 145 * States at which a trigger can be fired. These are the 146 * possible values for pg_trigger.tgenabled. 147 */ 148 #define TRIGGER_FIRES_ON_ORIGIN 'O' 149 #define TRIGGER_FIRES_ALWAYS 'A' 150 #define TRIGGER_FIRES_ON_REPLICA 'R' 151 #define TRIGGER_DISABLED 'D' 152 153 extern ObjectAddress CreateTrigger(CreateTrigStmt *stmt, const char *queryString, 154 Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid, 155 Oid funcoid, Oid parentTriggerOid, Node *whenClause, 156 bool isInternal, bool in_partition); 157 extern ObjectAddress CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString, 158 Oid relOid, Oid refRelOid, Oid constraintOid, 159 Oid indexOid, Oid funcoid, Oid parentTriggerOid, 160 Node *whenClause, bool isInternal, bool in_partition, 161 char trigger_fires_when); 162 163 extern void RemoveTriggerById(Oid trigOid); 164 extern Oid get_trigger_oid(Oid relid, const char *name, bool missing_ok); 165 166 extern ObjectAddress renametrig(RenameStmt *stmt); 167 168 extern void EnableDisableTrigger(Relation rel, const char *tgname, 169 char fires_when, bool skip_system, LOCKMODE lockmode); 170 171 extern void RelationBuildTriggers(Relation relation); 172 173 extern TriggerDesc *CopyTriggerDesc(TriggerDesc *trigdesc); 174 175 extern const char *FindTriggerIncompatibleWithInheritance(TriggerDesc *trigdesc); 176 177 extern TransitionCaptureState *MakeTransitionCaptureState(TriggerDesc *trigdesc, 178 Oid relid, CmdType cmdType); 179 180 extern void FreeTriggerDesc(TriggerDesc *trigdesc); 181 182 extern void ExecBSInsertTriggers(EState *estate, 183 ResultRelInfo *relinfo); 184 extern void ExecASInsertTriggers(EState *estate, 185 ResultRelInfo *relinfo, 186 TransitionCaptureState *transition_capture); 187 extern bool ExecBRInsertTriggers(EState *estate, 188 ResultRelInfo *relinfo, 189 TupleTableSlot *slot); 190 extern void ExecARInsertTriggers(EState *estate, 191 ResultRelInfo *relinfo, 192 TupleTableSlot *slot, 193 List *recheckIndexes, 194 TransitionCaptureState *transition_capture); 195 extern bool ExecIRInsertTriggers(EState *estate, 196 ResultRelInfo *relinfo, 197 TupleTableSlot *slot); 198 extern void ExecBSDeleteTriggers(EState *estate, 199 ResultRelInfo *relinfo); 200 extern void ExecASDeleteTriggers(EState *estate, 201 ResultRelInfo *relinfo, 202 TransitionCaptureState *transition_capture); 203 extern bool ExecBRDeleteTriggers(EState *estate, 204 EPQState *epqstate, 205 ResultRelInfo *relinfo, 206 ItemPointer tupleid, 207 HeapTuple fdw_trigtuple, 208 TupleTableSlot **epqslot); 209 extern void ExecARDeleteTriggers(EState *estate, 210 ResultRelInfo *relinfo, 211 ItemPointer tupleid, 212 HeapTuple fdw_trigtuple, 213 TransitionCaptureState *transition_capture); 214 extern bool ExecIRDeleteTriggers(EState *estate, 215 ResultRelInfo *relinfo, 216 HeapTuple trigtuple); 217 extern void ExecBSUpdateTriggers(EState *estate, 218 ResultRelInfo *relinfo); 219 extern void ExecASUpdateTriggers(EState *estate, 220 ResultRelInfo *relinfo, 221 TransitionCaptureState *transition_capture); 222 extern bool ExecBRUpdateTriggers(EState *estate, 223 EPQState *epqstate, 224 ResultRelInfo *relinfo, 225 ItemPointer tupleid, 226 HeapTuple fdw_trigtuple, 227 TupleTableSlot *slot); 228 extern void ExecARUpdateTriggers(EState *estate, 229 ResultRelInfo *relinfo, 230 ItemPointer tupleid, 231 HeapTuple fdw_trigtuple, 232 TupleTableSlot *slot, 233 List *recheckIndexes, 234 TransitionCaptureState *transition_capture); 235 extern bool ExecIRUpdateTriggers(EState *estate, 236 ResultRelInfo *relinfo, 237 HeapTuple trigtuple, 238 TupleTableSlot *slot); 239 extern void ExecBSTruncateTriggers(EState *estate, 240 ResultRelInfo *relinfo); 241 extern void ExecASTruncateTriggers(EState *estate, 242 ResultRelInfo *relinfo); 243 244 extern void AfterTriggerBeginXact(void); 245 extern void AfterTriggerBeginQuery(void); 246 extern void AfterTriggerEndQuery(EState *estate); 247 extern void AfterTriggerFireDeferred(void); 248 extern void AfterTriggerEndXact(bool isCommit); 249 extern void AfterTriggerBeginSubXact(void); 250 extern void AfterTriggerEndSubXact(bool isCommit); 251 extern void AfterTriggerSetState(ConstraintsSetStmt *stmt); 252 extern bool AfterTriggerPendingOnRel(Oid relid); 253 254 255 /* 256 * in utils/adt/ri_triggers.c 257 */ 258 extern bool RI_FKey_pk_upd_check_required(Trigger *trigger, Relation pk_rel, 259 TupleTableSlot *old_slot, TupleTableSlot *new_slot); 260 extern bool RI_FKey_fk_upd_check_required(Trigger *trigger, Relation fk_rel, 261 TupleTableSlot *old_slot, TupleTableSlot *new_slot); 262 extern bool RI_Initial_Check(Trigger *trigger, 263 Relation fk_rel, Relation pk_rel); 264 extern void RI_PartitionRemove_Check(Trigger *trigger, Relation fk_rel, 265 Relation pk_rel); 266 267 /* result values for RI_FKey_trigger_type: */ 268 #define RI_TRIGGER_PK 1 /* is a trigger on the PK relation */ 269 #define RI_TRIGGER_FK 2 /* is a trigger on the FK relation */ 270 #define RI_TRIGGER_NONE 0 /* is not an RI trigger function */ 271 272 extern int RI_FKey_trigger_type(Oid tgfoid); 273 274 #endif /* TRIGGER_H */ 275