PostgreSQL Source Code  git master
catalog.h File Reference
#include "catalog/pg_class.h"
#include "utils/relcache.h"
Include dependency graph for catalog.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

bool IsSystemRelation (Relation relation)
 
bool IsToastRelation (Relation relation)
 
bool IsCatalogRelation (Relation relation)
 
bool IsSystemClass (Oid relid, Form_pg_class reltuple)
 
bool IsToastClass (Form_pg_class reltuple)
 
bool IsCatalogRelationOid (Oid relid)
 
bool IsCatalogNamespace (Oid namespaceId)
 
bool IsToastNamespace (Oid namespaceId)
 
bool IsReservedName (const char *name)
 
bool IsSharedRelation (Oid relationId)
 
bool IsPinnedObject (Oid classId, Oid objectId)
 
Oid GetNewOidWithIndex (Relation relation, Oid indexId, AttrNumber oidcolumn)
 
Oid GetNewRelFileNode (Oid reltablespace, Relation pg_class, char relpersistence)
 

Function Documentation

◆ GetNewOidWithIndex()

Oid GetNewOidWithIndex ( Relation  relation,
Oid  indexId,
AttrNumber  oidcolumn 
)

Definition at line 381 of file catalog.c.

References Assert, BTEqualStrategyNumber, CHECK_FOR_INTERRUPTS, ereport, errdetail_plural(), errmsg(), errmsg_plural(), GetNewObjectId(), GETNEWOID_LOG_MAX_INTERVAL, GETNEWOID_LOG_THRESHOLD, HeapTupleIsValid, IsBinaryUpgrade, IsBootstrapProcessingMode, IsSystemRelation(), sort-test::key, LOG, ObjectIdGetDatum, RelationGetRelationName, RelationGetRelid, ScanKeyInit(), SnapshotAny, systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by AddEnumLabel(), AssignTypeArrayOid(), AssignTypeMultirangeArrayOid(), AssignTypeMultirangeOid(), CastCreate(), CollationCreate(), ConversionCreate(), CreateAccessMethod(), CreateConstraintEntry(), createdb(), CreateForeignDataWrapper(), CreateForeignServer(), CreateOpFamily(), CreatePolicy(), CreateProceduralLanguage(), CreatePublication(), CreateRole(), CreateStatistics(), CreateSubscription(), CreateTableSpace(), CreateTransform(), CreateTriggerFiringOn(), CreateUserMapping(), DefineOpClass(), DefineTSConfiguration(), DefineTSDictionary(), DefineTSParser(), DefineTSTemplate(), EnumValuesCreate(), GetNewRelFileNode(), insert_event_trigger_tuple(), InsertExtensionTuple(), InsertRule(), LargeObjectCreate(), NamespaceCreate(), OperatorCreate(), OperatorShellMake(), pg_nextoid(), ProcedureCreate(), publication_add_relation(), publication_add_schema(), SetDefaultACL(), StoreAttrDefault(), storeOperators(), storeProcedures(), toast_save_datum(), TypeCreate(), and TypeShellMake().

