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

📄 tablecmds.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (!pg_class_ownercheck(myrelid, GetUserId()))		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,					   RelationGetRelationName(targetrelation));	if (!allowSystemTableMods && IsSystemRelation(targetrelation))		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("permission denied: \"%s\" is a system catalog",						RelationGetRelationName(targetrelation))));	/*	 * if the 'recurse' flag is set then we are supposed to rename this	 * attribute in all classes that inherit from 'relname' (as well as in	 * 'relname').	 *	 * any permissions or problems with duplicate attributes will cause the	 * whole transaction to abort, which is what we want -- all or nothing.	 */	if (recurse)	{		ListCell   *child;		List	   *children;		/* this routine is actually in the planner */		children = find_all_inheritors(myrelid);		/*		 * find_all_inheritors does the recursive search of the inheritance		 * hierarchy, so all we have to do is process all of the relids in the		 * list that it returns.		 */		foreach(child, children)		{			Oid			childrelid = lfirst_oid(child);			if (childrelid == myrelid)				continue;			/* note we need not recurse again */			renameatt(childrelid, oldattname, newattname, false, true);		}	}	else	{		/*		 * If we are told not to recurse, there had better not be any child		 * tables; else the rename would put them out of step.		 */		if (!recursing &&			find_inheritance_children(myrelid) != NIL)			ereport(ERROR,					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),					 errmsg("inherited column \"%s\" must be renamed in child tables too",							oldattname)));	}	attrelation = heap_open(AttributeRelationId, RowExclusiveLock);	atttup = SearchSysCacheCopyAttName(myrelid, oldattname);	if (!HeapTupleIsValid(atttup))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_COLUMN),				 errmsg("column \"%s\" does not exist",						oldattname)));	attform = (Form_pg_attribute) GETSTRUCT(atttup);	attnum = attform->attnum;	if (attnum <= 0)		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				 errmsg("cannot rename system column \"%s\"",						oldattname)));	/*	 * if the attribute is inherited, forbid the renaming, unless we are	 * already inside a recursive rename.	 */	if (attform->attinhcount > 0 && !recursing)		ereport(ERROR,				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),				 errmsg("cannot rename inherited column \"%s\"",						oldattname)));	/* should not already exist */	/* this test is deliberately not attisdropped-aware */	if (SearchSysCacheExists(ATTNAME,							 ObjectIdGetDatum(myrelid),							 PointerGetDatum(newattname),							 0, 0))		ereport(ERROR,				(errcode(ERRCODE_DUPLICATE_COLUMN),				 errmsg("column \"%s\" of relation \"%s\" already exists",					  newattname, RelationGetRelationName(targetrelation))));	namestrcpy(&(attform->attname), newattname);	simple_heap_update(attrelation, &atttup->t_self, atttup);	/* keep system catalog indexes current */	CatalogUpdateIndexes(attrelation, atttup);	heap_freetuple(atttup);	/*	 * Update column names of indexes that refer to the column being renamed.	 */	indexoidlist = RelationGetIndexList(targetrelation);	foreach(indexoidscan, indexoidlist)	{		Oid			indexoid = lfirst_oid(indexoidscan);		HeapTuple	indextup;		Form_pg_index indexform;		int			i;		/*		 * Scan through index columns to see if there's any simple index		 * entries for this attribute.	We ignore expressional entries.		 */		indextup = SearchSysCache(INDEXRELID,								  ObjectIdGetDatum(indexoid),								  0, 0, 0);		if (!HeapTupleIsValid(indextup))			elog(ERROR, "cache lookup failed for index %u", indexoid);		indexform = (Form_pg_index) GETSTRUCT(indextup);		for (i = 0; i < indexform->indnatts; i++)		{			if (attnum != indexform->indkey.values[i])				continue;			/*			 * Found one, rename it.			 */			atttup = SearchSysCacheCopy(ATTNUM,										ObjectIdGetDatum(indexoid),										Int16GetDatum(i + 1),										0, 0);			if (!HeapTupleIsValid(atttup))				continue;		/* should we raise an error? */			/*			 * Update the (copied) attribute tuple.			 */			namestrcpy(&(((Form_pg_attribute) GETSTRUCT(atttup))->attname),					   newattname);			simple_heap_update(attrelation, &atttup->t_self, atttup);			/* keep system catalog indexes current */			CatalogUpdateIndexes(attrelation, atttup);			heap_freetuple(atttup);		}		ReleaseSysCache(indextup);	}	list_free(indexoidlist);	heap_close(attrelation, RowExclusiveLock);	/*	 * Update att name in any RI triggers associated with the relation.	 */	if (targetrelation->rd_rel->reltriggers > 0)	{		/* update tgargs column reference where att is primary key */		update_ri_trigger_args(RelationGetRelid(targetrelation),							   oldattname, newattname,							   false, false);		/* update tgargs column reference where att is foreign key */		update_ri_trigger_args(RelationGetRelid(targetrelation),							   oldattname, newattname,							   true, false);	}	relation_close(targetrelation, NoLock);		/* close rel but keep lock */}/* *		renamerel		- change the name of a relation * *		XXX - When renaming sequences, we don't bother to modify the *			  sequence name that is stored within the sequence itself *			  (this would cause problems with MVCC). In the future, *			  the sequence name should probably be removed from the *			  sequence, AFAIK there's no need for it to be there. */voidrenamerel(Oid myrelid, const char *newrelname){	Relation	targetrelation;	Relation	relrelation;	/* for RELATION relation */	HeapTuple	reltup;	Oid			namespaceId;	char	   *oldrelname;	char		relkind;	bool		relhastriggers;	/*	 * Grab an exclusive lock on the target table or index, which we will NOT	 * release until end of transaction.	 */	targetrelation = relation_open(myrelid, AccessExclusiveLock);	oldrelname = pstrdup(RelationGetRelationName(targetrelation));	namespaceId = RelationGetNamespace(targetrelation);	if (!allowSystemTableMods && IsSystemRelation(targetrelation))		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("permission denied: \"%s\" is a system catalog",						RelationGetRelationName(targetrelation))));	relkind = targetrelation->rd_rel->relkind;	relhastriggers = (targetrelation->rd_rel->reltriggers > 0);	/*	 * Find relation's pg_class tuple, and make sure newrelname isn't in use.	 */	relrelation = heap_open(RelationRelationId, RowExclusiveLock);	reltup = SearchSysCacheCopy(RELOID,								PointerGetDatum(myrelid),								0, 0, 0);	if (!HeapTupleIsValid(reltup))		/* shouldn't happen */		elog(ERROR, "cache lookup failed for relation %u", myrelid);	if (get_relname_relid(newrelname, namespaceId) != InvalidOid)		ereport(ERROR,				(errcode(ERRCODE_DUPLICATE_TABLE),				 errmsg("relation \"%s\" already exists",						newrelname)));	/*	 * Update pg_class tuple with new relname.	(Scribbling on reltup is OK	 * because it's a copy...)	 */	namestrcpy(&(((Form_pg_class) GETSTRUCT(reltup))->relname), newrelname);	simple_heap_update(relrelation, &reltup->t_self, reltup);	/* keep the system catalog indexes current */	CatalogUpdateIndexes(relrelation, reltup);	heap_freetuple(reltup);	heap_close(relrelation, RowExclusiveLock);	/*	 * Also rename the associated type, if any.	 */	if (relkind != RELKIND_INDEX)		TypeRename(oldrelname, namespaceId, newrelname);	/*	 * Update rel name in any RI triggers associated with the relation.	 */	if (relhastriggers)	{		/* update tgargs where relname is primary key */		update_ri_trigger_args(myrelid,							   oldrelname,							   newrelname,							   false, true);		/* update tgargs where relname is foreign key */		update_ri_trigger_args(myrelid,							   oldrelname,							   newrelname,							   true, true);	}	/*	 * Close rel, but keep exclusive lock!	 */	relation_close(targetrelation, NoLock);}/* * Scan pg_trigger for RI triggers that are on the specified relation * (if fk_scan is false) or have it as the tgconstrrel (if fk_scan * is true).  Update RI trigger args fields matching oldname to contain * newname instead.  If update_relname is true, examine the relname * fields; otherwise examine the attname fields. */static voidupdate_ri_trigger_args(Oid relid,					   const char *oldname,					   const char *newname,					   bool fk_scan,					   bool update_relname){	Relation	tgrel;	ScanKeyData skey[1];	SysScanDesc trigscan;	HeapTuple	tuple;	Datum		values[Natts_pg_trigger];	char		nulls[Natts_pg_trigger];	char		replaces[Natts_pg_trigger];	tgrel = heap_open(TriggerRelationId, RowExclusiveLock);	if (fk_scan)	{		ScanKeyInit(&skey[0],					Anum_pg_trigger_tgconstrrelid,					BTEqualStrategyNumber, F_OIDEQ,					ObjectIdGetDatum(relid));		trigscan = systable_beginscan(tgrel, TriggerConstrRelidIndexId,									  true, SnapshotNow,									  1, skey);	}	else	{		ScanKeyInit(&skey[0],					Anum_pg_trigger_tgrelid,					BTEqualStrategyNumber, F_OIDEQ,					ObjectIdGetDatum(relid));		trigscan = systable_beginscan(tgrel, TriggerRelidNameIndexId,									  true, SnapshotNow,									  1, skey);	}	while ((tuple = systable_getnext(trigscan)) != NULL)	{		Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);		bytea	   *val;		bytea	   *newtgargs;		bool		isnull;		int			tg_type;		bool		examine_pk;		bool		changed;		int			tgnargs;		int			i;		int			newlen;		const char *arga[RI_MAX_ARGUMENTS];		const char *argp;		tg_type = RI_FKey_trigger_type(pg_trigger->tgfoid);		if (tg_type == RI_TRIGGER_NONE)		{			/* Not an RI trigger, forget it */			continue;		}		/*		 * It is an RI trigger, so parse the tgargs bytea.		 *		 * NB: we assume the field will never be compressed or moved out of		 * line; so does trigger.c ...		 */		tgnargs = pg_trigger->tgnargs;		val = (bytea *)			DatumGetPointer(fastgetattr(tuple,										Anum_pg_trigger_tgargs,										tgrel->rd_att, &isnull));		if (isnull || tgnargs < RI_FIRST_ATTNAME_ARGNO ||			tgnargs > RI_MAX_ARGUMENTS)		{			/* This probably shouldn't happen, but ignore busted triggers */			continue;		}		argp = (const char *) VARDATA(val);		for (i = 0; i < tgnargs; i++)		{			arga[i] = argp;			argp += strlen(argp) + 1;		}		/*		 * Figure out which item(s) to look at.  If the trigger is primary-key		 * type and attached to my rel, I should look at the PK fields; if it		 * is foreign-key type and attached to my rel, I should look at the FK		 * fields.	But the opposite rule holds when examining triggers found		 * by tgconstrrel search.		 */		examine_pk = (tg_type == RI_TRIGGER_PK) == (!fk_scan);		changed = false;		if (update_relname)		{			/* Change the relname if needed */			i = examine_pk ? RI_PK_RELNAME_ARGNO : RI_FK_RELNAME_ARGNO;			if (strcmp(arga[i], oldname) == 0)			{				arga[i] = newname;				changed = true;			}		}		else		{			/* Change attname(s) if needed */			i = examine_pk ? RI_FIRST_ATTNAME_ARGNO + RI_KEYPAIR_PK_IDX :				RI_FIRST_ATTNAME_ARGNO + RI_KEYPAIR_FK_IDX;			for (; i < tgnargs; i += 2)			{				if (strcmp(arga[i], oldname) == 0)				{					arga[i] = newname;					changed = true;				}			}		}		if (!changed)		{			/* Don't need to update this tuple */			continue;		}		/*		 * Construct modified tgargs bytea.		 */		newlen = VARHDRSZ;		for (i = 0; i < tgnargs; i++)			newlen += strlen(arga[i]) + 1;		newtgargs = (bytea *) palloc(newlen);		VARATT_SIZEP(newtgargs) = newlen;		newlen = VARHDRSZ;		for (i = 0; i < tgnargs; i++)		{			strcpy(((char *) newtgargs) + newlen, arga[i]);			newlen += strlen(arga[i]) + 1;		}		/*		 * Build modified tuple.		 */		for (i = 0; i < Natts_pg_trigger; i++)		{			values[i] = (Datum) 0;			replaces[i] = ' ';			nulls[i] = ' ';

⌨️ 快捷键说明

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