/*------------------------------------------------------------------------- * * catalog.c * routines concerned with catalog naming conventions * * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $PostgreSQL: pgsql/src/backend/catalog/catalog.c,v 1.52 2004/06/18 06:13:19 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" #include "access/transam.h" #include "catalog/catalog.h" #include "catalog/catname.h" #include "catalog/pg_namespace.h" #include "catalog/pg_tablespace.h" #include "miscadmin.h" #define OIDCHARS 10 /* max chars printed by %u */ /* * relpath - construct path to a relation's file * * Result is a palloc'd string. */ char * relpath(RelFileNode rnode) { int pathlen; char *path; if (rnode.spcNode == GLOBALTABLESPACE_OID) { /* Shared system relations live in {datadir}/global */ Assert(rnode.dbNode == 0); pathlen = strlen(DataDir) + 8 + OIDCHARS + 1; path = (char *) palloc(pathlen); snprintf(path, pathlen, "%s/global/%u", DataDir, rnode.relNode); } else if (rnode.spcNode == DEFAULTTABLESPACE_OID) { /* The default tablespace is {datadir}/base */ pathlen = strlen(DataDir) + 6 + OIDCHARS + 1 + OIDCHARS + 1; path = (char *) palloc(pathlen); snprintf(path, pathlen, "%s/base/%u/%u", DataDir, rnode.dbNode, rnode.relNode); } else { /* All other tablespaces are accessed via symlinks */ pathlen = strlen(DataDir) + 16 + OIDCHARS + 1 + OIDCHARS + 1 + OIDCHARS + 1; path = (char *) palloc(pathlen); snprintf(path, pathlen, "%s/pg_tablespaces/%u/%u/%u", DataDir, rnode.spcNode, rnode.dbNode, rnode.relNode); } return path; } /* * GetDatabasePath - construct path to a database dir * * Result is a palloc'd string. * * XXX this must agree with relpath()! */ char * GetDatabasePath(Oid dbNode, Oid spcNode) { int pathlen; char *path; if (spcNode == GLOBALTABLESPACE_OID) { /* Shared system relations live in {datadir}/global */ Assert(dbNode == 0); pathlen = strlen(DataDir) + 7 + 1; path = (char *) palloc(pathlen); snprintf(path, pathlen, "%s/global", DataDir); } else if (spcNode == DEFAULTTABLESPACE_OID) { /* The default tablespace is {datadir}/base */ pathlen = strlen(DataDir) + 6 + OIDCHARS + 1; path = (char *) palloc(pathlen); snprintf(path, pathlen, "%s/base/%u", DataDir, dbNode); } else { /* All other tablespaces are accessed via symlinks */ pathlen = strlen(DataDir) + 16 + OIDCHARS + 1 + OIDCHARS + 1; path = (char *) palloc(pathlen); snprintf(path, pathlen, "%s/pg_tablespaces/%u/%u", DataDir, spcNode, dbNode); } return path; } /* * IsSystemRelation * True iff the relation is a system catalog relation. * * NB: TOAST relations are considered system relations by this test * for compatibility with the old IsSystemRelationName function. * This is appropriate in many places but not all. Where it's not, * also check IsToastRelation. * * We now just test if the relation is in the system catalog namespace; * so it's no longer necessary to forbid user relations from having * names starting with pg_. Now only schema names have the pg_ * distinction/requirement. */ bool IsSystemRelation(Relation relation) { return IsSystemNamespace(RelationGetNamespace(relation)) || IsToastNamespace(RelationGetNamespace(relation)); } /* * IsSystemClass * Like the above, but takes a Form_pg_class as argument. * Used when we do not want to open the relation and have to * search pg_class directly. */ bool IsSystemClass(Form_pg_class reltuple) { Oid relnamespace = reltuple->relnamespace; return IsSystemNamespace(relnamespace) || IsToastNamespace(relnamespace); } /* * IsToastRelation * True iff relation is a TOAST support relation (or index). */ bool IsToastRelation(Relation relation) { return IsToastNamespace(RelationGetNamespace(relation)); } /* * IsToastClass * Like the above, but takes a Form_pg_class as argument. * Used when we do not want to open the relation and have to * search pg_class directly. */ bool IsToastClass(Form_pg_class reltuple) { Oid relnamespace = reltuple->relnamespace; return IsToastNamespace(relnamespace); } /* * IsSystemNamespace * True iff namespace is pg_catalog. * * NOTE: the reason this isn't a macro is to avoid having to include * catalog/pg_namespace.h in a lot of places. */ bool IsSystemNamespace(Oid namespaceId) { return namespaceId == PG_CATALOG_NAMESPACE; } /* * IsToastNamespace * True iff namespace is pg_toast. * * NOTE: the reason this isn't a macro is to avoid having to include * catalog/pg_namespace.h in a lot of places. */ bool IsToastNamespace(Oid namespaceId) { return namespaceId == PG_TOAST_NAMESPACE; } /* * IsReservedName * True iff name starts with the pg_ prefix. * * For some classes of objects, the prefix pg_ is reserved for * system objects only. As of 7.3, this is now only true for * schema names. */ bool IsReservedName(const char *name) { /* ugly coding for speed */ return (name[0] == 'p' && name[1] == 'g' && name[2] == '_'); } /* * newoid - returns a unique identifier across all catalogs. * * Object Id allocation is now done by GetNewObjectID in * access/transam/varsup. * * This code probably needs to change to generate OIDs separately * for each table. */ Oid newoid(void) { return GetNewObjectId(); }