trigger.c
来自「关系型数据库 Postgresql 6.5.2」· C语言 代码 · 共 876 行 · 第 1/2 页
C
876 行
NAMEDATALEN, relation->rd_rel->relname.data); index_endscan(sd); pfree(sd); index_close(irel); heap_close(tgrel); /* Build trigdesc */ trigdesc->triggers = triggers; for (found = 0; found < ntrigs; found++) { build = &(triggers[found]); DescribeTrigger(trigdesc, build); } relation->trigdesc = trigdesc;}voidFreeTriggerDesc(Relation relation){ TriggerDesc *trigdesc = relation->trigdesc; Trigger ***t; Trigger *trigger; int i; if (trigdesc == NULL) return; t = trigdesc->tg_before_statement; for (i = 0; i < 3; i++) if (t[i] != NULL) pfree(t[i]); t = trigdesc->tg_before_row; for (i = 0; i < 3; i++) if (t[i] != NULL) pfree(t[i]); t = trigdesc->tg_after_row; for (i = 0; i < 3; i++) if (t[i] != NULL) pfree(t[i]); t = trigdesc->tg_after_statement; for (i = 0; i < 3; i++) if (t[i] != NULL) pfree(t[i]); trigger = trigdesc->triggers; for (i = 0; i < relation->rd_rel->reltriggers; 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); relation->trigdesc = NULL; return;}static voidDescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger){ uint16 *n; Trigger ***t, ***tp; if (TRIGGER_FOR_ROW(trigger->tgtype)) /* Is ROW/STATEMENT * 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 (NI) */ { 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 = (Trigger **) palloc(sizeof(Trigger *)); else *tp = (Trigger **) repalloc(*tp, (n[TRIGGER_EVENT_INSERT] + 1) * sizeof(Trigger *)); (*tp)[n[TRIGGER_EVENT_INSERT]] = trigger; (n[TRIGGER_EVENT_INSERT])++; } if (TRIGGER_FOR_DELETE(trigger->tgtype)) { tp = &(t[TRIGGER_EVENT_DELETE]); if (*tp == NULL) *tp = (Trigger **) palloc(sizeof(Trigger *)); else *tp = (Trigger **) repalloc(*tp, (n[TRIGGER_EVENT_DELETE] + 1) * sizeof(Trigger *)); (*tp)[n[TRIGGER_EVENT_DELETE]] = trigger; (n[TRIGGER_EVENT_DELETE])++; } if (TRIGGER_FOR_UPDATE(trigger->tgtype)) { tp = &(t[TRIGGER_EVENT_UPDATE]); if (*tp == NULL) *tp = (Trigger **) palloc(sizeof(Trigger *)); else *tp = (Trigger **) repalloc(*tp, (n[TRIGGER_EVENT_UPDATE] + 1) * sizeof(Trigger *)); (*tp)[n[TRIGGER_EVENT_UPDATE]] = trigger; (n[TRIGGER_EVENT_UPDATE])++; }}static HeapTupleExecCallTriggerFunc(Trigger *trigger){ if (trigger->tgfunc.fn_addr == NULL) fmgr_info(trigger->tgfoid, &trigger->tgfunc); if (trigger->tgfunc.fn_plhandler != NULL) { return (HeapTuple) (*(trigger->tgfunc.fn_plhandler)) (&trigger->tgfunc); } return (HeapTuple) ((*fmgr_faddr(&trigger->tgfunc)) ());}HeapTupleExecBRInsertTriggers(Relation rel, HeapTuple trigtuple){ TriggerData *SaveTriggerData; int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_INSERT]; Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_INSERT]; HeapTuple newtuple = trigtuple; HeapTuple oldtuple; int i; SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData)); SaveTriggerData->tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE; SaveTriggerData->tg_relation = rel; SaveTriggerData->tg_newtuple = NULL; for (i = 0; i < ntrigs; i++) { CurrentTriggerData = SaveTriggerData; CurrentTriggerData->tg_trigtuple = oldtuple = newtuple; CurrentTriggerData->tg_trigger = trigger[i]; newtuple = ExecCallTriggerFunc(trigger[i]); if (newtuple == NULL) break; else if (oldtuple != newtuple && oldtuple != trigtuple) pfree(oldtuple); } CurrentTriggerData = NULL; pfree(SaveTriggerData); return newtuple;}voidExecARInsertTriggers(Relation rel, HeapTuple trigtuple){ TriggerData *SaveTriggerData; int ntrigs = rel->trigdesc->n_after_row[TRIGGER_EVENT_INSERT]; Trigger **trigger = rel->trigdesc->tg_after_row[TRIGGER_EVENT_INSERT]; int i; SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData)); SaveTriggerData->tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_ROW; SaveTriggerData->tg_relation = rel; SaveTriggerData->tg_newtuple = NULL; for (i = 0; i < ntrigs; i++) { CurrentTriggerData = SaveTriggerData; CurrentTriggerData->tg_trigtuple = trigtuple; CurrentTriggerData->tg_trigger = trigger[i]; ExecCallTriggerFunc(trigger[i]); } CurrentTriggerData = NULL; pfree(SaveTriggerData); return;}boolExecBRDeleteTriggers(EState *estate, ItemPointer tupleid){ Relation rel = estate->es_result_relation_info->ri_RelationDesc; TriggerData *SaveTriggerData; int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_DELETE]; Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_DELETE]; HeapTuple trigtuple; HeapTuple newtuple = NULL; TupleTableSlot *newSlot; int i; trigtuple = GetTupleForTrigger(estate, tupleid, &newSlot); if (trigtuple == NULL) return false; SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData)); SaveTriggerData->tg_event = TRIGGER_EVENT_DELETE | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE; SaveTriggerData->tg_relation = rel; SaveTriggerData->tg_newtuple = NULL; for (i = 0; i < ntrigs; i++) { CurrentTriggerData = SaveTriggerData; CurrentTriggerData->tg_trigtuple = trigtuple; CurrentTriggerData->tg_trigger = trigger[i]; newtuple = ExecCallTriggerFunc(trigger[i]); if (newtuple == NULL) break; if (newtuple != trigtuple) pfree(newtuple); } CurrentTriggerData = NULL; pfree(SaveTriggerData); pfree(trigtuple); return (newtuple == NULL) ? false : true;}voidExecARDeleteTriggers(EState *estate, ItemPointer tupleid){ Relation rel = estate->es_result_relation_info->ri_RelationDesc; TriggerData *SaveTriggerData; int ntrigs = rel->trigdesc->n_after_row[TRIGGER_EVENT_DELETE]; Trigger **trigger = rel->trigdesc->tg_after_row[TRIGGER_EVENT_DELETE]; HeapTuple trigtuple; int i; trigtuple = GetTupleForTrigger(estate, tupleid, NULL); Assert(trigtuple != NULL); SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData)); SaveTriggerData->tg_event = TRIGGER_EVENT_DELETE | TRIGGER_EVENT_ROW; SaveTriggerData->tg_relation = rel; SaveTriggerData->tg_newtuple = NULL; for (i = 0; i < ntrigs; i++) { CurrentTriggerData = SaveTriggerData; CurrentTriggerData->tg_trigtuple = trigtuple; CurrentTriggerData->tg_trigger = trigger[i]; ExecCallTriggerFunc(trigger[i]); } CurrentTriggerData = NULL; pfree(SaveTriggerData); pfree(trigtuple); return;}HeapTupleExecBRUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple){ Relation rel = estate->es_result_relation_info->ri_RelationDesc; TriggerData *SaveTriggerData; int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE]; Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_UPDATE]; HeapTuple trigtuple; HeapTuple oldtuple; HeapTuple intuple = newtuple; TupleTableSlot *newSlot; int i; trigtuple = GetTupleForTrigger(estate, tupleid, &newSlot); if (trigtuple == NULL) return NULL; /* * In READ COMMITTED isolevel it's possible that newtuple was changed * due to concurrent update. */ if (newSlot != NULL) intuple = newtuple = ExecRemoveJunk(estate->es_junkFilter, newSlot); SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData)); SaveTriggerData->tg_event = TRIGGER_EVENT_UPDATE | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE; SaveTriggerData->tg_relation = rel; for (i = 0; i < ntrigs; i++) { CurrentTriggerData = SaveTriggerData; CurrentTriggerData->tg_trigtuple = trigtuple; CurrentTriggerData->tg_newtuple = oldtuple = newtuple; CurrentTriggerData->tg_trigger = trigger[i]; newtuple = ExecCallTriggerFunc(trigger[i]); if (newtuple == NULL) break; else if (oldtuple != newtuple && oldtuple != intuple) pfree(oldtuple); } CurrentTriggerData = NULL; pfree(SaveTriggerData); pfree(trigtuple); return newtuple;}voidExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple){ Relation rel = estate->es_result_relation_info->ri_RelationDesc; TriggerData *SaveTriggerData; int ntrigs = rel->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE]; Trigger **trigger = rel->trigdesc->tg_after_row[TRIGGER_EVENT_UPDATE]; HeapTuple trigtuple; int i; trigtuple = GetTupleForTrigger(estate, tupleid, NULL); Assert(trigtuple != NULL); SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData)); SaveTriggerData->tg_event = TRIGGER_EVENT_UPDATE | TRIGGER_EVENT_ROW; SaveTriggerData->tg_relation = rel; for (i = 0; i < ntrigs; i++) { CurrentTriggerData = SaveTriggerData; CurrentTriggerData->tg_trigtuple = trigtuple; CurrentTriggerData->tg_newtuple = newtuple; CurrentTriggerData->tg_trigger = trigger[i]; ExecCallTriggerFunc(trigger[i]); } CurrentTriggerData = NULL; pfree(SaveTriggerData); pfree(trigtuple); return;}extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti, ItemPointer tid);static HeapTupleGetTupleForTrigger(EState *estate, ItemPointer tid, TupleTableSlot **newSlot){ Relation relation = estate->es_result_relation_info->ri_RelationDesc; HeapTupleData tuple; HeapTuple result; Buffer buffer; if (newSlot != NULL) { int test; /* * mark tuple for update */ *newSlot = NULL; tuple.t_self = *tid;ltrmark:; test = heap_mark4update(relation, &tuple, &buffer); switch (test) { case HeapTupleSelfUpdated: ReleaseBuffer(buffer); return (NULL); case HeapTupleMayBeUpdated: break; case HeapTupleUpdated: ReleaseBuffer(buffer); if (XactIsoLevel == XACT_SERIALIZABLE) elog(ERROR, "Can't serialize access due to concurrent update"); else if (!(ItemPointerEquals(&(tuple.t_self), tid))) { TupleTableSlot *epqslot = EvalPlanQual(estate, estate->es_result_relation_info->ri_RangeTableIndex, &(tuple.t_self)); if (!(TupIsNull(epqslot))) { *tid = tuple.t_self; *newSlot = epqslot; goto ltrmark; } } /* * if tuple was deleted or PlanQual failed for updated * tuple - we have not process this tuple! */ return (NULL); default: ReleaseBuffer(buffer); elog(ERROR, "Unknown status %u from heap_mark4update", test); return (NULL); } } else { PageHeader dp; ItemId lp; buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid)); if (!BufferIsValid(buffer)) elog(ERROR, "GetTupleForTrigger: failed ReadBuffer"); dp = (PageHeader) BufferGetPage(buffer); lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid)); Assert(ItemIdIsUsed(lp)); tuple.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp); tuple.t_len = ItemIdGetLength(lp); tuple.t_self = *tid; } result = heap_copytuple(&tuple); ReleaseBuffer(buffer); return result;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?