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 3201 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().

3203 {
3205  RelIdCacheEnt *idhentry;
3206  int i;
3207 
3208  /*
3209  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3210  * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3211  * logic as in AtEOXact_RelationCache.
3212  */
3214  {
3215  hash_seq_init(&status, RelationIdCache);
3216  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3217  {
3218  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3219  mySubid, parentSubid);
3220  }
3221  }
3222  else
3223  {
3224  for (i = 0; i < eoxact_list_len; i++)
3225  {
3226  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3227  (void *) &eoxact_list[i],
3228  HASH_FIND,
3229  NULL);
3230  if (idhentry != NULL)
3231  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3232  mySubid, parentSubid);
3233  }
3234  }
3235 
3236  /* Don't reset the list; we still need more cleanup later */
3237 }
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:3248
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 3056 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().

3057 {
3059  RelIdCacheEnt *idhentry;
3060  int i;
3061 
3062  /*
3063  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3064  * listed in it. Otherwise fall back on a hash_seq_search scan.
3065  *
3066  * For simplicity, eoxact_list[] entries are not deleted till end of
3067  * top-level transaction, even though we could remove them at
3068  * subtransaction end in some cases, or remove relations from the list if
3069  * they are cleared for other reasons. Therefore we should expect the
3070  * case that list entries are not found in the hashtable; if not, there's
3071  * nothing to do for them.
3072  */
3074  {
3075  hash_seq_init(&status, RelationIdCache);
3076  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3077  {
3078  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3079  }
3080  }
3081  else
3082  {
3083  for (i = 0; i < eoxact_list_len; i++)
3084  {
3085  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3086  (void *) &eoxact_list[i],
3087  HASH_FIND,
3088  NULL);
3089  if (idhentry != NULL)
3090  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3091  }
3092  }
3093 
3094  if (EOXactTupleDescArrayLen > 0)
3095  {
3096  Assert(EOXactTupleDescArray != NULL);
3097  for (i = 0; i < NextEOXactTupleDescNum; i++)
3100  EOXactTupleDescArray = NULL;
3101  }
3102 
3103  /* Now we're out of the transaction and can clear the lists */
3104  eoxact_list_len = 0;
3105  eoxact_list_overflowed = false;
3106  NextEOXactTupleDescNum = 0;
3108 }
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:3119
static bool eoxact_list_overflowed
Definition: relcache.c:167
static int NextEOXactTupleDescNum
Definition: relcache.c:183
void pfree(void *pointer)
Definition: mcxt.c:1169
#define Assert(condition)
Definition: c.h:804
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:309
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 5534 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().

5535 {
5539 
5540  return 0; /* return value does not matter */
5541 }
#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:3316
#define RelationGetRelationName(relation)
Definition: rel.h:491
int err_generic_string(int field, const char *str)
Definition: elog.c:1351
#define RelationGetNamespace(relation)
Definition: rel.h:498

◆ errtablecol()

int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5551 of file relcache.c.

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

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

5552 {
5553  TupleDesc reldesc = RelationGetDescr(rel);
5554  const char *colname;
5555 
5556  /* Use reldesc if it's a user attribute, else consult the catalogs */
5557  if (attnum > 0 && attnum <= reldesc->natts)
5558  colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
5559  else
5560  colname = get_attname(RelationGetRelid(rel), attnum, false);
5561 
5562  return errtablecolname(rel, colname);
5563 }
#define RelationGetDescr(relation)
Definition: rel.h:483
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
NameData attname
Definition: pg_attribute.h:41
int16 attnum
Definition: pg_attribute.h:83
#define NameStr(name)
Definition: c.h:681
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:5575

◆ errtablecolname()

int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5575 of file relcache.c.

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

Referenced by errtablecol().

5576 {
5577  errtable(rel);
5579 
5580  return 0; /* return value does not matter */
5581 }
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:67
int err_generic_string(int field, const char *str)
Definition: elog.c:1351
int errtable(Relation rel)
Definition: relcache.c:5534

◆ errtableconstraint()

int errtableconstraint ( Relation  rel,
const char *  conname 
)

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

5589 {
5590  errtable(rel);
5592 
5593  return 0; /* return value does not matter */
5594 }
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:69
int err_generic_string(int field, const char *str)
Definition: elog.c:1351
int errtable(Relation rel)
Definition: relcache.c:5534

◆ GetRelationPublicationActions()

struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

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

5344 {
5345  List *puboids;
5346  ListCell *lc;
5347  MemoryContext oldcxt;
5348  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5349 
5350  /*
5351  * If not publishable, it publishes no actions. (pgoutput_change() will
5352  * ignore it.)
5353  */
5354  if (!is_publishable_relation(relation))
5355  return pubactions;
5356 
5357  if (relation->rd_pubactions)
5358  return memcpy(pubactions, relation->rd_pubactions,
5359  sizeof(PublicationActions));
5360 
5361  /* Fetch the publication membership info. */
5362  puboids = GetRelationPublications(RelationGetRelid(relation));
5363  if (relation->rd_rel->relispartition)
5364  {
5365  /* Add publications that the ancestors are in too. */
5366  List *ancestors = get_partition_ancestors(RelationGetRelid(relation));
5367  ListCell *lc;
5368 
5369  foreach(lc, ancestors)
5370  {
5371  Oid ancestor = lfirst_oid(lc);
5372 
5373  puboids = list_concat_unique_oid(puboids,
5374  GetRelationPublications(ancestor));
5375  }
5376  }
5377  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5378 
5379  foreach(lc, puboids)
5380  {
5381  Oid pubid = lfirst_oid(lc);
5382  HeapTuple tup;
5383  Form_pg_publication pubform;
5384 
5386 
5387  if (!HeapTupleIsValid(tup))
5388  elog(ERROR, "cache lookup failed for publication %u", pubid);
5389 
5390  pubform = (Form_pg_publication) GETSTRUCT(tup);
5391 
5392  pubactions->pubinsert |= pubform->pubinsert;
5393  pubactions->pubupdate |= pubform->pubupdate;
5394  pubactions->pubdelete |= pubform->pubdelete;
5395  pubactions->pubtruncate |= pubform->pubtruncate;
5396 
5397  ReleaseSysCache(tup);
5398 
5399  /*
5400  * If we know everything is replicated, there is no point to check for
5401  * other publications.
5402  */
5403  if (pubactions->pubinsert && pubactions->pubupdate &&
5404  pubactions->pubdelete && pubactions->pubtruncate)
5405  break;
5406  }
5407 
5408  if (relation->rd_pubactions)
5409  {
5410  pfree(relation->rd_pubactions);
5411  relation->rd_pubactions = NULL;
5412  }
5413 
5414  /* Now save copy of the actions in the relcache entry. */
5416  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5417  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5418  MemoryContextSwitchTo(oldcxt);
5419 
5420  return pubactions;
5421 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
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:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
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:1093
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:1062
#define elog(elevel,...)
Definition: elog.h:232
FormData_pg_publication * Form_pg_publication
Definition: pg_list.h:50
List * get_partition_ancestors(Oid relid)
Definition: partition.c:133
#define RelationGetRelid(relation)
Definition: rel.h:457
#define lfirst_oid(lc)
Definition: pg_list.h:171
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ RelationAssumeNewRelfilenode()

void RelationAssumeNewRelfilenode ( Relation  relation)

Definition at line 3727 of file relcache.c.

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

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

3728 {
3731  relation->rd_firstRelfilenodeSubid = relation->rd_newRelfilenodeSubid;
3732 
3733  /* Flag relation as needing eoxact cleanup (to clear these fields) */
3734  EOXactListAdd(relation);
3735 }
#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:593

◆ 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 3330 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().

3341 {
3342  Relation rel;
3343  MemoryContext oldcxt;
3344  int natts = tupDesc->natts;
3345  int i;
3346  bool has_not_null;
3347  bool nailit;
3348 
3349  AssertArg(natts >= 0);
3350 
3351  /*
3352  * check for creation of a rel that must be nailed in cache.
3353  *
3354  * XXX this list had better match the relations specially handled in
3355  * RelationCacheInitializePhase2/3.
3356  */
3357  switch (relid)
3358  {
3359  case DatabaseRelationId:
3360  case AuthIdRelationId:
3361  case AuthMemRelationId:
3362  case RelationRelationId:
3363  case AttributeRelationId:
3364  case ProcedureRelationId:
3365  case TypeRelationId:
3366  nailit = true;
3367  break;
3368  default:
3369  nailit = false;
3370  break;
3371  }
3372 
3373  /*
3374  * check that hardwired list of shared rels matches what's in the
3375  * bootstrap .bki file. If you get a failure here during initdb, you
3376  * probably need to fix IsSharedRelation() to match whatever you've done
3377  * to the set of shared relations.
3378  */
3379  if (shared_relation != IsSharedRelation(relid))
3380  elog(ERROR, "shared_relation flag for \"%s\" does not match IsSharedRelation(%u)",
3381  relname, relid);
3382 
3383  /* Shared relations had better be mapped, too */
3384  Assert(mapped_relation || !shared_relation);
3385 
3386  /*
3387  * switch to the cache context to create the relcache entry.
3388  */
3389  if (!CacheMemoryContext)
3391 
3393 
3394  /*
3395  * allocate a new relation descriptor and fill in basic state fields.
3396  */
3397  rel = (Relation) palloc0(sizeof(RelationData));
3398 
3399  /* make sure relation is marked as having no open file yet */
3400  rel->rd_smgr = NULL;
3401 
3402  /* mark it nailed if appropriate */
3403  rel->rd_isnailed = nailit;
3404 
3405  rel->rd_refcnt = nailit ? 1 : 0;
3406 
3407  /* it's being created in this transaction */
3412 
3413  /*
3414  * create a new tuple descriptor from the one passed in. We do this
3415  * partly to copy it into the cache context, and partly because the new
3416  * relation can't have any defaults or constraints yet; they have to be
3417  * added in later steps, because they require additions to multiple system
3418  * catalogs. We can copy attnotnull constraints here, however.
3419  */
3420  rel->rd_att = CreateTupleDescCopy(tupDesc);
3421  rel->rd_att->tdrefcount = 1; /* mark as refcounted */
3422  has_not_null = false;
3423  for (i = 0; i < natts; i++)
3424  {
3425  Form_pg_attribute satt = TupleDescAttr(tupDesc, i);
3426  Form_pg_attribute datt = TupleDescAttr(rel->rd_att, i);
3427 
3428  datt->attidentity = satt->attidentity;
3429  datt->attgenerated = satt->attgenerated;
3430  datt->attnotnull = satt->attnotnull;
3431  has_not_null |= satt->attnotnull;
3432  }
3433 
3434  if (has_not_null)
3435  {
3436  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
3437 
3438  constr->has_not_null = true;
3439  rel->rd_att->constr = constr;
3440  }
3441 
3442  /*
3443  * initialize relation tuple form (caller may add/override data later)
3444  */
3446 
3447  namestrcpy(&rel->rd_rel->relname, relname);
3448  rel->rd_rel->relnamespace = relnamespace;
3449 
3450  rel->rd_rel->relkind = relkind;
3451  rel->rd_rel->relnatts = natts;
3452  rel->rd_rel->reltype = InvalidOid;
3453  /* needed when bootstrapping: */
3454  rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;
3455 
3456  /* set up persistence and relcache fields dependent on it */
3457  rel->rd_rel->relpersistence = relpersistence;
3458  switch (relpersistence)
3459  {
3460  case RELPERSISTENCE_UNLOGGED:
3461  case RELPERSISTENCE_PERMANENT:
3463  rel->rd_islocaltemp = false;
3464  break;
3465  case RELPERSISTENCE_TEMP:
3466  Assert(isTempOrTempToastNamespace(relnamespace));
3468  rel->rd_islocaltemp = true;
3469  break;
3470  default:
3471  elog(ERROR, "invalid relpersistence: %c", relpersistence);
3472  break;
3473  }
3474 
3475  /* if it's a materialized view, it's not populated initially */
3476  if (relkind == RELKIND_MATVIEW)
3477  rel->rd_rel->relispopulated = false;
3478  else
3479  rel->rd_rel->relispopulated = true;
3480 
3481  /* set replica identity -- system catalogs and non-tables don't have one */
3482  if (!IsCatalogNamespace(relnamespace) &&
3483  (relkind == RELKIND_RELATION ||
3484  relkind == RELKIND_MATVIEW ||
3485  relkind == RELKIND_PARTITIONED_TABLE))
3486  rel->rd_rel->relreplident = REPLICA_IDENTITY_DEFAULT;
3487  else
3488  rel->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
3489 
3490  /*
3491  * Insert relation physical and logical identifiers (OIDs) into the right
3492  * places. For a mapped relation, we set relfilenode to zero and rely on
3493  * RelationInitPhysicalAddr to consult the map.
3494  */
3495  rel->rd_rel->relisshared = shared_relation;
3496 
3497  RelationGetRelid(rel) = relid;
3498 
3499  for (i = 0; i < natts; i++)
3500  TupleDescAttr(rel->rd_att, i)->attrelid = relid;
3501 
3502  rel->rd_rel->reltablespace = reltablespace;
3503 
3504  if (mapped_relation)
3505  {
3506  rel->rd_rel->relfilenode = InvalidOid;
3507  /* Add it to the active mapping information */
3508  RelationMapUpdateMap(relid, relfilenode, shared_relation, true);
3509  }
3510  else
3511  rel->rd_rel->relfilenode = relfilenode;
3512 
3513  RelationInitLockInfo(rel); /* see lmgr.c */
3514 
3516 
3517  rel->rd_rel->relam = accessmtd;
3518 
3519  /*
3520  * RelationInitTableAccessMethod will do syscache lookups, so we mustn't
3521  * run it in CacheMemoryContext. Fortunately, the remaining steps don't
3522  * require a long-lived current context.
3523  */
3524  MemoryContextSwitchTo(oldcxt);
3525 
3526  if (relkind == RELKIND_RELATION ||
3527  relkind == RELKIND_SEQUENCE ||
3528  relkind == RELKIND_TOASTVALUE ||
3529  relkind == RELKIND_MATVIEW)
3531 
3532  /*
3533  * Okay to insert into the relcache hash table.
3534  *
3535  * Ordinarily, there should certainly not be an existing hash entry for
3536  * the same OID; but during bootstrap, when we create a "real" relcache
3537  * entry for one of the bootstrap relations, we'll be overwriting the
3538  * phony one created with formrdesc. So allow that to happen for nailed
3539  * rels.
3540  */
3541  RelationCacheInsert(rel, nailit);
3542 
3543  /*
3544  * Flag relation as needing eoxact cleanup (to clear rd_createSubid). We
3545  * can't do this before storing relid in it.
3546  */
3547  EOXactListAdd(rel);
3548 
3549  /* It's fully valid */
3550  rel->rd_isvalid = true;
3551 
3552  /*
3553  * Caller expects us to pin the returned entry.
3554  */
3556 
3557  return rel;
3558 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
#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:1738
#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:46
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1252
void RelationInitLockInfo(Relation relation)
Definition: lmgr.c:72
#define BackendIdForTempRelations()
Definition: backendid.h:34
TupleConstr * constr
Definition: tupdesc.h:85
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
#define AssertArg(condition)
Definition: c.h:806
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:1093
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2063
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:243
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:804
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:723
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
#define InvalidSubTransactionId
Definition: c.h:593
bool IsCatalogNamespace(Oid namespaceId)
Definition: catalog.c:182
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
int rd_refcnt
Definition: rel.h:58
#define elog(elevel,...)
Definition: elog.h:232
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:51

◆ RelationCacheInitFilePostInvalidate()

void RelationCacheInitFilePostInvalidate ( void  )

Definition at line 6361 of file relcache.c.

References LWLockRelease().

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

6362 {
6363  LWLockRelease(RelCacheInitLock);
6364 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )

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

6337 {
6338  char localinitfname[MAXPGPATH];
6339  char sharedinitfname[MAXPGPATH];
6340 
6341  if (DatabasePath)
6342  snprintf(localinitfname, sizeof(localinitfname), "%s/%s",
6344  snprintf(sharedinitfname, sizeof(sharedinitfname), "global/%s",
6346 
6347  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6348 
6349  /*
6350  * The files might not be there if no backend has been started since the
6351  * last removal. But complain about failures other than ENOENT with
6352  * ERROR. Fortunately, it's not too late to abort the transaction if we
6353  * can't get rid of the would-be-obsolete init file.
6354  */
6355  if (DatabasePath)
6356  unlink_initfile(localinitfname, ERROR);
6357  unlink_initfile(sharedinitfname, ERROR);
6358 }
#define ERROR
Definition: elog.h:46
#define MAXPGPATH
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25
char * DatabasePath
Definition: globals.c:96
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6433
#define snprintf
Definition: port.h:216

◆ RelationCacheInitFileRemove()

void RelationCacheInitFileRemove ( void  )

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

6377 {
6378  const char *tblspcdir = "pg_tblspc";
6379  DIR *dir;
6380  struct dirent *de;
6381  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6382 
6383  snprintf(path, sizeof(path), "global/%s",
6385  unlink_initfile(path, LOG);
6386 
6387  /* Scan everything in the default tablespace */
6389 
6390  /* Scan the tablespace link directory to find non-default tablespaces */
6391  dir = AllocateDir(tblspcdir);
6392 
6393  while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6394  {
6395  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6396  {
6397  /* Scan the tablespace dir for per-database dirs */
6398  snprintf(path, sizeof(path), "%s/%s/%s",
6399  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6401  }
6402  }
6403 
6404  FreeDir(dir);
6405 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6409
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2715
#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:2634
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6433
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:216
int FreeDir(DIR *dir)
Definition: fd.c:2752

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 3753 of file relcache.c.

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

Referenced by InitPostgres().

3754 {
3755  HASHCTL ctl;
3756 
3757  /*
3758  * make sure cache memory context exists
3759  */
3760  if (!CacheMemoryContext)
3762 
3763  /*
3764  * create hashtable that indexes the relcache
3765  */
3766  ctl.keysize = sizeof(Oid);
3767  ctl.entrysize = sizeof(RelIdCacheEnt);
3768  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3769  &ctl, HASH_ELEM | HASH_BLOBS);
3770 
3771  /*
3772  * relation mapper needs to be initialized too
3773  */
3775 }
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:3750
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ RelationCacheInitializePhase2()

void RelationCacheInitializePhase2 ( void  )

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

3790 {
3791  MemoryContext oldcxt;
3792 
3793  /*
3794  * relation mapper needs initialized too
3795  */
3797 
3798  /*
3799  * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3800  * nothing.
3801  */
3803  return;
3804 
3805  /*
3806  * switch to cache memory context
3807  */
3809 
3810  /*
3811  * Try to load the shared relcache cache file. If unsuccessful, bootstrap
3812  * the cache with pre-made descriptors for the critical shared catalogs.
3813  */
3814  if (!load_relcache_init_file(true))
3815  {
3816  formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
3817  Natts_pg_database, Desc_pg_database);
3818  formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
3819  Natts_pg_authid, Desc_pg_authid);
3820  formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
3821  Natts_pg_auth_members, Desc_pg_auth_members);
3822  formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
3823  Natts_pg_shseclabel, Desc_pg_shseclabel);
3824  formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
3825  Natts_pg_subscription, Desc_pg_subscription);
3826 
3827 #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
3828  }
3829 
3830  MemoryContextSwitchTo(oldcxt);
3831 }
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:5652
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:1802
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ RelationCacheInitializePhase3()

void RelationCacheInitializePhase3 ( void  )

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

3849 {
3851  RelIdCacheEnt *idhentry;
3852  MemoryContext oldcxt;
3853  bool needNewCacheFile = !criticalSharedRelcachesBuilt;
3854 
3855  /*
3856  * relation mapper needs initialized too
3857  */
3859 
3860  /*
3861  * switch to cache memory context
3862  */
3864 
3865  /*
3866  * Try to load the local relcache cache file. If unsuccessful, bootstrap
3867  * the cache with pre-made descriptors for the critical "nailed-in" system
3868  * catalogs.
3869  */
3870  if (IsBootstrapProcessingMode() ||
3871  !load_relcache_init_file(false))
3872  {
3873  needNewCacheFile = true;
3874 
3875  formrdesc("pg_class", RelationRelation_Rowtype_Id, false,
3876  Natts_pg_class, Desc_pg_class);
3877  formrdesc("pg_attribute", AttributeRelation_Rowtype_Id, false,
3878  Natts_pg_attribute, Desc_pg_attribute);
3879  formrdesc("pg_proc", ProcedureRelation_Rowtype_Id, false,
3880  Natts_pg_proc, Desc_pg_proc);
3881  formrdesc("pg_type", TypeRelation_Rowtype_Id, false,
3882  Natts_pg_type, Desc_pg_type);
3883 
3884 #define NUM_CRITICAL_LOCAL_RELS 4 /* fix if you change list above */
3885  }
3886 
3887  MemoryContextSwitchTo(oldcxt);
3888 
3889  /* In bootstrap mode, the faked-up formrdesc info is all we'll have */
3891  return;
3892 
3893  /*
3894  * If we didn't get the critical system indexes loaded into relcache, do
3895  * so now. These are critical because the catcache and/or opclass cache
3896  * depend on them for fetches done during relcache load. Thus, we have an
3897  * infinite-recursion problem. We can break the recursion by doing
3898  * heapscans instead of indexscans at certain key spots. To avoid hobbling
3899  * performance, we only want to do that until we have the critical indexes
3900  * loaded into relcache. Thus, the flag criticalRelcachesBuilt is used to
3901  * decide whether to do heapscan or indexscan at the key spots, and we set
3902  * it true after we've loaded the critical indexes.
3903  *
3904  * The critical indexes are marked as "nailed in cache", partly to make it
3905  * easy for load_relcache_init_file to count them, but mainly because we
3906  * cannot flush and rebuild them once we've set criticalRelcachesBuilt to
3907  * true. (NOTE: perhaps it would be possible to reload them by
3908  * temporarily setting criticalRelcachesBuilt to false again. For now,
3909  * though, we just nail 'em in.)
3910  *
3911  * RewriteRelRulenameIndexId and TriggerRelidNameIndexId are not critical
3912  * in the same way as the others, because the critical catalogs don't
3913  * (currently) have any rules or triggers, and so these indexes can be
3914  * rebuilt without inducing recursion. However they are used during
3915  * relcache load when a rel does have rules or triggers, so we choose to
3916  * nail them for performance reasons.
3917  */
3919  {
3921  RelationRelationId);
3923  AttributeRelationId);
3925  IndexRelationId);
3927  OperatorClassRelationId);
3929  AccessMethodProcedureRelationId);
3931  RewriteRelationId);
3933  TriggerRelationId);
3934 
3935 #define NUM_CRITICAL_LOCAL_INDEXES 7 /* fix if you change list above */
3936 
3937  criticalRelcachesBuilt = true;
3938  }
3939 
3940  /*
3941  * Process critical shared indexes too.
3942  *
3943  * DatabaseNameIndexId isn't critical for relcache loading, but rather for
3944  * initial lookup of MyDatabaseId, without which we'll never find any
3945  * non-shared catalogs at all. Autovacuum calls InitPostgres with a
3946  * database OID, so it instead depends on DatabaseOidIndexId. We also
3947  * need to nail up some indexes on pg_authid and pg_auth_members for use
3948  * during client authentication. SharedSecLabelObjectIndexId isn't
3949  * critical for the core system, but authentication hooks might be
3950  * interested in it.
3951  */
3953  {
3955  DatabaseRelationId);
3957  DatabaseRelationId);
3959  AuthIdRelationId);
3961  AuthIdRelationId);
3963  AuthMemRelationId);
3965  SharedSecLabelRelationId);
3966 
3967 #define NUM_CRITICAL_SHARED_INDEXES 6 /* fix if you change list above */
3968 
3970  }
3971 
3972  /*
3973  * Now, scan all the relcache entries and update anything that might be
3974  * wrong in the results from formrdesc or the relcache cache file. If we
3975  * faked up relcache entries using formrdesc, then read the real pg_class
3976  * rows and replace the fake entries with them. Also, if any of the
3977  * relcache entries have rules, triggers, or security policies, load that
3978  * info the hard way since it isn't recorded in the cache file.
3979  *
3980  * Whenever we access the catalogs to read data, there is a possibility of
3981  * a shared-inval cache flush causing relcache entries to be removed.
3982  * Since hash_seq_search only guarantees to still work after the *current*
3983  * entry is removed, it's unsafe to continue the hashtable scan afterward.
3984  * We handle this by restarting the scan from scratch after each access.
3985  * This is theoretically O(N^2), but the number of entries that actually
3986  * need to be fixed is small enough that it doesn't matter.
3987  */
3988  hash_seq_init(&status, RelationIdCache);
3989 
3990  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3991  {
3992  Relation relation = idhentry->reldesc;
3993  bool restart = false;
3994 
3995  /*
3996  * Make sure *this* entry doesn't get flushed while we work with it.
3997  */
3999 
4000  /*
4001  * If it's a faked-up entry, read the real pg_class tuple.
4002  */
4003  if (relation->rd_rel->relowner == InvalidOid)
4004  {
4005  HeapTuple htup;
4006  Form_pg_class relp;
4007 
4008  htup = SearchSysCache1(RELOID,
4009  ObjectIdGetDatum(RelationGetRelid(relation)));
4010  if (!HeapTupleIsValid(htup))
4011  elog(FATAL, "cache lookup failed for relation %u",
4012  RelationGetRelid(relation));
4013  relp = (Form_pg_class) GETSTRUCT(htup);
4014 
4015  /*
4016  * Copy tuple to relation->rd_rel. (See notes in
4017  * AllocateRelationDesc())
4018  */
4019  memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
4020 
4021  /* Update rd_options while we have the tuple */
4022  if (relation->rd_options)
4023  pfree(relation->rd_options);
4024  RelationParseRelOptions(relation, htup);
4025 
4026  /*
4027  * Check the values in rd_att were set up correctly. (We cannot
4028  * just copy them over now: formrdesc must have set up the rd_att
4029  * data correctly to start with, because it may already have been
4030  * copied into one or more catcache entries.)
4031  */
4032  Assert(relation->rd_att->tdtypeid == relp->reltype);
4033  Assert(relation->rd_att->tdtypmod == -1);
4034 
4035  ReleaseSysCache(htup);
4036 
4037  /* relowner had better be OK now, else we'll loop forever */
4038  if (relation->rd_rel->relowner == InvalidOid)
4039  elog(ERROR, "invalid relowner in pg_class entry for \"%s\"",
4040  RelationGetRelationName(relation));
4041 
4042  restart = true;
4043  }
4044 
4045  /*
4046  * Fix data that isn't saved in relcache cache file.
4047  *
4048  * relhasrules or relhastriggers could possibly be wrong or out of
4049  * date. If we don't actually find any rules or triggers, clear the
4050  * local copy of the flag so that we don't get into an infinite loop
4051  * here. We don't make any attempt to fix the pg_class entry, though.
4052  */
4053  if (relation->rd_rel->relhasrules && relation->rd_rules == NULL)
4054  {
4055  RelationBuildRuleLock(relation);
4056  if (relation->rd_rules == NULL)
4057  relation->rd_rel->relhasrules = false;
4058  restart = true;
4059  }
4060  if (relation->rd_rel->relhastriggers && relation->trigdesc == NULL)
4061  {
4062  RelationBuildTriggers(relation);
4063  if (relation->trigdesc == NULL)
4064  relation->rd_rel->relhastriggers = false;
4065  restart = true;
4066  }
4067 
4068  /*
4069  * Re-load the row security policies if the relation has them, since
4070  * they are not preserved in the cache. Note that we can never NOT
4071  * have a policy while relrowsecurity is true,
4072  * RelationBuildRowSecurity will create a single default-deny policy
4073  * if there is no policy defined in pg_policy.
4074  */
4075  if (relation->rd_rel->relrowsecurity && relation->rd_rsdesc == NULL)
4076  {
4077  RelationBuildRowSecurity(relation);
4078 
4079  Assert(relation->rd_rsdesc != NULL);
4080  restart = true;
4081  }
4082 
4083  /* Reload tableam data if needed */
4084  if (relation->rd_tableam == NULL &&
4085  (relation->rd_rel->relkind == RELKIND_RELATION ||
4086  relation->rd_rel->relkind == RELKIND_SEQUENCE ||
4087  relation->rd_rel->relkind == RELKIND_TOASTVALUE ||
4088  relation->rd_rel->relkind == RELKIND_MATVIEW))
4089  {
4091  Assert(relation->rd_tableam != NULL);
4092 
4093  restart = true;
4094  }
4095 
4096  /* Release hold on the relation */
4098 
4099  /* Now, restart the hashtable scan if needed */
4100  if (restart)
4101  {
4102  hash_seq_term(&status);
4103  hash_seq_init(&status, RelationIdCache);
4104  }
4105  }
4106 
4107  /*
4108  * Lastly, write out new relcache cache files if needed. We don't bother
4109  * to distinguish cases where only one of the two needs an update.
4110  */
4111  if (needNewCacheFile)
4112  {
4113  /*
4114  * Force all the catcaches to finish initializing and thereby open the
4115  * catalogs and indexes they use. This will preload the relcache with
4116  * entries for all the most important system catalogs and indexes, so
4117  * that the init files will be most useful for future backends.
4118  */
4120 
4121  /* now write the files */
4123  write_relcache_init_file(false);
4124  }
4125 }
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5652
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define TriggerRelidNameIndexId
Definition: pg_trigger.h:87
void RelationBuildRowSecurity(Relation relation)
Definition: policy.c:195
void RelationInitTableAccessMethod(Relation relation)
Definition: relcache.c:1738
#define IndexRelidIndexId
Definition: pg_index.h:74
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:47
#define AuthMemMemRoleIndexId
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2076
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
int32 tdtypmod
Definition: tupdesc.h:83
#define FATAL
Definition: elog.h:49
static void write_relcache_init_file(bool shared)
Definition: relcache.c:6069
TriggerDesc * trigdesc
Definition: rel.h:116
static void RelationParseRelOptions(Relation relation, HeapTuple tuple)
Definition: relcache.c:442
#define AttributeRelidNumIndexId
Definition: pg_attribute.h:208
static void load_critical_index(Oid indexoid, Oid heapoid)
Definition: relcache.c:4134
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:2063
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:804
#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:1637
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1802
static const FormData_pg_attribute Desc_pg_class[Natts_pg_class]
Definition: relcache.c:109
#define elog(elevel,...)
Definition: elog.h:232
void RelationMapInitializePhase3(void)
Definition: relmapper.c:625
static void RelationBuildRuleLock(Relation relation)
Definition: relcache.c:709
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:51

