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

📄 heap.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 4 页
字号:
/*------------------------------------------------------------------------- * * heap.c *	  code to create and destroy POSTGRES heap relations * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.292.2.2 2006/04/24 01:40:39 alvherre Exp $ * * * INTERFACE ROUTINES *		heap_create()			- Create an uncataloged heap relation *		heap_create_with_catalog() - Create a cataloged relation *		heap_drop_with_catalog() - Removes named relation from catalogs * * NOTES *	  this code taken from access/heap/create.c, which contains *	  the old heap_create_with_catalog, amcreate, and amdestroy. *	  those routines will soon call these routines using the function *	  manager, *	  just like the poorly named "NewXXX" routines do.	The *	  "New" routines are all going to die soon, once and for all! *		-cim 1/13/91 * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/heapam.h"#include "access/genam.h"#include "catalog/catalog.h"#include "catalog/dependency.h"#include "catalog/heap.h"#include "catalog/index.h"#include "catalog/indexing.h"#include "catalog/pg_attrdef.h"#include "catalog/pg_constraint.h"#include "catalog/pg_inherits.h"#include "catalog/pg_namespace.h"#include "catalog/pg_statistic.h"#include "catalog/pg_type.h"#include "commands/tablecmds.h"#include "commands/trigger.h"#include "miscadmin.h"#include "nodes/makefuncs.h"#include "optimizer/clauses.h"#include "optimizer/planmain.h"#include "optimizer/var.h"#include "parser/parse_coerce.h"#include "parser/parse_expr.h"#include "parser/parse_relation.h"#include "rewrite/rewriteRemove.h"#include "storage/smgr.h"#include "utils/builtins.h"#include "utils/fmgroids.h"#include "utils/inval.h"#include "utils/lsyscache.h"#include "utils/relcache.h"#include "utils/syscache.h"static void AddNewRelationTuple(Relation pg_class_desc,					Relation new_rel_desc,					Oid new_rel_oid, Oid new_type_oid,					Oid relowner,					char relkind);static Oid AddNewRelationType(const char *typeName,				   Oid typeNamespace,				   Oid new_rel_oid,				   char new_rel_kind);static void RelationRemoveInheritance(Oid relid);static void StoreRelCheck(Relation rel, char *ccname, char *ccbin);static void StoreConstraints(Relation rel, TupleDesc tupdesc);static void SetRelationNumChecks(Relation rel, int numchecks);/* ---------------------------------------------------------------- *				XXX UGLY HARD CODED BADNESS FOLLOWS XXX * *		these should all be moved to someplace in the lib/catalog *		module, if not obliterated first. * ---------------------------------------------------------------- *//* * Note: *		Should the system special case these attributes in the future? *		Advantage:	consume much less space in the ATTRIBUTE relation. *		Disadvantage:  special cases will be all over the place. */static FormData_pg_attribute a1 = {	0, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData),	SelfItemPointerAttributeNumber, 0, -1, -1,	false, 'p', 's', true, false, false, true, 0};static FormData_pg_attribute a2 = {	0, {"oid"}, OIDOID, 0, sizeof(Oid),	ObjectIdAttributeNumber, 0, -1, -1,	true, 'p', 'i', true, false, false, true, 0};static FormData_pg_attribute a3 = {	0, {"xmin"}, XIDOID, 0, sizeof(TransactionId),	MinTransactionIdAttributeNumber, 0, -1, -1,	true, 'p', 'i', true, false, false, true, 0};static FormData_pg_attribute a4 = {	0, {"cmin"}, CIDOID, 0, sizeof(CommandId),	MinCommandIdAttributeNumber, 0, -1, -1,	true, 'p', 'i', true, false, false, true, 0};static FormData_pg_attribute a5 = {	0, {"xmax"}, XIDOID, 0, sizeof(TransactionId),	MaxTransactionIdAttributeNumber, 0, -1, -1,	true, 'p', 'i', true, false, false, true, 0};static FormData_pg_attribute a6 = {	0, {"cmax"}, CIDOID, 0, sizeof(CommandId),	MaxCommandIdAttributeNumber, 0, -1, -1,	true, 'p', 'i', true, false, false, true, 0};/* * We decided to call this attribute "tableoid" rather than say * "classoid" on the basis that in the future there may be more than one * table of a particular class/type. In any case table is still the word * used in SQL. */static FormData_pg_attribute a7 = {	0, {"tableoid"}, OIDOID, 0, sizeof(Oid),	TableOidAttributeNumber, 0, -1, -1,	true, 'p', 'i', true, false, false, true, 0};static const Form_pg_attribute SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6, &a7};/* * This function returns a Form_pg_attribute pointer for a system attribute. * Note that we elog if the presented attno is invalid, which would only * happen if there's a problem upstream. */Form_pg_attributeSystemAttributeDefinition(AttrNumber attno, bool relhasoids){	if (attno >= 0 || attno < -(int) lengthof(SysAtt))		elog(ERROR, "invalid system attribute number %d", attno);	if (attno == ObjectIdAttributeNumber && !relhasoids)		elog(ERROR, "invalid system attribute number %d", attno);	return SysAtt[-attno - 1];}/* * If the given name is a system attribute name, return a Form_pg_attribute * pointer for a prototype definition.	If not, return NULL. */Form_pg_attributeSystemAttributeByName(const char *attname, bool relhasoids){	int			j;	for (j = 0; j < (int) lengthof(SysAtt); j++)	{		Form_pg_attribute att = SysAtt[j];		if (relhasoids || att->attnum != ObjectIdAttributeNumber)		{			if (strcmp(NameStr(att->attname), attname) == 0)				return att;		}	}	return NULL;}/* ---------------------------------------------------------------- *				XXX END OF UGLY HARD CODED BADNESS XXX * ---------------------------------------------------------------- *//* ---------------------------------------------------------------- *		heap_create		- Create an uncataloged heap relation * *		Note API change: the caller must now always provide the OID *		to use for the relation. * *		rel->rd_rel is initialized by RelationBuildLocalRelation, *		and is mostly zeroes at return. * ---------------------------------------------------------------- */Relationheap_create(const char *relname,			Oid relnamespace,			Oid reltablespace,			Oid relid,			TupleDesc tupDesc,			char relkind,			bool shared_relation,			bool allow_system_table_mods){	bool		create_storage;	Relation	rel;	/* The caller must have provided an OID for the relation. */	Assert(OidIsValid(relid));	/*	 * sanity checks	 */	if (!allow_system_table_mods &&		(IsSystemNamespace(relnamespace) || IsToastNamespace(relnamespace)) &&		IsNormalProcessingMode())		ereport(ERROR,				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				 errmsg("permission denied to create \"%s.%s\"",						get_namespace_name(relnamespace), relname),		errdetail("System catalog modifications are currently disallowed.")));	/*	 * Decide if we need storage or not, and handle a couple other special	 * cases for particular relkinds.	 */	switch (relkind)	{		case RELKIND_VIEW:		case RELKIND_COMPOSITE_TYPE:			create_storage = false;			/*			 * Force reltablespace to zero if the relation has no physical			 * storage.  This is mainly just for cleanliness' sake.			 */			reltablespace = InvalidOid;			break;		case RELKIND_SEQUENCE:			create_storage = true;			/*			 * Force reltablespace to zero for sequences, since we don't			 * support moving them around into different tablespaces.			 */			reltablespace = InvalidOid;			break;		default:			create_storage = true;			break;	}	/*	 * Never allow a pg_class entry to explicitly specify the database's	 * default tablespace in reltablespace; force it to zero instead. This	 * ensures that if the database is cloned with a different default	 * tablespace, the pg_class entry will still match where CREATE DATABASE	 * will put the physically copied relation.	 *	 * Yes, this is a bit of a hack.	 */	if (reltablespace == MyDatabaseTableSpace)		reltablespace = InvalidOid;	/*	 * build the relcache entry.	 */	rel = RelationBuildLocalRelation(relname,									 relnamespace,									 tupDesc,									 relid,									 reltablespace,									 shared_relation);	/*	 * have the storage manager create the relation's disk file, if needed.	 */	if (create_storage)	{		Assert(rel->rd_smgr == NULL);		RelationOpenSmgr(rel);		smgrcreate(rel->rd_smgr, rel->rd_istemp, false);	}	return rel;}/* ---------------------------------------------------------------- *		heap_create_with_catalog		- Create a cataloged relation * *		this is done in multiple steps: * *		1) CheckAttributeNamesTypes() is used to make certain the tuple *		   descriptor contains a valid set of attribute names and types * *		2) pg_class is opened and get_relname_relid() *		   performs a scan to ensure that no relation with the *		   same name already exists. * *		3) heap_create() is called to create the new relation on disk. * *		4) TypeCreate() is called to define a new type corresponding *		   to the new relation. * *		5) AddNewRelationTuple() is called to register the *		   relation in pg_class. * *		6) AddNewAttributeTuples() is called to register the *		   new relation's schema in pg_attribute. * *		7) StoreConstraints is called ()		- vadim 08/22/97 * *		8) the relations are closed and the new relation's oid *		   is returned. * * ---------------------------------------------------------------- *//* -------------------------------- *		CheckAttributeNamesTypes * *		this is used to make certain the tuple descriptor contains a *		valid set of attribute names and datatypes.  a problem simply *		generates ereport(ERROR) which aborts the current transaction. * -------------------------------- */voidCheckAttributeNamesTypes(TupleDesc tupdesc, char relkind){	int			i;	int			j;	int			natts = tupdesc->natts;	/* Sanity check on column count */	if (natts < 0 || natts > MaxHeapAttributeNumber)		ereport(ERROR,				(errcode(ERRCODE_TOO_MANY_COLUMNS),				 errmsg("tables can have at most %d columns",						MaxHeapAttributeNumber)));	/*	 * first check for collision with system attribute names	 *	 * Skip this for a view or type relation, since those don't have system	 * attributes.	 */	if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)	{		for (i = 0; i < natts; i++)		{			if (SystemAttributeByName(NameStr(tupdesc->attrs[i]->attname),									  tupdesc->tdhasoid) != NULL)				ereport(ERROR,						(errcode(ERRCODE_DUPLICATE_COLUMN),						 errmsg("column name \"%s\" conflicts with a system column name",								NameStr(tupdesc->attrs[i]->attname))));		}	}	/*	 * next check for repeated attribute names	 */	for (i = 1; i < natts; i++)	{		for (j = 0; j < i; j++)		{			if (strcmp(NameStr(tupdesc->attrs[j]->attname),					   NameStr(tupdesc->attrs[i]->attname)) == 0)				ereport(ERROR,						(errcode(ERRCODE_DUPLICATE_COLUMN),						 errmsg("column name \"%s\" is duplicated",								NameStr(tupdesc->attrs[j]->attname))));		}	}	/*	 * next check the attribute types	 */	for (i = 0; i < natts; i++)	{		CheckAttributeType(NameStr(tupdesc->attrs[i]->attname),						   tupdesc->attrs[i]->atttypid);	}}/* -------------------------------- *		CheckAttributeType * *		Verify that the proposed datatype of an attribute is legal. *		This is needed because there are types (and pseudo-types) *		in the catalogs that we do not support as elements of real tuples. * -------------------------------- */voidCheckAttributeType(const char *attname, Oid atttypid){	char		att_typtype = get_typtype(atttypid);	/*	 * Warn user, but don't fail, if column to be created has UNKNOWN type	 * (usually as a result of a 'retrieve into' - jolly)	 *	 * Refuse any attempt to create a pseudo-type column.	 */	if (atttypid == UNKNOWNOID)		ereport(WARNING,				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),				 errmsg("column \"%s\" has type \"unknown\"", attname),				 errdetail("Proceeding with relation creation anyway.")));	else if (att_typtype == 'p')	{		/* Special hack for pg_statistic: allow ANYARRAY during initdb */		if (atttypid != ANYARRAYOID || IsUnderPostmaster)			ereport(ERROR,					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),					 errmsg("column \"%s\" has pseudo-type %s",							attname, format_type_be(atttypid))));	}}/* -------------------------------- *		AddNewAttributeTuples * *		this registers the new relation's schema by adding *		tuples to pg_attribute. * -------------------------------- */static voidAddNewAttributeTuples(Oid new_rel_oid,					  TupleDesc tupdesc,					  char relkind,					  bool oidislocal,					  int oidinhcount){	const Form_pg_attribute *dpp;	int			i;	HeapTuple	tup;	Relation	rel;	CatalogIndexState indstate;	int			natts = tupdesc->natts;	ObjectAddress myself,				referenced;	/*	 * open pg_attribute and its indexes.	 */	rel = heap_open(AttributeRelationId, RowExclusiveLock);	indstate = CatalogOpenIndexes(rel);	/*	 * First we add the user attributes.  This is also a convenient place to	 * add dependencies on their datatypes.	 */	dpp = tupdesc->attrs;	for (i = 0; i < natts; i++)	{		/* Fill in the correct relation OID */		(*dpp)->attrelid = new_rel_oid;		/* Make sure these are OK, too */		(*dpp)->attstattarget = -1;		(*dpp)->attcacheoff = -1;		tup = heap_addheader(Natts_pg_attribute,							 false,							 ATTRIBUTE_TUPLE_SIZE,							 (void *) *dpp);		simple_heap_insert(rel, tup);		CatalogIndexInsert(indstate, tup);		heap_freetuple(tup);		myself.classId = RelationRelationId;		myself.objectId = new_rel_oid;		myself.objectSubId = i + 1;		referenced.classId = TypeRelationId;		referenced.objectId = (*dpp)->atttypid;		referenced.objectSubId = 0;		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);		dpp++;	}	/*	 * Next we add the system attributes.  Skip OID if rel has no OIDs. Skip	 * all for a view or type relation.  We don't bother with making datatype	 * dependencies here, since presumably all these types are pinned.	 */	if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)	{		dpp = SysAtt;		for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++)		{			if (tupdesc->tdhasoid ||				(*dpp)->attnum != ObjectIdAttributeNumber)			{				Form_pg_attribute attStruct;				tup = heap_addheader(Natts_pg_attribute,									 false,									 ATTRIBUTE_TUPLE_SIZE,									 (void *) *dpp);				attStruct = (Form_pg_attribute) GETSTRUCT(tup);				/* Fill in the correct relation OID in the copied tuple */				attStruct->attrelid = new_rel_oid;				/* Fill in correct inheritance info for the OID column */				if (attStruct->attnum == ObjectIdAttributeNumber)				{					attStruct->attislocal = oidislocal;					attStruct->attinhcount = oidinhcount;				}

⌨️ 快捷键说明

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