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

3209 {
3211  RelIdCacheEnt *idhentry;
3212  int i;
3213 
3214  /*
3215  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3216  * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3217  * logic as in AtEOXact_RelationCache.
3218  */
3220  {
3221  hash_seq_init(&status, RelationIdCache);
3222  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3223  {
3224  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3225  mySubid, parentSubid);
3226  }
3227  }
3228  else
3229  {
3230  for (i = 0; i < eoxact_list_len; i++)
3231  {
3232  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3233  (void *) &eoxact_list[i],
3234  HASH_FIND,
3235  NULL);
3236  if (idhentry != NULL)
3237  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3238  mySubid, parentSubid);
3239  }
3240  }
3241 
3242  /* Don't reset the list; we still need more cleanup later */
3243 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:164
static void AtEOSubXact_cleanup(Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
Definition: relcache.c:3254
Relation reldesc
Definition: relcache.c:128
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:927
static HTAB * RelationIdCache
Definition: relcache.c:131
static bool eoxact_list_overflowed
Definition: relcache.c:166
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1410
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1400
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
static int eoxact_list_len
Definition: relcache.c:165

◆ AtEOXact_RelationCache()

void AtEOXact_RelationCache ( bool  isCommit)

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

3063 {
3065  RelIdCacheEnt *idhentry;
3066  int i;
3067 
3068  /*
3069  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3070  * listed in it. Otherwise fall back on a hash_seq_search scan.
3071  *
3072  * For simplicity, eoxact_list[] entries are not deleted till end of
3073  * top-level transaction, even though we could remove them at
3074  * subtransaction end in some cases, or remove relations from the list if
3075  * they are cleared for other reasons. Therefore we should expect the
3076  * case that list entries are not found in the hashtable; if not, there's
3077  * nothing to do for them.
3078  */
3080  {
3081  hash_seq_init(&status, RelationIdCache);
3082  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3083  {
3084  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3085  }
3086  }
3087  else
3088  {
3089  for (i = 0; i < eoxact_list_len; i++)
3090  {
3091  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3092  (void *) &eoxact_list[i],
3093  HASH_FIND,
3094  NULL);
3095  if (idhentry != NULL)
3096  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3097  }
3098  }
3099 
3100  if (EOXactTupleDescArrayLen > 0)
3101  {
3102  Assert(EOXactTupleDescArray != NULL);
3103  for (i = 0; i < NextEOXactTupleDescNum; i++)
3106  EOXactTupleDescArray = NULL;
3107  }
3108 
3109  /* Now we're out of the transaction and can clear the lists */
3110  eoxact_list_len = 0;
3111  eoxact_list_overflowed = false;
3112  NextEOXactTupleDescNum = 0;
3114 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:164
static int EOXactTupleDescArrayLen
Definition: relcache.c:183
Relation reldesc
Definition: relcache.c:128
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:927
static HTAB * RelationIdCache
Definition: relcache.c:131
static void AtEOXact_cleanup(Relation relation, bool isCommit)
Definition: relcache.c:3125
static bool eoxact_list_overflowed
Definition: relcache.c:166
static int NextEOXactTupleDescNum
Definition: relcache.c:182
void pfree(void *pointer)
Definition: mcxt.c:1056
#define Assert(condition)
Definition: c.h:745
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1410
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1400
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:313
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
static int eoxact_list_len
Definition: relcache.c:165
static TupleDesc * EOXactTupleDescArray
Definition: relcache.c:181

◆ errtable()

int errtable ( Relation  rel)

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

5491 {
5495 
5496  return 0; /* return value does not matter */
5497 }
#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:3191
#define RelationGetRelationName(relation)
Definition: rel.h:490
int err_generic_string(int field, const char *str)
Definition: elog.c:1265
#define RelationGetNamespace(relation)
Definition: rel.h:497

◆ errtablecol()

int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5507 of file relcache.c.

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

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

5508 {
5509  TupleDesc reldesc = RelationGetDescr(rel);
5510  const char *colname;
5511 
5512  /* Use reldesc if it's a user attribute, else consult the catalogs */
5513  if (attnum > 0 && attnum <= reldesc->natts)
5514  colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
5515  else
5516  colname = get_attname(RelationGetRelid(rel), attnum, false);
5517 
5518  return errtablecolname(rel, colname);
5519 }
#define RelationGetDescr(relation)
Definition: rel.h:482
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
NameData attname
Definition: pg_attribute.h:40
int16 attnum
Definition: pg_attribute.h:79
#define NameStr(name)
Definition: c.h:622
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:825
#define RelationGetRelid(relation)
Definition: rel.h:456
int errtablecolname(Relation rel, const char *colname)
Definition: relcache.c:5531

◆ errtablecolname()

int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5531 of file relcache.c.

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

Referenced by errtablecol().

5532 {
5533  errtable(rel);
5535 
5536  return 0; /* return value does not matter */
5537 }
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:67
int err_generic_string(int field, const char *str)
Definition: elog.c:1265
int errtable(Relation rel)
Definition: relcache.c:5490

◆ errtableconstraint()

int errtableconstraint ( Relation  rel,
const char *  conname 
)

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

5545 {
5546  errtable(rel);
5548 
5549  return 0; /* return value does not matter */
5550 }
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:69
int err_generic_string(int field, const char *str)
Definition: elog.c:1265
int errtable(Relation rel)
Definition: relcache.c:5490

◆ GetRelationPublicationActions()

struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

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

5300 {
5301  List *puboids;
5302  ListCell *lc;
5303  MemoryContext oldcxt;
5304  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5305 
5306  /*
5307  * If not publishable, it publishes no actions. (pgoutput_change() will
5308  * ignore it.)
5309  */
5310  if (!is_publishable_relation(relation))
5311  return pubactions;
5312 
5313  if (relation->rd_pubactions)
5314  return memcpy(pubactions, relation->rd_pubactions,
5315  sizeof(PublicationActions));
5316 
5317  /* Fetch the publication membership info. */
5318  puboids = GetRelationPublications(RelationGetRelid(relation));
5319  if (relation->rd_rel->relispartition)
5320  {
5321  /* Add publications that the ancestors are in too. */
5322  List *ancestors = get_partition_ancestors(RelationGetRelid(relation));
5323  ListCell *lc;
5324 
5325  foreach(lc, ancestors)
5326  {
5327  Oid ancestor = lfirst_oid(lc);
5328 
5329  puboids = list_concat_unique_oid(puboids,
5330  GetRelationPublications(ancestor));
5331  }
5332  }
5333  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5334 
5335  foreach(lc, puboids)
5336  {
5337  Oid pubid = lfirst_oid(lc);
5338  HeapTuple tup;
5339  Form_pg_publication pubform;
5340 
5342 
5343  if (!HeapTupleIsValid(tup))
5344  elog(ERROR, "cache lookup failed for publication %u", pubid);
5345 
5346  pubform = (Form_pg_publication) GETSTRUCT(tup);
5347 
5348  pubactions->pubinsert |= pubform->pubinsert;
5349  pubactions->pubupdate |= pubform->pubupdate;
5350  pubactions->pubdelete |= pubform->pubdelete;
5351  pubactions->pubtruncate |= pubform->pubtruncate;
5352 
5353  ReleaseSysCache(tup);
5354 
5355  /*
5356  * If we know everything is replicated, there is no point to check for
5357  * other publications.
5358  */
5359  if (pubactions->pubinsert && pubactions->pubupdate &&
5360  pubactions->pubdelete && pubactions->pubtruncate)
5361  break;
5362  }
5363 
5364  if (relation->rd_pubactions)
5365  {
5366  pfree(relation->rd_pubactions);
5367  relation->rd_pubactions = NULL;
5368  }
5369 
5370  /* Now save copy of the actions in the relcache entry. */
5372  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5373  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5374  MemoryContextSwitchTo(oldcxt);
5375 
5376  return pubactions;
5377 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
PublicationActions * rd_pubactions
Definition: rel.h:150
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Form_pg_class rd_rel
Definition: rel.h:109
unsigned int Oid
Definition: postgres_ext.h:31
List * GetRelationPublications(Oid relid)
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
List * list_concat_unique_oid(List *list1, const List *list2)
Definition: list.c:1301
bool is_publishable_relation(Relation rel)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void * palloc0(Size size)
Definition: mcxt.c:980
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
List * GetAllTablesPublications(void)
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:214
FormData_pg_publication * Form_pg_publication
Definition: pg_list.h:50
List * get_partition_ancestors(Oid relid)
Definition: partition.c:115
#define RelationGetRelid(relation)
Definition: rel.h:456
#define lfirst_oid(lc)
Definition: pg_list.h:192
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationAssumeNewRelfilenode()

void RelationAssumeNewRelfilenode ( Relation  relation)

Definition at line 3731 of file relcache.c.

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

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

3732 {
3735  relation->rd_firstRelfilenodeSubid = relation->rd_newRelfilenodeSubid;
3736 
3737  /* Flag relation as needing eoxact cleanup (to clear these fields) */
3738  EOXactListAdd(relation);
3739 }
#define EOXactListAdd(rel)
Definition: relcache.c:168
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:103
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:723
#define InvalidSubTransactionId
Definition: c.h:526

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

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

◆ RelationCacheInitFilePostInvalidate()

void RelationCacheInitFilePostInvalidate ( void  )

Definition at line 6316 of file relcache.c.

References LWLockRelease().

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

6317 {
6318  LWLockRelease(RelCacheInitLock);
6319 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )

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

6292 {
6293  char localinitfname[MAXPGPATH];
6294  char sharedinitfname[MAXPGPATH];
6295 
6296  if (DatabasePath)
6297  snprintf(localinitfname, sizeof(localinitfname), "%s/%s",
6299  snprintf(sharedinitfname, sizeof(sharedinitfname), "global/%s",
6301 
6302  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6303 
6304  /*
6305  * The files might not be there if no backend has been started since the
6306  * last removal. But complain about failures other than ENOENT with
6307  * ERROR. Fortunately, it's not too late to abort the transaction if we
6308  * can't get rid of the would-be-obsolete init file.
6309  */
6310  if (DatabasePath)
6311  unlink_initfile(localinitfname, ERROR);
6312  unlink_initfile(sharedinitfname, ERROR);
6313 }
#define ERROR
Definition: elog.h:43
#define MAXPGPATH
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25
char * DatabasePath
Definition: globals.c:93
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6388
#define snprintf
Definition: port.h:193

◆ RelationCacheInitFileRemove()

void RelationCacheInitFileRemove ( void  )

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

6332 {
6333  const char *tblspcdir = "pg_tblspc";
6334  DIR *dir;
6335  struct dirent *de;
6336  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6337 
6338  snprintf(path, sizeof(path), "global/%s",
6340  unlink_initfile(path, LOG);
6341 
6342  /* Scan everything in the default tablespace */
6344 
6345  /* Scan the tablespace link directory to find non-default tablespaces */
6346  dir = AllocateDir(tblspcdir);
6347 
6348  while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6349  {
6350  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6351  {
6352  /* Scan the tablespace dir for per-database dirs */
6353  snprintf(path, sizeof(path), "%s/%s/%s",
6354  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6356  }
6357  }
6358 
6359  FreeDir(dir);
6360 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6364
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2664
#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:2583
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6388
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:193
int FreeDir(DIR *dir)
Definition: fd.c:2701

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 3757 of file relcache.c.

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

Referenced by InitPostgres().

3758 {
3759  HASHCTL ctl;
3760 
3761  /*
3762  * make sure cache memory context exists
3763  */
3764  if (!CacheMemoryContext)
3766 
3767  /*
3768  * create hashtable that indexes the relcache
3769  */
3770  MemSet(&ctl, 0, sizeof(ctl));
3771  ctl.keysize = sizeof(Oid);
3772  ctl.entrysize = sizeof(RelIdCacheEnt);
3773  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3774  &ctl, HASH_ELEM | HASH_BLOBS);
3775 
3776  /*
3777  * relation mapper needs to be initialized too
3778  */
3780 }
void RelationMapInitialize(void)
Definition: relmapper.c:584
#define HASH_ELEM
Definition: hsearch.h:87
struct relidcacheent RelIdCacheEnt
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:949
static HTAB * RelationIdCache
Definition: relcache.c:131
unsigned int Oid
Definition: postgres_ext.h:31
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:328
Size keysize
Definition: hsearch.h:72
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
#define INITRELCACHESIZE
Definition: relcache.c:3754
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInitializePhase2()

void RelationCacheInitializePhase2 ( void  )

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

3795 {
3796  MemoryContext oldcxt;
3797 
3798  /*
3799  * relation mapper needs initialized too
3800  */
3802 
3803  /*
3804  * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3805  * nothing.
3806  */
3808  return;
3809 
3810  /*
3811  * switch to cache memory context
3812  */
3814 
3815  /*
3816  * Try to load the shared relcache cache file. If unsuccessful, bootstrap
3817  * the cache with pre-made descriptors for the critical shared catalogs.
3818  */
3819  if (!load_relcache_init_file(true))
3820  {
3821  formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
3822  Natts_pg_database, Desc_pg_database);
3823  formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
3824  Natts_pg_authid, Desc_pg_authid);
3825  formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
3826  Natts_pg_auth_members, Desc_pg_auth_members);
3827  formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
3828  Natts_pg_shseclabel, Desc_pg_shseclabel);
3829  formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
3830  Natts_pg_subscription, Desc_pg_subscription);
3831 
3832 #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
3833  }
3834 
3835  MemoryContextSwitchTo(oldcxt);
3836 }
static const FormData_pg_attribute Desc_pg_auth_members[Natts_pg_auth_members]
Definition: relcache.c:114
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5608
void RelationMapInitializePhase2(void)
Definition: relmapper.c:604
static const FormData_pg_attribute Desc_pg_authid[Natts_pg_authid]
Definition: relcache.c:113
static const FormData_pg_attribute Desc_pg_subscription[Natts_pg_subscription]
Definition: relcache.c:117
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static const FormData_pg_attribute Desc_pg_database[Natts_pg_database]
Definition: relcache.c:112
static const FormData_pg_attribute Desc_pg_shseclabel[Natts_pg_shseclabel]
Definition: relcache.c:116
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:393
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1809
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInitializePhase3()

void RelationCacheInitializePhase3 ( void  )

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

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

◆ RelationCacheInvalidate()

void RelationCacheInvalidate ( void  )

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

2825 {
2827  RelIdCacheEnt *idhentry;
2828  Relation relation;
2829  List *rebuildFirstList = NIL;
2830  List *rebuildList = NIL;
2831  ListCell *l;
2832 
2833  /*
2834  * Reload relation mapping data before starting to reconstruct cache.
2835  */
2837 
2838  /* Phase 1 */
2839  hash_seq_init(&status, RelationIdCache);
2840 
2841  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2842  {
2843  relation = idhentry->reldesc;
2844 
2845  /* Must close all smgr references to avoid leaving dangling ptrs */
2846  RelationCloseSmgr(relation);
2847 
2848  /*
2849  * Ignore new relations; no other backend will manipulate them before
2850  * we commit. Likewise, before replacing a relation's relfilenode, we
2851  * shall have acquired AccessExclusiveLock and drained any applicable
2852  * pending invalidations.
2853  */
2854  if (relation->rd_createSubid != InvalidSubTransactionId ||
2856  continue;
2857 
2859 
2860  if (RelationHasReferenceCountZero(relation))
2861  {
2862  /* Delete this entry immediately */
2863  Assert(!relation->rd_isnailed);
2864  RelationClearRelation(relation, false);
2865  }
2866  else
2867  {
2868  /*
2869  * If it's a mapped relation, immediately update its rd_node in
2870  * case its relfilenode changed. We must do this during phase 1
2871  * in case the relation is consulted during rebuild of other
2872  * relcache entries in phase 2. It's safe since consulting the
2873  * map doesn't involve any access to relcache entries.
2874  */
2875  if (RelationIsMapped(relation))
2876  RelationInitPhysicalAddr(relation);
2877 
2878  /*
2879  * Add this entry to list of stuff to rebuild in second pass.
2880  * pg_class goes to the front of rebuildFirstList while
2881  * pg_class_oid_index goes to the back of rebuildFirstList, so
2882  * they are done first and second respectively. Other nailed
2883  * relations go to the front of rebuildList, so they'll be done
2884  * next in no particular order; and everything else goes to the
2885  * back of rebuildList.
2886  */
2887  if (RelationGetRelid(relation) == RelationRelationId)
2888  rebuildFirstList = lcons(relation, rebuildFirstList);
2889  else if (RelationGetRelid(relation) == ClassOidIndexId)
2890  rebuildFirstList = lappend(rebuildFirstList, relation);
2891  else if (relation->rd_isnailed)
2892  rebuildList = lcons(relation, rebuildList);
2893  else
2894  rebuildList = lappend(rebuildList, relation);
2895  }
2896  }
2897 
2898  /*
2899  * Now zap any remaining smgr cache entries. This must happen before we
2900  * start to rebuild entries, since that may involve catalog fetches which
2901  * will re-open catalog files.
2902  */
2903  smgrcloseall();
2904 
2905  /* Phase 2: rebuild the items found to need rebuild in phase 1 */
2906  foreach(l, rebuildFirstList)
2907  {
2908  relation = (Relation) lfirst(l);
2909  RelationClearRelation(relation, true);
2910  }
2911  list_free(rebuildFirstList);
2912  foreach(l, rebuildList)
2913  {
2914  relation = (Relation) lfirst(l);
2915  RelationClearRelation(relation, true);
2916  }
2917  list_free(rebuildList);
2918 }
#define NIL
Definition: pg_list.h:65
static long relcacheInvalsReceived
Definition: relcache.c:151
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2424
bool rd_isnailed
Definition: rel.h:61
Relation reldesc
Definition: relcache.c:128
#define RelationCloseSmgr(relation)
Definition: rel.h:525
static HTAB * RelationIdCache
Definition: relcache.c:131
void smgrcloseall(void)
Definition: smgr.c:287
struct RelationData * Relation
Definition: relcache.h:27
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1274
#define ClassOidIndexId
Definition: indexing.h:119
List * lappend(List *list, void *datum)
Definition: list.c:321
#define RelationIsMapped(relation)
Definition: rel.h:505
SubTransactionId rd_createSubid
Definition: rel.h:102
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
List * lcons(void *datum, List *list)
Definition: list.c:453
#define Assert(condition)
Definition: c.h:745
#define lfirst(lc)
Definition: pg_list.h:190
#define InvalidSubTransactionId
Definition: c.h:526
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1410
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1400
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:440
void list_free(List *list)
Definition: list.c:1376
void RelationMapInvalidateAll(void)
Definition: relmapper.c:425
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:456

◆ RelationCacheInvalidateEntry()

void RelationCacheInvalidateEntry ( Oid  relationId)

Definition at line 2781 of file relcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

2782 {
2783  Relation relation;
2784 
2785  RelationIdCacheLookup(relationId, relation);
2786 
2787  if (PointerIsValid(relation))
2788  {
2790  RelationFlushRelation(relation);
2791  }
2792 }
static long relcacheInvalsReceived
Definition: relcache.c:151
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:210
static void RelationFlushRelation(Relation relation)
Definition: relcache.c:2704
#define PointerIsValid(pointer)
Definition: c.h:639

◆ RelationClose()

void RelationClose ( Relation  relation)

Definition at line 2103 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(), relation_close(), RememberToFreeTupleDescAtEOX(), ReorderBufferProcessTXN(), ReorderBufferToastReplace(), and ResourceOwnerReleaseInternal().

2104 {
2105  /* Note: no locking manipulations needed */
2107 
2108  /*
2109  * If the relation is no longer open in this session, we can clean up any
2110  * stale partition descriptors it has. This is unlikely, so check to see
2111  * if there are child contexts before expending a call to mcxt.c.
2112  */
2113  if (RelationHasReferenceCountZero(relation) &&
2114  relation->rd_pdcxt != NULL &&
2115  relation->rd_pdcxt->firstchild != NULL)
2117 
2118 #ifdef RELCACHE_FORCE_RELEASE
2119  if (RelationHasReferenceCountZero(relation) &&
2120  relation->rd_createSubid == InvalidSubTransactionId &&
2122  RelationClearRelation(relation, false);
2123 #endif
2124 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2424
MemoryContext firstchild
Definition: memnodes.h:85
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2083
SubTransactionId rd_createSubid
Definition: rel.h:102
void MemoryContextDeleteChildren(MemoryContext context)
Definition: mcxt.c:256
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
MemoryContext rd_pdcxt
Definition: rel.h:129
#define InvalidSubTransactionId
Definition: c.h:526
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:440

◆ RelationCloseSmgrByOid()

void RelationCloseSmgrByOid ( Oid  relationId)

Definition at line 2927 of file relcache.c.

References PointerIsValid, RelationCloseSmgr, and RelationIdCacheLookup.

Referenced by swap_relation_files().

2928 {
2929  Relation relation;
2930 
2931  RelationIdCacheLookup(relationId, relation);
2932 
2933  if (!PointerIsValid(relation))
2934  return; /* not in cache, nothing to do */
2935 
2936  RelationCloseSmgr(relation);
2937 }
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:210
#define RelationCloseSmgr(relation)
Definition: rel.h:525
#define PointerIsValid(pointer)
Definition: c.h:639

◆ RelationForgetRelation()

void RelationForgetRelation ( Oid  rid)

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

2738 {
2739  Relation relation;
2740 
2741  RelationIdCacheLookup(rid, relation);
2742 
2743  if (!PointerIsValid(relation))
2744  return; /* not in cache, nothing to do */
2745 
2746  if (!RelationHasReferenceCountZero(relation))
2747  elog(ERROR, "relation %u is still open", rid);
2748 
2750  if (relation->rd_createSubid != InvalidSubTransactionId ||
2752  {
2753  /*
2754  * In the event of subtransaction rollback, we must not forget
2755  * rd_*Subid. Mark the entry "dropped" so RelationClearRelation()
2756  * invalidates it in lieu of destroying it. (If we're in a top
2757  * transaction, we could opt to destroy the entry.)
2758  */
2760  }
2761 
2762  RelationClearRelation(relation, false);
2763 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2424
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:210
#define ERROR
Definition: elog.h:43
SubTransactionId rd_createSubid
Definition: rel.h:102
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
#define Assert(condition)
Definition: c.h:745
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:723
#define InvalidSubTransactionId
Definition: c.h:526
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:440
#define elog(elevel,...)
Definition: elog.h:214
#define PointerIsValid(pointer)
Definition: c.h:639
SubTransactionId rd_droppedSubid
Definition: rel.h:107

◆ RelationGetDummyIndexExpressions()

List* RelationGetDummyIndexExpressions ( Relation  relation)

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

4801 {
4802  List *result;
4803  Datum exprsDatum;
4804  bool isnull;
4805  char *exprsString;
4806  List *rawExprs;
4807  ListCell *lc;
4808 
4809  /* Quick exit if there is nothing to do. */
4810  if (relation->rd_indextuple == NULL ||
4811  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indexprs, NULL))
4812  return NIL;
4813 
4814  /* Extract raw node tree(s) from index tuple. */
4815  exprsDatum = heap_getattr(relation->rd_indextuple,
4816  Anum_pg_index_indexprs,
4818  &isnull);
4819  Assert(!isnull);
4820  exprsString = TextDatumGetCString(exprsDatum);
4821  rawExprs = (List *) stringToNode(exprsString);
4822  pfree(exprsString);
4823 
4824  /* Construct null Consts; the typlen and typbyval are arbitrary. */
4825  result = NIL;
4826  foreach(lc, rawExprs)
4827  {
4828  Node *rawExpr = (Node *) lfirst(lc);
4829 
4830  result = lappend(result,
4831  makeConst(exprType(rawExpr),
4832  exprTypmod(rawExpr),
4833  exprCollation(rawExpr),
4834  1,
4835  (Datum) 0,
4836  true,
4837  true));
4838  }
4839 
4840  return result;
4841 }
#define NIL
Definition: pg_list.h:65
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:275
Definition: nodes.h:529
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:176
void pfree(void *pointer)
Definition: mcxt.c:1056
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4218
List * lappend(List *list, void *datum)
Definition: list.c:321
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:87
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:745
#define lfirst(lc)
Definition: pg_list.h:190
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:719
Definition: pg_list.h:50

◆ RelationGetExclusionInfo()

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

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

5179 {
5180  int indnkeyatts;
5181  Oid *ops;
5182  Oid *funcs;
5183  uint16 *strats;
5184  Relation conrel;
5185  SysScanDesc conscan;
5186  ScanKeyData skey[1];
5187  HeapTuple htup;
5188  bool found;
5189  MemoryContext oldcxt;
5190  int i;
5191 
5192  indnkeyatts = IndexRelationGetNumberOfKeyAttributes(indexRelation);
5193 
5194  /* Allocate result space in caller context */
5195  *operators = ops = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5196  *procs = funcs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5197  *strategies = strats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
5198 
5199  /* Quick exit if we have the data cached already */
5200  if (indexRelation->rd_exclstrats != NULL)
5201  {
5202  memcpy(ops, indexRelation->rd_exclops, sizeof(Oid) * indnkeyatts);
5203  memcpy(funcs, indexRelation->rd_exclprocs, sizeof(Oid) * indnkeyatts);
5204  memcpy(strats, indexRelation->rd_exclstrats, sizeof(uint16) * indnkeyatts);
5205  return;
5206  }
5207 
5208  /*
5209  * Search pg_constraint for the constraint associated with the index. To
5210  * make this not too painfully slow, we use the index on conrelid; that
5211  * will hold the parent relation's OID not the index's own OID.
5212  *
5213  * Note: if we wanted to rely on the constraint name matching the index's
5214  * name, we could just do a direct lookup using pg_constraint's unique
5215  * index. For the moment it doesn't seem worth requiring that.
5216  */
5217  ScanKeyInit(&skey[0],
5218  Anum_pg_constraint_conrelid,
5219  BTEqualStrategyNumber, F_OIDEQ,
5220  ObjectIdGetDatum(indexRelation->rd_index->indrelid));
5221 
5222  conrel = table_open(ConstraintRelationId, AccessShareLock);
5223  conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
5224  NULL, 1, skey);
5225  found = false;
5226 
5227  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
5228  {
5230  Datum val;
5231  bool isnull;
5232  ArrayType *arr;
5233  int nelem;
5234 
5235  /* We want the exclusion constraint owning the index */
5236  if (conform->contype != CONSTRAINT_EXCLUSION ||
5237  conform->conindid != RelationGetRelid(indexRelation))
5238  continue;
5239 
5240  /* There should be only one */
5241  if (found)
5242  elog(ERROR, "unexpected exclusion constraint record found for rel %s",
5243  RelationGetRelationName(indexRelation));
5244  found = true;
5245 
5246  /* Extract the operator OIDS from conexclop */
5247  val = fastgetattr(htup,
5248  Anum_pg_constraint_conexclop,
5249  conrel->rd_att, &isnull);
5250  if (isnull)
5251  elog(ERROR, "null conexclop for rel %s",
5252  RelationGetRelationName(indexRelation));
5253 
5254  arr = DatumGetArrayTypeP(val); /* ensure not toasted */
5255  nelem = ARR_DIMS(arr)[0];
5256  if (ARR_NDIM(arr) != 1 ||
5257  nelem != indnkeyatts ||
5258  ARR_HASNULL(arr) ||
5259  ARR_ELEMTYPE(arr) != OIDOID)
5260  elog(ERROR, "conexclop is not a 1-D Oid array");
5261 
5262  memcpy(ops, ARR_DATA_PTR(arr), sizeof(Oid) * indnkeyatts);
5263  }
5264 
5265  systable_endscan(conscan);
5266  table_close(conrel, AccessShareLock);
5267 
5268  if (!found)
5269  elog(ERROR, "exclusion constraint record missing for rel %s",
5270  RelationGetRelationName(indexRelation));
5271 
5272  /* We need the func OIDs and strategy numbers too */
5273  for (i = 0; i < indnkeyatts; i++)
5274  {
5275  funcs[i] = get_opcode(ops[i]);
5276  strats[i] = get_op_opfamily_strategy(ops[i],
5277  indexRelation->rd_opfamily[i]);
5278  /* shouldn't fail, since it was checked at index creation */
5279  if (strats[i] == InvalidStrategy)
5280  elog(ERROR, "could not find strategy for operator %u in family %u",
5281  ops[i], indexRelation->rd_opfamily[i]);
5282  }
5283 
5284  /* Save a copy of the results in the relcache entry. */
5285  oldcxt = MemoryContextSwitchTo(indexRelation->rd_indexcxt);
5286  indexRelation->rd_exclops = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5287  indexRelation->rd_exclprocs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5288  indexRelation->rd_exclstrats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
5289  memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * indnkeyatts);
5290  memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * indnkeyatts);
5291  memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * indnkeyatts);
5292  MemoryContextSwitchTo(oldcxt);
5293 }
#define InvalidStrategy
Definition: stratnum.h:24
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:712
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
uint16 * rd_exclstrats
Definition: rel.h:198
#define AccessShareLock
Definition: lockdefs.h:36
Oid * rd_exclprocs
Definition: rel.h:197
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:357
Form_pg_index rd_index
Definition: rel.h:174
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
unsigned short uint16
Definition: c.h:373
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:282
#define ARR_DATA_PTR(a)
Definition: array.h:310
#define RelationGetRelationName(relation)
Definition: rel.h:490
#define ARR_HASNULL(a)
Definition: array.h:279
Oid * rd_opfamily
Definition: rel.h:189
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition: rel.h:475
Oid * rd_exclops
Definition: rel.h:196
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:110
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1202
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define ARR_NDIM(a)
Definition: array.h:278
#define ConstraintRelidTypidNameIndexId
Definition: indexing.h:133
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition: lsyscache.c:81
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:214
MemoryContext rd_indexcxt
Definition: rel.h:186
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:280
#define RelationGetRelid(relation)
Definition: rel.h:456
long val
Definition: informix.c:664
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ RelationGetFKeyList()

List* RelationGetFKeyList ( Relation  relation)

Definition at line 4398 of file relcache.c.

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

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

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

◆ RelationGetIndexAttOptions()

bytea** RelationGetIndexAttOptions ( Relation  relation,
bool  copy 
)

Definition at line 5429 of file relcache.c.

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

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

5430 {
5431  MemoryContext oldcxt;
5432  bytea **opts = relation->rd_opcoptions;
5433  Oid relid = RelationGetRelid(relation);
5434  int natts = RelationGetNumberOfAttributes(relation); /* XXX
5435  * IndexRelationGetNumberOfKeyAttributes */
5436  int i;
5437 
5438  /* Try to copy cached options. */
5439  if (opts)
5440  return copy ? CopyIndexAttOptions(opts, natts) : opts;
5441 
5442  /* Get and parse opclass options. */
5443  opts = palloc0(sizeof(*opts) * natts);
5444 
5445  for (i = 0; i < natts; i++)
5446  {
5448  {
5449  Datum attoptions = get_attoptions(relid, i + 1);
5450 
5451  opts[i] = index_opclass_options(relation, i + 1, attoptions, false);
5452 
5453  if (attoptions != (Datum) 0)
5454  pfree(DatumGetPointer(attoptions));
5455  }
5456  }
5457 
5458  /* Copy parsed options to the cache. */
5459  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
5460  relation->rd_opcoptions = CopyIndexAttOptions(opts, natts);
5461  MemoryContextSwitchTo(oldcxt);
5462 
5463  if (copy)
5464  return opts;
5465 
5466  for (i = 0; i < natts; i++)
5467  {
5468  if (opts[i])
5469  pfree(opts[i]);
5470  }
5471 
5472  pfree(opts);
5473 
5474  return relation->rd_opcoptions;
5475 }
#define AttributeRelidNumIndexId
Definition: indexing.h:101
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:462
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bytea ** rd_opcoptions
Definition: rel.h:200
unsigned int Oid
Definition: postgres_ext.h:31
Datum get_attoptions(Oid relid, int16 attnum)
Definition: lsyscache.c:968
void pfree(void *pointer)
Definition: mcxt.c:1056
static bytea ** CopyIndexAttOptions(bytea **srcopts, int natts)
Definition: relcache.c:5409
bytea * index_opclass_options(Relation indrel, AttrNumber attnum, Datum attoptions, bool validate)
Definition: indexam.c:936
void * palloc0(Size size)
Definition: mcxt.c:980
uintptr_t Datum
Definition: postgres.h:367
#define DatumGetPointer(X)
Definition: postgres.h:549
MemoryContext rd_indexcxt
Definition: rel.h:186
int i
Definition: c.h:562
bool criticalRelcachesBuilt
Definition: relcache.c:137
#define RelationGetRelid(relation)
Definition: rel.h:456

◆ RelationGetIndexAttrBitmap()

Bitmapset* RelationGetIndexAttrBitmap ( Relation  relation,
IndexAttrBitmapKind  attrKind 
)

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

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

◆ RelationGetIndexExpressions()

List* RelationGetIndexExpressions ( Relation  relation)

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

4742 {
4743  List *result;
4744  Datum exprsDatum;
4745  bool isnull;
4746  char *exprsString;
4747  MemoryContext oldcxt;
4748 
4749  /* Quick exit if we already computed the result. */
4750  if (relation->rd_indexprs)
4751  return copyObject(relation->rd_indexprs);
4752 
4753  /* Quick exit if there is nothing to do. */
4754  if (relation->rd_indextuple == NULL ||
4755  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indexprs, NULL))
4756  return NIL;
4757 
4758  /*
4759  * We build the tree we intend to return in the caller's context. After
4760  * successfully completing the work, we copy it into the relcache entry.
4761  * This avoids problems if we get some sort of error partway through.
4762  */
4763  exprsDatum = heap_getattr(relation->rd_indextuple,
4764  Anum_pg_index_indexprs,
4766  &isnull);
4767  Assert(!isnull);
4768  exprsString = TextDatumGetCString(exprsDatum);
4769  result = (List *) stringToNode(exprsString);
4770  pfree(exprsString);
4771 
4772  /*
4773  * Run the expressions through eval_const_expressions. This is not just an
4774  * optimization, but is necessary, because the planner will be comparing
4775  * them to similarly-processed qual clauses, and may fail to detect valid
4776  * matches without this. We must not use canonicalize_qual, however,
4777  * since these aren't qual expressions.
4778  */
4779  result = (List *) eval_const_expressions(NULL, (Node *) result);
4780 
4781  /* May as well fix opfuncids too */
4782  fix_opfuncids((Node *) result);
4783 
4784  /* Now save a copy of the completed tree in the relcache entry. */
4785  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4786  relation->rd_indexprs = copyObject(result);
4787  MemoryContextSwitchTo(oldcxt);
4788 
4789  return result;
4790 }
#define NIL
Definition: pg_list.h:65
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1587
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
List * rd_indexprs
Definition: rel.h:194
Definition: nodes.h:529
void * stringToNode(const char *str)
Definition: read.c:89
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2255
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
struct HeapTupleData * rd_indextuple
Definition: rel.h:176
void pfree(void *pointer)
Definition: mcxt.c:1056
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4218
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:87
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:745
MemoryContext rd_indexcxt
Definition: rel.h:186
#define copyObject(obj)
Definition: nodes.h:645
Definition: pg_list.h:50

