📄 trigger.c
字号:
} else t[i] = NULL; } n = newdesc->n_after_statement; t = newdesc->tg_after_statement; for (i = 0; i < TRIGGER_NUM_EVENT_CLASSES; i++) { if (n[i] > 0) { tnew = (int *) palloc(n[i] * sizeof(int)); memcpy(tnew, t[i], n[i] * sizeof(int)); t[i] = tnew; } else t[i] = NULL; } return newdesc;}/* * Free a TriggerDesc data structure. */voidFreeTriggerDesc(TriggerDesc *trigdesc){ int **t; Trigger *trigger; int i; if (trigdesc == NULL) return; t = trigdesc->tg_before_statement; for (i = 0; i < TRIGGER_NUM_EVENT_CLASSES; i++) if (t[i] != NULL) pfree(t[i]); t = trigdesc->tg_before_row; for (i = 0; i < TRIGGER_NUM_EVENT_CLASSES; i++) if (t[i] != NULL) pfree(t[i]); t = trigdesc->tg_after_row; for (i = 0; i < TRIGGER_NUM_EVENT_CLASSES; i++) if (t[i] != NULL) pfree(t[i]); t = trigdesc->tg_after_statement; for (i = 0; i < TRIGGER_NUM_EVENT_CLASSES; i++) if (t[i] != NULL) pfree(t[i]); trigger = trigdesc->triggers; for (i = 0; i < trigdesc->numtriggers; i++) { pfree(trigger->tgname); if (trigger->tgnargs > 0) { while (--(trigger->tgnargs) >= 0) pfree(trigger->tgargs[trigger->tgnargs]); pfree(trigger->tgargs); } trigger++; } pfree(trigdesc->triggers); pfree(trigdesc);}/* * Compare two TriggerDesc structures for logical equality. */#ifdef NOT_USEDboolequalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2){ int i, j; /* * We need not examine the "index" data, just the trigger array * itself; if we have the same triggers with the same types, the * derived index data should match. * * As of 7.3 we assume trigger set ordering is significant in the * comparison; so we just compare corresponding slots of the two sets. */ if (trigdesc1 != NULL) { if (trigdesc2 == NULL) return false; if (trigdesc1->numtriggers != trigdesc2->numtriggers) return false; for (i = 0; i < trigdesc1->numtriggers; i++) { Trigger *trig1 = trigdesc1->triggers + i; Trigger *trig2 = trigdesc2->triggers + i; if (trig1->tgoid != trig2->tgoid) return false; if (strcmp(trig1->tgname, trig2->tgname) != 0) return false; if (trig1->tgfoid != trig2->tgfoid) return false; if (trig1->tgtype != trig2->tgtype) return false; if (trig1->tgenabled != trig2->tgenabled) return false; if (trig1->tgisconstraint != trig2->tgisconstraint) return false; if (trig1->tgconstrrelid != trig2->tgconstrrelid) return false; if (trig1->tgdeferrable != trig2->tgdeferrable) return false; if (trig1->tginitdeferred != trig2->tginitdeferred) return false; if (trig1->tgnargs != trig2->tgnargs) return false; if (memcmp(trig1->tgattr, trig2->tgattr, sizeof(trig1->tgattr)) != 0) return false; for (j = 0; j < trig1->tgnargs; j++) if (strcmp(trig1->tgargs[j], trig2->tgargs[j]) != 0) return false; } } else if (trigdesc2 != NULL) return false; return true;}#endif /* NOT_USED *//* * Call a trigger function. * * trigdata: trigger descriptor. * finfo: possibly-cached call info for the function. * per_tuple_context: memory context to execute the function in. * * Returns the tuple (or NULL) as returned by the function. */static HeapTupleExecCallTriggerFunc(TriggerData *trigdata, FmgrInfo *finfo, MemoryContext per_tuple_context){ FunctionCallInfoData fcinfo; Datum result; MemoryContext oldContext; /* * We cache fmgr lookup info, to avoid making the lookup again on each * call. */ if (finfo->fn_oid == InvalidOid) fmgr_info(trigdata->tg_trigger->tgfoid, finfo); Assert(finfo->fn_oid == trigdata->tg_trigger->tgfoid); /* * Do the function evaluation in the per-tuple memory context, so that * leaked memory will be reclaimed once per tuple. Note in particular * that any new tuple created by the trigger function will live till * the end of the tuple cycle. */ oldContext = MemoryContextSwitchTo(per_tuple_context); /* * Call the function, passing no arguments but setting a context. */ MemSet(&fcinfo, 0, sizeof(fcinfo)); fcinfo.flinfo = finfo; fcinfo.context = (Node *) trigdata; result = FunctionCallInvoke(&fcinfo); MemoryContextSwitchTo(oldContext); /* * Trigger protocol allows function to return a null pointer, but NOT * to set the isnull result flag. */ if (fcinfo.isnull) ereport(ERROR, (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), errmsg("trigger function %u returned null value", fcinfo.flinfo->fn_oid))); return (HeapTuple) DatumGetPointer(result);}voidExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo){ TriggerDesc *trigdesc; int ntrigs; int *tgindx; int i; TriggerData LocTriggerData; trigdesc = relinfo->ri_TrigDesc; if (trigdesc == NULL) return; ntrigs = trigdesc->n_before_statement[TRIGGER_EVENT_INSERT]; tgindx = trigdesc->tg_before_statement[TRIGGER_EVENT_INSERT]; if (ntrigs == 0) return; /* Allocate cache space for fmgr lookup info, if not done yet */ if (relinfo->ri_TrigFunctions == NULL) relinfo->ri_TrigFunctions = (FmgrInfo *) palloc0(trigdesc->numtriggers * sizeof(FmgrInfo)); LocTriggerData.type = T_TriggerData; LocTriggerData.tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_BEFORE; LocTriggerData.tg_relation = relinfo->ri_RelationDesc; LocTriggerData.tg_newtuple = NULL; LocTriggerData.tg_trigtuple = NULL; for (i = 0; i < ntrigs; i++) { Trigger *trigger = &trigdesc->triggers[tgindx[i]]; HeapTuple newtuple; if (!trigger->tgenabled) continue; LocTriggerData.tg_trigger = trigger; newtuple = ExecCallTriggerFunc(&LocTriggerData, relinfo->ri_TrigFunctions + tgindx[i], GetPerTupleMemoryContext(estate)); if (newtuple) ereport(ERROR, (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), errmsg("BEFORE STATEMENT trigger cannot return a value"))); }}voidExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo){ TriggerDesc *trigdesc = relinfo->ri_TrigDesc; if (trigdesc && trigdesc->n_after_statement[TRIGGER_EVENT_INSERT] > 0) DeferredTriggerSaveEvent(relinfo, TRIGGER_EVENT_INSERT, false, NULL, NULL);}HeapTupleExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple){ TriggerDesc *trigdesc = relinfo->ri_TrigDesc; int ntrigs = trigdesc->n_before_row[TRIGGER_EVENT_INSERT]; int *tgindx = trigdesc->tg_before_row[TRIGGER_EVENT_INSERT]; HeapTuple newtuple = trigtuple; HeapTuple oldtuple; TriggerData LocTriggerData; int i; /* Allocate cache space for fmgr lookup info, if not done yet */ if (relinfo->ri_TrigFunctions == NULL) relinfo->ri_TrigFunctions = (FmgrInfo *) palloc0(trigdesc->numtriggers * sizeof(FmgrInfo)); LocTriggerData.type = T_TriggerData; LocTriggerData.tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE; LocTriggerData.tg_relation = relinfo->ri_RelationDesc; LocTriggerData.tg_newtuple = NULL; for (i = 0; i < ntrigs; i++) { Trigger *trigger = &trigdesc->triggers[tgindx[i]]; if (!trigger->tgenabled) continue; LocTriggerData.tg_trigtuple = oldtuple = newtuple; LocTriggerData.tg_trigger = trigger; newtuple = ExecCallTriggerFunc(&LocTriggerData, relinfo->ri_TrigFunctions + tgindx[i], GetPerTupleMemoryContext(estate)); if (oldtuple != newtuple && oldtuple != trigtuple) heap_freetuple(oldtuple); if (newtuple == NULL) break; } return newtuple;}voidExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo, HeapTuple trigtuple){ TriggerDesc *trigdesc = relinfo->ri_TrigDesc; if (trigdesc && trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0) DeferredTriggerSaveEvent(relinfo, TRIGGER_EVENT_INSERT, true, NULL, trigtuple);}voidExecBSDeleteTriggers(EState *estate, ResultRelInfo *relinfo){ TriggerDesc *trigdesc; int ntrigs; int *tgindx; int i; TriggerData LocTriggerData; trigdesc = relinfo->ri_TrigDesc; if (trigdesc == NULL) return; ntrigs = trigdesc->n_before_statement[TRIGGER_EVENT_DELETE]; tgindx = trigdesc->tg_before_statement[TRIGGER_EVENT_DELETE]; if (ntrigs == 0) return; /* Allocate cache space for fmgr lookup info, if not done yet */ if (relinfo->ri_TrigFunctions == NULL) relinfo->ri_TrigFunctions = (FmgrInfo *) palloc0(trigdesc->numtriggers * sizeof(FmgrInfo)); LocTriggerData.type = T_TriggerData; LocTriggerData.tg_event = TRIGGER_EVENT_DELETE | TRIGGER_EVENT_BEFORE; LocTriggerData.tg_relation = relinfo->ri_RelationDesc; LocTriggerData.tg_newtuple = NULL; LocTriggerData.tg_trigtuple = NULL; for (i = 0; i < ntrigs; i++) { Trigger *trigger = &trigdesc->triggers[tgindx[i]]; HeapTuple newtuple; if (!trigger->tgenabled) continue; LocTriggerData.tg_trigger = trigger; newtuple = ExecCallTriggerFunc(&LocTriggerData, relinfo->ri_TrigFunctions + tgindx[i], GetPerTupleMemoryContext(estate)); if (newtuple) ereport(ERROR, (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), errmsg("BEFORE STATEMENT trigger cannot return a value"))); }}voidExecASDeleteTriggers(EState *estate, ResultRelInfo *relinfo){ TriggerDesc *trigdesc = relinfo->ri_TrigDesc; if (trigdesc && trigdesc->n_after_statement[TRIGGER_EVENT_DELETE] > 0) DeferredTriggerSaveEvent(relinfo, TRIGGER_EVENT_DELETE, false, NULL, NULL);}boolExecBRDeleteTriggers(EState *estate, ResultRelInfo *relinfo, ItemPointer tupleid, CommandId cid){ TriggerDesc *trigdesc = relinfo->ri_TrigDesc; int ntrigs = trigdesc->n_before_row[TRIGGER_EVENT_DELETE]; int *tgindx = trigdesc->tg_before_row[TRIGGER_EVENT_DELETE]; TriggerData LocTriggerData; HeapTuple trigtuple; HeapTuple newtuple = NULL; TupleTableSlot *newSlot; int i; trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, cid, &newSlot); if (trigtuple == NULL) return false; /* Allocate cache space for fmgr lookup info, if not done yet */ if (relinfo->ri_TrigFunctions == NULL) relinfo->ri_TrigFunctions = (FmgrInfo *) palloc0(trigdesc->numtriggers * sizeof(FmgrInfo)); LocTriggerData.type = T_TriggerData; LocTriggerData.tg_event = TRIGGER_EVENT_DELETE | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE; LocTriggerData.tg_relation = relinfo->ri_RelationDesc; LocTriggerData.tg_newtuple = NULL; for (i = 0; i < ntrigs; i++) { Trigger *trigger = &trigdesc->triggers[tgindx[i]]; if (!trigger->tgenabled) continue; LocTriggerData.tg_trigtuple = trigtuple; LocTriggerData.tg_trigger = trigger; newtuple = ExecCallTriggerFunc(&LocTriggerData, relinfo->ri_TrigFunctions + tgindx[i], GetPerTupleMemoryContext(estate)); if (newtuple == NULL) break; if (newtuple != trigtuple) heap_freetuple(newtuple); } heap_freetuple(trigtuple); return (newtuple == NULL) ? false : true;}voidExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo, ItemPointer tupleid){ TriggerDesc *trigdesc = relinfo->ri_TrigDesc; if (trigdesc && trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0) { HeapTuple trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, (CommandId) 0, NULL); DeferredTriggerSaveEvent(relinfo, TRIGGER_EVENT_DELETE, true, trigtuple, NULL); heap_freetuple(trigtuple); }}voidExecBSUpdateTriggers(EState *estate, ResultRelInfo *relinfo){ TriggerDesc *trigdesc; int ntrigs; int *tgindx; int i; TriggerData LocTriggerData; trigdesc = relinfo->ri_TrigDesc; if (trigdesc == NULL) return; ntrigs = trigdesc->n_before_statement[TRIGGER_EVENT_UPDATE]; tgindx = trigdesc->tg_before_statement[TRIGGER_EVENT_UPDATE]; if (ntrigs == 0) return; /* Allocate cache space for fmgr lookup info, if not done yet */ if (relinfo->ri_TrigFunctions == NULL) relinfo->ri_TrigFunctions = (FmgrInfo *) palloc0(trigdesc->numtriggers * sizeof(FmgrInfo)); LocTriggerData.type = T_TriggerData; LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE | TRIGGER_EVENT_BEFORE; LocTriggerData.tg_relation = relinfo->ri_RelationDesc; LocTriggerData.tg_newtuple = NULL; LocTriggerData.tg_trigtuple = NULL; for (i = 0; i < ntrigs; i++) { Trigger *trigger = &trigdesc->triggers[tgindx[i]]; HeapTuple newtuple; if (!trigger->tgenabled) continue; LocTriggerData.tg_trigger = trigger; newtuple = ExecCallTriggerFunc(&LocTriggerData, relinfo->ri_TrigFunctions + tgindx[i], GetPerTupleMemoryContext(estate)); if (newtuple) ereport(ERROR, (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), errmsg("BEFORE STATEMENT trigger cannot return a value"))); }}voidExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo){ TriggerDesc *trigdesc = relinfo->ri_TrigDesc; if (trigdesc && trigdesc->n_after_statement[TRIGGER_EVENT_UPDATE] > 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -