PostgreSQL Source Code  git master
catalog.c File Reference
#include "postgres.h"
#include <fcntl.h>
#include <unistd.h>
#include "access/genam.h"
#include "access/htup_details.h"
#include "access/sysattr.h"
#include "access/table.h"
#include "access/transam.h"
#include "catalog/catalog.h"
#include "catalog/namespace.h"
#include "catalog/pg_auth_members.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_database.h"
#include "catalog/pg_db_role_setting.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_replication_origin.h"
#include "catalog/pg_shdepend.h"
#include "catalog/pg_shdescription.h"
#include "catalog/pg_shseclabel.h"
#include "catalog/pg_subscription.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_type.h"
#include "miscadmin.h"
#include "storage/fd.h"
#include "utils/fmgroids.h"
#include "utils/fmgrprotos.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
Include dependency graph for catalog.c:

Go to the source code of this file.

Macros

#define GETNEWOID_LOG_THRESHOLD   1000000
 
#define GETNEWOID_LOG_MAX_INTERVAL   128000000
 

Functions

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

Macro Definition Documentation

◆ GETNEWOID_LOG_MAX_INTERVAL

#define GETNEWOID_LOG_MAX_INTERVAL   128000000

Definition at line 55 of file catalog.c.

Referenced by GetNewOidWithIndex().

◆ GETNEWOID_LOG_THRESHOLD

#define GETNEWOID_LOG_THRESHOLD   1000000

Definition at line 54 of file catalog.c.

Referenced by GetNewOidWithIndex().

Function Documentation

◆ GetNewOidWithIndex()

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

Definition at line 322 of file catalog.c.

References Assert, BTEqualStrategyNumber, CHECK_FOR_INTERRUPTS, ereport, errdetail(), errmsg(), 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(), CreateTrigger(), CreateUserMapping(), DefineOpClass(), DefineTSConfiguration(), DefineTSDictionary(), DefineTSParser(), DefineTSTemplate(), EnumValuesCreate(), GetNewRelFileNode(), insert_event_trigger_tuple(), InsertExtensionTuple(), InsertRule(), LargeObjectCreate(), NamespaceCreate(), OperatorCreate(), OperatorShellMake(), pg_nextoid(), ProcedureCreate(), publication_add_relation(), SetDefaultACL(), StoreAttrDefault(), storeOperators(), storeProcedures(), toast_save_datum(), TypeCreate(), and TypeShellMake().

