LCOV - code coverage report
Current view: top level - src/backend/access/common - relation.c (source / functions) Hit Total Coverage
Test: PostgreSQL 16beta1 Lines: 41 42 97.6 %
Date: 2023-05-31 04:12:22 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-2023, 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    52571948 : 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    52571948 :     if (lockmode != NoLock)
      56    48733666 :         LockRelationOid(relationId, lockmode);
      57             : 
      58             :     /* The relcache does all the real work... */
      59    52571946 :     r = RelationIdGetRelation(relationId);
      60             : 
      61    52571926 :     if (!RelationIsValid(r))
      62          14 :         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    52571912 :     if (RelationUsesLocalBuffers(r))
      74      245110 :         MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
      75             : 
      76    52571912 :     pgstat_init_relation(r);
      77             : 
      78    52571912 :     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      423690 : 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      423690 :     if (lockmode != NoLock)
      97      422758 :         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      423690 :     if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relationId)))
     104             :     {
     105             :         /* Release useless lock */
     106          14 :         if (lockmode != NoLock)
     107          14 :             UnlockRelationOid(relationId, lockmode);
     108             : 
     109          14 :         return NULL;
     110             :     }
     111             : 
     112             :     /* Should be safe to do a relcache load */
     113      423676 :     r = RelationIdGetRelation(relationId);
     114             : 
     115      423676 :     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      423676 :     if (RelationUsesLocalBuffers(r))
     124         496 :         MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
     125             : 
     126      423676 :     pgstat_init_relation(r);
     127             : 
     128      423676 :     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       81100 : 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       81100 :     if (lockmode != NoLock)
     154       44582 :         AcceptInvalidationMessages();
     155             : 
     156             :     /* Look up and lock the appropriate relation using namespace search */
     157       81100 :     relOid = RangeVarGetRelid(relation, lockmode, false);
     158             : 
     159             :     /* Let relation_open do the rest */
     160       81000 :     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      649906 : 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      649906 :     if (lockmode != NoLock)
     183      649906 :         AcceptInvalidationMessages();
     184             : 
     185             :     /* Look up and lock the appropriate relation using namespace search */
     186      649906 :     relOid = RangeVarGetRelid(relation, lockmode, missing_ok);
     187             : 
     188             :     /* Return NULL on not-found */
     189      649512 :     if (!OidIsValid(relOid))
     190         218 :         return NULL;
     191             : 
     192             :     /* Let relation_open do the rest */
     193      649294 :     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    28183032 : relation_close(Relation relation, LOCKMODE lockmode)
     207             : {
     208    28183032 :     LockRelId   relid = relation->rd_lockInfo.lockRelId;
     209             : 
     210             :     Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
     211             : 
     212             :     /* The relcache does the real work... */
     213    28183032 :     RelationClose(relation);
     214             : 
     215    28183032 :     if (lockmode != NoLock)
     216    22159022 :         UnlockRelationId(&relid, lockmode);
     217    28183032 : }

Generated by: LCOV version 1.14