1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* catalog.c
|
1997-09-07 07:04:48 +02:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2000-10-22 07:14:01 +02:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.36 2000/10/22 05:14:01 momjian Exp $
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
1997-01-10 21:19:49 +01:00
|
|
|
|
1999-07-16 01:04:24 +02:00
|
|
|
#include "postgres.h"
|
1996-11-04 00:27:08 +01:00
|
|
|
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "access/transam.h"
|
|
|
|
#include "catalog/catalog.h"
|
1999-07-16 05:14:30 +02:00
|
|
|
#include "catalog/catname.h"
|
1999-07-16 01:04:24 +02:00
|
|
|
#include "catalog/pg_type.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "miscadmin.h"
|
|
|
|
#include "utils/syscache.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2000-10-16 16:52:28 +02:00
|
|
|
#ifdef OLD_FILE_NAMING
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
2000-04-09 06:43:20 +02:00
|
|
|
* 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.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1998-02-26 05:46:47 +01:00
|
|
|
char *
|
2000-01-16 21:05:00 +01:00
|
|
|
relpath(const char *relname)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1999-05-25 18:15:34 +02:00
|
|
|
char *path;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
if (IsSharedSystemRelationName(relname))
|
|
|
|
{
|
2000-07-03 22:48:46 +02:00
|
|
|
/* Shared system relations live in {datadir}/global */
|
|
|
|
size_t bufsize = strlen(DataDir) + 8 + sizeof(NameData) + 1;
|
2000-04-09 06:43:20 +02:00
|
|
|
|
1998-12-14 06:19:16 +01:00
|
|
|
path = (char *) palloc(bufsize);
|
2000-07-03 22:48:46 +02:00
|
|
|
snprintf(path, bufsize, "%s/global/%s", DataDir, relname);
|
1998-09-01 05:29:17 +02:00
|
|
|
return path;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
2000-04-12 19:17:23 +02:00
|
|
|
|
2000-04-09 06:43:20 +02:00
|
|
|
/*
|
|
|
|
* If it is in the current database, assume it is in current working
|
|
|
|
* directory. NB: this does not work during bootstrap!
|
|
|
|
*/
|
2000-01-22 15:20:56 +01:00
|
|
|
return pstrdup(relname);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2000-04-09 06:43:20 +02:00
|
|
|
/*
|
|
|
|
* relpath_blind - construct path to a relation's file
|
|
|
|
*
|
|
|
|
* Construct the path using only the info available to smgrblindwrt,
|
2000-04-12 19:17:23 +02:00
|
|
|
* namely the names and OIDs of the database and relation. (Shared system
|
2000-04-09 06:43:20 +02:00
|
|
|
* 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)
|
|
|
|
{
|
2000-07-03 22:48:46 +02:00
|
|
|
/* Shared system relations live in {datadir}/global */
|
|
|
|
path = (char *) palloc(strlen(DataDir) + 8 + sizeof(NameData) + 1);
|
|
|
|
sprintf(path, "%s/global/%s", DataDir, relname);
|
2000-04-09 06:43:20 +02:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2000-10-16 16:52:28 +02:00
|
|
|
#else /* ! OLD_FILE_NAMING */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* relpath - construct path to a relation's file
|
|
|
|
*
|
|
|
|
* Result is a palloc'd string.
|
|
|
|
*/
|
|
|
|
|
|
|
|
char *
|
|
|
|
relpath(RelFileNode rnode)
|
|
|
|
{
|
|
|
|
char *path;
|
|
|
|
|
|
|
|
if (rnode.tblNode == (Oid) 0) /* "global tablespace" */
|
|
|
|
{
|
|
|
|
/* Shared system relations live in {datadir}/global */
|
|
|
|
path = (char *) palloc(strlen(DataDir) + 8 + sizeof(NameData) + 1);
|
|
|
|
sprintf(path, "%s%cglobal%c%u", DataDir, SEP_CHAR, SEP_CHAR, rnode.relNode);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
path = (char *) palloc(strlen(DataDir) + 6 + 2 * sizeof(NameData) + 3);
|
|
|
|
sprintf(path, "%s%cbase%c%u%c%u", DataDir, SEP_CHAR, SEP_CHAR,
|
|
|
|
rnode.tblNode, SEP_CHAR, rnode.relNode);
|
|
|
|
}
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* GetDatabasePath - construct path to a database dir
|
|
|
|
*
|
|
|
|
* Result is a palloc'd string.
|
|
|
|
*/
|
|
|
|
|
|
|
|
char *
|
|
|
|
GetDatabasePath(Oid tblNode)
|
|
|
|
{
|
|
|
|
char *path;
|
|
|
|
|
|
|
|
if (tblNode == (Oid) 0) /* "global tablespace" */
|
|
|
|
{
|
|
|
|
/* Shared system relations live in {datadir}/global */
|
|
|
|
path = (char *) palloc(strlen(DataDir) + 8);
|
|
|
|
sprintf(path, "%s%cglobal", DataDir, SEP_CHAR);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
path = (char *) palloc(strlen(DataDir) + 6 + sizeof(NameData) + 1);
|
|
|
|
sprintf(path, "%s%cbase%c%u", DataDir, SEP_CHAR, SEP_CHAR, tblNode);
|
|
|
|
}
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* OLD_FILE_NAMING */
|
2000-04-09 06:43:20 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
1999-05-25 18:15:34 +02:00
|
|
|
* IsSystemRelationName
|
1997-09-07 07:04:48 +02:00
|
|
|
* True iff name is the name of a system catalog relation.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* 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.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* XXX this is way bogus. -- pma
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
bool
|
2000-01-16 21:05:00 +01:00
|
|
|
IsSystemRelationName(const char *relname)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-10-22 07:14:01 +02:00
|
|
|
if (relname[0] && relname[1] && relname[2])
|
1997-09-07 07:04:48 +02:00
|
|
|
return (relname[0] == 'p' &&
|
|
|
|
relname[1] == 'g' &&
|
|
|
|
relname[2] == '_');
|
|
|
|
else
|
|
|
|
return FALSE;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1999-05-25 18:15:34 +02:00
|
|
|
* IsSharedSystemRelationName
|
1997-09-07 07:04:48 +02:00
|
|
|
* True iff name is the name of a shared system catalog relation.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
bool
|
2000-01-16 21:05:00 +01:00
|
|
|
IsSharedSystemRelationName(const char *relname)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
int i;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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++;
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* newoid - returns a unique identifier across all catalogs.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Object Id allocation is now done by GetNewObjectID in
|
|
|
|
* access/transam/varsup.c. oids are now allocated correctly.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* old comments:
|
1997-09-07 07:04:48 +02:00
|
|
|
* This needs to change soon, it fails if there are too many more
|
|
|
|
* than one call per second when postgres restarts after it dies.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* 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.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
Oid
|
|
|
|
newoid()
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
Oid lastoid;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
GetNewObjectId(&lastoid);
|
|
|
|
if (!OidIsValid(lastoid))
|
1998-01-06 20:42:33 +01:00
|
|
|
elog(ERROR, "newoid: GetNewObjectId returns invalid oid");
|
1997-09-07 07:04:48 +02:00
|
|
|
return lastoid;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* fillatt - fills the ATTRIBUTE relation fields from the TYP
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* 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.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* In the future, attnum may not be set?!? or may be passed as an arg?!?
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Current implementation is very inefficient--should cashe the
|
|
|
|
* information if this is at all possible.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Check to see if this is really needed, and especially in the case
|
|
|
|
* of index tuples.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
fillatt(TupleDesc tupleDesc)
|
|
|
|
{
|
1998-09-01 05:29:17 +02:00
|
|
|
Form_pg_attribute *attributeP;
|
|
|
|
Form_pg_type typp;
|
1997-09-08 04:41:22 +02:00
|
|
|
HeapTuple tuple;
|
|
|
|
int i;
|
|
|
|
int natts = tupleDesc->natts;
|
1998-09-01 05:29:17 +02:00
|
|
|
Form_pg_attribute *att = tupleDesc->attrs;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
if (natts < 0 || natts > MaxHeapAttributeNumber)
|
1998-01-06 20:42:33 +01:00
|
|
|
elog(ERROR, "fillatt: %d attributes is too large", natts);
|
1997-09-07 07:04:48 +02:00
|
|
|
if (natts == 0)
|
|
|
|
{
|
|
|
|
elog(DEBUG, "fillatt: called with natts == 0");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
attributeP = &att[0];
|
|
|
|
|
|
|
|
for (i = 0; i < natts;)
|
|
|
|
{
|
1999-11-22 18:56:41 +01:00
|
|
|
tuple = SearchSysCacheTuple(TYPEOID,
|
1998-09-01 06:40:42 +02:00
|
|
|
ObjectIdGetDatum((*attributeP)->atttypid),
|
1997-09-07 07:04:48 +02:00
|
|
|
0, 0, 0);
|
|
|
|
if (!HeapTupleIsValid(tuple))
|
|
|
|
{
|
2000-01-15 03:59:43 +01:00
|
|
|
elog(ERROR, "fillatt: unknown atttypid %d",
|
1997-09-07 07:04:48 +02:00
|
|
|
(*attributeP)->atttypid);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1997-09-08 23:56:23 +02:00
|
|
|
(*attributeP)->attnum = (int16) ++i;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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...
|
|
|
|
*/
|
1998-01-17 00:21:07 +01:00
|
|
|
if (!(*attributeP)->attisset)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
1998-09-01 06:40:42 +02:00
|
|
|
typp = (Form_pg_type) GETSTRUCT(tuple); /* XXX */
|
1997-09-07 07:04:48 +02:00
|
|
|
(*attributeP)->attlen = typp->typlen;
|
|
|
|
(*attributeP)->attbyval = typp->typbyval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
attributeP += 1;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
}
|