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

📄 tablecmds.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
				newattno[parent_attno - 1] = exist_attno;			}			else			{				/*				 * No, create a new inherited column				 */				def = makeNode(ColumnDef);				def->colname = pstrdup(attributeName);				typename = makeNode(TypeName);				typename->typeid = attribute->atttypid;				typename->typmod = attribute->atttypmod;				def->typename = typename;				def->inhcount = 1;				def->is_local = false;				def->is_not_null = attribute->attnotnull;				def->raw_default = NULL;				def->cooked_default = NULL;				def->constraints = NIL;				def->support = NULL;				inhSchema = lappend(inhSchema, def);				newattno[parent_attno - 1] = ++child_attno;			}			/*			 * Copy default if any			 */			if (attribute->atthasdef)			{				char	   *this_default = NULL;				AttrDefault *attrdef;				int			i;				/* Find default in constraint structure */				Assert(constr != NULL);				attrdef = constr->defval;				for (i = 0; i < constr->num_defval; i++)				{					if (attrdef[i].adnum == parent_attno)					{						this_default = attrdef[i].adbin;						break;					}				}				Assert(this_default != NULL);				/*				 * If default expr could contain any vars, we'd need to fix				 * 'em, but it can't; so default is ready to apply to child.				 *				 * If we already had a default from some prior parent, check				 * to see if they are the same.  If so, no problem; if not,				 * mark the column as having a bogus default. Below, we will				 * complain if the bogus default isn't overridden by the child				 * schema.				 */				Assert(def->raw_default == NULL);				if (def->cooked_default == NULL)					def->cooked_default = pstrdup(this_default);				else if (strcmp(def->cooked_default, this_default) != 0)				{					def->cooked_default = bogus_marker;					have_bogus_defaults = true;				}			}		}		/*		 * Now copy the constraints of this parent, adjusting attnos using the		 * completed newattno[] map		 */		if (constr && constr->num_check > 0)		{			ConstrCheck *check = constr->check;			int			i;			for (i = 0; i < constr->num_check; i++)			{				Constraint *cdef = makeNode(Constraint);				Node	   *expr;				cdef->contype = CONSTR_CHECK;				cdef->name = pstrdup(check[i].ccname);				cdef->raw_expr = NULL;				/* adjust varattnos of ccbin here */				expr = stringToNode(check[i].ccbin);				change_varattnos_of_a_node(expr, newattno);				cdef->cooked_expr = nodeToString(expr);				constraints = lappend(constraints, cdef);			}		}		pfree(newattno);		/*		 * Close the parent rel, but keep our AccessShareLock on it until xact		 * commit.	That will prevent someone else from deleting or ALTERing		 * the parent before the child is committed.		 */		heap_close(relation, NoLock);	}	/*	 * If we had no inherited attributes, the result schema is just the	 * explicitly declared columns.  Otherwise, we need to merge the declared	 * columns into the inherited schema list.	 */	if (inhSchema != NIL)	{		foreach(entry, schema)		{			ColumnDef  *newdef = lfirst(entry);			char	   *attributeName = newdef->colname;			int			exist_attno;			/*			 * Does it conflict with some previously inherited column?			 */			exist_attno = findAttrByName(attributeName, inhSchema);			if (exist_attno > 0)			{				ColumnDef  *def;				/*				 * Yes, try to merge the two column definitions. They must				 * have the same type and typmod.				 */				ereport(NOTICE,				   (errmsg("merging column \"%s\" with inherited definition",						   attributeName)));				def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1);				if (typenameTypeId(def->typename) != typenameTypeId(newdef->typename) ||					def->typename->typmod != newdef->typename->typmod)					ereport(ERROR,							(errcode(ERRCODE_DATATYPE_MISMATCH),							 errmsg("column \"%s\" has a type conflict",									attributeName),							 errdetail("%s versus %s",									   TypeNameToString(def->typename),									   TypeNameToString(newdef->typename))));				/* Mark the column as locally defined */				def->is_local = true;				/* Merge of NOT NULL constraints = OR 'em together */				def->is_not_null |= newdef->is_not_null;				/* If new def has a default, override previous default */				if (newdef->raw_default != NULL)				{					def->raw_default = newdef->raw_default;					def->cooked_default = newdef->cooked_default;				}			}			else			{				/*				 * No, attach new column to result schema				 */				inhSchema = lappend(inhSchema, newdef);			}		}		schema = inhSchema;		/*		 * Check that we haven't exceeded the legal # of columns after merging		 * in inherited columns.		 */		if (list_length(schema) > MaxHeapAttributeNumber)			ereport(ERROR,					(errcode(ERRCODE_TOO_MANY_COLUMNS),					 errmsg("tables can have at most %d columns",							MaxHeapAttributeNumber)));	}	/*	 * If we found any conflicting parent default values, check to make sure	 * they were overridden by the child.	 */	if (have_bogus_defaults)	{		foreach(entry, schema)		{			ColumnDef  *def = lfirst(entry);			if (def->cooked_default == bogus_marker)				ereport(ERROR,						(errcode(ERRCODE_INVALID_COLUMN_DEFINITION),				  errmsg("column \"%s\" inherits conflicting default values",						 def->colname),						 errhint("To resolve the conflict, specify a default explicitly.")));		}	}	*supOids = parentOids;	*supconstr = constraints;	*supOidCount = parentsWithOids;	return schema;}/* * complementary static functions for MergeAttributes(). * * Varattnos of pg_constraint.conbin must be rewritten when subclasses inherit * constraints from parent classes, since the inherited attributes could * be given different column numbers in multiple-inheritance cases. * * Note that the passed node tree is modified in place! */static boolchange_varattnos_walker(Node *node, const AttrNumber *newattno){	if (node == NULL)		return false;	if (IsA(node, Var))	{		Var		   *var = (Var *) node;		if (var->varlevelsup == 0 && var->varno == 1 &&			var->varattno > 0)		{			/*			 * ??? the following may be a problem when the node is multiply			 * referenced though stringToNode() doesn't create such a node			 * currently.			 */			Assert(newattno[var->varattno - 1] > 0);			var->varattno = newattno[var->varattno - 1];		}		return false;	}	return expression_tree_walker(node, change_varattnos_walker,								  (void *) newattno);}static boolchange_varattnos_of_a_node(Node *node, const AttrNumber *newattno){	return change_varattnos_walker(node, newattno);}/* * StoreCatalogInheritance *		Updates the system catalogs with proper inheritance information. * * supers is a list of the OIDs of the new relation's direct ancestors. */static voidStoreCatalogInheritance(Oid relationId, List *supers){	Relation	relation;	TupleDesc	desc;	int16		seqNumber;	ListCell   *entry;	HeapTuple	tuple;	/*	 * sanity checks	 */	AssertArg(OidIsValid(relationId));	if (supers == NIL)		return;	/*	 * Store INHERITS information in pg_inherits using direct ancestors only.	 * Also enter dependencies on the direct ancestors, and make sure they are	 * marked with relhassubclass = true.	 *	 * (Once upon a time, both direct and indirect ancestors were found here	 * and then entered into pg_ipl.  Since that catalog doesn't exist	 * anymore, there's no need to look for indirect ancestors.)	 */	relation = heap_open(InheritsRelationId, RowExclusiveLock);	desc = RelationGetDescr(relation);	seqNumber = 1;	foreach(entry, supers)	{		Oid			parentOid = lfirst_oid(entry);		Datum		datum[Natts_pg_inherits];		char		nullarr[Natts_pg_inherits];		ObjectAddress childobject,					parentobject;		datum[0] = ObjectIdGetDatum(relationId);		/* inhrel */		datum[1] = ObjectIdGetDatum(parentOid); /* inhparent */		datum[2] = Int16GetDatum(seqNumber);	/* inhseqno */		nullarr[0] = ' ';		nullarr[1] = ' ';		nullarr[2] = ' ';		tuple = heap_formtuple(desc, datum, nullarr);		simple_heap_insert(relation, tuple);		CatalogUpdateIndexes(relation, tuple);		heap_freetuple(tuple);		/*		 * Store a dependency too		 */		parentobject.classId = RelationRelationId;		parentobject.objectId = parentOid;		parentobject.objectSubId = 0;		childobject.classId = RelationRelationId;		childobject.objectId = relationId;		childobject.objectSubId = 0;		recordDependencyOn(&childobject, &parentobject, DEPENDENCY_NORMAL);		/*		 * Mark the parent as having subclasses.		 */		setRelhassubclassInRelation(parentOid, true);		seqNumber += 1;	}	heap_close(relation, RowExclusiveLock);}/* * Look for an existing schema entry with the given name. * * Returns the index (starting with 1) if attribute already exists in schema, * 0 if it doesn't. */static intfindAttrByName(const char *attributeName, List *schema){	ListCell   *s;	int			i = 1;	foreach(s, schema)	{		ColumnDef  *def = lfirst(s);		if (strcmp(attributeName, def->colname) == 0)			return i;		i++;	}	return 0;}/* * Update a relation's pg_class.relhassubclass entry to the given value */static voidsetRelhassubclassInRelation(Oid relationId, bool relhassubclass){	Relation	relationRelation;	HeapTuple	tuple;	Form_pg_class classtuple;	/*	 * Fetch a modifiable copy of the tuple, modify it, update pg_class.	 *	 * If the tuple already has the right relhassubclass setting, we don't	 * need to update it, but we still need to issue an SI inval message.	 */	relationRelation = heap_open(RelationRelationId, RowExclusiveLock);	tuple = SearchSysCacheCopy(RELOID,							   ObjectIdGetDatum(relationId),							   0, 0, 0);	if (!HeapTupleIsValid(tuple))		elog(ERROR, "cache lookup failed for relation %u", relationId);	classtuple = (Form_pg_class) GETSTRUCT(tuple);	if (classtuple->relhassubclass != relhassubclass)	{		classtuple->relhassubclass = relhassubclass;		simple_heap_update(relationRelation, &tuple->t_self, tuple);		/* keep the catalog indexes up to date */		CatalogUpdateIndexes(relationRelation, tuple);	}	else	{		/* no need to change tuple, but force relcache rebuild anyway */		CacheInvalidateRelcacheByTuple(tuple);	}	heap_freetuple(tuple);	heap_close(relationRelation, RowExclusiveLock);}/* *		renameatt		- changes the name of a attribute in a relation * *		Attname attribute is changed in attribute catalog. *		No record of the previous attname is kept (correct?). * *		get proper relrelation from relation catalog (if not arg) *		scan attribute catalog *				for name conflict (within rel) *				for original attribute (if not arg) *		modify attname in attribute tuple *		insert modified attribute in attribute catalog *		delete original attribute from attribute catalog */voidrenameatt(Oid myrelid,		  const char *oldattname,		  const char *newattname,		  bool recurse,		  bool recursing){	Relation	targetrelation;	Relation	attrelation;	HeapTuple	atttup;	Form_pg_attribute attform;	int			attnum;	List	   *indexoidlist;	ListCell   *indexoidscan;	/*	 * Grab an exclusive lock on the target table, which we will NOT release	 * until end of transaction.	 */	targetrelation = relation_open(myrelid, AccessExclusiveLock);	/*	 * permissions checking.  this would normally be done in utility.c, but	 * this particular routine is recursive.	 *	 * normally, only the owner of a class can change its schema.	 */

⌨️ 快捷键说明

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