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

3216 {
3218  RelIdCacheEnt *idhentry;
3219  int i;
3220 
3221  /*
3222  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3223  * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3224  * logic as in AtEOXact_RelationCache.
3225  */
3227  {
3228  hash_seq_init(&status, RelationIdCache);
3229  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3230  {
3231  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3232  mySubid, parentSubid);
3233  }
3234  }
3235  else
3236  {
3237  for (i = 0; i < eoxact_list_len; i++)
3238  {
3239  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3240  (void *) &eoxact_list[i],
3241  HASH_FIND,
3242  NULL);
3243  if (idhentry != NULL)
3244  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3245  mySubid, parentSubid);
3246  }
3247  }
3248 
3249  /* Don't reset the list; we still need more cleanup later */
3250 }
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:3261
Relation reldesc
Definition: relcache.c:128
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
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:1401
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1391
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
static int eoxact_list_len
Definition: relcache.c:165

◆ AtEOXact_RelationCache()

void AtEOXact_RelationCache ( bool  isCommit)

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

3070 {
3072  RelIdCacheEnt *idhentry;
3073  int i;
3074 
3075  /*
3076  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3077  * listed in it. Otherwise fall back on a hash_seq_search scan.
3078  *
3079  * For simplicity, eoxact_list[] entries are not deleted till end of
3080  * top-level transaction, even though we could remove them at
3081  * subtransaction end in some cases, or remove relations from the list if
3082  * they are cleared for other reasons. Therefore we should expect the
3083  * case that list entries are not found in the hashtable; if not, there's
3084  * nothing to do for them.
3085  */
3087  {
3088  hash_seq_init(&status, RelationIdCache);
3089  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3090  {
3091  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3092  }
3093  }
3094  else
3095  {
3096  for (i = 0; i < eoxact_list_len; i++)
3097  {
3098  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3099  (void *) &eoxact_list[i],
3100  HASH_FIND,
3101  NULL);
3102  if (idhentry != NULL)
3103  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3104  }
3105  }
3106 
3107  if (EOXactTupleDescArrayLen > 0)
3108  {
3109  Assert(EOXactTupleDescArray != NULL);
3110  for (i = 0; i < NextEOXactTupleDescNum; i++)
3113  EOXactTupleDescArray = NULL;
3114  }
3115 
3116  /* Now we're out of the transaction and can clear the lists */
3117  eoxact_list_len = 0;
3118  eoxact_list_overflowed = false;
3119  NextEOXactTupleDescNum = 0;
3121 }
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:919
static HTAB * RelationIdCache
Definition: relcache.c:131
static void AtEOXact_cleanup(Relation relation, bool isCommit)
Definition: relcache.c:3132
static bool eoxact_list_overflowed
Definition: relcache.c:166
static int NextEOXactTupleDescNum
Definition: relcache.c:182
void pfree(void *pointer)
Definition: mcxt.c:1057
#define Assert(condition)
Definition: c.h:746
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1401
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1391
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:313
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
static int eoxact_list_len
Definition: relcache.c:165
static TupleDesc * EOXactTupleDescArray
Definition: relcache.c:181

◆ errtable()

int errtable ( Relation  rel)

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

5498 {
5502 
5503  return 0; /* return value does not matter */
5504 }
#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:1262
#define RelationGetNamespace(relation)
Definition: rel.h:497

◆ errtablecol()

int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5514 of file relcache.c.

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

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

5515 {
5516  TupleDesc reldesc = RelationGetDescr(rel);
5517  const char *colname;
5518 
5519  /* Use reldesc if it's a user attribute, else consult the catalogs */
5520  if (attnum > 0 && attnum <= reldesc->natts)
5521  colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
5522  else
5523  colname = get_attname(RelationGetRelid(rel), attnum, false);
5524 
5525  return errtablecolname(rel, colname);
5526 }
#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:623
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:5538

◆ errtablecolname()