◆ RelationGetIndexList()

List* RelationGetIndexList ( Relation  relation)

Definition at line 4507 of file relcache.c.

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

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

4508 {
4509  Relation indrel;
4510  SysScanDesc indscan;
4511  ScanKeyData skey;
4512  HeapTuple htup;
4513  List *result;
4514  List *oldlist;
4515  char replident = relation->rd_rel->relreplident;
4516  Oid pkeyIndex = InvalidOid;
4517  Oid candidateIndex = InvalidOid;
4518  MemoryContext oldcxt;
4519 
4520  /* Quick exit if we already computed the list. */
4521  if (relation->rd_indexvalid)
4522  return list_copy(relation->rd_indexlist);
4523 
4524  /*
4525  * We build the list we intend to return (in the caller's context) while
4526  * doing the scan. After successfully completing the scan, we copy that
4527  * list into the relcache entry. This avoids cache-context memory leakage
4528  * if we get some sort of error partway through.
4529  */
4530  result = NIL;
4531 
4532  /* Prepare to scan pg_index for entries having indrelid = this rel. */
4533  ScanKeyInit(&skey,
4534  Anum_pg_index_indrelid,
4535  BTEqualStrategyNumber, F_OIDEQ,
4536  ObjectIdGetDatum(RelationGetRelid(relation)));
4537 
4538  indrel = table_open(IndexRelationId, AccessShareLock);
4539  indscan = systable_beginscan(indrel, IndexIndrelidIndexId, true,
4540  NULL, 1, &skey);
4541 
4542  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4543  {
4545 
4546  /*
4547  * Ignore any indexes that are currently being dropped. This will
4548  * prevent them from being searched, inserted into, or considered in
4549  * HOT-safety decisions. It's unsafe to touch such an index at all
4550  * since its catalog entries could disappear at any instant.
4551  */
4552  if (!index->indislive)
4553  continue;
4554 
4555  /* add index's OID to result list */
4556  result = lappend_oid(result, index->indexrelid);
4557 
4558  /*
4559  * Invalid, non-unique, non-immediate or predicate indexes aren't
4560  * interesting for either oid indexes or replication identity indexes,
4561  * so don't check them.
4562  */
4563  if (!index->indisvalid || !index->indisunique ||
4564  !index->indimmediate ||
4565  !heap_attisnull(htup, Anum_pg_index_indpred, NULL))
4566  continue;
4567 
4568  /* remember primary key index if any */
4569  if (index->indisprimary)
4570  pkeyIndex = index->indexrelid;
4571 
4572  /* remember explicitly chosen replica index */
4573  if (index->indisreplident)
4574  candidateIndex = index->indexrelid;
4575  }
4576 
4577  systable_endscan(indscan);
4578 
4579  table_close(indrel, AccessShareLock);
4580 
4581  /* Sort the result list into OID order, per API spec. */
4582  list_sort(result, list_oid_cmp);
4583 
4584  /* Now save a copy of the completed list in the relcache entry. */
4586  oldlist = relation->rd_indexlist;
4587  relation->rd_indexlist = list_copy(result);
4588  relation->rd_pkindex = pkeyIndex;
4589  if (replident == REPLICA_IDENTITY_DEFAULT && OidIsValid(pkeyIndex))
4590  relation->rd_replidindex = pkeyIndex;
4591  else if (replident == REPLICA_IDENTITY_INDEX && OidIsValid(candidateIndex))
4592  relation->rd_replidindex = candidateIndex;
4593  else
4594  relation->rd_replidindex = InvalidOid;
4595  relation->rd_indexvalid = true;
4596  MemoryContextSwitchTo(oldcxt);
4597 
4598  /* Don't leak the old list, if there is one */
4599  list_free(oldlist);
4600 
4601  return result;
4602 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid rd_replidindex
Definition: rel.h:139
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
List * list_copy(const List *oldlist)
Definition: list.c:1403
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
Form_pg_class rd_rel
Definition: rel.h:109
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:357
#define OidIsValid(objectId)
Definition: c.h:651
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
Definition: type.h:89
int list_oid_cmp(const ListCell *p1, const ListCell *p2)
Definition: list.c:1498
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
Oid rd_pkindex
Definition: rel.h:138
List * rd_indexlist
Definition: rel.h:137
FormData_pg_index * Form_pg_index
Definition: pg_index.h:68
bool rd_indexvalid
Definition: rel.h:63
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void list_sort(List *list, list_sort_comparator cmp)
Definition: list.c:1481
void list_free(List *list)
Definition: list.c:1376
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:456
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define IndexIndrelidIndexId
Definition: indexing.h:171
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationGetIndexPredicate()

List* RelationGetIndexPredicate ( Relation  relation)

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

4855 {
4856  List *result;
4857  Datum predDatum;
4858  bool isnull;
4859  char *predString;
4860  MemoryContext oldcxt;
4861 
4862  /* Quick exit if we already computed the result. */
4863  if (relation->rd_indpred)
4864  return copyObject(relation->rd_indpred);
4865 
4866  /* Quick exit if there is nothing to do. */
4867  if (relation->rd_indextuple == NULL ||
4868  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indpred, NULL))
4869  return NIL;
4870 
4871  /*
4872  * We build the tree we intend to return in the caller's context. After
4873  * successfully completing the work, we copy it into the relcache entry.
4874  * This avoids problems if we get some sort of error partway through.
4875  */
4876  predDatum = heap_getattr(relation->rd_indextuple,
4877  Anum_pg_index_indpred,
4879  &isnull);
4880  Assert(!isnull);
4881  predString = TextDatumGetCString(predDatum);
4882  result = (List *) stringToNode(predString);
4883  pfree(predString);
4884 
4885  /*
4886  * Run the expression through const-simplification and canonicalization.
4887  * This is not just an optimization, but is necessary, because the planner
4888  * will be comparing it to similarly-processed qual clauses, and may fail
4889  * to detect valid matches without this. This must match the processing
4890  * done to qual clauses in preprocess_expression()! (We can skip the
4891  * stuff involving subqueries, however, since we don't allow any in index
4892  * predicates.)
4893  */
4894  result = (List *) eval_const_expressions(NULL, (Node *) result);
4895 
4896  result = (List *) canonicalize_qual((Expr *) result, false);
4897 
4898  /* Also convert to implicit-AND format */
4899  result = make_ands_implicit((Expr *) result);
4900 
4901  /* May as well fix opfuncids too */
4902  fix_opfuncids((Node *) result);
4903 
4904  /* Now save a copy of the completed tree in the relcache entry. */
4905  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4906  relation->rd_indpred = copyObject(result);
4907  MemoryContextSwitchTo(oldcxt);
4908 
4909  return result;
4910 }
#define NIL
Definition: pg_list.h:65
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1587
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:529
void * stringToNode(const char *str)
Definition: read.c:89
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2255
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
struct HeapTupleData * rd_indextuple
Definition: rel.h:176
void pfree(void *pointer)
Definition: mcxt.c:1056
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4218
Expr * canonicalize_qual(Expr *qual, bool is_check)
Definition: prepqual.c:292
List * rd_indpred
Definition: rel.h:195
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:87
uintptr_t Datum
Definition: postgres.h:367
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:718
#define Assert(condition)
Definition: c.h:745
MemoryContext rd_indexcxt
Definition: rel.h:186
#define copyObject(obj)
Definition: nodes.h:645
Definition: pg_list.h:50

