catalog.c 6.1 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * catalog.c
4
 *
5
 *
B
Add:  
Bruce Momjian 已提交
6 7
 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
 * Portions Copyright (c) 1994, Regents of the University of California
8 9 10
 *
 *
 * IDENTIFICATION
11
 *	  $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.33 2000/07/03 20:48:28 petere Exp $
12 13 14
 *
 *-------------------------------------------------------------------------
 */
15

16
#include "postgres.h"
17

B
Bruce Momjian 已提交
18 19
#include "access/transam.h"
#include "catalog/catalog.h"
B
Bruce Momjian 已提交
20
#include "catalog/catname.h"
21
#include "catalog/pg_type.h"
B
Bruce Momjian 已提交
22 23
#include "miscadmin.h"
#include "utils/syscache.h"
24 25

/*
26 27 28 29 30 31
 * relpath				- construct path to a relation's file
 *
 * Note that this only works with relations that are visible to the current
 * backend, ie, either in the current database or shared system relations.
 *
 * Result is a palloc'd string.
32
 */
33
char *
34
relpath(const char *relname)
35
{
B
Bruce Momjian 已提交
36
	char	   *path;
37 38 39

	if (IsSharedSystemRelationName(relname))
	{
40 41
		/* Shared system relations live in {datadir}/global */
		size_t		bufsize = strlen(DataDir) + 8 + sizeof(NameData) + 1;
42

M
 
Marc G. Fournier 已提交
43
		path = (char *) palloc(bufsize);
44
		snprintf(path, bufsize, "%s/global/%s", DataDir, relname);
45
		return path;
46
	}
47

48 49 50 51
	/*
	 * If it is in the current database, assume it is in current working
	 * directory.  NB: this does not work during bootstrap!
	 */
52
	return pstrdup(relname);
53 54
}

55 56 57 58
/*
 * relpath_blind			- construct path to a relation's file
 *
 * Construct the path using only the info available to smgrblindwrt,
59
 * namely the names and OIDs of the database and relation.	(Shared system
60 61 62 63 64 65 66 67 68 69 70 71 72 73
 * relations are identified with dbid = 0.)  Note that we may have to
 * access a relation belonging to a different database!
 *
 * Result is a palloc'd string.
 */

char *
relpath_blind(const char *dbname, const char *relname,
			  Oid dbid, Oid relid)
{
	char	   *path;

	if (dbid == (Oid) 0)
	{
74 75 76
		/* Shared system relations live in {datadir}/global */
		path = (char *) palloc(strlen(DataDir) + 8 + sizeof(NameData) + 1);
		sprintf(path, "%s/global/%s", DataDir, relname);
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
	}
	else if (dbid == MyDatabaseId)
	{
		/* XXX why is this inconsistent with relpath() ? */
		path = (char *) palloc(strlen(DatabasePath) + sizeof(NameData) + 2);
		sprintf(path, "%s%c%s", DatabasePath, SEP_CHAR, relname);
	}
	else
	{
		/* this is work around only !!! */
		char		dbpathtmp[MAXPGPATH];
		Oid			id;
		char	   *dbpath;

		GetRawDatabaseInfo(dbname, &id, dbpathtmp);

		if (id != dbid)
			elog(FATAL, "relpath_blind: oid of db %s is not %u",
				 dbname, dbid);
		dbpath = ExpandDatabasePath(dbpathtmp);
		if (dbpath == NULL)
			elog(FATAL, "relpath_blind: can't expand path for db %s",
				 dbname);
		path = (char *) palloc(strlen(dbpath) + sizeof(NameData) + 2);
		sprintf(path, "%s%c%s", dbpath, SEP_CHAR, relname);
		pfree(dbpath);
	}
	return path;
}


108
/*
B
Bruce Momjian 已提交
109
 * IsSystemRelationName
110
 *		True iff name is the name of a system catalog relation.
111
 *
112 113 114
 *		We now make a new requirement where system catalog relns must begin
 *		with pg_ while user relns are forbidden to do so.  Make the test
 *		trivial and instantaneous.
115
 *
116
 *		XXX this is way bogus. -- pma
117 118
 */