◆ RelationCacheInvalidate()

void RelationCacheInvalidate ( void  )

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

2819 {
2821  RelIdCacheEnt *idhentry;
2822  Relation relation;
2823  List *rebuildFirstList = NIL;
2824  List *rebuildList = NIL;
2825  ListCell *l;
2826 
2827  /*
2828  * Reload relation mapping data before starting to reconstruct cache.
2829  */
2831 
2832  /* Phase 1 */
2833  hash_seq_init(&status, RelationIdCache);
2834 
2835  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2836  {
2837  relation = idhentry->reldesc;
2838 
2839  /* Must close all smgr references to avoid leaving dangling ptrs */
2840  RelationCloseSmgr(relation);
2841 
2842  /*
2843  * Ignore new relations; no other backend will manipulate them before
2844  * we commit. Likewise, before replacing a relation's relfilenode, we
2845  * shall have acquired AccessExclusiveLock and drained any applicable
2846  * pending invalidations.
2847  */
2848  if (relation->rd_createSubid != InvalidSubTransactionId ||
2850  continue;
2851 
2853 
2854  if (RelationHasReferenceCountZero(relation))
2855  {
2856  /* Delete this entry immediately */
2857  Assert(!relation->rd_isnailed);
2858  RelationClearRelation(relation, false);
2859  }
2860  else
2861  {
2862  /*
2863  * If it's a mapped relation, immediately update its rd_node in
2864  * case its relfilenode changed. We must do this during phase 1
2865  * in case the relation is consulted during rebuild of other
2866  * relcache entries in phase 2. It's safe since consulting the
2867  * map doesn't involve any access to relcache entries.
2868  */
2869  if (RelationIsMapped(relation))
2870  RelationInitPhysicalAddr(relation);
2871 
2872  /*
2873  * Add this entry to list of stuff to rebuild in second pass.
2874  * pg_class goes to the front of rebuildFirstList while
2875  * pg_class_oid_index goes to the back of rebuildFirstList, so
2876  * they are done first and second respectively. Other nailed
2877  * relations go to the front of rebuildList, so they'll be done
2878  * next in no particular order; and everything else goes to the
2879  * back of rebuildList.
2880  */
2881  if (RelationGetRelid(relation) == RelationRelationId)
2882  rebuildFirstList = lcons(relation, rebuildFirstList);
2883  else if (RelationGetRelid(relation) == ClassOidIndexId)
2884  rebuildFirstList = lappend(rebuildFirstList, relation);
2885  else if (relation->rd_isnailed)
2886  rebuildList = lcons(relation, rebuildList);
2887  else
2888  rebuildList = lappend(rebuildList, relation);
2889  }
2890  }
2891 
2892  /*
2893  * Now zap any remaining smgr cache entries. This must happen before we
2894  * start to rebuild entries, since that may involve catalog fetches which
2895  * will re-open catalog files.
2896  */
2897  smgrcloseall();
2898 
2899  /* Phase 2: rebuild the items found to need rebuild in phase 1 */
2900  foreach(l, rebuildFirstList)
2901  {
2902  relation = (Relation) lfirst(l);
2903  RelationClearRelation(relation, true);
2904  }
2905  list_free(rebuildFirstList);
2906  foreach(l, rebuildList)
2907  {
2908  relation = (Relation) lfirst(l);
2909  RelationClearRelation(relation, true);
2910  }
2911  list_free(rebuildList);
2912 }
#define NIL
Definition: pg_list.h:65
static long relcacheInvalsReceived
Definition: relcache.c:152
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2418
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:1252
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:804
#define lfirst(lc)
Definition: pg_list.h:169
#define InvalidSubTransactionId
Definition: c.h:593
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 2775 of file relcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

2776 {
2777  Relation relation;
2778 
2779  RelationIdCacheLookup(relationId, relation);
2780 
2781  if (PointerIsValid(relation))
2782  {
2784  RelationFlushRelation(relation);
2785  }
2786 }
static long relcacheInvalsReceived
Definition: relcache.c:152
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:211
static void RelationFlushRelation(Relation relation)
Definition: relcache.c:2698
#define PointerIsValid(pointer)
Definition: c.h:698

◆ RelationClose()

void RelationClose ( Relation  relation)

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

2097 {
2098  /* Note: no locking manipulations needed */
2100 
2101  /*
2102  * If the relation is no longer open in this session, we can clean up any
2103  * stale partition descriptors it has. This is unlikely, so check to see
2104  * if there are child contexts before expending a call to mcxt.c.
2105  */
2106  if (RelationHasReferenceCountZero(relation) &&
2107  relation->rd_pdcxt != NULL &&
2108  relation->rd_pdcxt->firstchild != NULL)
2110 
2111 #ifdef RELCACHE_FORCE_RELEASE
2112  if (RelationHasReferenceCountZero(relation) &&
2113  relation->rd_createSubid == InvalidSubTransactionId &&
2115  RelationClearRelation(relation, false);
2116 #endif
2117 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2418
MemoryContext firstchild
Definition: memnodes.h:87
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2076
SubTransactionId rd_createSubid
Definition: rel.h:103
void MemoryContextDeleteChildren(MemoryContext context)
Definition: mcxt.c:263
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:106
MemoryContext rd_pdcxt
Definition: rel.h:130
#define InvalidSubTransactionId
Definition: c.h:593
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:441

◆ RelationCloseSmgrByOid()

void RelationCloseSmgrByOid ( Oid  relationId)

Definition at line 2921 of file relcache.c.

References PointerIsValid, RelationCloseSmgr, and RelationIdCacheLookup.

Referenced by swap_relation_files().

2922 {
2923  Relation relation;
2924 
2925  RelationIdCacheLookup(relationId, relation);
2926 
2927  if (!PointerIsValid(relation))
2928  return; /* not in cache, nothing to do */
2929 
2930  RelationCloseSmgr(relation);
2931 }
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:211
#define RelationCloseSmgr(relation)
Definition: rel.h:526
#define PointerIsValid(pointer)
Definition: c.h:698

◆ RelationForgetRelation()

void RelationForgetRelation ( Oid  rid)

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

2732 {
2733  Relation relation;
2734 
2735  RelationIdCacheLookup(rid, relation);
2736 
2737  if (!PointerIsValid(relation))
2738  return; /* not in cache, nothing to do */
2739 
2740  if (!RelationHasReferenceCountZero(relation))
2741  elog(ERROR, "relation %u is still open", rid);
2742 
2744  if (relation->rd_createSubid != InvalidSubTransactionId ||
2746  {
2747  /*
2748  * In the event of subtransaction rollback, we must not forget
2749  * rd_*Subid. Mark the entry "dropped" so RelationClearRelation()
2750  * invalidates it in lieu of destroying it. (If we're in a top
2751  * transaction, we could opt to destroy the entry.)
2752  */
2754  }
2755 
2756  RelationClearRelation(relation, false);
2757 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2418
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:211
#define ERROR
Definition: elog.h:46
SubTransactionId rd_createSubid
Definition: rel.h:103
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:106
#define Assert(condition)
Definition: c.h:804
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:723
#define InvalidSubTransactionId
Definition: c.h:593
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:441
#define elog(elevel,...)
Definition: elog.h:232
#define PointerIsValid(pointer)
Definition: c.h:698
SubTransactionId rd_droppedSubid
Definition: rel.h:108

◆ RelationGetDummyIndexExpressions()

List* RelationGetDummyIndexExpressions ( Relation  relation)

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

4845 {
4846  List *result;
4847  Datum exprsDatum;
4848  bool isnull;
4849  char *exprsString;
4850  List *rawExprs;
4851  ListCell *lc;
4852 
4853  /* Quick exit if there is nothing to do. */
4854  if (relation->rd_indextuple == NULL ||
4855  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indexprs, NULL))
4856  return NIL;
4857 
4858  /* Extract raw node tree(s) from index tuple. */
4859  exprsDatum = heap_getattr(relation->rd_indextuple,
4860  Anum_pg_index_indexprs,
4862  &isnull);
4863  Assert(!isnull);
4864  exprsString = TextDatumGetCString(exprsDatum);
4865  rawExprs = (List *) stringToNode(exprsString);
4866  pfree(exprsString);
4867 
4868  /* Construct null Consts; the typlen and typbyval are arbitrary. */
4869  result = NIL;
4870  foreach(lc, rawExprs)
4871  {
4872  Node *rawExpr = (Node *) lfirst(lc);
4873 
4874  result = lappend(result,
4875  makeConst(exprType(rawExpr),
4876  exprTypmod(rawExpr),
4877  exprCollation(rawExpr),
4878  1,
4879  (Datum) 0,
4880  true,
4881  true));
4882  }
4883 
4884  return result;
4885 }
#define NIL
Definition: pg_list.h:65
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:267
Definition: nodes.h:539
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:1169
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4213
List * lappend(List *list, void *datum)
Definition: list.c:336
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:761
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:411
#define Assert(condition)
Definition: c.h:804
#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 5219 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().

5223 {
5224  int indnkeyatts;
5225  Oid *ops;
5226  Oid *funcs;
5227  uint16 *strats;
5228  Relation conrel;
5229  SysScanDesc conscan;
5230  ScanKeyData skey[1];
5231  HeapTuple htup;
5232  bool found;
5233  MemoryContext oldcxt;
5234  int i;
5235 
5236  indnkeyatts = IndexRelationGetNumberOfKeyAttributes(indexRelation);
5237 
5238  /* Allocate result space in caller context */
5239  *operators = ops = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5240  *procs = funcs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5241  *strategies = strats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
5242 
5243  /* Quick exit if we have the data cached already */
5244  if (indexRelation->rd_exclstrats != NULL)
5245  {
5246  memcpy(ops, indexRelation->rd_exclops, sizeof(Oid) * indnkeyatts);
5247  memcpy(funcs, indexRelation->rd_exclprocs, sizeof(Oid) * indnkeyatts);
5248  memcpy(strats, indexRelation->rd_exclstrats, sizeof(uint16) * indnkeyatts);
5249  return;
5250  }
5251 
5252  /*
5253  * Search pg_constraint for the constraint associated with the index. To
5254  * make this not too painfully slow, we use the index on conrelid; that
5255  * will hold the parent relation's OID not the index's own OID.
5256  *
5257  * Note: if we wanted to rely on the constraint name matching the index's
5258  * name, we could just do a direct lookup using pg_constraint's unique
5259  * index. For the moment it doesn't seem worth requiring that.
5260  */
5261  ScanKeyInit(&skey[0],
5262  Anum_pg_constraint_conrelid,
5263  BTEqualStrategyNumber, F_OIDEQ,
5264  ObjectIdGetDatum(indexRelation->rd_index->indrelid));
5265 
5266  conrel = table_open(ConstraintRelationId, AccessShareLock);
5267  conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
5268  NULL, 1, skey);
5269  found = false;
5270 
5271  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
5272  {
5274  Datum val;
5275  bool isnull;
5276  ArrayType *arr;
5277  int nelem;
5278 
5279  /* We want the exclusion constraint owning the index */
5280  if (conform->contype != CONSTRAINT_EXCLUSION ||
5281  conform->conindid != RelationGetRelid(indexRelation))
5282  continue;
5283 
5284  /* There should be only one */
5285  if (found)
5286  elog(ERROR, "unexpected exclusion constraint record found for rel %s",
5287  RelationGetRelationName(indexRelation));
5288  found = true;
5289 
5290  /* Extract the operator OIDS from conexclop */
5291  val = fastgetattr(htup,
5292  Anum_pg_constraint_conexclop,
5293  conrel->rd_att, &isnull);
5294  if (isnull)
5295  elog(ERROR, "null conexclop for rel %s",
5296  RelationGetRelationName(indexRelation));
5297 
5298  arr = DatumGetArrayTypeP(val); /* ensure not toasted */
5299  nelem = ARR_DIMS(arr)[0];
5300  if (ARR_NDIM(arr) != 1 ||
5301  nelem != indnkeyatts ||
5302  ARR_HASNULL(arr) ||
5303  ARR_ELEMTYPE(arr) != OIDOID)
5304  elog(ERROR, "conexclop is not a 1-D Oid array");
5305 
5306  memcpy(ops, ARR_DATA_PTR(arr), sizeof(Oid) * indnkeyatts);
5307  }
5308 
5309  systable_endscan(conscan);
5310  table_close(conrel, AccessShareLock);
5311 
5312  if (!found)
5313  elog(ERROR, "exclusion constraint record missing for rel %s",
5314  RelationGetRelationName(indexRelation));
5315 
5316  /* We need the func OIDs and strategy numbers too */
5317  for (i = 0; i < indnkeyatts; i++)
5318  {
5319  funcs[i] = get_opcode(ops[i]);
5320  strats[i] = get_op_opfamily_strategy(ops[i],
5321  indexRelation->rd_opfamily[i]);
5322  /* shouldn't fail, since it was checked at index creation */
5323  if (strats[i] == InvalidStrategy)
5324  elog(ERROR, "could not find strategy for operator %u in family %u",
5325  ops[i], indexRelation->rd_opfamily[i]);
5326  }
5327 
5328  /* Save a copy of the results in the relcache entry. */
5329  oldcxt = MemoryContextSwitchTo(indexRelation->rd_indexcxt);
5330  indexRelation->rd_exclops = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5331  indexRelation->rd_exclprocs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5332  indexRelation->rd_exclstrats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
5333  memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * indnkeyatts);
5334  memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * indnkeyatts);
5335  memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * indnkeyatts);
5336  MemoryContextSwitchTo(oldcxt);
5337 }
#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:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:711
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:383
Form_pg_index rd_index
Definition: rel.h:175
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
unsigned short uint16
Definition: c.h:440
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#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:411
TupleDesc rd_att
Definition: rel.h:111
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1256
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:1062
#define elog(elevel,...)
Definition: elog.h:232
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 4442 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(), CloneFkReferencing(), DetachPartitionFinalize(), and get_relation_foreign_keys().

