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 + -
显示快捷键?