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

📄 trigger.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
 * 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 + -