int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5538 of file relcache.c.

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

Referenced by errtablecol().

5539 {
5540  errtable(rel);
5542 
5543  return 0; /* return value does not matter */
5544 }
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:67
int err_generic_string(int field, const char *str)
Definition: elog.c:1262
int errtable(Relation rel)
Definition: relcache.c:5497

◆ errtableconstraint()

int errtableconstraint ( Relation  rel,
const char *  conname 
)

Definition at line 5551 of file relcache.c.

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

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

5552 {
5553  errtable(rel);
5555 
5556  return 0; /* return value does not matter */
5557 }
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:69
int err_generic_string(int field, const char *str)
Definition: elog.c:1262
int errtable(Relation rel)
Definition: relcache.c:5497

◆ GetRelationPublicationActions()

struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

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

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

◆ RelationAssumeNewRelfilenode()

void RelationAssumeNewRelfilenode ( Relation  relation)

Definition at line 3738 of file relcache.c.

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

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

3739 {
3742  relation->rd_firstRelfilenodeSubid = relation->rd_newRelfilenodeSubid;
3743 
3744  /* Flag relation as needing eoxact cleanup (to clear these fields) */
3745  EOXactListAdd(relation);
3746 }
#define EOXactListAdd(rel)
Definition: relcache.c:168
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:103
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:723
#define InvalidSubTransactionId
Definition: c.h:527

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

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

References LWLockRelease().

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

6324 {
6325  LWLockRelease(RelCacheInitLock);
6326 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )

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

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

◆ RelationCacheInitFileRemove()

void RelationCacheInitFileRemove ( void  )

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

