📄 trigger.c
字号:
* possible size (trigdesc->numtriggers) if it's used at all. This does * not waste space permanently since we're only building a temporary * trigdesc at this point. */static voidInsertTrigger(TriggerDesc *trigdesc, Trigger *trigger, int indx){ uint16 *n; int **t, **tp; if (TRIGGER_FOR_ROW(trigger->tgtype)) { /* ROW trigger */ if (TRIGGER_FOR_BEFORE(trigger->tgtype)) { n = trigdesc->n_before_row; t = trigdesc->tg_before_row; } else { n = trigdesc->n_after_row; t = trigdesc->tg_after_row; } } else { /* STATEMENT trigger */ if (TRIGGER_FOR_BEFORE(trigger->tgtype)) { n = trigdesc->n_before_statement; t = trigdesc->tg_before_statement; } else { n = trigdesc->n_after_statement; t = trigdesc->tg_after_statement; } } if (TRIGGER_FOR_INSERT(trigger->tgtype)) { tp = &(t[TRIGGER_EVENT_INSERT]); if (*tp == NULL) *tp = (int *) palloc(trigdesc->numtriggers * sizeof(int)); (*tp)[n[TRIGGER_EVENT_INSERT]] = indx; (n[TRIGGER_EVENT_INSERT])++; } if (TRIGGER_FOR_DELETE(trigger->tgtype)) { tp = &(t[TRIGGER_EVENT_DELETE]); if (*tp == NULL) *tp = (int *) palloc(trigdesc->numtriggers * sizeof(int)); (*tp)[n[TRIGGER_EVENT_DELETE]] = indx; (n[TRIGGER_EVENT_DELETE])++; } if (TRIGGER_FOR_UPDATE(trigger->tgtype)) { tp = &(t[TRIGGER_EVENT_UPDATE]); if (*tp == NULL) *tp = (int *) palloc(trigdesc->numtriggers * sizeof(int)); (*tp)[n[TRIGGER_EVENT_UPDATE]] = indx; (n[TRIGGER_EVENT_UPDATE])++; }}/* * Copy a TriggerDesc data structure. * * The copy is allocated in the current memory context. */TriggerDesc *CopyTriggerDesc(TriggerDesc *trigdesc){ TriggerDesc *newdesc; uint16 *n; int **t, *tnew; Trigger *trigger; int i; if (trigdesc == NULL || trigdesc->numtriggers <= 0) return NULL; newdesc = (TriggerDesc *) palloc(sizeof(TriggerDesc)); memcpy(newdesc, trigdesc, sizeof(TriggerDesc)); trigger = (Trigger *) palloc(trigdesc->numtriggers * sizeof(Trigger)); memcpy(trigger, trigdesc->triggers, trigdesc->numtriggers * sizeof(Trigger)); newdesc->triggers = trigger; for (i = 0; i < trigdesc->numtriggers; i++) { trigger->tgname = pstrdup(trigger->tgname); if (trigger->tgnattr > 0) { int2 *newattr; newattr = (int2 *) palloc(trigger->tgnattr * sizeof(int2)); memcpy(newattr, trigger->tgattr, trigger->tgnattr * sizeof(int2)); trigger->tgattr = newattr; } if (trigger->tgnargs > 0) { char **newargs; int16 j; newargs = (char **) palloc(trigger->tgnargs * sizeof(char *)); for (j = 0; j < trigger->tgnargs; j++) newargs[j] = pstrdup(trigger->tgargs[j]); trigger->tgargs = newargs; } trigger++; } n = newdesc->n_before_statement; t = newdesc->tg_before_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; } n = newdesc->n_before_row; t = newdesc->tg_before_row; 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; } n = newdesc->n_after_row; t = newdesc->tg_after_row; 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; } 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->tgnattr > 0) pfree(trigger->tgattr); 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 (trig1->tgnattr != trig2->tgnattr) return false; if (trig1->tgnattr > 0 && memcmp(trig1->tgattr, trig2->tgattr, trig1->tgnattr * sizeof(int2)) != 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. * tgindx: trigger's index in finfo and instr arrays. * finfo: array of cached trigger function call information. * instr: optional array of EXPLAIN ANALYZE instrumentation state. * per_tuple_context: memory context to execute the function in. * * Returns the tuple (or NULL) as returned by the function. */static HeapTupleExecCallTriggerFunc(TriggerData *trigdata, int tgindx, FmgrInfo *finfo, Instrumentation *instr, MemoryContext per_tuple_context){ FunctionCallInfoData fcinfo; Datum result; MemoryContext oldContext; finfo += tgindx; /* * 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); /* * If doing EXPLAIN ANALYZE, start charging time to this trigger. */ if (instr) InstrStartNode(instr + tgindx); /* * 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. */ InitFunctionCallInfoData(fcinfo, finfo, 0, (Node *) trigdata, NULL); 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))); /* * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count * one "tuple returned" (really the number of firings). */ if (instr) InstrStopNode(instr + tgindx, true); 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; LocTriggerData.type = T_TriggerData; LocTriggerData.tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_BEFORE; LocTriggerData.tg_relation = relinfo->ri_RelationDesc; LocTriggerData.tg_trigtuple = NULL; LocTriggerData.tg_newtuple = NULL; LocTriggerData.tg_trigtuplebuf = InvalidBuffer; LocTriggerData.tg_newtuplebuf = InvalidBuffer; 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, tgindx[i], relinfo->ri_TrigFunctions, relinfo->ri_TrigInstrument, 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) AfterTriggerSaveEvent(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; 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; LocTriggerData.tg_newtuplebuf = InvalidBuffer; for (i = 0; i < ntrigs; i++) { Trigger *trigger = &trigdesc->triggers[tgindx[i]]; if (!trigger->tgenabled) continue; LocTriggerData.tg_trigtuple = oldtuple = newtuple; LocTriggerData.tg_trigtuplebuf = InvalidBuffer; LocTriggerData.tg_trigger = trigger; newtuple = ExecCallTriggerFunc(&LocTriggerData, tgindx[i], relinfo->ri_TrigFunctions, relinfo->ri_TrigInstrument, 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) AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_INSERT,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -