LCOV - differential code coverage report
Current view: top level - src/backend/catalog - catalog.c (source / functions) Coverage Total Hit LBC UBC GBC GNC CBC DCB
Current: 77aeca80249c9e640c811e80633a2e334a9320de vs 38afc3dcb25c45b744d4025029ce0a6c90b7059f Lines: 79.1 % 177 140 37 8 132 1
Current Date: 2026-07-25 19:08:27 +0900 Functions: 95.0 % 20 19 1 3 16
Baseline: lcov-20260725-baseline Branches: 75.1 % 197 148 1 48 1 6 141
Baseline Date: 2026-07-25 19:09:19 +0900 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 100.0 % 8 8 8
(360..) days: 78.1 % 169 132 37 132
Function coverage date bins:
(7,30] days: 100.0 % 2 2 2
(360..) days: 94.4 % 18 17 1 1 16
Branch coverage date bins:
(7,30] days: 100.0 % 6 6 6
(360..) days: 74.3 % 191 142 1 48 1 141

 Age         Owner                    Branch data    TLA  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-2026, 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/htup_details.h"
                                 25                 :                : #include "access/table.h"
                                 26                 :                : #include "access/transam.h"
                                 27                 :                : #include "catalog/catalog.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_db_role_setting.h"
                                 33                 :                : #include "catalog/pg_largeobject.h"
                                 34                 :                : #include "catalog/pg_namespace.h"
                                 35                 :                : #include "catalog/pg_parameter_acl.h"
                                 36                 :                : #include "catalog/pg_replication_origin.h"
                                 37                 :                : #include "catalog/pg_seclabel.h"
                                 38                 :                : #include "catalog/pg_shdepend.h"
                                 39                 :                : #include "catalog/pg_shdescription.h"
                                 40                 :                : #include "catalog/pg_shseclabel.h"
                                 41                 :                : #include "catalog/pg_subscription.h"
                                 42                 :                : #include "catalog/pg_tablespace.h"
                                 43                 :                : #include "catalog/pg_type.h"
                                 44                 :                : #include "miscadmin.h"
                                 45                 :                : #include "utils/fmgroids.h"
                                 46                 :                : #include "utils/fmgrprotos.h"
                                 47                 :                : #include "utils/rel.h"
                                 48                 :                : #include "utils/snapmgr.h"
                                 49                 :                : #include "utils/syscache.h"
                                 50                 :                : 
                                 51                 :                : /*
                                 52                 :                :  * Parameters to determine when to emit a log message in
                                 53                 :                :  * GetNewOidWithIndex()
                                 54                 :                :  */
                                 55                 :                : #define GETNEWOID_LOG_THRESHOLD 1000000
                                 56                 :                : #define GETNEWOID_LOG_MAX_INTERVAL 128000000
                                 57                 :                : 
                                 58                 :                : /*
                                 59                 :                :  * IsSystemRelation
                                 60                 :                :  *      True iff the relation is either a system catalog or a toast table.
                                 61                 :                :  *      See IsCatalogRelation for the exact definition of a system catalog.
                                 62                 :                :  *
                                 63                 :                :  *      We treat toast tables of user relations as "system relations" for
                                 64                 :                :  *      protection purposes, e.g. you can't change their schemas without
                                 65                 :                :  *      special permissions.  Therefore, most uses of this function are
                                 66                 :                :  *      checking whether allow_system_table_mods restrictions apply.
                                 67                 :                :  *      For other purposes, consider whether you shouldn't be using
                                 68                 :                :  *      IsCatalogRelation instead.
                                 69                 :                :  *
                                 70                 :                :  *      This function does not perform any catalog accesses.
                                 71                 :                :  *      Some callers rely on that!
                                 72                 :                :  */
                                 73                 :                : bool
 8870 tgl@sss.pgh.pa.us          74                 :CBC      759154 : IsSystemRelation(Relation relation)
                                 75                 :                : {
 4622 rhaas@postgresql.org       76                 :         759154 :     return IsSystemClass(RelationGetRelid(relation), relation->rd_rel);
                                 77                 :                : }
                                 78                 :                : 
                                 79                 :                : /*
                                 80                 :                :  * IsSystemClass
                                 81                 :                :  *      Like the above, but takes a Form_pg_class as argument.
                                 82                 :                :  *      Used when we do not want to open the relation and have to
                                 83                 :                :  *      search pg_class directly.
                                 84                 :                :  */
                                 85                 :                : bool
                                 86                 :         824597 : IsSystemClass(Oid relid, Form_pg_class reltuple)
                                 87                 :                : {
                                 88                 :                :     /* IsCatalogRelationOid is a bit faster, so test that first */
   23 akapila@postgresql.o       89         [ +  + ]:GNC     1038559 :     return (IsCatalogRelationOid(relid) ||
                                 90   [ +  +  +  + ]:        1038559 :             IsToastClass(reltuple) ||
                                 91                 :         177632 :             IsConflictLogTableClass(reltuple));
                                 92                 :                : }
                                 93                 :                : 
                                 94                 :                : /*
                                 95                 :                :  * IsCatalogRelation
                                 96                 :                :  *      True iff the relation is a system catalog.
                                 97                 :                :  *
                                 98                 :                :  *      By a system catalog, we mean one that is created during the bootstrap
                                 99                 :                :  *      phase of initdb.  That includes not just the catalogs per se, but
                                100                 :                :  *      also their indexes, and TOAST tables and indexes if any.
                                101                 :                :  *
                                102                 :                :  *      This function does not perform any catalog accesses.
                                103                 :                :  *      Some callers rely on that!
                                104                 :                :  */
                                105                 :                : bool
 4622 rhaas@postgresql.org      106                 :CBC    40628899 : IsCatalogRelation(Relation relation)
                                107                 :                : {
 2635 tgl@sss.pgh.pa.us         108                 :       40628899 :     return IsCatalogRelationOid(RelationGetRelid(relation));
                                109                 :                : }
                                110                 :                : 
                                111                 :                : /*
                                112                 :                :  * IsCatalogRelationOid
                                113                 :                :  *      True iff the relation identified by this OID is a system catalog.
                                114                 :                :  *
                                115                 :                :  *      By a system catalog, we mean one that is created during the bootstrap
                                116                 :                :  *      phase of initdb.  That includes not just the catalogs per se, but
                                117                 :                :  *      also their indexes, and TOAST tables and indexes if any.
                                118                 :                :  *
                                119                 :                :  *      This function does not perform any catalog accesses.
                                120                 :                :  *      Some callers rely on that!
                                121                 :                :  */
                                122                 :                : bool
                                123                 :      403562793 : IsCatalogRelationOid(Oid relid)
                                124                 :                : {
                                125                 :                :     /*
                                126                 :                :      * We consider a relation to be a system catalog if it has a pinned OID.
                                127                 :                :      * This includes all the defined catalogs, their indexes, and their TOAST
                                128                 :                :      * tables and indexes.
                                129                 :                :      *
                                130                 :                :      * This rule excludes the relations in information_schema, which are not
                                131                 :                :      * integral to the system and can be treated the same as user relations.
                                132                 :                :      * (Since it's valid to drop and recreate information_schema, any rule
                                133                 :                :      * that did not act this way would be wrong.)
                                134                 :                :      *
                                135                 :                :      * This test is reliable since an OID wraparound will skip this range of
                                136                 :                :      * OIDs; see GetNewObjectId().
                                137                 :                :      */
 1836                           138                 :      403562793 :     return (relid < (Oid) FirstUnpinnedObjectId);
                                139                 :                : }
                                140                 :                : 
                                141                 :                : /*
                                142                 :                :  * IsCatalogTextUniqueIndexOid
                                143                 :                :  *      True iff the relation identified by this OID is a catalog UNIQUE index
                                144                 :                :  *      having a column of type "text".
                                145                 :                :  *
                                146                 :                :  *      The relcache must not use these indexes.  Inserting into any UNIQUE
                                147                 :                :  *      index compares index keys while holding BUFFER_LOCK_EXCLUSIVE.
                                148                 :                :  *      bttextcmp() can search the COLLOID catcache.  Depending on concurrent
                                149                 :                :  *      invalidation traffic, catcache can reach relcache builds.  A backend
                                150                 :                :  *      would self-deadlock on LWLocks if the relcache build read the
                                151                 :                :  *      exclusive-locked buffer.
                                152                 :                :  *
                                153                 :                :  *      To avoid being itself the cause of self-deadlock, this doesn't read
                                154                 :                :  *      catalogs.  Instead, it uses a hard-coded list with a supporting
                                155                 :                :  *      regression test.
                                156                 :                :  */
                                157                 :                : bool
  464 noah@leadboat.com         158                 :          12211 : IsCatalogTextUniqueIndexOid(Oid relid)
                                159                 :                : {
                                160         [ +  + ]:          12211 :     switch (relid)
                                161                 :                :     {
                                162                 :             16 :         case ParameterAclParnameIndexId:
                                163                 :                :         case ReplicationOriginNameIndex:
                                164                 :                :         case SecLabelObjectIndexId:
                                165                 :                :         case SharedSecLabelObjectIndexId:
                                166                 :             16 :             return true;
                                167                 :                :     }
                                168                 :          12195 :     return false;
                                169                 :                : }
                                170                 :                : 
                                171                 :                : /*
                                172                 :                :  * IsInplaceUpdateRelation
                                173                 :                :  *      True iff core code performs inplace updates on the relation.
                                174                 :                :  *
                                175                 :                :  *      This is used for assertions and for making the executor follow the
                                176                 :                :  *      locking protocol described at README.tuplock section "Locking to write
                                177                 :                :  *      inplace-updated tables".  Extensions may inplace-update other heap
                                178                 :                :  *      tables, but concurrent SQL UPDATE on the same table may overwrite
                                179                 :                :  *      those modifications.
                                180                 :                :  *
                                181                 :                :  *      The executor can assume these are not partitions or partitioned and
                                182                 :                :  *      have no triggers.
                                183                 :                :  */
                                184                 :                : bool
  758                           185                 :        2756612 : IsInplaceUpdateRelation(Relation relation)
                                186                 :                : {
                                187                 :        2756612 :     return IsInplaceUpdateOid(RelationGetRelid(relation));
                                188                 :                : }
                                189                 :                : 
                                190                 :                : /*
                                191                 :                :  * IsInplaceUpdateOid
                                192                 :                :  *      Like the above, but takes an OID as argument.
                                193                 :                :  */
                                194                 :                : bool
                                195                 :        2756612 : IsInplaceUpdateOid(Oid relid)
                                196                 :                : {
                                197   [ +  +  +  + ]:        2756612 :     return (relid == RelationRelationId ||
                                198                 :                :             relid == DatabaseRelationId);
                                199                 :                : }
                                200                 :                : 
                                201                 :                : /*
                                202                 :                :  * IsToastRelation
                                203                 :                :  *      True iff relation is a TOAST support relation (or index).
                                204                 :                :  *
                                205                 :                :  *      Does not perform any catalog accesses.
                                206                 :                :  */
                                207                 :                : bool
 8870 tgl@sss.pgh.pa.us         208                 :        3346238 : IsToastRelation(Relation relation)
                                209                 :                : {
                                210                 :                :     /*
                                211                 :                :      * What we actually check is whether the relation belongs to a pg_toast
                                212                 :                :      * namespace.  This should be equivalent because of restrictions that are
                                213                 :                :      * enforced elsewhere against creating user relations in, or moving
                                214                 :                :      * relations into/out of, a pg_toast namespace.  Notice also that this
                                215                 :                :      * will not say "true" for toast tables belonging to other sessions' temp
                                216                 :                :      * tables; we expect that other mechanisms will prevent access to those.
                                217                 :                :      */
                                218                 :        3346238 :     return IsToastNamespace(RelationGetNamespace(relation));
                                219                 :                : }
                                220                 :                : 
                                221                 :                : /*
                                222                 :                :  * IsToastClass
                                223                 :                :  *      Like the above, but takes a Form_pg_class as argument.
                                224                 :                :  *      Used when we do not want to open the relation and have to
                                225                 :                :  *      search pg_class directly.
                                226                 :                :  */
                                227                 :                : bool
                                228                 :         213962 : IsToastClass(Form_pg_class reltuple)
                                229                 :                : {
 8725 bruce@momjian.us          230                 :         213962 :     Oid         relnamespace = reltuple->relnamespace;
                                231                 :                : 
                                232                 :         213962 :     return IsToastNamespace(relnamespace);
                                233                 :                : }
                                234                 :                : 
                                235                 :                : /*
                                236                 :                :  * IsConflictLogTableClass
                                237                 :                :  *      True iff pg_class tuple represents a Conflict Log Table.
                                238                 :                :  *
                                239                 :                :  *      Does not perform any catalog accesses.
                                240                 :                :  */
                                241                 :                : bool
   23 akapila@postgresql.o      242                 :GNC      585998 : IsConflictLogTableClass(Form_pg_class reltuple)
                                243                 :                : {
                                244                 :         585998 :     Oid         relnamespace = reltuple->relnamespace;
                                245                 :                : 
                                246                 :         585998 :     return IsConflictLogTableNamespace(relnamespace);
                                247                 :                : }
                                248                 :                : 
                                249                 :                : /*
                                250                 :                :  * IsCatalogNamespace
                                251                 :                :  *      True iff namespace is pg_catalog.
                                252                 :                :  *
                                253                 :                :  *      Does not perform any catalog accesses.
                                254                 :                :  *
                                255                 :                :  * NOTE: the reason this isn't a macro is to avoid having to include
                                256                 :                :  * catalog/pg_namespace.h in a lot of places.
                                257                 :                :  */
                                258                 :                : bool
 2635 tgl@sss.pgh.pa.us         259                 :CBC      143749 : IsCatalogNamespace(Oid namespaceId)
                                260                 :                : {
 8870                           261                 :         143749 :     return namespaceId == PG_CATALOG_NAMESPACE;
                                262                 :                : }
                                263                 :                : 
                                264                 :                : /*
                                265                 :                :  * IsToastNamespace
                                266                 :                :  *      True iff namespace is pg_toast or my temporary-toast-table namespace.
                                267                 :                :  *
                                268                 :                :  *      Does not perform any catalog accesses.
                                269                 :                :  *
                                270                 :                :  * Note: this will return false for temporary-toast-table namespaces belonging
                                271                 :                :  * to other backends.  Those are treated the same as other backends' regular
                                272                 :                :  * temp table namespaces, and access is prevented where appropriate.
                                273                 :                :  * If you need to check for those, you may be able to use isAnyTempNamespace,
                                274                 :                :  * but beware that that does involve a catalog access.
                                275                 :                :  */
                                276                 :                : bool
                                277                 :        3623163 : IsToastNamespace(Oid namespaceId)
                                278                 :                : {
 6940                           279   [ +  +  +  + ]:        7180256 :     return (namespaceId == PG_TOAST_NAMESPACE) ||
                                280                 :        3557093 :         isTempToastNamespace(namespaceId);
                                281                 :                : }
                                282                 :                : 
                                283                 :                : /*
                                284                 :                :  * IsConflictLogTableNamespace
                                285                 :                :  *      True iff namespace is pg_conflict.
                                286                 :                :  *
                                287                 :                :  *      Does not perform any catalog accesses.
                                288                 :                :  */
                                289                 :                : bool
   23 akapila@postgresql.o      290                 :GNC      798432 : IsConflictLogTableNamespace(Oid namespaceId)
                                291                 :                : {
                                292                 :         798432 :     return namespaceId == PG_CONFLICT_NAMESPACE;
                                293                 :                : }
                                294                 :                : 
                                295                 :                : /*
                                296                 :                :  * IsReservedName
                                297                 :                :  *      True iff name starts with the pg_ prefix.
                                298                 :                :  *
                                299                 :                :  *      For some classes of objects, the prefix pg_ is reserved for
                                300                 :                :  *      system objects only.  As of 8.0, this was only true for
                                301                 :                :  *      schema and tablespace names.  With 9.6, this is also true
                                302                 :                :  *      for roles.
                                303                 :                :  */
                                304                 :                : bool
 8870 tgl@sss.pgh.pa.us         305                 :CBC        2435 : IsReservedName(const char *name)
                                306                 :                : {
                                307                 :                :     /* ugly coding for speed */
                                308                 :           2508 :     return (name[0] == 'p' &&
                                309   [ +  +  +  + ]:           2449 :             name[1] == 'g' &&
                                310         [ +  + ]:             14 :             name[2] == '_');
                                311                 :                : }
                                312                 :                : 
                                313                 :                : 
                                314                 :                : /*
                                315                 :                :  * IsSharedRelation
                                316                 :                :  *      Given the OID of a relation, determine whether it's supposed to be
                                317                 :                :  *      shared across an entire database cluster.
                                318                 :                :  *
                                319                 :                :  * In older releases, this had to be hard-wired so that we could compute the
                                320                 :                :  * locktag for a relation and lock it before examining its catalog entry.
                                321                 :                :  * Since we now have MVCC catalog access, the race conditions that made that
                                322                 :                :  * a hard requirement are gone, so we could look at relaxing this restriction.
                                323                 :                :  * However, if we scanned the pg_class entry to find relisshared, and only
                                324                 :                :  * then locked the relation, pg_class could get updated in the meantime,
                                325                 :                :  * forcing us to scan the relation again, which would definitely be complex
                                326                 :                :  * and might have undesirable performance consequences.  Fortunately, the set
                                327                 :                :  * of shared relations is fairly static, so a hand-maintained list of their
                                328                 :                :  * OIDs isn't completely impractical.
                                329                 :                :  */
                                330                 :                : bool
 7299                           331                 :       26385860 : IsSharedRelation(Oid relationId)
                                332                 :                : {
                                333                 :                :     /* These are the shared catalogs (look for BKI_SHARED_RELATION) */
                                334   [ +  +  +  + ]:       26385860 :     if (relationId == AuthIdRelationId ||
                                335         [ +  + ]:       26262462 :         relationId == AuthMemRelationId ||
                                336         [ +  + ]:       26176403 :         relationId == DatabaseRelationId ||
 4105 andres@anarazel.de        337         [ +  + ]:       26152717 :         relationId == DbRoleSettingRelationId ||
 1571 tgl@sss.pgh.pa.us         338         [ +  + ]:       26134287 :         relationId == ParameterAclRelationId ||
 3474 peter_e@gmx.net           339         [ +  + ]:       26117535 :         relationId == ReplicationOriginRelationId ||
 1571 tgl@sss.pgh.pa.us         340         [ +  + ]:       25814494 :         relationId == SharedDependRelationId ||
                                341         [ +  + ]:       25811413 :         relationId == SharedDescriptionRelationId ||
                                342         [ +  + ]:       25805126 :         relationId == SharedSecLabelRelationId ||
                                343         [ +  + ]:       25783906 :         relationId == SubscriptionRelationId ||
                                344                 :                :         relationId == TableSpaceRelationId)
 7299                           345                 :         628465 :         return true;
                                346                 :                :     /* These are their indexes */
 1571                           347   [ +  +  +  + ]:       25757395 :     if (relationId == AuthIdOidIndexId ||
                                348         [ +  + ]:       25692292 :         relationId == AuthIdRolnameIndexId ||
 7299                           349         [ +  + ]:       25682651 :         relationId == AuthMemMemRoleIndexId ||
 1571                           350         [ +  + ]:       25677678 :         relationId == AuthMemRoleMemIndexId ||
 1437 rhaas@postgresql.org      351         [ +  + ]:       25675809 :         relationId == AuthMemOidIndexId ||
                                352         [ +  + ]:       25674539 :         relationId == AuthMemGrantorIndexId ||
 7299 tgl@sss.pgh.pa.us         353         [ +  + ]:       25652514 :         relationId == DatabaseNameIndexId ||
                                354         [ +  + ]:       25608461 :         relationId == DatabaseOidIndexId ||
 4105 andres@anarazel.de        355         [ +  + ]:       25535604 :         relationId == DbRoleSettingDatidRolidIndexId ||
 1571 tgl@sss.pgh.pa.us         356         [ +  + ]:       25530019 :         relationId == ParameterAclOidIndexId ||
                                357         [ +  + ]:       25524471 :         relationId == ParameterAclParnameIndexId ||
 4105 andres@anarazel.de        358         [ +  + ]:       25520123 :         relationId == ReplicationOriginIdentIndex ||
 3474 peter_e@gmx.net           359         [ +  + ]:       25515967 :         relationId == ReplicationOriginNameIndex ||
 1571 tgl@sss.pgh.pa.us         360         [ +  + ]:       25347219 :         relationId == SharedDependDependerIndexId ||
                                361         [ +  + ]:       25338991 :         relationId == SharedDependReferenceIndexId ||
                                362         [ +  + ]:       25336640 :         relationId == SharedDescriptionObjIndexId ||
                                363         [ +  + ]:       25331092 :         relationId == SharedSecLabelObjectIndexId ||
                                364         [ +  + ]:       25326232 :         relationId == SubscriptionNameIndexId ||
 3474 peter_e@gmx.net           365         [ +  + ]:       25320876 :         relationId == SubscriptionObjectIndexId ||
 1571 tgl@sss.pgh.pa.us         366         [ +  + ]:       25318737 :         relationId == TablespaceNameIndexId ||
                                367                 :                :         relationId == TablespaceOidIndexId)
 7299                           368                 :         451866 :         return true;
                                369                 :                :     /* These are their toast tables and toast indexes */
  672 nathan@postgresql.or      370   [ +  +  +  + ]:       25305529 :     if (relationId == PgDatabaseToastTable ||
 2927 michael@paquier.xyz       371         [ +  + ]:       25304244 :         relationId == PgDatabaseToastIndex ||
 6135 alvherre@alvh.no-ip.      372         [ +  + ]:       25303653 :         relationId == PgDbRoleSettingToastTable ||
 4144 bruce@momjian.us          373         [ +  + ]:       25303297 :         relationId == PgDbRoleSettingToastIndex ||
 1571 tgl@sss.pgh.pa.us         374         [ +  + ]:       25302706 :         relationId == PgParameterAclToastTable ||
                                375         [ +  + ]:       25302350 :         relationId == PgParameterAclToastIndex ||
 2927 michael@paquier.xyz       376         [ +  + ]:       25301726 :         relationId == PgShdescriptionToastTable ||
                                377         [ +  + ]:       25301337 :         relationId == PgShdescriptionToastIndex ||
 4144 bruce@momjian.us          378         [ +  + ]:       25300746 :         relationId == PgShseclabelToastTable ||
 2927 michael@paquier.xyz       379         [ +  + ]:       25300390 :         relationId == PgShseclabelToastIndex ||
                                380         [ +  + ]:       25299799 :         relationId == PgSubscriptionToastTable ||
                                381         [ +  + ]:       25299443 :         relationId == PgSubscriptionToastIndex ||
                                382         [ +  + ]:       25298826 :         relationId == PgTablespaceToastTable ||
                                383                 :                :         relationId == PgTablespaceToastIndex)
 7299 tgl@sss.pgh.pa.us         384                 :           7086 :         return true;
                                385                 :       25298443 :     return false;
                                386                 :                : }
                                387                 :                : 
                                388                 :                : /*
                                389                 :                :  * IsPinnedObject
                                390                 :                :  *      Given the class + OID identity of a database object, report whether
                                391                 :                :  *      it is "pinned", that is not droppable because the system requires it.
                                392                 :                :  *
                                393                 :                :  * We used to represent this explicitly in pg_depend, but that proved to be
                                394                 :                :  * an undesirable amount of overhead, so now we rely on an OID range test.
                                395                 :                :  */
                                396                 :                : bool
 1836                           397                 :        2125102 : IsPinnedObject(Oid classId, Oid objectId)
                                398                 :                : {
                                399                 :                :     /*
                                400                 :                :      * Objects with OIDs above FirstUnpinnedObjectId are never pinned.  Since
                                401                 :                :      * the OID generator skips this range when wrapping around, this check
                                402                 :                :      * guarantees that user-defined objects are never considered pinned.
                                403                 :                :      */
                                404         [ +  + ]:        2125102 :     if (objectId >= FirstUnpinnedObjectId)
                                405                 :         896671 :         return false;
                                406                 :                : 
                                407                 :                :     /*
                                408                 :                :      * Large objects are never pinned.  We need this special case because
                                409                 :                :      * their OIDs can be user-assigned.
                                410                 :                :      */
                                411         [ +  + ]:        1228431 :     if (classId == LargeObjectRelationId)
                                412                 :             36 :         return false;
                                413                 :                : 
                                414                 :                :     /*
                                415                 :                :      * There are a few objects defined in the catalog .dat files that, as a
                                416                 :                :      * matter of policy, we prefer not to treat as pinned.  We used to handle
                                417                 :                :      * that by excluding them from pg_depend, but it's just as easy to
                                418                 :                :      * hard-wire their OIDs here.  (If the user does indeed drop and recreate
                                419                 :                :      * them, they'll have new but certainly-unpinned OIDs, so no problem.)
                                420                 :                :      *
                                421                 :                :      * Checking both classId and objectId is overkill, since OIDs below
                                422                 :                :      * FirstGenbkiObjectId should be globally unique, but do it anyway for
                                423                 :                :      * robustness.
                                424                 :                :      */
                                425                 :                : 
                                426                 :                :     /* the public namespace is not pinned */
                                427   [ +  +  +  + ]:        1228395 :     if (classId == NamespaceRelationId &&
                                428                 :                :         objectId == PG_PUBLIC_NAMESPACE)
                                429                 :          74922 :         return false;
                                430                 :                : 
                                431                 :                :     /*
                                432                 :                :      * Databases are never pinned.  It might seem that it'd be prudent to pin
                                433                 :                :      * at least template0; but we do this intentionally so that template0 and
                                434                 :                :      * template1 can be rebuilt from each other, thus letting them serve as
                                435                 :                :      * mutual backups (as long as you've not modified template1, anyway).
                                436                 :                :      */
 1556                           437         [ -  + ]:        1153473 :     if (classId == DatabaseRelationId)
 1556 tgl@sss.pgh.pa.us         438                 :UBC           0 :         return false;
                                439                 :                : 
                                440                 :                :     /*
                                441                 :                :      * All other initdb-created objects are pinned.  This is overkill (the
                                442                 :                :      * system doesn't really depend on having every last weird datatype, for
                                443                 :                :      * instance) but generating only the minimum required set of dependencies
                                444                 :                :      * seems hard, and enforcing an accurate list would be much more expensive
                                445                 :                :      * than the simple range test used here.
                                446                 :                :      */
 1836 tgl@sss.pgh.pa.us         447                 :CBC     1153473 :     return true;
                                448                 :                : }
                                449                 :                : 
                                450                 :                : 
                                451                 :                : /*
                                452                 :                :  * GetNewOidWithIndex
                                453                 :                :  *      Generate a new OID that is unique within the system relation.
                                454                 :                :  *
                                455                 :                :  * Since the OID is not immediately inserted into the table, there is a
                                456                 :                :  * race condition here; but a problem could occur only if someone else
                                457                 :                :  * managed to cycle through 2^32 OIDs and generate the same OID before we
                                458                 :                :  * finish inserting our row.  This seems unlikely to be a problem.  Note
                                459                 :                :  * that if we had to *commit* the row to end the race condition, the risk
                                460                 :                :  * would be rather higher; therefore we use SnapshotAny in the test, so that
                                461                 :                :  * we will see uncommitted rows.  (We used to use SnapshotDirty, but that has
                                462                 :                :  * the disadvantage that it ignores recently-deleted rows, creating a risk
                                463                 :                :  * of transient conflicts for as long as our own MVCC snapshots think a
                                464                 :                :  * recently-deleted row is live.  The risk is far higher when selecting TOAST
                                465                 :                :  * OIDs, because SnapshotToast considers dead rows as active indefinitely.)
                                466                 :                :  *
                                467                 :                :  * Note that we are effectively assuming that the table has a relatively small
                                468                 :                :  * number of entries (much less than 2^32) and there aren't very long runs of
                                469                 :                :  * consecutive existing OIDs.  This is a mostly reasonable assumption for
                                470                 :                :  * system catalogs.
                                471                 :                :  *
                                472                 :                :  * Caller must have a suitable lock on the relation.
                                473                 :                :  */
                                474                 :                : Oid
 6678                           475                 :         569043 : GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
                                476                 :                : {
                                477                 :                :     Oid         newOid;
                                478                 :                :     SysScanDesc scan;
                                479                 :                :     ScanKeyData key;
                                480                 :                :     bool        collides;
 1949 fujii@postgresql.org      481                 :         569043 :     uint64      retries = 0;
                                482                 :         569043 :     uint64      retries_before_log = GETNEWOID_LOG_THRESHOLD;
                                483                 :                : 
                                484                 :                :     /* Only system relations are supported */
 2804 andres@anarazel.de        485         [ -  + ]:         569043 :     Assert(IsSystemRelation(relation));
                                486                 :                : 
                                487                 :                :     /* In bootstrap mode, we don't have any indexes to use */
                                488         [ +  + ]:         569043 :     if (IsBootstrapProcessingMode())
                                489                 :           6944 :         return GetNewObjectId();
                                490                 :                : 
                                491                 :                :     /*
                                492                 :                :      * We should never be asked to generate a new pg_type OID during
                                493                 :                :      * pg_upgrade; doing so would risk collisions with the OIDs it wants to
                                494                 :                :      * assign.  Hitting this assert means there's some path where we failed to
                                495                 :                :      * ensure that a type OID is determined by commands in the dump script.
                                496                 :                :      */
 3330 tgl@sss.pgh.pa.us         497   [ +  +  -  + ]:         562099 :     Assert(!IsBinaryUpgrade || RelationGetRelid(relation) != TypeRelationId);
                                498                 :                : 
                                499                 :                :     /* Generate new OIDs until we find one not in the table */
                                500                 :                :     do
                                501                 :                :     {
 6730                           502         [ -  + ]:         562099 :         CHECK_FOR_INTERRUPTS();
                                503                 :                : 
 7652                           504                 :         562099 :         newOid = GetNewObjectId();
                                505                 :                : 
                                506                 :         562099 :         ScanKeyInit(&key,
                                507                 :                :                     oidcolumn,
                                508                 :                :                     BTEqualStrategyNumber, F_OIDEQ,
                                509                 :                :                     ObjectIdGetDatum(newOid));
                                510                 :                : 
                                511                 :                :         /* see notes above about using SnapshotAny */
 6678                           512                 :         562099 :         scan = systable_beginscan(relation, indexId, true,
                                513                 :                :                                   SnapshotAny, 1, &key);
                                514                 :                : 
                                515                 :         562099 :         collides = HeapTupleIsValid(systable_getnext(scan));
                                516                 :                : 
                                517                 :         562099 :         systable_endscan(scan);
                                518                 :                : 
                                519                 :                :         /*
                                520                 :                :          * Log that we iterate more than GETNEWOID_LOG_THRESHOLD but have not
                                521                 :                :          * yet found OID unused in the relation. Then repeat logging with
                                522                 :                :          * exponentially increasing intervals until we iterate more than
                                523                 :                :          * GETNEWOID_LOG_MAX_INTERVAL. Finally repeat logging every
                                524                 :                :          * GETNEWOID_LOG_MAX_INTERVAL unless an unused OID is found. This
                                525                 :                :          * logic is necessary not to fill up the server log with the similar
                                526                 :                :          * messages.
                                527                 :                :          */
 1949 fujii@postgresql.org      528         [ -  + ]:         562099 :         if (retries >= retries_before_log)
                                529                 :                :         {
 1949 fujii@postgresql.org      530         [ #  # ]:UBC           0 :             ereport(LOG,
                                531                 :                :                     (errmsg("still searching for an unused OID in relation \"%s\"",
                                532                 :                :                             RelationGetRelationName(relation)),
                                533                 :                :                      errdetail_plural("OID candidates have been checked %" PRIu64 " time, but no unused OID has been found yet.",
                                534                 :                :                                       "OID candidates have been checked %" PRIu64 " times, but no unused OID has been found yet.",
                                535                 :                :                                       retries,
                                536                 :                :                                       retries)));
                                537                 :                : 
                                538                 :                :             /*
                                539                 :                :              * Double the number of retries to do before logging next until it
                                540                 :                :              * reaches GETNEWOID_LOG_MAX_INTERVAL.
                                541                 :                :              */
                                542         [ #  # ]:              0 :             if (retries_before_log * 2 <= GETNEWOID_LOG_MAX_INTERVAL)
                                543                 :              0 :                 retries_before_log *= 2;
                                544                 :                :             else
                                545                 :              0 :                 retries_before_log += GETNEWOID_LOG_MAX_INTERVAL;
                                546                 :                :         }
                                547                 :                : 
 1949 fujii@postgresql.org      548                 :CBC      562099 :         retries++;
 7652 tgl@sss.pgh.pa.us         549         [ -  + ]:         562099 :     } while (collides);
                                550                 :                : 
                                551                 :                :     /*
                                552                 :                :      * If at least one log message is emitted, also log the completion of OID
                                553                 :                :      * assignment.
                                554                 :                :      */
 1949 fujii@postgresql.org      555         [ -  + ]:         562099 :     if (retries > GETNEWOID_LOG_THRESHOLD)
                                556                 :                :     {
 1949 fujii@postgresql.org      557         [ #  # ]:UBC           0 :         ereport(LOG,
                                558                 :                :                 (errmsg_plural("new OID has been assigned in relation \"%s\" after %" PRIu64 " retry",
                                559                 :                :                                "new OID has been assigned in relation \"%s\" after %" PRIu64 " retries",
                                560                 :                :                                retries,
                                561                 :                :                                RelationGetRelationName(relation), retries)));
                                562                 :                :     }
                                563                 :                : 
 7652 tgl@sss.pgh.pa.us         564                 :CBC      562099 :     return newOid;
                                565                 :                : }
                                566                 :                : 
                                567                 :                : /*
                                568                 :                :  * GetNewRelFileNumber
                                569                 :                :  *      Generate a new relfilenumber that is unique within the
                                570                 :                :  *      database of the given tablespace.
                                571                 :                :  *
                                572                 :                :  * If the relfilenumber will also be used as the relation's OID, pass the
                                573                 :                :  * opened pg_class catalog, and this routine will guarantee that the result
                                574                 :                :  * is also an unused OID within pg_class.  If the result is to be used only
                                575                 :                :  * as a relfilenumber for an existing relation, pass NULL for pg_class.
                                576                 :                :  *
                                577                 :                :  * As with GetNewOidWithIndex(), there is some theoretical risk of a race
                                578                 :                :  * condition, but it doesn't seem worth worrying about.
                                579                 :                :  *
                                580                 :                :  * Note: we don't support using this in bootstrap mode.  All relations
                                581                 :                :  * created by bootstrap have preassigned OIDs, so there's no need.
                                582                 :                :  */
                                583                 :                : RelFileNumber
 1396 rhaas@postgresql.org      584                 :          81419 : GetNewRelFileNumber(Oid reltablespace, Relation pg_class, char relpersistence)
                                585                 :                : {
                                586                 :                :     RelFileLocatorBackend rlocator;
                                587                 :                :     RelPathStr  rpath;
                                588                 :                :     bool        collides;
                                589                 :                :     ProcNumber  procNumber;
                                590                 :                : 
                                591                 :                :     /*
                                592                 :                :      * If we ever get here during pg_upgrade, there's something wrong; all
                                593                 :                :      * relfilenumber assignments during a binary-upgrade run should be
                                594                 :                :      * determined by commands in the dump script.
                                595                 :                :      */
                                596         [ -  + ]:          81419 :     Assert(!IsBinaryUpgrade);
                                597                 :                : 
                                598      [ +  +  - ]:          81419 :     switch (relpersistence)
                                599                 :                :     {
                                600                 :           4888 :         case RELPERSISTENCE_TEMP:
  874 heikki.linnakangas@i      601         [ +  - ]:           4888 :             procNumber = ProcNumberForTempRelations();
 1396 rhaas@postgresql.org      602                 :           4888 :             break;
                                603                 :          76531 :         case RELPERSISTENCE_UNLOGGED:
                                604                 :                :         case RELPERSISTENCE_PERMANENT:
  874 heikki.linnakangas@i      605                 :          76531 :             procNumber = INVALID_PROC_NUMBER;
 1396 rhaas@postgresql.org      606                 :          76531 :             break;
 1396 rhaas@postgresql.org      607                 :UBC           0 :         default:
                                608         [ #  # ]:              0 :             elog(ERROR, "invalid relpersistence: %c", relpersistence);
                                609                 :                :             return InvalidRelFileNumber;    /* placate compiler */
                                610                 :                :     }
                                611                 :                : 
                                612                 :                :     /* This logic should match RelationInitPhysicalAddr */
 1396 rhaas@postgresql.org      613         [ +  + ]:CBC       81419 :     rlocator.locator.spcOid = reltablespace ? reltablespace : MyDatabaseTableSpace;
                                614                 :          81419 :     rlocator.locator.dbOid =
                                615                 :          81419 :         (rlocator.locator.spcOid == GLOBALTABLESPACE_OID) ?
                                616         [ +  + ]:          81419 :         InvalidOid : MyDatabaseId;
                                617                 :                : 
                                618                 :                :     /*
                                619                 :                :      * The relpath will vary based on the backend number, so we must
                                620                 :                :      * initialize that properly here to make sure that any collisions based on
                                621                 :                :      * filename are properly detected.
                                622                 :                :      */
  874 heikki.linnakangas@i      623                 :          81419 :     rlocator.backend = procNumber;
                                624                 :                : 
                                625                 :                :     do
                                626                 :                :     {
 1396 rhaas@postgresql.org      627         [ +  + ]:          81419 :         CHECK_FOR_INTERRUPTS();
                                628                 :                : 
                                629                 :                :         /* Generate the OID */
                                630         [ +  + ]:          81419 :         if (pg_class)
                                631                 :          73055 :             rlocator.locator.relNumber = GetNewOidWithIndex(pg_class, ClassOidIndexId,
                                632                 :                :                                                             Anum_pg_class_oid);
                                633                 :                :         else
                                634                 :           8364 :             rlocator.locator.relNumber = GetNewObjectId();
                                635                 :                : 
                                636                 :                :         /* Check for existing file of same name */
                                637                 :          81419 :         rpath = relpath(rlocator, MAIN_FORKNUM);
                                638                 :                : 
  515 andres@anarazel.de        639         [ -  + ]:          81419 :         if (access(rpath.str, F_OK) == 0)
                                640                 :                :         {
                                641                 :                :             /* definite collision */
 1396 rhaas@postgresql.org      642                 :UBC           0 :             collides = true;
                                643                 :                :         }
                                644                 :                :         else
                                645                 :                :         {
                                646                 :                :             /*
                                647                 :                :              * Here we have a little bit of a dilemma: if errno is something
                                648                 :                :              * other than ENOENT, should we declare a collision and loop? In
                                649                 :                :              * practice it seems best to go ahead regardless of the errno.  If
                                650                 :                :              * there is a colliding file we will get an smgr failure when we
                                651                 :                :              * attempt to create the new relation file.
                                652                 :                :              */
 1396 rhaas@postgresql.org      653                 :CBC       81419 :             collides = false;
                                654                 :                :         }
                                655         [ -  + ]:          81419 :     } while (collides);
                                656                 :                : 
                                657                 :          81419 :     return rlocator.locator.relNumber;
                                658                 :                : }
                                659                 :                : 
                                660                 :                : /*
                                661                 :                :  * SQL callable interface for GetNewOidWithIndex().  Outside of initdb's
                                662                 :                :  * direct insertions into catalog tables, and recovering from corruption, this
                                663                 :                :  * should rarely be needed.
                                664                 :                :  *
                                665                 :                :  * Function is intentionally not documented in the user facing docs.
                                666                 :                :  */
                                667                 :                : Datum
 2804 andres@anarazel.de        668                 :UBC           0 : pg_nextoid(PG_FUNCTION_ARGS)
                                669                 :                : {
 2621 tgl@sss.pgh.pa.us         670                 :              0 :     Oid         reloid = PG_GETARG_OID(0);
                                671                 :              0 :     Name        attname = PG_GETARG_NAME(1);
                                672                 :              0 :     Oid         idxoid = PG_GETARG_OID(2);
                                673                 :                :     Relation    rel;
                                674                 :                :     Relation    idx;
                                675                 :                :     HeapTuple   atttuple;
                                676                 :                :     Form_pg_attribute attform;
                                677                 :                :     AttrNumber  attno;
                                678                 :                :     Oid         newoid;
                                679                 :                : 
                                680                 :                :     /*
                                681                 :                :      * As this function is not intended to be used during normal running, and
                                682                 :                :      * only supports system catalogs (which require superuser permissions to
                                683                 :                :      * modify), just checking for superuser ought to not obstruct valid
                                684                 :                :      * usecases.
                                685                 :                :      */
 2804 andres@anarazel.de        686         [ #  # ]:              0 :     if (!superuser())
                                687         [ #  # ]:              0 :         ereport(ERROR,
                                688                 :                :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                689                 :                :                  errmsg("must be superuser to call %s()",
                                690                 :                :                         "pg_nextoid")));
                                691                 :                : 
 2742                           692                 :              0 :     rel = table_open(reloid, RowExclusiveLock);
 2804                           693                 :              0 :     idx = index_open(idxoid, RowExclusiveLock);
                                694                 :                : 
                                695         [ #  # ]:              0 :     if (!IsSystemRelation(rel))
                                696         [ #  # ]:              0 :         ereport(ERROR,
                                697                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                698                 :                :                  errmsg("pg_nextoid() can only be used on system catalogs")));
                                699                 :                : 
                                700         [ #  # ]:              0 :     if (idx->rd_index->indrelid != RelationGetRelid(rel))
                                701         [ #  # ]:              0 :         ereport(ERROR,
                                702                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                703                 :                :                  errmsg("index \"%s\" does not belong to table \"%s\"",
                                704                 :                :                         RelationGetRelationName(idx),
                                705                 :                :                         RelationGetRelationName(rel))));
                                706                 :                : 
                                707                 :              0 :     atttuple = SearchSysCacheAttName(reloid, NameStr(*attname));
                                708         [ #  # ]:              0 :     if (!HeapTupleIsValid(atttuple))
                                709         [ #  # ]:              0 :         ereport(ERROR,
                                710                 :                :                 (errcode(ERRCODE_UNDEFINED_COLUMN),
                                711                 :                :                  errmsg("column \"%s\" of relation \"%s\" does not exist",
                                712                 :                :                         NameStr(*attname), RelationGetRelationName(rel))));
                                713                 :                : 
                                714                 :              0 :     attform = ((Form_pg_attribute) GETSTRUCT(atttuple));
                                715                 :              0 :     attno = attform->attnum;
                                716                 :                : 
                                717         [ #  # ]:              0 :     if (attform->atttypid != OIDOID)
                                718         [ #  # ]:              0 :         ereport(ERROR,
                                719                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                720                 :                :                  errmsg("column \"%s\" is not of type %s",
                                721                 :                :                         NameStr(*attname), "oid")));
                                722                 :                : 
                                723         [ #  # ]:              0 :     if (IndexRelationGetNumberOfKeyAttributes(idx) != 1 ||
                                724         [ #  # ]:              0 :         idx->rd_index->indkey.values[0] != attno)
                                725         [ #  # ]:              0 :         ereport(ERROR,
                                726                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                727                 :                :                  errmsg("index \"%s\" is not the index for column \"%s\"",
                                728                 :                :                         RelationGetRelationName(idx),
                                729                 :                :                         NameStr(*attname))));
                                730                 :                : 
                                731                 :              0 :     newoid = GetNewOidWithIndex(rel, idxoid, attno);
                                732                 :                : 
                                733                 :              0 :     ReleaseSysCache(atttuple);
 2742                           734                 :              0 :     table_close(rel, RowExclusiveLock);
 2804                           735                 :              0 :     index_close(idx, RowExclusiveLock);
                                736                 :                : 
 1836 tgl@sss.pgh.pa.us         737                 :              0 :     PG_RETURN_OID(newoid);
                                738                 :                : }
                                739                 :                : 
                                740                 :                : /*
                                741                 :                :  * SQL callable interface for StopGeneratingPinnedObjectIds().
                                742                 :                :  *
                                743                 :                :  * This is only to be used by initdb, so it's intentionally not documented in
                                744                 :                :  * the user facing docs.
                                745                 :                :  */
                                746                 :                : Datum
 1836 tgl@sss.pgh.pa.us         747                 :CBC          54 : pg_stop_making_pinned_objects(PG_FUNCTION_ARGS)
                                748                 :                : {
                                749                 :                :     /*
                                750                 :                :      * Belt-and-suspenders check, since StopGeneratingPinnedObjectIds will
                                751                 :                :      * fail anyway in non-single-user mode.
                                752                 :                :      */
                                753         [ -  + ]:             54 :     if (!superuser())
 1836 tgl@sss.pgh.pa.us         754         [ #  # ]:UBC           0 :         ereport(ERROR,
                                755                 :                :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                756                 :                :                  errmsg("must be superuser to call %s()",
                                757                 :                :                         "pg_stop_making_pinned_objects")));
                                758                 :                : 
 1836 tgl@sss.pgh.pa.us         759                 :CBC          54 :     StopGeneratingPinnedObjectIds();
                                760                 :                : 
                                761                 :             54 :     PG_RETURN_VOID();
                                762                 :                : }
        

Generated by: LCOV version 2.0-1