LCOV - differential code coverage report
Current view: top level - src/backend/catalog - catalog.c (source / functions) Coverage Total Hit LBC UIC UBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 77.7 % 166 129 4 26 7 36 12 81 29 41 1 3
Current Date: 2023-04-08 17:13:01 Functions: 93.3 % 15 14 1 3 2 9 1 3 1
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (180,240] days: 89.7 % 29 26 2 1 7 12 7 2 11
Legend: Lines: hit not hit (240..) days: 75.2 % 137 103 2 25 7 29 74 27 28
Function coverage date bins:
(180,240] days: 100.0 % 1 1 1
(240..) days: 72.2 % 18 13 1 3 1 9 1 3

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

Generated by: LCOV version v1.16-55-g56c0a2a