LCOV - code coverage report
Current view: top level - src/backend/catalog - catalog.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 103 107 96.3 %
Date: 2017-09-29 13:40:31 Functions: 13 13 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * catalog.c
       4             :  *      routines concerned with catalog naming conventions and other
       5             :  *      bits of hard-wired knowledge
       6             :  *
       7             :  *
       8             :  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
       9             :  * Portions Copyright (c) 1994, Regents of the University of California
      10             :  *
      11             :  *
      12             :  * IDENTIFICATION
      13             :  *    src/backend/catalog/catalog.c
      14             :  *
      15             :  *-------------------------------------------------------------------------
      16             :  */
      17             : 
      18             : #include "postgres.h"
      19             : 
      20             : #include <fcntl.h>
      21             : #include <unistd.h>
      22             : 
      23             : #include "access/genam.h"
      24             : #include "access/sysattr.h"
      25             : #include "access/transam.h"
      26             : #include "catalog/catalog.h"
      27             : #include "catalog/indexing.h"
      28             : #include "catalog/namespace.h"
      29             : #include "catalog/pg_auth_members.h"
      30             : #include "catalog/pg_authid.h"
      31             : #include "catalog/pg_database.h"
      32             : #include "catalog/pg_namespace.h"
      33             : #include "catalog/pg_pltemplate.h"
      34             : #include "catalog/pg_db_role_setting.h"
      35             : #include "catalog/pg_replication_origin.h"
      36             : #include "catalog/pg_shdepend.h"
      37             : #include "catalog/pg_shdescription.h"
      38             : #include "catalog/pg_shseclabel.h"
      39             : #include "catalog/pg_subscription.h"
      40             : #include "catalog/pg_tablespace.h"
      41             : #include "catalog/pg_type.h"
      42             : #include "catalog/toasting.h"
      43             : #include "miscadmin.h"
      44             : #include "storage/fd.h"
      45             : #include "utils/fmgroids.h"
      46             : #include "utils/rel.h"
      47             : #include "utils/tqual.h"
      48             : 
      49             : 
      50             : /*
      51             :  * IsSystemRelation
      52             :  *      True iff the relation is either a system catalog or toast table.
      53             :  *      By a system catalog, we mean one that created in the pg_catalog schema
      54             :  *      during initdb.  User-created relations in pg_catalog don't count as
      55             :  *      system catalogs.
      56             :  *
      57             :  *      NB: TOAST relations are considered system relations by this test
      58             :  *      for compatibility with the old IsSystemRelationName function.
      59             :  *      This is appropriate in many places but not all.  Where it's not,
      60             :  *      also check IsToastRelation or use IsCatalogRelation().
      61             :  */
      62             : bool
      63       27281 : IsSystemRelation(Relation relation)
      64             : {
      65       27281 :     return IsSystemClass(RelationGetRelid(relation), relation->rd_rel);
      66             : }
      67             : 
      68             : /*
      69             :  * IsSystemClass
      70             :  *      Like the above, but takes a Form_pg_class as argument.
      71             :  *      Used when we do not want to open the relation and have to
      72             :  *      search pg_class directly.
      73             :  */
      74             : bool
      75       36441 : IsSystemClass(Oid relid, Form_pg_class reltuple)
      76             : {
      77       36441 :     return IsToastClass(reltuple) || IsCatalogClass(relid, reltuple);
      78             : }
      79             : 
      80             : /*
      81             :  * IsCatalogRelation
      82             :  *      True iff the relation is a system catalog, or the toast table for
      83             :  *      a system catalog.  By a system catalog, we mean one that created
      84             :  *      in the pg_catalog schema during initdb.  As with IsSystemRelation(),
      85             :  *      user-created relations in pg_catalog don't count as system catalogs.
      86             :  *
      87             :  *      Note that IsSystemRelation() returns true for ALL toast relations,
      88             :  *      but this function returns true only for toast relations of system
      89             :  *      catalogs.
      90             :  */
      91             : bool
      92     1233978 : IsCatalogRelation(Relation relation)
      93             : {
      94     1233978 :     return IsCatalogClass(RelationGetRelid(relation), relation->rd_rel);
      95             : }
      96             : 
      97             : /*
      98             :  * IsCatalogClass
      99             :  *      True iff the relation is a system catalog relation.
     100             :  *
     101             :  * Check IsCatalogRelation() for details.
     102             :  */
     103             : bool
     104     1269040 : IsCatalogClass(Oid relid, Form_pg_class reltuple)
     105             : {
     106     1269040 :     Oid         relnamespace = reltuple->relnamespace;
     107             : 
     108             :     /*
     109             :      * Never consider relations outside pg_catalog/pg_toast to be catalog
     110             :      * relations.
     111             :      */
     112     1269040 :     if (!IsSystemNamespace(relnamespace) && !IsToastNamespace(relnamespace))
     113      811231 :         return false;
     114             : 
     115             :     /* ----
     116             :      * Check whether the oid was assigned during initdb, when creating the
     117             :      * initial template database. Minus the relations in information_schema
     118             :      * excluded above, these are integral part of the system.
     119             :      * We could instead check whether the relation is pinned in pg_depend, but
     120             :      * this is noticeably cheaper and doesn't require catalog access.
     121             :      *
     122             :      * This test is safe since even an oid wraparound will preserve this
     123             :      * property (c.f. GetNewObjectId()) and it has the advantage that it works
     124             :      * correctly even if a user decides to create a relation in the pg_catalog
     125             :      * namespace.
     126             :      * ----
     127             :      */
     128      457809 :     return relid < FirstNormalObjectId;
     129             : }
     130             : 
     131             : /*
     132             :  * IsToastRelation
     133             :  *      True iff relation is a TOAST support relation (or index).
     134             :  */
     135             : bool
     136      123547 : IsToastRelation(Relation relation)
     137             : {
     138      123547 :     return IsToastNamespace(RelationGetNamespace(relation));
     139             : }
     140             : 
     141             : /*
     142             :  * IsToastClass
     143             :  *      Like the above, but takes a Form_pg_class as argument.
     144             :  *      Used when we do not want to open the relation and have to
     145             :  *      search pg_class directly.
     146             :  */
     147             : bool
     148       36441 : IsToastClass(Form_pg_class reltuple)
     149             : {
     150       36441 :     Oid         relnamespace = reltuple->relnamespace;
     151             : 
     152       36441 :     return IsToastNamespace(relnamespace);
     153             : }
     154             : 
     155             : /*
     156             :  * IsSystemNamespace
     157             :  *      True iff namespace is pg_catalog.
     158             :  *
     159             :  * NOTE: the reason this isn't a macro is to avoid having to include
     160             :  * catalog/pg_namespace.h in a lot of places.
     161             :  */
     162             : bool
     163     1276079 : IsSystemNamespace(Oid namespaceId)
     164             : {
     165     1276079 :     return namespaceId == PG_CATALOG_NAMESPACE;
     166             : }
     167             : 
     168             : /*
     169             :  * IsToastNamespace
     170             :  *      True iff namespace is pg_toast or my temporary-toast-table namespace.
     171             :  *
     172             :  * Note: this will return false for temporary-toast-table namespaces belonging
     173             :  * to other backends.  Those are treated the same as other backends' regular
     174             :  * temp table namespaces, and access is prevented where appropriate.
     175             :  */
     176             : bool
     177      975351 : IsToastNamespace(Oid namespaceId)
     178             : {
     179     1948094 :     return (namespaceId == PG_TOAST_NAMESPACE) ||
     180      972743 :         isTempToastNamespace(namespaceId);
     181             : }
     182             : 
     183             : 
     184             : /*
     185             :  * IsReservedName
     186             :  *      True iff name starts with the pg_ prefix.
     187             :  *
     188             :  *      For some classes of objects, the prefix pg_ is reserved for
     189             :  *      system objects only.  As of 8.0, this was only true for
     190             :  *      schema and tablespace names.  With 9.6, this is also true
     191             :  *      for roles.
     192             :  */
     193             : bool
     194         242 : IsReservedName(const char *name)
     195             : {
     196             :     /* ugly coding for speed */
     197         489 :     return (name[0] == 'p' &&
     198         246 :             name[1] == 'g' &&
     199           4 :             name[2] == '_');
     200             : }
     201             : 
     202             : 
     203             : /*
     204             :  * IsSharedRelation
     205             :  *      Given the OID of a relation, determine whether it's supposed to be
     206             :  *      shared across an entire database cluster.
     207             :  *
     208             :  * In older releases, this had to be hard-wired so that we could compute the
     209             :  * locktag for a relation and lock it before examining its catalog entry.
     210             :  * Since we now have MVCC catalog access, the race conditions that made that
     211             :  * a hard requirement are gone, so we could look at relaxing this restriction.
     212             :  * However, if we scanned the pg_class entry to find relisshared, and only
     213             :  * then locked the relation, pg_class could get updated in the meantime,
     214             :  * forcing us to scan the relation again, which would definitely be complex
     215             :  * and might have undesirable performance consequences.  Fortunately, the set
     216             :  * of shared relations is fairly static, so a hand-maintained list of their
     217             :  * OIDs isn't completely impractical.
     218             :  */
     219             : bool
     220     1006107 : IsSharedRelation(Oid relationId)
     221             : {
     222             :     /* These are the shared catalogs (look for BKI_SHARED_RELATION) */
     223     1006107 :     if (relationId == AuthIdRelationId ||
     224     1002346 :         relationId == AuthMemRelationId ||
     225     1000661 :         relationId == DatabaseRelationId ||
     226     1000653 :         relationId == PLTemplateRelationId ||
     227     1000529 :         relationId == SharedDescriptionRelationId ||
     228      986063 :         relationId == SharedDependRelationId ||
     229      985920 :         relationId == SharedSecLabelRelationId ||
     230      985262 :         relationId == TableSpaceRelationId ||
     231      984482 :         relationId == DbRoleSettingRelationId ||
     232      984406 :         relationId == ReplicationOriginRelationId ||
     233             :         relationId == SubscriptionRelationId)
     234       21951 :         return true;
     235             :     /* These are their indexes (see indexing.h) */
     236      984156 :     if (relationId == AuthIdRolnameIndexId ||
     237      981499 :         relationId == AuthIdOidIndexId ||
     238      981340 :         relationId == AuthMemRoleMemIndexId ||
     239      981077 :         relationId == AuthMemMemRoleIndexId ||
     240      980448 :         relationId == DatabaseNameIndexId ||
     241      979884 :         relationId == DatabaseOidIndexId ||
     242      979877 :         relationId == PLTemplateNameIndexId ||
     243      979758 :         relationId == SharedDescriptionObjIndexId ||
     244      969840 :         relationId == SharedDependDependerIndexId ||
     245      965206 :         relationId == SharedDependReferenceIndexId ||
     246      965089 :         relationId == SharedSecLabelObjectIndexId ||
     247      964778 :         relationId == TablespaceOidIndexId ||
     248      964745 :         relationId == TablespaceNameIndexId ||
     249      963113 :         relationId == DbRoleSettingDatidRolidIndexId ||
     250      963090 :         relationId == ReplicationOriginIdentIndex ||
     251      963071 :         relationId == ReplicationOriginNameIndex ||
     252      963021 :         relationId == SubscriptionObjectIndexId ||
     253             :         relationId == SubscriptionNameIndexId)
     254       21196 :         return true;
     255             :     /* These are their toast tables and toast indexes (see toasting.h) */
     256      962960 :     if (relationId == PgShdescriptionToastTable ||
     257      962953 :         relationId == PgShdescriptionToastIndex ||
     258      962949 :         relationId == PgDbRoleSettingToastTable ||
     259      962946 :         relationId == PgDbRoleSettingToastIndex ||
     260      962942 :         relationId == PgShseclabelToastTable ||
     261             :         relationId == PgShseclabelToastIndex)
     262          21 :         return true;
     263      962939 :     return false;
     264             : }
     265             : 
     266             : 
     267             : /*
     268             :  * GetNewOid
     269             :  *      Generate a new OID that is unique within the given relation.
     270             :  *
     271             :  * Caller must have a suitable lock on the relation.
     272             :  *
     273             :  * Uniqueness is promised only if the relation has a unique index on OID.
     274             :  * This is true for all system catalogs that have OIDs, but might not be
     275             :  * true for user tables.  Note that we are effectively assuming that the
     276             :  * table has a relatively small number of entries (much less than 2^32)
     277             :  * and there aren't very long runs of consecutive existing OIDs.  Again,
     278             :  * this is reasonable for system catalogs but less so for user tables.
     279             :  *
     280             :  * Since the OID is not immediately inserted into the table, there is a
     281             :  * race condition here; but a problem could occur only if someone else
     282             :  * managed to cycle through 2^32 OIDs and generate the same OID before we
     283             :  * finish inserting our row.  This seems unlikely to be a problem.  Note
     284             :  * that if we had to *commit* the row to end the race condition, the risk
     285             :  * would be rather higher; therefore we use SnapshotDirty in the test,
     286             :  * so that we will see uncommitted rows.
     287             :  */
     288             : Oid
     289       33441 : GetNewOid(Relation relation)
     290             : {
     291             :     Oid         oidIndex;
     292             : 
     293             :     /* If relation doesn't have OIDs at all, caller is confused */
     294       33441 :     Assert(relation->rd_rel->relhasoids);
     295             : 
     296             :     /* In bootstrap mode, we don't have any indexes to use */
     297       33441 :     if (IsBootstrapProcessingMode())
     298        1563 :         return GetNewObjectId();
     299             : 
     300             :     /* The relcache will cache the identity of the OID index for us */
     301       31878 :     oidIndex = RelationGetOidIndex(relation);
     302             : 
     303             :     /* If no OID index, just hand back the next OID counter value */
     304       31878 :     if (!OidIsValid(oidIndex))
     305             :     {
     306             :         /*
     307             :          * System catalogs that have OIDs should *always* have a unique OID
     308             :          * index; we should only take this path for user tables. Give a
     309             :          * warning if it looks like somebody forgot an index.
     310             :          */
     311       19193 :         if (IsSystemRelation(relation))
     312           0 :             elog(WARNING, "generating possibly-non-unique OID for \"%s\"",
     313             :                  RelationGetRelationName(relation));
     314             : 
     315       19193 :         return GetNewObjectId();
     316             :     }
     317             : 
     318             :     /* Otherwise, use the index to find a nonconflicting OID */
     319       12685 :     return GetNewOidWithIndex(relation, oidIndex, ObjectIdAttributeNumber);
     320             : }
     321             : 
     322             : /*
     323             :  * GetNewOidWithIndex
     324             :  *      Guts of GetNewOid: use the supplied index
     325             :  *
     326             :  * This is exported separately because there are cases where we want to use
     327             :  * an index that will not be recognized by RelationGetOidIndex: TOAST tables
     328             :  * have indexes that are usable, but have multiple columns and are on
     329             :  * ordinary columns rather than a true OID column.  This code will work
     330             :  * anyway, so long as the OID is the index's first column.  The caller must
     331             :  * pass in the actual heap attnum of the OID column, however.
     332             :  *
     333             :  * Caller must have a suitable lock on the relation.
     334             :  */
     335             : Oid
     336       12806 : GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
     337             : {
     338             :     Oid         newOid;
     339             :     SnapshotData SnapshotDirty;
     340             :     SysScanDesc scan;
     341             :     ScanKeyData key;
     342             :     bool        collides;
     343             : 
     344             :     /*
     345             :      * We should never be asked to generate a new pg_type OID during
     346             :      * pg_upgrade; doing so would risk collisions with the OIDs it wants to
     347             :      * assign.  Hitting this assert means there's some path where we failed to
     348             :      * ensure that a type OID is determined by commands in the dump script.
     349             :      */
     350       12806 :     Assert(!IsBinaryUpgrade || RelationGetRelid(relation) != TypeRelationId);
     351             : 
     352       12806 :     InitDirtySnapshot(SnapshotDirty);
     353             : 
     354             :     /* Generate new OIDs until we find one not in the table */
     355             :     do
     356             :     {
     357       12806 :         CHECK_FOR_INTERRUPTS();
     358             : 
     359       12806 :         newOid = GetNewObjectId();
     360             : 
     361       12806 :         ScanKeyInit(&key,
     362             :                     oidcolumn,
     363             :                     BTEqualStrategyNumber, F_OIDEQ,
     364             :                     ObjectIdGetDatum(newOid));
     365             : 
     366             :         /* see notes above about using SnapshotDirty */
     367       12806 :         scan = systable_beginscan(relation, indexId, true,
     368             :                                   &SnapshotDirty, 1, &key);
     369             : 
     370       12806 :         collides = HeapTupleIsValid(systable_getnext(scan));
     371             : 
     372       12806 :         systable_endscan(scan);
     373       12806 :     } while (collides);
     374             : 
     375       12806 :     return newOid;
     376             : }
     377             : 
     378             : /*
     379             :  * GetNewRelFileNode
     380             :  *      Generate a new relfilenode number that is unique within the
     381             :  *      database of the given tablespace.
     382             :  *
     383             :  * If the relfilenode will also be used as the relation's OID, pass the
     384             :  * opened pg_class catalog, and this routine will guarantee that the result
     385             :  * is also an unused OID within pg_class.  If the result is to be used only
     386             :  * as a relfilenode for an existing relation, pass NULL for pg_class.
     387             :  *
     388             :  * As with GetNewOid, there is some theoretical risk of a race condition,
     389             :  * but it doesn't seem worth worrying about.
     390             :  *
     391             :  * Note: we don't support using this in bootstrap mode.  All relations
     392             :  * created by bootstrap have preassigned OIDs, so there's no need.
     393             :  */
     394             : Oid
     395        4455 : GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
     396             : {
     397             :     RelFileNodeBackend rnode;
     398             :     char       *rpath;
     399             :     int         fd;
     400             :     bool        collides;
     401             :     BackendId   backend;
     402             : 
     403             :     /*
     404             :      * If we ever get here during pg_upgrade, there's something wrong; all
     405             :      * relfilenode assignments during a binary-upgrade run should be
     406             :      * determined by commands in the dump script.
     407             :      */
     408        4455 :     Assert(!IsBinaryUpgrade);
     409             : 
     410        4455 :     switch (relpersistence)
     411             :     {
     412             :         case RELPERSISTENCE_TEMP:
     413         650 :             backend = BackendIdForTempRelations();
     414         650 :             break;
     415             :         case RELPERSISTENCE_UNLOGGED:
     416             :         case RELPERSISTENCE_PERMANENT:
     417        3805 :             backend = InvalidBackendId;
     418        3805 :             break;
     419             :         default:
     420           0 :             elog(ERROR, "invalid relpersistence: %c", relpersistence);
     421             :             return InvalidOid;  /* placate compiler */
     422             :     }
     423             : 
     424             :     /* This logic should match RelationInitPhysicalAddr */
     425        4455 :     rnode.node.spcNode = reltablespace ? reltablespace : MyDatabaseTableSpace;
     426        4455 :     rnode.node.dbNode = (rnode.node.spcNode == GLOBALTABLESPACE_OID) ? InvalidOid : MyDatabaseId;
     427             : 
     428             :     /*
     429             :      * The relpath will vary based on the backend ID, so we must initialize
     430             :      * that properly here to make sure that any collisions based on filename
     431             :      * are properly detected.
     432             :      */
     433        4455 :     rnode.backend = backend;
     434             : 
     435             :     do
     436             :     {
     437        4455 :         CHECK_FOR_INTERRUPTS();
     438             : 
     439             :         /* Generate the OID */
     440        4455 :         if (pg_class)
     441        4159 :             rnode.node.relNode = GetNewOid(pg_class);
     442             :         else
     443         296 :             rnode.node.relNode = GetNewObjectId();
     444             : 
     445             :         /* Check for existing file of same name */
     446        4455 :         rpath = relpath(rnode, MAIN_FORKNUM);
     447        4455 :         fd = BasicOpenFile(rpath, O_RDONLY | PG_BINARY, 0);
     448             : 
     449        4455 :         if (fd >= 0)
     450             :         {
     451             :             /* definite collision */
     452           0 :             close(fd);
     453           0 :             collides = true;
     454             :         }
     455             :         else
     456             :         {
     457             :             /*
     458             :              * Here we have a little bit of a dilemma: if errno is something
     459             :              * other than ENOENT, should we declare a collision and loop? In
     460             :              * particular one might think this advisable for, say, EPERM.
     461             :              * However there really shouldn't be any unreadable files in a
     462             :              * tablespace directory, and if the EPERM is actually complaining
     463             :              * that we can't read the directory itself, we'd be in an infinite
     464             :              * loop.  In practice it seems best to go ahead regardless of the
     465             :              * errno.  If there is a colliding file we will get an smgr
     466             :              * failure when we attempt to create the new relation file.
     467             :              */
     468        4455 :             collides = false;
     469             :         }
     470             : 
     471        4455 :         pfree(rpath);
     472        4455 :     } while (collides);
     473             : 
     474        4455 :     return rnode.node.relNode;
     475             : }

Generated by: LCOV version 1.11