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

📄 trigger.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * trigger.c *	  PostgreSQL TRIGGERs support code. * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/genam.h"#include "access/heapam.h"#include "catalog/catalog.h"#include "catalog/catname.h"#include "catalog/indexing.h"#include "catalog/pg_language.h"#include "catalog/pg_proc.h"#include "catalog/pg_trigger.h"#include "commands/trigger.h"#include "executor/executor.h"#include "miscadmin.h"#include "utils/acl.h"#include "utils/builtins.h"#include "utils/inval.h"#include "utils/syscache.h"DLLIMPORT TriggerData *CurrentTriggerData = NULL;void		RelationBuildTriggers(Relation relation);void		FreeTriggerDesc(Relation relation);static void DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger);static HeapTuple GetTupleForTrigger(EState *estate, ItemPointer tid,				   TupleTableSlot **newSlot);extern GlobalMemory CacheCxt;voidCreateTrigger(CreateTrigStmt *stmt){	int16		tgtype;	int16		tgattr[8] = {0};	Datum		values[Natts_pg_trigger];	char		nulls[Natts_pg_trigger];	Relation	rel;	Relation	tgrel;	HeapScanDesc tgscan;	ScanKeyData key;	Relation	pgrel;	HeapTuple	tuple;	Relation	idescs[Num_pg_trigger_indices];	Relation	ridescs[Num_pg_class_indices];	MemoryContext oldcxt;	Oid			fargtypes[8];	int			found = 0;	int			i;	if (!allowSystemTableMods && IsSystemRelationName(stmt->relname))		elog(ERROR, "CreateTrigger: can't create trigger for system relation %s", stmt->relname);#ifndef NO_SECURITY	if (!pg_ownercheck(GetPgUserName(), stmt->relname, RELNAME))		elog(ERROR, "%s: %s", stmt->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);#endif	rel = heap_openr(stmt->relname);	if (!RelationIsValid(rel))		elog(ERROR, "CreateTrigger: there is no relation %s", stmt->relname);	LockRelation(rel, AccessExclusiveLock);	TRIGGER_CLEAR_TYPE(tgtype);	if (stmt->before)		TRIGGER_SETT_BEFORE(tgtype);	if (stmt->row)		TRIGGER_SETT_ROW(tgtype);	else		elog(ERROR, "CreateTrigger: STATEMENT triggers are unimplemented, yet");	for (i = 0; i < 3 && stmt->actions[i]; i++)	{		switch (stmt->actions[i])		{			case 'i':				if (TRIGGER_FOR_INSERT(tgtype))					elog(ERROR, "CreateTrigger: double INSERT event specified");				TRIGGER_SETT_INSERT(tgtype);				break;			case 'd':				if (TRIGGER_FOR_DELETE(tgtype))					elog(ERROR, "CreateTrigger: double DELETE event specified");				TRIGGER_SETT_DELETE(tgtype);				break;			case 'u':				if (TRIGGER_FOR_UPDATE(tgtype))					elog(ERROR, "CreateTrigger: double UPDATE event specified");				TRIGGER_SETT_UPDATE(tgtype);				break;			default:				elog(ERROR, "CreateTrigger: unknown event specified");				break;		}	}	/* Scan pg_trigger */	tgrel = heap_openr(TriggerRelationName);	LockRelation(tgrel, AccessExclusiveLock);	ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,						   F_OIDEQ, RelationGetRelid(rel));	tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);	while (HeapTupleIsValid(tuple = heap_getnext(tgscan, 0)))	{		Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);		if (namestrcmp(&(pg_trigger->tgname), stmt->trigname) == 0)			elog(ERROR, "CreateTrigger: trigger %s already defined on relation %s",				 stmt->trigname, stmt->relname);		else			found++;	}	heap_endscan(tgscan);	MemSet(fargtypes, 0, 8 * sizeof(Oid));	tuple = SearchSysCacheTuple(PRONAME,								PointerGetDatum(stmt->funcname),								Int32GetDatum(0),								PointerGetDatum(fargtypes),								0);	if (!HeapTupleIsValid(tuple) ||		((Form_pg_proc) GETSTRUCT(tuple))->pronargs != 0)		elog(ERROR, "CreateTrigger: function %s() does not exist",			 stmt->funcname);	if (((Form_pg_proc) GETSTRUCT(tuple))->prorettype != 0)		elog(ERROR, "CreateTrigger: function %s() must return OPAQUE",			 stmt->funcname);	if (((Form_pg_proc) GETSTRUCT(tuple))->prolang != ClanguageId)	{		HeapTuple	langTup;		langTup = SearchSysCacheTuple(LANOID,			ObjectIdGetDatum(((Form_pg_proc) GETSTRUCT(tuple))->prolang),									  0, 0, 0);		if (!HeapTupleIsValid(langTup))			elog(ERROR, "CreateTrigger: cache lookup for PL failed");		if (((Form_pg_language) GETSTRUCT(langTup))->lanispl == false)			elog(ERROR, "CreateTrigger: only C and PL functions are supported");	}	MemSet(nulls, ' ', Natts_pg_trigger * sizeof(char));	values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));	values[Anum_pg_trigger_tgname - 1] = NameGetDatum(namein(stmt->trigname));	values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(tuple->t_data->t_oid);	values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum(tgtype);	if (stmt->args)	{		List	   *le;		char	   *args;		int16		nargs = length(stmt->args);		int			len = 0;		foreach(le, stmt->args)		{			char	   *ar = (char *) lfirst(le);			len += strlen(ar) + VARHDRSZ;			for (; *ar; ar++)			{				if (*ar == '\\')					len++;			}		}		args = (char *) palloc(len + 1);		args[0] = 0;		foreach(le, stmt->args)		{			char	   *s = (char *) lfirst(le);			char	   *d = args + strlen(args);			while (*s)			{				if (*s == '\\')					*d++ = '\\';				*d++ = *s++;			}			*d = 0;			strcat(args, "\\000");		}		values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(nargs);		values[Anum_pg_trigger_tgargs - 1] = PointerGetDatum(byteain(args));	}	else	{		values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum(0);		values[Anum_pg_trigger_tgargs - 1] = PointerGetDatum(byteain(""));	}	values[Anum_pg_trigger_tgattr - 1] = PointerGetDatum(tgattr);	tuple = heap_formtuple(tgrel->rd_att, values, nulls);	heap_insert(tgrel, tuple);	CatalogOpenIndices(Num_pg_trigger_indices, Name_pg_trigger_indices, idescs);	CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple);	CatalogCloseIndices(Num_pg_trigger_indices, idescs);	pfree(tuple);	UnlockRelation(tgrel, AccessExclusiveLock);	heap_close(tgrel);	pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));	pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1]));	/* update pg_class */	tuple = SearchSysCacheTupleCopy(RELNAME,									PointerGetDatum(stmt->relname),									0, 0, 0);	if (!HeapTupleIsValid(tuple))		elog(ERROR, "CreateTrigger: relation %s not found in pg_class", stmt->relname);	pgrel = heap_openr(RelationRelationName);	((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1;	RelationInvalidateHeapTuple(pgrel, tuple);	heap_replace(pgrel, &tuple->t_self, tuple, NULL);	CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);	CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);	CatalogCloseIndices(Num_pg_class_indices, ridescs);	pfree(tuple);	heap_close(pgrel);	CommandCounterIncrement();	oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);	FreeTriggerDesc(rel);	rel->rd_rel->reltriggers = found + 1;	RelationBuildTriggers(rel);	MemoryContextSwitchTo(oldcxt);	heap_close(rel);	return;}voidDropTrigger(DropTrigStmt *stmt){	Relation	rel;	Relation	tgrel;	HeapScanDesc tgscan;	ScanKeyData key;	Relation	pgrel;	HeapTuple	tuple;	Relation	ridescs[Num_pg_class_indices];	MemoryContext oldcxt;	int			found = 0;	int			tgfound = 0;#ifndef NO_SECURITY	if (!pg_ownercheck(GetPgUserName(), stmt->relname, RELNAME))		elog(ERROR, "%s: %s", stmt->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);#endif	rel = heap_openr(stmt->relname);	if (!RelationIsValid(rel))		elog(ERROR, "DropTrigger: there is no relation %s", stmt->relname);	LockRelation(rel, AccessExclusiveLock);	tgrel = heap_openr(TriggerRelationName);	LockRelation(tgrel, AccessExclusiveLock);	ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,						   F_OIDEQ, RelationGetRelid(rel));	tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);	while (HeapTupleIsValid(tuple = heap_getnext(tgscan, 0)))	{		Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);		if (namestrcmp(&(pg_trigger->tgname), stmt->trigname) == 0)		{			heap_delete(tgrel, &tuple->t_self, NULL);			tgfound++;		}		else			found++;	}	if (tgfound == 0)		elog(ERROR, "DropTrigger: there is no trigger %s on relation %s",			 stmt->trigname, stmt->relname);	if (tgfound > 1)		elog(NOTICE, "DropTrigger: found (and deleted) %d trigger %s on relation %s",			 tgfound, stmt->trigname, stmt->relname);	heap_endscan(tgscan);	UnlockRelation(tgrel, AccessExclusiveLock);	heap_close(tgrel);	tuple = SearchSysCacheTupleCopy(RELNAME,									PointerGetDatum(stmt->relname),									0, 0, 0);	if (!HeapTupleIsValid(tuple))		elog(ERROR, "DropTrigger: relation %s not found in pg_class", stmt->relname);	/* update pg_class */	pgrel = heap_openr(RelationRelationName);	((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found;	RelationInvalidateHeapTuple(pgrel, tuple);	heap_replace(pgrel, &tuple->t_self, tuple, NULL);	CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);	CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);	CatalogCloseIndices(Num_pg_class_indices, ridescs);	pfree(tuple);	heap_close(pgrel);	CommandCounterIncrement();	oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);	FreeTriggerDesc(rel);	rel->rd_rel->reltriggers = found;	if (found > 0)		RelationBuildTriggers(rel);	MemoryContextSwitchTo(oldcxt);	heap_close(rel);	return;}voidRelationRemoveTriggers(Relation rel){	Relation	tgrel;	HeapScanDesc tgscan;	ScanKeyData key;	HeapTuple	tup;	tgrel = heap_openr(TriggerRelationName);	LockRelation(tgrel, AccessExclusiveLock);	ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,						   F_OIDEQ, RelationGetRelid(rel));	tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);	while (HeapTupleIsValid(tup = heap_getnext(tgscan, 0)))		heap_delete(tgrel, &tup->t_self, NULL);	heap_endscan(tgscan);	UnlockRelation(tgrel, AccessExclusiveLock);	heap_close(tgrel);}voidRelationBuildTriggers(Relation relation){	TriggerDesc *trigdesc = (TriggerDesc *) palloc(sizeof(TriggerDesc));	int			ntrigs = relation->rd_rel->reltriggers;	Trigger    *triggers = NULL;	Trigger    *build;	Relation	tgrel;	Form_pg_trigger pg_trigger;	Relation	irel;	ScanKeyData skey;	HeapTupleData tuple;	IndexScanDesc sd;	RetrieveIndexResult indexRes;	Buffer		buffer;	struct varlena *val;	bool		isnull;	int			found;	MemSet(trigdesc, 0, sizeof(TriggerDesc));	ScanKeyEntryInitialize(&skey,						   (bits16) 0x0,						   (AttrNumber) 1,						   (RegProcedure) F_OIDEQ,						   ObjectIdGetDatum(RelationGetRelid(relation)));	tgrel = heap_openr(TriggerRelationName);	irel = index_openr(TriggerRelidIndex);	sd = index_beginscan(irel, false, 1, &skey);	for (found = 0;;)	{		indexRes = index_getnext(sd, ForwardScanDirection);		if (!indexRes)			break;		tuple.t_self = indexRes->heap_iptr;		heap_fetch(tgrel, SnapshotNow, &tuple, &buffer);		pfree(indexRes);		if (!tuple.t_data)			continue;		if (found == ntrigs)			elog(ERROR, "RelationBuildTriggers: unexpected record found for rel %.*s",				 NAMEDATALEN, relation->rd_rel->relname.data);		pg_trigger = (Form_pg_trigger) GETSTRUCT(&tuple);		if (triggers == NULL)			triggers = (Trigger *) palloc(sizeof(Trigger));		else			triggers = (Trigger *) repalloc(triggers, (found + 1) * sizeof(Trigger));		build = &(triggers[found]);		build->tgname = nameout(&(pg_trigger->tgname));		build->tgfoid = pg_trigger->tgfoid;		build->tgfunc.fn_addr = NULL;		build->tgtype = pg_trigger->tgtype;		build->tgnargs = pg_trigger->tgnargs;		memcpy(build->tgattr, &(pg_trigger->tgattr), 8 * sizeof(int16));		val = (struct varlena *) fastgetattr(&tuple,											 Anum_pg_trigger_tgargs,											 tgrel->rd_att, &isnull);		if (isnull)			elog(ERROR, "RelationBuildTriggers: tgargs IS NULL for rel %.*s",				 NAMEDATALEN, relation->rd_rel->relname.data);		if (build->tgnargs > 0)		{			char	   *p;			int			i;			val = (struct varlena *) fastgetattr(&tuple,												 Anum_pg_trigger_tgargs,												 tgrel->rd_att, &isnull);			if (isnull)				elog(ERROR, "RelationBuildTriggers: tgargs IS NULL for rel %.*s",					 NAMEDATALEN, relation->rd_rel->relname.data);			p = (char *) VARDATA(val);			build->tgargs = (char **) palloc(build->tgnargs * sizeof(char *));			for (i = 0; i < build->tgnargs; i++)			{				build->tgargs[i] = (char *) palloc(strlen(p) + 1);				strcpy(build->tgargs[i], p);				p += strlen(p) + 1;			}		}		else			build->tgargs = NULL;		found++;		ReleaseBuffer(buffer);	}	if (found < ntrigs)		elog(ERROR, "RelationBuildTriggers: %d record not found for rel %.*s",			 ntrigs - found,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -