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 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 } 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 */ 52 struct AfterTriggersTableData; /* private in trigger.c */ 53 54 typedef 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 149 extern 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 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); 169 170 extern void RemoveTriggerById(Oid trigOid); 171 extern Oid get_trigger_oid(Oid relid, const char *name, bool missing_ok); 172 173 extern ObjectAddress renametrig(RenameStmt *stmt); 174 175 extern void EnableDisableTrigger(Relation rel, const char *tgname, 176 char fires_when, bool skip_system, LOCKMODE lockmode); 177 178 extern void RelationBuildTriggers(Relation relation); 179 180 extern TriggerDesc *CopyTriggerDesc(TriggerDesc *trigdesc); 181 182 extern const char *FindTriggerIncompatibleWithInheritance(TriggerDesc *trigdesc); 183 184 extern TransitionCaptureState *MakeTransitionCaptureState(TriggerDesc *trigdesc, 185 Oid relid, CmdType cmdType); 186 187 extern void FreeTriggerDesc(TriggerDesc *trigdesc); 188 189 extern void ExecBSInsertTriggers(EState *estate, 190 ResultRelInfo *relinfo); 191 extern void ExecASInsertTriggers(EState *estate, 192 ResultRelInfo *relinfo, 193 TransitionCaptureState *transition_capture); 194 extern bool ExecBRInsertTriggers(EState *estate, 195 ResultRelInfo *relinfo, 196 TupleTableSlot *slot); 197 extern void ExecARInsertTriggers(EState *estate, 198 ResultRelInfo *relinfo, 199 TupleTableSlot *slot, 200 List *recheckIndexes, 201 TransitionCaptureState *transition_capture); 202 extern bool ExecIRInsertTriggers(EState *estate, 203 ResultRelInfo *relinfo, 204 TupleTableSlot *slot); 205 extern void ExecBSDeleteTriggers(EState *estate, 206 ResultRelInfo *relinfo); 207 extern void ExecASDeleteTriggers(EState *estate, 208 ResultRelInfo *relinfo, 209 TransitionCaptureState *transition_capture); 210 extern bool ExecBRDeleteTriggers(EState *estate, 211 EPQState *epqstate, 212 ResultRelInfo *relinfo, 213 ItemPointer tupleid, 214 HeapTuple fdw_trigtuple, 215 TupleTableSlot **epqslot); 216 extern void ExecARDeleteTriggers(EState *estate, 217 ResultRelInfo *relinfo, 218 ItemPointer tupleid, 219 HeapTuple fdw_trigtuple, 220 TransitionCaptureState *transition_capture); 221 extern bool ExecIRDeleteTriggers(EState *estate, 222 ResultRelInfo *relinfo, 223 HeapTuple trigtuple); 224 extern void ExecBSUpdateTriggers(EState *estate, 225 ResultRelInfo *relinfo); 226 extern void ExecASUpdateTriggers(EState *estate, 227 ResultRelInfo *relinfo, 228 TransitionCaptureState *transition_capture); 229 extern bool ExecBRUpdateTriggers(EState *estate, 230 EPQState *epqstate, 231 ResultRelInfo *relinfo, 232 ItemPointer tupleid, 233 HeapTuple fdw_trigtuple, 234 TupleTableSlot *slot); 235 extern void ExecARUpdateTriggers(EState *estate, 236 ResultRelInfo *relinfo, 237 ItemPointer tupleid, 238 HeapTuple fdw_trigtuple, 239 TupleTableSlot *slot, 240 List *recheckIndexes, 241 TransitionCaptureState *transition_capture); 242 extern bool ExecIRUpdateTriggers(EState *estate, 243 ResultRelInfo *relinfo, 244 HeapTuple trigtuple, 245 TupleTableSlot *slot); 246 extern void ExecBSTruncateTriggers(EState *estate, 247 ResultRelInfo *relinfo); 248 extern void ExecASTruncateTriggers(EState *estate, 249 ResultRelInfo *relinfo); 250 251 extern void AfterTriggerBeginXact(void); 252 extern void AfterTriggerBeginQuery(void); 253 extern void AfterTriggerEndQuery(EState *estate); 254 extern void AfterTriggerFireDeferred(void); 255 extern void AfterTriggerEndXact(bool isCommit); 256 extern void AfterTriggerBeginSubXact(void); 257 extern void AfterTriggerEndSubXact(bool isCommit); 258 extern void AfterTriggerSetState(ConstraintsSetStmt *stmt); 259 extern bool AfterTriggerPendingOnRel(Oid relid); 260 261 262 /* 263 * in utils/adt/ri_triggers.c 264 */ 265 extern bool RI_FKey_pk_upd_check_required(Trigger *trigger, Relation pk_rel, 266 TupleTableSlot *old_slot, TupleTableSlot *new_slot); 267 extern bool RI_FKey_fk_upd_check_required(Trigger *trigger, Relation fk_rel, 268 TupleTableSlot *old_slot, TupleTableSlot *new_slot); 269 extern bool RI_Initial_Check(Trigger *trigger, 270 Relation fk_rel, Relation pk_rel); 271 extern void RI_PartitionRemove_Check(Trigger *trigger, Relation fk_rel, 272 Relation pk_rel); 273 274 /* result values for RI_FKey_trigger_type: */ 275 #define RI_TRIGGER_PK 1 /* is a trigger on the PK relation */ 276 #define RI_TRIGGER_FK 2 /* is a trigger on the FK relation */ 277 #define RI_TRIGGER_NONE 0 /* is not an RI trigger function */ 278 279 extern int RI_FKey_trigger_type(Oid tgfoid); 280 281 #endif /* TRIGGER_H */ 282