PostgreSQL Source Code  git master
relcache.h File Reference
#include "postgres.h"
#include "access/tupdesc.h"
#include "nodes/bitmapset.h"
Include dependency graph for relcache.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define RELCACHE_INIT_FILENAME   "pg_internal.init"
 
#define AssertPendingSyncs_RelationCache()   do {} while (0)
 

Typedefs

typedef struct RelationDataRelation
 
typedef RelationRelationPtr
 
typedef enum IndexAttrBitmapKind IndexAttrBitmapKind
 

Enumerations

enum  IndexAttrBitmapKind { INDEX_ATTR_BITMAP_ALL, INDEX_ATTR_BITMAP_KEY, INDEX_ATTR_BITMAP_PRIMARY_KEY, INDEX_ATTR_BITMAP_IDENTITY_KEY }
 

Functions

Relation RelationIdGetRelation (Oid relationId)
 
void RelationClose (Relation relation)
 
ListRelationGetFKeyList (Relation relation)
 
ListRelationGetIndexList (Relation relation)
 
ListRelationGetStatExtList (Relation relation)
 
Oid RelationGetPrimaryKeyIndex (Relation relation)
 
Oid RelationGetReplicaIndex (Relation relation)
 
ListRelationGetIndexExpressions (Relation relation)
 
ListRelationGetDummyIndexExpressions (Relation relation)
 
ListRelationGetIndexPredicate (Relation relation)
 
DatumRelationGetIndexRawAttOptions (Relation relation)
 
bytea ** RelationGetIndexAttOptions (Relation relation, bool copy)
 
BitmapsetRelationGetIndexAttrBitmap (Relation relation, IndexAttrBitmapKind attrKind)
 
