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

3208 {
3210  RelIdCacheEnt *idhentry;
3211  int i;
3212 
3213  /*
3214  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3215  * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3216  * logic as in AtEOXact_RelationCache.
3217  */
3219  {
3220  hash_seq_init(&status, RelationIdCache);
3221  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3222  {
3223  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3224  mySubid, parentSubid);
3225  }
3226  }
3227  else
3228  {
3229  for (i = 0; i < eoxact_list_len; i++)
3230  {
3231  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3232  (void *) &eoxact_list[i],
3233  HASH_FIND,
3234  NULL);
3235  if (idhentry != NULL)
3236  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3237  mySubid, parentSubid);
3238  }
3239  }
3240 
3241  /* Don't reset the list; we still need more cleanup later */
3242 }
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:3253
Relation reldesc
Definition: relcache.c:128
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:908
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:1391
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1381
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 3061 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().

3062 {
3064  RelIdCacheEnt *idhentry;
3065  int i;
3066 
3067  /*
3068  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3069  * listed in it. Otherwise fall back on a hash_seq_search scan.
3070  *
3071  * For simplicity, eoxact_list[] entries are not deleted till end of
3072  * top-level transaction, even though we could remove them at
3073  * subtransaction end in some cases, or remove relations from the list if
3074  * they are cleared for other reasons. Therefore we should expect the
3075  * case that list entries are not found in the hashtable; if not, there's
3076  * nothing to do for them.
3077  */
3079  {
3080  hash_seq_init(&status, RelationIdCache);
3081  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3082  {
3083  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3084  }
3085  }
3086  else
3087  {
3088  for (i = 0; i < eoxact_list_len; i++)
3089  {
3090  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3091  (void *) &eoxact_list[i],
3092  HASH_FIND,
3093  NULL);
3094  if (idhentry != NULL)
3095  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3096  }
3097  }
3098 
3099  if (EOXactTupleDescArrayLen > 0)
3100  {
3101  Assert(EOXactTupleDescArray != NULL);
3102  for (i = 0; i < NextEOXactTupleDescNum; i++)
3105  EOXactTupleDescArray = NULL;
3106  }
3107 
3108  /* Now we're out of the transaction and can clear the lists */
3109  eoxact_list_len = 0;
3110  eoxact_list_overflowed = false;
3111  NextEOXactTupleDescNum = 0;
3113 }
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:908
static HTAB * RelationIdCache
Definition: relcache.c:131
static void AtEOXact_cleanup(Relation relation, bool isCommit)
Definition: relcache.c:3124
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:738
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1391
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1381
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 5489 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().

5490 {
5494 
5495  return 0; /* return value does not matter */
5496 }
#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 5506 of file relcache.c.

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

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

5507 {
5508  TupleDesc reldesc = RelationGetDescr(rel);
5509  const char *colname;
5510 
5511  /* Use reldesc if it's a user attribute, else consult the catalogs */
5512  if (attnum > 0 && attnum <= reldesc->natts)
5513  colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
5514  else
5515  colname = get_attname(RelationGetRelid(rel), attnum, false);
5516 
5517  return errtablecolname(rel, colname);
5518 }
#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:615
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:5530

◆ errtablecolname()

int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5530 of file relcache.c.

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

Referenced by errtablecol().

5531 {
5532  errtable(rel);
5534 
5535  return 0; /* return value does not matter */
5536 }
#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:5489

◆ errtableconstraint()

int errtableconstraint ( Relation  rel,
const char *  conname 
)

Definition at line 5543 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(), ri_ReportViolation(), and validateCheckConstraint().

5544 {
5545  errtable(rel);
5547 
5548  return 0; /* return value does not matter */
5549 }
#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:5489

◆ GetRelationPublicationActions()

struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

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