323 {
324  Oid newOid;
325  SysScanDesc scan;
327  bool collides;
328  uint64 retries = 0;
329  uint64 retries_before_log = GETNEWOID_LOG_THRESHOLD;
330 
331  /* Only system relations are supported */
332  Assert(IsSystemRelation(relation));
333 
334  /* In bootstrap mode, we don't have any indexes to use */
336  return GetNewObjectId();
337 
338  /*
339  * We should never be asked to generate a new pg_type OID during
340  * pg_upgrade; doing so would risk collisions with the OIDs it wants to
341  * assign. Hitting this assert means there's some path where we failed to
342  * ensure that a type OID is determined by commands in the dump script.
343  */
344  Assert(!IsBinaryUpgrade || RelationGetRelid(relation) != TypeRelationId);
345 
346  /* Generate new OIDs until we find one not in the table */
347  do
348  {
350 
351  newOid = GetNewObjectId();
352 
353  ScanKeyInit(&key,
354  oidcolumn,
355  BTEqualStrategyNumber, F_OIDEQ,
356  ObjectIdGetDatum(newOid));
357 
358  /* see notes above about using SnapshotAny */
359  scan = systable_beginscan(relation, indexId, true,
360  SnapshotAny, 1, &key);
361 
362  collides = HeapTupleIsValid(systable_getnext(scan));
363 
364  systable_endscan(scan);
365 
366  /*
367  * Log that we iterate more than GETNEWOID_LOG_THRESHOLD but have not
368  * yet found OID unused in the relation. Then repeat logging with
369  * exponentially increasing intervals until we iterate more than
370  * GETNEWOID_LOG_MAX_INTERVAL. Finally repeat logging every
371  * GETNEWOID_LOG_MAX_INTERVAL unless an unused OID is found. This
372  * logic is necessary not to fill up the server log with the similar
373  * messages.
374  */
375  if (retries >= retries_before_log)
376  {
377  ereport(LOG,
378  (errmsg("still finding an unused OID within relation \"%s\"",
379  RelationGetRelationName(relation)),
380  errdetail("OID candidates were checked \"%llu\" times, but no unused OID is yet found.",
381  (unsigned long long) retries)));
382 
383  /*
384  * Double the number of retries to do before logging next until it
385  * reaches GETNEWOID_LOG_MAX_INTERVAL.
386  */
387  if (retries_before_log * 2 <= GETNEWOID_LOG_MAX_INTERVAL)
388  retries_before_log *= 2;
389  else
390  retries_before_log += GETNEWOID_LOG_MAX_INTERVAL;
391  }
392 
393  retries++;
394  } while (collides);
395 
396  /*
397  * If at least one log message is emitted, also log the completion of OID
398  * assignment.
399  */
400  if (retries > GETNEWOID_LOG_THRESHOLD)
401  {
402  ereport(LOG,
403  (errmsg("new OID has been assigned in relation \"%s\" after \"%llu\" retries",
404  RelationGetRelationName(relation), (unsigned long long) retries)));
405  }
406 
407  return newOid;
408 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
bool IsSystemRelation(Relation relation)
Definition: catalog.c:73
#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
int errdetail(const char *fmt,...)
Definition: elog.c:1042
#define RelationGetRelationName(relation)
Definition: rel.h:491
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
#define SnapshotAny
Definition: snapmgr.h:67
#define GETNEWOID_LOG_THRESHOLD
Definition: catalog.c:54
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:394
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:102
#define RelationGetRelid(relation)
Definition: rel.h:457
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define GETNEWOID_LOG_MAX_INTERVAL
Definition: catalog.c:55

◆ GetNewRelFileNode()

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

Definition at line 427 of file catalog.c.

References Assert, RelFileNodeBackend::backend, BackendIdForTempRelations, CHECK_FOR_INTERRUPTS, ClassOidIndexId, 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().

428 {
429  RelFileNodeBackend rnode;
430  char *rpath;
431  bool collides;
432  BackendId backend;
433 
434  /*
435  * If we ever get here during pg_upgrade, there's something wrong; all
436  * relfilenode assignments during a binary-upgrade run should be
437  * determined by commands in the dump script.
438  */
440 
441  switch (relpersistence)
442  {
443  case RELPERSISTENCE_TEMP:
444  backend = BackendIdForTempRelations();
445  break;
446  case RELPERSISTENCE_UNLOGGED:
447  case RELPERSISTENCE_PERMANENT:
448  backend = InvalidBackendId;
449  break;
450  default:
451  elog(ERROR, "invalid relpersistence: %c", relpersistence);
452  return InvalidOid; /* placate compiler */
453  }
454 
455  /* This logic should match RelationInitPhysicalAddr */
456  rnode.node.spcNode = reltablespace ? reltablespace : MyDatabaseTableSpace;
457  rnode.node.dbNode = (rnode.node.spcNode == GLOBALTABLESPACE_OID) ? InvalidOid : MyDatabaseId;
458 
459  /*
460  * The relpath will vary based on the backend ID, so we must initialize
461  * that properly here to make sure that any collisions based on filename
462  * are properly detected.
463  */
464  rnode.backend = backend;
465 
466  do
467  {
469 
470  /* Generate the OID */
471  if (pg_class)
473  Anum_pg_class_oid);
474  else
475  rnode.node.relNode = GetNewObjectId();
476 
477  /* Check for existing file of same name */
478  rpath = relpath(rnode, MAIN_FORKNUM);
479 
480  if (access(rpath, F_OK) == 0)
481  {
482  /* definite collision */
483  collides = true;
484  }
485  else
486  {
487  /*
488  * Here we have a little bit of a dilemma: if errno is something
489  * other than ENOENT, should we declare a collision and loop? In
490  * practice it seems best to go ahead regardless of the errno. If
491  * there is a colliding file we will get an smgr failure when we
492  * attempt to create the new relation file.
493  */
494  collides = false;
495  }
496 
497  pfree(rpath);
498  } while (collides);
499 
500  return rnode.node.relNode;
501 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:322
#define ClassOidIndexId
Definition: pg_class.h:156
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:102

◆ IsCatalogNamespace()

bool IsCatalogNamespace ( Oid  namespaceId)

Definition at line 182 of file catalog.c.

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

183 {
184  return namespaceId == PG_CATALOG_NAMESPACE;
185 }

◆ IsCatalogRelation()

bool IsCatalogRelation ( Relation  relation)

◆ IsCatalogRelationOid()

bool IsCatalogRelationOid ( Oid  relid)

Definition at line 120 of file catalog.c.

References FirstBootstrapObjectId.

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

121 {
122  /*
123  * We consider a relation to be a system catalog if it has an OID that was
124  * manually assigned or assigned by genbki.pl. This includes all the
125  * defined catalogs, their indexes, and their TOAST 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  */
135  return (relid < (Oid) FirstBootstrapObjectId);
136 }
unsigned int Oid
Definition: postgres_ext.h:31
#define FirstBootstrapObjectId
Definition: transam.h:189

◆ IsReservedName()

bool IsReservedName ( const char *  name)

Definition at line 217 of file catalog.c.

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

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

◆ IsSharedRelation()

bool IsSharedRelation ( Oid  relationId)

Definition at line 243 of file catalog.c.

References AuthIdOidIndexId, AuthIdRolnameIndexId, AuthMemMemRoleIndexId, AuthMemRoleMemIndexId, DatabaseNameIndexId, DatabaseOidIndexId, DbRoleSettingDatidRolidIndexId, PgAuthidToastIndex, PgAuthidToastTable, PgDatabaseToastIndex, PgDatabaseToastTable, PgDbRoleSettingToastIndex, PgDbRoleSettingToastTable, PgReplicationOriginToastIndex, PgReplicationOriginToastTable, PgShdescriptionToastIndex, PgShdescriptionToastTable, PgShseclabelToastIndex, PgShseclabelToastTable, PgSubscriptionToastIndex, PgSubscriptionToastTable, PgTablespaceToastIndex, PgTablespaceToastTable, ReplicationOriginIdentIndex, ReplicationOriginNameIndex, SharedDependDependerIndexId, SharedDependReferenceIndexId, SharedDescriptionObjIndexId, SharedSecLabelObjectIndexId, SubscriptionNameIndexId, SubscriptionObjectIndexId, TablespaceNameIndexId, and TablespaceOidIndexId.

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

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

◆ IsSystemClass()

bool IsSystemClass ( Oid  relid,
Form_pg_class  reltuple 
)

Definition at line 85 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().

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

◆ IsSystemRelation()

◆ IsToastClass()

bool IsToastClass ( Form_pg_class  reltuple)

Definition at line 165 of file catalog.c.

References IsToastNamespace().

Referenced by IsSystemClass().

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

◆ IsToastNamespace()

bool IsToastNamespace ( Oid  namespaceId)

Definition at line 200 of file catalog.c.

References isTempToastNamespace().

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

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

◆ IsToastRelation()

bool IsToastRelation ( Relation  relation)

Definition at line 145 of file catalog.c.

References IsToastNamespace(), and RelationGetNamespace.

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

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  return IsToastNamespace(RelationGetNamespace(relation));
156 }
bool IsToastNamespace(Oid namespaceId)
Definition: catalog.c:200
#define RelationGetNamespace(relation)
Definition: rel.h:498

