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

📄 tablecmds.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
										  localHasOids,										  parentOidCount,										  stmt->oncommit,										  allowSystemTableMods);	StoreCatalogInheritance(relationId, inheritOids);	/*	 * We must bump the command counter to make the newly-created relation	 * tuple visible for opening.	 */	CommandCounterIncrement();	/*	 * Open the new relation and acquire exclusive lock on it.	This isn't	 * really necessary for locking out other backends (since they can't see	 * the new rel anyway until we commit), but it keeps the lock manager from	 * complaining about deadlock risks.	 */	rel = relation_open(relationId, AccessExclusiveLock);	/*	 * Now add any newly specified column default values and CHECK constraints	 * to the new relation.  These are passed to us in the form of raw	 * parsetrees; we need to transform them to executable expression trees	 * before they can be added. The most convenient way to do that is to	 * apply the parser's transformExpr routine, but transformExpr doesn't	 * work unless we have a pre-existing relation. So, the transformation has	 * to be postponed to this final step of CREATE TABLE.	 *	 * Another task that's conveniently done at this step is to add dependency	 * links between columns and supporting relations (such as SERIAL	 * sequences).	 *	 * First, scan schema to find new column defaults.	 */	rawDefaults = NIL;	attnum = 0;	foreach(listptr, schema)	{		ColumnDef  *colDef = lfirst(listptr);		attnum++;		if (colDef->raw_default != NULL)		{			RawColumnDefault *rawEnt;			Assert(colDef->cooked_default == NULL);			rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));			rawEnt->attnum = attnum;			rawEnt->raw_default = colDef->raw_default;			rawDefaults = lappend(rawDefaults, rawEnt);		}		/* Create dependency for supporting relation for this column */		if (colDef->support != NULL)			add_column_support_dependency(relationId, attnum, colDef->support);	}	/*	 * Parse and add the defaults/constraints, if any.	 */	if (rawDefaults || stmt->constraints)		AddRelationRawConstraints(rel, rawDefaults, stmt->constraints);	/*	 * Clean up.  We keep lock on new relation (although it shouldn't be	 * visible to anyone else anyway, until commit).	 */	relation_close(rel, NoLock);	return relationId;}/* * RemoveRelation *		Deletes a relation. */voidRemoveRelation(const RangeVar *relation, DropBehavior behavior){	Oid			relOid;	ObjectAddress object;	relOid = RangeVarGetRelid(relation, false);	object.classId = RelationRelationId;	object.objectId = relOid;	object.objectSubId = 0;	performDeletion(&object, behavior);}/* * ExecuteTruncate *		Executes a TRUNCATE command. * * This is a multi-relation truncate.  It first opens and grabs exclusive * locks on all relations involved, checking permissions and otherwise * verifying that the relation is OK for truncation.  When they are all * open, it checks foreign key references on them, namely that FK references * are all internal to the group that's being truncated.  Finally all * relations are truncated and reindexed. */voidExecuteTruncate(List *relations){	List	   *rels = NIL;	ListCell   *cell;	foreach(cell, relations)	{		RangeVar   *rv = lfirst(cell);		Relation	rel;		/* Grab exclusive lock in preparation for truncate */		rel = heap_openrv(rv, AccessExclusiveLock);		/* Only allow truncate on regular tables */		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(RelationGetRelid(rel), 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))));		/*		 * We can never allow truncation of shared or nailed-in-cache		 * relations, because we can't support changing their relfilenode		 * values.		 */		if (rel->rd_rel->relisshared || rel->rd_isnailed)			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),					 errmsg("cannot truncate system relation \"%s\"",							RelationGetRelationName(rel))));		/*		 * Don't allow truncate on temp tables of other backends ... their		 * local buffer manager is not going to cope.		 */		if (isOtherTempNamespace(RelationGetNamespace(rel)))			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),			  errmsg("cannot truncate temporary tables of other sessions")));		/* Save it into the list of rels to truncate */		rels = lappend(rels, rel);	}	/*	 * Check foreign key references.	 */	heap_truncate_check_FKs(rels, false);	/*	 * OK, truncate each table.	 */	foreach(cell, rels)	{		Relation	rel = lfirst(cell);		Oid			heap_relid;		Oid			toast_relid;		/*		 * Create a new empty storage file for the relation, and assign it as		 * the relfilenode value.	The old storage file is scheduled for		 * deletion at commit.		 */		setNewRelfilenode(rel);		heap_relid = RelationGetRelid(rel);		toast_relid = rel->rd_rel->reltoastrelid;		heap_close(rel, NoLock);		/*		 * The same for the toast table, if any.		 */		if (OidIsValid(toast_relid))		{			rel = relation_open(toast_relid, AccessExclusiveLock);			setNewRelfilenode(rel);			heap_close(rel, NoLock);		}		/*		 * Reconstruct the indexes to match, and we're done.		 */		reindex_relation(heap_relid, true);	}}/*---------- * MergeAttributes *		Returns new schema given initial schema and superclasses. * * Input arguments: * 'schema' is the column/attribute definition for the table. (It's a list *		of ColumnDef's.) It is destructively changed. * 'supers' is a list of names (as RangeVar nodes) of parent relations. * 'istemp' is TRUE if we are creating a temp relation. * * Output arguments: * 'supOids' receives a list of the OIDs of the parent relations. * 'supconstr' receives a list of constraints belonging to the parents, *		updated as necessary to be valid for the child. * 'supOidCount' is set to the number of parents that have OID columns. * * Return value: * Completed schema list. * * Notes: *	  The order in which the attributes are inherited is very important. *	  Intuitively, the inherited attributes should come first. If a table *	  inherits from multiple parents, the order of those attributes are *	  according to the order of the parents specified in CREATE TABLE. * *	  Here's an example: * *		create table person (name text, age int4, location point); *		create table emp (salary int4, manager text) inherits(person); *		create table student (gpa float8) inherits (person); *		create table stud_emp (percent int4) inherits (emp, student); * *	  The order of the attributes of stud_emp is: * *							person {1:name, 2:age, 3:location} *							/	 \ *			   {6:gpa}	student   emp {4:salary, 5:manager} *							\	 / *						   stud_emp {7:percent} * *	   If the same attribute name appears multiple times, then it appears *	   in the result table in the proper location for its first appearance. * *	   Constraints (including NOT NULL constraints) for the child table *	   are the union of all relevant constraints, from both the child schema *	   and parent tables. * *	   The default value for a child column is defined as: *		(1) If the child schema specifies a default, that value is used. *		(2) If neither the child nor any parent specifies a default, then *			the column will not have a default. *		(3) If conflicting defaults are inherited from different parents *			(and not overridden by the child), an error is raised. *		(4) Otherwise the inherited default is used. *		Rule (3) is new in Postgres 7.1; in earlier releases you got a *		rather arbitrary choice of which parent default to use. *---------- */static List *MergeAttributes(List *schema, List *supers, bool istemp,				List **supOids, List **supconstr, int *supOidCount){	ListCell   *entry;	List	   *inhSchema = NIL;	List	   *parentOids = NIL;	List	   *constraints = NIL;	int			parentsWithOids = 0;	bool		have_bogus_defaults = false;	char	   *bogus_marker = "Bogus!";		/* marks conflicting defaults */	int			child_attno;	/*	 * Check for and reject tables with too many columns. We perform this	 * check relatively early for two reasons: (a) we don't run the risk of	 * overflowing an AttrNumber in subsequent code (b) an O(n^2) algorithm is	 * okay if we're processing <= 1600 columns, but could take minutes to	 * execute if the user attempts to create a table with hundreds of	 * thousands of columns.	 *	 * Note that we also need to check that any we do not exceed this figure	 * after including columns from inherited relations.	 */	if (list_length(schema) > MaxHeapAttributeNumber)		ereport(ERROR,				(errcode(ERRCODE_TOO_MANY_COLUMNS),				 errmsg("tables can have at most %d columns",						MaxHeapAttributeNumber)));	/*	 * Check for duplicate names in the explicit list of attributes.	 *	 * Although we might consider merging such entries in the same way that we	 * handle name conflicts for inherited attributes, it seems to make more	 * sense to assume such conflicts are errors.	 */	foreach(entry, schema)	{		ColumnDef  *coldef = lfirst(entry);		ListCell   *rest;		for_each_cell(rest, lnext(entry))		{			ColumnDef  *restdef = lfirst(rest);			if (strcmp(coldef->colname, restdef->colname) == 0)				ereport(ERROR,						(errcode(ERRCODE_DUPLICATE_COLUMN),						 errmsg("column \"%s\" duplicated",								coldef->colname)));		}	}	/*	 * Scan the parents left-to-right, and merge their attributes to form a	 * list of inherited attributes (inhSchema).  Also check to see if we need	 * to inherit an OID column.	 */	child_attno = 0;	foreach(entry, supers)	{		RangeVar   *parent = (RangeVar *) lfirst(entry);		Relation	relation;		TupleDesc	tupleDesc;		TupleConstr *constr;		AttrNumber *newattno;		AttrNumber	parent_attno;		relation = heap_openrv(parent, AccessShareLock);		if (relation->rd_rel->relkind != RELKIND_RELATION)			ereport(ERROR,					(errcode(ERRCODE_WRONG_OBJECT_TYPE),					 errmsg("inherited relation \"%s\" is not a table",							parent->relname)));		/* Permanent rels cannot inherit from temporary ones */		if (!istemp && isTempNamespace(RelationGetNamespace(relation)))			ereport(ERROR,					(errcode(ERRCODE_WRONG_OBJECT_TYPE),					 errmsg("cannot inherit from temporary relation \"%s\"",							parent->relname)));		/*		 * We should have an UNDER permission flag for this, but for now,		 * demand that creator of a child table own the parent.		 */		if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))			aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,						   RelationGetRelationName(relation));		/*		 * Reject duplications in the list of parents.		 */		if (list_member_oid(parentOids, RelationGetRelid(relation)))			ereport(ERROR,					(errcode(ERRCODE_DUPLICATE_TABLE),					 errmsg("inherited relation \"%s\" duplicated",							parent->relname)));		parentOids = lappend_oid(parentOids, RelationGetRelid(relation));		if (relation->rd_rel->relhasoids)			parentsWithOids++;		tupleDesc = RelationGetDescr(relation);		constr = tupleDesc->constr;		/*		 * newattno[] will contain the child-table attribute numbers for the		 * attributes of this parent table.  (They are not the same for		 * parents after the first one, nor if we have dropped columns.)		 */		newattno = (AttrNumber *)			palloc(tupleDesc->natts * sizeof(AttrNumber));		for (parent_attno = 1; parent_attno <= tupleDesc->natts;			 parent_attno++)		{			Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1];			char	   *attributeName = NameStr(attribute->attname);			int			exist_attno;			ColumnDef  *def;			TypeName   *typename;			/*			 * Ignore dropped columns in the parent.			 */			if (attribute->attisdropped)			{				/*				 * change_varattnos_of_a_node asserts that this is greater				 * than zero, so if anything tries to use it, we should find				 * out.				 */				newattno[parent_attno - 1] = 0;				continue;			}			/*			 * Does it conflict with some previously inherited column?			 */			exist_attno = findAttrByName(attributeName, inhSchema);			if (exist_attno > 0)			{				/*				 * Yes, try to merge the two column definitions. They must				 * have the same type and typmod.				 */				ereport(NOTICE,						(errmsg("merging multiple inherited definitions of column \"%s\"",								attributeName)));				def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1);				if (typenameTypeId(def->typename) != attribute->atttypid ||					def->typename->typmod != attribute->atttypmod)					ereport(ERROR,							(errcode(ERRCODE_DATATYPE_MISMATCH),						errmsg("inherited column \"%s\" has a type conflict",							   attributeName),							 errdetail("%s versus %s",									   TypeNameToString(def->typename),									   format_type_be(attribute->atttypid))));				def->inhcount++;				/* Merge of NOT NULL constraints = OR 'em together */				def->is_not_null |= attribute->attnotnull;				/* Default and other constraints are handled below */

⌨️ 快捷键说明

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