4443 {
4444  List *result;
4445  Relation conrel;
4446  SysScanDesc conscan;
4447  ScanKeyData skey;
4448  HeapTuple htup;
4449  List *oldlist;
4450  MemoryContext oldcxt;
4451 
4452  /* Quick exit if we already computed the list. */
4453  if (relation->rd_fkeyvalid)
4454  return relation->rd_fkeylist;
4455 
4456  /* Fast path: non-partitioned tables without triggers can't have FKs */
4457  if (!relation->rd_rel->relhastriggers &&
4458  relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
4459  return NIL;
4460 
4461  /*
4462  * We build the list we intend to return (in the caller's context) while
4463  * doing the scan. After successfully completing the scan, we copy that
4464  * list into the relcache entry. This avoids cache-context memory leakage
4465  * if we get some sort of error partway through.
4466  */
4467  result = NIL;
4468 
4469  /* Prepare to scan pg_constraint for entries having conrelid = this rel. */
4470  ScanKeyInit(&skey,
4471  Anum_pg_constraint_conrelid,
4472  BTEqualStrategyNumber, F_OIDEQ,
4473  ObjectIdGetDatum(RelationGetRelid(relation)));
4474 
4475  conrel = table_open(ConstraintRelationId, AccessShareLock);
4476  conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
4477  NULL, 1, &skey);
4478 
4479  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4480  {
4481  Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(htup);
4482  ForeignKeyCacheInfo *info;
4483 
4484  /* consider only foreign keys */
4485  if (constraint->contype != CONSTRAINT_FOREIGN)
4486  continue;
4487 
4488  info = makeNode(ForeignKeyCacheInfo);
4489  info->conoid = constraint->oid;
4490  info->conrelid = constraint->conrelid;
4491  info->confrelid = constraint->confrelid;
4492 
4493  DeconstructFkConstraintRow(htup, &info->nkeys,
4494  info->conkey,
4495  info->confkey,
4496  info->conpfeqop,
4497  NULL, NULL);
4498 
4499  /* Add FK's node to the result list */
4500  result = lappend(result, info);
4501  }
4502 
4503  systable_endscan(conscan);
4504  table_close(conrel, AccessShareLock);
4505 
4506  /* Now save a copy of the completed list in the relcache entry. */
4508  oldlist = relation->rd_fkeylist;
4509  relation->rd_fkeylist = copyObject(result);
4510  relation->rd_fkeyvalid = true;
4511  MemoryContextSwitchTo(oldcxt);
4512 
4513  /* Don't leak the old list, if there is one */
4514  list_free_deep(oldlist);
4515 
4516  return result;
4517 }
#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:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
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:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ConstraintRelidTypidNameIndexId
List * lappend(List *list, void *datum)
Definition: list.c:336
#define makeNode(_type_)
Definition: nodes.h:587
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:655
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:51

