⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trigger.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 5 页
字号:
		}		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 + -