void RelationGetExclusionInfo (Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
 
void RelationInitIndexAccessInfo (Relation relation)
 
struct PublicationActionsGetRelationPublicationActions (Relation relation)
 
void RelationInitTableAccessMethod (Relation relation)
 
int errtable (Relation rel)
 
int errtablecol (Relation rel, int attnum)
 
int errtablecolname (Relation rel, const char *colname)
 
int errtableconstraint (Relation rel, const char *conname)
 
void RelationCacheInitialize (void)
 
void RelationCacheInitializePhase2 (void)
 
void RelationCacheInitializePhase3 (void)
 
Relation RelationBuildLocalRelation (const char *relname, Oid relnamespace, TupleDesc tupDesc, Oid relid, Oid accessmtd, Oid relfilenode, Oid reltablespace, bool shared_relation, bool mapped_relation, char relpersistence, char relkind)
 
void RelationSetNewRelfilenode (Relation relation, char persistence)
 
void RelationAssumeNewRelfilenode (Relation relation)
 
void RelationForgetRelation (Oid rid)
 
void RelationCacheInvalidateEntry (Oid relationId)
 
void RelationCacheInvalidate (void)
 
void RelationCloseSmgrByOid (Oid relationId)
 
void AtEOXact_RelationCache (bool isCommit)
 
void AtEOSubXact_RelationCache (bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
 
bool RelationIdIsInInitFile (Oid relationId)
 
void RelationCacheInitFilePreInvalidate (void)
 
void RelationCacheInitFilePostInvalidate (void)
 
void RelationCacheInitFileRemove (void)
 

Variables

bool criticalRelcachesBuilt
 
bool criticalSharedRelcachesBuilt
 

Macro Definition Documentation

◆ AssertPendingSyncs_RelationCache

#define AssertPendingSyncs_RelationCache ( )    do {} while (0)

Definition at line 131 of file relcache.h.

Referenced by RememberToFreeTupleDescAtEOX(), and smgrDoPendingSyncs().

◆ RELCACHE_INIT_FILENAME

#define RELCACHE_INIT_FILENAME   "pg_internal.init"

Typedef Documentation

◆ IndexAttrBitmapKind

◆ Relation

typedef struct RelationData* Relation

Definition at line 27 of file relcache.h.

◆ RelationPtr

Definition at line 35 of file relcache.h.

Enumeration Type Documentation

◆ IndexAttrBitmapKind

Enumerator
INDEX_ATTR_BITMAP_ALL 
INDEX_ATTR_BITMAP_KEY 
INDEX_ATTR_BITMAP_PRIMARY_KEY 
INDEX_ATTR_BITMAP_IDENTITY_KEY 

Definition at line 57 of file relcache.h.

Function Documentation

◆ AtEOSubXact_RelationCache()

void AtEOSubXact_RelationCache ( bool  isCommit,
SubTransactionId  mySubid,
SubTransactionId  parentSubid 
)

Definition at line 3227 of file relcache.c.

References AtEOSubXact_cleanup(), eoxact_list, eoxact_list_len, eoxact_list_overflowed, HASH_FIND, hash_search(), hash_seq_init(), hash_seq_search(), i, relidcacheent::reldesc, and status().

Referenced by AbortSubTransaction(), and CommitSubTransaction().

3229 {
3231  RelIdCacheEnt *idhentry;
3232  int i;
3233 
3234  /*
3235  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3236  * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3237  * logic as in AtEOXact_RelationCache.
3238  */
3240  {
3241  hash_seq_init(&status, RelationIdCache);
3242  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3243  {
3244  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3245  mySubid, parentSubid);
3246  }
3247  }
3248  else
3249  {
3250  for (i = 0; i < eoxact_list_len; i++)
3251  {
3252  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3253  (void *) &eoxact_list[i],
3254  HASH_FIND,
3255  NULL);
3256  if (idhentry != NULL)
3257  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3258  mySubid, parentSubid);
3259  }
3260  }
3261 
3262  /* Don't reset the list; we still need more cleanup later */
3263 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:165
static void AtEOSubXact_cleanup(Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
Definition: relcache.c:3274
Relation reldesc
Definition: relcache.c:129
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
static HTAB * RelationIdCache
Definition: relcache.c:132
static bool eoxact_list_overflowed
Definition: relcache.c:167
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1436
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1426
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
static int eoxact_list_len
Definition: relcache.c:166

◆ AtEOXact_RelationCache()

void AtEOXact_RelationCache ( bool  isCommit)

Definition at line 3082 of file relcache.c.

References Assert, AtEOXact_cleanup(), eoxact_list, eoxact_list_len, eoxact_list_overflowed, EOXactTupleDescArrayLen, FreeTupleDesc(), HASH_FIND, hash_search(), hash_seq_init(), hash_seq_search(), i, NextEOXactTupleDescNum, pfree(), relidcacheent::reldesc, and status().

Referenced by AbortTransaction(), CommitTransaction(), and PrepareTransaction().

3083 {
3085  RelIdCacheEnt *idhentry;
3086  int i;
3087 
3088  /*
3089  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3090  * listed in it. Otherwise fall back on a hash_seq_search scan.
3091  *
3092  * For simplicity, eoxact_list[] entries are not deleted till end of
3093  * top-level transaction, even though we could remove them at
3094  * subtransaction end in some cases, or remove relations from the list if
3095  * they are cleared for other reasons. Therefore we should expect the
3096  * case that list entries are not found in the hashtable; if not, there's
3097  * nothing to do for them.
3098  */
3100  {
3101  hash_seq_init(&status, RelationIdCache);
3102  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3103  {
3104  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3105  }
3106  }
3107  else
3108  {
3109  for (i = 0; i < eoxact_list_len; i++)
3110  {
3111  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3112  (void *) &eoxact_list[i],
3113  HASH_FIND,
3114  NULL);
3115  if (idhentry != NULL)
3116  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3117  }
3118  }
3119 
3120  if (EOXactTupleDescArrayLen > 0)
3121  {
3122  Assert(EOXactTupleDescArray != NULL);
3123  for (i = 0; i < NextEOXactTupleDescNum; i++)
3126  EOXactTupleDescArray = NULL;
3127  }
3128 
3129  /* Now we're out of the transaction and can clear the lists */
3130  eoxact_list_len = 0;
3131  eoxact_list_overflowed = false;
3132  NextEOXactTupleDescNum = 0;
3134 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:165
static int EOXactTupleDescArrayLen
Definition: relcache.c:184
Relation reldesc
Definition: relcache.c:129
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
static HTAB * RelationIdCache
Definition: relcache.c:132
static void AtEOXact_cleanup(Relation relation, bool isCommit)
Definition: relcache.c:3145
static bool eoxact_list_overflowed
Definition: relcache.c:167
static int NextEOXactTupleDescNum
Definition: relcache.c:183
void pfree(void *pointer)
Definition: mcxt.c:1057
#define Assert(condition)
Definition: c.h:792
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1436
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1426
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:313
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
static int eoxact_list_len
Definition: relcache.c:166
static TupleDesc * EOXactTupleDescArray
Definition: relcache.c:182

◆ errtable()

int errtable ( Relation  rel)

Definition at line 5509 of file relcache.c.

References err_generic_string(), get_namespace_name(), PG_DIAG_SCHEMA_NAME, PG_DIAG_TABLE_NAME, RelationGetNamespace, and RelationGetRelationName.

Referenced by ATPrepChangePersistence(), ATRewriteTable(), BuildRelationExtStatistics(), check_default_partition_contents(), errtablecolname(), errtableconstraint(), ExecFindPartition(), and ExecPartitionCheckEmitError().

5510 {
5514 
5515  return 0; /* return value does not matter */
5516 }
#define PG_DIAG_SCHEMA_NAME
Definition: postgres_ext.h:65
#define PG_DIAG_TABLE_NAME
Definition: postgres_ext.h:66
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3289
#define RelationGetRelationName(relation)
Definition: rel.h:491
int err_generic_string(int field, const char *str)
Definition: elog.c:1356
#define RelationGetNamespace(relation)
Definition: rel.h:498

◆ errtablecol()

int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5526 of file relcache.c.

References attname, errtablecolname(), get_attname(), NameStr, RelationGetDescr, RelationGetRelid, relidcacheent::reldesc, and TupleDescAttr.

Referenced by AlterDomainNotNull(), ATRewriteTable(), ExecConstraints(), and validateDomainConstraint().

5527 {
5528  TupleDesc reldesc = RelationGetDescr(rel);
5529  const char *colname;
5530 
5531  /* Use reldesc if it's a user attribute, else consult the catalogs */
5532  if (attnum > 0 && attnum <= reldesc->natts)
5533  colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
5534  else
5535  colname = get_attname(RelationGetRelid(rel), attnum, false);
5536 
5537  return errtablecolname(rel, colname);
5538 }
#define RelationGetDescr(relation)
Definition: rel.h:483
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
NameData attname
Definition: pg_attribute.h:40
int16 attnum
Definition: pg_attribute.h:79
#define NameStr(name)
Definition: c.h:669
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:825
#define RelationGetRelid(relation)
Definition: rel.h:457
int errtablecolname(Relation rel, const char *colname)
Definition: relcache.c:5550

◆ errtablecolname()

int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5550 of file relcache.c.

References err_generic_string(), errtable(), and PG_DIAG_COLUMN_NAME.

Referenced by errtablecol().

5551 {
5552  errtable(rel);
5554 
5555  return 0; /* return value does not matter */
5556 }
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:67
int err_generic_string(int field, const char *str)
Definition: elog.c:1356
int errtable(Relation rel)
Definition: relcache.c:5509

◆ errtableconstraint()

int errtableconstraint ( Relation  rel,
const char *  conname 
)

Definition at line 5563 of file relcache.c.

References err_generic_string(), errtable(), and PG_DIAG_CONSTRAINT_NAME.

Referenced by _bt_check_third_page(), _bt_check_unique(), ATPrepChangePersistence(), ATRewriteTable(), check_exclusion_or_unique_constraint(), comparetup_index_btree(), ExecCheckIndexConstraints(), ExecConstraints(), RI_FKey_check(), RI_Initial_Check(), and ri_ReportViolation().

5564 {
5565  errtable(rel);
5567 
5568  return 0; /* return value does not matter */
5569 }
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:69
int err_generic_string(int field, const char *str)
Definition: elog.c:1356
int errtable(Relation rel)
Definition: relcache.c:5509

◆ GetRelationPublicationActions()

struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

Definition at line 5318 of file relcache.c.

References CacheMemoryContext, elog, ERROR, get_partition_ancestors(), GetAllTablesPublications(), GetRelationPublications(), GETSTRUCT, HeapTupleIsValid, is_publishable_relation(), lfirst_oid, list_concat_unique_oid(), MemoryContextSwitchTo(), ObjectIdGetDatum, palloc(), palloc0(), pfree(), PublicationActions::pubdelete, PublicationActions::pubinsert, PUBLICATIONOID, PublicationActions::pubtruncate, PublicationActions::pubupdate, RelationData::rd_pubactions, RelationData::rd_rel, RelationGetRelid, ReleaseSysCache(), and SearchSysCache1().

Referenced by CheckCmdReplicaIdentity().

5319 {
5320  List *puboids;
5321  ListCell *lc;
5322  MemoryContext oldcxt;
5323  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5324 
5325  /*
5326  * If not publishable, it publishes no actions. (pgoutput_change() will
5327  * ignore it.)
5328  */
5329  if (!is_publishable_relation(relation))
5330  return pubactions;
5331 
5332  if (relation->rd_pubactions)
5333  return memcpy(pubactions, relation->rd_pubactions,
5334  sizeof(PublicationActions));
5335 
5336  /* Fetch the publication membership info. */
5337  puboids = GetRelationPublications(RelationGetRelid(relation));
5338  if (relation->rd_rel->relispartition)
5339  {
5340  /* Add publications that the ancestors are in too. */
5341  List *ancestors = get_partition_ancestors(RelationGetRelid(relation));
5342  ListCell *lc;
5343 
5344  foreach(lc, ancestors)
5345  {
5346  Oid ancestor = lfirst_oid(lc);
5347 
5348  puboids = list_concat_unique_oid(puboids,
5349  GetRelationPublications(ancestor));
5350  }
5351  }
5352  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5353 
5354  foreach(lc, puboids)
5355  {
5356  Oid pubid = lfirst_oid(lc);
5357  HeapTuple tup;
5358  Form_pg_publication pubform;
5359 
5361 
5362  if (!HeapTupleIsValid(tup))
5363  elog(ERROR, "cache lookup failed for publication %u", pubid);
5364 
5365  pubform = (Form_pg_publication) GETSTRUCT(tup);
5366 
5367  pubactions->pubinsert |= pubform->pubinsert;
5368  pubactions->pubupdate |= pubform->pubupdate;
5369  pubactions->pubdelete |= pubform->pubdelete;
5370  pubactions->pubtruncate |= pubform->pubtruncate;
5371 
5372  ReleaseSysCache(tup);
5373 
5374  /*
5375  * If we know everything is replicated, there is no point to check for
5376  * other publications.
5377  */
5378  if (pubactions->pubinsert && pubactions->pubupdate &&
5379  pubactions->pubdelete && pubactions->pubtruncate)
5380  break;
5381  }
5382 
5383  if (relation->rd_pubactions)
5384  {
5385  pfree(relation->rd_pubactions);
5386  relation->rd_pubactions = NULL;
5387  }
5388 
5389  /* Now save copy of the actions in the relcache entry. */
5391  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5392  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5393  MemoryContextSwitchTo(oldcxt);
5394 
5395  return pubactions;
5396 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
PublicationActions * rd_pubactions
Definition: rel.h:151
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Form_pg_class rd_rel
Definition: rel.h:110
unsigned int Oid
Definition: postgres_ext.h:31
List * GetRelationPublications(Oid relid)
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
List * list_concat_unique_oid(List *list1, const List *list2)
Definition: list.c:1316
bool is_publishable_relation(Relation rel)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void * palloc0(Size size)
Definition: mcxt.c:981
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
List * GetAllTablesPublications(void)
void * palloc(Size size)
Definition: mcxt.c:950
#define elog(elevel,...)
Definition: elog.h:228
FormData_pg_publication * Form_pg_publication
Definition: pg_list.h:50
List * get_partition_ancestors(Oid relid)
Definition: partition.c:115
#define RelationGetRelid(relation)
Definition: rel.h:457
#define lfirst_oid(lc)
Definition: pg_list.h:171
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationAssumeNewRelfilenode()

void RelationAssumeNewRelfilenode ( Relation  relation)

Definition at line 3751 of file relcache.c.

References EOXactListAdd, GetCurrentSubTransactionId(), InvalidSubTransactionId, RelationData::rd_firstRelfilenodeSubid, and RelationData::rd_newRelfilenodeSubid.

Referenced by ATExecSetTableSpace(), RelationSetNewRelfilenode(), and swap_relation_files().

3752 {
3755  relation->rd_firstRelfilenodeSubid = relation->rd_newRelfilenodeSubid;
3756 
3757  /* Flag relation as needing eoxact cleanup (to clear these fields) */
3758  EOXactListAdd(relation);
3759 }
#define EOXactListAdd(rel)
Definition: relcache.c:169
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:104
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:106
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:723
#define InvalidSubTransactionId
Definition: c.h:581

◆ RelationBuildLocalRelation()

Relation RelationBuildLocalRelation ( const char *  relname,
Oid  relnamespace,
TupleDesc  tupDesc,
Oid  relid,
Oid  accessmtd,
Oid  relfilenode,
Oid  reltablespace,
bool  shared_relation,
bool  mapped_relation,
char  relpersistence,
char  relkind 
)

Definition at line 3356 of file relcache.c.

References Assert, AssertArg, BackendIdForTempRelations, CacheMemoryContext, CLASS_TUPLE_SIZE, TupleDescData::constr, CreateCacheMemoryContext(), CreateTupleDescCopy(), elog, EOXactListAdd, ERROR, GetCurrentSubTransactionId(), TupleConstr::has_not_null, i, InvalidBackendId, InvalidOid, InvalidSubTransactionId, IsCatalogNamespace(), IsSharedRelation(), isTempOrTempToastNamespace(), MemoryContextSwitchTo(), namestrcpy(), TupleDescData::natts, palloc0(), RelationData::rd_att, RelationData::rd_backend, RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_firstRelfilenodeSubid, RelationData::rd_islocaltemp, RelationData::rd_isnailed, RelationData::rd_isvalid, RelationData::rd_newRelfilenodeSubid, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_smgr, RelationCacheInsert, RelationGetRelid, RelationIncrementReferenceCount(), RelationInitLockInfo(), RelationInitPhysicalAddr(), RelationInitTableAccessMethod(), RelationMapUpdateMap(), TupleDescData::tdrefcount, and TupleDescAttr.

Referenced by heap_create().

3367 {
3368  Relation rel;
3369  MemoryContext oldcxt;
3370  int natts = tupDesc->natts;
3371  int i;
3372  bool has_not_null;
3373  bool nailit;
3374 
3375  AssertArg(natts >= 0);
3376 
3377  /*
3378  * check for creation of a rel that must be nailed in cache.
3379  *
3380  * XXX this list had better match the relations specially handled in
3381  * RelationCacheInitializePhase2/3.
3382  */
3383  switch (relid)
3384  {
3385  case DatabaseRelationId:
3386  case AuthIdRelationId:
3387  case AuthMemRelationId:
3388  case RelationRelationId:
3389  case AttributeRelationId:
3390  case ProcedureRelationId:
3391  case TypeRelationId:
3392  nailit = true;
3393  break;
3394  default:
3395  nailit = false;
3396  break;
3397  }
3398 
3399  /*
3400  * check that hardwired list of shared rels matches what's in the
3401  * bootstrap .bki file. If you get a failure here during initdb, you
3402  * probably need to fix IsSharedRelation() to match whatever you've done
3403  * to the set of shared relations.
3404  */
3405  if (shared_relation != IsSharedRelation(relid))
3406  elog(ERROR, "shared_relation flag for \"%s\" does not match IsSharedRelation(%u)",
3407  relname, relid);
3408 
3409  /* Shared relations had better be mapped, too */
3410  Assert(mapped_relation || !shared_relation);
3411 
3412  /*
3413  * switch to the cache context to create the relcache entry.
3414  */
3415  if (!CacheMemoryContext)
3417 
3419 
3420  /*
3421  * allocate a new relation descriptor and fill in basic state fields.
3422  */
3423  rel = (Relation) palloc0(sizeof(RelationData));
3424 
3425  /* make sure relation is marked as having no open file yet */
3426  rel->rd_smgr = NULL;
3427 
3428  /* mark it nailed if appropriate */
3429  rel->rd_isnailed = nailit;
3430 
3431  rel->rd_refcnt = nailit ? 1 : 0;
3432 
3433  /* it's being created in this transaction */
3438 
3439  /*
3440  * create a new tuple descriptor from the one passed in. We do this
3441  * partly to copy it into the cache context, and partly because the new
3442  * relation can't have any defaults or constraints yet; they have to be
3443  * added in later steps, because they require additions to multiple system
3444  * catalogs. We can copy attnotnull constraints here, however.
3445  */
3446  rel->rd_att = CreateTupleDescCopy(tupDesc);
3447  rel->rd_att->tdrefcount = 1; /* mark as refcounted */
3448  has_not_null = false;
3449  for (i = 0; i < natts; i++)
3450  {
3451  Form_pg_attribute satt = TupleDescAttr(tupDesc, i);
3452  Form_pg_attribute datt = TupleDescAttr(rel->rd_att, i);
3453 
3454  datt->attidentity = satt->attidentity;
3455  datt->attgenerated = satt->attgenerated;
3456  datt->attnotnull = satt->attnotnull;
3457  has_not_null |= satt->attnotnull;
3458  }
3459 
3460  if (has_not_null)
3461  {
3462  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
3463 
3464  constr->has_not_null = true;
3465  rel->rd_att->constr = constr;
3466  }
3467 
3468  /*
3469  * initialize relation tuple form (caller may add/override data later)
3470  */
3472 
3473  namestrcpy(&rel->rd_rel->relname, relname);
3474  rel->rd_rel->relnamespace = relnamespace;
3475 
3476  rel->rd_rel->relkind = relkind;
3477  rel->rd_rel->relnatts = natts;
3478  rel->rd_rel->reltype = InvalidOid;
3479  /* needed when bootstrapping: */
3480  rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;
3481 
3482  /* set up persistence and relcache fields dependent on it */
3483  rel->rd_rel->relpersistence = relpersistence;
3484  switch (relpersistence)
3485  {
3486  case RELPERSISTENCE_UNLOGGED:
3487  case RELPERSISTENCE_PERMANENT:
3489  rel->rd_islocaltemp = false;
3490  break;
3491  case RELPERSISTENCE_TEMP:
3492  Assert(isTempOrTempToastNamespace(relnamespace));
3494  rel->rd_islocaltemp = true;
3495  break;
3496  default:
3497  elog(ERROR, "invalid relpersistence: %c", relpersistence);
3498  break;
3499  }
3500 
3501  /* if it's a materialized view, it's not populated initially */
3502  if (relkind == RELKIND_MATVIEW)
3503  rel->rd_rel->relispopulated = false;
3504  else
3505  rel->rd_rel->relispopulated = true;
3506 
3507  /* set replica identity -- system catalogs and non-tables don't have one */
3508  if (!IsCatalogNamespace(relnamespace) &&
3509  (relkind == RELKIND_RELATION ||
3510  relkind == RELKIND_MATVIEW ||
3511  relkind == RELKIND_PARTITIONED_TABLE))
3512  rel->rd_rel->relreplident = REPLICA_IDENTITY_DEFAULT;
3513  else
3514  rel->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
3515 
3516  /*
3517  * Insert relation physical and logical identifiers (OIDs) into the right
3518  * places. For a mapped relation, we set relfilenode to zero and rely on
3519  * RelationInitPhysicalAddr to consult the map.
3520  */
3521  rel->rd_rel->relisshared = shared_relation;
3522 
3523  RelationGetRelid(rel) = relid;
3524 
3525  for (i = 0; i < natts; i++)
3526  TupleDescAttr(rel->rd_att, i)->attrelid = relid;
3527 
3528  rel->rd_rel->reltablespace = reltablespace;
3529 
3530  if (mapped_relation)
3531  {
3532  rel->rd_rel->relfilenode = InvalidOid;
3533  /* Add it to the active mapping information */
3534  RelationMapUpdateMap(relid, relfilenode, shared_relation, true);
3535  }
3536  else
3537  rel->rd_rel->relfilenode = relfilenode;
3538 
3539  RelationInitLockInfo(rel); /* see lmgr.c */
3540 
3542 
3543  rel->rd_rel->relam = accessmtd;
3544 
3545  if (relkind == RELKIND_RELATION ||
3546  relkind == RELKIND_SEQUENCE ||
3547  relkind == RELKIND_TOASTVALUE ||
3548  relkind == RELKIND_MATVIEW)
3550 
3551  /*
3552  * Okay to insert into the relcache hash table.
3553  *
3554  * Ordinarily, there should certainly not be an existing hash entry for
3555  * the same OID; but during bootstrap, when we create a "real" relcache
3556  * entry for one of the bootstrap relations, we'll be overwriting the
3557  * phony one created with formrdesc. So allow that to happen for nailed
3558  * rels.
3559  */
3560  RelationCacheInsert(rel, nailit);
3561 
3562  /*
3563  * Flag relation as needing eoxact cleanup (to clear rd_createSubid). We
3564  * can't do this before storing relid in it.
3565  */
3566  EOXactListAdd(rel);
3567 
3568  /*
3569  * done building relcache entry.
3570  */
3571  MemoryContextSwitchTo(oldcxt);
3572 
3573  /* It's fully valid */
3574  rel->rd_isvalid = true;
3575 
3576  /*
3577  * Caller expects us to pin the returned entry.
3578  */
3580 
3581  return rel;
3582 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
#define EOXactListAdd(rel)
Definition: relcache.c:169
void namestrcpy(Name name, const char *str)
Definition: name.c:233
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3180
void RelationInitTableAccessMethod(Relation relation)
Definition: relcache.c:1765
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
struct SMgrRelationData * rd_smgr
Definition: rel.h:57
bool rd_isnailed
Definition: rel.h:61
bool rd_islocaltemp
Definition: rel.h:60
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool rd_isvalid
Definition: rel.h:62
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:104
Form_pg_class rd_rel
Definition: rel.h:110
NameData relname
Definition: pg_class.h:38
struct RelationData * Relation
Definition: relcache.h:27
#define ERROR
Definition: elog.h:45
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1279
void RelationInitLockInfo(Relation relation)
Definition: lmgr.c:71
#define BackendIdForTempRelations()
Definition: backendid.h:34
TupleConstr * constr
Definition: tupdesc.h:85
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
#define AssertArg(condition)
Definition: c.h:794
SubTransactionId rd_createSubid
Definition: rel.h:103
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:106
#define InvalidBackendId
Definition: backendid.h:23
void * palloc0(Size size)
Definition: mcxt.c:981
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2090
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:236
TupleDesc rd_att
Definition: rel.h:111
#define InvalidOid
Definition: postgres_ext.h:36
#define RelationCacheInsert(RELATION, replace_allowed)
Definition: relcache.c:189
#define CLASS_TUPLE_SIZE
Definition: pg_class.h:145
BackendId rd_backend
Definition: rel.h:59
#define Assert(condition)
Definition: c.h:792
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:723
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
#define InvalidSubTransactionId
Definition: c.h:581
bool IsCatalogNamespace(Oid namespaceId)
Definition: catalog.c:175
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
int rd_refcnt
Definition: rel.h:58
#define elog(elevel,...)
Definition: elog.h:228
int i
int tdrefcount
Definition: tupdesc.h:84
bool has_not_null
Definition: tupdesc.h:44
#define RelationGetRelid(relation)
Definition: rel.h:457
SubTransactionId rd_droppedSubid
Definition: rel.h:108
void RelationMapUpdateMap(Oid relationId, Oid fileNode, bool shared, bool immediate)
Definition: relmapper.c:261
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInitFilePostInvalidate()

void RelationCacheInitFilePostInvalidate ( void  )

Definition at line 6336 of file relcache.c.

References LWLockRelease().

Referenced by AtEOXact_Inval(), FinishPreparedTransaction(), and ProcessCommittedInvalidationMessages().

6337 {
6338  LWLockRelease(RelCacheInitLock);
6339 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1808

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )

Definition at line 6311 of file relcache.c.

References DatabasePath, ERROR, LW_EXCLUSIVE, LWLockAcquire(), MAXPGPATH, RELCACHE_INIT_FILENAME, snprintf, and unlink_initfile().

Referenced by AtEOXact_Inval(), FinishPreparedTransaction(), and ProcessCommittedInvalidationMessages().

6312 {
6313  char localinitfname[MAXPGPATH];
6314  char sharedinitfname[MAXPGPATH];
6315 
6316  if (DatabasePath)
6317  snprintf(localinitfname, sizeof(localinitfname), "%s/%s",
6319  snprintf(sharedinitfname, sizeof(sharedinitfname), "global/%s",
6321 
6322  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6323 
6324  /*
6325  * The files might not be there if no backend has been started since the
6326  * last removal. But complain about failures other than ENOENT with
6327  * ERROR. Fortunately, it's not too late to abort the transaction if we
6328  * can't get rid of the would-be-obsolete init file.
6329  */
6330  if (DatabasePath)
6331  unlink_initfile(localinitfname, ERROR);
6332  unlink_initfile(sharedinitfname, ERROR);
6333 }
#define ERROR
Definition: elog.h:45
#define MAXPGPATH
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25
char * DatabasePath
Definition: globals.c:94
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6408
#define snprintf
Definition: port.h:215

◆ RelationCacheInitFileRemove()

void RelationCacheInitFileRemove ( void  )

Definition at line 6351 of file relcache.c.

References AllocateDir(), dirent::d_name, FreeDir(), LOG, MAXPGPATH, ReadDirExtended(), RelationCacheInitFileRemoveInDir(), RELCACHE_INIT_FILENAME, snprintf, TABLESPACE_VERSION_DIRECTORY, and unlink_initfile().

Referenced by StartupXLOG().

6352 {
6353  const char *tblspcdir = "pg_tblspc";
6354  DIR *dir;
6355  struct dirent *de;
6356  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6357 
6358  snprintf(path, sizeof(path), "global/%s",
6360  unlink_initfile(path, LOG);
6361 
6362  /* Scan everything in the default tablespace */
6364 
6365  /* Scan the tablespace link directory to find non-default tablespaces */
6366  dir = AllocateDir(tblspcdir);
6367 
6368  while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6369  {
6370  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6371  {
6372  /* Scan the tablespace dir for per-database dirs */
6373  snprintf(path, sizeof(path), "%s/%s/%s",
6374  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6376  }
6377  }
6378 
6379  FreeDir(dir);
6380 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6384
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2696
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:26
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2615
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6408
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:215
int FreeDir(DIR *dir)
Definition: fd.c:2733

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 3777 of file relcache.c.

References CacheMemoryContext, CreateCacheMemoryContext(), HASHCTL::entrysize, HASH_BLOBS, hash_create(), HASH_ELEM, INITRELCACHESIZE, HASHCTL::keysize, and RelationMapInitialize().

Referenced by InitPostgres().

3778 {
3779  HASHCTL ctl;
3780 
3781  /*
3782  * make sure cache memory context exists
3783  */
3784  if (!CacheMemoryContext)
3786 
3787  /*
3788  * create hashtable that indexes the relcache
3789  */
3790  ctl.keysize = sizeof(Oid);
3791  ctl.entrysize = sizeof(RelIdCacheEnt);
3792  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3793  &ctl, HASH_ELEM | HASH_BLOBS);
3794 
3795  /*
3796  * relation mapper needs to be initialized too
3797  */
3799 }
void RelationMapInitialize(void)
Definition: relmapper.c:584
#define HASH_ELEM
Definition: hsearch.h:95
struct relidcacheent RelIdCacheEnt
Size entrysize
Definition: hsearch.h:76
static HTAB * RelationIdCache
Definition: relcache.c:132
unsigned int Oid
Definition: postgres_ext.h:31
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
#define HASH_BLOBS
Definition: hsearch.h:97
Size keysize
Definition: hsearch.h:75
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
#define INITRELCACHESIZE
Definition: relcache.c:3774
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInitializePhase2()

void RelationCacheInitializePhase2 ( void  )

Definition at line 3813 of file relcache.c.

References CacheMemoryContext, Desc_pg_auth_members, Desc_pg_authid, Desc_pg_database, Desc_pg_shseclabel, Desc_pg_subscription, formrdesc(), IsBootstrapProcessingMode, load_relcache_init_file(), MemoryContextSwitchTo(), and RelationMapInitializePhase2().

Referenced by InitPostgres().

3814 {
3815  MemoryContext oldcxt;
3816 
3817  /*
3818  * relation mapper needs initialized too
3819  */
3821 
3822  /*
3823  * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3824  * nothing.
3825  */
3827  return;
3828 
3829  /*
3830  * switch to cache memory context
3831  */
3833 
3834  /*
3835  * Try to load the shared relcache cache file. If unsuccessful, bootstrap
3836  * the cache with pre-made descriptors for the critical shared catalogs.
3837  */
3838  if (!load_relcache_init_file(true))
3839  {
3840  formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
3841  Natts_pg_database, Desc_pg_database);
3842  formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
3843  Natts_pg_authid, Desc_pg_authid);
3844  formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
3845  Natts_pg_auth_members, Desc_pg_auth_members);
3846  formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
3847  Natts_pg_shseclabel, Desc_pg_shseclabel);
3848  formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
3849  Natts_pg_subscription, Desc_pg_subscription);
3850 
3851 #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
3852  }
3853 
3854  MemoryContextSwitchTo(oldcxt);
3855 }
static const FormData_pg_attribute Desc_pg_auth_members[Natts_pg_auth_members]
Definition: relcache.c:115
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5627
void RelationMapInitializePhase2(void)
Definition: relmapper.c:604
static const FormData_pg_attribute Desc_pg_authid[Natts_pg_authid]
Definition: relcache.c:114
static const FormData_pg_attribute Desc_pg_subscription[Natts_pg_subscription]
Definition: relcache.c:118
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static const FormData_pg_attribute Desc_pg_database[Natts_pg_database]
Definition: relcache.c:113
static const FormData_pg_attribute Desc_pg_shseclabel[Natts_pg_shseclabel]
Definition: relcache.c:117
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:394
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1829
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInitializePhase3()

void RelationCacheInitializePhase3 ( void  )

Definition at line 3872 of file relcache.c.

References AccessMethodProcedureIndexId, Assert, AttributeRelidNumIndexId, AuthIdOidIndexId, AuthIdRolnameIndexId, AuthMemMemRoleIndexId, CacheMemoryContext, CLASS_TUPLE_SIZE, ClassOidIndexId, criticalRelcachesBuilt, criticalSharedRelcachesBuilt, DatabaseNameIndexId, DatabaseOidIndexId, Desc_pg_attribute, Desc_pg_class, Desc_pg_proc, Desc_pg_type, elog, ERROR, FATAL, formrdesc(), GETSTRUCT, hash_seq_init(), hash_seq_search(), hash_seq_term(), HeapTupleIsValid, IndexRelidIndexId, InitCatalogCachePhase2(), InvalidOid, IsBootstrapProcessingMode, load_critical_index(), load_relcache_init_file(), MemoryContextSwitchTo(), ObjectIdGetDatum, OpclassOidIndexId, pfree(), RelationData::rd_att, RelationData::rd_options, RelationData::rd_rel, RelationData::rd_rsdesc, RelationData::rd_rules, RelationData::rd_tableam, RelationBuildRowSecurity(), RelationBuildRuleLock(), RelationBuildTriggers(), RelationDecrementReferenceCount(), RelationGetRelationName, RelationGetRelid, RelationIncrementReferenceCount(), RelationInitTableAccessMethod(), RelationMapInitializePhase3(), RelationParseRelOptions(), relidcacheent::reldesc, ReleaseSysCache(), RELOID, RewriteRelRulenameIndexId, SearchSysCache1(), SharedSecLabelObjectIndexId, status(), TupleDescData::tdtypeid, TupleDescData::tdtypmod, RelationData::trigdesc, TriggerRelidNameIndexId, and write_relcache_init_file().

Referenced by InitPostgres().

3873 {
3875  RelIdCacheEnt *idhentry;
3876  MemoryContext oldcxt;
3877  bool needNewCacheFile = !criticalSharedRelcachesBuilt;
3878 
3879  /*
3880  * relation mapper needs initialized too
3881  */
3883 
3884  /*
3885  * switch to cache memory context
3886  */
3888 
3889  /*
3890  * Try to load the local relcache cache file. If unsuccessful, bootstrap
3891  * the cache with pre-made descriptors for the critical "nailed-in" system
3892  * catalogs.
3893  */
3894  if (IsBootstrapProcessingMode() ||
3895  !load_relcache_init_file(false))
3896  {
3897  needNewCacheFile = true;
3898 
3899  formrdesc("pg_class", RelationRelation_Rowtype_Id, false,
3900  Natts_pg_class, Desc_pg_class);
3901  formrdesc("pg_attribute", AttributeRelation_Rowtype_Id, false,
3902  Natts_pg_attribute, Desc_pg_attribute);
3903  formrdesc("pg_proc", ProcedureRelation_Rowtype_Id, false,
3904  Natts_pg_proc, Desc_pg_proc);
3905  formrdesc("pg_type", TypeRelation_Rowtype_Id, false,
3906  Natts_pg_type, Desc_pg_type);
3907 
3908 #define NUM_CRITICAL_LOCAL_RELS 4 /* fix if you change list above */
3909  }
3910 
3911  MemoryContextSwitchTo(oldcxt);
3912 
3913  /* In bootstrap mode, the faked-up formrdesc info is all we'll have */
3915  return;
3916 
3917  /*
3918  * If we didn't get the critical system indexes loaded into relcache, do
3919  * so now. These are critical because the catcache and/or opclass cache
3920  * depend on them for fetches done during relcache load. Thus, we have an
3921  * infinite-recursion problem. We can break the recursion by doing
3922  * heapscans instead of indexscans at certain key spots. To avoid hobbling
3923  * performance, we only want to do that until we have the critical indexes
3924  * loaded into relcache. Thus, the flag criticalRelcachesBuilt is used to
3925  * decide whether to do heapscan or indexscan at the key spots, and we set
3926  * it true after we've loaded the critical indexes.
3927  *
3928  * The critical indexes are marked as "nailed in cache", partly to make it
3929  * easy for load_relcache_init_file to count them, but mainly because we
3930  * cannot flush and rebuild them once we've set criticalRelcachesBuilt to
3931  * true. (NOTE: perhaps it would be possible to reload them by
3932  * temporarily setting criticalRelcachesBuilt to false again. For now,
3933  * though, we just nail 'em in.)
3934  *
3935  * RewriteRelRulenameIndexId and TriggerRelidNameIndexId are not critical
3936  * in the same way as the others, because the critical catalogs don't
3937  * (currently) have any rules or triggers, and so these indexes can be
3938  * rebuilt without inducing recursion. However they are used during
3939  * relcache load when a rel does have rules or triggers, so we choose to
3940  * nail them for performance reasons.
3941  */
3943  {
3945  RelationRelationId);
3947  AttributeRelationId);
3949  IndexRelationId);
3951  OperatorClassRelationId);
3953  AccessMethodProcedureRelationId);
3955  RewriteRelationId);
3957  TriggerRelationId);
3958 
3959 #define NUM_CRITICAL_LOCAL_INDEXES 7 /* fix if you change list above */
3960 
3961  criticalRelcachesBuilt = true;
3962  }
3963 
3964  /*
3965  * Process critical shared indexes too.
3966  *
3967  * DatabaseNameIndexId isn't critical for relcache loading, but rather for
3968  * initial lookup of MyDatabaseId, without which we'll never find any
3969  * non-shared catalogs at all. Autovacuum calls InitPostgres with a
3970  * database OID, so it instead depends on DatabaseOidIndexId. We also
3971  * need to nail up some indexes on pg_authid and pg_auth_members for use
3972  * during client authentication. SharedSecLabelObjectIndexId isn't
3973  * critical for the core system, but authentication hooks might be
3974  * interested in it.
3975  */
3977  {
3979  DatabaseRelationId);
3981  DatabaseRelationId);
3983  AuthIdRelationId);
3985  AuthIdRelationId);
3987  AuthMemRelationId);
3989  SharedSecLabelRelationId);
3990 
3991 #define NUM_CRITICAL_SHARED_INDEXES 6 /* fix if you change list above */
3992 
3994  }
3995 
3996  /*
3997  * Now, scan all the relcache entries and update anything that might be
3998  * wrong in the results from formrdesc or the relcache cache file. If we
3999  * faked up relcache entries using formrdesc, then read the real pg_class
4000  * rows and replace the fake entries with them. Also, if any of the
4001  * relcache entries have rules, triggers, or security policies, load that
4002  * info the hard way since it isn't recorded in the cache file.
4003  *
4004  * Whenever we access the catalogs to read data, there is a possibility of
4005  * a shared-inval cache flush causing relcache entries to be removed.
4006  * Since hash_seq_search only guarantees to still work after the *current*
4007  * entry is removed, it's unsafe to continue the hashtable scan afterward.
4008  * We handle this by restarting the scan from scratch after each access.
4009  * This is theoretically O(N^2), but the number of entries that actually
4010  * need to be fixed is small enough that it doesn't matter.
4011  */
4012  hash_seq_init(&status, RelationIdCache);
4013 
4014  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
4015  {
4016  Relation relation = idhentry->reldesc;
4017  bool restart = false;
4018 
4019  /*
4020  * Make sure *this* entry doesn't get flushed while we work with it.
4021  */
4023 
4024  /*
4025  * If it's a faked-up entry, read the real pg_class tuple.
4026  */
4027  if (relation->rd_rel->relowner == InvalidOid)
4028  {
4029  HeapTuple htup;
4030  Form_pg_class relp;
4031 
4032  htup = SearchSysCache1(RELOID,
4033  ObjectIdGetDatum(RelationGetRelid(relation)));
4034  if (!HeapTupleIsValid(htup))
4035  elog(FATAL, "cache lookup failed for relation %u",
4036  RelationGetRelid(relation));
4037  relp = (Form_pg_class) GETSTRUCT(htup);
4038 
4039  /*
4040  * Copy tuple to relation->rd_rel. (See notes in
4041  * AllocateRelationDesc())
4042  */
4043  memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
4044 
4045  /* Update rd_options while we have the tuple */
4046  if (relation->rd_options)
4047  pfree(relation->rd_options);
4048  RelationParseRelOptions(relation, htup);
4049 
4050  /*
4051  * Check the values in rd_att were set up correctly. (We cannot
4052  * just copy them over now: formrdesc must have set up the rd_att
4053  * data correctly to start with, because it may already have been
4054  * copied into one or more catcache entries.)
4055  */
4056  Assert(relation->rd_att->tdtypeid == relp->reltype);
4057  Assert(relation->rd_att->tdtypmod == -1);
4058 
4059  ReleaseSysCache(htup);
4060 
4061  /* relowner had better be OK now, else we'll loop forever */
4062  if (relation->rd_rel->relowner == InvalidOid)
4063  elog(ERROR, "invalid relowner in pg_class entry for \"%s\"",
4064  RelationGetRelationName(relation));
4065 
4066  restart = true;
4067  }
4068 
4069  /*
4070  * Fix data that isn't saved in relcache cache file.
4071  *
4072  * relhasrules or relhastriggers could possibly be wrong or out of
4073  * date. If we don't actually find any rules or triggers, clear the
4074  * local copy of the flag so that we don't get into an infinite loop
4075  * here. We don't make any attempt to fix the pg_class entry, though.
4076  */
4077  if (relation->rd_rel->relhasrules && relation->rd_rules == NULL)
4078  {
4079  RelationBuildRuleLock(relation);
4080  if (relation->rd_rules == NULL)
4081  relation->rd_rel->relhasrules = false;
4082  restart = true;
4083  }
4084  if (relation->rd_rel->relhastriggers && relation->trigdesc == NULL)
4085  {
4086  RelationBuildTriggers(relation);
4087  if (relation->trigdesc == NULL)
4088  relation->rd_rel->relhastriggers = false;
4089  restart = true;
4090  }
4091 
4092  /*
4093  * Re-load the row security policies if the relation has them, since
4094  * they are not preserved in the cache. Note that we can never NOT
4095  * have a policy while relrowsecurity is true,
4096  * RelationBuildRowSecurity will create a single default-deny policy
4097  * if there is no policy defined in pg_policy.
4098  */
4099  if (relation->rd_rel->relrowsecurity && relation->rd_rsdesc == NULL)
4100  {
4101  RelationBuildRowSecurity(relation);
4102 
4103  Assert(relation->rd_rsdesc != NULL);
4104  restart = true;
4105  }
4106 
4107  /* Reload tableam data if needed */
4108  if (relation->rd_tableam == NULL &&
4109  (relation->rd_rel->relkind == RELKIND_RELATION ||
4110  relation->rd_rel->relkind == RELKIND_SEQUENCE ||
4111  relation->rd_rel->relkind == RELKIND_TOASTVALUE ||
4112  relation->rd_rel->relkind == RELKIND_MATVIEW))
4113  {
4115  Assert(relation->rd_tableam != NULL);
4116 
4117  restart = true;
4118  }
4119 
4120  /* Release hold on the relation */
4122 
4123  /* Now, restart the hashtable scan if needed */
4124  if (restart)
4125  {
4126  hash_seq_term(&status);
4127  hash_seq_init(&status, RelationIdCache);
4128  }
4129  }
4130 
4131  /*
4132  * Lastly, write out new relcache cache files if needed. We don't bother
4133  * to distinguish cases where only one of the two needs an update.
4134  */
4135  if (needNewCacheFile)
4136  {
4137  /*
4138  * Force all the catcaches to finish initializing and thereby open the
4139  * catalogs and indexes they use. This will preload the relcache with
4140  * entries for all the most important system catalogs and indexes, so
4141  * that the init files will be most useful for future backends.
4142  */
4144 
4145  /* now write the files */
4147  write_relcache_init_file(false);
4148  }
4149 }
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5627
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define TriggerRelidNameIndexId
Definition: pg_trigger.h:80
void RelationBuildRowSecurity(Relation relation)
Definition: policy.c:195
void RelationInitTableAccessMethod(Relation relation)
Definition: relcache.c:1765
#define IndexRelidIndexId
Definition: pg_index.h:73
Relation reldesc
Definition: relcache.c:129
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define DatabaseNameIndexId
Definition: pg_database.h:88
bool criticalSharedRelcachesBuilt
Definition: relcache.c:144
static HTAB * RelationIdCache
Definition: relcache.c:132
Form_pg_class rd_rel
Definition: rel.h:110
#define ClassOidIndexId
Definition: pg_class.h:156
#define SharedSecLabelObjectIndexId
Definition: pg_shseclabel.h:46
#define AuthMemMemRoleIndexId
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2103
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
int32 tdtypmod
Definition: tupdesc.h:83
#define FATAL
Definition: elog.h:54
static void write_relcache_init_file(bool shared)
Definition: relcache.c:6044
TriggerDesc * trigdesc
Definition: rel.h:116
static void RelationParseRelOptions(Relation relation, HeapTuple tuple)
Definition: relcache.c:441
#define AttributeRelidNumIndexId
Definition: pg_attribute.h:198
static void load_critical_index(Oid indexoid, Oid heapoid)
Definition: relcache.c:4158
static const FormData_pg_attribute Desc_pg_proc[Natts_pg_proc]
Definition: relcache.c:111
#define RelationGetRelationName(relation)
Definition: rel.h:491
#define OpclassOidIndexId
Definition: pg_opclass.h:88
struct RowSecurityDesc * rd_rsdesc
Definition: rel.h:118
#define DatabaseOidIndexId
Definition: pg_database.h:90
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2090
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define AccessMethodProcedureIndexId
Definition: pg_amproc.h:71
const struct TableAmRoutine * rd_tableam
Definition: rel.h:172
TupleDesc rd_att
Definition: rel.h:111
#define InvalidOid
Definition: postgres_ext.h:36
#define CLASS_TUPLE_SIZE
Definition: pg_class.h:145
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:792
#define RewriteRelRulenameIndexId
Definition: pg_rewrite.h:59
RuleLock * rd_rules
Definition: rel.h:114
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1436
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1426
#define AuthIdOidIndexId
Definition: pg_authid.h:65
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:394
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
Oid tdtypeid
Definition: tupdesc.h:82
void RelationBuildTriggers(Relation relation)
Definition: trigger.c:1644
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1829
static const FormData_pg_attribute Desc_pg_class[Natts_pg_class]
Definition: relcache.c:109
#define elog(elevel,...)
Definition: elog.h:228
void RelationMapInitializePhase3(void)
Definition: relmapper.c:625
static void RelationBuildRuleLock(Relation relation)
Definition: relcache.c:736
bool criticalRelcachesBuilt
Definition: relcache.c:138
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
void InitCatalogCachePhase2(void)
Definition: syscache.c:1086
#define AuthIdRolnameIndexId
Definition: pg_authid.h:63
#define RelationGetRelid(relation)
Definition: rel.h:457
static const FormData_pg_attribute Desc_pg_type[Natts_pg_type]
Definition: relcache.c:112
bytea * rd_options
Definition: rel.h:158
void hash_seq_term(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1512
static const FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute]
Definition: relcache.c:110
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInvalidate()