6339 {
6340  const char *tblspcdir = "pg_tblspc";
6341  DIR *dir;
6342  struct dirent *de;
6343  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6344 
6345  snprintf(path, sizeof(path), "global/%s",
6347  unlink_initfile(path, LOG);
6348 
6349  /* Scan everything in the default tablespace */
6351 
6352  /* Scan the tablespace link directory to find non-default tablespaces */
6353  dir = AllocateDir(tblspcdir);
6354 
6355  while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6356  {
6357  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6358  {
6359  /* Scan the tablespace dir for per-database dirs */
6360  snprintf(path, sizeof(path), "%s/%s/%s",
6361  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6363  }
6364  }
6365 
6366  FreeDir(dir);
6367 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6371
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2664
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:26
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2583
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6395
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:215
int FreeDir(DIR *dir)
Definition: fd.c:2701

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 3764 of file relcache.c.

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

Referenced by InitPostgres().

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

◆ RelationCacheInitializePhase2()

void RelationCacheInitializePhase2 ( void  )

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

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

◆ RelationCacheInitializePhase3()

void RelationCacheInitializePhase3 ( void  )

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

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

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

◆ RelationCacheInvalidateEntry()

void RelationCacheInvalidateEntry ( Oid  relationId)

Definition at line 2788 of file relcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

2789 {
2790  Relation relation;
2791 
2792  RelationIdCacheLookup(relationId, relation);
2793 
2794  if (PointerIsValid(relation))
2795  {
2797  RelationFlushRelation(relation);
2798  }
2799 }
static long relcacheInvalsReceived
Definition: relcache.c:151
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:210
static void RelationFlushRelation(Relation relation)
Definition: relcache.c:2711
#define PointerIsValid(pointer)
Definition: c.h:640

◆ RelationClose()

void RelationClose ( Relation  relation)

Definition at line 2110 of file relcache.c.

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

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

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

◆ RelationCloseSmgrByOid()

void RelationCloseSmgrByOid ( Oid  relationId)

Definition at line 2934 of file relcache.c.

References PointerIsValid, RelationCloseSmgr, and RelationIdCacheLookup.

Referenced by swap_relation_files().

2935 {
2936  Relation relation;
2937 
2938  RelationIdCacheLookup(relationId, relation);
2939 
2940  if (!PointerIsValid(relation))
2941  return; /* not in cache, nothing to do */
2942 
2943  RelationCloseSmgr(relation);
2944 }
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:210
#define RelationCloseSmgr(relation)
Definition: rel.h:525
#define PointerIsValid(pointer)
Definition: c.h:640

◆ RelationForgetRelation()

void RelationForgetRelation ( Oid  rid)

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

2745 {
2746  Relation relation;
2747 
2748  RelationIdCacheLookup(rid, relation);
2749 
2750  if (!PointerIsValid(relation))
2751  return; /* not in cache, nothing to do */
2752 
2753  if (!RelationHasReferenceCountZero(relation))
2754  elog(ERROR, "relation %u is still open", rid);
2755 
2757  if (relation->rd_createSubid != InvalidSubTransactionId ||
2759  {
2760  /*
2761  * In the event of subtransaction rollback, we must not forget
2762  * rd_*Subid. Mark the entry "dropped" so RelationClearRelation()
2763  * invalidates it in lieu of destroying it. (If we're in a top
2764  * transaction, we could opt to destroy the entry.)
2765  */
2767  }
2768 
2769  RelationClearRelation(relation, false);
2770 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2431
#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:746
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:723
#define InvalidSubTransactionId
Definition: c.h:527
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:440
#define elog(elevel,...)
Definition: elog.h:214
#define PointerIsValid(pointer)
Definition: c.h:640
SubTransactionId rd_droppedSubid
Definition: rel.h:107

◆ RelationGetDummyIndexExpressions()

List* RelationGetDummyIndexExpressions ( Relation  relation)

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

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

◆ RelationGetExclusionInfo()

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

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

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

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

5437 {
5438  MemoryContext oldcxt;
5439  bytea **opts = relation->rd_opcoptions;
5440  Oid relid = RelationGetRelid(relation);
5441  int natts = RelationGetNumberOfAttributes(relation); /* XXX
5442  * IndexRelationGetNumberOfKeyAttributes */
5443  int i;
5444 
5445  /* Try to copy cached options. */
5446  if (opts)
5447  return copy ? CopyIndexAttOptions(opts, natts) : opts;
5448 
5449  /* Get and parse opclass options. */
5450  opts = palloc0(sizeof(*opts) * natts);
5451 
5452  for (i = 0; i < natts; i++)
5453  {
5455  {
5456  Datum attoptions = get_attoptions(relid, i + 1);
5457 
5458  opts[i] = index_opclass_options(relation, i + 1, attoptions, false);
5459 
5460  if (attoptions != (Datum) 0)
5461  pfree(DatumGetPointer(attoptions));
5462  }
5463  }
5464 
5465  /* Copy parsed options to the cache. */
5466  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
5467  relation->rd_opcoptions = CopyIndexAttOptions(opts, natts);
5468  MemoryContextSwitchTo(oldcxt);
5469 
5470  if (copy)
5471  return opts;
5472 
5473  for (i = 0; i < natts; i++)
5474  {
5475  if (opts[i])
5476  pfree(opts[i]);
5477  }
5478 
5479  pfree(opts);
5480 
5481  return relation->rd_opcoptions;
5482 }
#define AttributeRelidNumIndexId
Definition: indexing.h:107
#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:1057
static bytea ** CopyIndexAttOptions(bytea **srcopts, int natts)
Definition: relcache.c:5416
bytea * index_opclass_options(Relation indrel, AttrNumber attnum, Datum attoptions, bool validate)
Definition: indexam.c:937
void * palloc0(Size size)
Definition: mcxt.c:981
uintptr_t Datum
Definition: postgres.h:367
#define DatumGetPointer(X)
Definition: postgres.h:549
MemoryContext rd_indexcxt
Definition: rel.h:186
int i
Definition: c.h:563
bool criticalRelcachesBuilt
Definition: relcache.c:137
#define RelationGetRelid(relation)
Definition: rel.h:456

◆ RelationGetIndexAttrBitmap()

Bitmapset* RelationGetIndexAttrBitmap ( Relation  relation,
IndexAttrBitmapKind  attrKind 
)

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

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

◆ RelationGetIndexExpressions()

List* RelationGetIndexExpressions ( Relation  relation)

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

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

◆ RelationGetIndexList()

List* RelationGetIndexList ( Relation  relation)

Definition at line 4514 of file relcache.c.

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

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

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

◆ RelationGetIndexPredicate()

List* RelationGetIndexPredicate ( Relation  relation)

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

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

◆ RelationGetIndexRawAttOptions()

Datum* RelationGetIndexRawAttOptions ( Relation  relation)

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

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

◆ RelationGetPrimaryKeyIndex()

Oid RelationGetPrimaryKeyIndex ( Relation  relation)

Definition at line 4702 of file relcache.c.

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

Referenced by build_replindex_scan_key(), and GetRelationIdentityOrPK().

4703 {
4704  List *ilist;
4705 
4706  if (!relation->rd_indexvalid)
4707  {
4708  /* RelationGetIndexList does the heavy lifting. */
4709  ilist = RelationGetIndexList(relation);
4710  list_free(ilist);
4711  Assert(relation->rd_indexvalid);
4712  }
4713 
4714  return relation->rd_pkindex;
4715 }
Oid rd_pkindex
Definition: rel.h:138
bool rd_indexvalid
Definition: rel.h:63
#define Assert(condition)
Definition: c.h:746
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4514
void list_free(List *list)
Definition: list.c:1376
Definition: pg_list.h:50

◆ RelationGetReplicaIndex()

Oid RelationGetReplicaIndex ( Relation  relation)

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

4724 {
4725  List *ilist;
4726 
4727  if (!relation->rd_indexvalid)
4728  {
4729  /* RelationGetIndexList does the heavy lifting. */
4730  ilist = RelationGetIndexList(relation);
4731  list_free(ilist);
4732  Assert(relation->rd_indexvalid);
4733  }
4734 
4735  return relation->rd_replidindex;
4736 }
Oid rd_replidindex
Definition: rel.h:139
bool rd_indexvalid
Definition: rel.h:63
#define Assert(condition)
Definition: c.h:746
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4514
void list_free(List *list)
Definition: list.c:1376
Definition: pg_list.h:50

◆ RelationGetStatExtList()

List* RelationGetStatExtList ( Relation  relation)

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

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

◆ RelationIdGetRelation()

Relation RelationIdGetRelation ( Oid  relationId)

Definition at line 2004 of file relcache.c.

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

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

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

◆ RelationIdIsInInitFile()

bool RelationIdIsInInitFile ( Oid  relationId)

Definition at line 6258 of file relcache.c.

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

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

6259 {
6260  if (relationId == SharedSecLabelRelationId ||
6261  relationId == TriggerRelidNameIndexId ||
6262  relationId == DatabaseNameIndexId ||
6263  relationId == SharedSecLabelObjectIndexId)
6264  {
6265  /*
6266  * If this Assert fails, we don't need the applicable special case
6267  * anymore.
6268  */
6269  Assert(!RelationSupportsSysCache(relationId));
6270  return true;
6271  }
6272  return RelationSupportsSysCache(relationId);
6273 }
#define TriggerRelidNameIndexId
Definition: indexing.h:264
#define Assert(condition)
Definition: c.h:746
#define DatabaseNameIndexId
Definition: indexing.h:155
#define SharedSecLabelObjectIndexId
Definition: indexing.h:331
bool RelationSupportsSysCache(Oid relid)
Definition: syscache.c:1521

◆ RelationInitIndexAccessInfo()

void RelationInitIndexAccessInfo ( Relation  relation)

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

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

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

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

Variable Documentation

◆ criticalRelcachesBuilt

◆ criticalSharedRelcachesBuilt

bool criticalSharedRelcachesBuilt