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

📄 heap.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
/*------------------------------------------------------------------------- * * heap.c *	  code to create and destroy POSTGRES heap relations * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/catalog/heap.c,v 1.89 1999/07/08 02:46:37 momjian Exp $ * * * INTERFACE ROUTINES *		heap_create()			- Create an uncataloged heap relation *		heap_create_with_catalog() - Create a cataloged relation *		heap_destroy_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 "miscadmin.h"#include "access/heapam.h"#include "catalog/catalog.h"#include "catalog/catname.h"#include "catalog/heap.h"#include "catalog/index.h"#include "catalog/indexing.h"#include "catalog/pg_attrdef.h"#include "catalog/pg_index.h"#include "catalog/pg_inherits.h"#include "catalog/pg_ipl.h"#include "catalog/pg_relcheck.h"#include "catalog/pg_type.h"#include "commands/trigger.h"#include "fmgr.h"#include "nodes/plannodes.h"#include "optimizer/tlist.h"#include "parser/parse_expr.h"#include "parser/parse_node.h"#include "parser/parse_target.h"#include "parser/parse_type.h"#include "parser/parse_coerce.h"#include "rewrite/rewriteRemove.h"#include "storage/bufmgr.h"#include "storage/lmgr.h"#include "storage/smgr.h"#include "tcop/tcopprot.h"#include "utils/catcache.h"#include "utils/builtins.h"#include "utils/mcxt.h"#include "utils/relcache.h"#include "utils/syscache.h"#include "utils/tqual.h"#include "utils/temprel.h"#ifndef HAVE_MEMMOVE#include <regex/utils.h>#else#include <string.h>#endifstatic void AddNewRelationTuple(Relation pg_class_desc,				  Relation new_rel_desc, Oid new_rel_oid, unsigned natts,					char relkind, char *temp_relname);static void AddToNoNameRelList(Relation r);static void DeleteAttributeTuples(Relation rel);static void DeleteRelationTuple(Relation rel);static void DeleteTypeTuple(Relation rel);static void RelationRemoveIndexes(Relation relation);static void RelationRemoveInheritance(Relation relation);static void RemoveFromNoNameRelList(Relation r);static void AddNewRelationType(char *typeName, Oid new_rel_oid);static void StoreConstraints(Relation rel);static void RemoveConstraints(Relation rel);/* ---------------------------------------------------------------- *				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 executor special case these attributes in the future? *		Advantage:	consume 1/2 the space in the ATTRIBUTE relation. *		Disadvantage:  having rules to compute values in these tuples may *				be more difficult if not impossible. */static FormData_pg_attribute a1 = {	0xffffffff, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData),	SelfItemPointerAttributeNumber, 0, -1, -1, '\0', '\0', 'i', '\0', '\0'};static FormData_pg_attribute a2 = {	0xffffffff, {"oid"}, OIDOID, 0, sizeof(Oid),	ObjectIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'};static FormData_pg_attribute a3 = {	0xffffffff, {"xmin"}, XIDOID, 0, sizeof(TransactionId),	MinTransactionIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'};static FormData_pg_attribute a4 = {	0xffffffff, {"cmin"}, CIDOID, 0, sizeof(CommandId),	MinCommandIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'};static FormData_pg_attribute a5 = {	0xffffffff, {"xmax"}, XIDOID, 0, sizeof(TransactionId),	MaxTransactionIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'};static FormData_pg_attribute a6 = {	0xffffffff, {"cmax"}, CIDOID, 0, sizeof(CommandId),	MaxCommandIdAttributeNumber, 0, -1, -1, '\001', '\0', 'i', '\0', '\0'};static Form_pg_attribute HeapAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6};/* ---------------------------------------------------------------- *				XXX END OF UGLY HARD CODED BADNESS XXX * ---------------------------------------------------------------- *//* the tempRelList holds   the list of temporary uncatalogued relations that are created.   these relations should be destroyed at the end of transactions*/typedef struct tempRelList{	Relation   *rels;			/* array of relation descriptors */	int			num;			/* number of temporary relations */	int			size;			/* size of space allocated for the rels								 * array */} TempRelList;#define NONAME_REL_LIST_SIZE	32static TempRelList *tempRels = NULL;/* ---------------------------------------------------------------- *		heap_create		- Create an uncataloged heap relation * *		Fields relpages, reltuples, reltuples, relkeys, relhistory, *		relisindexed, and relkind of rel->rd_rel are initialized *		to all zeros, as are rd_last and rd_hook.  Rd_refcnt is set to 1. * *		Remove the system relation specific code to elsewhere eventually. * *		Eventually, must place information about this temporary relation *		into the transaction context block. * * * if heap_create is called with "" as the name, then heap_create will create * a temporary name "pg_noname.$PID.$SEQUENCE" for the relation * ---------------------------------------------------------------- */Relationheap_create(char *relname,			TupleDesc tupDesc,			bool isnoname,			bool istemp){	unsigned	i;	Oid			relid;	Relation	rel;	int			len;	bool		nailme = false;	int			natts = tupDesc->natts;	static unsigned int uniqueId = 0;	extern GlobalMemory CacheCxt;	MemoryContext oldcxt;	/* ----------------	 *	sanity checks	 * ----------------	 */	AssertArg(natts > 0);	if (relname && !allowSystemTableMods && IsSystemRelationName(relname) && IsNormalProcessingMode())	{		elog(ERROR, "Illegal class name '%s'"			 "\n\tThe 'pg_' name prefix is reserved for system catalogs",			 relname);	}	/* ----------------	 *	switch to the cache context so that we don't lose	 *	allocations at the end of this transaction, I guess.	 *	-cim 6/14/90	 * ----------------	 */	if (!CacheCxt)		CacheCxt = CreateGlobalMemory("Cache");	oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);	/* ----------------	 *	real ugly stuff to assign the proper relid in the relation	 *	descriptor follows.	 * ----------------	 */	if (relname && !strcmp(RelationRelationName, relname))	{		relid = RelOid_pg_class;		nailme = true;	}	else if (relname && !strcmp(AttributeRelationName, relname))	{		relid = RelOid_pg_attribute;		nailme = true;	}	else if (relname && !strcmp(ProcedureRelationName, relname))	{		relid = RelOid_pg_proc;		nailme = true;	}	else if (relname && !strcmp(TypeRelationName, relname))	{		relid = RelOid_pg_type;		nailme = true;	}	else		relid = newoid();	if (isnoname)	{		Assert(!relname);		relname = palloc(NAMEDATALEN);		snprintf(relname, NAMEDATALEN, "pg_noname.%d.%u",				 (int) MyProcPid, uniqueId++);	}	if (istemp)	{		/* replace relname of caller */		snprintf(relname, NAMEDATALEN, "pg_temp.%d.%u",				 MyProcPid, uniqueId++);	}	/* ----------------	 *	allocate a new relation descriptor.	 *	 *	XXX the length computation may be incorrect, handle elsewhere	 * ----------------	 */	len = sizeof(RelationData);	rel = (Relation) palloc(len);	MemSet((char *) rel, 0, len);	/*	 * create a new tuple descriptor from the one passed in	 */	rel->rd_att = CreateTupleDescCopyConstr(tupDesc);	/* ----------------	 *	nail the reldesc if this is a bootstrap create reln and	 *	we may need it in the cache later on in the bootstrap	 *	process so we don't ever want it kicked out.  e.g. pg_attribute!!!	 * ----------------	 */	if (nailme)		rel->rd_isnailed = true;	RelationSetReferenceCount(rel, 1);	rel->rd_rel = (Form_pg_class) palloc(sizeof *rel->rd_rel);	/* ----------------	 *	initialize the fields of our new relation descriptor	 * ----------------	 */	MemSet((char *) rel->rd_rel, 0, sizeof *rel->rd_rel);	namestrcpy(&(rel->rd_rel->relname), relname);	rel->rd_rel->relkind = RELKIND_UNCATALOGED;	rel->rd_rel->relnatts = natts;	if (tupDesc->constr)		rel->rd_rel->relchecks = tupDesc->constr->num_check;	for (i = 0; i < natts; i++)		rel->rd_att->attrs[i]->attrelid = relid;	RelationGetRelid(rel) = relid;	if (nailme)	{		/* for system relations, set the reltype field here */		rel->rd_rel->reltype = relid;	}	/* ----------------	 *	remember if this is a noname relation	 * ----------------	 */	rel->rd_isnoname = isnoname;	/* ----------------	 *	have the storage manager create the relation.	 * ----------------	 */	rel->rd_nonameunlinked = TRUE;		/* change once table is created */	rel->rd_fd = (File) smgrcreate(DEFAULT_SMGR, rel);	rel->rd_nonameunlinked = FALSE;	RelationRegisterRelation(rel);	MemoryContextSwitchTo(oldcxt);	/*	 * add all noname relations to the tempRels list so they can be	 * properly disposed of at the end of transaction	 */	if (isnoname)		AddToNoNameRelList(rel);	return rel;}/* ---------------------------------------------------------------- *		heap_create_with_catalog		- Create a cataloged relation * *		this is done in 6 steps: * *		1) CheckAttributeNames() is used to make certain the tuple *		   descriptor contains a valid set of attribute names * *		2) pg_class is opened and RelationFindRelid() *		   preforms a scan to ensure that no relation with the *		   same name already exists. * *		3) heap_create_with_catalog() is called to create the new relation *		   on disk. * *		4) TypeDefine() is called to define a new type corresponding *		   to the new relation. * *		5) AddNewAttributeTuples() is called to register the *		   new relation's schema in pg_attribute. * *		6) AddNewRelationTuple() is called to register the *		   relation itself in the catalogs. * *		7) StoreConstraints is called ()		- vadim 08/22/97 * *		8) the relations are closed and the new relation's oid *		   is returned. * * old comments: *		A new relation is inserted into the RELATION relation *		with the specified attribute(s) (newly inserted into *		the ATTRIBUTE relation).  How does concurrency control *		work?  Is it automatic now?  Expects the caller to have *		attname, atttypid, atttyparg, attproc, and attlen domains filled. *		Create fills the attnum domains sequentually from zero, *		fills the attdisbursion domains with zeros, and fills the *		attrelid fields with the relid. * *		scan relation catalog for name conflict *		scan type catalog for typids (if not arg) *		create and insert attribute(s) into attribute catalog *		create new relation *		insert new relation into attribute catalog * *		Should coordinate with heap_create_with_catalog(). Either *		it should not be called or there should be a way to prevent *		the relation from being removed at the end of the *		transaction if it is successful ('u'/'r' may be enough). *		Also, if the transaction does not commit, then the *		relation should be removed. * *		XXX amcreate ignores "off" when inserting (for now). *		XXX amcreate (like the other utilities) needs to understand indexes. * * ---------------------------------------------------------------- *//* -------------------------------- *		CheckAttributeNames * *		this is used to make certain the tuple descriptor contains a *		valid set of attribute names.  a problem simply generates *		elog(ERROR) which aborts the current transaction. * -------------------------------- */static voidCheckAttributeNames(TupleDesc tupdesc){	unsigned	i;	unsigned	j;	int			natts = tupdesc->natts;	/* ----------------	 *	first check for collision with system attribute names	 * ----------------	 *	 *	 also, warn user if attribute to be created has	 *	 an unknown typid  (usually as a result of a 'retrieve into'	 *	  - jolly	 */	for (i = 0; i < natts; i += 1)	{		for (j = 0; j < sizeof HeapAtt / sizeof HeapAtt[0]; j += 1)		{			if (nameeq(&(HeapAtt[j]->attname),					   &(tupdesc->attrs[i]->attname)))			{				elog(ERROR, "Attribute '%s' has a name conflict"					 "\n\tName matches an existing system attribute",					 HeapAtt[j]->attname.data);			}		}		if (tupdesc->attrs[i]->atttypid == UNKNOWNOID)		{			elog(NOTICE, "Attribute '%s' has an unknown type"				 "\n\tRelation created; continue",				 tupdesc->attrs[i]->attname.data);		}	}	/* ----------------	 *	next check for repeated attribute names	 * ----------------	 */	for (i = 1; i < natts; i += 1)	{		for (j = 0; j < i; j += 1)		{			if (nameeq(&(tupdesc->attrs[j]->attname),					   &(tupdesc->attrs[i]->attname)))			{				elog(ERROR, "Attribute '%s' is repeated",					 tupdesc->attrs[j]->attname.data);			}		}	}}/* -------------------------------- *		RelnameFindRelid * *		this preforms a scan of pg_class to ensure that *		no relation with the same name already exists. * -------------------------------- */OidRelnameFindRelid(char *relname){	HeapTuple	tuple;	Oid			relid;	/*	 * If this is not bootstrap (initdb) time, use the catalog index on	 * pg_class.	 */	if (!IsBootstrapProcessingMode())	{		tuple = SearchSysCacheTuple(RELNAME,									PointerGetDatum(relname),									0, 0, 0);		if (HeapTupleIsValid(tuple))			relid = tuple->t_data->t_oid;		else			relid = InvalidOid;	}	else	{		Relation	pg_class_desc;		ScanKeyData key;		HeapScanDesc pg_class_scan;		pg_class_desc = heap_openr(RelationRelationName);		/* ----------------		 *	At bootstrap time, we have to do this the hard way.  Form the		 *	scan key.		 * ----------------		 */		ScanKeyEntryInitialize(&key,							   0,							   (AttrNumber) Anum_pg_class_relname,							   (RegProcedure) F_NAMEEQ,							   (Datum) relname);		/* ----------------		 *	begin the scan		 * ----------------		 */		pg_class_scan = heap_beginscan(pg_class_desc,									   0,									   SnapshotNow,									   1,									   &key);		/* ----------------		 *	get a tuple.  if the tuple is NULL then it means we		 *	didn't find an existing relation.		 * ----------------		 */		tuple = heap_getnext(pg_class_scan, 0);		if (HeapTupleIsValid(tuple))			relid = tuple->t_data->t_oid;		else			relid = InvalidOid;		heap_endscan(pg_class_scan);		heap_close(pg_class_desc);	}	return relid;}/* -------------------------------- *		AddNewAttributeTuples * *		this registers the new relation's schema by adding *		tuples to pg_attribute. * -------------------------------- */static voidAddNewAttributeTuples(Oid new_rel_oid,					  TupleDesc tupdesc){	Form_pg_attribute *dpp;	unsigned	i;	HeapTuple	tup;	Relation	rel;	bool		hasindex;	Relation	idescs[Num_pg_attr_indices];	int			natts = tupdesc->natts;	/* ----------------	 *	open pg_attribute	 * ----------------	 */	rel = heap_openr(AttributeRelationName);	/* -----------------	 * Check if we have any indices defined on pg_attribute.	 * -----------------	 */	Assert(rel);	Assert(rel->rd_rel);	hasindex = RelationGetForm(rel)->relhasindex;	if (hasindex)		CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);	/* ----------------	 *	initialize tuple descriptor.  Note we use setheapoverride()	 *	so that we can see the effects of our TypeDefine() done	 *	previously.	 * ----------------	 */	setheapoverride(true);	fillatt(tupdesc);	setheapoverride(false);

⌨️ 快捷键说明

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