◆ RelationGetIndexAttOptions()

bytea** RelationGetIndexAttOptions ( Relation  relation,
bool  copy 
)

Definition at line 5473 of file relcache.c.

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

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

5474 {
5475  MemoryContext oldcxt;
5476  bytea **opts = relation->rd_opcoptions;
5477  Oid relid = RelationGetRelid(relation);
5478  int natts = RelationGetNumberOfAttributes(relation); /* XXX
5479  * IndexRelationGetNumberOfKeyAttributes */
5480  int i;
5481 
5482  /* Try to copy cached options. */
5483  if (opts)
5484  return copy ? CopyIndexAttOptions(opts, natts) : opts;
5485 
5486  /* Get and parse opclass options. */
5487  opts = palloc0(sizeof(*opts) * natts);
5488 
5489  for (i = 0; i < natts; i++)
5490  {
5492  {
5493  Datum attoptions = get_attoptions(relid, i + 1);
5494 
5495  opts[i] = index_opclass_options(relation, i + 1, attoptions, false);
5496 
5497  if (attoptions != (Datum) 0)
5498  pfree(DatumGetPointer(attoptions));
5499  }
5500  }
5501 
5502  /* Copy parsed options to the cache. */
5503  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
5504  relation->rd_opcoptions = CopyIndexAttOptions(opts, natts);
5505  MemoryContextSwitchTo(oldcxt);
5506 
5507  if (copy)
5508  return opts;
5509 
5510  for (i = 0; i < natts; i++)
5511  {
5512  if (opts[i])
5513  pfree(opts[i]);
5514  }
5515 
5516  pfree(opts);
5517 
5518  return relation->rd_opcoptions;
5519 }
#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:995
void pfree(void *pointer)
Definition: mcxt.c:1169
#define AttributeRelidNumIndexId
Definition: pg_attribute.h:208
static bytea ** CopyIndexAttOptions(bytea **srcopts, int natts)
Definition: relcache.c:5453
bytea * index_opclass_options(Relation indrel, AttrNumber attnum, Datum attoptions, bool validate)
Definition: indexam.c:939
static AmcheckOptions opts
Definition: pg_amcheck.c:103
void * palloc0(Size size)
Definition: mcxt.c:1093
uintptr_t Datum
Definition: postgres.h:411
#define DatumGetPointer(X)
Definition: postgres.h:593
MemoryContext rd_indexcxt
Definition: rel.h:187
int i
Definition: c.h:621
bool criticalRelcachesBuilt
Definition: relcache.c:138
#define RelationGetRelid(relation)
Definition: rel.h:457

◆ RelationGetIndexAttrBitmap()

Bitmapset* RelationGetIndexAttrBitmap ( Relation  relation,
IndexAttrBitmapKind  attrKind 
)

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

