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

📄 command.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
字号:
/*------------------------------------------------------------------------- * * command.c *	  random postgres portal and utility support code * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/commands/command.c,v 1.47.2.1 1999/08/02 05:56:57 scrappy Exp $ * * NOTES *	  The PortalExecutorHeapMemory crap needs to be eliminated *	  by designing a better executor / portal processing memory *	  interface. * *	  The PerformAddAttribute() code, like most of the relation *	  manipulating code in the commands/ directory, should go *	  someplace closer to the lib/catalog code. * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/heapam.h"#include "catalog/catalog.h"#include "catalog/catname.h"#include "catalog/indexing.h"#include "catalog/pg_type.h"#include "commands/command.h"#include "executor/execdefs.h"#include "executor/executor.h"#include "miscadmin.h"#include "optimizer/prep.h"#include "utils/acl.h"#include "utils/builtins.h"#include "utils/syscache.h"#include "utils/temprel.h"/* ---------------- *		PortalExecutorHeapMemory stuff * *		This is where the XXXSuperDuperHacky code was. -cim 3/15/90 * ---------------- */MemoryContext PortalExecutorHeapMemory = NULL;/* -------------------------------- *		PortalCleanup * -------------------------------- */voidPortalCleanup(Portal portal){	MemoryContext context;	/* ----------------	 *	sanity checks	 * ----------------	 */	AssertArg(PortalIsValid(portal));	AssertArg(portal->cleanup == PortalCleanup);	/* ----------------	 *	set proper portal-executor context before calling ExecMain.	 * ----------------	 */	context = MemoryContextSwitchTo((MemoryContext) PortalGetHeapMemory(portal));	PortalExecutorHeapMemory = (MemoryContext) PortalGetHeapMemory(portal);	/* ----------------	 *	tell the executor to shutdown the query	 * ----------------	 */	ExecutorEnd(PortalGetQueryDesc(portal), PortalGetState(portal));	/* ----------------	 *	switch back to previous context	 * ----------------	 */	MemoryContextSwitchTo(context);	PortalExecutorHeapMemory = (MemoryContext) NULL;}/* -------------------------------- *		PerformPortalFetch * -------------------------------- */voidPerformPortalFetch(char *name,				   bool forward,				   int count,				   char *tag,				   CommandDest dest){	Portal		portal;	int			feature;	QueryDesc  *queryDesc;	MemoryContext context;	Const		limcount;	/* ----------------	 *	sanity checks	 * ----------------	 */	if (name == NULL)	{		elog(NOTICE, "PerformPortalFetch: blank portal unsupported");		return;	}	/* ----------------	 *	Create a const node from the given count value	 * ----------------	 */	memset(&limcount, 0, sizeof(limcount));	limcount.type = T_Const;	limcount.consttype = INT4OID;	limcount.constlen = sizeof(int4);	limcount.constvalue = (Datum) count;	limcount.constisnull = FALSE;	limcount.constbyval = TRUE;	limcount.constisset = FALSE;	limcount.constiscast = FALSE;	/* ----------------	 *	get the portal from the portal name	 * ----------------	 */	portal = GetPortalByName(name);	if (!PortalIsValid(portal))	{		elog(NOTICE, "PerformPortalFetch: portal \"%s\" not found",			 name);		return;	}	/* ----------------	 *	switch into the portal context	 * ----------------	 */	context = MemoryContextSwitchTo((MemoryContext) PortalGetHeapMemory(portal));	AssertState(context == (MemoryContext) PortalGetHeapMemory(GetPortalByName(NULL)));	/* ----------------	 *	setup "feature" to tell the executor what direction and	 *	how many tuples to fetch.	 * ----------------	 */	if (forward)		feature = EXEC_FOR;	else		feature = EXEC_BACK;	/* ----------------	 *	tell the destination to prepare to recieve some tuples	 * ----------------	 */	queryDesc = PortalGetQueryDesc(portal);	if (dest == None)			/* MOVE */	{		QueryDesc  *qdesc = (QueryDesc *) palloc(sizeof(QueryDesc));		memcpy(qdesc, queryDesc, sizeof(QueryDesc));		qdesc->dest = dest;		queryDesc = qdesc;	}	BeginCommand(name,				 queryDesc->operation,				 portal->attinfo,		/* QueryDescGetTypeInfo(queryDesc),										 * */				 false,			/* portal fetches don't end up in								 * relations */				 false,			/* this is a portal fetch, not a "retrieve								 * portal" */				 tag,				 dest);	/* ----------------	 *	execute the portal fetch operation	 * ----------------	 */	PortalExecutorHeapMemory = (MemoryContext) PortalGetHeapMemory(portal);	ExecutorRun(queryDesc, PortalGetState(portal), feature,				(Node *) NULL, (Node *) &limcount);	if (dest == None)			/* MOVE */		pfree(queryDesc);	/* ----------------	 * Note: the "end-of-command" tag is returned by higher-level	 *		 utility code	 *	 * Return blank portal for now.	 * Otherwise, this named portal will be cleaned.	 * Note: portals will only be supported within a BEGIN...END	 * block in the near future.  Later, someone will fix it to	 * do what is possible across transaction boundries.	 * ----------------	 */	MemoryContextSwitchTo(			 (MemoryContext) PortalGetHeapMemory(GetPortalByName(NULL)));}/* -------------------------------- *		PerformPortalClose * -------------------------------- */voidPerformPortalClose(char *name, CommandDest dest){	Portal		portal;	/* ----------------	 *	sanity checks	 * ----------------	 */	if (name == NULL)	{		elog(NOTICE, "PerformPortalClose: blank portal unsupported");		return;	}	/* ----------------	 *	get the portal from the portal name	 * ----------------	 */	portal = GetPortalByName(name);	if (!PortalIsValid(portal))	{		elog(NOTICE, "PerformPortalClose: portal \"%s\" not found",			 name);		return;	}	/* ----------------	 *	Note: PortalCleanup is called as a side-effect	 * ----------------	 */	PortalDestroy(&portal);}/* ---------------- *		PerformAddAttribute * *		adds an additional attribute to a relation * *		Adds attribute field(s) to a relation.	Each new attribute *		is given attnums in sequential order and is added to the *		ATTRIBUTE relation.  If the AMI fails, defunct tuples will *		remain in the ATTRIBUTE relation for later vacuuming. *		Later, there may be some reserved attribute names??? * *		(If needed, can instead use elog to handle exceptions.) * *		Note: *				Initial idea of ordering the tuple attributes so that all *		the variable length domains occured last was scratched.  Doing *		so would not speed access too much (in general) and would create *		many complications in formtuple, amgetattr, and addattribute. * *		scan attribute catalog for name conflict (within rel) *		scan type catalog for absence of data type (if not arg) *		create attnum magically??? *		create attribute tuple *		insert attribute in attribute catalog *		modify reldesc *		create new relation tuple *		insert new relation in relation catalog *		delete original relation from relation catalog * ---------------- */voidPerformAddAttribute(char *relationName,					char *userName,					bool inherits,					ColumnDef *colDef){	Relation	rel,				attrdesc;	HeapTuple	reltup;	HeapTuple	attributeTuple;	Form_pg_attribute attribute;	FormData_pg_attribute attributeD;	int			i;	int			minattnum,				maxatts;	HeapTuple	tup;	Relation	idescs[Num_pg_attr_indices];	Relation	ridescs[Num_pg_class_indices];	bool		hasindex;	/*	 * 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.	 */	if (!allowSystemTableMods && IsSystemRelationName(relationName))		elog(ERROR, "PerformAddAttribute: class \"%s\" is a system catalog",			 relationName);#ifndef NO_SECURITY	if (!pg_ownercheck(userName, relationName, RELNAME))		elog(ERROR, "PerformAddAttribute: you do not own class \"%s\"",			 relationName);#endif	/*	 * we can't add a not null attribute	 */	if (colDef->is_not_null)		elog(ERROR, "Can't add a NOT NULL attribute to an existing relation");	if (colDef->defval)		elog(ERROR, "ADD ATTRIBUTE: DEFAULT not yet implemented");	/*	 * if the first element in the 'schema' list is a "*" then we are	 * supposed to add this attribute to all classes that inherit from	 * 'relationName' (as well as to 'relationName').	 *	 * any permissions or problems with duplicate attributes will cause the	 * whole transaction to abort, which is what we want -- all or	 * nothing.	 */	if (colDef != NULL)	{		if (inherits)		{			Oid			myrelid,						childrelid;			List	   *child,					   *children;			rel = heap_openr(relationName);			if (!RelationIsValid(rel))			{				elog(ERROR, "PerformAddAttribute: unknown relation: \"%s\"",					 relationName);			}			myrelid = RelationGetRelid(rel);			heap_close(rel);			/* this routine is actually in the planner */			children = find_all_inheritors(lconsi(myrelid, NIL), NIL);			/*			 * 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)			{				childrelid = lfirsti(child);				if (childrelid == myrelid)					continue;				rel = heap_open(childrelid);				if (!RelationIsValid(rel))				{					elog(ERROR, "PerformAddAttribute: can't find catalog entry for inheriting class with oid %u",						 childrelid);				}				PerformAddAttribute((rel->rd_rel->relname).data,									userName, false, colDef);				heap_close(rel);			}		}	}	rel = heap_openr(RelationRelationName);	reltup = SearchSysCacheTupleCopy(RELNAME,									 PointerGetDatum(relationName),									 0, 0, 0);	if (!HeapTupleIsValid(reltup))	{		heap_close(rel);		elog(ERROR, "PerformAddAttribute: relation \"%s\" not found",			 relationName);	}	/*	 * XXX is the following check sufficient?	 */	if (((Form_pg_class) GETSTRUCT(reltup))->relkind == RELKIND_INDEX)	{		elog(ERROR, "PerformAddAttribute: index relation \"%s\" not changed",			 relationName);		return;	}	minattnum = ((Form_pg_class) GETSTRUCT(reltup))->relnatts;	maxatts = minattnum + 1;	if (maxatts > MaxHeapAttributeNumber)	{		pfree(reltup);		heap_close(rel);		elog(ERROR, "PerformAddAttribute: relations limited to %d attributes",			 MaxHeapAttributeNumber);	}	attrdesc = heap_openr(AttributeRelationName);	Assert(attrdesc);	Assert(RelationGetForm(attrdesc));	/*	 * Open all (if any) pg_attribute indices	 */	hasindex = RelationGetForm(attrdesc)->relhasindex;	if (hasindex)		CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);	attributeD.attrelid = reltup->t_data->t_oid;	attributeTuple = heap_addheader(Natts_pg_attribute,									sizeof attributeD,									(char *) &attributeD);	attribute = (Form_pg_attribute) GETSTRUCT(attributeTuple);	i = 1 + minattnum;	{		HeapTuple	typeTuple;		Form_pg_type tform;		char	   *typename;		int			attnelems;		tup = SearchSysCacheTuple(ATTNAME,								  ObjectIdGetDatum(reltup->t_data->t_oid),								  PointerGetDatum(colDef->colname),								  0, 0);		if (HeapTupleIsValid(tup))		{			heap_close(attrdesc);			heap_close(rel);			elog(ERROR, "PerformAddAttribute: attribute \"%s\" already exists in class \"%s\"",				 colDef->colname, relationName);		}		/*		 * check to see if it is an array attribute.		 */		typename = colDef->typename->name;		if (colDef->typename->arrayBounds)		{			attnelems = length(colDef->typename->arrayBounds);			typename = makeArrayTypeName(colDef->typename->name);		}		else			attnelems = 0;		typeTuple = SearchSysCacheTuple(TYPNAME,										PointerGetDatum(typename),										0, 0, 0);		tform = (Form_pg_type) GETSTRUCT(typeTuple);		if (!HeapTupleIsValid(typeTuple))			elog(ERROR, "Add: type \"%s\" nonexistent", typename);		namestrcpy(&(attribute->attname), colDef->colname);		attribute->atttypid = typeTuple->t_data->t_oid;		attribute->attlen = tform->typlen;		attribute->attdisbursion = 0;		attribute->attcacheoff = -1;		attribute->atttypmod = colDef->typename->typmod;		attribute->attnum = i;		attribute->attbyval = tform->typbyval;		attribute->attnelems = attnelems;		attribute->attisset = (bool) (tform->typtype == 'c');		attribute->attalign = tform->typalign;		attribute->attnotnull = false;		attribute->atthasdef = (colDef->defval != NULL);		heap_insert(attrdesc, attributeTuple);		if (hasindex)			CatalogIndexInsert(idescs,							   Num_pg_attr_indices,							   attrdesc,							   attributeTuple);	}	if (hasindex)		CatalogCloseIndices(Num_pg_attr_indices, idescs);	heap_close(attrdesc);	((Form_pg_class) GETSTRUCT(reltup))->relnatts = maxatts;	heap_replace(rel, &reltup->t_self, reltup, NULL);	{		HeapTuple	temptup;		if ((temptup = get_temp_rel_by_name(relationName)) != NULL)			((Form_pg_class) GETSTRUCT(temptup))->relnatts = maxatts;	}	/* keep catalog indices current */	CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);	CatalogIndexInsert(ridescs, Num_pg_class_indices, rel, reltup);	CatalogCloseIndices(Num_pg_class_indices, ridescs);	pfree(reltup);	heap_close(rel);}voidLockTableCommand(LockStmt *lockstmt){	Relation	rel;	int			aclresult;	rel = heap_openr(lockstmt->relname);	if (rel == NULL)		elog(ERROR, "LOCK TABLE: relation %s can't be openned", lockstmt->relname);	if (lockstmt->mode == AccessShareLock)		aclresult = pg_aclcheck(lockstmt->relname, GetPgUserName(), ACL_RD);	else		aclresult = pg_aclcheck(lockstmt->relname, GetPgUserName(), ACL_WR);	if (aclresult != ACLCHECK_OK)		elog(ERROR, "LOCK TABLE: permission denied");	LockRelation(rel, lockstmt->mode);}

⌨️ 快捷键说明

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