void RelationCacheInvalidate ( void  )

Definition at line 2844 of file relcache.c.

References Assert, ClassOidIndexId, hash_seq_init(), hash_seq_search(), InvalidSubTransactionId, lappend(), lcons(), lfirst, list_free(), NIL, RelationData::rd_createSubid, RelationData::rd_firstRelfilenodeSubid, RelationData::rd_isnailed, RelationClearRelation(), RelationCloseSmgr, RelationGetRelid, RelationHasReferenceCountZero, RelationInitPhysicalAddr(), RelationIsMapped, RelationMapInvalidateAll(), relcacheInvalsReceived, relidcacheent::reldesc, smgrcloseall(), and status().

Referenced by InvalidateSystemCaches(), and LocalExecuteInvalidationMessage().

2845 {
2847  RelIdCacheEnt *idhentry;
2848  Relation relation;
2849  List *rebuildFirstList = NIL;
2850  List *rebuildList = NIL;
2851  ListCell *l;
2852 
2853  /*
2854  * Reload relation mapping data before starting to reconstruct cache.
2855  */
2857 
2858  /* Phase 1 */
2859  hash_seq_init(&status, RelationIdCache);
2860 
2861  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2862  {
2863  relation = idhentry->reldesc;
2864 
2865  /* Must close all smgr references to avoid leaving dangling ptrs */
2866  RelationCloseSmgr(relation);
2867 
2868  /*
2869  * Ignore new relations; no other backend will manipulate them before
2870  * we commit. Likewise, before replacing a relation's relfilenode, we
2871  * shall have acquired AccessExclusiveLock and drained any applicable
2872  * pending invalidations.
2873  */
2874  if (relation->rd_createSubid != InvalidSubTransactionId ||
2876  continue;
2877 
2879 
2880  if (RelationHasReferenceCountZero(relation))
2881  {
2882  /* Delete this entry immediately */
2883  Assert(!relation->rd_isnailed);
2884  RelationClearRelation(relation, false);
2885  }
2886  else
2887  {
2888  /*
2889  * If it's a mapped relation, immediately update its rd_node in
2890  * case its relfilenode changed. We must do this during phase 1
2891  * in case the relation is consulted during rebuild of other
2892  * relcache entries in phase 2. It's safe since consulting the
2893  * map doesn't involve any access to relcache entries.
2894  */
2895  if (RelationIsMapped(relation))
2896  RelationInitPhysicalAddr(relation);
2897 
2898  /*
2899  * Add this entry to list of stuff to rebuild in second pass.
2900  * pg_class goes to the front of rebuildFirstList while
2901  * pg_class_oid_index goes to the back of rebuildFirstList, so
2902  * they are done first and second respectively. Other nailed
2903  * relations go to the front of rebuildList, so they'll be done
2904  * next in no particular order; and everything else goes to the
2905  * back of rebuildList.
2906  */
2907  if (RelationGetRelid(relation) == RelationRelationId)
2908  rebuildFirstList = lcons(relation, rebuildFirstList);
2909  else if (RelationGetRelid(relation) == ClassOidIndexId)
2910  rebuildFirstList = lappend(rebuildFirstList, relation);
2911  else if (relation->rd_isnailed)
2912  rebuildList = lcons(relation, rebuildList);
2913  else
2914  rebuildList = lappend(rebuildList, relation);
2915  }
2916  }
2917 
2918  /*
2919  * Now zap any remaining smgr cache entries. This must happen before we
2920  * start to rebuild entries, since that may involve catalog fetches which
2921  * will re-open catalog files.
2922  */
2923  smgrcloseall();
2924 
2925  /* Phase 2: rebuild the items found to need rebuild in phase 1 */
2926  foreach(l, rebuildFirstList)
2927  {
2928  relation = (Relation) lfirst(l);
2929  RelationClearRelation(relation, true);
2930  }
2931  list_free(rebuildFirstList);
2932  foreach(l, rebuildList)
2933  {
2934  relation = (Relation) lfirst(l);
2935  RelationClearRelation(relation, true);
2936  }
2937  list_free(rebuildList);
2938 }
#define NIL
Definition: pg_list.h:65
static long relcacheInvalsReceived
Definition: relcache.c:152
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2444
bool rd_isnailed
Definition: rel.h:61
Relation reldesc
Definition: relcache.c:129
#define RelationCloseSmgr(relation)
Definition: rel.h:526
static HTAB * RelationIdCache
Definition: relcache.c:132
#define ClassOidIndexId
Definition: pg_class.h:156
void smgrcloseall(void)
Definition: smgr.c:286
struct RelationData * Relation
Definition: relcache.h:27
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1279
List * lappend(List *list, void *datum)
Definition: list.c:336
#define RelationIsMapped(relation)
Definition: rel.h:506
SubTransactionId rd_createSubid
Definition: rel.h:103
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:106
List * lcons(void *datum, List *list)
Definition: list.c:468
#define Assert(condition)
Definition: c.h:792
#define lfirst(lc)
Definition: pg_list.h:169
#define InvalidSubTransactionId
Definition: c.h:581
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1436
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1426
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:441
void list_free(List *list)
Definition: list.c:1391
void RelationMapInvalidateAll(void)
Definition: relmapper.c:425
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:457

◆ RelationCacheInvalidateEntry()

void RelationCacheInvalidateEntry ( Oid  relationId)

Definition at line 2801 of file relcache.c.

References PointerIsValid, RelationFlushRelation(), RelationIdCacheLookup, and relcacheInvalsReceived.

Referenced by LocalExecuteInvalidationMessage().

2802 {
2803  Relation relation;
2804 
2805  RelationIdCacheLookup(relationId, relation);
2806 
2807  if (PointerIsValid(relation))
2808  {
2810  RelationFlushRelation(relation);
2811  }
2812 }
static long relcacheInvalsReceived
Definition: relcache.c:152
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:211
static void RelationFlushRelation(Relation relation)
Definition: relcache.c:2724
#define PointerIsValid(pointer)
Definition: c.h:686

◆ RelationClose()

void RelationClose ( Relation  relation)

Definition at line 2123 of file relcache.c.

References MemoryContextData::firstchild, InvalidSubTransactionId, MemoryContextDeleteChildren(), RelationData::rd_createSubid, RelationData::rd_firstRelfilenodeSubid, RelationData::rd_pdcxt, RelationClearRelation(), RelationDecrementReferenceCount(), and RelationHasReferenceCountZero.

Referenced by index_close(), maybe_send_schema(), pgoutput_change(), relation_close(), RememberToFreeTupleDescAtEOX(), ReorderBufferProcessTXN(), ReorderBufferToastReplace(), and ResourceOwnerReleaseInternal().

2124 {
2125  /* Note: no locking manipulations needed */
2127 
2128  /*
2129  * If the relation is no longer open in this session, we can clean up any
2130  * stale partition descriptors it has. This is unlikely, so check to see
2131  * if there are child contexts before expending a call to mcxt.c.
2132  */
2133  if (RelationHasReferenceCountZero(relation) &&
2134  relation->rd_pdcxt != NULL &&
2135  relation->rd_pdcxt->firstchild != NULL)
2137 
2138 #ifdef RELCACHE_FORCE_RELEASE
2139  if (RelationHasReferenceCountZero(relation) &&
2140  relation->rd_createSubid == InvalidSubTransactionId &&
2142  RelationClearRelation(relation, false);
2143 #endif
2144 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2444
MemoryContext firstchild
Definition: memnodes.h:85
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2103
SubTransactionId rd_createSubid
Definition: rel.h:103
void MemoryContextDeleteChildren(MemoryContext context)
Definition: mcxt.c:257
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:106
MemoryContext rd_pdcxt
Definition: rel.h:130
#define InvalidSubTransactionId
Definition: c.h:581
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:441

◆ RelationCloseSmgrByOid()

void RelationCloseSmgrByOid ( Oid  relationId)

Definition at line 2947 of file relcache.c.

References PointerIsValid, RelationCloseSmgr, and RelationIdCacheLookup.

Referenced by swap_relation_files().

2948 {
2949  Relation relation;
2950 
2951  RelationIdCacheLookup(relationId, relation);
2952 
2953  if (!PointerIsValid(relation))
2954  return; /* not in cache, nothing to do */
2955 
2956  RelationCloseSmgr(relation);
2957 }
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:211
#define RelationCloseSmgr(relation)
Definition: rel.h:526
#define PointerIsValid(pointer)
Definition: c.h:686

◆ RelationForgetRelation()

void RelationForgetRelation ( Oid  rid)

Definition at line 2757 of file relcache.c.

References Assert, elog, ERROR, GetCurrentSubTransactionId(), InvalidSubTransactionId, PointerIsValid, RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_firstRelfilenodeSubid, RelationClearRelation(), RelationHasReferenceCountZero, and RelationIdCacheLookup.

Referenced by heap_drop_with_catalog(), and index_drop().

2758 {
2759  Relation relation;
2760 
2761  RelationIdCacheLookup(rid, relation);
2762 
2763  if (!PointerIsValid(relation))
2764  return; /* not in cache, nothing to do */
2765 
2766  if (!RelationHasReferenceCountZero(relation))
2767  elog(ERROR, "relation %u is still open", rid);
2768 
2770  if (relation->rd_createSubid != InvalidSubTransactionId ||
2772  {
2773  /*
2774  * In the event of subtransaction rollback, we must not forget
2775  * rd_*Subid. Mark the entry "dropped" so RelationClearRelation()
2776  * invalidates it in lieu of destroying it. (If we're in a top
2777  * transaction, we could opt to destroy the entry.)
2778  */
2780  }
2781 
2782  RelationClearRelation(relation, false);
2783 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2444
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:211
#define ERROR
Definition: elog.h:45
SubTransactionId rd_createSubid
Definition: rel.h:103
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:106
#define Assert(condition)
Definition: c.h:792
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:723
#define InvalidSubTransactionId
Definition: c.h:581
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:441
#define elog(elevel,...)
Definition: elog.h:228
#define PointerIsValid(pointer)
Definition: c.h:686
SubTransactionId rd_droppedSubid
Definition: rel.h:108

◆ RelationGetDummyIndexExpressions()

List* RelationGetDummyIndexExpressions ( Relation  relation)

Definition at line 4819 of file relcache.c.

References Assert, exprCollation(), exprType(), exprTypmod(), GetPgIndexDescriptor(), heap_attisnull(), heap_getattr, lappend(), lfirst, makeConst(), NIL, pfree(), RelationData::rd_indextuple, stringToNode(), and TextDatumGetCString.

Referenced by BuildDummyIndexInfo().

4820 {
4821  List *result;
4822  Datum exprsDatum;
4823  bool isnull;
4824  char *exprsString;
4825  List *rawExprs;
4826  ListCell *lc;
4827 
4828  /* Quick exit if there is nothing to do. */
4829  if (relation->rd_indextuple == NULL ||
4830  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indexprs, NULL))
4831  return NIL;
4832 
4833  /* Extract raw node tree(s) from index tuple. */
4834  exprsDatum = heap_getattr(relation->rd_indextuple,
4835  Anum_pg_index_indexprs,
4837  &isnull);
4838  Assert(!isnull);
4839  exprsString = TextDatumGetCString(exprsDatum);
4840  rawExprs = (List *) stringToNode(exprsString);
4841  pfree(exprsString);
4842 
4843  /* Construct null Consts; the typlen and typbyval are arbitrary. */
4844  result = NIL;
4845  foreach(lc, rawExprs)
4846  {
4847  Node *rawExpr = (Node *) lfirst(lc);
4848 
4849  result = lappend(result,
4850  makeConst(exprType(rawExpr),
4851  exprTypmod(rawExpr),
4852  exprCollation(rawExpr),
4853  1,
4854  (Datum) 0,
4855  true,
4856  true));
4857  }
4858 
4859  return result;
4860 }
#define NIL
Definition: pg_list.h:65
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:267
Definition: nodes.h:528
void * stringToNode(const char *str)
Definition: read.c:89
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:299
struct HeapTupleData * rd_indextuple
Definition: rel.h:177
void pfree(void *pointer)
Definition: mcxt.c:1057
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4237
List * lappend(List *list, void *datum)
Definition: list.c:336
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:792
#define lfirst(lc)
Definition: pg_list.h:169
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:759
Definition: pg_list.h:50

◆ RelationGetExclusionInfo()

void RelationGetExclusionInfo ( Relation  indexRelation,
Oid **  operators,
Oid **  procs,
uint16 **  strategies 
)

Definition at line 5194 of file relcache.c.

References AccessShareLock, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, BTEqualStrategyNumber, ConstraintRelidTypidNameIndexId, DatumGetArrayTypeP, elog, ERROR, fastgetattr, get_op_opfamily_strategy(), get_opcode(), GETSTRUCT, HeapTupleIsValid, i, IndexRelationGetNumberOfKeyAttributes, InvalidStrategy, MemoryContextSwitchTo(), ObjectIdGetDatum, palloc(), RelationData::rd_att, RelationData::rd_exclops, RelationData::rd_exclprocs, RelationData::rd_exclstrats, RelationData::rd_index, RelationData::rd_indexcxt, RelationData::rd_opfamily, RelationGetRelationName, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), and val.

Referenced by BuildIndexInfo(), and CheckIndexCompatible().

5198 {
5199  int indnkeyatts;
5200  Oid *ops;
5201  Oid *funcs;
5202  uint16 *strats;
5203  Relation conrel;
5204  SysScanDesc conscan;
5205  ScanKeyData skey[1];
5206  HeapTuple htup;
5207  bool found;
5208  MemoryContext oldcxt;
5209  int i;
5210 
5211  indnkeyatts = IndexRelationGetNumberOfKeyAttributes(indexRelation);
5212 
5213  /* Allocate result space in caller context */
5214  *operators = ops = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5215  *procs = funcs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5216  *strategies = strats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
5217 
5218  /* Quick exit if we have the data cached already */
5219  if (indexRelation->rd_exclstrats != NULL)
5220  {
5221  memcpy(ops, indexRelation->rd_exclops, sizeof(Oid) * indnkeyatts);
5222  memcpy(funcs, indexRelation->rd_exclprocs, sizeof(Oid) * indnkeyatts);
5223  memcpy(strats, indexRelation->rd_exclstrats, sizeof(uint16) * indnkeyatts);
5224  return;
5225  }
5226 
5227  /*
5228  * Search pg_constraint for the constraint associated with the index. To
5229  * make this not too painfully slow, we use the index on conrelid; that
5230  * will hold the parent relation's OID not the index's own OID.
5231  *
5232  * Note: if we wanted to rely on the constraint name matching the index's
5233  * name, we could just do a direct lookup using pg_constraint's unique
5234  * index. For the moment it doesn't seem worth requiring that.
5235  */
5236  ScanKeyInit(&skey[0],
5237  Anum_pg_constraint_conrelid,
5238  BTEqualStrategyNumber, F_OIDEQ,
5239  ObjectIdGetDatum(indexRelation->rd_index->indrelid));
5240 
5241  conrel = table_open(ConstraintRelationId, AccessShareLock);
5242  conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
5243  NULL, 1, skey);
5244  found = false;
5245 
5246  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
5247  {
5249  Datum val;
5250  bool isnull;
5251  ArrayType *arr;
5252  int nelem;
5253 
5254  /* We want the exclusion constraint owning the index */
5255  if (conform->contype != CONSTRAINT_EXCLUSION ||
5256  conform->conindid != RelationGetRelid(indexRelation))
5257  continue;
5258 
5259  /* There should be only one */
5260  if (found)
5261  elog(ERROR, "unexpected exclusion constraint record found for rel %s",
5262  RelationGetRelationName(indexRelation));
5263  found = true;
5264 
5265  /* Extract the operator OIDS from conexclop */
5266  val = fastgetattr(htup,
5267  Anum_pg_constraint_conexclop,
5268  conrel->rd_att, &isnull);
5269  if (isnull)
5270  elog(ERROR, "null conexclop for rel %s",
5271  RelationGetRelationName(indexRelation));
5272 
5273  arr = DatumGetArrayTypeP(val); /* ensure not toasted */
5274  nelem = ARR_DIMS(arr)[0];
5275  if (ARR_NDIM(arr) != 1 ||
5276  nelem != indnkeyatts ||
5277  ARR_HASNULL(arr) ||
5278  ARR_ELEMTYPE(arr) != OIDOID)
5279  elog(ERROR, "conexclop is not a 1-D Oid array");
5280 
5281  memcpy(ops, ARR_DATA_PTR(arr), sizeof(Oid) * indnkeyatts);
5282  }
5283 
5284  systable_endscan(conscan);
5285  table_close(conrel, AccessShareLock);
5286 
5287  if (!found)
5288  elog(ERROR, "exclusion constraint record missing for rel %s",
5289  RelationGetRelationName(indexRelation));
5290 
5291  /* We need the func OIDs and strategy numbers too */
5292  for (i = 0; i < indnkeyatts; i++)
5293  {
5294  funcs[i] = get_opcode(ops[i]);
5295  strats[i] = get_op_opfamily_strategy(ops[i],
5296  indexRelation->rd_opfamily[i]);
5297  /* shouldn't fail, since it was checked at index creation */
5298  if (strats[i] == InvalidStrategy)
5299  elog(ERROR, "could not find strategy for operator %u in family %u",
5300  ops[i], indexRelation->rd_opfamily[i]);
5301  }
5302 
5303  /* Save a copy of the results in the relcache entry. */
5304  oldcxt = MemoryContextSwitchTo(indexRelation->rd_indexcxt);
5305  indexRelation->rd_exclops = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5306  indexRelation->rd_exclprocs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5307  indexRelation->rd_exclstrats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
5308  memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * indnkeyatts);
5309  memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * indnkeyatts);
5310  memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * indnkeyatts);
5311  MemoryContextSwitchTo(oldcxt);
5312 }
#define InvalidStrategy
Definition: stratnum.h:24
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:593
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:712
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
uint16 * rd_exclstrats
Definition: rel.h:199
#define AccessShareLock
Definition: lockdefs.h:36
Oid * rd_exclprocs
Definition: rel.h:198
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:381
Form_pg_index rd_index
Definition: rel.h:175
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:500
unsigned short uint16
Definition: c.h:428
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
#define ARR_DIMS(a)
Definition: array.h:287
#define ConstraintRelidTypidNameIndexId
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define RelationGetRelationName(relation)
Definition: rel.h:491
#define ARR_HASNULL(a)
Definition: array.h:284
Oid * rd_opfamily
Definition: rel.h:190
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition: rel.h:476
Oid * rd_exclops
Definition: rel.h:197
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:111
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1229
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define ARR_NDIM(a)
Definition: array.h:283
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition: lsyscache.c:81
void * palloc(Size size)
Definition: mcxt.c:950
#define elog(elevel,...)
Definition: elog.h:228
MemoryContext rd_indexcxt
Definition: rel.h:187
int i
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ARR_ELEMTYPE(a)
Definition: array.h:285
#define RelationGetRelid(relation)
Definition: rel.h:457
long val
Definition: informix.c:664
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define DatumGetArrayTypeP(X)
Definition: array.h:254