4982 {
4983  Bitmapset *indexattrs; /* indexed columns */
4984  Bitmapset *uindexattrs; /* columns in unique indexes */
4985  Bitmapset *pkindexattrs; /* columns in the primary index */
4986  Bitmapset *idindexattrs; /* columns in the replica identity */
4987  List *indexoidlist;
4988  List *newindexoidlist;
4989  Oid relpkindex;
4990  Oid relreplindex;
4991  ListCell *l;
4992  MemoryContext oldcxt;
4993 
4994  /* Quick exit if we already computed the result. */
4995  if (relation->rd_indexattr != NULL)
4996  {
4997  switch (attrKind)
4998  {
4999  case INDEX_ATTR_BITMAP_ALL:
5000  return bms_copy(relation->rd_indexattr);
5001  case INDEX_ATTR_BITMAP_KEY:
5002  return bms_copy(relation->rd_keyattr);
5004  return bms_copy(relation->rd_pkattr);
5006  return bms_copy(relation->rd_idattr);
5007  default:
5008  elog(ERROR, "unknown attrKind %u", attrKind);
5009  }
5010  }
5011 
5012  /* Fast path if definitely no indexes */
5013  if (!RelationGetForm(relation)->relhasindex)
5014  return NULL;
5015 
5016  /*
5017  * Get cached list of index OIDs. If we have to start over, we do so here.
5018  */
5019 restart:
5020  indexoidlist = RelationGetIndexList(relation);
5021 
5022  /* Fall out if no indexes (but relhasindex was set) */
5023  if (indexoidlist == NIL)
5024  return NULL;
5025 
5026  /*
5027  * Copy the rd_pkindex and rd_replidindex values computed by
5028  * RelationGetIndexList before proceeding. This is needed because a
5029  * relcache flush could occur inside index_open below, resetting the
5030  * fields managed by RelationGetIndexList. We need to do the work with
5031  * stable values of these fields.
5032  */
5033  relpkindex = relation->rd_pkindex;
5034  relreplindex = relation->rd_replidindex;
5035 
5036  /*
5037  * For each index, add referenced attributes to indexattrs.
5038  *
5039  * Note: we consider all indexes returned by RelationGetIndexList, even if
5040  * they are not indisready or indisvalid. This is important because an
5041  * index for which CREATE INDEX CONCURRENTLY has just started must be
5042  * included in HOT-safety decisions (see README.HOT). If a DROP INDEX
5043  * CONCURRENTLY is far enough along that we should ignore the index, it
5044  * won't be returned at all by RelationGetIndexList.
5045  */
5046  indexattrs = NULL;
5047  uindexattrs = NULL;
5048  pkindexattrs = NULL;
5049  idindexattrs = NULL;
5050  foreach(l, indexoidlist)
5051  {
5052  Oid indexOid = lfirst_oid(l);
5053  Relation indexDesc;
5054  Datum datum;
5055  bool isnull;
5056  Node *indexExpressions;
5057  Node *indexPredicate;
5058  int i;
5059  bool isKey; /* candidate key */
5060  bool isPK; /* primary key */
5061  bool isIDKey; /* replica identity index */
5062 
5063  indexDesc = index_open(indexOid, AccessShareLock);
5064 
5065  /*
5066  * Extract index expressions and index predicate. Note: Don't use
5067  * RelationGetIndexExpressions()/RelationGetIndexPredicate(), because
5068  * those might run constant expressions evaluation, which needs a
5069  * snapshot, which we might not have here. (Also, it's probably more
5070  * sound to collect the bitmaps before any transformations that might
5071  * eliminate columns, but the practical impact of this is limited.)
5072  */
5073 
5074  datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indexprs,
5075  GetPgIndexDescriptor(), &isnull);
5076  if (!isnull)
5077  indexExpressions = stringToNode(TextDatumGetCString(datum));
5078  else
5079  indexExpressions = NULL;
5080 
5081  datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indpred,
5082  GetPgIndexDescriptor(), &isnull);
5083  if (!isnull)
5084  indexPredicate = stringToNode(TextDatumGetCString(datum));
5085  else
5086  indexPredicate = NULL;
5087 
5088  /* Can this index be referenced by a foreign key? */
5089  isKey = indexDesc->rd_index->indisunique &&
5090  indexExpressions == NULL &&
5091  indexPredicate == NULL;
5092 
5093  /* Is this a primary key? */
5094  isPK = (indexOid == relpkindex);
5095 
5096  /* Is this index the configured (or default) replica identity? */
5097  isIDKey = (indexOid == relreplindex);
5098 
5099  /* Collect simple attribute references */
5100  for (i = 0; i < indexDesc->rd_index->indnatts; i++)
5101  {
5102  int attrnum = indexDesc->rd_index->indkey.values[i];
5103 
5104  /*
5105  * Since we have covering indexes with non-key columns, we must
5106  * handle them accurately here. non-key columns must be added into
5107  * indexattrs, since they are in index, and HOT-update shouldn't
5108  * miss them. Obviously, non-key columns couldn't be referenced by
5109  * foreign key or identity key. Hence we do not include them into
5110  * uindexattrs, pkindexattrs and idindexattrs bitmaps.
5111  */
5112  if (attrnum != 0)
5113  {
5114  indexattrs = bms_add_member(indexattrs,
5116 
5117  if (isKey && i < indexDesc->rd_index->indnkeyatts)
5118  uindexattrs = bms_add_member(uindexattrs,
5120 
5121  if (isPK && i < indexDesc->rd_index->indnkeyatts)
5122  pkindexattrs = bms_add_member(pkindexattrs,
5124 
5125  if (isIDKey && i < indexDesc->rd_index->indnkeyatts)
5126  idindexattrs = bms_add_member(idindexattrs,
5128  }
5129  }
5130 
5131  /* Collect all attributes used in expressions, too */
5132  pull_varattnos(indexExpressions, 1, &indexattrs);
5133 
5134  /* Collect all attributes in the index predicate, too */
5135  pull_varattnos(indexPredicate, 1, &indexattrs);
5136 
5137  index_close(indexDesc, AccessShareLock);
5138  }
5139 
5140  /*
5141  * During one of the index_opens in the above loop, we might have received
5142  * a relcache flush event on this relcache entry, which might have been
5143  * signaling a change in the rel's index list. If so, we'd better start
5144  * over to ensure we deliver up-to-date attribute bitmaps.
5145  */
5146  newindexoidlist = RelationGetIndexList(relation);
5147  if (equal(indexoidlist, newindexoidlist) &&
5148  relpkindex == relation->rd_pkindex &&
5149  relreplindex == relation->rd_replidindex)
5150  {
5151  /* Still the same index set, so proceed */
5152  list_free(newindexoidlist);
5153  list_free(indexoidlist);
5154  }
5155  else
5156  {
5157  /* Gotta do it over ... might as well not leak memory */
5158  list_free(newindexoidlist);
5159  list_free(indexoidlist);
5160  bms_free(uindexattrs);
5161  bms_free(pkindexattrs);
5162  bms_free(idindexattrs);
5163  bms_free(indexattrs);
5164 
5165  goto restart;
5166  }
5167 
5168  /* Don't leak the old values of these bitmaps, if any */
5169  bms_free(relation->rd_indexattr);
5170  relation->rd_indexattr = NULL;
5171  bms_free(relation->rd_keyattr);
5172  relation->rd_keyattr = NULL;
5173  bms_free(relation->rd_pkattr);
5174  relation->rd_pkattr = NULL;
5175  bms_free(relation->rd_idattr);
5176  relation->rd_idattr = NULL;
5177 
5178  /*
5179  * Now save copies of the bitmaps in the relcache entry. We intentionally
5180  * set rd_indexattr last, because that's the one that signals validity of
5181  * the values; if we run out of memory before making that copy, we won't
5182  * leave the relcache entry looking like the other ones are valid but
5183  * empty.
5184  */
5186  relation->rd_keyattr = bms_copy(uindexattrs);
5187  relation->rd_pkattr = bms_copy(pkindexattrs);
5188  relation->rd_idattr = bms_copy(idindexattrs);
5189  relation->rd_indexattr = bms_copy(indexattrs);
5190  MemoryContextSwitchTo(oldcxt);
5191 
5192  /* We return our original working copy for caller to play with */
5193  switch (attrKind)
5194  {
5195  case INDEX_ATTR_BITMAP_ALL:
5196  return indexattrs;
5197  case INDEX_ATTR_BITMAP_KEY:
5198  return uindexattrs;
5200  return pkindexattrs;
5202  return idindexattrs;
5203  default:
5204  elog(ERROR, "unknown attrKind %u", attrKind);
5205  return NULL;
5206  }
5207 }
#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:3105
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:539
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:46
Oid rd_pkindex
Definition: rel.h:139
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4213
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:761
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:411
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:4551
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:232
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:51

◆ RelationGetIndexExpressions()

List* RelationGetIndexExpressions ( Relation  relation)

Definition at line 4785 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(), GetIndexInputType(), index_unchanged_by_update(), infer_arbiter_indexes(), plan_create_index_workers(), and transformIndexConstraint().

4786 {
4787  List *result;
4788  Datum exprsDatum;
4789  bool isnull;
4790  char *exprsString;
4791  MemoryContext oldcxt;
4792 
4793  /* Quick exit if we already computed the result. */
4794  if (relation->rd_indexprs)
4795  return copyObject(relation->rd_indexprs);
4796 
4797  /* Quick exit if there is nothing to do. */
4798  if (relation->rd_indextuple == NULL ||
4799  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indexprs, NULL))
4800  return NIL;
4801 
4802  /*
4803  * We build the tree we intend to return in the caller's context. After
4804  * successfully completing the work, we copy it into the relcache entry.
4805  * This avoids problems if we get some sort of error partway through.
4806  */
4807  exprsDatum = heap_getattr(relation->rd_indextuple,
4808  Anum_pg_index_indexprs,
4810  &isnull);
4811  Assert(!isnull);
4812  exprsString = TextDatumGetCString(exprsDatum);
4813  result = (List *) stringToNode(exprsString);
4814  pfree(exprsString);
4815 
4816  /*
4817  * Run the expressions through eval_const_expressions. This is not just an
4818  * optimization, but is necessary, because the planner will be comparing
4819  * them to similarly-processed qual clauses, and may fail to detect valid
4820  * matches without this. We must not use canonicalize_qual, however,
4821  * since these aren't qual expressions.
4822  */
4823  result = (List *) eval_const_expressions(NULL, (Node *) result);
4824 
4825  /* May as well fix opfuncids too */
4826  fix_opfuncids((Node *) result);
4827 
4828  /* Now save a copy of the completed tree in the relcache entry. */
4829  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4830  relation->rd_indexprs = copyObject(result);
4831  MemoryContextSwitchTo(oldcxt);
4832 
4833  return result;
4834 }
#define NIL
Definition: pg_list.h:65
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1652
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
List * rd_indexprs
Definition: rel.h:195
Definition: nodes.h:539
void * stringToNode(const char *str)
Definition: read.c:89
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2090
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:1169
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4213
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:761
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:411
#define Assert(condition)
Definition: c.h:804
MemoryContext rd_indexcxt
Definition: rel.h:187
#define copyObject(obj)
Definition: nodes.h:655
Definition: pg_list.h:50

◆ RelationGetIndexList()

List* RelationGetIndexList ( Relation  relation)

Definition at line 4551 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(), ATExecDropNotNull(), ATExecSetTableSpace(), AttachPartitionEnsureIndexes(), calculate_indexes_size(), calculate_toast_table_size(), cluster(), DefineIndex(), DefineRelation(), DetachPartitionFinalize(), 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(), SetIndexStorageProperties(), toast_open_indexes(), transformFkeyCheckAttrs(), transformFkeyGetPrimaryKey(), triggered_change_notification(), and vac_open_indexes().

4552 {
4553  Relation indrel;
4554  SysScanDesc indscan;
4555  ScanKeyData skey;
4556  HeapTuple htup;
4557  List *result;
4558  List *oldlist;
4559  char replident = relation->rd_rel->relreplident;
4560  Oid pkeyIndex = InvalidOid;
4561  Oid candidateIndex = InvalidOid;
4562  MemoryContext oldcxt;
4563 
4564  /* Quick exit if we already computed the list. */
4565  if (relation->rd_indexvalid)
4566  return list_copy(relation->rd_indexlist);
4567 
4568  /*
4569  * We build the list we intend to return (in the caller's context) while
4570  * doing the scan. After successfully completing the scan, we copy that
4571  * list into the relcache entry. This avoids cache-context memory leakage
4572  * if we get some sort of error partway through.
4573  */
4574  result = NIL;
4575 
4576  /* Prepare to scan pg_index for entries having indrelid = this rel. */
4577  ScanKeyInit(&skey,
4578  Anum_pg_index_indrelid,
4579  BTEqualStrategyNumber, F_OIDEQ,
4580  ObjectIdGetDatum(RelationGetRelid(relation)));
4581 
4582  indrel = table_open(IndexRelationId, AccessShareLock);
4583  indscan = systable_beginscan(indrel, IndexIndrelidIndexId, true,
4584  NULL, 1, &skey);
4585 
4586  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4587  {
4589 
4590  /*
4591  * Ignore any indexes that are currently being dropped. This will
4592  * prevent them from being searched, inserted into, or considered in
4593  * HOT-safety decisions. It's unsafe to touch such an index at all
4594  * since its catalog entries could disappear at any instant.
4595  */
4596  if (!index->indislive)
4597  continue;
4598 
4599  /* add index's OID to result list */
4600  result = lappend_oid(result, index->indexrelid);
4601 
4602  /*
4603  * Invalid, non-unique, non-immediate or predicate indexes aren't
4604  * interesting for either oid indexes or replication identity indexes,
4605  * so don't check them.
4606  */
4607  if (!index->indisvalid || !index->indisunique ||
4608  !index->indimmediate ||
4609  !heap_attisnull(htup, Anum_pg_index_indpred, NULL))
4610  continue;
4611 
4612  /* remember primary key index if any */
4613  if (index->indisprimary)
4614  pkeyIndex = index->indexrelid;
4615 
4616  /* remember explicitly chosen replica index */
4617  if (index->indisreplident)
4618  candidateIndex = index->indexrelid;
4619  }
4620 
4621  systable_endscan(indscan);
4622 
4623  table_close(indrel, AccessShareLock);
4624 
4625  /* Sort the result list into OID order, per API spec. */
4626  list_sort(result, list_oid_cmp);
4627 
4628  /* Now save a copy of the completed list in the relcache entry. */
4630  oldlist = relation->rd_indexlist;
4631  relation->rd_indexlist = list_copy(result);
4632  relation->rd_pkindex = pkeyIndex;
4633  if (replident == REPLICA_IDENTITY_DEFAULT && OidIsValid(pkeyIndex))
4634  relation->rd_replidindex = pkeyIndex;
4635  else if (replident == REPLICA_IDENTITY_INDEX && OidIsValid(candidateIndex))
4636  relation->rd_replidindex = candidateIndex;
4637  else
4638  relation->rd_replidindex = InvalidOid;
4639  relation->rd_indexvalid = true;
4640  MemoryContextSwitchTo(oldcxt);
4641 
4642  /* Don't leak the old list, if there is one */
4643  list_free(oldlist);
4644 
4645  return result;
4646 }
#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:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
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:72
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:710
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
Definition: type.h:89
int list_oid_cmp(const ListCell *p1, const ListCell *p2)
Definition: list.c:1529
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
Oid rd_pkindex
Definition: rel.h:139
List * rd_indexlist
Definition: rel.h:138
FormData_pg_index * Form_pg_index
Definition: pg_index.h:69
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:51

◆ RelationGetIndexPredicate()

List* RelationGetIndexPredicate ( Relation  relation)

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

4899 {
4900  List *result;
4901  Datum predDatum;
4902  bool isnull;
4903  char *predString;
4904  MemoryContext oldcxt;
4905 
4906  /* Quick exit if we already computed the result. */
4907  if (relation->rd_indpred)
4908  return copyObject(relation->rd_indpred);
4909 
4910  /* Quick exit if there is nothing to do. */
4911  if (relation->rd_indextuple == NULL ||
4912  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indpred, NULL))
4913  return NIL;
4914 
4915  /*
4916  * We build the tree we intend to return in the caller's context. After
4917  * successfully completing the work, we copy it into the relcache entry.
4918  * This avoids problems if we get some sort of error partway through.
4919  */
4920  predDatum = heap_getattr(relation->rd_indextuple,
4921  Anum_pg_index_indpred,
4923  &isnull);
4924  Assert(!isnull);
4925  predString = TextDatumGetCString(predDatum);
4926  result = (List *) stringToNode(predString);
4927  pfree(predString);
4928 
4929  /*
4930  * Run the expression through const-simplification and canonicalization.
4931  * This is not just an optimization, but is necessary, because the planner
4932  * will be comparing it to similarly-processed qual clauses, and may fail
4933  * to detect valid matches without this. This must match the processing
4934  * done to qual clauses in preprocess_expression()! (We can skip the
4935  * stuff involving subqueries, however, since we don't allow any in index
4936  * predicates.)
4937  */
4938  result = (List *) eval_const_expressions(NULL, (Node *) result);
4939 
4940  result = (List *) canonicalize_qual((Expr *) result, false);
4941 
4942  /* Also convert to implicit-AND format */
4943  result = make_ands_implicit((Expr *) result);
4944 
4945  /* May as well fix opfuncids too */
4946  fix_opfuncids((Node *) result);
4947 
4948  /* Now save a copy of the completed tree in the relcache entry. */
4949  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4950  relation->rd_indpred = copyObject(result);
4951  MemoryContextSwitchTo(oldcxt);
4952 
4953  return result;
4954 }
#define NIL
Definition: pg_list.h:65
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1652
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:539
void * stringToNode(const char *str)
Definition: read.c:89
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2090
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:1169
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4213
Expr * canonicalize_qual(Expr *qual, bool is_check)
Definition: prepqual.c:293
List * rd_indpred
Definition: rel.h:196
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:761
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:411
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:719
#define Assert(condition)
Definition: c.h:804
MemoryContext rd_indexcxt
Definition: rel.h:187
#define copyObject(obj)
Definition: nodes.h:655
Definition: pg_list.h:50

◆ RelationGetIndexRawAttOptions()

Datum* RelationGetIndexRawAttOptions ( Relation  relation)

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

