LCOV - code coverage report
Current view: top level - src/backend/access/common - relation.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 41 42 97.6 %
Date: 2019-11-21 15:06:52 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * relation.c
       4             :  *    Generic relation related routines.
       5             :  *
       6             :  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/access/common/relation.c
      12             :  *
      13             :  * NOTES
      14             :  *    This file contains relation_ routines that implement access to relations
      15             :  *    (tables, indexes, etc). Support that's specific to subtypes of relations
      16             :  *    should go into their respective files, not here.
      17             :  *
      18             :  *-------------------------------------------------------------------------
      19             :  */
      20             : 
      21             : #include "postgres.h"
      22             : 
      23             : #include "access/relation.h"
      24             : #include "access/xact.h"
      25             : #include "catalog/namespace.h"
      26             : #include "miscadmin.h"
      27             : #include "pgstat.h"
      28             : #include "storage/lmgr.h"
      29             : #include "utils/inval.h"
      30             : #include "utils/syscache.h"
      31             : 
      32             : 
      33             : /* ----------------
      34             :  *      relation_open - open any relation by relation OID
      35             :  *
      36             :  *      If lockmode is not "NoLock", the specified kind of lock is
      37             :  *      obtained on the relation.  (Generally, NoLock should only be
      38             :  *      used if the caller knows it has some appropriate lock on the
      39             :  *      relation already.)
      40             :  *
      41             :  *      An error is raised if the relation does not exist.
      42             :  *
      43             :  *      NB: a "relation" is anything with a pg_class entry.  The caller is
      44             :  *      expected to check whether the relkind is something it can handle.
      45             :  * ----------------
      46             :  */
      47             : Relation
      48    27297928 : relation_open(Oid relationId, LOCKMODE lockmode)
      49             : {
      50             :     Relation    r;
      51             : 
      52             :     Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
      53             : 
      54             :     /* Get the lock before trying to open the relcache entry */
      55    27297928 :     if (lockmode != NoLock)
      56    25008306 :         LockRelationOid(relationId, lockmode);
      57             : 
      58             :     /* The relcache does all the real work... */
      59    27297928 :     r = RelationIdGetRelation(relationId);
      60             : 
      61    27297926 :     if (!RelationIsValid(r))
      62           4 :         elog(ERROR, "could not open relation with OID %u", relationId);
      63             : 
      64             :     /*
      65             :      * If we didn't get the lock ourselves, assert that caller holds one,
      66             :      * except in bootstrap mode where no locks are used.
      67             :      */
      68             :     Assert(lockmode != NoLock ||
      69             :            IsBootstrapProcessingMode() ||
      70             :            CheckRelationLockedByMe(r, AccessShareLock, true));
      71             : 
      72             :     /* Make note that we've accessed a temporary relation */
      73    27297922 :     if (RelationUsesLocalBuffers(r))
      74       79046 :         MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
      75             : 
      76    27297922 :     pgstat_initstats(r);
      77             : 
      78    27297922 :     return r;
      79             : }
      80             : 
      81             : /* ----------------
      82             :  *      try_relation_open - open any relation by relation OID
      83             :  *
      84             :  *      Same as relation_open, except return NULL instead of failing
      85             :  *      if the relation does not exist.
      86             :  * ----------------
      87             :  */
      88             : Relation
      89       73382 : try_relation_open(Oid relationId, LOCKMODE lockmode)
      90             : {
      91             :     Relation    r;
      92             : 
      93             :     Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
      94             : 
      95             :     /* Get the lock first */
      96       73382 :     if (lockmode != NoLock)
      97       72440 :         LockRelationOid(relationId, lockmode);
      98             : 
      99             :     /*
     100             :      * Now that we have the lock, probe to see if the relation really exists
     101             :      * or not.
     102             :      */
     103       73382 :     if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relationId)))
     104             :     {
     105             :         /* Release useless lock */
     106          16 :         if (lockmode != NoLock)
     107          16 :             UnlockRelationOid(relationId, lockmode);
     108             : 
     109          16 :         return NULL;
     110             :     }
     111             : 
     112             :     /* Should be safe to do a relcache load */
     113       73366 :     r = RelationIdGetRelation(relationId);
     114             : 
     115       73366 :     if (!RelationIsValid(r))
     116           0 :         elog(ERROR, "could not open relation with OID %u", relationId);
     117             : 
     118             :     /* If we didn't get the lock ourselves, assert that caller holds one */
     119             :     Assert(lockmode != NoLock ||
     120             :            CheckRelationLockedByMe(r, AccessShareLock, true));
     121             : 
     122             :     /* Make note that we've accessed a temporary relation */
     123       73366 :     if (RelationUsesLocalBuffers(r))
     124          96 :         MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
     125             : 
     126       73366 :     pgstat_initstats(r);
     127             : 
     128       73366 :     return r;
     129             : }
     130             : 
     131             : /* ----------------
     132             :  *      relation_openrv - open any relation specified by a RangeVar
     133             :  *
     134             :  *      Same as relation_open, but the relation is specified by a RangeVar.
     135             :  * ----------------
     136             :  */
     137             : Relation
     138       42372 : relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
     139             : {
     140             :     Oid         relOid;
     141             : 
     142             :     /*
     143             :      * Check for shared-cache-inval messages before trying to open the
     144             :      * relation.  This is needed even if we already hold a lock on the
     145             :      * relation, because GRANT/REVOKE are executed without taking any lock on
     146             :      * the target relation, and we want to be sure we see current ACL
     147             :      * information.  We can skip this if asked for NoLock, on the assumption
     148             :      * that such a call is not the first one in the current command, and so we
     149             :      * should be reasonably up-to-date already.  (XXX this all could stand to
     150             :      * be redesigned, but for the moment we'll keep doing this like it's been
     151             :      * done historically.)
     152             :      */
     153       42372 :     if (lockmode != NoLock)
     154       23374 :         AcceptInvalidationMessages();
     155             : 
     156             :     /* Look up and lock the appropriate relation using namespace search */
     157       42372 :     relOid = RangeVarGetRelid(relation, lockmode, false);
     158             : 
     159             :     /* Let relation_open do the rest */
     160       42300 :     return relation_open(relOid, NoLock);
     161             : }
     162             : 
     163             : /* ----------------
     164             :  *      relation_openrv_extended - open any relation specified by a RangeVar
     165             :  *
     166             :  *      Same as relation_openrv, but with an additional missing_ok argument
     167             :  *      allowing a NULL return rather than an error if the relation is not
     168             :  *      found.  (Note that some other causes, such as permissions problems,
     169             :  *      will still result in an ereport.)
     170             :  * ----------------
     171             :  */
     172             : Relation
     173      397218 : relation_openrv_extended(const RangeVar *relation, LOCKMODE lockmode,
     174             :                          bool missing_ok)
     175             : {
     176             :     Oid         relOid;
     177             : 
     178             :     /*
     179             :      * Check for shared-cache-inval messages before trying to open the
     180             :      * relation.  See comments in relation_openrv().
     181             :      */
     182      397218 :     if (lockmode != NoLock)
     183      397218 :         AcceptInvalidationMessages();
     184             : 
     185             :     /* Look up and lock the appropriate relation using namespace search */
     186      397218 :     relOid = RangeVarGetRelid(relation, lockmode, missing_ok);
     187             : 
     188             :     /* Return NULL on not-found */
     189      396956 :     if (!OidIsValid(relOid))
     190         128 :         return NULL;
     191             : 
     192             :     /* Let relation_open do the rest */
     193      396828 :     return relation_open(relOid, NoLock);
     194             : }
     195             : 
     196             : /* ----------------
     197             :  *      relation_close - close any relation
     198             :  *
     199             :  *      If lockmode is not "NoLock", we then release the specified lock.
     200             :  *
     201             :  *      Note that it is often sensible to hold a lock beyond relation_close;
     202             :  *      in that case, the lock is released automatically at xact end.
     203             :  * ----------------
     204             :  */
     205             : void
     206    13078028 : relation_close(Relation relation, LOCKMODE lockmode)
     207             : {
     208    13078028 :     LockRelId   relid = relation->rd_lockInfo.lockRelId;
     209             : 
     210             :     Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
     211             : 
     212             :     /* The relcache does the real work... */
     213    13078028 :     RelationClose(relation);
     214             : 
     215    13078028 :     if (lockmode != NoLock)
     216    10365496 :         UnlockRelationId(&relid, lockmode);
     217    13078028 : }

Generated by: LCOV version 1.13