◆ RelationGetFKeyList()

List* RelationGetFKeyList ( Relation  relation)

Definition at line 4417 of file relcache.c.

References AccessShareLock, BTEqualStrategyNumber, CacheMemoryContext, ForeignKeyCacheInfo::confkey, ForeignKeyCacheInfo::confrelid, ForeignKeyCacheInfo::conkey, ForeignKeyCacheInfo::conoid, ForeignKeyCacheInfo::conpfeqop, ForeignKeyCacheInfo::conrelid, ConstraintRelidTypidNameIndexId, copyObject, DeconstructFkConstraintRow(), GETSTRUCT, HeapTupleIsValid, lappend(), list_free_deep(), makeNode, MemoryContextSwitchTo(), NIL, ForeignKeyCacheInfo::nkeys, ObjectIdGetDatum, RelationData::rd_fkeylist, RelationData::rd_fkeyvalid, RelationData::rd_rel, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by addFkRecurseReferencing(), ATExecDetachPartition(), CloneFkReferencing(), and get_relation_foreign_keys().

4418 {
4419  List *result;
4420  Relation conrel;
4421  SysScanDesc conscan;
4422  ScanKeyData skey;
4423  HeapTuple htup;
4424  List *oldlist;
4425  MemoryContext oldcxt;
4426 
4427  /* Quick exit if we already computed the list. */
4428  if (relation->rd_fkeyvalid)
4429  return relation->rd_fkeylist;
4430 
4431  /* Fast path: non-partitioned tables without triggers can't have FKs */
4432  if (!relation->rd_rel->relhastriggers &&
4433  relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
4434  return NIL;
4435 
4436  /*
4437  * We build the list we intend to return (in the caller's context) while
4438  * doing the scan. After successfully completing the scan, we copy that
4439  * list into the relcache entry. This avoids cache-context memory leakage
4440  * if we get some sort of error partway through.
4441  */
4442  result = NIL;
4443 
4444  /* Prepare to scan pg_constraint for entries having conrelid = this rel. */
4445  ScanKeyInit(&skey,
4446  Anum_pg_constraint_conrelid,
4447  BTEqualStrategyNumber, F_OIDEQ,
4448  ObjectIdGetDatum(RelationGetRelid(relation)));
4449 
4450  conrel = table_open(ConstraintRelationId, AccessShareLock);
4451  conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
4452  NULL, 1, &skey);
4453 
4454  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4455  {
4456  Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(htup);
4457  ForeignKeyCacheInfo *info;
4458 
4459  /* consider only foreign keys */
4460  if (constraint->contype != CONSTRAINT_FOREIGN)
4461  continue;
4462 
4463  info = makeNode(ForeignKeyCacheInfo);
4464  info->conoid = constraint->oid;
4465  info->conrelid = constraint->conrelid;
4466  info->confrelid = constraint->confrelid;
4467 
4468  DeconstructFkConstraintRow(htup, &info->nkeys,
4469  info->conkey,
4470  info->confkey,
4471  info->conpfeqop,
4472  NULL, NULL);
4473 
4474  /* Add FK's node to the result list */
4475  result = lappend(result, info);
4476  }
4477 
4478  systable_endscan(conscan);
4479  table_close(conrel, AccessShareLock);
4480 
4481  /* Now save a copy of the completed list in the relcache entry. */
4483  oldlist = relation->rd_fkeylist;
4484  relation->rd_fkeylist = copyObject(result);
4485  relation->rd_fkeyvalid = true;
4486  MemoryContextSwitchTo(oldcxt);
4487 
4488  /* Don't leak the old list, if there is one */
4489  list_free_deep(oldlist);
4490 
4491  return result;
4492 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:593
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void DeconstructFkConstraintRow(HeapTuple tuple, int *numfks, AttrNumber *conkey, AttrNumber *confkey, Oid *pf_eq_oprs, Oid *pp_eq_oprs, Oid *ff_eq_oprs)
AttrNumber conkey[INDEX_MAX_KEYS]
Definition: rel.h:263
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
List * rd_fkeylist
Definition: rel.h:121
Form_pg_class rd_rel
Definition: rel.h:110
void list_free_deep(List *list)
Definition: list.c:1405
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:381
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:500
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ConstraintRelidTypidNameIndexId
List * lappend(List *list, void *datum)
Definition: list.c:336
#define makeNode(_type_)
Definition: nodes.h:576
Oid conpfeqop[INDEX_MAX_KEYS]
Definition: rel.h:265
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
AttrNumber confkey[INDEX_MAX_KEYS]
Definition: rel.h:264
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define copyObject(obj)
Definition: nodes.h:644
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
bool rd_fkeyvalid
Definition: rel.h:122
#define RelationGetRelid(relation)
Definition: rel.h:457
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationGetIndexAttOptions()

bytea** RelationGetIndexAttOptions ( Relation  relation,
bool  copy 
)

Definition at line 5448 of file relcache.c.

References AttributeRelidNumIndexId, CopyIndexAttOptions(), criticalRelcachesBuilt, DatumGetPointer, get_attoptions(), i, index_opclass_options(), MemoryContextSwitchTo(), palloc0(), pfree(), RelationData::rd_indexcxt, RelationData::rd_opcoptions, RelationGetNumberOfAttributes, and RelationGetRelid.

Referenced by get_relation_info(), index_getprocinfo(), load_critical_index(), and RelationInitIndexAccessInfo().

5449 {
5450  MemoryContext oldcxt;
5451  bytea **opts = relation->rd_opcoptions;
5452  Oid relid = RelationGetRelid(relation);
5453  int natts = RelationGetNumberOfAttributes(relation); /* XXX
5454  * IndexRelationGetNumberOfKeyAttributes */
5455  int i;
5456 
5457  /* Try to copy cached options. */
5458  if (opts)
5459  return copy ? CopyIndexAttOptions(opts, natts) : opts;
5460 
5461  /* Get and parse opclass options. */
5462  opts = palloc0(sizeof(*opts) * natts);
5463 
5464  for (i = 0; i < natts; i++)
5465  {
5467  {
5468  Datum attoptions = get_attoptions(relid, i + 1);
5469 
5470  opts[i] = index_opclass_options(relation, i + 1, attoptions, false);
5471 
5472  if (attoptions != (Datum) 0)
5473  pfree(DatumGetPointer(attoptions));
5474  }
5475  }
5476 
5477  /* Copy parsed options to the cache. */
5478  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
5479  relation->rd_opcoptions = CopyIndexAttOptions(opts, natts);
5480  MemoryContextSwitchTo(oldcxt);
5481 
5482  if (copy)
5483  return opts;
5484 
5485  for (i = 0; i < natts; i++)
5486  {
5487  if (opts[i])
5488  pfree(opts[i]);
5489  }
5490 
5491  pfree(opts);
5492 
5493  return relation->rd_opcoptions;
5494 }
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:463
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bytea ** rd_opcoptions
Definition: rel.h:201
unsigned int Oid
Definition: postgres_ext.h:31
Datum get_attoptions(Oid relid, int16 attnum)
Definition: lsyscache.c:968
void pfree(void *pointer)
Definition: mcxt.c:1057
#define AttributeRelidNumIndexId
Definition: pg_attribute.h:198
static bytea ** CopyIndexAttOptions(bytea **srcopts, int natts)
Definition: relcache.c:5428
bytea * index_opclass_options(Relation indrel, AttrNumber attnum, Datum attoptions, bool validate)
Definition: indexam.c:939
void * palloc0(Size size)
Definition: mcxt.c:981
uintptr_t Datum
Definition: postgres.h:367
#define DatumGetPointer(X)
Definition: postgres.h:549
MemoryContext rd_indexcxt
Definition: rel.h:187
int i
Definition: c.h:609
bool criticalRelcachesBuilt
Definition: relcache.c:138
#define RelationGetRelid(relation)
Definition: rel.h:457

◆ RelationGetIndexAttrBitmap()

Bitmapset* RelationGetIndexAttrBitmap ( Relation  relation,
IndexAttrBitmapKind  attrKind 
)

Definition at line 4956 of file relcache.c.

References AccessShareLock, bms_add_member(), bms_copy(), bms_free(), CacheMemoryContext, elog, equal(), ERROR, FirstLowInvalidHeapAttributeNumber, GetPgIndexDescriptor(), heap_getattr, i, INDEX_ATTR_BITMAP_ALL, INDEX_ATTR_BITMAP_IDENTITY_KEY, INDEX_ATTR_BITMAP_KEY, INDEX_ATTR_BITMAP_PRIMARY_KEY, index_close(), index_open(), lfirst_oid, list_free(), MemoryContextSwitchTo(), NIL, pull_varattnos(), RelationData::rd_idattr, RelationData::rd_index, RelationData::rd_indexattr, RelationData::rd_indextuple, RelationData::rd_keyattr, RelationData::rd_pkattr, RelationData::rd_pkindex, RelationData::rd_replidindex, RelationGetForm, RelationGetIndexList(), stringToNode(), and TextDatumGetCString.

Referenced by ExecUpdateLockMode(), ExtractReplicaIdentity(), GetParentedForeignKeyRefs(), heap_update(), logicalrep_rel_open(), and logicalrep_write_attrs().

4957 {
4958  Bitmapset *indexattrs; /* indexed columns */
4959  Bitmapset *uindexattrs; /* columns in unique indexes */
4960  Bitmapset *pkindexattrs; /* columns in the primary index */
4961  Bitmapset *idindexattrs; /* columns in the replica identity */
4962  List *indexoidlist;
4963  List *newindexoidlist;
4964  Oid relpkindex;
4965  Oid relreplindex;
4966  ListCell *l;
4967  MemoryContext oldcxt;
4968 
4969  /* Quick exit if we already computed the result. */
4970  if (relation->rd_indexattr != NULL)
4971  {
4972  switch (attrKind)
4973  {
4974  case INDEX_ATTR_BITMAP_ALL:
4975  return bms_copy(relation->rd_indexattr);
4976  case INDEX_ATTR_BITMAP_KEY:
4977  return bms_copy(relation->rd_keyattr);
4979  return bms_copy(relation->rd_pkattr);
4981  return bms_copy(relation->rd_idattr);
4982  default:
4983  elog(ERROR, "unknown attrKind %u", attrKind);
4984  }
4985  }
4986 
4987  /* Fast path if definitely no indexes */
4988  if (!RelationGetForm(relation)->relhasindex)
4989  return NULL;
4990 
4991  /*
4992  * Get cached list of index OIDs. If we have to start over, we do so here.
4993  */
4994 restart:
4995  indexoidlist = RelationGetIndexList(relation);
4996 
4997  /* Fall out if no indexes (but relhasindex was set) */
4998  if (indexoidlist == NIL)
4999  return NULL;
5000 
5001  /*
5002  * Copy the rd_pkindex and rd_replidindex values computed by
5003  * RelationGetIndexList before proceeding. This is needed because a
5004  * relcache flush could occur inside index_open below, resetting the
5005  * fields managed by RelationGetIndexList. We need to do the work with
5006  * stable values of these fields.
5007  */
5008  relpkindex = relation->rd_pkindex;
5009  relreplindex = relation->rd_replidindex;
5010 
5011  /*
5012  * For each index, add referenced attributes to indexattrs.
5013  *
5014  * Note: we consider all indexes returned by RelationGetIndexList, even if
5015  * they are not indisready or indisvalid. This is important because an
5016  * index for which CREATE INDEX CONCURRENTLY has just started must be
5017  * included in HOT-safety decisions (see README.HOT). If a DROP INDEX
5018  * CONCURRENTLY is far enough along that we should ignore the index, it
5019  * won't be returned at all by RelationGetIndexList.
5020  */
5021  indexattrs = NULL;
5022  uindexattrs = NULL;
5023  pkindexattrs = NULL;
5024  idindexattrs = NULL;
5025  foreach(l, indexoidlist)
5026  {
5027  Oid indexOid = lfirst_oid(l);
5028  Relation indexDesc;
5029  Datum datum;
5030  bool isnull;
5031  Node *indexExpressions;
5032  Node *indexPredicate;
5033  int i;
5034  bool isKey; /* candidate key */
5035  bool isPK; /* primary key */
5036  bool isIDKey; /* replica identity index */
5037 
5038  indexDesc = index_open(indexOid, AccessShareLock);
5039 
5040  /*
5041  * Extract index expressions and index predicate. Note: Don't use
5042  * RelationGetIndexExpressions()/RelationGetIndexPredicate(), because
5043  * those might run constant expressions evaluation, which needs a
5044  * snapshot, which we might not have here. (Also, it's probably more
5045  * sound to collect the bitmaps before any transformations that might
5046  * eliminate columns, but the practical impact of this is limited.)
5047  */
5048 
5049  datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indexprs,
5050  GetPgIndexDescriptor(), &isnull);
5051  if (!isnull)
5052  indexExpressions = stringToNode(TextDatumGetCString(datum));
5053  else
5054  indexExpressions = NULL;
5055 
5056  datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indpred,
5057  GetPgIndexDescriptor(), &isnull);
5058  if (!isnull)
5059  indexPredicate = stringToNode(TextDatumGetCString(datum));
5060  else
5061  indexPredicate = NULL;
5062 
5063  /* Can this index be referenced by a foreign key? */
5064  isKey = indexDesc->rd_index->indisunique &&
5065  indexExpressions == NULL &&
5066  indexPredicate == NULL;
5067 
5068  /* Is this a primary key? */
5069  isPK = (indexOid == relpkindex);
5070 
5071  /* Is this index the configured (or default) replica identity? */
5072  isIDKey = (indexOid == relreplindex);
5073 
5074  /* Collect simple attribute references */
5075  for (i = 0; i < indexDesc->rd_index->indnatts; i++)
5076  {
5077  int attrnum = indexDesc->rd_index->indkey.values[i];
5078 
5079  /*
5080  * Since we have covering indexes with non-key columns, we must
5081  * handle them accurately here. non-key columns must be added into
5082  * indexattrs, since they are in index, and HOT-update shouldn't
5083  * miss them. Obviously, non-key columns couldn't be referenced by
5084  * foreign key or identity key. Hence we do not include them into
5085  * uindexattrs, pkindexattrs and idindexattrs bitmaps.
5086  */
5087  if (attrnum != 0)
5088  {
5089  indexattrs = bms_add_member(indexattrs,
5091 
5092  if (isKey && i < indexDesc->rd_index->indnkeyatts)
5093  uindexattrs = bms_add_member(uindexattrs,
5095 
5096  if (isPK && i < indexDesc->rd_index->indnkeyatts)
5097  pkindexattrs = bms_add_member(pkindexattrs,
5099 
5100  if (isIDKey && i < indexDesc->rd_index->indnkeyatts)
5101  idindexattrs = bms_add_member(idindexattrs,
5103  }
5104  }
5105 
5106  /* Collect all attributes used in expressions, too */
5107  pull_varattnos(indexExpressions, 1, &indexattrs);
5108 
5109  /* Collect all attributes in the index predicate, too */
5110  pull_varattnos(indexPredicate, 1, &indexattrs);
5111 
5112  index_close(indexDesc, AccessShareLock);
5113  }
5114 
5115  /*
5116  * During one of the index_opens in the above loop, we might have received
5117  * a relcache flush event on this relcache entry, which might have been
5118  * signaling a change in the rel's index list. If so, we'd better start
5119  * over to ensure we deliver up-to-date attribute bitmaps.
5120  */
5121  newindexoidlist = RelationGetIndexList(relation);
5122  if (equal(indexoidlist, newindexoidlist) &&
5123  relpkindex == relation->rd_pkindex &&
5124  relreplindex == relation->rd_replidindex)
5125  {
5126  /* Still the same index set, so proceed */
5127  list_free(newindexoidlist);
5128  list_free(indexoidlist);
5129  }
5130  else
5131  {
5132  /* Gotta do it over ... might as well not leak memory */
5133  list_free(newindexoidlist);
5134  list_free(indexoidlist);
5135  bms_free(uindexattrs);
5136  bms_free(pkindexattrs);
5137  bms_free(idindexattrs);
5138  bms_free(indexattrs);
5139 
5140  goto restart;
5141  }
5142 
5143  /* Don't leak the old values of these bitmaps, if any */
5144  bms_free(relation->rd_indexattr);
5145  relation->rd_indexattr = NULL;
5146  bms_free(relation->rd_keyattr);
5147  relation->rd_keyattr = NULL;
5148  bms_free(relation->rd_pkattr);
5149  relation->rd_pkattr = NULL;
5150  bms_free(relation->rd_idattr);
5151  relation->rd_idattr = NULL;
5152 
5153  /*
5154  * Now save copies of the bitmaps in the relcache entry. We intentionally
5155  * set rd_indexattr last, because that's the one that signals validity of
5156  * the values; if we run out of memory before making that copy, we won't
5157  * leave the relcache entry looking like the other ones are valid but
5158  * empty.
5159  */
5161  relation->rd_keyattr = bms_copy(uindexattrs);
5162  relation->rd_pkattr = bms_copy(pkindexattrs);
5163  relation->rd_idattr = bms_copy(idindexattrs);
5164  relation->rd_indexattr = bms_copy(indexattrs);
5165  MemoryContextSwitchTo(oldcxt);
5166 
5167  /* We return our original working copy for caller to play with */
5168  switch (attrKind)
5169  {
5170  case INDEX_ATTR_BITMAP_ALL:
5171  return indexattrs;
5172  case INDEX_ATTR_BITMAP_KEY:
5173  return uindexattrs;
5175  return pkindexattrs;
5177  return idindexattrs;
5178  default:
5179  elog(ERROR, "unknown attrKind %u", attrKind);
5180  return NULL;
5181  }
5182 }
#define NIL
Definition: pg_list.h:65
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:74
Bitmapset * rd_keyattr
Definition: rel.h:147
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3042
Oid rd_replidindex
Definition: rel.h:140
#define RelationGetForm(relation)
Definition: rel.h:451
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:528
void * stringToNode(const char *str)
Definition: read.c:89
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
unsigned int Oid
Definition: postgres_ext.h:31
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition: var.c:246
struct HeapTupleData * rd_indextuple
Definition: rel.h:177
Form_pg_index rd_index
Definition: rel.h:175
#define ERROR
Definition: elog.h:45
Oid rd_pkindex
Definition: rel.h:139
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4237
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:367
Bitmapset * rd_idattr
Definition: rel.h:149
void bms_free(Bitmapset *a)
Definition: bitmapset.c:208
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4526
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:158
Bitmapset * rd_pkattr
Definition: rel.h:148
void list_free(List *list)
Definition: list.c:1391
#define elog(elevel,...)
Definition: elog.h:228
int i
Definition: pg_list.h:50
Bitmapset * rd_indexattr
Definition: rel.h:146
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:132
#define lfirst_oid(lc)
Definition: pg_list.h:171
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationGetIndexExpressions()

List* RelationGetIndexExpressions ( Relation  relation)

Definition at line 4760 of file relcache.c.

References Assert, copyObject, eval_const_expressions(), fix_opfuncids(), GetPgIndexDescriptor(), heap_attisnull(), heap_getattr, MemoryContextSwitchTo(), NIL, pfree(), RelationData::rd_indexcxt, RelationData::rd_indexprs, RelationData::rd_indextuple, stringToNode(), and TextDatumGetCString.

Referenced by ATExecReplicaIdentity(), BuildIndexInfo(), get_relation_info(), index_unchanged_by_update(), infer_arbiter_indexes(), plan_create_index_workers(), and transformIndexConstraint().

4761 {
4762  List *result;
4763  Datum exprsDatum;
4764  bool isnull;
4765  char *exprsString;
4766  MemoryContext oldcxt;
4767 
4768  /* Quick exit if we already computed the result. */
4769  if (relation->rd_indexprs)
4770  return copyObject(relation->rd_indexprs);
4771 
4772  /* Quick exit if there is nothing to do. */
4773  if (relation->rd_indextuple == NULL ||
4774  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indexprs, NULL))
4775  return NIL;
4776 
4777  /*
4778  * We build the tree we intend to return in the caller's context. After
4779  * successfully completing the work, we copy it into the relcache entry.
4780  * This avoids problems if we get some sort of error partway through.
4781  */
4782  exprsDatum = heap_getattr(relation->rd_indextuple,
4783  Anum_pg_index_indexprs,
4785  &isnull);
4786  Assert(!isnull);
4787  exprsString = TextDatumGetCString(exprsDatum);
4788  result = (List *) stringToNode(exprsString);
4789  pfree(exprsString);
4790 
4791  /*
4792  * Run the expressions through eval_const_expressions. This is not just an
4793  * optimization, but is necessary, because the planner will be comparing
4794  * them to similarly-processed qual clauses, and may fail to detect valid
4795  * matches without this. We must not use canonicalize_qual, however,
4796  * since these aren't qual expressions.
4797  */
4798  result = (List *) eval_const_expressions(NULL, (Node *) result);
4799 
4800  /* May as well fix opfuncids too */
4801  fix_opfuncids((Node *) result);
4802 
4803  /* Now save a copy of the completed tree in the relcache entry. */
4804  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4805  relation->rd_indexprs = copyObject(result);
4806  MemoryContextSwitchTo(oldcxt);
4807 
4808  return result;
4809 }
#define NIL
Definition: pg_list.h:65
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1627
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
List * rd_indexprs
Definition: rel.h:195
Definition: nodes.h:528
void * stringToNode(const char *str)
Definition: read.c:89
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2022
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
struct HeapTupleData * rd_indextuple
Definition: rel.h:177
void pfree(void *pointer)
Definition: mcxt.c:1057
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4237
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:792
MemoryContext rd_indexcxt
Definition: rel.h:187
#define copyObject(obj)
Definition: nodes.h:644
Definition: pg_list.h:50

◆ RelationGetIndexList()

List* RelationGetIndexList ( Relation  relation)

Definition at line 4526 of file relcache.c.

References AccessShareLock, BTEqualStrategyNumber, CacheMemoryContext, GETSTRUCT, heap_attisnull(), HeapTupleIsValid, IndexIndrelidIndexId, InvalidOid, lappend_oid(), list_copy(), list_free(), list_oid_cmp(), list_sort(), MemoryContextSwitchTo(), NIL, ObjectIdGetDatum, OidIsValid, RelationData::rd_indexlist, RelationData::rd_indexvalid, RelationData::rd_pkindex, RelationData::rd_rel, RelationData::rd_replidindex, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by AlterIndexNamespaces(), ATExecChangeOwner(), ATExecDetachPartition(), ATExecDropNotNull(), ATExecSetStorage(), ATExecSetTableSpace(), AttachPartitionEnsureIndexes(), calculate_indexes_size(), calculate_toast_table_size(), cluster(), DefineIndex(), DefineRelation(), ExecInitPartitionInfo(), ExecOpenIndices(), ExecRefreshMatView(), expandTableLikeClause(), get_relation_info(), GetParentedForeignKeyRefs(), index_get_partition(), infer_arbiter_indexes(), mark_index_clustered(), refresh_by_match_merge(), reindex_relation(), ReindexRelationConcurrently(), relation_mark_replica_identity(), RelationGetIndexAttrBitmap(), RelationGetPrimaryKeyIndex(), RelationGetReplicaIndex(), relationHasPrimaryKey(), RelationTruncateIndexes(), toast_open_indexes(), transformFkeyCheckAttrs(), transformFkeyGetPrimaryKey(), triggered_change_notification(), and vac_open_indexes().

4527 {
4528  Relation indrel;
4529  SysScanDesc indscan;
4530  ScanKeyData skey;
4531  HeapTuple htup;
4532  List *result;
4533  List *oldlist;
4534  char replident = relation->rd_rel->relreplident;
4535  Oid pkeyIndex = InvalidOid;
4536  Oid candidateIndex = InvalidOid;
4537  MemoryContext oldcxt;
4538 
4539  /* Quick exit if we already computed the list. */
4540  if (relation->rd_indexvalid)
4541  return list_copy(relation->rd_indexlist);
4542 
4543  /*
4544  * We build the list we intend to return (in the caller's context) while
4545  * doing the scan. After successfully completing the scan, we copy that
4546  * list into the relcache entry. This avoids cache-context memory leakage
4547  * if we get some sort of error partway through.
4548  */
4549  result = NIL;
4550 
4551  /* Prepare to scan pg_index for entries having indrelid = this rel. */
4552  ScanKeyInit(&skey,
4553  Anum_pg_index_indrelid,
4554  BTEqualStrategyNumber, F_OIDEQ,
4555  ObjectIdGetDatum(RelationGetRelid(relation)));
4556 
4557  indrel = table_open(IndexRelationId, AccessShareLock);
4558  indscan = systable_beginscan(indrel, IndexIndrelidIndexId, true,
4559  NULL, 1, &skey);
4560 
4561  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4562  {
4564 
4565  /*
4566  * Ignore any indexes that are currently being dropped. This will
4567  * prevent them from being searched, inserted into, or considered in
4568  * HOT-safety decisions. It's unsafe to touch such an index at all
4569  * since its catalog entries could disappear at any instant.
4570  */
4571  if (!index->indislive)
4572  continue;
4573 
4574  /* add index's OID to result list */
4575  result = lappend_oid(result, index->indexrelid);
4576 
4577  /*
4578  * Invalid, non-unique, non-immediate or predicate indexes aren't
4579  * interesting for either oid indexes or replication identity indexes,
4580  * so don't check them.
4581  */
4582  if (!index->indisvalid || !index->indisunique ||
4583  !index->indimmediate ||
4584  !heap_attisnull(htup, Anum_pg_index_indpred, NULL))
4585  continue;
4586 
4587  /* remember primary key index if any */
4588  if (index->indisprimary)
4589  pkeyIndex = index->indexrelid;
4590 
4591  /* remember explicitly chosen replica index */
4592  if (index->indisreplident)
4593  candidateIndex = index->indexrelid;
4594  }
4595 
4596  systable_endscan(indscan);
4597 
4598  table_close(indrel, AccessShareLock);
4599 
4600  /* Sort the result list into OID order, per API spec. */
4601  list_sort(result, list_oid_cmp);
4602 
4603  /* Now save a copy of the completed list in the relcache entry. */
4605  oldlist = relation->rd_indexlist;
4606  relation->rd_indexlist = list_copy(result);
4607  relation->rd_pkindex = pkeyIndex;
4608  if (replident == REPLICA_IDENTITY_DEFAULT && OidIsValid(pkeyIndex))
4609  relation->rd_replidindex = pkeyIndex;
4610  else if (replident == REPLICA_IDENTITY_INDEX && OidIsValid(candidateIndex))
4611  relation->rd_replidindex = candidateIndex;
4612  else
4613  relation->rd_replidindex = InvalidOid;
4614  relation->rd_indexvalid = true;
4615  MemoryContextSwitchTo(oldcxt);
4616 
4617  /* Don't leak the old list, if there is one */
4618  list_free(oldlist);
4619 
4620  return result;
4621 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:593
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid rd_replidindex
Definition: rel.h:140
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
List * list_copy(const List *oldlist)
Definition: list.c:1418
#define IndexIndrelidIndexId
Definition: pg_index.h:71
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
Form_pg_class rd_rel
Definition: rel.h:110
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
#define OidIsValid(objectId)
Definition: c.h:698
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:381
Definition: type.h:89
int list_oid_cmp(const ListCell *p1, const ListCell *p2)
Definition: list.c:1513
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:500
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
Oid rd_pkindex
Definition: rel.h:139
List * rd_indexlist
Definition: rel.h:138
FormData_pg_index * Form_pg_index
Definition: pg_index.h:68
bool rd_indexvalid
Definition: rel.h:63
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void list_sort(List *list, list_sort_comparator cmp)
Definition: list.c:1496
void list_free(List *list)
Definition: list.c:1391
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:457
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationGetIndexPredicate()

List* RelationGetIndexPredicate ( Relation  relation)

Definition at line 4873 of file relcache.c.

References Assert, canonicalize_qual(), copyObject, eval_const_expressions(), fix_opfuncids(), GetPgIndexDescriptor(), heap_attisnull(), heap_getattr, make_ands_implicit(), MemoryContextSwitchTo(), NIL, pfree(), RelationData::rd_indexcxt, RelationData::rd_indextuple, RelationData::rd_indpred, stringToNode(), and TextDatumGetCString.

Referenced by ATExecReplicaIdentity(), BuildIndexInfo(), get_relation_info(), infer_arbiter_indexes(), is_usable_unique_index(), plan_create_index_workers(), and transformIndexConstraint().

4874 {
4875  List *result;
4876  Datum predDatum;
4877  bool isnull;
4878  char *predString;
4879  MemoryContext oldcxt;
4880 
4881  /* Quick exit if we already computed the result. */
4882  if (relation->rd_indpred)
4883  return copyObject(relation->rd_indpred);
4884 
4885  /* Quick exit if there is nothing to do. */
4886  if (relation->rd_indextuple == NULL ||
4887  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indpred, NULL))
4888  return NIL;
4889 
4890  /*
4891  * We build the tree we intend to return in the caller's context. After
4892  * successfully completing the work, we copy it into the relcache entry.
4893  * This avoids problems if we get some sort of error partway through.
4894  */
4895  predDatum = heap_getattr(relation->rd_indextuple,
4896  Anum_pg_index_indpred,
4898  &isnull);
4899  Assert(!isnull);
4900  predString = TextDatumGetCString(predDatum);
4901  result = (List *) stringToNode(predString);
4902  pfree(predString);
4903 
4904  /*
4905  * Run the expression through const-simplification and canonicalization.
4906  * This is not just an optimization, but is necessary, because the planner
4907  * will be comparing it to similarly-processed qual clauses, and may fail
4908  * to detect valid matches without this. This must match the processing
4909  * done to qual clauses in preprocess_expression()! (We can skip the
4910  * stuff involving subqueries, however, since we don't allow any in index
4911  * predicates.)
4912  */
4913  result = (List *) eval_const_expressions(NULL, (Node *) result);
4914 
4915  result = (List *) canonicalize_qual((Expr *) result, false);
4916 
4917  /* Also convert to implicit-AND format */
4918  result = make_ands_implicit((Expr *) result);
4919 
4920  /* May as well fix opfuncids too */
4921  fix_opfuncids((Node *) result);
4922 
4923  /* Now save a copy of the completed tree in the relcache entry. */
4924  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4925  relation->rd_indpred = copyObject(result);
4926  MemoryContextSwitchTo(oldcxt);
4927 
4928  return result;
4929 }
#define NIL
Definition: pg_list.h:65
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1627
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:528
void * stringToNode(const char *str)
Definition: read.c:89
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2022
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
struct HeapTupleData * rd_indextuple
Definition: rel.h:177
void pfree(void *pointer)
Definition: mcxt.c:1057
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4237
Expr * canonicalize_qual(Expr *qual, bool is_check)
Definition: prepqual.c:292
List * rd_indpred
Definition: rel.h:196
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:367
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:719
#define Assert(condition)
Definition: c.h:792
MemoryContext rd_indexcxt
Definition: rel.h:187
#define copyObject(obj)
Definition: nodes.h:644
Definition: pg_list.h:50

◆ RelationGetIndexRawAttOptions()

Datum* RelationGetIndexRawAttOptions ( Relation  relation)

Definition at line 5402 of file relcache.c.

References IndexAmRoutine::amoptsprocnum, attnum, get_attoptions(), index_getprocid(), OidIsValid, options, palloc0(), RelationData::rd_indam, RelationGetNumberOfAttributes, and RelationGetRelid.

Referenced by BuildIndexInfo(), and CheckIndexCompatible().

5403 {
5404  Oid indexrelid = RelationGetRelid(indexrel);
5405  int16 natts = RelationGetNumberOfAttributes(indexrel);
5406  Datum *options = NULL;
5407  int16 attnum;
5408 
5409  for (attnum = 1; attnum <= natts; attnum++)
5410  {
5411  if (indexrel->rd_indam->amoptsprocnum == 0)
5412  continue;
5413 
5414  if (!OidIsValid(index_getprocid(indexrel, attnum,
5415  indexrel->rd_indam->amoptsprocnum)))
5416  continue;
5417 
5418  if (!options)
5419  options = palloc0(sizeof(Datum) * natts);
5420 
5421  options[attnum - 1] = get_attoptions(indexrelid, attnum);
5422  }
5423 
5424  return options;
5425 }
signed short int16
Definition: c.h:416
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:463
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:698
Datum get_attoptions(Oid relid, int16 attnum)
Definition: lsyscache.c:968
static char ** options
void * palloc0(Size size)
Definition: mcxt.c:981
uintptr_t Datum
Definition: postgres.h:367
int16 attnum
Definition: pg_attribute.h:79
#define RelationGetRelid(relation)
Definition: rel.h:457
RegProcedure index_getprocid(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:769

◆ RelationGetPrimaryKeyIndex()

Oid RelationGetPrimaryKeyIndex ( Relation  relation)

Definition at line 4714 of file relcache.c.

References Assert, list_free(), RelationData::rd_indexvalid, RelationData::rd_pkindex, and RelationGetIndexList().

Referenced by build_replindex_scan_key(), and GetRelationIdentityOrPK().

4715 {
4716  List *ilist;
4717 
4718  if (!relation->rd_indexvalid)
4719  {
4720  /* RelationGetIndexList does the heavy lifting. */
4721  ilist = RelationGetIndexList(relation);
4722  list_free(ilist);
4723  Assert(relation->rd_indexvalid);
4724  }
4725 
4726  return relation->rd_pkindex;
4727 }
Oid rd_pkindex
Definition: rel.h:139
bool rd_indexvalid
Definition: rel.h:63
#define Assert(condition)
Definition: c.h:792
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4526
void list_free(List *list)
Definition: list.c:1391
Definition: pg_list.h:50

◆ RelationGetReplicaIndex()

Oid RelationGetReplicaIndex ( Relation  relation)

Definition at line 4735 of file relcache.c.

References Assert, list_free(), RelationData::rd_indexvalid, RelationData::rd_replidindex, and RelationGetIndexList().

Referenced by build_replindex_scan_key(), CheckCmdReplicaIdentity(), GetRelationIdentityOrPK(), and pg_get_replica_identity_index().

4736 {
4737  List *ilist;
4738 
4739  if (!relation->rd_indexvalid)
4740  {
4741  /* RelationGetIndexList does the heavy lifting. */
4742  ilist = RelationGetIndexList(relation);
4743  list_free(ilist);
4744  Assert(relation->rd_indexvalid);
4745  }
4746 
4747  return relation->rd_replidindex;
4748 }
Oid rd_replidindex
Definition: rel.h:140
bool rd_indexvalid
Definition: rel.h:63
#define Assert(condition)
Definition: c.h:792
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4526
void list_free(List *list)
Definition: list.c:1391
Definition: pg_list.h:50

◆ RelationGetStatExtList()

List* RelationGetStatExtList ( Relation  relation)

Definition at line 4645 of file relcache.c.

References AccessShareLock, BTEqualStrategyNumber, CacheMemoryContext, GETSTRUCT, HeapTupleIsValid, lappend_oid(), list_copy(), list_free(), list_oid_cmp(), list_sort(), MemoryContextSwitchTo(), NIL, ObjectIdGetDatum, RelationData::rd_statlist, RelationData::rd_statvalid, RelationGetRelid, ScanKeyInit(), StatisticExtRelidIndexId, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by get_relation_statistics(), and transformTableLikeClause().

4646 {
4647  Relation indrel;
4648  SysScanDesc indscan;
4649  ScanKeyData skey;
4650  HeapTuple htup;
4651  List *result;
4652  List *oldlist;
4653  MemoryContext oldcxt;
4654 
4655  /* Quick exit if we already computed the list. */
4656  if (relation->rd_statvalid != 0)
4657  return list_copy(relation->rd_statlist);
4658 
4659  /*
4660  * We build the list we intend to return (in the caller's context) while
4661  * doing the scan. After successfully completing the scan, we copy that
4662  * list into the relcache entry. This avoids cache-context memory leakage
4663  * if we get some sort of error partway through.
4664  */
4665  result = NIL;
4666 
4667  /*
4668  * Prepare to scan pg_statistic_ext for entries having stxrelid = this
4669  * rel.
4670  */
4671  ScanKeyInit(&skey,
4672  Anum_pg_statistic_ext_stxrelid,
4673  BTEqualStrategyNumber, F_OIDEQ,
4674  ObjectIdGetDatum(RelationGetRelid(relation)));
4675 
4676  indrel = table_open(StatisticExtRelationId, AccessShareLock);
4677  indscan = systable_beginscan(indrel, StatisticExtRelidIndexId, true,
4678  NULL, 1, &skey);
4679 
4680  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4681  {
4682  Oid oid = ((Form_pg_statistic_ext) GETSTRUCT(htup))->oid;
4683 
4684  result = lappend_oid(result, oid);
4685  }
4686 
4687  systable_endscan(indscan);
4688 
4689  table_close(indrel, AccessShareLock);
4690 
4691  /* Sort the result list into OID order, per API spec. */
4692  list_sort(result, list_oid_cmp);
4693 
4694  /* Now save a copy of the completed list in the relcache entry. */
4696  oldlist = relation->rd_statlist;
4697  relation->rd_statlist = list_copy(result);
4698 
4699  relation->rd_statvalid = true;
4700  MemoryContextSwitchTo(oldcxt);
4701 
4702  /* Don't leak the old list, if there is one */
4703  list_free(oldlist);
4704 
4705  return result;
4706 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:593
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
List * list_copy(const List *oldlist)
Definition: list.c:1418
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:381
int list_oid_cmp(const ListCell *p1, const ListCell *p2)
Definition: list.c:1513
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:500
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
bool rd_statvalid
Definition: rel.h:65
void list_sort(List *list, list_sort_comparator cmp)
Definition: list.c:1496
void list_free(List *list)
Definition: list.c:1391
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define StatisticExtRelidIndexId
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
List * rd_statlist
Definition: rel.h:143
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:457
#define BTEqualStrategyNumber
Definition: stratnum.h:31
FormData_pg_statistic_ext * Form_pg_statistic_ext
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationIdGetRelation()

Relation RelationIdGetRelation ( Oid  relationId)

Definition at line 2017 of file relcache.c.

References Assert, criticalRelcachesBuilt, InvalidSubTransactionId, IsTransactionState(), RelationData::rd_droppedSubid, RelationData::rd_isnailed, RelationData::rd_isvalid, RelationData::rd_rel, RelationBuildDesc(), RelationClearRelation(), RelationIdCacheLookup, RelationIncrementReferenceCount(), RelationIsValid, and RelationReloadIndexInfo().

Referenced by maybe_send_schema(), pgoutput_change(), relation_open(), RememberToFreeTupleDescAtEOX(), ReorderBufferProcessTXN(), ReorderBufferToastReplace(), and try_relation_open().

2018 {
2019  Relation rd;
2020 
2021  /* Make sure we're in an xact, even if this ends up being a cache hit */
2023 
2024  /*
2025  * first try to find reldesc in the cache
2026  */
2027  RelationIdCacheLookup(relationId, rd);
2028 
2029  if (RelationIsValid(rd))
2030  {
2031  /* return NULL for dropped relations */
2033  {
2034  Assert(!rd->rd_isvalid);
2035  return NULL;
2036  }
2037 
2039  /* revalidate cache entry if necessary */
2040  if (!rd->rd_isvalid)
2041  {
2042  /*
2043  * Indexes only have a limited number of possible schema changes,
2044  * and we don't want to use the full-blown procedure because it's
2045  * a headache for indexes that reload itself depends on.
2046  */
2047  if (rd->rd_rel->relkind == RELKIND_INDEX ||
2048  rd->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
2050  else
2051  RelationClearRelation(rd, true);
2052 
2053  /*
2054  * Normally entries need to be valid here, but before the relcache
2055  * has been initialized, not enough infrastructure exists to
2056  * perform pg_class lookups. The structure of such entries doesn't
2057  * change, but we still want to update the rd_rel entry. So
2058  * rd_isvalid = false is left in place for a later lookup.
2059  */
2060  Assert(rd->rd_isvalid ||
2062  }
2063  return rd;
2064  }
2065 
2066  /*
2067  * no reldesc in the cache, so have RelationBuildDesc() build one and add
2068  * it.
2069  */
2070  rd = RelationBuildDesc(relationId, true);
2071  if (RelationIsValid(rd))
2073  return rd;
2074 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2444
bool rd_isnailed
Definition: rel.h:61
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:211
bool rd_isvalid
Definition: rel.h:62
Form_pg_class rd_rel
Definition: rel.h:110
#define RelationIsValid(relation)
Definition: rel.h:430
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2090
static void RelationReloadIndexInfo(Relation relation)
Definition: relcache.c:2174
#define Assert(condition)
Definition: c.h:792
static Relation RelationBuildDesc(Oid targetRelId, bool insertIt)
Definition: relcache.c:1029
bool IsTransactionState(void)
Definition: xact.c:371
#define InvalidSubTransactionId
Definition: c.h:581
bool criticalRelcachesBuilt
Definition: relcache.c:138
SubTransactionId rd_droppedSubid
Definition: rel.h:108

◆ RelationIdIsInInitFile()

bool RelationIdIsInInitFile ( Oid  relationId)

Definition at line 6271 of file relcache.c.

References Assert, DatabaseNameIndexId, RelationSupportsSysCache(), SharedSecLabelObjectIndexId, and TriggerRelidNameIndexId.

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

6272 {
6273  if (relationId == SharedSecLabelRelationId ||
6274  relationId == TriggerRelidNameIndexId ||
6275  relationId == DatabaseNameIndexId ||
6276  relationId == SharedSecLabelObjectIndexId)
6277  {
6278  /*
6279  * If this Assert fails, we don't need the applicable special case
6280  * anymore.
6281  */
6282  Assert(!RelationSupportsSysCache(relationId));
6283  return true;
6284  }
6285  return RelationSupportsSysCache(relationId);
6286 }
#define TriggerRelidNameIndexId
Definition: pg_trigger.h:80
#define DatabaseNameIndexId
Definition: pg_database.h:88
#define SharedSecLabelObjectIndexId
Definition: pg_shseclabel.h:46
#define Assert(condition)
Definition: c.h:792
bool RelationSupportsSysCache(Oid relid)
Definition: syscache.c:1532

◆ RelationInitIndexAccessInfo()

void RelationInitIndexAccessInfo ( Relation  relation)

Definition at line 1385 of file relcache.c.

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, AMOID, IndexAmRoutine::amsupport, Assert, CacheMemoryContext, DatumGetPointer, elog, ERROR, fastgetattr, GetPgIndexDescriptor(), GETSTRUCT, heap_copytuple(), HeapTupleIsValid, IndexRelationGetNumberOfAttributes, IndexRelationGetNumberOfKeyAttributes, INDEXRELID, IndexSupportInitialize(), InitIndexAmRoutine(), MemoryContextAllocZero(), MemoryContextCopyAndSetIdentifier, MemoryContextSwitchTo(), NIL, ObjectIdGetDatum, RelationData::rd_amcache, RelationData::rd_amhandler, RelationData::rd_exclops, RelationData::rd_exclprocs, RelationData::rd_exclstrats, RelationData::rd_indam, RelationData::rd_indcollation, RelationData::rd_index, RelationData::rd_indexcxt, RelationData::rd_indexprs, RelationData::rd_indextuple, RelationData::rd_indoption, RelationData::rd_indpred, RelationData::rd_opcintype, RelationData::rd_opfamily, RelationData::rd_rel, RelationData::rd_support, RelationData::rd_supportinfo, RelationGetIndexAttOptions(), RelationGetNumberOfAttributes, RelationGetRelationName, RelationGetRelid, ReleaseSysCache(), SearchSysCache1(), int2vector::values, and oidvector::values.

Referenced by index_create(), and RelationBuildDesc().

1386 {
1387  HeapTuple tuple;
1388  Form_pg_am aform;
1389  Datum indcollDatum;
1390  Datum indclassDatum;
1391  Datum indoptionDatum;
1392  bool isnull;
1393  oidvector *indcoll;
1394  oidvector *indclass;
1395  int2vector *indoption;
1396  MemoryContext indexcxt;
1397  MemoryContext oldcontext;
1398  int indnatts;
1399  int indnkeyatts;
1400  uint16 amsupport;
1401 
1402  /*
1403  * Make a copy of the pg_index entry for the index. Since pg_index
1404  * contains variable-length and possibly-null fields, we have to do this
1405  * honestly rather than just treating it as a Form_pg_index struct.
1406  */
1407  tuple = SearchSysCache1(INDEXRELID,
1408  ObjectIdGetDatum(RelationGetRelid(relation)));
1409  if (!HeapTupleIsValid(tuple))
1410  elog(ERROR, "cache lookup failed for index %u",
1411  RelationGetRelid(relation));
1413  relation->rd_indextuple = heap_copytuple(tuple);
1414  relation->rd_index = (Form_pg_index) GETSTRUCT(relation->rd_indextuple);
1415  MemoryContextSwitchTo(oldcontext);
1416  ReleaseSysCache(tuple);
1417 
1418  /*
1419  * Look up the index's access method, save the OID of its handler function
1420  */
1421  tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(relation->rd_rel->relam));
1422  if (!HeapTupleIsValid(tuple))
1423  elog(ERROR, "cache lookup failed for access method %u",
1424  relation->rd_rel->relam);
1425  aform = (Form_pg_am) GETSTRUCT(tuple);
1426  relation->rd_amhandler = aform->amhandler;
1427  ReleaseSysCache(tuple);
1428 
1429  indnatts = RelationGetNumberOfAttributes(relation);
1430  if (indnatts != IndexRelationGetNumberOfAttributes(relation))
1431  elog(ERROR, "relnatts disagrees with indnatts for index %u",
1432  RelationGetRelid(relation));
1433  indnkeyatts = IndexRelationGetNumberOfKeyAttributes(relation);
1434 
1435  /*
1436  * Make the private context to hold index access info. The reason we need
1437  * a context, and not just a couple of pallocs, is so that we won't leak
1438  * any subsidiary info attached to fmgr lookup records.
1439  */
1441  "index info",
1443  relation->rd_indexcxt = indexcxt;
1445  RelationGetRelationName(relation));
1446 
1447  /*
1448  * Now we can fetch the index AM's API struct
1449  */
1450  InitIndexAmRoutine(relation);
1451 
1452  /*
1453  * Allocate arrays to hold data. Opclasses are not used for included
1454  * columns, so allocate them for indnkeyatts only.
1455  */
1456  relation->rd_opfamily = (Oid *)
1457  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1458  relation->rd_opcintype = (Oid *)
1459  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1460 
1461  amsupport = relation->rd_indam->amsupport;
1462  if (amsupport > 0)
1463  {
1464  int nsupport = indnatts * amsupport;
1465 
1466  relation->rd_support = (RegProcedure *)
1467  MemoryContextAllocZero(indexcxt, nsupport * sizeof(RegProcedure));
1468  relation->rd_supportinfo = (FmgrInfo *)
1469  MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
1470  }
1471  else
1472  {
1473  relation->rd_support = NULL;
1474  relation->rd_supportinfo = NULL;
1475  }
1476 
1477  relation->rd_indcollation = (Oid *)
1478  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1479 
1480  relation->rd_indoption = (int16 *)
1481  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(int16));
1482 
1483  /*
1484  * indcollation cannot be referenced directly through the C struct,
1485  * because it comes after the variable-width indkey field. Must extract
1486  * the datum the hard way...
1487  */
1488  indcollDatum = fastgetattr(relation->rd_indextuple,
1489  Anum_pg_index_indcollation,
1491  &isnull);
1492  Assert(!isnull);
1493  indcoll = (oidvector *) DatumGetPointer(indcollDatum);
1494  memcpy(relation->rd_indcollation, indcoll->values, indnkeyatts * sizeof(Oid));
1495 
1496  /*
1497  * indclass cannot be referenced directly through the C struct, because it
1498  * comes after the variable-width indkey field. Must extract the datum
1499  * the hard way...
1500  */
1501  indclassDatum = fastgetattr(relation->rd_indextuple,
1502  Anum_pg_index_indclass,
1504  &isnull);
1505  Assert(!isnull);
1506  indclass = (oidvector *) DatumGetPointer(indclassDatum);
1507 
1508  /*
1509  * Fill the support procedure OID array, as well as the info about
1510  * opfamilies and opclass input types. (aminfo and supportinfo are left
1511  * as zeroes, and are filled on-the-fly when used)
1512  */
1513  IndexSupportInitialize(indclass, relation->rd_support,
1514  relation->rd_opfamily, relation->rd_opcintype,
1515  amsupport, indnkeyatts);
1516 
1517  /*
1518  * Similarly extract indoption and copy it to the cache entry
1519  */
1520  indoptionDatum = fastgetattr(relation->rd_indextuple,
1521  Anum_pg_index_indoption,
1523  &isnull);
1524  Assert(!isnull);
1525  indoption = (int2vector *) DatumGetPointer(indoptionDatum);
1526  memcpy(relation->rd_indoption, indoption->values, indnkeyatts * sizeof(int16));
1527 
1528  (void) RelationGetIndexAttOptions(relation, false);
1529 
1530  /*
1531  * expressions, predicate, exclusion caches will be filled later
1532  */
1533  relation->rd_indexprs = NIL;
1534  relation->rd_indpred = NIL;
1535  relation->rd_exclops = NULL;
1536  relation->rd_exclprocs = NULL;
1537  relation->rd_exclstrats = NULL;
1538  relation->rd_amcache = NULL;
1539 }
signed short int16
Definition: c.h:416
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
#define NIL
Definition: pg_list.h:65
Definition: c.h:648
struct IndexAmRoutine * rd_indam
Definition: rel.h:189
Definition: fmgr.h:56
uint16 amsupport
Definition: amapi.h:216
#define AllocSetContextCreate
Definition: memutils.h:170
int16 * rd_indoption
Definition: rel.h:194
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:712
Definition: syscache.h:36
struct FmgrInfo * rd_supportinfo
Definition: rel.h:193
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:463
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:202
regproc RegProcedure
Definition: c.h:573
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
uint16 * rd_exclstrats
Definition: rel.h:199
List * rd_indexprs
Definition: rel.h:195
Oid * rd_exclprocs
Definition: rel.h:198
Form_pg_class rd_rel
Definition: rel.h:110
unsigned int Oid
Definition: postgres_ext.h:31
static void InitIndexAmRoutine(Relation relation)
Definition: relcache.c:1361
static void IndexSupportInitialize(oidvector *indclass, RegProcedure *indexSupport, Oid *opFamily, Oid *opcInType, StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber)
Definition: relcache.c:1555
struct HeapTupleData * rd_indextuple
Definition: rel.h:177
Form_pg_index rd_index
Definition: rel.h:175
unsigned short uint16
Definition: c.h:428
Oid * rd_indcollation
Definition: rel.h:200
Oid rd_amhandler
Definition: rel.h:167
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
#define MemoryContextCopyAndSetIdentifier(cxt, id)
Definition: memutils.h:97
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4237
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:656
#define IndexRelationGetNumberOfAttributes(relation)
Definition: rel.h:469
#define RelationGetRelationName(relation)
Definition: rel.h:491
List * rd_indpred
Definition: rel.h:196
Oid * rd_opfamily
Definition: rel.h:190
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition: rel.h:476
Oid * rd_exclops
Definition: rel.h:197
RegProcedure * rd_support
Definition: rel.h:192
FormData_pg_index * Form_pg_index
Definition: pg_index.h:68
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
Definition: c.h:637
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:840
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:792
int16 values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:645
#define DatumGetPointer(X)
Definition: postgres.h:549
FormData_pg_am * Form_pg_am
Definition: pg_am.h:48
#define elog(elevel,...)
Definition: elog.h:228
MemoryContext rd_indexcxt
Definition: rel.h:187
bytea ** RelationGetIndexAttOptions(Relation relation, bool copy)
Definition: relcache.c:5448
void * rd_amcache
Definition: rel.h:212
Oid * rd_opcintype
Definition: rel.h:191
#define RelationGetRelid(relation)
Definition: rel.h:457
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationInitTableAccessMethod()

void RelationInitTableAccessMethod ( Relation  relation)

Definition at line 1765 of file relcache.c.

References AMOID, Assert, elog, ERROR, GETSTRUCT, HeapTupleIsValid, InitTableAmRoutine(), InvalidOid, IsCatalogRelation(), ObjectIdGetDatum, RelationData::rd_amhandler, RelationData::rd_rel, ReleaseSysCache(), and SearchSysCache1().

Referenced by load_relcache_init_file(), RelationBuildDesc(), RelationBuildLocalRelation(), and RelationCacheInitializePhase3().

1766 {
1767  HeapTuple tuple;
1768  Form_pg_am aform;
1769 
1770  if (relation->rd_rel->relkind == RELKIND_SEQUENCE)
1771  {
1772  /*
1773  * Sequences are currently accessed like heap tables, but it doesn't
1774  * seem prudent to show that in the catalog. So just overwrite it
1775  * here.
1776  */
1777  relation->rd_amhandler = F_HEAP_TABLEAM_HANDLER;
1778  }
1779  else if (IsCatalogRelation(relation))
1780  {
1781  /*
1782  * Avoid doing a syscache lookup for catalog tables.
1783  */
1784  Assert(relation->rd_rel->relam == HEAP_TABLE_AM_OID);
1785  relation->rd_amhandler = F_HEAP_TABLEAM_HANDLER;
1786  }
1787  else
1788  {
1789  /*
1790  * Look up the table access method, save the OID of its handler
1791  * function.
1792  */
1793  Assert(relation->rd_rel->relam != InvalidOid);
1794  tuple = SearchSysCache1(AMOID,
1795  ObjectIdGetDatum(relation->rd_rel->relam));
1796  if (!HeapTupleIsValid(tuple))
1797  elog(ERROR, "cache lookup failed for access method %u",
1798  relation->rd_rel->relam);
1799  aform = (Form_pg_am) GETSTRUCT(tuple);
1800  relation->rd_amhandler = aform->amhandler;
1801  ReleaseSysCache(tuple);
1802  }
1803 
1804  /*
1805  * Now we can fetch the table AM's API struct
1806  */
1807  InitTableAmRoutine(relation);
1808 }
static void InitTableAmRoutine(Relation relation)
Definition: relcache.c:1756
bool IsCatalogRelation(Relation relation)
Definition: catalog.c:96
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Definition: syscache.h:36
Form_pg_class rd_rel
Definition: rel.h:110
Oid rd_amhandler
Definition: rel.h:167
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:792
FormData_pg_am * Form_pg_am
Definition: pg_am.h:48
#define elog(elevel,...)
Definition: elog.h:228

◆ RelationSetNewRelfilenode()

void RelationSetNewRelfilenode ( Relation  relation,
char  persistence 
)

Definition at line 3600 of file relcache.c.

References Assert, CacheInvalidateRelcache(), CatalogTupleUpdate(), CommandCounterIncrement(), elog, ERROR, GetCurrentTransactionId(), GetNewRelFileNode(), GETSTRUCT, heap_freetuple(), HeapTupleIsValid, InvalidMultiXactId, InvalidTransactionId, ObjectIdGetDatum, RelationData::rd_node, RelationData::rd_rel, RelationAssumeNewRelfilenode(), RelationCreateStorage(), RelationDropStorage(), RelationGetRelationName, RelationGetRelid, RelationIsMapped, RelationMapUpdateMap(), RelFileNode::relNode, RELOID, RowExclusiveLock, SearchSysCacheCopy1, smgrclose(), HeapTupleData::t_self, table_close(), table_open(), and table_relation_set_new_filenode().

Referenced by AlterSequence(), ExecuteTruncateGuts(), reindex_index(), and ResetSequence().

3601 {
3602  Oid newrelfilenode;
3603  Relation pg_class;
3604  HeapTuple tuple;
3605  Form_pg_class classform;
3606  MultiXactId minmulti = InvalidMultiXactId;
3607  TransactionId freezeXid = InvalidTransactionId;
3608  RelFileNode newrnode;
3609 
3610  /* Allocate a new relfilenode */
3611  newrelfilenode = GetNewRelFileNode(relation->rd_rel->reltablespace, NULL,
3612  persistence);
3613 
3614  /*
3615  * Get a writable copy of the pg_class tuple for the given relation.
3616  */
3617  pg_class = table_open(RelationRelationId, RowExclusiveLock);
3618 
3619  tuple = SearchSysCacheCopy1(RELOID,
3620  ObjectIdGetDatum(RelationGetRelid(relation)));
3621  if (!HeapTupleIsValid(tuple))
3622  elog(ERROR, "could not find tuple for relation %u",
3623  RelationGetRelid(relation));
3624  classform = (Form_pg_class) GETSTRUCT(tuple);
3625 
3626  /*
3627  * Schedule unlinking of the old storage at transaction commit.
3628  */
3629  RelationDropStorage(relation);
3630 
3631  /*
3632  * Create storage for the main fork of the new relfilenode. If it's a
3633  * table-like object, call into the table AM to do so, which'll also
3634  * create the table's init fork if needed.
3635  *
3636  * NOTE: If relevant for the AM, any conflict in relfilenode value will be
3637  * caught here, if GetNewRelFileNode messes up for any reason.
3638  */
3639  newrnode = relation->rd_node;
3640  newrnode.relNode = newrelfilenode;
3641 
3642  switch (relation->rd_rel->relkind)
3643  {
3644  case RELKIND_INDEX:
3645  case RELKIND_SEQUENCE:
3646  {
3647  /* handle these directly, at least for now */
3648  SMgrRelation srel;
3649 
3650  srel = RelationCreateStorage(newrnode, persistence);
3651  smgrclose(srel);
3652  }
3653  break;
3654 
3655  case RELKIND_RELATION:
3656  case RELKIND_TOASTVALUE:
3657  case RELKIND_MATVIEW:
3658  table_relation_set_new_filenode(relation, &newrnode,
3659  persistence,
3660  &freezeXid, &minmulti);
3661  break;
3662 
3663  default:
3664  /* we shouldn't be called for anything else */
3665  elog(ERROR, "relation \"%s\" does not have storage",
3666  RelationGetRelationName(relation));
3667  break;
3668  }
3669 
3670  /*
3671  * If we're dealing with a mapped index, pg_class.relfilenode doesn't
3672  * change; instead we have to send the update to the relation mapper.
3673  *
3674  * For mapped indexes, we don't actually change the pg_class entry at all;
3675  * this is essential when reindexing pg_class itself. That leaves us with
3676  * possibly-inaccurate values of relpages etc, but those will be fixed up
3677  * later.
3678  */
3679  if (RelationIsMapped(relation))
3680  {
3681  /* This case is only supported for indexes */
3682  Assert(relation->rd_rel->relkind == RELKIND_INDEX);
3683 
3684  /* Since we're not updating pg_class, these had better not change */
3685  Assert(classform->relfrozenxid == freezeXid);
3686  Assert(classform->relminmxid == minmulti);
3687  Assert(classform->relpersistence == persistence);
3688 
3689  /*
3690  * In some code paths it's possible that the tuple update we'd
3691  * otherwise do here is the only thing that would assign an XID for
3692  * the current transaction. However, we must have an XID to delete
3693  * files, so make sure one is assigned.
3694  */
3695  (void) GetCurrentTransactionId();
3696 
3697  /* Do the deed */
3699  newrelfilenode,
3700  relation->rd_rel->relisshared,
3701  false);
3702 
3703  /* Since we're not updating pg_class, must trigger inval manually */
3704  CacheInvalidateRelcache(relation);
3705  }
3706  else
3707  {
3708  /* Normal case, update the pg_class entry */
3709  classform->relfilenode = newrelfilenode;
3710 
3711  /* relpages etc. never change for sequences */
3712  if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
3713  {
3714  classform->relpages = 0; /* it's empty until further notice */
3715  classform->reltuples = -1;
3716  classform->relallvisible = 0;
3717  }
3718  classform->relfrozenxid = freezeXid;
3719  classform->relminmxid = minmulti;
3720  classform->relpersistence = persistence;
3721 
3722  CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
3723  }
3724 
3725  heap_freetuple(tuple);
3726 
3727  table_close(pg_class, RowExclusiveLock);
3728 
3729  /*
3730  * Make the pg_class row change or relation map change visible. This will
3731  * cause the relcache entry to get updated, too.
3732  */
3734 
3735  RelationAssumeNewRelfilenode(relation);
3736 }
void smgrclose(SMgrRelation reln)
Definition: smgr.c:256
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
uint32 TransactionId
Definition: c.h:575
Form_pg_class rd_rel
Definition: rel.h:110
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
SMgrRelation RelationCreateStorage(RelFileNode rnode, char relpersistence)
Definition: storage.c:118
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
ItemPointerData t_self
Definition: htup.h:65
TransactionId GetCurrentTransactionId(void)
Definition: xact.c:438
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvalidTransactionId
Definition: transam.h:31
#define RelationGetRelationName(relation)
Definition: rel.h:491
#define RelationIsMapped(relation)
Definition: rel.h:506
void RelationAssumeNewRelfilenode(Relation relation)
Definition: relcache.c:3751
void RelationDropStorage(Relation rel)
Definition: storage.c:195
void CommandCounterIncrement(void)
Definition: xact.c:1021
#define InvalidMultiXactId
Definition: multixact.h:24
TransactionId MultiXactId
Definition: c.h:585
RelFileNode rd_node
Definition: rel.h:55
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:792
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:302
Oid GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
Definition: catalog.c:378
static void table_relation_set_new_filenode(Relation rel, const RelFileNode *newrnode, char persistence, TransactionId *freezeXid, MultiXactId *minmulti)
Definition: tableam.h:1503
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1278
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:175
#define elog(elevel,...)
Definition: elog.h:228
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define RelationGetRelid(relation)
Definition: rel.h:457
void RelationMapUpdateMap(Oid relationId, Oid fileNode, bool shared, bool immediate)
Definition: relmapper.c:261

Variable Documentation

◆ criticalRelcachesBuilt

◆ criticalSharedRelcachesBuilt

bool criticalSharedRelcachesBuilt