52 #include "utils/fmgroids.h"
75 #define GetUpdatedColumns(relinfo, estate) \
76 (rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->updatedCols)
97 int event,
bool row_trigger,
139 Oid relOid,
Oid refRelOid,
Oid constraintOid,
Oid indexOid,
183 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
184 errmsg(
"\"%s\" is a table",
186 errdetail(
"Tables cannot have INSTEAD OF triggers.")));
196 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
197 errmsg(
"\"%s\" is a view",
199 errdetail(
"Views cannot have row-level BEFORE or AFTER triggers.")));
203 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
204 errmsg(
"\"%s\" is a view",
206 errdetail(
"Views cannot have TRUNCATE triggers.")));
213 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
214 errmsg(
"\"%s\" is a foreign table",
216 errdetail(
"Foreign tables cannot have INSTEAD OF triggers.")));
220 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
221 errmsg(
"\"%s\" is a foreign table",
223 errdetail(
"Foreign tables cannot have TRUNCATE triggers.")));
227 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
228 errmsg(
"\"%s\" is a foreign table",
230 errdetail(
"Foreign tables cannot have constraint triggers.")));
234 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
235 errmsg(
"\"%s\" is not a table or view",
240 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
241 errmsg(
"permission denied: \"%s\" is a system catalog",
256 constrrelid = refRelOid;
292 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
293 errmsg(
"TRUNCATE FOR EACH ROW triggers are not supported")));
300 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
301 errmsg(
"INSTEAD OF triggers must be FOR EACH ROW")));
304 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
305 errmsg(
"INSTEAD OF triggers cannot have WHEN conditions")));
308 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
309 errmsg(
"INSTEAD OF triggers cannot have column lists")));
365 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
366 errmsg(
"statement trigger's WHEN condition cannot reference column values"),
370 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
371 errmsg(
"INSERT trigger's WHEN condition cannot reference OLD values"),
378 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
379 errmsg(
"statement trigger's WHEN condition cannot reference column values"),
383 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
384 errmsg(
"DELETE trigger's WHEN condition cannot reference NEW values"),
388 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
389 errmsg(
"BEFORE trigger's WHEN condition cannot reference NEW system columns"),
394 elog(
ERROR,
"trigger WHEN condition cannot contain references to other relations");
434 (
errmsg(
"changing return type of function %s from \"opaque\" to \"trigger\"",
440 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
441 errmsg(
"function %s must return type %s",
518 snprintf(internaltrigname,
sizeof(internaltrigname),
520 trigname = internaltrigname;
550 if (
namestrcmp(&(pg_trigger->tgname), trigname) == 0)
553 errmsg(
"trigger \"%s\" for relation \"%s\" already exists",
562 memset(nulls,
false,
sizeof(nulls));
584 foreach(le, stmt->
args)
588 len += strlen(ar) + 4;
595 args = (
char *)
palloc(len + 1);
597 foreach(le, stmt->
args)
600 char *d = args + strlen(args);
641 (
errcode(ERRCODE_UNDEFINED_COLUMN),
642 errmsg(
"column \"%s\" of relation \"%s\" does not exist",
646 for (j = i - 1; j >= 0; j--)
648 if (columns[j] == attnum)
650 (
errcode(ERRCODE_DUPLICATE_COLUMN),
651 errmsg(
"column \"%s\" specified more than once",
655 columns[i++] = attnum;
695 elog(
ERROR,
"cache lookup failed for relation %u",
735 referenced.
objectId = constraintOid;
767 referenced.
objectId = constraintOid;
780 for (i = 0; i < ncolumns; i++)
791 if (whenClause !=
NULL)
837 static const char *
const funcdescr[3] = {
838 gettext_noop(
"Found referenced table's UPDATE trigger."),
839 gettext_noop(
"Found referenced table's DELETE trigger."),
860 foreach(l, stmt->
args)
869 if (strcmp(
strVal(arg),
"FULL") == 0)
876 fk_attrs =
lappend(fk_attrs, arg);
878 pk_attrs =
lappend(pk_attrs, arg);
910 case F_RI_FKEY_CASCADE_UPD:
911 case F_RI_FKEY_RESTRICT_UPD:
912 case F_RI_FKEY_SETNULL_UPD:
913 case F_RI_FKEY_SETDEFAULT_UPD:
914 case F_RI_FKEY_NOACTION_UPD:
918 case F_RI_FKEY_CASCADE_DEL:
919 case F_RI_FKEY_RESTRICT_DEL:
920 case F_RI_FKEY_SETNULL_DEL:
921 case F_RI_FKEY_SETDEFAULT_DEL:
922 case F_RI_FKEY_NOACTION_DEL:
932 foreach(l, info_list)
949 (
errmsg(
"ignoring incomplete trigger group for constraint \"%s\" %s",
950 constr_name, buf.
data),
956 info_list =
lappend(info_list, info);
965 (
errmsg(
"ignoring incomplete trigger group for constraint \"%s\" %s",
966 constr_name, buf.
data),
977 (
errmsg(
"converting trigger group into constraint \"%s\" %s",
978 constr_name, buf.
data),
1010 if (strcmp(constr_name,
"<unnamed>") == 0)
1019 case F_RI_FKEY_NOACTION_UPD:
1022 case F_RI_FKEY_CASCADE_UPD:
1025 case F_RI_FKEY_RESTRICT_UPD:
1028 case F_RI_FKEY_SETNULL_UPD:
1031 case F_RI_FKEY_SETDEFAULT_UPD:
1036 elog(
ERROR,
"confused about RI update function");
1040 case F_RI_FKEY_NOACTION_DEL:
1043 case F_RI_FKEY_CASCADE_DEL:
1046 case F_RI_FKEY_RESTRICT_DEL:
1049 case F_RI_FKEY_SETNULL_DEL:
1052 case F_RI_FKEY_SETDEFAULT_DEL:
1057 elog(
ERROR,
"confused about RI delete function");
1066 "(generated ALTER TABLE ADD FOREIGN KEY command)",
1105 elog(
ERROR,
"could not find tuple for trigger %u", trigOid);
1118 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1119 errmsg(
"\"%s\" is not a table, view, or foreign table",
1124 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1125 errmsg(
"permission denied: \"%s\" is a system catalog",
1189 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1190 errmsg(
"trigger \"%s\" for table \"%s\" does not exist",
1223 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1224 errmsg(
"\"%s\" is not a table, view, or foreign table",
1232 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1233 errmsg(
"permission denied: \"%s\" is a system catalog",
1303 errmsg(
"trigger \"%s\" for relation \"%s\" already exists",
1350 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1351 errmsg(
"trigger \"%s\" for table \"%s\" does not exist",
1389 char fires_when,
bool skip_system)
1420 found = changed =
false;
1426 if (oldtrig->tgisinternal)
1433 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1434 errmsg(
"permission denied: \"%s\" is a system trigger",
1440 if (oldtrig->tgenabled != fires_when)
1446 newtrig->tgenabled = fires_when;
1466 if (tgname && !found)
1468 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1469 errmsg(
"trigger \"%s\" for table \"%s\" does not exist",
1536 if (numtrigs >= maxtrigs)
1541 build = &(triggers[numtrigs]);
1546 build->
tgfoid = pg_trigger->tgfoid;
1547 build->
tgtype = pg_trigger->tgtype;
1548 build->
tgenabled = pg_trigger->tgenabled;
1555 build->
tgnargs = pg_trigger->tgnargs;
1557 build->
tgnattr = pg_trigger->tgattr.dim1;
1561 memcpy(build->
tgattr, &(pg_trigger->tgattr.values),
1573 tgrel->
rd_att, &isnull));
1575 elog(
ERROR,
"tgargs is null in trigger for relation \"%s\"",
1579 for (i = 0; i < build->
tgnargs; i++)
1611 for (i = 0; i < numtrigs; i++)
1704 memcpy(trigger, trigdesc->
triggers,
1716 memcpy(newattr, trigger->
tgattr,
1718 trigger->
tgattr = newattr;
1725 newargs = (
char **)
palloc(trigger->
tgnargs *
sizeof(
char *));
1726 for (j = 0; j < trigger->
tgnargs; j++)
1728 trigger->
tgargs = newargs;
1747 if (trigdesc ==
NULL)
1758 while (--(trigger->
tgnargs) >= 0)
1792 if (trigdesc1 !=
NULL)
1794 if (trigdesc2 ==
NULL)
1833 for (j = 0; j < trig1->
tgnargs; j++)
1844 else if (trigdesc2 !=
NULL)
1929 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
1930 errmsg(
"trigger function %u returned null value",
1952 if (trigdesc ==
NULL)
1988 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
1989 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
2042 if (oldtuple != newtuple && oldtuple != slottuple)
2044 if (newtuple ==
NULL)
2048 if (newtuple != slottuple)
2075 true,
NULL, trigtuple, recheckIndexes,
NULL);
2117 if (oldtuple != newtuple && oldtuple != slottuple)
2119 if (newtuple ==
NULL)
2123 if (newtuple != slottuple)
2151 if (trigdesc ==
NULL)
2187 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2188 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
2217 if (fdw_trigtuple ==
NULL)
2221 if (trigtuple ==
NULL)
2225 trigtuple = fdw_trigtuple;
2255 if (newtuple ==
NULL)
2260 if (newtuple != trigtuple)
2263 if (trigtuple != fdw_trigtuple)
2281 if (fdw_trigtuple ==
NULL)
2289 trigtuple = fdw_trigtuple;
2293 if (trigtuple != fdw_trigtuple)
2335 if (rettuple ==
NULL)
2337 if (rettuple != trigtuple)
2353 if (trigdesc ==
NULL)
2391 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2392 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
2429 if (fdw_trigtuple ==
NULL)
2433 lockmode, &newSlot);
2434 if (trigtuple ==
NULL)
2439 trigtuple = fdw_trigtuple;
2454 if (newSlot !=
NULL)
2458 newtuple = slottuple;
2478 updatedCols, trigtuple, newtuple))
2491 if (oldtuple != newtuple && oldtuple != slottuple)
2493 if (newtuple ==
NULL)
2495 if (trigtuple != fdw_trigtuple)
2500 if (trigtuple != fdw_trigtuple)
2503 if (newtuple != slottuple)
2527 List *recheckIndexes)
2536 if (fdw_trigtuple ==
NULL)
2544 trigtuple = fdw_trigtuple;
2547 true, trigtuple, newtuple, recheckIndexes,
2549 if (trigtuple != fdw_trigtuple)
2580 NULL, trigtuple, newtuple))
2593 if (oldtuple != newtuple && oldtuple != slottuple)
2595 if (newtuple ==
NULL)
2599 if (newtuple != slottuple)
2627 if (trigdesc ==
NULL)
2663 (
errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
2664 errmsg(
"BEFORE STATEMENT trigger cannot return a value")));
2692 if (newSlot !=
NULL)
2710 false, &buffer, &hufd);
2725 (
errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
2726 errmsg(
"tuple to be updated was already modified by an operation triggered by the current command"),
2727 errhint(
"Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
2740 (
errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
2741 errmsg(
"could not serialize access due to concurrent update")));
2776 elog(
ERROR,
"attempted to lock invisible tuple");
2780 elog(
ERROR,
"unrecognized heap_lock_tuple status: %u", test);
2853 for (i = 0; i < trigger->
tgnattr; i++)
2891 if (*predicate ==
NIL)
2950 if (!
ExecQual(*predicate, econtext,
false))
3042 #define AFTER_TRIGGER_OFFSET 0x0FFFFFFF
3044 #define AFTER_TRIGGER_DONE 0x10000000
3045 #define AFTER_TRIGGER_IN_PROGRESS 0x20000000
3047 #define AFTER_TRIGGER_FDW_REUSE 0x00000000
3048 #define AFTER_TRIGGER_FDW_FETCH 0x80000000
3049 #define AFTER_TRIGGER_1CTID 0x40000000
3050 #define AFTER_TRIGGER_2CTID 0xC0000000
3051 #define AFTER_TRIGGER_TUP_BITS 0xC0000000
3085 #define SizeofTriggerEvent(evt) \
3086 (((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_2CTID ? \
3087 sizeof(AfterTriggerEventData) : \
3088 ((evt)->ate_flags & AFTER_TRIGGER_TUP_BITS) == AFTER_TRIGGER_1CTID ? \
3089 sizeof(AfterTriggerEventDataOneCtid) : \
3090 sizeof(AfterTriggerEventDataZeroCtids))
3092 #define GetTriggerSharedData(evt) \
3093 ((AfterTriggerShared) ((char *) (evt) + ((evt)->ate_flags & AFTER_TRIGGER_OFFSET)))
3111 #define CHUNK_DATA_START(cptr) ((char *) (cptr) + MAXALIGN(sizeof(AfterTriggerEventChunk)))
3122 #define for_each_chunk(cptr, evtlist) \
3123 for (cptr = (evtlist).head; cptr != NULL; cptr = cptr->next)
3124 #define for_each_event(eptr, cptr) \
3125 for (eptr = (AfterTriggerEvent) CHUNK_DATA_START(cptr); \
3126 (char *) eptr < (cptr)->freeptr; \
3127 eptr = (AfterTriggerEvent) (((char *) eptr) + SizeofTriggerEvent(eptr)))
3129 #define for_each_event_chunk(eptr, cptr, evtlist) \
3130 for_each_chunk(cptr, evtlist) for_each_event(eptr, cptr)
3221 Oid tgoid,
bool tgisdeferred);
3275 SetConstraintState
state = afterTriggers.
state;
3319 AfterTriggerEvent event, AfterTriggerShared evtshared)
3324 AfterTriggerShared newshared;
3325 AfterTriggerEvent newevent;
3331 chunk = events->
tail;
3332 if (chunk ==
NULL ||
3333 chunk->endfree - chunk->freeptr < needed)
3341 "AfterTriggerEvents",
3361 #define MIN_CHUNK_SIZE 1024
3362 #define MAX_CHUNK_SIZE (1024*1024)
3364 #if MAX_CHUNK_SIZE > (AFTER_TRIGGER_OFFSET+1)
3365 #error MAX_CHUNK_SIZE must not exceed AFTER_TRIGGER_OFFSET
3373 chunksize = chunk->endptr - (
char *) chunk;
3375 if ((chunk->endptr - chunk->endfree) <=
3385 chunk->endptr = chunk->endfree = (
char *) chunk + chunksize;
3386 Assert(chunk->endfree - chunk->freeptr >= needed);
3389 events->
head = chunk;
3392 events->
tail = chunk;
3400 for (newshared = ((AfterTriggerShared) chunk->endptr) - 1;
3401 (
char *) newshared >= chunk->endfree;
3410 if ((
char *) newshared < chunk->endfree)
3412 *newshared = *evtshared;
3414 chunk->endfree = (
char *) newshared;
3419 memcpy(newevent, event, eventsize);
3422 newevent->
ate_flags |= (
char *) newshared - (
char *) newevent;
3424 chunk->freeptr += eventsize;
3440 for (chunk = events->
head; chunk !=
NULL; chunk = next_chunk)
3442 next_chunk = chunk->
next;
3471 *events = *old_events;
3473 for (chunk = events->
tail->
next; chunk !=
NULL; chunk = next_chunk)
3475 next_chunk = chunk->
next;
3534 for (tgindx = 0; tgindx < trigdesc->
numtriggers; tgindx++)
3543 elog(
ERROR,
"could not find trigger %u", tgoid);
3563 elog(
ERROR,
"failed to fetch tuple1 for AFTER trigger");
3569 elog(
ERROR,
"failed to fetch tuple2 for AFTER trigger");
3600 elog(
ERROR,
"failed to fetch tuple1 for AFTER trigger");
3617 elog(
ERROR,
"failed to fetch tuple2 for AFTER trigger");
3647 if (rettuple !=
NULL &&
3686 bool immediate_only)
3689 AfterTriggerEvent event;
3695 bool defer_it =
false;
3722 if (defer_it && move_list !=
NULL)
3761 bool all_fired =
true;
3764 bool local_estate =
false;
3776 local_estate =
true;
3782 "AfterTriggerTupleContext",
3789 AfterTriggerEvent event;
3790 bool all_fired_in_chunk =
true;
3825 if (trigdesc ==
NULL)
3826 elog(
ERROR,
"relation %u has no triggers",
3836 per_tuple_context, slot1, slot2);
3847 all_fired = all_fired_in_chunk =
false;
3852 if (delete_ok && all_fired_in_chunk)
3863 if (chunk == events->
tail)
4042 bool snap_pushed =
false;
4052 events = &afterTriggers.
events;
4164 #define DEFTRIG_INITALLOC 8
4165 afterTriggers.
state_stack = (SetConstraintState *)
4182 afterTriggers.
state_stack = (SetConstraintState *)
4184 new_alloc *
sizeof(SetConstraintState));
4190 new_alloc *
sizeof(
int));
4218 SetConstraintState
state;
4219 AfterTriggerEvent event;
4290 afterTriggers.
state = state;
4303 subxact_firing_id = afterTriggers.
firing_stack[my_level];
4383 static SetConstraintState
4386 SetConstraintState
state;
4408 static SetConstraintState
4411 SetConstraintState
state;
4428 static SetConstraintState
4430 Oid tgoid,
bool tgisdeferred)
4434 int newalloc = state->
numalloc * 2;
4436 newalloc =
Max(newalloc, 8);
4519 List *namespacelist;
4526 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4527 errmsg(
"cross-database references are not implemented: \"%s.%s.%s\"",
4550 foreach(nslc, namespacelist)
4567 true,
NULL, 2, skey);
4573 if (con->condeferrable)
4578 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
4579 errmsg(
"constraint \"%s\" is not deferrable",
4601 (
errcode(ERRCODE_UNDEFINED_OBJECT),
4602 errmsg(
"constraint \"%s\" does not exist",
4614 foreach(lc, conoidlist)
4642 if (pg_trigger->tgdeferrable)
4653 elog(
ERROR,
"no triggers found for constraint with OID %u",
4663 foreach(lc, tgoidlist)
4666 SetConstraintState
state = afterTriggers.
state;
4681 afterTriggers.
state =
4701 bool snapshot_set =
false;
4719 snapshot_set =
true;
4755 AfterTriggerEvent event;
4812 int event,
bool row_trigger,
4832 elog(
ERROR,
"AfterTriggerSaveEvent() called outside of query");
4906 elog(
ERROR,
"invalid after-trigger event code: %d", event);
4928 modifiedCols, oldtup, newtup))
4933 if (fdw_tuplestore ==
NULL)
4983 if (trigger->
tgfoid == F_UNIQUE_KEY_RECHECK)
5002 &new_event, &new_shared);
void RemoveTriggerById(Oid trigOid)
#define ItemPointerIsValid(pointer)
#define TRIGGER_EVENT_ROW
HeapTuple heap_copytuple(HeapTuple tuple)
void ExecASDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
#define Anum_pg_trigger_tgdeferrable
void InstrStopNode(Instrumentation *instr, double nTuples)
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
#define FKCONSTR_MATCH_SIMPLE
#define BUFFER_LOCK_UNLOCK
JunkFilter * ri_junkFilter
void * stringToNode(char *str)
#define TRIGGER_FOR_DELETE(type)
ExprState * ExecPrepareExpr(Expr *node, EState *estate)
struct AfterTriggerEventDataOneCtid AfterTriggerEventDataOneCtid
bool ExecIRDeleteTriggers(EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple)
int RI_FKey_trigger_type(Oid tgfoid)
void MemoryContextDelete(MemoryContext context)
Datum namein(PG_FUNCTION_ARGS)
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate)
#define AFTER_TRIGGER_FDW_REUSE
#define TriggerOidIndexId
#define AFTER_TRIGGER_INITDEFERRED
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
int errhint(const char *fmt,...)
void ExecBSDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
void systable_endscan(SysScanDesc sysscan)
static Tuplestorestate * GetCurrentFDWTuplestore(void)
#define fastgetattr(tup, attnum, tupleDesc, isnull)
MemoryContext TopTransactionContext
bool IsSystemRelation(Relation relation)
const char * quote_identifier(const char *ident)
ItemPointerData ate_ctid2
#define TRIGGER_TYPE_DELETE
bool equal(const void *a, const void *b)
#define RelationGetDescr(relation)
#define TRIGGER_EVENT_DELETE
SetConstraintStateData * SetConstraintState
TupleTableSlot * es_trig_newtup_slot
#define ObjectIdAttributeNumber
HTSU_Result heap_lock_tuple(Relation relation, HeapTuple tuple, CommandId cid, LockTupleMode mode, LockWaitPolicy wait_policy, bool follow_updates, Buffer *buffer, HeapUpdateFailureData *hufd)
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool missing_ok, bool nowait, RangeVarGetRelidCallback callback, void *callback_arg)
#define AFTER_TRIGGER_DEFERRABLE
ResourceOwner TopTransactionResourceOwner
void ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
#define PointerGetDatum(X)
HeapTupleHeaderData * HeapTupleHeader
#define RangeVarGetRelid(relation, lockmode, missing_ok)
bool heap_fetch(Relation relation, Snapshot snapshot, HeapTuple tuple, Buffer *userbuf, bool keep_buf, Relation stats_relation)
#define Anum_pg_trigger_tgconstraint
#define FKCONSTR_ACTION_NOACTION
#define ProcedureRelationId
ResourceOwner CurrentResourceOwner
#define AFTER_TRIGGER_DONE
#define TRIGGER_TYPE_MATCHES(type, level, timing, event)
char * pstrdup(const char *in)
#define RelationRelationId
TupleTableSlot * EvalPlanQual(EState *estate, EPQState *epqstate, Relation relation, Index rti, int lockmode, ItemPointer tid, TransactionId priorXmax)
int2vector * buildint2vector(const int16 *int2s, int n)
#define FKCONSTR_ACTION_SETDEFAULT
#define CHUNK_DATA_START(cptr)
ObjectAddress CreateTrigger(CreateTrigStmt *stmt, const char *queryString, Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid, bool isInternal)
SetConstraintTriggerData trigstates[FLEXIBLE_ARRAY_MEMBER]
struct AfterTriggerSharedData AfterTriggerSharedData
TupleTableSlot * ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, TupleTableSlot *slot)
#define Anum_pg_trigger_tgqual
TupleTableSlot * ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
bool trig_insert_after_statement
struct AfterTriggersData AfterTriggersData
static int MyTriggerDepth
#define AFTER_TRIGGER_TUP_BITS
void AfterTriggerSetState(ConstraintsSetStmt *stmt)
#define TRIGGER_CLEAR_TYPE(type)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
#define IsolationUsesXactSnapshot()
#define PG_RETURN_INT32(x)
#define DEFTRIG_INITALLOC
#define Anum_pg_trigger_tgtype
Instrumentation * ri_TrigInstrument
#define for_each_event_chunk(eptr, cptr, evtlist)
#define Anum_pg_trigger_tgnargs
struct SetConstraintTriggerData SetConstraintTriggerData
int errcode(int sqlerrcode)
int namestrcmp(Name name, const char *str)
void relation_close(Relation relation, LOCKMODE lockmode)
bool trig_update_before_statement
static SetConstraintState SetConstraintStateAddItem(SetConstraintState state, Oid tgoid, bool tgisdeferred)
AfterTriggerEventChunk * tail
static bool afterTriggerInvokeEvents(AfterTriggerEventList *events, CommandId firing_id, EState *estate, bool delete_ok)
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define FirstLowInvalidHeapAttributeNumber
void MemoryContextReset(MemoryContext context)
static bool afterTriggerCheckState(AfterTriggerShared evtshared)
struct AfterTriggerEventData AfterTriggerEventData
void ReleaseBuffer(Buffer buffer)
void PopActiveSnapshot(void)
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
List * pull_var_clause(Node *node, int flags)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
#define DirectFunctionCall1(func, arg1)
List * list_delete_ptr(List *list, void *datum)
#define Anum_pg_constraint_conname
void heap_freetuple(HeapTuple htup)
int namestrcpy(Name name, const char *str)
DestReceiver * None_Receiver
List * lappend_oid(List *list, Oid datum)
#define Anum_pg_trigger_tgisinternal
Snapshot GetTransactionSnapshot(void)
#define OidIsValid(objectId)
#define TRIGGER_EVENT_OPMASK
#define TRIGGER_FIRES_ON_ORIGIN
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
int SessionReplicationRole
#define ALLOCSET_DEFAULT_MINSIZE
#define SearchSysCache1(cacheId, key1)
Oid get_func_rettype(Oid funcid)
bool IsSystemClass(Oid relid, Form_pg_class reltuple)
int errdetail_internal(const char *fmt,...)
#define SESSION_REPLICATION_ROLE_ORIGIN
TupleTableSlot * ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple, TupleTableSlot *slot)
ParseState * make_parsestate(ParseState *parentParseState)
void * copyObject(const void *from)
#define TriggerRelidNameIndexId
#define GetTriggerSharedData(evt)
#define HeapTupleSetOid(tuple, oid)
#define for_each_event(eptr, cptr)
void assign_expr_collations(ParseState *pstate, Node *expr)
Alias * makeAlias(const char *aliasname, List *colnames)
bool trig_insert_instead_row
void FreeExecutorState(EState *estate)
#define GetPerTupleExprContext(estate)
#define TRIGGER_TYPE_INSTEAD
Datum pg_trigger_depth(PG_FUNCTION_ARGS)
struct AfterTriggerEventChunk * next
HeapTuple systable_getnext(SysScanDesc sysscan)
#define TRIGGER_FOR_ROW(type)
#define ItemIdGetLength(itemId)
void pfree(void *pointer)
MemoryContext es_query_cxt
void ExecBSTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
void appendStringInfo(StringInfo str, const char *fmt,...)
List * make_ands_implicit(Expr *clause)
void AfterTriggerEndXact(bool isCommit)
#define ObjectIdGetDatum(X)
#define TRIGGER_EVENT_INSTEAD
#define DatumGetCString(X)
#define TRIGGER_TYPE_AFTER
SetConstraintState * state_stack
ItemPointerData ate_ctid1
void InstrStartNode(Instrumentation *instr)
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Datum byteain(PG_FUNCTION_ARGS)
void ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple, HeapTuple newtuple, List *recheckIndexes)
#define DatumGetByteaP(X)
char * get_database_name(Oid dbid)
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
static void afterTriggerFreeEventList(AfterTriggerEventList *events)
void appendStringInfoString(StringInfo str, const char *s)
struct AfterTriggerEventChunk AfterTriggerEventChunk
bool trig_delete_after_row
#define TRIGGER_EVENT_BEFORE
void ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo)
#define TRIGGER_SETT_ROW(type)
#define FunctionCallInvoke(fcinfo)
void PushActiveSnapshot(Snapshot snap)
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
int errdetail(const char *fmt,...)
bool trig_truncate_before_statement
#define CStringGetDatum(X)
#define SizeofTriggerEvent(evt)
void ExecASTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
bool trig_update_after_statement
TupleTableSlot * ecxt_innertuple
TupleTableSlot * es_trig_oldtup_slot
bool trig_delete_before_statement
bool trig_update_before_row
bool ExecQual(List *qual, ExprContext *econtext, bool resultForNull)
#define RelationGetRelationName(relation)
bool trig_truncate_after_statement
#define RELKIND_FOREIGN_TABLE
#define TriggerConstraintIndexId
bool trig_insert_after_row
MemoryContext CurrentMemoryContext
const char * p_sourcetext
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc)
#define TRIGGER_FOR_BEFORE(type)
static void ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
TupleTableSlot * es_trig_tuple_slot
static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, int event, bool row_trigger, HeapTuple oldtup, HeapTuple newtup, List *recheckIndexes, Bitmapset *modifiedCols)
#define BufferGetPage(buffer)
#define AFTER_TRIGGER_1CTID
#define ereport(elevel, rest)
#define InvokeObjectPostAlterHook(classId, objectId, subId)
ObjectAddress renametrig(RenameStmt *stmt)
#define AFTER_TRIGGER_2CTID
MemoryContext TopMemoryContext
TriggerDesc * ri_TrigDesc
void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace)
EState * CreateExecutorState(void)
#define FKCONSTR_ACTION_CASCADE
bool trig_update_after_row
void EnableDisableTrigger(Relation rel, const char *tgname, char fires_when, bool skip_system)
List * lappend(List *list, void *datum)
struct AfterTriggerEventDataZeroCtids AfterTriggerEventDataZeroCtids
bool trig_update_instead_row
#define Anum_pg_trigger_tgrelid
#define AFTER_TRIGGER_OFFSET
ResultRelInfo * ExecGetTriggerResultRel(EState *estate, Oid relid)
void appendStringInfoChar(StringInfo str, char ch)
void initStringInfo(StringInfo str)
#define PageGetItemId(page, offsetNumber)
char * NameListToString(List *names)
TupleDesc tts_tupleDescriptor
void ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple)
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
#define FKCONSTR_MATCH_FULL
#define Anum_pg_trigger_tgconstrindid
void FreeTriggerDesc(TriggerDesc *trigdesc)
List * es_trig_target_relations
#define TextDatumGetCString(d)
bool trig_insert_before_row
bool trig_delete_instead_row
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
void * palloc0(Size size)
bool RI_FKey_fk_upd_check_required(Trigger *trigger, Relation fk_rel, HeapTuple old_row, HeapTuple new_row)
TupleTableSlot * ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
#define SESSION_REPLICATION_ROLE_REPLICA
static SetConstraintState SetConstraintStateCreate(int numalloc)
void ReleaseSysCache(HeapTuple tuple)
#define TRIGGER_TYPE_TRUNCATE
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
void ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo)
#define list_make1_oid(x1)
Oid simple_heap_insert(Relation relation, HeapTuple tup)
void LockBuffer(Buffer buffer, int mode)
#define Anum_pg_trigger_tgenabled
Oid GetNewOid(Relation relation)
#define Anum_pg_constraint_connamespace
Relation heap_open(Oid relationId, LOCKMODE lockmode)
void SetFunctionReturnType(Oid funcOid, Oid newRetType)
#define TRIGGER_FOR_TRUNCATE(type)
#define InvokeObjectPostCreateHookArg(classId, objectId, subId, is_internal)
void * MemoryContextAllocZero(MemoryContext context, Size size)
AfterTriggerEventList * events_stack
Relation heap_openrv(const RangeVar *relation, LOCKMODE lockmode)
bool allowSystemTableMods
#define TRIGGER_TYPE_UPDATE
void AfterTriggerFireDeferred(void)
static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo, Trigger *trigger, TriggerEvent event, Bitmapset *modifiedCols, HeapTuple oldtup, HeapTuple newtup)
#define ConstraintNameNspIndexId
int GetCurrentTransactionNestLevel(void)
static void AfterTriggerEnlargeQueryState(void)
void AfterTriggerBeginQuery(void)
#define GetUpdatedColumns(relinfo, estate)
#define for_each_chunk(cptr, evtlist)
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)
FormData_pg_constraint * Form_pg_constraint
TupleTableSlot * ecxt_outertuple
bool list_member_oid(const List *list, Oid datum)
#define HeapTupleIsValid(tuple)
bool ExecBRDeleteTriggers(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tupleid, HeapTuple fdw_trigtuple)
int attnameAttNum(Relation rd, const char *attname, bool sysColOK)
TriggerDesc * CopyTriggerDesc(TriggerDesc *trigdesc)
#define Assert(condition)
#define Anum_pg_trigger_tgargs
LockTupleMode ExecUpdateLockMode(EState *estate, ResultRelInfo *relinfo)
#define ShareRowExclusiveLock
void CatalogUpdateIndexes(Relation heapRel, HeapTuple heapTuple)
#define Anum_pg_trigger_tgconstrrelid
bool pg_class_ownercheck(Oid class_oid, Oid roleid)
bool trig_delete_after_statement
Node * transformWhereClause(ParseState *pstate, Node *clause, ParseExprKind exprKind, const char *constructName)
#define ItemIdIsNormal(itemId)
#define Anum_pg_trigger_tgname
static void afterTriggerAddEvent(AfterTriggerEventList *events, AfterTriggerEvent event, AfterTriggerShared evtshared)
#define TriggerRelationId
#define TRIGGER_EVENT_TRUNCATE
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
#define TRIGGER_FOR_INSERT(type)
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
bool RI_FKey_pk_upd_check_required(Trigger *trigger, Relation pk_rel, HeapTuple old_row, HeapTuple new_row)
bool trig_insert_before_statement
static int list_length(const List *l)
int parser_errposition(ParseState *pstate, int location)
void simple_heap_delete(Relation relation, ItemPointer tid)
Oid get_trigger_oid(Oid relid, const char *trigname, bool missing_ok)
void simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
FormData_pg_trigger * Form_pg_trigger
void tuplestore_end(Tuplestorestate *state)
bool AfterTriggerPendingOnRel(Oid relid)
RangeTblEntry * addRangeTableEntryForRelation(ParseState *pstate, Relation rel, Alias *alias, bool inh, bool inFromCl)
#define TRIGGER_TYPE_INSERT
#define ItemPointerGetOffsetNumber(pointer)
static void afterTriggerRestoreEventList(AfterTriggerEventList *events, const AfterTriggerEventList *old_events)
#define AFTER_TRIGGER_FDW_FETCH
HeapTuple ExecMaterializeSlot(TupleTableSlot *slot)
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
void * repalloc(void *pointer, Size size)
void ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple, List *recheckIndexes)
#define TRIGGER_EVENT_UPDATE
#define InvalidAttrNumber
struct AfterTriggerEventData * AfterTriggerEvent
#define ObjectAddressSet(addr, class_id, object_id)
#define GetPerTupleMemoryContext(estate)
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
void AfterTriggerEndSubXact(bool isCommit)
#define TRIGGER_FIRES_ON_REPLICA
#define DatumGetPointer(X)
void pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu, bool finalize)
void CacheInvalidateRelcache(Relation relation)
struct AfterTriggerEventList AfterTriggerEventList
#define TRIGGER_TYPE_BEFORE
#define TRIGGER_EVENT_INSERT
AfterTriggerEventChunk * head
Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes, bool noError)
bool IsSubTransaction(void)
static Datum values[MAXATTR]
void pgstat_init_function_usage(FunctionCallInfoData *fcinfo, PgStat_FunctionCallUsage *fcu)
static void SetTriggerFlags(TriggerDesc *trigdesc, Trigger *trigger)
FormData_pg_class * Form_pg_class
#define SearchSysCacheCopy1(cacheId, key1)
struct SetConstraintStateData SetConstraintStateData
#define AccessExclusiveLock
void ExecBSUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
void RelationBuildTriggers(Relation relation)
#define ItemPointerSetInvalid(pointer)
void AfterTriggerEndQuery(EState *estate)
static HeapTuple GetTupleForTrigger(EState *estate, EPQState *epqstate, ResultRelInfo *relinfo, ItemPointer tid, LockTupleMode lockmode, TupleTableSlot **newSlot)
const ObjectAddress InvalidObjectAddress
static void RangeVarCallbackForRenameTrigger(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg)
int errmsg(const char *fmt,...)
void * MemoryContextAlloc(MemoryContext context, Size size)
void list_free(List *list)
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
#define ALLOCSET_DEFAULT_INITSIZE
struct SetConstraintTriggerData * SetConstraintTrigger
#define AFTER_TRIGGER_IN_PROGRESS
static bool afterTriggerMarkEvents(AfterTriggerEventList *events, AfterTriggerEventList *move_list, bool immediate_only)
void ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
#define BUFFER_LOCK_SHARE
#define CStringGetTextDatum(s)
char * nodeToString(const void *obj)
Tuplestorestate ** fdw_tuplestores
Relation relation_open(Oid relationId, LOCKMODE lockmode)
#define FKCONSTR_ACTION_RESTRICT
void AfterTriggerBeginXact(void)
AfterTriggerEventList events
#define ALLOCSET_DEFAULT_MAXSIZE
#define ConstraintRelationId
AfterTriggerEventList * query_stack
TupleTableSlot * ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TupleTableSlot *slot)
void AfterTriggerBeginSubXact(void)
#define ItemPointerGetBlockNumber(pointer)
#define CONSTRAINT_TRIGGER
Datum nameout(PG_FUNCTION_ARGS)
static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata, int tgindx, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context)
#define HeapTupleGetOid(tuple)
void LockRelationOid(Oid relid, LOCKMODE lockmode)
#define TRIGGER_TYPE_STATEMENT
void free_parsestate(ParseState *pstate)
ItemPointerData ate_ctid1
#define FKCONSTR_ACTION_SETNULL
#define ERRCODE_DUPLICATE_OBJECT
char * get_rel_name(Oid relid)
bool bms_is_member(int x, const Bitmapset *a)
#define TRIGGER_FIRED_BY_UPDATE(event)
List * fetch_search_path(bool includeImplicit)
static AfterTriggersData afterTriggers
#define RelationGetRelid(relation)
Oid CreateConstraintEntry(const char *constraintName, Oid constraintNamespace, char constraintType, bool isDeferrable, bool isDeferred, bool isValidated, Oid relId, const int16 *constraintKey, int constraintNKeys, Oid domainId, Oid indexRelId, Oid foreignRelId, const int16 *foreignKey, const Oid *pfEqOp, const Oid *ppEqOp, const Oid *ffEqOp, int foreignNKeys, char foreignUpdateType, char foreignDeleteType, char foreignMatchType, const Oid *exclOp, Node *conExpr, const char *conBin, const char *conSrc, bool conIsLocal, int conInhCount, bool conNoInherit, bool is_internal)
void ExecCloseIndices(ResultRelInfo *resultRelInfo)
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
#define BTEqualStrategyNumber
struct AfterTriggerSharedData * AfterTriggerShared
#define offsetof(type, field)
static void AfterTriggerExecute(AfterTriggerEvent event, Relation rel, TriggerDesc *trigdesc, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context, TupleTableSlot *trig_tuple_slot1, TupleTableSlot *trig_tuple_slot2)
#define PageGetItem(page, itemId)
FmgrInfo * ri_TrigFunctions
#define Anum_pg_trigger_tgfoid
#define Anum_pg_trigger_tginitdeferred
#define Anum_pg_trigger_tgattr
#define ItemPointerCopy(fromPointer, toPointer)
bool trig_delete_before_row
MemoryContext CacheMemoryContext
void ProcessUtility(Node *parsetree, const char *queryString, ProcessUtilityContext context, ParamListInfo params, DestReceiver *dest, char *completionTag)
#define TRIGGER_FOR_INSTEAD(type)
#define RelationGetNamespace(relation)
static SetConstraintState SetConstraintStateCopy(SetConstraintState state)