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

📄 pg_type.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
字号:
/*------------------------------------------------------------------------- * * pg_type.c *	  routines to support manipulation of the pg_type relation * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.37.2.1 1999/08/02 05:56:55 scrappy Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/heapam.h"#include "catalog/catname.h"#include "catalog/indexing.h"#include "catalog/pg_type.h"#include "miscadmin.h"#include "parser/parse_func.h"#include "utils/builtins.h"#include "utils/syscache.h"static Oid TypeShellMakeWithOpenRelation(Relation pg_type_desc,							  char *typeName);/* ---------------------------------------------------------------- *		TypeGetWithOpenRelation * *		preforms a scan on pg_type for a type tuple with the *		given type name. * ---------------------------------------------------------------- *		pg_type_desc			 -- reldesc for pg_type *		typeName				 -- name of type to be fetched *		defined					 -- has the type been defined? */static OidTypeGetWithOpenRelation(Relation pg_type_desc,						char *typeName,						bool *defined){	HeapScanDesc scan;	HeapTuple	tup;	Oid			typoid;	static ScanKeyData typeKey[1] = {		{0, Anum_pg_type_typname, F_NAMEEQ}	};	/* ----------------	 *	initialize the scan key and begin a scan of pg_type	 * ----------------	 */	fmgr_info(F_NAMEEQ, &typeKey[0].sk_func);	typeKey[0].sk_nargs = typeKey[0].sk_func.fn_nargs;	typeKey[0].sk_argument = PointerGetDatum(typeName);	scan = heap_beginscan(pg_type_desc,						  0,						  SnapshotSelf, /* cache? */						  1,						  typeKey);	/* ----------------	 *	get the type tuple, if it exists.	 * ----------------	 */	tup = heap_getnext(scan, 0);	/* ----------------	 *	if no type tuple exists for the given type name, then	 *	end the scan and return appropriate information.	 * ----------------	 */	if (!HeapTupleIsValid(tup))	{		heap_endscan(scan);		*defined = false;		return InvalidOid;	}	/* ----------------	 *	here, the type tuple does exist so we pull information from	 *	the typisdefined field of the tuple and return the tuple's	 *	oid, which is the oid of the type.	 * ----------------	 */	*defined = (bool) ((Form_pg_type) GETSTRUCT(tup))->typisdefined;	typoid = tup->t_data->t_oid;	heap_endscan(scan);	return typoid;}/* ---------------------------------------------------------------- *		TypeGet * *		Finds the ObjectId of a type, even if uncommitted; "defined" *		is only set if the type has actually been defined, i.e., if *		the type tuple is not a shell. * *		Note: the meat of this function is now in the function *			  TypeGetWithOpenRelation().  -cim 6/15/90 * *		Also called from util/remove.c * ---------------------------------------------------------------- */OidTypeGet(char *typeName,			/* name of type to be fetched */		bool *defined)			/* has the type been defined? */{	Relation	pg_type_desc;	Oid			typeoid;	/* ----------------	 *	open the pg_type relation	 * ----------------	 */	pg_type_desc = heap_openr(TypeRelationName);	/* ----------------	 *	scan the type relation for the information we want	 * ----------------	 */	typeoid = TypeGetWithOpenRelation(pg_type_desc,									  typeName,									  defined);	/* ----------------	 *	close the type relation and return the type oid.	 * ----------------	 */	heap_close(pg_type_desc);	return typeoid;}/* ---------------------------------------------------------------- *		TypeShellMakeWithOpenRelation * * ---------------------------------------------------------------- */static OidTypeShellMakeWithOpenRelation(Relation pg_type_desc, char *typeName){	int			i;	HeapTuple	tup;	Datum		values[Natts_pg_type];	char		nulls[Natts_pg_type];	Oid			typoid;	NameData	name;	TupleDesc	tupDesc;	/* ----------------	 *	initialize our *nulls and *values arrays	 * ----------------	 */	for (i = 0; i < Natts_pg_type; ++i)	{		nulls[i] = ' ';		values[i] = (Datum) NULL;		/* redundant, but safe */	}	/* ----------------	 *	initialize *values with the type name and	 * ----------------	 */	i = 0;	namestrcpy(&name, typeName);	values[i++] = NameGetDatum(&name);	/* 1 */	values[i++] = (Datum) InvalidOid;	/* 2 */	values[i++] = (Datum) (int16) 0;	/* 3 */	values[i++] = (Datum) (int16) 0;	/* 4 */	values[i++] = (Datum) (bool) 0;		/* 5 */	values[i++] = (Datum) (bool) 0;		/* 6 */	values[i++] = (Datum) (bool) 0;		/* 7 */	values[i++] = (Datum) (bool) 0;		/* 8 */	values[i++] = (Datum) InvalidOid;	/* 9 */	values[i++] = (Datum) InvalidOid;	/* 10 */	values[i++] = (Datum) InvalidOid;	/* 11 */	values[i++] = (Datum) InvalidOid;	/* 12 */	values[i++] = (Datum) InvalidOid;	/* 13 */	values[i++] = (Datum) InvalidOid;	/* 14 */	values[i++] = (Datum) 'i';	/* 15 */	/*	 * ... and fill typdefault with a bogus value	 */	values[i++] = (Datum) fmgr(F_TEXTIN, typeName);		/* 15 */	/* ----------------	 *	create a new type tuple with FormHeapTuple	 * ----------------	 */	tupDesc = pg_type_desc->rd_att;	tup = heap_formtuple(tupDesc, values, nulls);	/* ----------------	 *	insert the tuple in the relation and get the tuple's oid.	 * ----------------	 */	heap_insert(pg_type_desc, tup);	typoid = tup->t_data->t_oid;	if (RelationGetForm(pg_type_desc)->relhasindex)	{		Relation	idescs[Num_pg_type_indices];		CatalogOpenIndices(Num_pg_type_indices, Name_pg_type_indices, idescs);		CatalogIndexInsert(idescs, Num_pg_type_indices, pg_type_desc, tup);		CatalogCloseIndices(Num_pg_type_indices, idescs);	}	/* ----------------	 *	free the tuple and return the type-oid	 * ----------------	 */	pfree(tup);	return typoid;}/* ---------------------------------------------------------------- *		TypeShellMake * *		This procedure inserts a "shell" tuple into the type *		relation.  The type tuple inserted has invalid values *		and in particular, the "typisdefined" field is false. * *		This is used so that a tuple exists in the catalogs. *		The invalid fields should be fixed up sometime after *		this routine is called, and then the "typeisdefined" *		field is set to true. -cim 6/15/90 * ---------------------------------------------------------------- */OidTypeShellMake(char *typeName){	Relation	pg_type_desc;	Oid			typoid;	Assert(PointerIsValid(typeName));	/* ----------------	 *	open pg_type	 * ----------------	 */	pg_type_desc = heap_openr(TypeRelationName);	/* ----------------	 *	insert the shell tuple	 * ----------------	 */	typoid = TypeShellMakeWithOpenRelation(pg_type_desc, typeName);	/* ----------------	 *	close pg_type and return the tuple's oid.	 * ----------------	 */	heap_close(pg_type_desc);	return typoid;}/* ---------------------------------------------------------------- *		TypeCreate * *		This does all the necessary work needed to define a new type. * ---------------------------------------------------------------- */OidTypeCreate(char *typeName,		   Oid relationOid,		/* only for 'c'atalog typeTypes */		   int16 internalSize,		   int16 externalSize,		   char typeType,		   char typDelim,		   char *inputProcedure,		   char *outputProcedure,		   char *receiveProcedure,		   char *sendProcedure,		   char *elementTypeName,		   char *defaultTypeValue,		/* internal rep */		   bool passedByValue,		   char alignment){	int			i,				j;	Relation	pg_type_desc;	HeapScanDesc pg_type_scan;	Oid			typeObjectId;	Oid			elementObjectId = InvalidOid;	HeapTuple	tup;	char		nulls[Natts_pg_type];	char		replaces[Natts_pg_type];	Datum		values[Natts_pg_type];	char	   *procname;	char	   *procs[4];	bool		defined;	NameData	name;	TupleDesc	tupDesc;	Oid			argList[8];	static ScanKeyData typeKey[1] = {		{0, Anum_pg_type_typname, F_NAMEEQ}	};	fmgr_info(F_NAMEEQ, &typeKey[0].sk_func);	typeKey[0].sk_nargs = typeKey[0].sk_func.fn_nargs;	/* ----------------	 *	check that the type is not already defined.	 * ----------------	 */	typeObjectId = TypeGet(typeName, &defined);	if (OidIsValid(typeObjectId) && defined)		elog(ERROR, "TypeCreate: type %s already defined", typeName);	/* ----------------	 *	if this type has an associated elementType, then we check that	 *	it is defined.	 * ----------------	 */	if (elementTypeName)	{		elementObjectId = TypeGet(elementTypeName, &defined);		if (!defined)			elog(ERROR, "TypeCreate: type %s is not defined", elementTypeName);	}	/* ----------------	 *	XXX comment me	 * ----------------	 */	if (externalSize == 0)		externalSize = -1;		/* variable length */	/* ----------------	 *	initialize arrays needed by FormHeapTuple	 * ----------------	 */	for (i = 0; i < Natts_pg_type; ++i)	{		nulls[i] = ' ';		replaces[i] = 'r';		values[i] = (Datum) NULL;		/* redundant, but nice */	}	/*	 * XXX	 *	 * Do this so that user-defined types have size -1 instead of zero if	 * they are variable-length - this is so that everything else in the	 * backend works.	 */	if (internalSize == 0)		internalSize = -1;	/* ----------------	 *	initialize the *values information	 * ----------------	 */	i = 0;	namestrcpy(&name, typeName);	values[i++] = NameGetDatum(&name);	/* 1 */	values[i++] = (Datum) GetUserId();	/* 2 */	values[i++] = (Datum) internalSize; /* 3 */	values[i++] = (Datum) externalSize; /* 4 */	values[i++] = (Datum) passedByValue;		/* 5 */	values[i++] = (Datum) typeType;		/* 6 */	values[i++] = (Datum) (bool) 1;		/* 7 */	values[i++] = (Datum) typDelim;		/* 8 */	values[i++] = (Datum) (typeType == 'c' ? relationOid : InvalidOid); /* 9 */	values[i++] = (Datum) elementObjectId;		/* 10 */	procs[0] = inputProcedure;	procs[1] = outputProcedure;	procs[2] = (receiveProcedure) ? receiveProcedure : inputProcedure;	procs[3] = (sendProcedure) ? sendProcedure : outputProcedure;	for (j = 0; j < 4; ++j)	{		procname = procs[j];		/*		 * First look for a 1-argument func with all argtypes 0. This is		 * valid for all four kinds of procedure.		 */		MemSet(argList, 0, 8 * sizeof(Oid));		tup = SearchSysCacheTuple(PRONAME,								  PointerGetDatum(procname),								  Int32GetDatum(1),								  PointerGetDatum(argList),								  0);		if (!HeapTupleIsValid(tup))		{			/*			 * For array types, the input procedures may take 3 args (data			 * value, element OID, atttypmod); the pg_proc argtype			 * signature is 0,0,INT4OID.  The output procedures may take 2			 * args (data value, element OID).			 */			if (OidIsValid(elementObjectId))			{				int			nargs;				if (j % 2)				{					/* output proc */					nargs = 2;				}				else				{					/* input proc */					nargs = 3;					argList[2] = INT4OID;				}				tup = SearchSysCacheTuple(PRONAME,										  PointerGetDatum(procname),										  Int32GetDatum(nargs),										  PointerGetDatum(argList),										  0);			}			if (!HeapTupleIsValid(tup))				func_error("TypeCreate", procname, 1, argList, NULL);		}		values[i++] = (Datum) tup->t_data->t_oid;		/* 11 - 14 */	}	/* ----------------	 * set default alignment	 * ----------------	 */	values[i++] = (Datum) alignment;	/* 15 */	/* ----------------	 *	initialize the default value for this type.	 * ----------------	 */	values[i] = (Datum) fmgr(F_TEXTIN,	/* 16 */							 PointerIsValid(defaultTypeValue)							 ? defaultTypeValue : "-"); /* XXX default														 * typdefault */	/* ----------------	 *	open pg_type and begin a scan for the type name.	 * ----------------	 */	pg_type_desc = heap_openr(TypeRelationName);	/* -----------------	 * Set a write lock initially so as not upgrade a read to a write	 * when the heap_insert() or heap_replace() is called.	 * -----------------	 */	LockRelation(pg_type_desc, AccessExclusiveLock);	typeKey[0].sk_argument = PointerGetDatum(typeName);	pg_type_scan = heap_beginscan(pg_type_desc,								  0,								  SnapshotSelf, /* cache? */								  1,								  typeKey);	/* ----------------	 *	define the type either by adding a tuple to the type	 *	relation, or by updating the fields of the "shell" tuple	 *	already there.	 * ----------------	 */	tup = heap_getnext(pg_type_scan, 0);	if (HeapTupleIsValid(tup))	{		tup = heap_modifytuple(tup,							   pg_type_desc,							   values,							   nulls,							   replaces);		setheapoverride(true);		heap_replace(pg_type_desc, &tup->t_self, tup, NULL);		setheapoverride(false);		typeObjectId = tup->t_data->t_oid;	}	else	{		tupDesc = pg_type_desc->rd_att;		tup = heap_formtuple(tupDesc,							 values,							 nulls);		heap_insert(pg_type_desc, tup);		typeObjectId = tup->t_data->t_oid;	}	/* ----------------	 *	finish up	 * ----------------	 */	heap_endscan(pg_type_scan);	if (RelationGetForm(pg_type_desc)->relhasindex)	{		Relation	idescs[Num_pg_type_indices];		CatalogOpenIndices(Num_pg_type_indices, Name_pg_type_indices, idescs);		CatalogIndexInsert(idescs, Num_pg_type_indices, pg_type_desc, tup);		CatalogCloseIndices(Num_pg_type_indices, idescs);	}	UnlockRelation(pg_type_desc, AccessExclusiveLock);	heap_close(pg_type_desc);	return typeObjectId;}/* ---------------------------------------------------------------- *		TypeRename * *		This renames a type * ---------------------------------------------------------------- */voidTypeRename(char *oldTypeName, char *newTypeName){	Relation	pg_type_desc;	Relation	idescs[Num_pg_type_indices];	HeapTuple	oldtup,				newtup;	pg_type_desc = heap_openr(TypeRelationName);	oldtup = SearchSysCacheTupleCopy(TYPNAME,									 PointerGetDatum(oldTypeName),									 0, 0, 0);	if (!HeapTupleIsValid(oldtup))	{		heap_close(pg_type_desc);		elog(ERROR, "TypeRename: type %s not defined", oldTypeName);	}	newtup = SearchSysCacheTuple(TYPNAME,								 PointerGetDatum(newTypeName),								 0, 0, 0);	if (HeapTupleIsValid(newtup))	{		pfree(oldtup);		heap_close(pg_type_desc);		elog(ERROR, "TypeRename: type %s already defined", newTypeName);	}	namestrcpy(&(((Form_pg_type) GETSTRUCT(oldtup))->typname), newTypeName);	setheapoverride(true);	heap_replace(pg_type_desc, &oldtup->t_self, oldtup, NULL);	setheapoverride(false);	/* update the system catalog indices */	CatalogOpenIndices(Num_pg_type_indices, Name_pg_type_indices, idescs);	CatalogIndexInsert(idescs, Num_pg_type_indices, pg_type_desc, oldtup);	CatalogCloseIndices(Num_pg_type_indices, idescs);	pfree(oldtup);	heap_close(pg_type_desc);}/* * makeArrayTypeName(typeName); *	  - given a base type name, make an array of type name out of it * * the CALLER is responsible for pfreeing the */char *makeArrayTypeName(char *typeName){	char	   *arr;	if (!typeName)		return NULL;	arr = palloc(strlen(typeName) + 2);	arr[0] = '_';	strcpy(arr + 1, typeName);	return arr;}

⌨️ 快捷键说明

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