5299 {
5300  List *puboids;
5301  ListCell *lc;
5302  MemoryContext oldcxt;
5303  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5304 
5305  /*
5306  * If not publishable, it publishes no actions. (pgoutput_change() will
5307  * ignore it.)
5308  */
5309  if (!is_publishable_relation(relation))
5310  return pubactions;
5311 
5312  if (relation->rd_pubactions)
5313  return memcpy(pubactions, relation->rd_pubactions,
5314  sizeof(PublicationActions));
5315 
5316  /* Fetch the publication membership info. */
5317  puboids = GetRelationPublications(RelationGetRelid(relation));
5318  if (relation->rd_rel->relispartition)
5319  {
5320  /* Add publications that the ancestors are in too. */
5321  List *ancestors = get_partition_ancestors(RelationGetRelid(relation));
5322  ListCell *lc;
5323 
5324  foreach(lc, ancestors)
5325  {
5326  Oid ancestor = lfirst_oid(lc);
5327 
5328  puboids = list_concat_unique_oid(puboids,
5329  GetRelationPublications(ancestor));
5330  }
5331  }
5332  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5333 
5334  foreach(lc, puboids)
5335  {
5336  Oid pubid = lfirst_oid(lc);
5337  HeapTuple tup;
5338  Form_pg_publication pubform;
5339 
5341 
5342  if (!HeapTupleIsValid(tup))
5343  elog(ERROR, "cache lookup failed for publication %u", pubid);
5344 
5345  pubform = (Form_pg_publication) GETSTRUCT(tup);
5346 
5347  pubactions->pubinsert |= pubform->pubinsert;
5348  pubactions->pubupdate |= pubform->pubupdate;
5349  pubactions->pubdelete |= pubform->pubdelete;
5350  pubactions->pubtruncate |= pubform->pubtruncate;
5351 
5352  ReleaseSysCache(tup);
5353 
5354  /*
5355  * If we know everything is replicated, there is no point to check for
5356  * other publications.
5357  */
5358  if (pubactions->pubinsert && pubactions->pubupdate &&
5359  pubactions->pubdelete && pubactions->pubtruncate)
5360  break;
5361  }
5362 
5363  if (relation->rd_pubactions)
5364  {
5365  pfree(relation->rd_pubactions);
5366  relation->rd_pubactions = NULL;
5367  }
5368 
5369  /* Now save copy of the actions in the relcache entry. */
5371  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5372  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5373  MemoryContextSwitchTo(oldcxt);
5374 
5375  return pubactions;
5376 }
#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 3730 of file relcache.c.

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

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

3731 {
3734  relation->rd_firstRelfilenodeSubid = relation->rd_newRelfilenodeSubid;
3735 
3736  /* Flag relation as needing eoxact cleanup (to clear these fields) */
3737  EOXactListAdd(relation);
3738 }
#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:708
#define InvalidSubTransactionId
Definition: c.h:519

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

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

References LWLockRelease().

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

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

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )

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

6291 {
6292  char localinitfname[MAXPGPATH];
6293  char sharedinitfname[MAXPGPATH];
6294 
6295  if (DatabasePath)
6296  snprintf(localinitfname, sizeof(localinitfname), "%s/%s",
6298  snprintf(sharedinitfname, sizeof(sharedinitfname), "global/%s",
6300 
6301  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6302 
6303  /*
6304  * The files might not be there if no backend has been started since the
6305  * last removal. But complain about failures other than ENOENT with
6306  * ERROR. Fortunately, it's not too late to abort the transaction if we
6307  * can't get rid of the would-be-obsolete init file.
6308  */
6309  if (DatabasePath)
6310  unlink_initfile(localinitfname, ERROR);
6311  unlink_initfile(sharedinitfname, ERROR);
6312 }
#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:6387
#define snprintf
Definition: port.h:193

◆ RelationCacheInitFileRemove()

void RelationCacheInitFileRemove ( void  )

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

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

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 3756 of file relcache.c.

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

Referenced by InitPostgres().

3757 {
3758  HASHCTL ctl;
3759 
3760  /*
3761  * make sure cache memory context exists
3762  */
3763  if (!CacheMemoryContext)
3765 
3766  /*
3767  * create hashtable that indexes the relcache
3768  */
3769  MemSet(&ctl, 0, sizeof(ctl));
3770  ctl.keysize = sizeof(Oid);
3771  ctl.entrysize = sizeof(RelIdCacheEnt);
3772  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3773  &ctl, HASH_ELEM | HASH_BLOBS);
3774 
3775  /*
3776  * relation mapper needs to be initialized too
3777  */
3779 }
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:971
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:318
Size keysize
Definition: hsearch.h:72
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
#define INITRELCACHESIZE
Definition: relcache.c:3753
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInitializePhase2()

void RelationCacheInitializePhase2 ( void  )

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

3794 {
3795  MemoryContext oldcxt;
3796 
3797  /*
3798  * relation mapper needs initialized too
3799  */
3801 
3802  /*
3803  * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3804  * nothing.
3805  */
3807  return;
3808 
3809  /*
3810  * switch to cache memory context
3811  */
3813 
3814  /*
3815  * Try to load the shared relcache cache file. If unsuccessful, bootstrap
3816  * the cache with pre-made descriptors for the critical shared catalogs.
3817  */
3818  if (!load_relcache_init_file(true))
3819  {
3820  formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
3821  Natts_pg_database, Desc_pg_database);
3822  formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
3823  Natts_pg_authid, Desc_pg_authid);
3824  formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
3825  Natts_pg_auth_members, Desc_pg_auth_members);
3826  formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
3827  Natts_pg_shseclabel, Desc_pg_shseclabel);
3828  formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
3829  Natts_pg_subscription, Desc_pg_subscription);
3830 
3831 #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
3832  }
3833 
3834  MemoryContextSwitchTo(oldcxt);
3835 }
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:5607
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:392
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1808
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInitializePhase3()