5428 {
5429  Oid indexrelid = RelationGetRelid(indexrel);
5430  int16 natts = RelationGetNumberOfAttributes(indexrel);
5431  Datum *options = NULL;
5432  int16 attnum;
5433 
5434  for (attnum = 1; attnum <= natts; attnum++)
5435  {
5436  if (indexrel->rd_indam->amoptsprocnum == 0)
5437  continue;
5438 
5439  if (!OidIsValid(index_getprocid(indexrel, attnum,
5440  indexrel->rd_indam->amoptsprocnum)))
5441  continue;
5442 
5443  if (!options)
5444  options = palloc0(sizeof(Datum) * natts);
5445 
5446  options[attnum - 1] = get_attoptions(indexrelid, attnum);
5447  }
5448 
5449  return options;
5450 }
signed short int16
Definition: c.h:428
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:463
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
Datum get_attoptions(Oid relid, int16 attnum)
Definition: lsyscache.c:995
static char ** options
void * palloc0(Size size)
Definition: mcxt.c:1093
uintptr_t Datum
Definition: postgres.h:411
int16 attnum
Definition: pg_attribute.h:83
#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 4739 of file relcache.c.

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

Referenced by build_replindex_scan_key(), and GetRelationIdentityOrPK().

4740 {
4741  List *ilist;
4742 
4743  if (!relation->rd_indexvalid)
4744  {
4745  /* RelationGetIndexList does the heavy lifting. */
4746  ilist = RelationGetIndexList(relation);
4747  list_free(ilist);
4748  Assert(relation->rd_indexvalid);
4749  }
4750 
4751  return relation->rd_pkindex;
4752 }
Oid rd_pkindex
Definition: rel.h:139
bool rd_indexvalid
Definition: rel.h:63
#define Assert(condition)
Definition: c.h:804
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4551
void list_free(List *list)
Definition: list.c:1391
Definition: pg_list.h:50

◆ RelationGetReplicaIndex()

Oid RelationGetReplicaIndex ( Relation  relation)

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

4761 {
4762  List *ilist;
4763 
4764  if (!relation->rd_indexvalid)
4765  {
4766  /* RelationGetIndexList does the heavy lifting. */
4767  ilist = RelationGetIndexList(relation);
4768  list_free(ilist);
4769  Assert(relation->rd_indexvalid);
4770  }
4771 
4772  return relation->rd_replidindex;
4773 }
Oid rd_replidindex
Definition: rel.h:140
bool rd_indexvalid
Definition: rel.h:63
#define Assert(condition)
Definition: c.h:804
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4551
void list_free(List *list)
Definition: list.c:1391
Definition: pg_list.h:50

◆ RelationGetStatExtList()

List* RelationGetStatExtList ( Relation  relation)

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

4671 {
4672  Relation indrel;
4673  SysScanDesc indscan;
4674  ScanKeyData skey;
4675  HeapTuple htup;
4676  List *result;
4677  List *oldlist;
4678  MemoryContext oldcxt;
4679 
4680  /* Quick exit if we already computed the list. */
4681  if (relation->rd_statvalid != 0)
4682  return list_copy(relation->rd_statlist);
4683 
4684  /*
4685  * We build the list we intend to return (in the caller's context) while
4686  * doing the scan. After successfully completing the scan, we copy that
4687  * list into the relcache entry. This avoids cache-context memory leakage
4688  * if we get some sort of error partway through.
4689  */
4690  result = NIL;
4691 
4692  /*
4693  * Prepare to scan pg_statistic_ext for entries having stxrelid = this
4694  * rel.
4695  */
4696  ScanKeyInit(&skey,
4697  Anum_pg_statistic_ext_stxrelid,
4698  BTEqualStrategyNumber, F_OIDEQ,
4699  ObjectIdGetDatum(RelationGetRelid(relation)));
4700 
4701  indrel = table_open(StatisticExtRelationId, AccessShareLock);
4702  indscan = systable_beginscan(indrel, StatisticExtRelidIndexId, true,
4703  NULL, 1, &skey);
4704 
4705  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4706  {
4707  Oid oid = ((Form_pg_statistic_ext) GETSTRUCT(htup))->oid;
4708 
4709  result = lappend_oid(result, oid);
4710  }
4711 
4712  systable_endscan(indscan);
4713 
4714  table_close(indrel, AccessShareLock);
4715 
4716  /* Sort the result list into OID order, per API spec. */
4717  list_sort(result, list_oid_cmp);
4718 
4719  /* Now save a copy of the completed list in the relcache entry. */
4721  oldlist = relation->rd_statlist;
4722  relation->rd_statlist = list_copy(result);
4723 
4724  relation->rd_statvalid = true;
4725  MemoryContextSwitchTo(oldcxt);
4726 
4727  /* Don't leak the old list, if there is one */
4728  list_free(oldlist);
4729 
4730  return result;
4731 }
#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:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
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:383
int list_oid_cmp(const ListCell *p1, const ListCell *p2)
Definition: list.c:1529
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#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:51

◆ RelationIdGetRelation()

Relation RelationIdGetRelation ( Oid  relationId)

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

1991 {
1992  Relation rd;
1993 
1994  /* Make sure we're in an xact, even if this ends up being a cache hit */
1996 
1997  /*
1998  * first try to find reldesc in the cache
1999  */
2000  RelationIdCacheLookup(relationId, rd);
2001 
2002  if (RelationIsValid(rd))
2003  {
2004  /* return NULL for dropped relations */
2006  {
2007  Assert(!rd->rd_isvalid);
2008  return NULL;
2009  }
2010 
2012  /* revalidate cache entry if necessary */
2013  if (!rd->rd_isvalid)
2014  {
2015  /*
2016  * Indexes only have a limited number of possible schema changes,
2017  * and we don't want to use the full-blown procedure because it's
2018  * a headache for indexes that reload itself depends on.
2019  */
2020  if (rd->rd_rel->relkind == RELKIND_INDEX ||
2021  rd->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
2023  else
2024  RelationClearRelation(rd, true);
2025 
2026  /*
2027  * Normally entries need to be valid here, but before the relcache
2028  * has been initialized, not enough infrastructure exists to
2029  * perform pg_class lookups. The structure of such entries doesn't
2030  * change, but we still want to update the rd_rel entry. So
2031  * rd_isvalid = false is left in place for a later lookup.
2032  */
2033  Assert(rd->rd_isvalid ||
2035  }
2036  return rd;
2037  }
2038 
2039  /*
2040  * no reldesc in the cache, so have RelationBuildDesc() build one and add
2041  * it.
2042  */
2043  rd = RelationBuildDesc(relationId, true);
2044  if (RelationIsValid(rd))
2046  return rd;
2047 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2418
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:2063
static void RelationReloadIndexInfo(Relation relation)
Definition: relcache.c:2147
#define Assert(condition)
Definition: c.h:804
static Relation RelationBuildDesc(Oid targetRelId, bool insertIt)
Definition: relcache.c:1002
bool IsTransactionState(void)
Definition: xact.c:371
#define InvalidSubTransactionId
Definition: c.h:593
bool criticalRelcachesBuilt
Definition: relcache.c:138
SubTransactionId rd_droppedSubid
Definition: rel.h:108

◆ RelationIdIsInInitFile()

bool RelationIdIsInInitFile ( Oid  relationId)

Definition at line 6296 of file relcache.c.

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

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

6297 {
6298  if (relationId == SharedSecLabelRelationId ||
6299  relationId == TriggerRelidNameIndexId ||
6300  relationId == DatabaseNameIndexId ||
6301  relationId == SharedSecLabelObjectIndexId)
6302  {
6303  /*
6304  * If this Assert fails, we don't need the applicable special case
6305  * anymore.
6306  */
6307  Assert(!RelationSupportsSysCache(relationId));
6308  return true;
6309  }
6310  return RelationSupportsSysCache(relationId);
6311 }
#define TriggerRelidNameIndexId
Definition: pg_trigger.h:87
#define DatabaseNameIndexId
Definition: pg_database.h:88
#define SharedSecLabelObjectIndexId
Definition: pg_shseclabel.h:47
#define Assert(condition)
Definition: c.h:804
bool RelationSupportsSysCache(Oid relid)
Definition: syscache.c:1532

◆ RelationInitIndexAccessInfo()

void RelationInitIndexAccessInfo ( Relation  relation)

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

1359 {
1360  HeapTuple tuple;
1361  Form_pg_am aform;
1362  Datum indcollDatum;
1363  Datum indclassDatum;
1364  Datum indoptionDatum;
1365  bool isnull;
1366  oidvector *indcoll;
1367  oidvector *indclass;
1368  int2vector *indoption;
1369  MemoryContext indexcxt;
1370  MemoryContext oldcontext;
1371  int indnatts;
1372  int indnkeyatts;
1373  uint16 amsupport;
1374 
1375  /*
1376  * Make a copy of the pg_index entry for the index. Since pg_index
1377  * contains variable-length and possibly-null fields, we have to do this
1378  * honestly rather than just treating it as a Form_pg_index struct.
1379  */
1380  tuple = SearchSysCache1(INDEXRELID,
1381  ObjectIdGetDatum(RelationGetRelid(relation)));
1382  if (!HeapTupleIsValid(tuple))
1383  elog(ERROR, "cache lookup failed for index %u",
1384  RelationGetRelid(relation));
1386  relation->rd_indextuple = heap_copytuple(tuple);
1387  relation->rd_index = (Form_pg_index) GETSTRUCT(relation->rd_indextuple);
1388  MemoryContextSwitchTo(oldcontext);
1389  ReleaseSysCache(tuple);
1390 
1391  /*
1392  * Look up the index's access method, save the OID of its handler function
1393  */
1394  tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(relation->rd_rel->relam));
1395  if (!HeapTupleIsValid(tuple))
1396  elog(ERROR, "cache lookup failed for access method %u",
1397  relation->rd_rel->relam);
1398  aform = (Form_pg_am) GETSTRUCT(tuple);
1399  relation->rd_amhandler = aform->amhandler;
1400  ReleaseSysCache(tuple);
1401 
1402  indnatts = RelationGetNumberOfAttributes(relation);
1403  if (indnatts != IndexRelationGetNumberOfAttributes(relation))
1404  elog(ERROR, "relnatts disagrees with indnatts for index %u",
1405  RelationGetRelid(relation));
1406  indnkeyatts = IndexRelationGetNumberOfKeyAttributes(relation);
1407 
1408  /*
1409  * Make the private context to hold index access info. The reason we need
1410  * a context, and not just a couple of pallocs, is so that we won't leak
1411  * any subsidiary info attached to fmgr lookup records.
1412  */
1414  "index info",
1416  relation->rd_indexcxt = indexcxt;
1418  RelationGetRelationName(relation));
1419 
1420  /*
1421  * Now we can fetch the index AM's API struct
1422  */
1423  InitIndexAmRoutine(relation);
1424 
1425  /*
1426  * Allocate arrays to hold data. Opclasses are not used for included
1427  * columns, so allocate them for indnkeyatts only.
1428  */
1429  relation->rd_opfamily = (Oid *)
1430  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1431  relation->rd_opcintype = (Oid *)
1432  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1433 
1434  amsupport = relation->rd_indam->amsupport;
1435  if (amsupport > 0)
1436  {
1437  int nsupport = indnatts * amsupport;
1438 
1439  relation->rd_support = (RegProcedure *)
1440  MemoryContextAllocZero(indexcxt, nsupport * sizeof(RegProcedure));
1441  relation->rd_supportinfo = (FmgrInfo *)
1442  MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
1443  }
1444  else
1445  {
1446  relation->rd_support = NULL;
1447  relation->rd_supportinfo = NULL;
1448  }
1449 
1450  relation->rd_indcollation = (Oid *)
1451  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1452 
1453  relation->rd_indoption = (int16 *)
1454  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(int16));
1455 
1456  /*
1457  * indcollation cannot be referenced directly through the C struct,
1458  * because it comes after the variable-width indkey field. Must extract
1459  * the datum the hard way...
1460  */
1461  indcollDatum = fastgetattr(relation->rd_indextuple,
1462  Anum_pg_index_indcollation,
1464  &isnull);
1465  Assert(!isnull);
1466  indcoll = (oidvector *) DatumGetPointer(indcollDatum);
1467  memcpy(relation->rd_indcollation, indcoll->values, indnkeyatts * sizeof(Oid));
1468 
1469  /*
1470  * indclass cannot be referenced directly through the C struct, because it
1471  * comes after the variable-width indkey field. Must extract the datum
1472  * the hard way...
1473  */
1474  indclassDatum = fastgetattr(relation->rd_indextuple,
1475  Anum_pg_index_indclass,
1477  &isnull);
1478  Assert(!isnull);
1479  indclass = (oidvector *) DatumGetPointer(indclassDatum);
1480 
1481  /*
1482  * Fill the support procedure OID array, as well as the info about
1483  * opfamilies and opclass input types. (aminfo and supportinfo are left
1484  * as zeroes, and are filled on-the-fly when used)
1485  */
1486  IndexSupportInitialize(indclass, relation->rd_support,
1487  relation->rd_opfamily, relation->rd_opcintype,
1488  amsupport, indnkeyatts);
1489 
1490  /*
1491  * Similarly extract indoption and copy it to the cache entry
1492  */
1493  indoptionDatum = fastgetattr(relation->rd_indextuple,
1494  Anum_pg_index_indoption,
1496  &isnull);
1497  Assert(!isnull);
1498  indoption = (int2vector *) DatumGetPointer(indoptionDatum);
1499  memcpy(relation->rd_indoption, indoption->values, indnkeyatts * sizeof(int16));
1500 
1501  (void) RelationGetIndexAttOptions(relation, false);
1502 
1503  /*
1504  * expressions, predicate, exclusion caches will be filled later
1505  */
1506  relation->rd_indexprs = NIL;
1507  relation->rd_indpred = NIL;
1508  relation->rd_exclops = NULL;
1509  relation->rd_exclprocs = NULL;
1510  relation->rd_exclstrats = NULL;
1511  relation->rd_amcache = NULL;
1512 }
signed short int16
Definition: c.h:428
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
#define NIL
Definition: pg_list.h:65
Definition: c.h:660
struct IndexAmRoutine * rd_indam
Definition: rel.h:189
Definition: fmgr.h:56
uint16 amsupport
Definition: amapi.h:216
#define AllocSetContextCreate
Definition: memutils.h:173
int16 * rd_indoption
Definition: rel.h:194
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:711
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:205
regproc RegProcedure
Definition: c.h:585
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:1334
static void IndexSupportInitialize(oidvector *indclass, RegProcedure *indexSupport, Oid *opFamily, Oid *opcInType, StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber)
Definition: relcache.c:1528
struct HeapTupleData * rd_indextuple
Definition: rel.h:177
Form_pg_index rd_index
Definition: rel.h:175
unsigned short uint16
Definition: c.h:440
Oid * rd_indcollation
Definition: rel.h:200
Oid rd_amhandler
Definition: rel.h:167
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define MemoryContextCopyAndSetIdentifier(cxt, id)
Definition: memutils.h:98
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4213
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:668
#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:69
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
Definition: c.h:649
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:906
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
int16 values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:657
#define DatumGetPointer(X)
Definition: postgres.h:593
FormData_pg_am * Form_pg_am
Definition: pg_am.h:48
#define elog(elevel,...)
Definition: elog.h:232
MemoryContext rd_indexcxt
Definition: rel.h:187
bytea ** RelationGetIndexAttOptions(Relation relation, bool copy)
Definition: relcache.c:5473
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:51