bool
119
IsSystemRelationName(const char *relname)
120
{
121 122 123 124 125 126
	if (relname[0] && relname[1] && relname[2])
		return (relname[0] == 'p' &&
				relname[1] == 'g' &&
				relname[2] == '_');
	else
		return FALSE;
127 128 129
}

/*
B
Bruce Momjian 已提交
130
 * IsSharedSystemRelationName
131
 *		True iff name is the name of a shared system catalog relation.
132 133
 */
bool
134
IsSharedSystemRelationName(const char *relname)
135
{
136
	int			i;
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151

	/*
	 * Quick out: if it's not a system relation, it can't be a shared
	 * system relation.
	 */
	if (!IsSystemRelationName(relname))
		return FALSE;

	i = 0;
	while (SharedSystemRelationNames[i] != NULL)
	{
		if (strcmp(SharedSystemRelationNames[i], relname) == 0)
			return TRUE;
		i++;
	}
152 153 154 155
	return FALSE;
}

/*
156
 *		newoid			- returns a unique identifier across all catalogs.
157
 *
158 159
 *		Object Id allocation is now done by GetNewObjectID in
 *		access/transam/varsup.c.  oids are now allocated correctly.
160 161
 *
 * old comments:
162 163
 *		This needs to change soon, it fails if there are too many more
 *		than one call per second when postgres restarts after it dies.
164
 *
165 166 167 168
 *		The distribution of OID's should be done by the POSTMASTER.
 *		Also there needs to be a facility to preallocate OID's.  Ie.,
 *		for a block of OID's to be declared as invalid ones to allow
 *		user programs to use them for temporary object identifiers.
169
 */
170 171
Oid
newoid()
172
{
173
	Oid			lastoid;
174 175 176

	GetNewObjectId(&lastoid);
	if (!OidIsValid(lastoid))
B
Bruce Momjian 已提交
177
		elog(ERROR, "newoid: GetNewObjectId returns invalid oid");
178
	return lastoid;
179 180 181
}

/*
182
 *		fillatt			- fills the ATTRIBUTE relation fields from the TYP
183
 *
184 185 186
 *		Expects that the atttypid domain is set for each att[].
 *		Returns with the attnum, and attlen domains set.
 *		attnum, attproc, atttyparg, ... should be set by the user.
187
 *
188
 *		In the future, attnum may not be set?!? or may be passed as an arg?!?
189
 *
190 191
 *		Current implementation is very inefficient--should cashe the
 *		information if this is at all possible.
192
 *
193 194
 *		Check to see if this is really needed, and especially in the case
 *		of index tuples.
195 196 197 198
 */
void
fillatt(TupleDesc tupleDesc)
{
199 200
	Form_pg_attribute *attributeP;
	Form_pg_type typp;
201 202 203
	HeapTuple	tuple;
	int			i;
	int			natts = tupleDesc->natts;
204
	Form_pg_attribute *att = tupleDesc->attrs;
205 206

	if (natts < 0 || natts > MaxHeapAttributeNumber)
B
Bruce Momjian 已提交
207
		elog(ERROR, "fillatt: %d attributes is too large", natts);
208 209 210 211 212 213 214 215 216 217
	if (natts == 0)
	{
		elog(DEBUG, "fillatt: called with natts == 0");
		return;
	}

	attributeP = &att[0];

	for (i = 0; i < natts;)
	{
218
		tuple = SearchSysCacheTuple(TYPEOID,
219
							   ObjectIdGetDatum((*attributeP)->atttypid),
220 221 222
									0, 0, 0);
		if (!HeapTupleIsValid(tuple))
		{
223
			elog(ERROR, "fillatt: unknown atttypid %d",
224 225 226 227
				 (*attributeP)->atttypid);
		}
		else
		{
228
			(*attributeP)->attnum = (int16) ++i;
229 230 231 232 233 234 235

			/*
			 * Check if the attr is a set before messing with the length
			 * and byval, since those were already set in
			 * TupleDescInitEntry.	In fact, this seems redundant here,
			 * but who knows what I'll break if I take it out...
			 */
236
			if (!(*attributeP)->attisset)
237
			{
238
				typp = (Form_pg_type) GETSTRUCT(tuple); /* XXX */
239 240 241 242 243
				(*attributeP)->attlen = typp->typlen;
				(*attributeP)->attbyval = typp->typbyval;
			}
		}
		attributeP += 1;
244 245
	}
}