void RelationCacheInitializePhase3 ( void  )

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

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

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

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

Referenced by LocalExecuteInvalidationMessage().

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

◆ RelationClose()

void RelationClose ( Relation  relation)

Definition at line 2102 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(), ReorderBufferCommit(), ReorderBufferToastReplace(), and ResourceOwnerReleaseInternal().

2103 {
2104  /* Note: no locking manipulations needed */
2106 
2107  /*
2108  * If the relation is no longer open in this session, we can clean up any
2109  * stale partition descriptors it has. This is unlikely, so check to see
2110  * if there are child contexts before expending a call to mcxt.c.
2111  */
2112  if (RelationHasReferenceCountZero(relation) &&
2113  relation->rd_pdcxt != NULL &&
2114  relation->rd_pdcxt->firstchild != NULL)
2116 
2117 #ifdef RELCACHE_FORCE_RELEASE
2118  if (RelationHasReferenceCountZero(relation) &&
2119  relation->rd_createSubid == InvalidSubTransactionId &&
2121  RelationClearRelation(relation, false);
2122 #endif
2123 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2423
MemoryContext firstchild
Definition: memnodes.h:85
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2082
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:519
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:440

◆ RelationCloseSmgrByOid()

void RelationCloseSmgrByOid ( Oid  relationId)

Definition at line 2926 of file relcache.c.

References PointerIsValid, RelationCloseSmgr, and RelationIdCacheLookup.

Referenced by swap_relation_files().

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

◆ RelationForgetRelation()

void RelationForgetRelation ( Oid  rid)

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

2737 {
2738  Relation relation;
2739 
2740  RelationIdCacheLookup(rid, relation);
2741 
2742  if (!PointerIsValid(relation))
2743  return; /* not in cache, nothing to do */
2744 
2745  if (!RelationHasReferenceCountZero(relation))
2746  elog(ERROR, "relation %u is still open", rid);
2747 
2749  if (relation->rd_createSubid != InvalidSubTransactionId ||
2751  {
2752  /*
2753  * In the event of subtransaction rollback, we must not forget
2754  * rd_*Subid. Mark the entry "dropped" so RelationClearRelation()
2755  * invalidates it in lieu of destroying it. (If we're in a top
2756  * transaction, we could opt to destroy the entry.)
2757  */
2759  }
2760 
2761  RelationClearRelation(relation, false);
2762 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2423
#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:738
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:708
#define InvalidSubTransactionId
Definition: c.h:519
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:440
#define elog(elevel,...)
Definition: elog.h:214
#define PointerIsValid(pointer)
Definition: c.h:632
SubTransactionId rd_droppedSubid
Definition: rel.h:107

◆ RelationGetDummyIndexExpressions()

List* RelationGetDummyIndexExpressions ( Relation  relation)

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

4800 {
4801  List *result;
4802  Datum exprsDatum;
4803  bool isnull;
4804  char *exprsString;
4805  List *rawExprs;
4806  ListCell *lc;
4807 
4808  /* Quick exit if there is nothing to do. */
4809  if (relation->rd_indextuple == NULL ||
4810  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indexprs, NULL))
4811  return NIL;
4812 
4813  /* Extract raw node tree(s) from index tuple. */
4814  exprsDatum = heap_getattr(relation->rd_indextuple,
4815  Anum_pg_index_indexprs,
4817  &isnull);
4818  Assert(!isnull);
4819  exprsString = TextDatumGetCString(exprsDatum);
4820  rawExprs = (List *) stringToNode(exprsString);
4821  pfree(exprsString);
4822 
4823  /* Construct null Consts; the typlen and typbyval are arbitrary. */
4824  result = NIL;
4825  foreach(lc, rawExprs)
4826  {
4827  Node *rawExpr = (Node *) lfirst(lc);
4828 
4829  result = lappend(result,
4830  makeConst(exprType(rawExpr),
4831  exprTypmod(rawExpr),
4832  exprCollation(rawExpr),
4833  1,
4834  (Datum) 0,
4835  true,
4836  true));
4837  }
4838 
4839  return result;
4840 }
#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:297
struct HeapTupleData * rd_indextuple
Definition: rel.h:176
void pfree(void *pointer)
Definition: mcxt.c:1056
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4217
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:88
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:738
#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 5174 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().

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

4398 {
4399  List *result;
4400  Relation conrel;
4401  SysScanDesc conscan;
4402  ScanKeyData skey;
4403  HeapTuple htup;
4404  List *oldlist;
4405  MemoryContext oldcxt;
4406 
4407  /* Quick exit if we already computed the list. */
4408  if (relation->rd_fkeyvalid)
4409  return relation->rd_fkeylist;
4410 
4411  /* Fast path: non-partitioned tables without triggers can't have FKs */
4412  if (!relation->rd_rel->relhastriggers &&
4413  relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
4414  return NIL;
4415 
4416  /*
4417  * We build the list we intend to return (in the caller's context) while
4418  * doing the scan. After successfully completing the scan, we copy that
4419  * list into the relcache entry. This avoids cache-context memory leakage
4420  * if we get some sort of error partway through.
4421  */
4422  result = NIL;
4423 
4424  /* Prepare to scan pg_constraint for entries having conrelid = this rel. */
4425  ScanKeyInit(&skey,
4426  Anum_pg_constraint_conrelid,
4427  BTEqualStrategyNumber, F_OIDEQ,
4428  ObjectIdGetDatum(RelationGetRelid(relation)));
4429 
4430  conrel = table_open(ConstraintRelationId, AccessShareLock);
4431  conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
4432  NULL, 1, &skey);
4433 
4434  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4435  {
4436  Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(htup);
4437  ForeignKeyCacheInfo *info;
4438 
4439  /* consider only foreign keys */
4440  if (constraint->contype != CONSTRAINT_FOREIGN)
4441  continue;
4442 
4443  info = makeNode(ForeignKeyCacheInfo);
4444  info->conoid = constraint->oid;
4445  info->conrelid = constraint->conrelid;
4446  info->confrelid = constraint->confrelid;
4447 
4448  DeconstructFkConstraintRow(htup, &info->nkeys,
4449  info->conkey,
4450  info->confkey,
4451  info->conpfeqop,
4452  NULL, NULL);
4453 
4454  /* Add FK's node to the result list */
4455  result = lappend(result, info);
4456  }
4457 
4458  systable_endscan(conscan);
4459  table_close(conrel, AccessShareLock);
4460 
4461  /* Now save a copy of the completed list in the relcache entry. */
4463  oldlist = relation->rd_fkeylist;
4464  relation->rd_fkeylist = copyObject(result);
4465  relation->rd_fkeyvalid = true;
4466  MemoryContextSwitchTo(oldcxt);
4467 
4468  /* Don't leak the old list, if there is one */
4469  list_free_deep(oldlist);
4470 
4471  return result;
4472 }
#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:529
#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:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#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:128
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 5428 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().

5429 {
5430  MemoryContext oldcxt;
5431  bytea **opts = relation->rd_opcoptions;
5432  Oid relid = RelationGetRelid(relation);
5433  int natts = RelationGetNumberOfAttributes(relation); /* XXX
5434  * IndexRelationGetNumberOfKeyAttributes */
5435  int i;
5436 
5437  /* Try to copy cached options. */
5438  if (opts)
5439  return copy ? CopyIndexAttOptions(opts, natts) : opts;
5440 
5441  /* Get and parse opclass options. */
5442  opts = palloc0(sizeof(*opts) * natts);
5443 
5444  for (i = 0; i < natts; i++)
5445  {
5447  {
5448  Datum attoptions = get_attoptions(relid, i + 1);
5449 
5450  opts[i] = index_opclass_options(relation, i + 1, attoptions, false);
5451 
5452  if (attoptions != (Datum) 0)
5453  pfree(DatumGetPointer(attoptions));
5454  }
5455  }
5456 
5457  /* Copy parsed options to the cache. */
5458  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
5459  relation->rd_opcoptions = CopyIndexAttOptions(opts, natts);
5460  MemoryContextSwitchTo(oldcxt);
5461 
5462  if (copy)
5463  return opts;
5464 
5465  for (i = 0; i < natts; i++)
5466  {
5467  if (opts[i])
5468  pfree(opts[i]);
5469  }
5470 
5471  pfree(opts);
5472 
5473  return relation->rd_opcoptions;
5474 }
#define AttributeRelidNumIndexId
Definition: indexing.h:96
#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:5408
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:555
bool criticalRelcachesBuilt
Definition: relcache.c:137
#define RelationGetRelid(relation)
Definition: rel.h:456

◆ RelationGetIndexAttrBitmap()

Bitmapset* RelationGetIndexAttrBitmap ( Relation  relation,
IndexAttrBitmapKind  attrKind 
)

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

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

4741 {
4742  List *result;
4743  Datum exprsDatum;
4744  bool isnull;
4745  char *exprsString;
4746  MemoryContext oldcxt;
4747 
4748  /* Quick exit if we already computed the result. */
4749  if (relation->rd_indexprs)
4750  return copyObject(relation->rd_indexprs);
4751 
4752  /* Quick exit if there is nothing to do. */
4753  if (relation->rd_indextuple == NULL ||
4754  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indexprs, NULL))
4755  return NIL;
4756 
4757  /*
4758  * We build the tree we intend to return in the caller's context. After
4759  * successfully completing the work, we copy it into the relcache entry.
4760  * This avoids problems if we get some sort of error partway through.
4761  */
4762  exprsDatum = heap_getattr(relation->rd_indextuple,
4763  Anum_pg_index_indexprs,
4765  &isnull);
4766  Assert(!isnull);
4767  exprsString = TextDatumGetCString(exprsDatum);
4768  result = (List *) stringToNode(exprsString);
4769  pfree(exprsString);
4770 
4771  /*
4772  * Run the expressions through eval_const_expressions. This is not just an
4773  * optimization, but is necessary, because the planner will be comparing
4774  * them to similarly-processed qual clauses, and may fail to detect valid
4775  * matches without this. We must not use canonicalize_qual, however,
4776  * since these aren't qual expressions.
4777  */
4778  result = (List *) eval_const_expressions(NULL, (Node *) result);
4779 
4780  /* May as well fix opfuncids too */
4781  fix_opfuncids((Node *) result);
4782 
4783  /* Now save a copy of the completed tree in the relcache entry. */
4784  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4785  relation->rd_indexprs = copyObject(result);
4786  MemoryContextSwitchTo(oldcxt);
4787 
4788  return result;
4789 }
#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:4217
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:88
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:738
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 4506 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().

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

◆ RelationGetIndexPredicate()

List* RelationGetIndexPredicate ( Relation  relation)

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

4854 {
4855  List *result;
4856  Datum predDatum;
4857  bool isnull;
4858  char *predString;
4859  MemoryContext oldcxt;
4860 
4861  /* Quick exit if we already computed the result. */
4862  if (relation->rd_indpred)
4863  return copyObject(relation->rd_indpred);
4864 
4865  /* Quick exit if there is nothing to do. */
4866  if (relation->rd_indextuple == NULL ||
4867  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indpred, NULL))
4868  return NIL;
4869 
4870  /*
4871  * We build the tree we intend to return in the caller's context. After
4872  * successfully completing the work, we copy it into the relcache entry.
4873  * This avoids problems if we get some sort of error partway through.
4874  */
4875  predDatum = heap_getattr(relation->rd_indextuple,
4876  Anum_pg_index_indpred,
4878  &isnull);
4879  Assert(!isnull);
4880  predString = TextDatumGetCString(predDatum);
4881  result = (List *) stringToNode(predString);
4882  pfree(predString);
4883 
4884  /*
4885  * Run the expression through const-simplification and canonicalization.
4886  * This is not just an optimization, but is necessary, because the planner
4887  * will be comparing it to similarly-processed qual clauses, and may fail
4888  * to detect valid matches without this. This must match the processing
4889  * done to qual clauses in preprocess_expression()! (We can skip the
4890  * stuff involving subqueries, however, since we don't allow any in index
4891  * predicates.)
4892  */
4893  result = (List *) eval_const_expressions(NULL, (Node *) result);
4894 
4895  result = (List *) canonicalize_qual((Expr *) result, false);
4896 
4897  /* Also convert to implicit-AND format */
4898  result = make_ands_implicit((Expr *) result);
4899 
4900  /* May as well fix opfuncids too */
4901  fix_opfuncids((Node *) result);
4902 
4903  /* Now save a copy of the completed tree in the relcache entry. */
4904  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4905  relation->rd_indpred = copyObject(result);
4906  MemoryContextSwitchTo(oldcxt);
4907 
4908  return result;
4909 }
#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:4217
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:88
uintptr_t Datum
Definition: postgres.h:367
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:716
#define Assert(condition)
Definition: c.h:738
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 5382 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().

5383 {
5384  Oid indexrelid = RelationGetRelid(indexrel);
5385  int16 natts = RelationGetNumberOfAttributes(indexrel);
5386  Datum *options = NULL;
5387  int16 attnum;
5388 
5389  for (attnum = 1; attnum <= natts; attnum++)
5390  {
5391  if (indexrel->rd_indam->amoptsprocnum == 0)
5392  continue;
5393 
5394  if (!OidIsValid(index_getprocid(indexrel, attnum,
5395  indexrel->rd_indam->amoptsprocnum)))
5396  continue;
5397 
5398  if (!options)
5399  options = palloc0(sizeof(Datum) * natts);
5400 
5401  options[attnum - 1] = get_attoptions(indexrelid, attnum);
5402  }
5403 
5404  return options;
5405 }
signed short int16
Definition: c.h:354
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:462
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:644
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 4694 of file relcache.c.

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

Referenced by build_replindex_scan_key(), and GetRelationIdentityOrPK().

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

◆ RelationGetReplicaIndex()

Oid RelationGetReplicaIndex ( Relation  relation)

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

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

◆ RelationGetStatExtList()

List* RelationGetStatExtList ( Relation  relation)

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

4626 {
4627  Relation indrel;
4628  SysScanDesc indscan;
4629  ScanKeyData skey;
4630  HeapTuple htup;
4631  List *result;
4632  List *oldlist;
4633  MemoryContext oldcxt;
4634 
4635  /* Quick exit if we already computed the list. */
4636  if (relation->rd_statvalid != 0)
4637  return list_copy(relation->rd_statlist);
4638 
4639  /*
4640  * We build the list we intend to return (in the caller's context) while
4641  * doing the scan. After successfully completing the scan, we copy that
4642  * list into the relcache entry. This avoids cache-context memory leakage
4643  * if we get some sort of error partway through.
4644  */
4645  result = NIL;
4646 
4647  /*
4648  * Prepare to scan pg_statistic_ext for entries having stxrelid = this
4649  * rel.
4650  */
4651  ScanKeyInit(&skey,
4652  Anum_pg_statistic_ext_stxrelid,
4653  BTEqualStrategyNumber, F_OIDEQ,
4654  ObjectIdGetDatum(RelationGetRelid(relation)));
4655 
4656  indrel = table_open(StatisticExtRelationId, AccessShareLock);
4657  indscan = systable_beginscan(indrel, StatisticExtRelidIndexId, true,
4658  NULL, 1, &skey);
4659 
4660  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4661  {
4662  Oid oid = ((Form_pg_statistic_ext) GETSTRUCT(htup))->oid;
4663 
4664  result = lappend_oid(result, oid);
4665  }
4666 
4667  systable_endscan(indscan);
4668 
4669  table_close(indrel, AccessShareLock);
4670 
4671  /* Sort the result list into OID order, per API spec. */
4672  list_sort(result, list_oid_cmp);
4673 
4674  /* Now save a copy of the completed list in the relcache entry. */
4676  oldlist = relation->rd_statlist;
4677  relation->rd_statlist = list_copy(result);
4678 
4679  relation->rd_statvalid = true;
4680  MemoryContextSwitchTo(oldcxt);
4681 
4682  /* Don't leak the old list, if there is one */
4683  list_free(oldlist);
4684 
4685  return result;
4686 }
#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:529
#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:235
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:356
int list_oid_cmp(const ListCell *p1, const ListCell *p2)
Definition: list.c:1498
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#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 1996 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(), ReorderBufferCommit(), ReorderBufferToastReplace(), and try_relation_open().

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

◆ RelationIdIsInInitFile()

bool RelationIdIsInInitFile ( Oid  relationId)

Definition at line 6250 of file relcache.c.

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

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

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

◆ RelationInitIndexAccessInfo()

void RelationInitIndexAccessInfo ( Relation  relation)

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

1365 {
1366  HeapTuple tuple;
1367  Form_pg_am aform;
1368  Datum indcollDatum;
1369  Datum indclassDatum;
1370  Datum indoptionDatum;
1371  bool isnull;
1372  oidvector *indcoll;
1373  oidvector *indclass;
1374  int2vector *indoption;
1375  MemoryContext indexcxt;
1376  MemoryContext oldcontext;
1377  int indnatts;
1378  int indnkeyatts;
1379  uint16 amsupport;
1380 
1381  /*
1382  * Make a copy of the pg_index entry for the index. Since pg_index
1383  * contains variable-length and possibly-null fields, we have to do this
1384  * honestly rather than just treating it as a Form_pg_index struct.
1385  */
1386  tuple = SearchSysCache1(INDEXRELID,
1387  ObjectIdGetDatum(RelationGetRelid(relation)));
1388  if (!HeapTupleIsValid(tuple))
1389  elog(ERROR, "cache lookup failed for index %u",
1390  RelationGetRelid(relation));
1392  relation->rd_indextuple = heap_copytuple(tuple);
1393  relation->rd_index = (Form_pg_index) GETSTRUCT(relation->rd_indextuple);
1394  MemoryContextSwitchTo(oldcontext);
1395  ReleaseSysCache(tuple);
1396 
1397  /*
1398  * Look up the index's access method, save the OID of its handler function
1399  */
1400  tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(relation->rd_rel->relam));
1401  if (!HeapTupleIsValid(tuple))
1402  elog(ERROR, "cache lookup failed for access method %u",
1403  relation->rd_rel->relam);
1404  aform = (Form_pg_am) GETSTRUCT(tuple);
1405  relation->rd_amhandler = aform->amhandler;
1406  ReleaseSysCache(tuple);
1407 
1408  indnatts = RelationGetNumberOfAttributes(relation);
1409  if (indnatts != IndexRelationGetNumberOfAttributes(relation))
1410  elog(ERROR, "relnatts disagrees with indnatts for index %u",
1411  RelationGetRelid(relation));
1412  indnkeyatts = IndexRelationGetNumberOfKeyAttributes(relation);
1413 
1414  /*
1415  * Make the private context to hold index access info. The reason we need
1416  * a context, and not just a couple of pallocs, is so that we won't leak
1417  * any subsidiary info attached to fmgr lookup records.
1418  */
1420  "index info",
1422  relation->rd_indexcxt = indexcxt;
1424  RelationGetRelationName(relation));
1425 
1426  /*
1427  * Now we can fetch the index AM's API struct
1428  */
1429  InitIndexAmRoutine(relation);
1430 
1431  /*
1432  * Allocate arrays to hold data. Opclasses are not used for included
1433  * columns, so allocate them for indnkeyatts only.
1434  */
1435  relation->rd_opfamily = (Oid *)
1436  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1437  relation->rd_opcintype = (Oid *)
1438  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1439 
1440  amsupport = relation->rd_indam->amsupport;
1441  if (amsupport > 0)
1442  {
1443  int nsupport = indnatts * amsupport;
1444 
1445  relation->rd_support = (RegProcedure *)
1446  MemoryContextAllocZero(indexcxt, nsupport * sizeof(RegProcedure));
1447  relation->rd_supportinfo = (FmgrInfo *)
1448  MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
1449  }
1450  else
1451  {
1452  relation->rd_support = NULL;
1453  relation->rd_supportinfo = NULL;
1454  }
1455 
1456  relation->rd_indcollation = (Oid *)
1457  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1458 
1459  relation->rd_indoption = (int16 *)
1460  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(int16));
1461 
1462  /*
1463  * indcollation cannot be referenced directly through the C struct,
1464  * because it comes after the variable-width indkey field. Must extract
1465  * the datum the hard way...
1466  */
1467  indcollDatum = fastgetattr(relation->rd_indextuple,
1468  Anum_pg_index_indcollation,
1470  &isnull);
1471  Assert(!isnull);
1472  indcoll = (oidvector *) DatumGetPointer(indcollDatum);
1473  memcpy(relation->rd_indcollation, indcoll->values, indnkeyatts * sizeof(Oid));
1474 
1475  /*
1476  * indclass cannot be referenced directly through the C struct, because it
1477  * comes after the variable-width indkey field. Must extract the datum
1478  * the hard way...
1479  */
1480  indclassDatum = fastgetattr(relation->rd_indextuple,
1481  Anum_pg_index_indclass,
1483  &isnull);
1484  Assert(!isnull);
1485  indclass = (oidvector *) DatumGetPointer(indclassDatum);
1486 
1487  /*
1488  * Fill the support procedure OID array, as well as the info about
1489  * opfamilies and opclass input types. (aminfo and supportinfo are left
1490  * as zeroes, and are filled on-the-fly when used)
1491  */
1492  IndexSupportInitialize(indclass, relation->rd_support,
1493  relation->rd_opfamily, relation->rd_opcintype,
1494  amsupport, indnkeyatts);
1495 
1496  /*
1497  * Similarly extract indoption and copy it to the cache entry
1498  */
1499  indoptionDatum = fastgetattr(relation->rd_indextuple,
1500  Anum_pg_index_indoption,
1502  &isnull);
1503  Assert(!isnull);
1504  indoption = (int2vector *) DatumGetPointer(indoptionDatum);
1505  memcpy(relation->rd_indoption, indoption->values, indnkeyatts * sizeof(int16));
1506 
1507  (void) RelationGetIndexAttOptions(relation, false);
1508 
1509  /*
1510  * expressions, predicate, exclusion caches will be filled later
1511  */
1512  relation->rd_indexprs = NIL;
1513  relation->rd_indpred = NIL;
1514  relation->rd_exclops = NULL;
1515  relation->rd_exclprocs = NULL;
1516  relation->rd_exclstrats = NULL;
1517  relation->rd_amcache = NULL;
1518 }
signed short int16
Definition: c.h:354
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
#define NIL
Definition: pg_list.h:65
Definition: c.h:594
struct IndexAmRoutine * rd_indam
Definition: rel.h:188
Definition: fmgr.h:56
uint16 amsupport
Definition: amapi.h:173
#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:511
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:1340
static void IndexSupportInitialize(oidvector *indclass, RegProcedure *indexSupport, Oid *opFamily, Oid *opcInType, StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber)
Definition: relcache.c:1534
struct HeapTupleData * rd_indextuple
Definition: rel.h:176
Form_pg_index rd_index
Definition: rel.h:174
unsigned short uint16
Definition: c.h:366
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:4217
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:602
#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:66
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
Definition: c.h:583
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:738
int16 values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:591
#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:5428
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 1744 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().

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

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