382 {
383  Oid newOid;
384  SysScanDesc scan;
386  bool collides;
387  uint64 retries = 0;
388  uint64 retries_before_log = GETNEWOID_LOG_THRESHOLD;
389 
390  /* Only system relations are supported */
391  Assert(IsSystemRelation(relation));
392 
393  /* In bootstrap mode, we don't have any indexes to use */
395  return GetNewObjectId();
396 
397  /*
398  * We should never be asked to generate a new pg_type OID during
399  * pg_upgrade; doing so would risk collisions with the OIDs it wants to
400  * assign. Hitting this assert means there's some path where we failed to
401  * ensure that a type OID is determined by commands in the dump script.
402  */
403  Assert(!IsBinaryUpgrade || RelationGetRelid(relation) != TypeRelationId);
404 
405  /* Generate new OIDs until we find one not in the table */
406  do
407  {
409 
410  newOid = GetNewObjectId();
411 
412  ScanKeyInit(&key,
413  oidcolumn,
414  BTEqualStrategyNumber, F_OIDEQ,
415  ObjectIdGetDatum(newOid));
416 
417  /* see notes above about using SnapshotAny */
418  scan = systable_beginscan(relation, indexId, true,
419  SnapshotAny, 1, &key);
420 
421  collides = HeapTupleIsValid(systable_getnext(scan));
422 
423  systable_endscan(scan);
424 
425  /*
426  * Log that we iterate more than GETNEWOID_LOG_THRESHOLD but have not
427  * yet found OID unused in the relation. Then repeat logging with
428  * exponentially increasing intervals until we iterate more than
429  * GETNEWOID_LOG_MAX_INTERVAL. Finally repeat logging every
430  * GETNEWOID_LOG_MAX_INTERVAL unless an unused OID is found. This
431  * logic is necessary not to fill up the server log with the similar
432  * messages.
433  */
434  if (retries >= retries_before_log)
435  {
436  ereport(LOG,
437  (errmsg("still searching for an unused OID in relation \"%s\"",
438  RelationGetRelationName(relation)),
439  errdetail_plural("OID candidates have been checked %llu time, but no unused OID has been found yet.",
440  "OID candidates have been checked %llu times, but no unused OID has been found yet.",
441  retries,
442  (unsigned long long) retries)));
443 
444  /*
445  * Double the number of retries to do before logging next until it
446  * reaches GETNEWOID_LOG_MAX_INTERVAL.
447  */
448  if (retries_before_log * 2 <= GETNEWOID_LOG_MAX_INTERVAL)
449  retries_before_log *= 2;
450  else
451  retries_before_log += GETNEWOID_LOG_MAX_INTERVAL;
452  }
453 
454  retries++;
455  } while (collides);
456 
457  /*
458  * If at least one log message is emitted, also log the completion of OID
459  * assignment.
460  */
461  if (retries > GETNEWOID_LOG_THRESHOLD)
462  {
463  ereport(LOG,
464  (errmsg_plural("new OID has been assigned in relation \"%s\" after %llu retry",
465  "new OID has been assigned in relation \"%s\" after %llu retries",
466  retries,
467  RelationGetRelationName(relation), (unsigned long long) retries)));
468  }
469 
470  return newOid;
471 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
bool IsSystemRelation(Relation relation)
Definition: catalog.c:74
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1019
#define LOG
Definition: elog.h:26
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
bool IsBinaryUpgrade
Definition: globals.c:113
Oid GetNewObjectId(void)
Definition: varsup.c:528
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define RelationGetRelationName(relation)
Definition: rel.h:511
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1134
#define SnapshotAny
Definition: snapmgr.h:67
#define GETNEWOID_LOG_THRESHOLD
Definition: catalog.c:55
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:406
int errmsg(const char *fmt,...)
Definition: elog.c:909
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:120
#define RelationGetRelid(relation)
Definition: rel.h:477
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define GETNEWOID_LOG_MAX_INTERVAL
Definition: catalog.c:56

◆ GetNewRelFileNode()

Oid GetNewRelFileNode ( Oid  reltablespace,
Relation  pg_class,
char  relpersistence 
)

Definition at line 490 of file catalog.c.

References Assert, RelFileNodeBackend::backend, BackendIdForTempRelations, CHECK_FOR_INTERRUPTS, RelFileNode::dbNode, elog, ERROR, GetNewObjectId(), GetNewOidWithIndex(), InvalidBackendId, InvalidOid, IsBinaryUpgrade, MAIN_FORKNUM, MyDatabaseId, MyDatabaseTableSpace, RelFileNodeBackend::node, pfree(), RelFileNode::relNode, relpath, and RelFileNode::spcNode.

Referenced by ATExecSetTableSpace(), heap_create_with_catalog(), index_create(), and RelationSetNewRelfilenode().

491 {
492  RelFileNodeBackend rnode;
493  char *rpath;
494  bool collides;
495  BackendId backend;
496 
497  /*
498  * If we ever get here during pg_upgrade, there's something wrong; all
499  * relfilenode assignments during a binary-upgrade run should be
500  * determined by commands in the dump script.
501  */
503 
504  switch (relpersistence)
505  {
506  case RELPERSISTENCE_TEMP:
507  backend = BackendIdForTempRelations();
508  break;
509  case RELPERSISTENCE_UNLOGGED:
510  case RELPERSISTENCE_PERMANENT:
511  backend = InvalidBackendId;
512  break;
513  default:
514  elog(ERROR, "invalid relpersistence: %c", relpersistence);
515  return InvalidOid; /* placate compiler */
516  }
517 
518  /* This logic should match RelationInitPhysicalAddr */
519  rnode.node.spcNode = reltablespace ? reltablespace : MyDatabaseTableSpace;
520  rnode.node.dbNode = (rnode.node.spcNode == GLOBALTABLESPACE_OID) ? InvalidOid : MyDatabaseId;
521 
522  /*
523  * The relpath will vary based on the backend ID, so we must initialize
524  * that properly here to make sure that any collisions based on filename
525  * are properly detected.
526  */
527  rnode.backend = backend;
528 
529  do
530  {
532 
533  /* Generate the OID */
534  if (pg_class)
535  rnode.node.relNode = GetNewOidWithIndex(pg_class, ClassOidIndexId,
536  Anum_pg_class_oid);
537  else
538  rnode.node.relNode = GetNewObjectId();
539 
540  /* Check for existing file of same name */
541  rpath = relpath(rnode, MAIN_FORKNUM);
542 
543  if (access(rpath, F_OK) == 0)
544  {
545  /* definite collision */
546  collides = true;
547  }
548  else
549  {
550  /*
551  * Here we have a little bit of a dilemma: if errno is something
552  * other than ENOENT, should we declare a collision and loop? In
553  * practice it seems best to go ahead regardless of the errno. If
554  * there is a colliding file we will get an smgr failure when we
555  * attempt to create the new relation file.
556  */
557  collides = false;
558  }
559 
560  pfree(rpath);
561  } while (collides);
562 
563  return rnode.node.relNode;
564 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:381
bool IsBinaryUpgrade
Definition: globals.c:113
Oid MyDatabaseTableSpace
Definition: globals.c:90
Oid GetNewObjectId(void)
Definition: varsup.c:528
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ERROR
Definition: elog.h:46
#define BackendIdForTempRelations()
Definition: backendid.h:34
#define InvalidBackendId
Definition: backendid.h:23
int BackendId
Definition: backendid.h:21
Oid MyDatabaseId
Definition: globals.c:88
#define InvalidOid
Definition: postgres_ext.h:36
RelFileNode node
Definition: relfilenode.h:74
#define Assert(condition)
Definition: c.h:804
BackendId backend
Definition: relfilenode.h:75
#define elog(elevel,...)
Definition: elog.h:232
#define relpath(rnode, forknum)
Definition: relpath.h:87
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:120

◆ IsCatalogNamespace()

bool IsCatalogNamespace ( Oid  namespaceId)

Definition at line 183 of file catalog.c.

Referenced by AlterTableMoveAll(), check_publication_add_schema(), heap_create(), and RelationBuildLocalRelation().

184 {
185  return namespaceId == PG_CATALOG_NAMESPACE;
186 }

◆ IsCatalogRelation()

bool IsCatalogRelation ( Relation  relation)

◆ IsCatalogRelationOid()

bool IsCatalogRelationOid ( Oid  relid)

Definition at line 121 of file catalog.c.

References FirstUnpinnedObjectId.

Referenced by check_relation_privileges(), is_publishable_class(), IsCatalogRelation(), IsSystemClass(), ReindexMultipleTables(), and ReindexRelationConcurrently().

122 {
123  /*
124  * We consider a relation to be a system catalog if it has a pinned OID.
125  * This includes all the defined catalogs, their indexes, and their TOAST
126  * tables and indexes.
127  *
128  * This rule excludes the relations in information_schema, which are not
129  * integral to the system and can be treated the same as user relations.
130  * (Since it's valid to drop and recreate information_schema, any rule
131  * that did not act this way would be wrong.)
132  *
133  * This test is reliable since an OID wraparound will skip this range of
134  * OIDs; see GetNewObjectId().
135  */
136  return (relid < (Oid) FirstUnpinnedObjectId);
137 }
unsigned int Oid
Definition: postgres_ext.h:31
#define FirstUnpinnedObjectId
Definition: transam.h:196

◆ IsPinnedObject()

bool IsPinnedObject ( Oid  classId,
Oid  objectId 
)

Definition at line 307 of file catalog.c.

References FirstUnpinnedObjectId.

Referenced by checkSharedDependencies(), DropTableSpace(), findDependentObjects(), isObjectPinned(), recordSharedDependencyOn(), shdepChangeDep(), shdepDropOwned(), shdepReassignOwned(), and updateAclDependencies().

308 {
309  /*
310  * Objects with OIDs above FirstUnpinnedObjectId are never pinned. Since
311  * the OID generator skips this range when wrapping around, this check
312  * guarantees that user-defined objects are never considered pinned.
313  */
314  if (objectId >= FirstUnpinnedObjectId)
315  return false;
316 
317  /*
318  * Large objects are never pinned. We need this special case because
319  * their OIDs can be user-assigned.
320  */
321  if (classId == LargeObjectRelationId)
322  return false;
323 
324  /*
325  * There are a few objects defined in the catalog .dat files that, as a
326  * matter of policy, we prefer not to treat as pinned. We used to handle
327  * that by excluding them from pg_depend, but it's just as easy to
328  * hard-wire their OIDs here. (If the user does indeed drop and recreate
329  * them, they'll have new but certainly-unpinned OIDs, so no problem.)
330  *
331  * Checking both classId and objectId is overkill, since OIDs below
332  * FirstGenbkiObjectId should be globally unique, but do it anyway for
333  * robustness.
334  */
335 
336  /* template1 is not pinned */
337  if (classId == DatabaseRelationId &&
338  objectId == TemplateDbOid)
339  return false;
340 
341  /* the public namespace is not pinned */
342  if (classId == NamespaceRelationId &&
343  objectId == PG_PUBLIC_NAMESPACE)
344  return false;
345 
346  /*
347  * All other initdb-created objects are pinned. This is overkill (the
348  * system doesn't really depend on having every last weird datatype, for
349  * instance) but generating only the minimum required set of dependencies
350  * seems hard, and enforcing an accurate list would be much more expensive
351  * than the simple range test used here.
352  */
353  return true;
354 }
#define FirstUnpinnedObjectId
Definition: transam.h:196

◆ IsReservedName()

bool IsReservedName ( const char *  name)

Definition at line 218 of file catalog.c.

Referenced by check_rolespec_name(), CreateRole(), CreateSchemaCommand(), CreateTableSpace(), pg_replication_origin_create(), RenameRole(), RenameSchema(), and RenameTableSpace().

219 {
220  /* ugly coding for speed */
221  return (name[0] == 'p' &&
222  name[1] == 'g' &&
223  name[2] == '_');
224 }
const char * name
Definition: encode.c:561

◆ IsSharedRelation()

bool IsSharedRelation ( Oid  relationId)

Definition at line 244 of file catalog.c.

References PgAuthidToastIndex, PgAuthidToastTable, PgDatabaseToastIndex, PgDatabaseToastTable, PgDbRoleSettingToastIndex, PgDbRoleSettingToastTable, PgReplicationOriginToastIndex, PgReplicationOriginToastTable, PgShdescriptionToastIndex, PgShdescriptionToastTable, PgShseclabelToastIndex, PgShseclabelToastTable, PgSubscriptionToastIndex, PgSubscriptionToastTable, PgTablespaceToastIndex, and PgTablespaceToastTable.

Referenced by CacheInvalidateCatalog(), CacheInvalidateHeapTuple(), classIdGetDbId(), DeleteSecurityLabel(), get_object_address(), GetSecurityLabel(), pgstat_recv_resetsinglecounter(), RelationBuildLocalRelation(), SetLocktagRelationOid(), SetSecurityLabel(), and UpdateLogicalMappings().

245 {
246  /* These are the shared catalogs (look for BKI_SHARED_RELATION) */
247  if (relationId == AuthIdRelationId ||
248  relationId == AuthMemRelationId ||
249  relationId == DatabaseRelationId ||
250  relationId == SharedDescriptionRelationId ||
251  relationId == SharedDependRelationId ||
252  relationId == SharedSecLabelRelationId ||
253  relationId == TableSpaceRelationId ||
254  relationId == DbRoleSettingRelationId ||
255  relationId == ReplicationOriginRelationId ||
256  relationId == SubscriptionRelationId)
257  return true;
258  /* These are their indexes */
259  if (relationId == AuthIdRolnameIndexId ||
260  relationId == AuthIdOidIndexId ||
261  relationId == AuthMemRoleMemIndexId ||
262  relationId == AuthMemMemRoleIndexId ||
263  relationId == DatabaseNameIndexId ||
264  relationId == DatabaseOidIndexId ||
265  relationId == SharedDescriptionObjIndexId ||
266  relationId == SharedDependDependerIndexId ||
267  relationId == SharedDependReferenceIndexId ||
268  relationId == SharedSecLabelObjectIndexId ||
269  relationId == TablespaceOidIndexId ||
270  relationId == TablespaceNameIndexId ||
271  relationId == DbRoleSettingDatidRolidIndexId ||
272  relationId == ReplicationOriginIdentIndex ||
273  relationId == ReplicationOriginNameIndex ||
274  relationId == SubscriptionObjectIndexId ||
275  relationId == SubscriptionNameIndexId)
276  return true;
277  /* These are their toast tables and toast indexes */
278  if (relationId == PgAuthidToastTable ||
279  relationId == PgAuthidToastIndex ||
280  relationId == PgDatabaseToastTable ||
281  relationId == PgDatabaseToastIndex ||
282  relationId == PgDbRoleSettingToastTable ||
283  relationId == PgDbRoleSettingToastIndex ||
284  relationId == PgReplicationOriginToastTable ||
285  relationId == PgReplicationOriginToastIndex ||
286  relationId == PgShdescriptionToastTable ||
287  relationId == PgShdescriptionToastIndex ||
288  relationId == PgShseclabelToastTable ||
289  relationId == PgShseclabelToastIndex ||
290  relationId == PgSubscriptionToastTable ||
291  relationId == PgSubscriptionToastIndex ||
292  relationId == PgTablespaceToastTable ||
293  relationId == PgTablespaceToastIndex)
294  return true;
295  return false;
296 }
#define PgDatabaseToastTable
Definition: pg_database.h:84
#define PgSubscriptionToastIndex
#define PgShseclabelToastTable
Definition: pg_shseclabel.h:43
#define PgAuthidToastIndex
Definition: pg_authid.h:60
#define PgShseclabelToastIndex
Definition: pg_shseclabel.h:44
#define PgDatabaseToastIndex
Definition: pg_database.h:85
#define PgReplicationOriginToastIndex
#define PgShdescriptionToastTable
#define PgAuthidToastTable
Definition: pg_authid.h:59
#define PgDbRoleSettingToastTable
#define PgSubscriptionToastTable
#define PgReplicationOriginToastTable
#define PgTablespaceToastTable
Definition: pg_tablespace.h:51
#define PgTablespaceToastIndex
Definition: pg_tablespace.h:52
#define PgShdescriptionToastIndex
#define PgDbRoleSettingToastIndex

◆ IsSystemClass()

bool IsSystemClass ( Oid  relid,
Form_pg_class  reltuple 
)

Definition at line 86 of file catalog.c.

References IsCatalogRelationOid(), and IsToastClass().

Referenced by IsSystemRelation(), pg_class_aclmask_ext(), RangeVarCallbackForAlterRelation(), RangeVarCallbackForDropRelation(), RangeVarCallbackForPolicy(), RangeVarCallbackForRenameRule(), RangeVarCallbackForRenameTrigger(), RangeVarCallbackOwnsRelation(), ReindexMultipleTables(), renameatt_check(), swap_relation_files(), and truncate_check_rel().

87 {
88  /* IsCatalogRelationOid is a bit faster, so test that first */
89  return (IsCatalogRelationOid(relid) || IsToastClass(reltuple));
90 }
bool IsCatalogRelationOid(Oid relid)
Definition: catalog.c:121
bool IsToastClass(Form_pg_class reltuple)
Definition: catalog.c:166

◆ IsSystemRelation()

◆ IsToastClass()

bool IsToastClass ( Form_pg_class  reltuple)

Definition at line 166 of file catalog.c.

References IsToastNamespace().

Referenced by IsSystemClass().

167 {
168  Oid relnamespace = reltuple->relnamespace;
169 
170  return IsToastNamespace(relnamespace);
171 }
bool IsToastNamespace(Oid namespaceId)
Definition: catalog.c:201
unsigned int Oid
Definition: postgres_ext.h:31

◆ IsToastNamespace()

bool IsToastNamespace ( Oid  namespaceId)

Definition at line 201 of file catalog.c.

References isTempToastNamespace().

Referenced by AlterTableMoveAll(), check_publication_add_schema(), heap_create(), IsToastClass(), IsToastRelation(), reindex_index(), reindex_relation(), and ReindexRelationConcurrently().

202 {
203  return (namespaceId == PG_TOAST_NAMESPACE) ||
204  isTempToastNamespace(namespaceId);
205 }
bool isTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3214

◆ IsToastRelation()

bool IsToastRelation ( Relation  relation)

Definition at line 146 of file catalog.c.

References IsToastNamespace(), and RelationGetNamespace.

Referenced by CacheInvalidateHeapTuple(), heap_abort_speculative(), heap_insert(), ReorderBufferProcessTXN(), and ReorderBufferToastAppendChunk().

147 {
148  /*
149  * What we actually check is whether the relation belongs to a pg_toast
150  * namespace. This should be equivalent because of restrictions that are
151  * enforced elsewhere against creating user relations in, or moving
152  * relations into/out of, a pg_toast namespace. Notice also that this
153  * will not say "true" for toast tables belonging to other sessions' temp
154  * tables; we expect that other mechanisms will prevent access to those.
155  */
156  return IsToastNamespace(RelationGetNamespace(relation));
157 }
bool IsToastNamespace(Oid namespaceId)
Definition: catalog.c:201
#define RelationGetNamespace(relation)
Definition: rel.h:518