◆ RelationInitTableAccessMethod()

void RelationInitTableAccessMethod ( Relation  relation)

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

1739 {
1740  HeapTuple tuple;
1741  Form_pg_am aform;
1742 
1743  if (relation->rd_rel->relkind == RELKIND_SEQUENCE)
1744  {
1745  /*
1746  * Sequences are currently accessed like heap tables, but it doesn't
1747  * seem prudent to show that in the catalog. So just overwrite it
1748  * here.
1749  */
1750  relation->rd_amhandler = F_HEAP_TABLEAM_HANDLER;
1751  }
1752  else if (IsCatalogRelation(relation))
1753  {
1754  /*
1755  * Avoid doing a syscache lookup for catalog tables.
1756  */
1757  Assert(relation->rd_rel->relam == HEAP_TABLE_AM_OID);
1758  relation->rd_amhandler = F_HEAP_TABLEAM_HANDLER;
1759  }
1760  else
1761  {
1762  /*
1763  * Look up the table access method, save the OID of its handler
1764  * function.
1765  */
1766  Assert(relation->rd_rel->relam != InvalidOid);
1767  tuple = SearchSysCache1(AMOID,
1768  ObjectIdGetDatum(relation->rd_rel->relam));
1769  if (!HeapTupleIsValid(tuple))
1770  elog(ERROR, "cache lookup failed for access method %u",
1771  relation->rd_rel->relam);
1772  aform = (Form_pg_am) GETSTRUCT(tuple);
1773  relation->rd_amhandler = aform->amhandler;
1774  ReleaseSysCache(tuple);
1775  }
1776 
1777  /*
1778  * Now we can fetch the table AM's API struct
1779  */
1780  InitTableAmRoutine(relation);
1781 }
static void InitTableAmRoutine(Relation relation)
Definition: relcache.c:1729
bool IsCatalogRelation(Relation relation)
Definition: catalog.c:103
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
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:551
#define ERROR
Definition: elog.h:46
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:804
FormData_pg_am * Form_pg_am
Definition: pg_am.h:48
#define elog(elevel,...)
Definition: elog.h:232

◆ RelationSetNewRelfilenode()

void RelationSetNewRelfilenode ( Relation  relation,
char  persistence 
)

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

3577 {
3578  Oid newrelfilenode;
3579  Relation pg_class;
3580  HeapTuple tuple;
3581  Form_pg_class classform;
3582  MultiXactId minmulti = InvalidMultiXactId;
3583  TransactionId freezeXid = InvalidTransactionId;
3584  RelFileNode newrnode;
3585 
3586  /* Allocate a new relfilenode */
3587  newrelfilenode = GetNewRelFileNode(relation->rd_rel->reltablespace, NULL,
3588  persistence);
3589 
3590  /*
3591  * Get a writable copy of the pg_class tuple for the given relation.
3592  */
3593  pg_class = table_open(RelationRelationId, RowExclusiveLock);
3594 
3595  tuple = SearchSysCacheCopy1(RELOID,
3596  ObjectIdGetDatum(RelationGetRelid(relation)));
3597  if (!HeapTupleIsValid(tuple))
3598  elog(ERROR, "could not find tuple for relation %u",
3599  RelationGetRelid(relation));
3600  classform = (Form_pg_class) GETSTRUCT(tuple);
3601 
3602  /*
3603  * Schedule unlinking of the old storage at transaction commit.
3604  */
3605  RelationDropStorage(relation);
3606 
3607  /*
3608  * Create storage for the main fork of the new relfilenode. If it's a
3609  * table-like object, call into the table AM to do so, which'll also
3610  * create the table's init fork if needed.
3611  *
3612  * NOTE: If relevant for the AM, any conflict in relfilenode value will be
3613  * caught here, if GetNewRelFileNode messes up for any reason.
3614  */
3615  newrnode = relation->rd_node;
3616  newrnode.relNode = newrelfilenode;
3617 
3618  switch (relation->rd_rel->relkind)
3619  {
3620  case RELKIND_INDEX:
3621  case RELKIND_SEQUENCE:
3622  {
3623  /* handle these directly, at least for now */
3624  SMgrRelation srel;
3625 
3626  srel = RelationCreateStorage(newrnode, persistence);
3627  smgrclose(srel);
3628  }
3629  break;
3630 
3631  case RELKIND_RELATION:
3632  case RELKIND_TOASTVALUE:
3633  case RELKIND_MATVIEW:
3634  table_relation_set_new_filenode(relation, &newrnode,
3635  persistence,
3636  &freezeXid, &minmulti);
3637  break;
3638 
3639  default:
3640  /* we shouldn't be called for anything else */
3641  elog(ERROR, "relation \"%s\" does not have storage",
3642  RelationGetRelationName(relation));
3643  break;
3644  }
3645 
3646  /*
3647  * If we're dealing with a mapped index, pg_class.relfilenode doesn't
3648  * change; instead we have to send the update to the relation mapper.
3649  *
3650  * For mapped indexes, we don't actually change the pg_class entry at all;
3651  * this is essential when reindexing pg_class itself. That leaves us with
3652  * possibly-inaccurate values of relpages etc, but those will be fixed up
3653  * later.
3654  */
3655  if (RelationIsMapped(relation))
3656  {
3657  /* This case is only supported for indexes */
3658  Assert(relation->rd_rel->relkind == RELKIND_INDEX);
3659 
3660  /* Since we're not updating pg_class, these had better not change */
3661  Assert(classform->relfrozenxid == freezeXid);
3662  Assert(classform->relminmxid == minmulti);
3663  Assert(classform->relpersistence == persistence);
3664 
3665  /*
3666  * In some code paths it's possible that the tuple update we'd
3667  * otherwise do here is the only thing that would assign an XID for
3668  * the current transaction. However, we must have an XID to delete
3669  * files, so make sure one is assigned.
3670  */
3671  (void) GetCurrentTransactionId();
3672 
3673  /* Do the deed */
3675  newrelfilenode,
3676  relation->rd_rel->relisshared,
3677  false);
3678 
3679  /* Since we're not updating pg_class, must trigger inval manually */
3680  CacheInvalidateRelcache(relation);
3681  }
3682  else
3683  {
3684  /* Normal case, update the pg_class entry */
3685  classform->relfilenode = newrelfilenode;
3686 
3687  /* relpages etc. never change for sequences */
3688  if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
3689  {
3690  classform->relpages = 0; /* it's empty until further notice */
3691  classform->reltuples = -1;
3692  classform->relallvisible = 0;
3693  }
3694  classform->relfrozenxid = freezeXid;
3695  classform->relminmxid = minmulti;
3696  classform->relpersistence = persistence;
3697 
3698  CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
3699  }
3700 
3701  heap_freetuple(tuple);
3702 
3703  table_close(pg_class, RowExclusiveLock);
3704 
3705  /*
3706  * Make the pg_class row change or relation map change visible. This will
3707  * cause the relcache entry to get updated, too.
3708  */
3710 
3711  RelationAssumeNewRelfilenode(relation);
3712 }
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:654
uint32 TransactionId
Definition: c.h:587
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:551
#define ERROR
Definition: elog.h:46
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:3727
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:597
RelFileNode rd_node
Definition: rel.h:55
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
Oid GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
Definition: catalog.c:427
static void table_relation_set_new_filenode(Relation rel, const RelFileNode *newrnode, char persistence, TransactionId *freezeXid, MultiXactId *minmulti)
Definition: tableam.h:1590
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:232
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