◆ RelationGetIndexRawAttOptions()

Datum* RelationGetIndexRawAttOptions ( Relation  relation)

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

5384 {
5385  Oid indexrelid = RelationGetRelid(indexrel);
5386  int16 natts = RelationGetNumberOfAttributes(indexrel);
5387  Datum *options = NULL;
5388  int16 attnum;
5389 
5390  for (attnum = 1; attnum <= natts; attnum++)
5391  {
5392  if (indexrel->rd_indam->amoptsprocnum == 0)
5393  continue;
5394 
5395  if (!OidIsValid(index_getprocid(indexrel, attnum,
5396  indexrel->rd_indam->amoptsprocnum)))
5397  continue;
5398 
5399  if (!options)
5400  options = palloc0(sizeof(Datum) * natts);
5401 
5402  options[attnum - 1] = get_attoptions(indexrelid, attnum);
5403  }
5404 
5405  return options;
5406 }
signed short int16
Definition: c.h:361
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:462
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:651
Datum get_attoptions(Oid relid, int16 attnum)
Definition: lsyscache.c:968
static char ** options
void * palloc0(Size size)
Definition: mcxt.c:980
uintptr_t Datum
Definition: postgres.h:367
int16 attnum
Definition: pg_attribute.h:79
#define RelationGetRelid(relation)
Definition: rel.h:456
RegProcedure index_getprocid(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:766

◆ RelationGetPrimaryKeyIndex()

Oid RelationGetPrimaryKeyIndex ( Relation  relation)

Definition at line 4695 of file relcache.c.

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

Referenced by build_replindex_scan_key(), and GetRelationIdentityOrPK().

4696 {
4697  List *ilist;
4698 
4699  if (!relation->rd_indexvalid)
4700  {
4701  /* RelationGetIndexList does the heavy lifting. */
4702  ilist = RelationGetIndexList(relation);
4703  list_free(ilist);
4704  Assert(relation->rd_indexvalid);
4705  }
4706 
4707  return relation->rd_pkindex;
4708 }
Oid rd_pkindex
Definition: rel.h:138
bool rd_indexvalid
Definition: rel.h:63
#define Assert(condition)
Definition: c.h:745
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4507
void list_free(List *list)
Definition: list.c:1376
Definition: pg_list.h:50

◆ RelationGetReplicaIndex()

Oid RelationGetReplicaIndex ( Relation  relation)

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

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

◆ RelationGetStatExtList()

List* RelationGetStatExtList ( Relation  relation)

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

4627 {
4628  Relation indrel;
4629  SysScanDesc indscan;
4630  ScanKeyData skey;
4631  HeapTuple htup;
4632  List *result;
4633  List *oldlist;
4634  MemoryContext oldcxt;
4635 
4636  /* Quick exit if we already computed the list. */
4637  if (relation->rd_statvalid != 0)
4638  return list_copy(relation->rd_statlist);
4639 
4640  /*
4641  * We build the list we intend to return (in the caller's context) while
4642  * doing the scan. After successfully completing the scan, we copy that
4643  * list into the relcache entry. This avoids cache-context memory leakage
4644  * if we get some sort of error partway through.
4645  */
4646  result = NIL;
4647 
4648  /*
4649  * Prepare to scan pg_statistic_ext for entries having stxrelid = this
4650  * rel.
4651  */
4652  ScanKeyInit(&skey,
4653  Anum_pg_statistic_ext_stxrelid,
4654  BTEqualStrategyNumber, F_OIDEQ,
4655  ObjectIdGetDatum(RelationGetRelid(relation)));
4656 
4657  indrel = table_open(StatisticExtRelationId, AccessShareLock);
4658  indscan = systable_beginscan(indrel, StatisticExtRelidIndexId, true,
4659  NULL, 1, &skey);
4660 
4661  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4662  {
4663  Oid oid = ((Form_pg_statistic_ext) GETSTRUCT(htup))->oid;
4664 
4665  result = lappend_oid(result, oid);
4666  }
4667 
4668  systable_endscan(indscan);
4669 
4670  table_close(indrel, AccessShareLock);
4671 
4672  /* Sort the result list into OID order, per API spec. */
4673  list_sort(result, list_oid_cmp);
4674 
4675  /* Now save a copy of the completed list in the relcache entry. */
4677  oldlist = relation->rd_statlist;
4678  relation->rd_statlist = list_copy(result);
4679 
4680  relation->rd_statvalid = true;
4681  MemoryContextSwitchTo(oldcxt);
4682 
4683  /* Don't leak the old list, if there is one */
4684  list_free(oldlist);
4685 
4686  return result;
4687 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:569
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
List * list_copy(const List *oldlist)
Definition: list.c:1403
unsigned int Oid
Definition: postgres_ext.h:31
#define StatisticExtRelidIndexId
Definition: indexing.h:240
List * lappend_oid(List *list, Oid datum)
Definition: list.c:357
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:357
int list_oid_cmp(const ListCell *p1, const ListCell *p2)
Definition: list.c:1498
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:476
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
bool rd_statvalid
Definition: rel.h:65
void list_sort(List *list, list_sort_comparator cmp)
Definition: list.c:1481
void list_free(List *list)
Definition: list.c:1376
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
List * rd_statlist
Definition: rel.h:142
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:456
#define BTEqualStrategyNumber
Definition: stratnum.h:31
FormData_pg_statistic_ext * Form_pg_statistic_ext
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationIdGetRelation()

Relation RelationIdGetRelation ( Oid  relationId)

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

1998 {
1999  Relation rd;
2000 
2001  /* Make sure we're in an xact, even if this ends up being a cache hit */
2003 
2004  /*
2005  * first try to find reldesc in the cache
2006  */
2007  RelationIdCacheLookup(relationId, rd);
2008 
2009  if (RelationIsValid(rd))
2010  {
2011  /* return NULL for dropped relations */
2013  {
2014  Assert(!rd->rd_isvalid);
2015  return NULL;
2016  }
2017 
2019  /* revalidate cache entry if necessary */
2020  if (!rd->rd_isvalid)
2021  {
2022  /*
2023  * Indexes only have a limited number of possible schema changes,
2024  * and we don't want to use the full-blown procedure because it's
2025  * a headache for indexes that reload itself depends on.
2026  */
2027  if (rd->rd_rel->relkind == RELKIND_INDEX ||
2028  rd->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
2030  else
2031  RelationClearRelation(rd, true);
2032 
2033  /*
2034  * Normally entries need to be valid here, but before the relcache
2035  * has been initialized, not enough infrastructure exists to
2036  * perform pg_class lookups. The structure of such entries doesn't
2037  * change, but we still want to update the rd_rel entry. So
2038  * rd_isvalid = false is left in place for a later lookup.
2039  */
2040  Assert(rd->rd_isvalid ||
2042  }
2043  return rd;
2044  }
2045 
2046  /*
2047  * no reldesc in the cache, so have RelationBuildDesc() build one and add
2048  * it.
2049  */
2050  rd = RelationBuildDesc(relationId, true);
2051  if (RelationIsValid(rd))
2053  return rd;
2054 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2424
bool rd_isnailed
Definition: rel.h:61
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:210
bool rd_isvalid
Definition: rel.h:62
Form_pg_class rd_rel
Definition: rel.h:109
#define RelationIsValid(relation)
Definition: rel.h:429
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2070
static void RelationReloadIndexInfo(Relation relation)
Definition: relcache.c:2154
#define Assert(condition)
Definition: c.h:745
static Relation RelationBuildDesc(Oid targetRelId, bool insertIt)
Definition: relcache.c:1028
bool IsTransactionState(void)
Definition: xact.c:371
#define InvalidSubTransactionId
Definition: c.h:526
bool criticalRelcachesBuilt
Definition: relcache.c:137
SubTransactionId rd_droppedSubid
Definition: rel.h:107

◆ RelationIdIsInInitFile()

bool RelationIdIsInInitFile ( Oid  relationId)

Definition at line 6251 of file relcache.c.

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

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

6252 {
6253  if (relationId == SharedSecLabelRelationId ||
6254  relationId == TriggerRelidNameIndexId ||
6255  relationId == DatabaseNameIndexId ||
6256  relationId == SharedSecLabelObjectIndexId)
6257  {
6258  /*
6259  * If this Assert fails, we don't need the applicable special case
6260  * anymore.
6261  */
6262  Assert(!RelationSupportsSysCache(relationId));
6263  return true;
6264  }
6265  return RelationSupportsSysCache(relationId);
6266 }
#define TriggerRelidNameIndexId
Definition: indexing.h:258
#define Assert(condition)
Definition: c.h:745
#define DatabaseNameIndexId
Definition: indexing.h:149
#define SharedSecLabelObjectIndexId
Definition: indexing.h:325
bool RelationSupportsSysCache(Oid relid)
Definition: syscache.c:1521

◆ RelationInitIndexAccessInfo()

void RelationInitIndexAccessInfo ( Relation  relation)

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

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

◆ RelationInitTableAccessMethod()

void RelationInitTableAccessMethod ( Relation  relation)

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

1746 {
1747  HeapTuple tuple;
1748  Form_pg_am aform;
1749 
1750  if (relation->rd_rel->relkind == RELKIND_SEQUENCE)
1751  {
1752  /*
1753  * Sequences are currently accessed like heap tables, but it doesn't
1754  * seem prudent to show that in the catalog. So just overwrite it
1755  * here.
1756  */
1757  relation->rd_amhandler = HEAP_TABLE_AM_HANDLER_OID;
1758  }
1759  else if (IsCatalogRelation(relation))
1760  {
1761  /*
1762  * Avoid doing a syscache lookup for catalog tables.
1763  */
1764  Assert(relation->rd_rel->relam == HEAP_TABLE_AM_OID);
1765  relation->rd_amhandler = HEAP_TABLE_AM_HANDLER_OID;
1766  }
1767  else
1768  {
1769  /*
1770  * Look up the table access method, save the OID of its handler
1771  * function.
1772  */
1773  Assert(relation->rd_rel->relam != InvalidOid);
1774  tuple = SearchSysCache1(AMOID,
1775  ObjectIdGetDatum(relation->rd_rel->relam));
1776  if (!HeapTupleIsValid(tuple))
1777  elog(ERROR, "cache lookup failed for access method %u",
1778  relation->rd_rel->relam);
1779  aform = (Form_pg_am) GETSTRUCT(tuple);
1780  relation->rd_amhandler = aform->amhandler;
1781  ReleaseSysCache(tuple);
1782  }
1783 
1784  /*
1785  * Now we can fetch the table AM's API struct
1786  */
1787  InitTableAmRoutine(relation);
1788 }
static void InitTableAmRoutine(Relation relation)
Definition: relcache.c:1736
bool IsCatalogRelation(Relation relation)
Definition: catalog.c:98
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Definition: syscache.h:36
Form_pg_class rd_rel
Definition: rel.h:109
Oid rd_amhandler
Definition: rel.h:166
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:745
FormData_pg_am * Form_pg_am
Definition: pg_am.h:48
#define elog(elevel,...)
Definition: elog.h:214

◆ RelationSetNewRelfilenode()

void RelationSetNewRelfilenode ( Relation  relation,
char  persistence 
)

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

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

Variable Documentation

◆ criticalRelcachesBuilt

◆ criticalSharedRelcachesBuilt

bool criticalSharedRelcachesBuilt