◆ pg_nextoid()

Datum pg_nextoid ( PG_FUNCTION_ARGS  )

Definition at line 511 of file catalog.c.

References attname, ereport, errcode(), errmsg(), ERROR, GetNewOidWithIndex(), GETSTRUCT, HeapTupleIsValid, idx(), index_close(), index_open(), IndexRelationGetNumberOfKeyAttributes, IsSystemRelation(), NameStr, PG_GETARG_NAME, PG_GETARG_OID, RelationData::rd_index, RelationGetRelationName, RelationGetRelid, ReleaseSysCache(), RowExclusiveLock, SearchSysCacheAttName(), superuser(), table_close(), and table_open().

512 {
513  Oid reloid = PG_GETARG_OID(0);
515  Oid idxoid = PG_GETARG_OID(2);
516  Relation rel;
517  Relation idx;
518  HeapTuple atttuple;
519  Form_pg_attribute attform;
520  AttrNumber attno;
521  Oid newoid;
522 
523  /*
524  * As this function is not intended to be used during normal running, and
525  * only supports system catalogs (which require superuser permissions to
526  * modify), just checking for superuser ought to not obstruct valid
527  * usecases.
528  */
529  if (!superuser())
530  ereport(ERROR,
531  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
532  errmsg("must be superuser to call pg_nextoid()")));
533 
534  rel = table_open(reloid, RowExclusiveLock);
535  idx = index_open(idxoid, RowExclusiveLock);
536 
537  if (!IsSystemRelation(rel))
538  ereport(ERROR,
539  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
540  errmsg("pg_nextoid() can only be used on system catalogs")));
541 
542  if (idx->rd_index->indrelid != RelationGetRelid(rel))
543  ereport(ERROR,
544  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
545  errmsg("index \"%s\" does not belong to table \"%s\"",
547  RelationGetRelationName(rel))));
548 
549  atttuple = SearchSysCacheAttName(reloid, NameStr(*attname));
550  if (!HeapTupleIsValid(atttuple))
551  ereport(ERROR,
552  (errcode(ERRCODE_UNDEFINED_COLUMN),
553  errmsg("column \"%s\" of relation \"%s\" does not exist",
554  NameStr(*attname), RelationGetRelationName(rel))));
555 
556  attform = ((Form_pg_attribute) GETSTRUCT(atttuple));
557  attno = attform->attnum;
558 
559  if (attform->atttypid != OIDOID)
560  ereport(ERROR,
561  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
562  errmsg("column \"%s\" is not of type oid",
563  NameStr(*attname))));
564 
566  idx->rd_index->indkey.values[0] != attno)
567  ereport(ERROR,
568  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
569  errmsg("index \"%s\" is not the index for column \"%s\"",
571  NameStr(*attname))));
572 
573  newoid = GetNewOidWithIndex(rel, idxoid, attno);
574 
575  ReleaseSysCache(atttuple);
578 
579  return newoid;
580 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:322
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
bool IsSystemRelation(Relation relation)
Definition: catalog.c:73
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259
unsigned int Oid
Definition: postgres_ext.h:31
Form_pg_index rd_index
Definition: rel.h:175
#define ERROR
Definition: elog.h:46
NameData attname
Definition: pg_attribute.h:41
Definition: c.h:675
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define RowExclusiveLock
Definition: lockdefs.h:38
#define RelationGetRelationName(relation)
Definition: rel.h:491
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition: rel.h:476
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1268
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:158
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define NameStr(name)
Definition: c.h:681
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
int16 AttrNumber
Definition: attnum.h:21
#define RelationGetRelid(relation)
Definition: rel.h:457
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:132
#define PG_GETARG_NAME(n)
Definition: fmgr.h:278