LCOV - differential code coverage report
Current view: top level - src/backend/catalog - catalog.c (source / functions) Coverage Total Hit UNC UBC GNC CBC DCB
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 77.7 % 166 129 37 3 126 3
Current Date: 2024-04-14 14:21:10 Functions: 93.3 % 15 14 1 1 13
Baseline: 16@8cea358b128 Branches: 74.1 % 197 146 1 50 1 145
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed [..60] days: 100.0 % 3 3 3
(240..) days: 77.3 % 163 126 37 126
Function coverage date bins:
(240..) days: 93.3 % 15 14 1 1 13
Branch coverage date bins:
[..60] days: 50.0 % 2 1 1 1
(240..) days: 74.4 % 195 145 50 145

 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-2024, 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_shdepend.h"
                                 38                 :                : #include "catalog/pg_shdescription.h"
                                 39                 :                : #include "catalog/pg_shseclabel.h"
                                 40                 :                : #include "catalog/pg_subscription.h"
                                 41                 :                : #include "catalog/pg_tablespace.h"
                                 42                 :                : #include "catalog/pg_type.h"
                                 43                 :                : #include "miscadmin.h"
                                 44                 :                : #include "utils/fmgroids.h"
                                 45                 :                : #include "utils/fmgrprotos.h"
                                 46                 :                : #include "utils/rel.h"
                                 47                 :                : #include "utils/snapmgr.h"
                                 48                 :                : #include "utils/syscache.h"
                                 49                 :                : 
                                 50                 :                : /*
                                 51                 :                :  * Parameters to determine when to emit a log message in
                                 52                 :                :  * GetNewOidWithIndex()
                                 53                 :                :  */
                                 54                 :                : #define GETNEWOID_LOG_THRESHOLD 1000000
                                 55                 :                : #define GETNEWOID_LOG_MAX_INTERVAL 128000000
                                 56                 :                : 
                                 57                 :                : /*
                                 58                 :                :  * IsSystemRelation
                                 59                 :                :  *      True iff the relation is either a system catalog or a toast table.
                                 60                 :                :  *      See IsCatalogRelation for the exact definition of a system catalog.
                                 61                 :                :  *
                                 62                 :                :  *      We treat toast tables of user relations as "system relations" for
                                 63                 :                :  *      protection purposes, e.g. you can't change their schemas without
                                 64                 :                :  *      special permissions.  Therefore, most uses of this function are
                                 65                 :                :  *      checking whether allow_system_table_mods restrictions apply.
                                 66                 :                :  *      For other purposes, consider whether you shouldn't be using
                                 67                 :                :  *      IsCatalogRelation instead.
                                 68                 :                :  *
                                 69                 :                :  *      This function does not perform any catalog accesses.
                                 70                 :                :  *      Some callers rely on that!
                                 71                 :                :  */
                                 72                 :                : bool
 8038 tgl@sss.pgh.pa.us          73                 :CBC      579556 : IsSystemRelation(Relation relation)
                                 74                 :                : {
 3790 rhaas@postgresql.org       75                 :         579556 :     return IsSystemClass(RelationGetRelid(relation), relation->rd_rel);
                                 76                 :                : }
                                 77                 :                : 
                                 78                 :                : /*
                                 79                 :                :  * IsSystemClass
                                 80                 :                :  *      Like the above, but takes a Form_pg_class as argument.
                                 81                 :                :  *      Used when we do not want to open the relation and have to
                                 82                 :                :  *      search pg_class directly.
                                 83                 :                :  */
                                 84                 :                : bool
                                 85                 :        1031436 : IsSystemClass(Oid relid, Form_pg_class reltuple)
                                 86                 :                : {
                                 87                 :                :     /* IsCatalogRelationOid is a bit faster, so test that first */
 1803 tgl@sss.pgh.pa.us          88   [ +  +  +  + ]:        1031436 :     return (IsCatalogRelationOid(relid) || IsToastClass(reltuple));
                                 89                 :                : }
                                 90                 :                : 
                                 91                 :                : /*
                                 92                 :                :  * IsCatalogRelation
                                 93                 :                :  *      True iff the relation is a system catalog.
                                 94                 :                :  *
                                 95                 :                :  *      By a system catalog, we mean one that is created during the bootstrap
                                 96                 :                :  *      phase of initdb.  That includes not just the catalogs per se, but
                                 97                 :                :  *      also their indexes, and TOAST tables and indexes if any.
                                 98                 :                :  *
                                 99                 :                :  *      This function does not perform any catalog accesses.
                                100                 :                :  *      Some callers rely on that!
                                101                 :                :  */
                                102                 :                : bool
 3790 rhaas@postgresql.org      103                 :       26172455 : IsCatalogRelation(Relation relation)
                                104                 :                : {
 1803 tgl@sss.pgh.pa.us         105                 :       26172455 :     return IsCatalogRelationOid(RelationGetRelid(relation));
                                106                 :                : }
                                107                 :                : 
                                108                 :                : /*
                                109                 :                :  * IsCatalogRelationOid
                                110                 :                :  *      True iff the relation identified by this OID is a system catalog.
                                111                 :                :  *
                                112                 :                :  *      By a system catalog, we mean one that is created during the bootstrap
                                113                 :                :  *      phase of initdb.  That includes not just the catalogs per se, but
                                114                 :                :  *      also their indexes, and TOAST tables and indexes if any.
                                115                 :                :  *
                                116                 :                :  *      This function does not perform any catalog accesses.
                                117                 :                :  *      Some callers rely on that!
                                118                 :                :  */
                                119                 :                : bool
                                120                 :       27574261 : IsCatalogRelationOid(Oid relid)
                                121                 :                : {
                                122                 :                :     /*
                                123                 :                :      * We consider a relation to be a system catalog if it has a pinned OID.
                                124                 :                :      * This includes all the defined catalogs, their indexes, and their TOAST
                                125                 :                :      * tables and indexes.
                                126                 :                :      *
                                127                 :                :      * This rule excludes the relations in information_schema, which are not
                                128                 :                :      * integral to the system and can be treated the same as user relations.
                                129                 :                :      * (Since it's valid to drop and recreate information_schema, any rule
                                130                 :                :      * that did not act this way would be wrong.)
                                131                 :                :      *
                                132                 :                :      * This test is reliable since an OID wraparound will skip this range of
                                133                 :                :      * OIDs; see GetNewObjectId().
                                134                 :                :      */
 1004                           135                 :       27574261 :     return (relid < (Oid) FirstUnpinnedObjectId);
                                136                 :                : }
                                137                 :                : 
                                138                 :                : /*
                                139                 :                :  * IsToastRelation
                                140                 :                :  *      True iff relation is a TOAST support relation (or index).
                                141                 :                :  *
                                142                 :                :  *      Does not perform any catalog accesses.
                                143                 :                :  */
                                144                 :                : bool
 8038                           145                 :        2365666 : IsToastRelation(Relation relation)
                                146                 :                : {
                                147                 :                :     /*
                                148                 :                :      * What we actually check is whether the relation belongs to a pg_toast
                                149                 :                :      * namespace.  This should be equivalent because of restrictions that are
                                150                 :                :      * enforced elsewhere against creating user relations in, or moving
                                151                 :                :      * relations into/out of, a pg_toast namespace.  Notice also that this
                                152                 :                :      * will not say "true" for toast tables belonging to other sessions' temp
                                153                 :                :      * tables; we expect that other mechanisms will prevent access to those.
                                154                 :                :      */
                                155                 :        2365666 :     return IsToastNamespace(RelationGetNamespace(relation));
                                156                 :                : }
                                157                 :                : 
                                158                 :                : /*
                                159                 :                :  * IsToastClass
                                160                 :                :  *      Like the above, but takes a Form_pg_class as argument.
                                161                 :                :  *      Used when we do not want to open the relation and have to
                                162                 :                :  *      search pg_class directly.
                                163                 :                :  */
                                164                 :                : bool
                                165                 :         539319 : IsToastClass(Form_pg_class reltuple)
                                166                 :                : {
 7893 bruce@momjian.us          167                 :         539319 :     Oid         relnamespace = reltuple->relnamespace;
                                168                 :                : 
                                169                 :         539319 :     return IsToastNamespace(relnamespace);
                                170                 :                : }
                                171                 :                : 
                                172                 :                : /*
                                173                 :                :  * IsCatalogNamespace
                                174                 :                :  *      True iff namespace is pg_catalog.
                                175                 :                :  *
                                176                 :                :  *      Does not perform any catalog accesses.
                                177                 :                :  *
                                178                 :                :  * NOTE: the reason this isn't a macro is to avoid having to include
                                179                 :                :  * catalog/pg_namespace.h in a lot of places.
                                180                 :                :  */
                                181                 :                : bool
 1803 tgl@sss.pgh.pa.us         182                 :          92647 : IsCatalogNamespace(Oid namespaceId)
                                183                 :                : {
 8038                           184                 :          92647 :     return namespaceId == PG_CATALOG_NAMESPACE;
                                185                 :                : }
                                186                 :                : 
                                187                 :                : /*
                                188                 :                :  * IsToastNamespace
                                189                 :                :  *      True iff namespace is pg_toast or my temporary-toast-table namespace.
                                190                 :                :  *
                                191                 :                :  *      Does not perform any catalog accesses.
                                192                 :                :  *
                                193                 :                :  * Note: this will return false for temporary-toast-table namespaces belonging
                                194                 :                :  * to other backends.  Those are treated the same as other backends' regular
                                195                 :                :  * temp table namespaces, and access is prevented where appropriate.
                                196                 :                :  * If you need to check for those, you may be able to use isAnyTempNamespace,
                                197                 :                :  * but beware that that does involve a catalog access.
                                198                 :                :  */
                                199                 :                : bool
                                200                 :        2946111 : IsToastNamespace(Oid namespaceId)
                                201                 :                : {
 6108                           202   [ +  +  +  + ]:        5854166 :     return (namespaceId == PG_TOAST_NAMESPACE) ||
                                203                 :        2908055 :         isTempToastNamespace(namespaceId);
                                204                 :                : }
                                205                 :                : 
                                206                 :                : 
                                207                 :                : /*
                                208                 :                :  * IsReservedName
                                209                 :                :  *      True iff name starts with the pg_ prefix.
                                210                 :                :  *
                                211                 :                :  *      For some classes of objects, the prefix pg_ is reserved for
                                212                 :                :  *      system objects only.  As of 8.0, this was only true for
                                213                 :                :  *      schema and tablespace names.  With 9.6, this is also true
                                214                 :                :  *      for roles.
                                215                 :                :  */
                                216                 :                : bool
 8038                           217                 :           1595 : IsReservedName(const char *name)
                                218                 :                : {
                                219                 :                :     /* ugly coding for speed */
                                220                 :           1633 :     return (name[0] == 'p' &&
                                221   [ +  +  +  + ]:           1602 :             name[1] == 'g' &&
                                222         [ +  - ]:              7 :             name[2] == '_');
                                223                 :                : }
                                224                 :                : 
                                225                 :                : 
                                226                 :                : /*
                                227                 :                :  * IsSharedRelation
                                228                 :                :  *      Given the OID of a relation, determine whether it's supposed to be
                                229                 :                :  *      shared across an entire database cluster.
                                230                 :                :  *
                                231                 :                :  * In older releases, this had to be hard-wired so that we could compute the
                                232                 :                :  * locktag for a relation and lock it before examining its catalog entry.
                                233                 :                :  * Since we now have MVCC catalog access, the race conditions that made that
                                234                 :                :  * a hard requirement are gone, so we could look at relaxing this restriction.
                                235                 :                :  * However, if we scanned the pg_class entry to find relisshared, and only
                                236                 :                :  * then locked the relation, pg_class could get updated in the meantime,
                                237                 :                :  * forcing us to scan the relation again, which would definitely be complex
                                238                 :                :  * and might have undesirable performance consequences.  Fortunately, the set
                                239                 :                :  * of shared relations is fairly static, so a hand-maintained list of their
                                240                 :                :  * OIDs isn't completely impractical.
                                241                 :                :  */
                                242                 :                : bool
 6467                           243                 :       17443801 : IsSharedRelation(Oid relationId)
                                244                 :                : {
                                245                 :                :     /* These are the shared catalogs (look for BKI_SHARED_RELATION) */
                                246   [ +  +  +  + ]:       17443801 :     if (relationId == AuthIdRelationId ||
                                247         [ +  + ]:       17344419 :         relationId == AuthMemRelationId ||
                                248         [ +  + ]:       17275854 :         relationId == DatabaseRelationId ||
 3273 andres@anarazel.de        249         [ +  + ]:       17257413 :         relationId == DbRoleSettingRelationId ||
  739 tgl@sss.pgh.pa.us         250         [ +  + ]:       17247022 :         relationId == ParameterAclRelationId ||
 2642 peter_e@gmx.net           251         [ +  + ]:       17233660 :         relationId == ReplicationOriginRelationId ||
  739 tgl@sss.pgh.pa.us         252         [ +  + ]:       17020237 :         relationId == SharedDependRelationId ||
                                253         [ +  + ]:       17017812 :         relationId == SharedDescriptionRelationId ||
                                254         [ +  + ]:       17013001 :         relationId == SharedSecLabelRelationId ||
                                255         [ +  + ]:       16996494 :         relationId == SubscriptionRelationId ||
                                256                 :                :         relationId == TableSpaceRelationId)
 6467                           257                 :         466071 :         return true;
                                258                 :                :     /* These are their indexes */
  739                           259   [ +  +  +  + ]:       16977730 :     if (relationId == AuthIdOidIndexId ||
                                260         [ +  + ]:       16927901 :         relationId == AuthIdRolnameIndexId ||
 6467                           261         [ +  + ]:       16919818 :         relationId == AuthMemMemRoleIndexId ||
  739                           262         [ +  + ]:       16915620 :         relationId == AuthMemRoleMemIndexId ||
  605 rhaas@postgresql.org      263         [ +  + ]:       16913683 :         relationId == AuthMemOidIndexId ||
                                264         [ +  + ]:       16912274 :         relationId == AuthMemGrantorIndexId ||
 6467 tgl@sss.pgh.pa.us         265         [ +  + ]:       16895969 :         relationId == DatabaseNameIndexId ||
                                266         [ +  + ]:       16861650 :         relationId == DatabaseOidIndexId ||
 3273 andres@anarazel.de        267         [ +  + ]:       16805167 :         relationId == DbRoleSettingDatidRolidIndexId ||
  739 tgl@sss.pgh.pa.us         268         [ +  + ]:       16802555 :         relationId == ParameterAclOidIndexId ||
                                269         [ +  + ]:       16799978 :         relationId == ParameterAclParnameIndexId ||
 3273 andres@anarazel.de        270         [ +  + ]:       16796315 :         relationId == ReplicationOriginIdentIndex ||
 2642 peter_e@gmx.net           271         [ +  + ]:       16792713 :         relationId == ReplicationOriginNameIndex ||
  739 tgl@sss.pgh.pa.us         272         [ +  + ]:       16690511 :         relationId == SharedDependDependerIndexId ||
                                273         [ +  + ]:       16684994 :         relationId == SharedDependReferenceIndexId ||
                                274         [ +  + ]:       16683050 :         relationId == SharedDescriptionObjIndexId ||
                                275         [ +  + ]:       16678948 :         relationId == SharedSecLabelObjectIndexId ||
                                276         [ +  + ]:       16675368 :         relationId == SubscriptionNameIndexId ||
 2642 peter_e@gmx.net           277         [ +  + ]:       16671402 :         relationId == SubscriptionObjectIndexId ||
  739 tgl@sss.pgh.pa.us         278         [ +  + ]:       16669663 :         relationId == TablespaceNameIndexId ||
                                279                 :                :         relationId == TablespaceOidIndexId)
 6467                           280                 :         317372 :         return true;
                                281                 :                :     /* These are their toast tables and toast indexes */
 2095 michael@paquier.xyz       282   [ +  +  +  + ]:       16660358 :     if (relationId == PgAuthidToastTable ||
                                283         [ +  + ]:       16658391 :         relationId == PgAuthidToastIndex ||
                                284         [ +  + ]:       16657284 :         relationId == PgDatabaseToastTable ||
                                285         [ +  + ]:       16656396 :         relationId == PgDatabaseToastIndex ||
 5303 alvherre@alvh.no-ip.      286         [ +  + ]:       16655359 :         relationId == PgDbRoleSettingToastTable ||
 3312 bruce@momjian.us          287         [ +  + ]:       16654536 :         relationId == PgDbRoleSettingToastIndex ||
  739 tgl@sss.pgh.pa.us         288         [ +  + ]:       16653498 :         relationId == PgParameterAclToastTable ||
                                289         [ +  + ]:       16652674 :         relationId == PgParameterAclToastIndex ||
 2095 michael@paquier.xyz       290         [ +  + ]:       16651636 :         relationId == PgReplicationOriginToastTable ||
                                291         [ +  + ]:       16650812 :         relationId == PgReplicationOriginToastIndex ||
                                292         [ +  + ]:       16649744 :         relationId == PgShdescriptionToastTable ||
                                293         [ +  + ]:       16648892 :         relationId == PgShdescriptionToastIndex ||
 3312 bruce@momjian.us          294         [ +  + ]:       16647854 :         relationId == PgShseclabelToastTable ||
 2095 michael@paquier.xyz       295         [ +  + ]:       16647030 :         relationId == PgShseclabelToastIndex ||
                                296         [ +  + ]:       16645994 :         relationId == PgSubscriptionToastTable ||
                                297         [ +  + ]:       16645172 :         relationId == PgSubscriptionToastIndex ||
                                298         [ +  + ]:       16644110 :         relationId == PgTablespaceToastTable ||
                                299                 :                :         relationId == PgTablespaceToastIndex)
 6467 tgl@sss.pgh.pa.us         300                 :          17096 :         return true;
                                301                 :       16643262 :     return false;
                                302                 :                : }
                                303                 :                : 
                                304                 :                : /*
                                305                 :                :  * IsPinnedObject
                                306                 :                :  *      Given the class + OID identity of a database object, report whether
                                307                 :                :  *      it is "pinned", that is not droppable because the system requires it.
                                308                 :                :  *
                                309                 :                :  * We used to represent this explicitly in pg_depend, but that proved to be
                                310                 :                :  * an undesirable amount of overhead, so now we rely on an OID range test.
                                311                 :                :  */
                                312                 :                : bool
 1004                           313                 :        1119814 : IsPinnedObject(Oid classId, Oid objectId)
                                314                 :                : {
                                315                 :                :     /*
                                316                 :                :      * Objects with OIDs above FirstUnpinnedObjectId are never pinned.  Since
                                317                 :                :      * the OID generator skips this range when wrapping around, this check
                                318                 :                :      * guarantees that user-defined objects are never considered pinned.
                                319                 :                :      */
                                320         [ +  + ]:        1119814 :     if (objectId >= FirstUnpinnedObjectId)
                                321                 :         319566 :         return false;
                                322                 :                : 
                                323                 :                :     /*
                                324                 :                :      * Large objects are never pinned.  We need this special case because
                                325                 :                :      * their OIDs can be user-assigned.
                                326                 :                :      */
                                327         [ +  + ]:         800248 :     if (classId == LargeObjectRelationId)
                                328                 :             27 :         return false;
                                329                 :                : 
                                330                 :                :     /*
                                331                 :                :      * There are a few objects defined in the catalog .dat files that, as a
                                332                 :                :      * matter of policy, we prefer not to treat as pinned.  We used to handle
                                333                 :                :      * that by excluding them from pg_depend, but it's just as easy to
                                334                 :                :      * hard-wire their OIDs here.  (If the user does indeed drop and recreate
                                335                 :                :      * them, they'll have new but certainly-unpinned OIDs, so no problem.)
                                336                 :                :      *
                                337                 :                :      * Checking both classId and objectId is overkill, since OIDs below
                                338                 :                :      * FirstGenbkiObjectId should be globally unique, but do it anyway for
                                339                 :                :      * robustness.
                                340                 :                :      */
                                341                 :                : 
                                342                 :                :     /* the public namespace is not pinned */
                                343   [ +  +  +  + ]:         800221 :     if (classId == NamespaceRelationId &&
                                344                 :                :         objectId == PG_PUBLIC_NAMESPACE)
                                345                 :          26550 :         return false;
                                346                 :                : 
                                347                 :                :     /*
                                348                 :                :      * Databases are never pinned.  It might seem that it'd be prudent to pin
                                349                 :                :      * at least template0; but we do this intentionally so that template0 and
                                350                 :                :      * template1 can be rebuilt from each other, thus letting them serve as
                                351                 :                :      * mutual backups (as long as you've not modified template1, anyway).
                                352                 :                :      */
  724                           353         [ -  + ]:         773671 :     if (classId == DatabaseRelationId)
  724 tgl@sss.pgh.pa.us         354                 :UBC           0 :         return false;
                                355                 :                : 
                                356                 :                :     /*
                                357                 :                :      * All other initdb-created objects are pinned.  This is overkill (the
                                358                 :                :      * system doesn't really depend on having every last weird datatype, for
                                359                 :                :      * instance) but generating only the minimum required set of dependencies
                                360                 :                :      * seems hard, and enforcing an accurate list would be much more expensive
                                361                 :                :      * than the simple range test used here.
                                362                 :                :      */
 1004 tgl@sss.pgh.pa.us         363                 :CBC      773671 :     return true;
                                364                 :                : }
                                365                 :                : 
                                366                 :                : 
                                367                 :                : /*
                                368                 :                :  * GetNewOidWithIndex
                                369                 :                :  *      Generate a new OID that is unique within the system relation.
                                370                 :                :  *
                                371                 :                :  * Since the OID is not immediately inserted into the table, there is a
                                372                 :                :  * race condition here; but a problem could occur only if someone else
                                373                 :                :  * managed to cycle through 2^32 OIDs and generate the same OID before we
                                374                 :                :  * finish inserting our row.  This seems unlikely to be a problem.  Note
                                375                 :                :  * that if we had to *commit* the row to end the race condition, the risk
                                376                 :                :  * would be rather higher; therefore we use SnapshotAny in the test, so that
                                377                 :                :  * we will see uncommitted rows.  (We used to use SnapshotDirty, but that has
                                378                 :                :  * the disadvantage that it ignores recently-deleted rows, creating a risk
                                379                 :                :  * of transient conflicts for as long as our own MVCC snapshots think a
                                380                 :                :  * recently-deleted row is live.  The risk is far higher when selecting TOAST
                                381                 :                :  * OIDs, because SnapshotToast considers dead rows as active indefinitely.)
                                382                 :                :  *
                                383                 :                :  * Note that we are effectively assuming that the table has a relatively small
                                384                 :                :  * number of entries (much less than 2^32) and there aren't very long runs of
                                385                 :                :  * consecutive existing OIDs.  This is a mostly reasonable assumption for
                                386                 :                :  * system catalogs.
                                387                 :                :  *
                                388                 :                :  * Caller must have a suitable lock on the relation.
                                389                 :                :  */
                                390                 :                : Oid
 5846                           391                 :         466082 : GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
                                392                 :                : {
                                393                 :                :     Oid         newOid;
                                394                 :                :     SysScanDesc scan;
                                395                 :                :     ScanKeyData key;
                                396                 :                :     bool        collides;
 1117 fujii@postgresql.org      397                 :         466082 :     uint64      retries = 0;
                                398                 :         466082 :     uint64      retries_before_log = GETNEWOID_LOG_THRESHOLD;
                                399                 :                : 
                                400                 :                :     /* Only system relations are supported */
 1972 andres@anarazel.de        401         [ -  + ]:         466082 :     Assert(IsSystemRelation(relation));
                                402                 :                : 
                                403                 :                :     /* In bootstrap mode, we don't have any indexes to use */
                                404         [ +  + ]:         466082 :     if (IsBootstrapProcessingMode())
                                405                 :           4485 :         return GetNewObjectId();
                                406                 :                : 
                                407                 :                :     /*
                                408                 :                :      * We should never be asked to generate a new pg_type OID during
                                409                 :                :      * pg_upgrade; doing so would risk collisions with the OIDs it wants to
                                410                 :                :      * assign.  Hitting this assert means there's some path where we failed to
                                411                 :                :      * ensure that a type OID is determined by commands in the dump script.
                                412                 :                :      */
 2498 tgl@sss.pgh.pa.us         413   [ +  +  -  + ]:         461597 :     Assert(!IsBinaryUpgrade || RelationGetRelid(relation) != TypeRelationId);
                                414                 :                : 
                                415                 :                :     /* Generate new OIDs until we find one not in the table */
                                416                 :                :     do
                                417                 :                :     {
 5898                           418         [ -  + ]:         461597 :         CHECK_FOR_INTERRUPTS();
                                419                 :                : 
 6820                           420                 :         461597 :         newOid = GetNewObjectId();
                                421                 :                : 
                                422                 :         461597 :         ScanKeyInit(&key,
                                423                 :                :                     oidcolumn,
                                424                 :                :                     BTEqualStrategyNumber, F_OIDEQ,
                                425                 :                :                     ObjectIdGetDatum(newOid));
                                426                 :                : 
                                427                 :                :         /* see notes above about using SnapshotAny */
 5846                           428                 :         461597 :         scan = systable_beginscan(relation, indexId, true,
                                429                 :                :                                   SnapshotAny, 1, &key);
                                430                 :                : 
                                431                 :         461597 :         collides = HeapTupleIsValid(systable_getnext(scan));
                                432                 :                : 
                                433                 :         461597 :         systable_endscan(scan);
                                434                 :                : 
                                435                 :                :         /*
                                436                 :                :          * Log that we iterate more than GETNEWOID_LOG_THRESHOLD but have not
                                437                 :                :          * yet found OID unused in the relation. Then repeat logging with
                                438                 :                :          * exponentially increasing intervals until we iterate more than
                                439                 :                :          * GETNEWOID_LOG_MAX_INTERVAL. Finally repeat logging every
                                440                 :                :          * GETNEWOID_LOG_MAX_INTERVAL unless an unused OID is found. This
                                441                 :                :          * logic is necessary not to fill up the server log with the similar
                                442                 :                :          * messages.
                                443                 :                :          */
 1117 fujii@postgresql.org      444         [ -  + ]:         461597 :         if (retries >= retries_before_log)
                                445                 :                :         {
 1117 fujii@postgresql.org      446         [ #  # ]:UBC           0 :             ereport(LOG,
                                447                 :                :                     (errmsg("still searching for an unused OID in relation \"%s\"",
                                448                 :                :                             RelationGetRelationName(relation)),
                                449                 :                :                      errdetail_plural("OID candidates have been checked %llu time, but no unused OID has been found yet.",
                                450                 :                :                                       "OID candidates have been checked %llu times, but no unused OID has been found yet.",
                                451                 :                :                                       retries,
                                452                 :                :                                       (unsigned long long) retries)));
                                453                 :                : 
                                454                 :                :             /*
                                455                 :                :              * Double the number of retries to do before logging next until it
                                456                 :                :              * reaches GETNEWOID_LOG_MAX_INTERVAL.
                                457                 :                :              */
                                458         [ #  # ]:              0 :             if (retries_before_log * 2 <= GETNEWOID_LOG_MAX_INTERVAL)
                                459                 :              0 :                 retries_before_log *= 2;
                                460                 :                :             else
                                461                 :              0 :                 retries_before_log += GETNEWOID_LOG_MAX_INTERVAL;
                                462                 :                :         }
                                463                 :                : 
 1117 fujii@postgresql.org      464                 :CBC      461597 :         retries++;
 6820 tgl@sss.pgh.pa.us         465         [ -  + ]:         461597 :     } while (collides);
                                466                 :                : 
                                467                 :                :     /*
                                468                 :                :      * If at least one log message is emitted, also log the completion of OID
                                469                 :                :      * assignment.
                                470                 :                :      */
 1117 fujii@postgresql.org      471         [ -  + ]:         461597 :     if (retries > GETNEWOID_LOG_THRESHOLD)
                                472                 :                :     {
 1117 fujii@postgresql.org      473         [ #  # ]:UBC           0 :         ereport(LOG,
                                474                 :                :                 (errmsg_plural("new OID has been assigned in relation \"%s\" after %llu retry",
                                475                 :                :                                "new OID has been assigned in relation \"%s\" after %llu retries",
                                476                 :                :                                retries,
                                477                 :                :                                RelationGetRelationName(relation), (unsigned long long) retries)));
                                478                 :                :     }
                                479                 :                : 
 6820 tgl@sss.pgh.pa.us         480                 :CBC      461597 :     return newOid;
                                481                 :                : }
                                482                 :                : 
                                483                 :                : /*
                                484                 :                :  * GetNewRelFileNumber
                                485                 :                :  *      Generate a new relfilenumber that is unique within the
                                486                 :                :  *      database of the given tablespace.
                                487                 :                :  *
                                488                 :                :  * If the relfilenumber will also be used as the relation's OID, pass the
                                489                 :                :  * opened pg_class catalog, and this routine will guarantee that the result
                                490                 :                :  * is also an unused OID within pg_class.  If the result is to be used only
                                491                 :                :  * as a relfilenumber for an existing relation, pass NULL for pg_class.
                                492                 :                :  *
                                493                 :                :  * As with GetNewOidWithIndex(), there is some theoretical risk of a race
                                494                 :                :  * condition, but it doesn't seem worth worrying about.
                                495                 :                :  *
                                496                 :                :  * Note: we don't support using this in bootstrap mode.  All relations
                                497                 :                :  * created by bootstrap have preassigned OIDs, so there's no need.
                                498                 :                :  */
                                499                 :                : RelFileNumber
  564 rhaas@postgresql.org      500                 :          52880 : GetNewRelFileNumber(Oid reltablespace, Relation pg_class, char relpersistence)
                                501                 :                : {
                                502                 :                :     RelFileLocatorBackend rlocator;
                                503                 :                :     char       *rpath;
                                504                 :                :     bool        collides;
                                505                 :                :     ProcNumber  procNumber;
                                506                 :                : 
                                507                 :                :     /*
                                508                 :                :      * If we ever get here during pg_upgrade, there's something wrong; all
                                509                 :                :      * relfilenumber assignments during a binary-upgrade run should be
                                510                 :                :      * determined by commands in the dump script.
                                511                 :                :      */
                                512         [ -  + ]:          52880 :     Assert(!IsBinaryUpgrade);
                                513                 :                : 
                                514      [ +  +  - ]:          52880 :     switch (relpersistence)
                                515                 :                :     {
                                516                 :           3148 :         case RELPERSISTENCE_TEMP:
   42 heikki.linnakangas@i      517         [ +  - ]:GNC        3148 :             procNumber = ProcNumberForTempRelations();
  564 rhaas@postgresql.org      518                 :CBC        3148 :             break;
                                519                 :          49732 :         case RELPERSISTENCE_UNLOGGED:
                                520                 :                :         case RELPERSISTENCE_PERMANENT:
   42 heikki.linnakangas@i      521                 :GNC       49732 :             procNumber = INVALID_PROC_NUMBER;
  564 rhaas@postgresql.org      522                 :CBC       49732 :             break;
  564 rhaas@postgresql.org      523                 :UBC           0 :         default:
                                524         [ #  # ]:              0 :             elog(ERROR, "invalid relpersistence: %c", relpersistence);
                                525                 :                :             return InvalidRelFileNumber;    /* placate compiler */
                                526                 :                :     }
                                527                 :                : 
                                528                 :                :     /* This logic should match RelationInitPhysicalAddr */
  564 rhaas@postgresql.org      529         [ +  + ]:CBC       52880 :     rlocator.locator.spcOid = reltablespace ? reltablespace : MyDatabaseTableSpace;
                                530                 :          52880 :     rlocator.locator.dbOid =
                                531                 :          52880 :         (rlocator.locator.spcOid == GLOBALTABLESPACE_OID) ?
                                532         [ +  + ]:          52880 :         InvalidOid : MyDatabaseId;
                                533                 :                : 
                                534                 :                :     /*
                                535                 :                :      * The relpath will vary based on the backend number, so we must
                                536                 :                :      * initialize that properly here to make sure that any collisions based on
                                537                 :                :      * filename are properly detected.
                                538                 :                :      */
   42 heikki.linnakangas@i      539                 :GNC       52880 :     rlocator.backend = procNumber;
                                540                 :                : 
                                541                 :                :     do
                                542                 :                :     {
  564 rhaas@postgresql.org      543         [ -  + ]:CBC       52880 :         CHECK_FOR_INTERRUPTS();
                                544                 :                : 
                                545                 :                :         /* Generate the OID */
                                546         [ +  + ]:          52880 :         if (pg_class)
                                547                 :          47022 :             rlocator.locator.relNumber = GetNewOidWithIndex(pg_class, ClassOidIndexId,
                                548                 :                :                                                             Anum_pg_class_oid);
                                549                 :                :         else
                                550                 :           5858 :             rlocator.locator.relNumber = GetNewObjectId();
                                551                 :                : 
                                552                 :                :         /* Check for existing file of same name */
                                553                 :          52880 :         rpath = relpath(rlocator, MAIN_FORKNUM);
                                554                 :                : 
                                555         [ -  + ]:          52880 :         if (access(rpath, F_OK) == 0)
                                556                 :                :         {
                                557                 :                :             /* definite collision */
  564 rhaas@postgresql.org      558                 :UBC           0 :             collides = true;
                                559                 :                :         }
                                560                 :                :         else
                                561                 :                :         {
                                562                 :                :             /*
                                563                 :                :              * Here we have a little bit of a dilemma: if errno is something
                                564                 :                :              * other than ENOENT, should we declare a collision and loop? In
                                565                 :                :              * practice it seems best to go ahead regardless of the errno.  If
                                566                 :                :              * there is a colliding file we will get an smgr failure when we
                                567                 :                :              * attempt to create the new relation file.
                                568                 :                :              */
  564 rhaas@postgresql.org      569                 :CBC       52880 :             collides = false;
                                570                 :                :         }
                                571                 :                : 
                                572                 :          52880 :         pfree(rpath);
                                573         [ -  + ]:          52880 :     } while (collides);
                                574                 :                : 
                                575                 :          52880 :     return rlocator.locator.relNumber;
                                576                 :                : }
                                577                 :                : 
                                578                 :                : /*
                                579                 :                :  * SQL callable interface for GetNewOidWithIndex().  Outside of initdb's
                                580                 :                :  * direct insertions into catalog tables, and recovering from corruption, this
                                581                 :                :  * should rarely be needed.
                                582                 :                :  *
                                583                 :                :  * Function is intentionally not documented in the user facing docs.
                                584                 :                :  */
                                585                 :                : Datum
 1972 andres@anarazel.de        586                 :UBC           0 : pg_nextoid(PG_FUNCTION_ARGS)
                                587                 :                : {
 1789 tgl@sss.pgh.pa.us         588                 :              0 :     Oid         reloid = PG_GETARG_OID(0);
                                589                 :              0 :     Name        attname = PG_GETARG_NAME(1);
                                590                 :              0 :     Oid         idxoid = PG_GETARG_OID(2);
                                591                 :                :     Relation    rel;
                                592                 :                :     Relation    idx;
                                593                 :                :     HeapTuple   atttuple;
                                594                 :                :     Form_pg_attribute attform;
                                595                 :                :     AttrNumber  attno;
                                596                 :                :     Oid         newoid;
                                597                 :                : 
                                598                 :                :     /*
                                599                 :                :      * As this function is not intended to be used during normal running, and
                                600                 :                :      * only supports system catalogs (which require superuser permissions to
                                601                 :                :      * modify), just checking for superuser ought to not obstruct valid
                                602                 :                :      * usecases.
                                603                 :                :      */
 1972 andres@anarazel.de        604         [ #  # ]:              0 :     if (!superuser())
                                605         [ #  # ]:              0 :         ereport(ERROR,
                                606                 :                :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                607                 :                :                  errmsg("must be superuser to call %s()",
                                608                 :                :                         "pg_nextoid")));
                                609                 :                : 
 1910                           610                 :              0 :     rel = table_open(reloid, RowExclusiveLock);
 1972                           611                 :              0 :     idx = index_open(idxoid, RowExclusiveLock);
                                612                 :                : 
                                613         [ #  # ]:              0 :     if (!IsSystemRelation(rel))
                                614         [ #  # ]:              0 :         ereport(ERROR,
                                615                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                616                 :                :                  errmsg("pg_nextoid() can only be used on system catalogs")));
                                617                 :                : 
                                618         [ #  # ]:              0 :     if (idx->rd_index->indrelid != RelationGetRelid(rel))
                                619         [ #  # ]:              0 :         ereport(ERROR,
                                620                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                621                 :                :                  errmsg("index \"%s\" does not belong to table \"%s\"",
                                622                 :                :                         RelationGetRelationName(idx),
                                623                 :                :                         RelationGetRelationName(rel))));
                                624                 :                : 
                                625                 :              0 :     atttuple = SearchSysCacheAttName(reloid, NameStr(*attname));
                                626         [ #  # ]:              0 :     if (!HeapTupleIsValid(atttuple))
                                627         [ #  # ]:              0 :         ereport(ERROR,
                                628                 :                :                 (errcode(ERRCODE_UNDEFINED_COLUMN),
                                629                 :                :                  errmsg("column \"%s\" of relation \"%s\" does not exist",
                                630                 :                :                         NameStr(*attname), RelationGetRelationName(rel))));
                                631                 :                : 
                                632                 :              0 :     attform = ((Form_pg_attribute) GETSTRUCT(atttuple));
                                633                 :              0 :     attno = attform->attnum;
                                634                 :                : 
                                635         [ #  # ]:              0 :     if (attform->atttypid != OIDOID)
                                636         [ #  # ]:              0 :         ereport(ERROR,
                                637                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                638                 :                :                  errmsg("column \"%s\" is not of type oid",
                                639                 :                :                         NameStr(*attname))));
                                640                 :                : 
                                641         [ #  # ]:              0 :     if (IndexRelationGetNumberOfKeyAttributes(idx) != 1 ||
                                642         [ #  # ]:              0 :         idx->rd_index->indkey.values[0] != attno)
                                643         [ #  # ]:              0 :         ereport(ERROR,
                                644                 :                :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                645                 :                :                  errmsg("index \"%s\" is not the index for column \"%s\"",
                                646                 :                :                         RelationGetRelationName(idx),
                                647                 :                :                         NameStr(*attname))));
                                648                 :                : 
                                649                 :              0 :     newoid = GetNewOidWithIndex(rel, idxoid, attno);
                                650                 :                : 
                                651                 :              0 :     ReleaseSysCache(atttuple);
 1910                           652                 :              0 :     table_close(rel, RowExclusiveLock);
 1972                           653                 :              0 :     index_close(idx, RowExclusiveLock);
                                654                 :                : 
 1004 tgl@sss.pgh.pa.us         655                 :              0 :     PG_RETURN_OID(newoid);
                                656                 :                : }
                                657                 :                : 
                                658                 :                : /*
                                659                 :                :  * SQL callable interface for StopGeneratingPinnedObjectIds().
                                660                 :                :  *
                                661                 :                :  * This is only to be used by initdb, so it's intentionally not documented in
                                662                 :                :  * the user facing docs.
                                663                 :                :  */
                                664                 :                : Datum
 1004 tgl@sss.pgh.pa.us         665                 :CBC          37 : pg_stop_making_pinned_objects(PG_FUNCTION_ARGS)
                                666                 :                : {
                                667                 :                :     /*
                                668                 :                :      * Belt-and-suspenders check, since StopGeneratingPinnedObjectIds will
                                669                 :                :      * fail anyway in non-single-user mode.
                                670                 :                :      */
                                671         [ -  + ]:             37 :     if (!superuser())
 1004 tgl@sss.pgh.pa.us         672         [ #  # ]:UBC           0 :         ereport(ERROR,
                                673                 :                :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                674                 :                :                  errmsg("must be superuser to call %s()",
                                675                 :                :                         "pg_stop_making_pinned_objects")));
                                676                 :                : 
 1004 tgl@sss.pgh.pa.us         677                 :CBC          37 :     StopGeneratingPinnedObjectIds();
                                678                 :                : 
                                679                 :             37 :     PG_RETURN_VOID();
                                680                 :                : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622