LCOV - differential code coverage report
Current view: top level - src/backend/catalog - catalog.c (source / functions) Coverage Total Hit LBC UBC CBC
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 78.2 % 170 133 37 133
Current Date: 2025-09-06 07:49:51 +0900 Functions: 94.4 % 18 17 1 17
Baseline: lcov-20250906-005545-baseline Branches: 74.4 % 195 145 1 49 145
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 100.0 % 7 7 7
(360..) days: 77.3 % 163 126 37 126
Function coverage date bins:
(30,360] days: 100.0 % 1 1 1
(360..) days: 94.1 % 17 16 1 16
Branch coverage date bins:
(30,360] days: 87.5 % 8 7 1 7
(360..) days: 73.8 % 187 138 1 48 138

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

Generated by: LCOV version 2.4-beta