Header And Logo

PostgreSQL
| The world's most advanced open source database.

catalog.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * catalog.c
00004  *      routines concerned with catalog naming conventions and other
00005  *      bits of hard-wired knowledge
00006  *
00007  *
00008  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00009  * Portions Copyright (c) 1994, Regents of the University of California
00010  *
00011  *
00012  * IDENTIFICATION
00013  *    src/backend/catalog/catalog.c
00014  *
00015  *-------------------------------------------------------------------------
00016  */
00017 
00018 #include "postgres.h"
00019 
00020 #include <fcntl.h>
00021 #include <unistd.h>
00022 
00023 #include "access/genam.h"
00024 #include "access/sysattr.h"
00025 #include "access/transam.h"
00026 #include "catalog/catalog.h"
00027 #include "catalog/indexing.h"
00028 #include "catalog/namespace.h"
00029 #include "catalog/pg_auth_members.h"
00030 #include "catalog/pg_authid.h"
00031 #include "catalog/pg_database.h"
00032 #include "catalog/pg_namespace.h"
00033 #include "catalog/pg_pltemplate.h"
00034 #include "catalog/pg_db_role_setting.h"
00035 #include "catalog/pg_shdepend.h"
00036 #include "catalog/pg_shdescription.h"
00037 #include "catalog/pg_shseclabel.h"
00038 #include "catalog/pg_tablespace.h"
00039 #include "catalog/toasting.h"
00040 #include "common/relpath.h"
00041 #include "miscadmin.h"
00042 #include "storage/fd.h"
00043 #include "utils/fmgroids.h"
00044 #include "utils/rel.h"
00045 #include "utils/tqual.h"
00046 
00047 
00048 
00049 /*
00050  * forkname_to_number - look up fork number by name
00051  */
00052 ForkNumber
00053 forkname_to_number(char *forkName)
00054 {
00055     ForkNumber  forkNum;
00056 
00057     for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
00058         if (strcmp(forkNames[forkNum], forkName) == 0)
00059             return forkNum;
00060 
00061     ereport(ERROR,
00062             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00063              errmsg("invalid fork name"),
00064              errhint("Valid fork names are \"main\", \"fsm\", and \"vm\".")));
00065     return InvalidForkNumber;   /* keep compiler quiet */
00066 }
00067 
00068 /*
00069  * GetDatabasePath          - construct path to a database dir
00070  *
00071  * Result is a palloc'd string.
00072  *
00073  * XXX this must agree with relpath()!
00074  */
00075 char *
00076 GetDatabasePath(Oid dbNode, Oid spcNode)
00077 {
00078     int         pathlen;
00079     char       *path;
00080 
00081     if (spcNode == GLOBALTABLESPACE_OID)
00082     {
00083         /* Shared system relations live in {datadir}/global */
00084         Assert(dbNode == 0);
00085         pathlen = 6 + 1;
00086         path = (char *) palloc(pathlen);
00087         snprintf(path, pathlen, "global");
00088     }
00089     else if (spcNode == DEFAULTTABLESPACE_OID)
00090     {
00091         /* The default tablespace is {datadir}/base */
00092         pathlen = 5 + OIDCHARS + 1;
00093         path = (char *) palloc(pathlen);
00094         snprintf(path, pathlen, "base/%u",
00095                  dbNode);
00096     }
00097     else
00098     {
00099         /* All other tablespaces are accessed via symlinks */
00100         pathlen = 9 + 1 + OIDCHARS + 1 + strlen(TABLESPACE_VERSION_DIRECTORY) +
00101             1 + OIDCHARS + 1;
00102         path = (char *) palloc(pathlen);
00103         snprintf(path, pathlen, "pg_tblspc/%u/%s/%u",
00104                  spcNode, TABLESPACE_VERSION_DIRECTORY, dbNode);
00105     }
00106     return path;
00107 }
00108 
00109 
00110 /*
00111  * IsSystemRelation
00112  *      True iff the relation is a system catalog relation.
00113  *
00114  *      NB: TOAST relations are considered system relations by this test
00115  *      for compatibility with the old IsSystemRelationName function.
00116  *      This is appropriate in many places but not all.  Where it's not,
00117  *      also check IsToastRelation.
00118  *
00119  *      We now just test if the relation is in the system catalog namespace;
00120  *      so it's no longer necessary to forbid user relations from having
00121  *      names starting with pg_.
00122  */
00123 bool
00124 IsSystemRelation(Relation relation)
00125 {
00126     return IsSystemNamespace(RelationGetNamespace(relation)) ||
00127         IsToastNamespace(RelationGetNamespace(relation));
00128 }
00129 
00130 /*
00131  * IsSystemClass
00132  *      Like the above, but takes a Form_pg_class as argument.
00133  *      Used when we do not want to open the relation and have to
00134  *      search pg_class directly.
00135  */
00136 bool
00137 IsSystemClass(Form_pg_class reltuple)
00138 {
00139     Oid         relnamespace = reltuple->relnamespace;
00140 
00141     return IsSystemNamespace(relnamespace) ||
00142         IsToastNamespace(relnamespace);
00143 }
00144 
00145 /*
00146  * IsToastRelation
00147  *      True iff relation is a TOAST support relation (or index).
00148  */
00149 bool
00150 IsToastRelation(Relation relation)
00151 {
00152     return IsToastNamespace(RelationGetNamespace(relation));
00153 }
00154 
00155 /*
00156  * IsToastClass
00157  *      Like the above, but takes a Form_pg_class as argument.
00158  *      Used when we do not want to open the relation and have to
00159  *      search pg_class directly.
00160  */
00161 bool
00162 IsToastClass(Form_pg_class reltuple)
00163 {
00164     Oid         relnamespace = reltuple->relnamespace;
00165 
00166     return IsToastNamespace(relnamespace);
00167 }
00168 
00169 /*
00170  * IsSystemNamespace
00171  *      True iff namespace is pg_catalog.
00172  *
00173  * NOTE: the reason this isn't a macro is to avoid having to include
00174  * catalog/pg_namespace.h in a lot of places.
00175  */
00176 bool
00177 IsSystemNamespace(Oid namespaceId)
00178 {
00179     return namespaceId == PG_CATALOG_NAMESPACE;
00180 }
00181 
00182 /*
00183  * IsToastNamespace
00184  *      True iff namespace is pg_toast or my temporary-toast-table namespace.
00185  *
00186  * Note: this will return false for temporary-toast-table namespaces belonging
00187  * to other backends.  Those are treated the same as other backends' regular
00188  * temp table namespaces, and access is prevented where appropriate.
00189  */
00190 bool
00191 IsToastNamespace(Oid namespaceId)
00192 {
00193     return (namespaceId == PG_TOAST_NAMESPACE) ||
00194         isTempToastNamespace(namespaceId);
00195 }
00196 
00197 
00198 /*
00199  * IsReservedName
00200  *      True iff name starts with the pg_ prefix.
00201  *
00202  *      For some classes of objects, the prefix pg_ is reserved for
00203  *      system objects only.  As of 8.0, this is only true for
00204  *      schema and tablespace names.
00205  */
00206 bool
00207 IsReservedName(const char *name)
00208 {
00209     /* ugly coding for speed */
00210     return (name[0] == 'p' &&
00211             name[1] == 'g' &&
00212             name[2] == '_');
00213 }
00214 
00215 
00216 /*
00217  * IsSharedRelation
00218  *      Given the OID of a relation, determine whether it's supposed to be
00219  *      shared across an entire database cluster.
00220  *
00221  * Hard-wiring this list is pretty grotty, but we really need it so that
00222  * we can compute the locktag for a relation (and then lock it) without
00223  * having already read its pg_class entry.  If we try to retrieve relisshared
00224  * from pg_class with no pre-existing lock, there is a race condition against
00225  * anyone who is concurrently committing a change to the pg_class entry:
00226  * since we read system catalog entries under SnapshotNow, it's possible
00227  * that both the old and new versions of the row are invalid at the instants
00228  * we scan them.  We fix this by insisting that updaters of a pg_class
00229  * row must hold exclusive lock on the corresponding rel, and that users
00230  * of a relation must hold at least AccessShareLock on the rel *before*
00231  * trying to open its relcache entry.  But to lock a rel, you have to
00232  * know if it's shared.  Fortunately, the set of shared relations is
00233  * fairly static, so a hand-maintained list of their OIDs isn't completely
00234  * impractical.
00235  */
00236 bool
00237 IsSharedRelation(Oid relationId)
00238 {
00239     /* These are the shared catalogs (look for BKI_SHARED_RELATION) */
00240     if (relationId == AuthIdRelationId ||
00241         relationId == AuthMemRelationId ||
00242         relationId == DatabaseRelationId ||
00243         relationId == PLTemplateRelationId ||
00244         relationId == SharedDescriptionRelationId ||
00245         relationId == SharedDependRelationId ||
00246         relationId == SharedSecLabelRelationId ||
00247         relationId == TableSpaceRelationId ||
00248         relationId == DbRoleSettingRelationId)
00249         return true;
00250     /* These are their indexes (see indexing.h) */
00251     if (relationId == AuthIdRolnameIndexId ||
00252         relationId == AuthIdOidIndexId ||
00253         relationId == AuthMemRoleMemIndexId ||
00254         relationId == AuthMemMemRoleIndexId ||
00255         relationId == DatabaseNameIndexId ||
00256         relationId == DatabaseOidIndexId ||
00257         relationId == PLTemplateNameIndexId ||
00258         relationId == SharedDescriptionObjIndexId ||
00259         relationId == SharedDependDependerIndexId ||
00260         relationId == SharedDependReferenceIndexId ||
00261         relationId == SharedSecLabelObjectIndexId ||
00262         relationId == TablespaceOidIndexId ||
00263         relationId == TablespaceNameIndexId ||
00264         relationId == DbRoleSettingDatidRolidIndexId)
00265         return true;
00266     /* These are their toast tables and toast indexes (see toasting.h) */
00267     if (relationId == PgShdescriptionToastTable ||
00268         relationId == PgShdescriptionToastIndex ||
00269         relationId == PgDbRoleSettingToastTable ||
00270         relationId == PgDbRoleSettingToastIndex)
00271         return true;
00272     return false;
00273 }
00274 
00275 
00276 /*
00277  * GetNewOid
00278  *      Generate a new OID that is unique within the given relation.
00279  *
00280  * Caller must have a suitable lock on the relation.
00281  *
00282  * Uniqueness is promised only if the relation has a unique index on OID.
00283  * This is true for all system catalogs that have OIDs, but might not be
00284  * true for user tables.  Note that we are effectively assuming that the
00285  * table has a relatively small number of entries (much less than 2^32)
00286  * and there aren't very long runs of consecutive existing OIDs.  Again,
00287  * this is reasonable for system catalogs but less so for user tables.
00288  *
00289  * Since the OID is not immediately inserted into the table, there is a
00290  * race condition here; but a problem could occur only if someone else
00291  * managed to cycle through 2^32 OIDs and generate the same OID before we
00292  * finish inserting our row.  This seems unlikely to be a problem.  Note
00293  * that if we had to *commit* the row to end the race condition, the risk
00294  * would be rather higher; therefore we use SnapshotDirty in the test,
00295  * so that we will see uncommitted rows.
00296  */
00297 Oid
00298 GetNewOid(Relation relation)
00299 {
00300     Oid         oidIndex;
00301 
00302     /* If relation doesn't have OIDs at all, caller is confused */
00303     Assert(relation->rd_rel->relhasoids);
00304 
00305     /* In bootstrap mode, we don't have any indexes to use */
00306     if (IsBootstrapProcessingMode())
00307         return GetNewObjectId();
00308 
00309     /* The relcache will cache the identity of the OID index for us */
00310     oidIndex = RelationGetOidIndex(relation);
00311 
00312     /* If no OID index, just hand back the next OID counter value */
00313     if (!OidIsValid(oidIndex))
00314     {
00315         /*
00316          * System catalogs that have OIDs should *always* have a unique OID
00317          * index; we should only take this path for user tables. Give a
00318          * warning if it looks like somebody forgot an index.
00319          */
00320         if (IsSystemRelation(relation))
00321             elog(WARNING, "generating possibly-non-unique OID for \"%s\"",
00322                  RelationGetRelationName(relation));
00323 
00324         return GetNewObjectId();
00325     }
00326 
00327     /* Otherwise, use the index to find a nonconflicting OID */
00328     return GetNewOidWithIndex(relation, oidIndex, ObjectIdAttributeNumber);
00329 }
00330 
00331 /*
00332  * GetNewOidWithIndex
00333  *      Guts of GetNewOid: use the supplied index
00334  *
00335  * This is exported separately because there are cases where we want to use
00336  * an index that will not be recognized by RelationGetOidIndex: TOAST tables
00337  * have indexes that are usable, but have multiple columns and are on
00338  * ordinary columns rather than a true OID column.  This code will work
00339  * anyway, so long as the OID is the index's first column.  The caller must
00340  * pass in the actual heap attnum of the OID column, however.
00341  *
00342  * Caller must have a suitable lock on the relation.
00343  */
00344 Oid
00345 GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
00346 {
00347     Oid         newOid;
00348     SnapshotData SnapshotDirty;
00349     SysScanDesc scan;
00350     ScanKeyData key;
00351     bool        collides;
00352 
00353     InitDirtySnapshot(SnapshotDirty);
00354 
00355     /* Generate new OIDs until we find one not in the table */
00356     do
00357     {
00358         CHECK_FOR_INTERRUPTS();
00359 
00360         newOid = GetNewObjectId();
00361 
00362         ScanKeyInit(&key,
00363                     oidcolumn,
00364                     BTEqualStrategyNumber, F_OIDEQ,
00365                     ObjectIdGetDatum(newOid));
00366 
00367         /* see notes above about using SnapshotDirty */
00368         scan = systable_beginscan(relation, indexId, true,
00369                                   &SnapshotDirty, 1, &key);
00370 
00371         collides = HeapTupleIsValid(systable_getnext(scan));
00372 
00373         systable_endscan(scan);
00374     } while (collides);
00375 
00376     return newOid;
00377 }
00378 
00379 /*
00380  * GetNewRelFileNode
00381  *      Generate a new relfilenode number that is unique within the given
00382  *      tablespace.
00383  *
00384  * If the relfilenode will also be used as the relation's OID, pass the
00385  * opened pg_class catalog, and this routine will guarantee that the result
00386  * is also an unused OID within pg_class.  If the result is to be used only
00387  * as a relfilenode for an existing relation, pass NULL for pg_class.
00388  *
00389  * As with GetNewOid, there is some theoretical risk of a race condition,
00390  * but it doesn't seem worth worrying about.
00391  *
00392  * Note: we don't support using this in bootstrap mode.  All relations
00393  * created by bootstrap have preassigned OIDs, so there's no need.
00394  */
00395 Oid
00396 GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
00397 {
00398     RelFileNodeBackend rnode;
00399     char       *rpath;
00400     int         fd;
00401     bool        collides;
00402     BackendId   backend;
00403 
00404     switch (relpersistence)
00405     {
00406         case RELPERSISTENCE_TEMP:
00407             backend = MyBackendId;
00408             break;
00409         case RELPERSISTENCE_UNLOGGED:
00410         case RELPERSISTENCE_PERMANENT:
00411             backend = InvalidBackendId;
00412             break;
00413         default:
00414             elog(ERROR, "invalid relpersistence: %c", relpersistence);
00415             return InvalidOid;  /* placate compiler */
00416     }
00417 
00418     /* This logic should match RelationInitPhysicalAddr */
00419     rnode.node.spcNode = reltablespace ? reltablespace : MyDatabaseTableSpace;
00420     rnode.node.dbNode = (rnode.node.spcNode == GLOBALTABLESPACE_OID) ? InvalidOid : MyDatabaseId;
00421 
00422     /*
00423      * The relpath will vary based on the backend ID, so we must initialize
00424      * that properly here to make sure that any collisions based on filename
00425      * are properly detected.
00426      */
00427     rnode.backend = backend;
00428 
00429     do
00430     {
00431         CHECK_FOR_INTERRUPTS();
00432 
00433         /* Generate the OID */
00434         if (pg_class)
00435             rnode.node.relNode = GetNewOid(pg_class);
00436         else
00437             rnode.node.relNode = GetNewObjectId();
00438 
00439         /* Check for existing file of same name */
00440         rpath = relpath(rnode, MAIN_FORKNUM);
00441         fd = BasicOpenFile(rpath, O_RDONLY | PG_BINARY, 0);
00442 
00443         if (fd >= 0)
00444         {
00445             /* definite collision */
00446             close(fd);
00447             collides = true;
00448         }
00449         else
00450         {
00451             /*
00452              * Here we have a little bit of a dilemma: if errno is something
00453              * other than ENOENT, should we declare a collision and loop? In
00454              * particular one might think this advisable for, say, EPERM.
00455              * However there really shouldn't be any unreadable files in a
00456              * tablespace directory, and if the EPERM is actually complaining
00457              * that we can't read the directory itself, we'd be in an infinite
00458              * loop.  In practice it seems best to go ahead regardless of the
00459              * errno.  If there is a colliding file we will get an smgr
00460              * failure when we attempt to create the new relation file.
00461              */
00462             collides = false;
00463         }
00464 
00465         pfree(rpath);
00466     } while (collides);
00467 
00468     return rnode.node.relNode;
00469 }