tablecmds.c

来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,338 行 · 第 1/5 页

C
2,338
字号
	 * Automatically create the secondary relation for TOAST if it	 * formerly had no such but now has toastable attributes.	 */	AlterTableCreateToastTable(myrelid, true);}/* * ALTER TABLE ALTER COLUMN DROP NOT NULL */voidAlterTableAlterColumnDropNotNull(Oid myrelid, bool recurse,								 const char *colName){	Relation	rel;	HeapTuple	tuple;	AttrNumber	attnum;	Relation	attr_rel;	List	   *indexoidlist;	List	   *indexoidscan;	rel = heap_open(myrelid, AccessExclusiveLock);	if (rel->rd_rel->relkind != RELKIND_RELATION)		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("\"%s\" is not a table",						RelationGetRelationName(rel))));	/* Permissions checks */	if (!pg_class_ownercheck(myrelid, GetUserId()))		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,					   RelationGetRelationName(rel));	if (!allowSystemTableMods && IsSystemRelation(rel))		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("permission denied: \"%s\" is a system catalog",						RelationGetRelationName(rel))));	/*	 * Propagate to children if desired	 */	if (recurse)	{		List	   *child,				   *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 = lfirsto(child);			if (childrelid == myrelid)				continue;			AlterTableAlterColumnDropNotNull(childrelid,											 false, colName);		}	}	/* now do the thing on this relation */	/*	 * get the number of the attribute	 */	attnum = get_attnum(myrelid, colName);	if (attnum == InvalidAttrNumber)		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_COLUMN),			 errmsg("column \"%s\" of relation \"%s\" does not exist",					colName, RelationGetRelationName(rel))));	/* Prevent them from altering a system attribute */	if (attnum < 0)		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				 errmsg("cannot alter system column \"%s\"",						colName)));	/*	 * Check that the attribute is not in a primary key	 */	/* Loop over all indexes on the relation */	indexoidlist = RelationGetIndexList(rel);	foreach(indexoidscan, indexoidlist)	{		Oid			indexoid = lfirsto(indexoidscan);		HeapTuple	indexTuple;		Form_pg_index indexStruct;		int			i;		indexTuple = SearchSysCache(INDEXRELID,									ObjectIdGetDatum(indexoid),									0, 0, 0);		if (!HeapTupleIsValid(indexTuple))			elog(ERROR, "cache lookup failed for index %u", indexoid);		indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);		/* If the index is not a primary key, skip the check */		if (indexStruct->indisprimary)		{			/*			 * Loop over each attribute in the primary key and see if it			 * matches the to-be-altered attribute			 */			for (i = 0; i < indexStruct->indnatts; i++)			{				if (indexStruct->indkey[i] == attnum)					ereport(ERROR,							(errcode(ERRCODE_INVALID_TABLE_DEFINITION),						   errmsg("column \"%s\" is in a primary key",								  colName)));			}		}		ReleaseSysCache(indexTuple);	}	freeList(indexoidlist);	/*	 * Okay, actually perform the catalog change	 */	attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock);	tuple = SearchSysCacheCopyAttName(myrelid, colName);	if (!HeapTupleIsValid(tuple))		/* shouldn't happen */		elog(ERROR, "cache lookup failed for attribute \"%s\" of relation %u",			 colName, myrelid);	((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull = FALSE;	simple_heap_update(attr_rel, &tuple->t_self, tuple);	/* keep the system catalog indexes current */	CatalogUpdateIndexes(attr_rel, tuple);	heap_close(attr_rel, RowExclusiveLock);	heap_close(rel, NoLock);}/* * ALTER TABLE ALTER COLUMN SET NOT NULL */voidAlterTableAlterColumnSetNotNull(Oid myrelid, bool recurse,								const char *colName){	Relation	rel;	HeapTuple	tuple;	AttrNumber	attnum;	Relation	attr_rel;	HeapScanDesc scan;	TupleDesc	tupdesc;	rel = heap_open(myrelid, AccessExclusiveLock);	if (rel->rd_rel->relkind != RELKIND_RELATION)		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("\"%s\" is not a table",						RelationGetRelationName(rel))));	/* Permissions checks */	if (!pg_class_ownercheck(myrelid, GetUserId()))		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,					   RelationGetRelationName(rel));	if (!allowSystemTableMods && IsSystemRelation(rel))		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("permission denied: \"%s\" is a system catalog",						RelationGetRelationName(rel))));	/*	 * Propagate to children if desired	 */	if (recurse)	{		List	   *child,				   *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 = lfirsto(child);			if (childrelid == myrelid)				continue;			AlterTableAlterColumnSetNotNull(childrelid,											false, colName);		}	}	/* now do the thing on this relation */	/*	 * get the number of the attribute	 */	attnum = get_attnum(myrelid, colName);	if (attnum == InvalidAttrNumber)		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_COLUMN),			 errmsg("column \"%s\" of relation \"%s\" does not exist",					colName, RelationGetRelationName(rel))));	/* Prevent them from altering a system attribute */	if (attnum < 0)		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				 errmsg("cannot alter system column \"%s\"",						colName)));	/*	 * Perform a scan to ensure that there are no NULL values already in	 * the relation	 */	tupdesc = RelationGetDescr(rel);	scan = heap_beginscan(rel, SnapshotNow, 0, NULL);	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)	{		Datum		d;		bool		isnull;		d = heap_getattr(tuple, attnum, tupdesc, &isnull);		if (isnull)			ereport(ERROR,					(errcode(ERRCODE_NOT_NULL_VIOLATION),					 errmsg("column \"%s\" contains null values",							colName)));	}	heap_endscan(scan);	/*	 * Okay, actually perform the catalog change	 */	attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock);	tuple = SearchSysCacheCopyAttName(myrelid, colName);	if (!HeapTupleIsValid(tuple))		/* shouldn't happen */		elog(ERROR, "cache lookup failed for attribute \"%s\" of relation %u",			 colName, myrelid);	((Form_pg_attribute) GETSTRUCT(tuple))->attnotnull = TRUE;	simple_heap_update(attr_rel, &tuple->t_self, tuple);	/* keep the system catalog indexes current */	CatalogUpdateIndexes(attr_rel, tuple);	heap_close(attr_rel, RowExclusiveLock);	heap_close(rel, NoLock);}/* * ALTER TABLE ALTER COLUMN SET/DROP DEFAULT */voidAlterTableAlterColumnDefault(Oid myrelid, bool recurse,							 const char *colName,							 Node *newDefault){	Relation	rel;	AttrNumber	attnum;	rel = heap_open(myrelid, AccessExclusiveLock);	/*	 * We allow defaults on views so that INSERT into a view can have	 * default-ish behavior.  This works because the rewriter substitutes	 * default values into INSERTs before it expands rules.	 */	if (rel->rd_rel->relkind != RELKIND_RELATION &&		rel->rd_rel->relkind != RELKIND_VIEW)		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("\"%s\" is not a table or view",						RelationGetRelationName(rel))));	/* Permissions checks */	if (!pg_class_ownercheck(myrelid, GetUserId()))		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,					   RelationGetRelationName(rel));	if (!allowSystemTableMods && IsSystemRelation(rel))		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("permission denied: \"%s\" is a system catalog",						RelationGetRelationName(rel))));	/*	 * Propagate to children if desired	 */	if (recurse)	{		List	   *child,				   *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 = lfirsto(child);			if (childrelid == myrelid)				continue;			AlterTableAlterColumnDefault(childrelid,										 false, colName, newDefault);		}	}	/* now do the thing on this relation */	/*	 * get the number of the attribute	 */	attnum = get_attnum(myrelid, colName);	if (attnum == InvalidAttrNumber)		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_COLUMN),			 errmsg("column \"%s\" of relation \"%s\" does not exist",					colName, RelationGetRelationName(rel))));	/* Prevent them from altering a system attribute */	if (attnum < 0)		ereport(ERROR,				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),				 errmsg("cannot alter system column \"%s\"",						colName)));	/*	 * Remove any old default for the column.  We use RESTRICT here for	 * safety, but at present we do not expect anything to depend on the	 * default.	 */	RemoveAttrDefault(myrelid, attnum, DROP_RESTRICT, false);	if (newDefault)	{		/* SET DEFAULT */		RawColumnDefault *rawEnt;		rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));		rawEnt->attnum = attnum;		rawEnt->raw_default = newDefault;		/*		 * This function is intended for CREATE TABLE, so it processes a		 * _list_ of defaults, but we just do one.		 */		AddRelationRawConstraints(rel, makeList1(rawEnt), NIL);	}	heap_close(rel, NoLock);}/* * ALTER TABLE ALTER COLUMN SET STATISTICS / STORAGE */voidAlterTableAlterColumnFlags(Oid myrelid, bool recurse,						   const char *colName,						   Node *flagValue, const char *flagType){	Relation	rel;	int			newtarget = 1;	char		newstorage = 'p';	Relation	attrelation;	HeapTuple	tuple;	Form_pg_attribute attrtuple;	rel = heap_open(myrelid, AccessExclusiveLock);	if (rel->rd_rel->relkind != RELKIND_RELATION)		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("\"%s\" is not a table",						RelationGetRelationName(rel))));	/* Permissions checks */	if (!pg_class_ownercheck(myrelid, GetUserId()))		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,					   RelationGetRelationName(rel));	/*	 * we allow statistics case for system tables	 */	if (*flagType != 'S' && !allowSystemTableMods && IsSystemRelation(rel))		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("permission denied: \"%s\" is a system catalog",						RelationGetRelationName(rel))));	/*	 * Check the supplied parameters before anything else	 */	if (*flagType == 'S')	{		/* STATISTICS */		Assert(IsA(flagValue, Integer));		newtarget = intVal(flagValue);		/*		 * Limit target to a sane range		 */		if (newtarget < -1)		{			ereport(ERROR,					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),					 errmsg("statistics target %d is too low",							newtarget)));		}		else if (newtarget > 1000)		{			newtarget = 1000;			ereport(WARNING,					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),					 errmsg("lowering statistics target to %d",							newtarget)));		}	}	else if (*flagType == 'M')	{		/* STORAGE */		char	   *storagemode;		Assert(IsA(flagValue, String));		storagemode = strVal(flagValue);		if (strcasecmp(storagemode, "plain") == 0)			newstorage = 'p';		else if (strcasecmp(storagemode, "external") == 0)			newstorage = 'e';		else if (strcasecmp(storagemode, "extended") == 0)			newstorage = 'x';		else if (strcasecmp(storagemode, "main") == 0)			newstorage = 'm';		else			er

⌨️ 快捷键说明

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