PostgreSQL Source Code  git master
relcache.h File Reference
#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"
 

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)
 
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 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

◆ RELCACHE_INIT_FILENAME

#define RELCACHE_INIT_FILENAME   "pg_internal.init"

Typedef Documentation

◆ IndexAttrBitmapKind

◆ Relation

typedef struct RelationData* Relation

Definition at line 26 of file relcache.h.

◆ RelationPtr

Definition at line 34 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 54 of file relcache.h.

Function Documentation

◆ AtEOSubXact_RelationCache()

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

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

3081 {
3083  RelIdCacheEnt *idhentry;
3084  int i;
3085 
3086  /*
3087  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3088  * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3089  * logic as in AtEOXact_RelationCache.
3090  */
3092  {
3093  hash_seq_init(&status, RelationIdCache);
3094  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3095  {
3096  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3097  mySubid, parentSubid);
3098  }
3099  }
3100  else
3101  {
3102  for (i = 0; i < eoxact_list_len; i++)
3103  {
3104  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3105  (void *) &eoxact_list[i],
3106  HASH_FIND,
3107  NULL);
3108  if (idhentry != NULL)
3109  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3110  mySubid, parentSubid);
3111  }
3112  }
3113 
3114  /* Don't reset the list; we still need more cleanup later */
3115 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:162
static void AtEOSubXact_cleanup(Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
Definition: relcache.c:3126
Relation reldesc
Definition: relcache.c:126
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
static HTAB * RelationIdCache
Definition: relcache.c:129
static bool eoxact_list_overflowed
Definition: relcache.c:164
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:226
static int eoxact_list_len
Definition: relcache.c:163

◆ AtEOXact_RelationCache()

void AtEOXact_RelationCache ( bool  isCommit)

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

2942 {
2944  RelIdCacheEnt *idhentry;
2945  int i;
2946 
2947  /*
2948  * Unless the eoxact_list[] overflowed, we only need to examine the rels
2949  * listed in it. Otherwise fall back on a hash_seq_search scan.
2950  *
2951  * For simplicity, eoxact_list[] entries are not deleted till end of
2952  * top-level transaction, even though we could remove them at
2953  * subtransaction end in some cases, or remove relations from the list if
2954  * they are cleared for other reasons. Therefore we should expect the
2955  * case that list entries are not found in the hashtable; if not, there's
2956  * nothing to do for them.
2957  */
2959  {
2960  hash_seq_init(&status, RelationIdCache);
2961  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2962  {
2963  AtEOXact_cleanup(idhentry->reldesc, isCommit);
2964  }
2965  }
2966  else
2967  {
2968  for (i = 0; i < eoxact_list_len; i++)
2969  {
2970  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
2971  (void *) &eoxact_list[i],
2972  HASH_FIND,
2973  NULL);
2974  if (idhentry != NULL)
2975  AtEOXact_cleanup(idhentry->reldesc, isCommit);
2976  }
2977  }
2978 
2979  if (EOXactTupleDescArrayLen > 0)
2980  {
2981  Assert(EOXactTupleDescArray != NULL);
2982  for (i = 0; i < NextEOXactTupleDescNum; i++)
2985  EOXactTupleDescArray = NULL;
2986  }
2987 
2988  /* Now we're out of the transaction and can clear the lists */
2989  eoxact_list_len = 0;
2990  eoxact_list_overflowed = false;
2991  NextEOXactTupleDescNum = 0;
2993 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:162
static int EOXactTupleDescArrayLen
Definition: relcache.c:181
Relation reldesc
Definition: relcache.c:126
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
static HTAB * RelationIdCache
Definition: relcache.c:129
static void AtEOXact_cleanup(Relation relation, bool isCommit)
Definition: relcache.c:3004
static bool eoxact_list_overflowed
Definition: relcache.c:164
static int NextEOXactTupleDescNum
Definition: relcache.c:180
void pfree(void *pointer)
Definition: mcxt.c:1056
#define Assert(condition)
Definition: c.h:739
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
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:226
static int eoxact_list_len
Definition: relcache.c:163
static TupleDesc * EOXactTupleDescArray
Definition: relcache.c:179

◆ errtable()

int errtable ( Relation  rel)

Definition at line 5201 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(), BuildRelationExtStatistics(), errtablecolname(), and errtableconstraint().

5202 {
5206 
5207  return 0; /* return value does not matter */
5208 }
#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:3094
#define RelationGetRelationName(relation)
Definition: rel.h:462
int err_generic_string(int field, const char *str)
Definition: elog.c:1273
#define RelationGetNamespace(relation)
Definition: rel.h:469

◆ errtablecol()

int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5218 of file relcache.c.

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

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

5219 {
5220  TupleDesc reldesc = RelationGetDescr(rel);
5221  const char *colname;
5222 
5223  /* Use reldesc if it's a user attribute, else consult the catalogs */
5224  if (attnum > 0 && attnum <= reldesc->natts)
5225  colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
5226  else
5227  colname = get_attname(RelationGetRelid(rel), attnum, false);
5228 
5229  return errtablecolname(rel, colname);
5230 }
#define RelationGetDescr(relation)
Definition: rel.h:454
#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:616
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:775
#define RelationGetRelid(relation)
Definition: rel.h:428
int errtablecolname(Relation rel, const char *colname)
Definition: relcache.c:5242

◆ errtablecolname()

int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5242 of file relcache.c.

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

Referenced by errtablecol().

5243 {
5244  errtable(rel);
5246 
5247  return 0; /* return value does not matter */
5248 }
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:67
int err_generic_string(int field, const char *str)
Definition: elog.c:1273
int errtable(Relation rel)
Definition: relcache.c:5201

◆ errtableconstraint()

int errtableconstraint ( Relation  rel,
const char *  conname 
)

Definition at line 5255 of file relcache.c.

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

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

5256 {
5257  errtable(rel);
5259 
5260  return 0; /* return value does not matter */
5261 }
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:69
int err_generic_string(int field, const char *str)
Definition: elog.c:1273
int errtable(Relation rel)
Definition: relcache.c:5201

◆ GetRelationPublicationActions()

struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

Definition at line 5122 of file relcache.c.

References CacheMemoryContext, elog, ERROR, 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, RelationGetRelid, ReleaseSysCache(), and SearchSysCache1().

Referenced by CheckCmdReplicaIdentity().

5123 {
5124  List *puboids;
5125  ListCell *lc;
5126  MemoryContext oldcxt;
5127  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5128 
5129  /*
5130  * If not publishable, it publishes no actions. (pgoutput_change() will
5131  * ignore it.)
5132  */
5133  if (!is_publishable_relation(relation))
5134  return pubactions;
5135 
5136  if (relation->rd_pubactions)
5137  return memcpy(pubactions, relation->rd_pubactions,
5138  sizeof(PublicationActions));
5139 
5140  /* Fetch the publication membership info. */
5141  puboids = GetRelationPublications(RelationGetRelid(relation));
5142  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5143 
5144  foreach(lc, puboids)
5145  {
5146  Oid pubid = lfirst_oid(lc);
5147  HeapTuple tup;
5148  Form_pg_publication pubform;
5149 
5151 
5152  if (!HeapTupleIsValid(tup))
5153  elog(ERROR, "cache lookup failed for publication %u", pubid);
5154 
5155  pubform = (Form_pg_publication) GETSTRUCT(tup);
5156 
5157  pubactions->pubinsert |= pubform->pubinsert;
5158  pubactions->pubupdate |= pubform->pubupdate;
5159  pubactions->pubdelete |= pubform->pubdelete;
5160  pubactions->pubtruncate |= pubform->pubtruncate;
5161 
5162  ReleaseSysCache(tup);
5163 
5164  /*
5165  * If we know everything is replicated, there is no point to check for
5166  * other publications.
5167  */
5168  if (pubactions->pubinsert && pubactions->pubupdate &&
5169  pubactions->pubdelete && pubactions->pubtruncate)
5170  break;
5171  }
5172 
5173  if (relation->rd_pubactions)
5174  {
5175  pfree(relation->rd_pubactions);
5176  relation->rd_pubactions = NULL;
5177  }
5178 
5179  /* Now save copy of the actions in the relcache entry. */
5181  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5182  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5183  MemoryContextSwitchTo(oldcxt);
5184 
5185  return pubactions;
5186 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
PublicationActions * rd_pubactions
Definition: rel.h:125
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned int Oid
Definition: postgres_ext.h:31
List * GetRelationPublications(Oid relid)
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
List * list_concat_unique_oid(List *list1, const List *list2)
Definition: list.c:1302
bool is_publishable_relation(Relation rel)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void * palloc0(Size size)
Definition: mcxt.c:980
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
List * GetAllTablesPublications(void)
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:228
FormData_pg_publication * Form_pg_publication
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:428
#define lfirst_oid(lc)
Definition: pg_list.h:192
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ 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 3178 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_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(), relfilenode, relkind, relpersistence, TupleDescData::tdrefcount, and TupleDescAttr.

Referenced by heap_create().

3189 {
3190  Relation rel;
3191  MemoryContext oldcxt;
3192  int natts = tupDesc->natts;
3193  int i;
3194  bool has_not_null;
3195  bool nailit;
3196 
3197  AssertArg(natts >= 0);
3198 
3199  /*
3200  * check for creation of a rel that must be nailed in cache.
3201  *
3202  * XXX this list had better match the relations specially handled in
3203  * RelationCacheInitializePhase2/3.
3204  */
3205  switch (relid)
3206  {
3207  case DatabaseRelationId:
3208  case AuthIdRelationId:
3209  case AuthMemRelationId:
3210  case RelationRelationId:
3211  case AttributeRelationId:
3212  case ProcedureRelationId:
3213  case TypeRelationId:
3214  nailit = true;
3215  break;
3216  default:
3217  nailit = false;
3218  break;
3219  }
3220 
3221  /*
3222  * check that hardwired list of shared rels matches what's in the
3223  * bootstrap .bki file. If you get a failure here during initdb, you
3224  * probably need to fix IsSharedRelation() to match whatever you've done
3225  * to the set of shared relations.
3226  */
3227  if (shared_relation != IsSharedRelation(relid))
3228  elog(ERROR, "shared_relation flag for \"%s\" does not match IsSharedRelation(%u)",
3229  relname, relid);
3230 
3231  /* Shared relations had better be mapped, too */
3232  Assert(mapped_relation || !shared_relation);
3233 
3234  /*
3235  * switch to the cache context to create the relcache entry.
3236  */
3237  if (!CacheMemoryContext)
3239 
3241 
3242  /*
3243  * allocate a new relation descriptor and fill in basic state fields.
3244  */
3245  rel = (Relation) palloc0(sizeof(RelationData));
3246 
3247  /* make sure relation is marked as having no open file yet */
3248  rel->rd_smgr = NULL;
3249 
3250  /* mark it nailed if appropriate */
3251  rel->rd_isnailed = nailit;
3252 
3253  rel->rd_refcnt = nailit ? 1 : 0;
3254 
3255  /* it's being created in this transaction */
3258 
3259  /*
3260  * create a new tuple descriptor from the one passed in. We do this
3261  * partly to copy it into the cache context, and partly because the new
3262  * relation can't have any defaults or constraints yet; they have to be
3263  * added in later steps, because they require additions to multiple system
3264  * catalogs. We can copy attnotnull constraints here, however.
3265  */
3266  rel->rd_att = CreateTupleDescCopy(tupDesc);
3267  rel->rd_att->tdrefcount = 1; /* mark as refcounted */
3268  has_not_null = false;
3269  for (i = 0; i < natts; i++)
3270  {
3271  Form_pg_attribute satt = TupleDescAttr(tupDesc, i);
3272  Form_pg_attribute datt = TupleDescAttr(rel->rd_att, i);
3273 
3274  datt->attidentity = satt->attidentity;
3275  datt->attgenerated = satt->attgenerated;
3276  datt->attnotnull = satt->attnotnull;
3277  has_not_null |= satt->attnotnull;
3278  }
3279 
3280  if (has_not_null)
3281  {
3282  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
3283 
3284  constr->has_not_null = true;
3285  rel->rd_att->constr = constr;
3286  }
3287 
3288  /*
3289  * initialize relation tuple form (caller may add/override data later)
3290  */
3292 
3293  namestrcpy(&rel->rd_rel->relname, relname);
3294  rel->rd_rel->relnamespace = relnamespace;
3295 
3296  rel->rd_rel->relkind = relkind;
3297  rel->rd_rel->relnatts = natts;
3298  rel->rd_rel->reltype = InvalidOid;
3299  /* needed when bootstrapping: */
3300  rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;
3301 
3302  /* set up persistence and relcache fields dependent on it */
3303  rel->rd_rel->relpersistence = relpersistence;
3304  switch (relpersistence)
3305  {
3306  case RELPERSISTENCE_UNLOGGED:
3307  case RELPERSISTENCE_PERMANENT:
3309  rel->rd_islocaltemp = false;
3310  break;
3311  case RELPERSISTENCE_TEMP:
3312  Assert(isTempOrTempToastNamespace(relnamespace));
3314  rel->rd_islocaltemp = true;
3315  break;
3316  default:
3317  elog(ERROR, "invalid relpersistence: %c", relpersistence);
3318  break;
3319  }
3320 
3321  /* if it's a materialized view, it's not populated initially */
3322  if (relkind == RELKIND_MATVIEW)
3323  rel->rd_rel->relispopulated = false;
3324  else
3325  rel->rd_rel->relispopulated = true;
3326 
3327  /* set replica identity -- system catalogs and non-tables don't have one */
3328  if (!IsCatalogNamespace(relnamespace) &&
3329  (relkind == RELKIND_RELATION ||
3330  relkind == RELKIND_MATVIEW ||
3331  relkind == RELKIND_PARTITIONED_TABLE))
3332  rel->rd_rel->relreplident = REPLICA_IDENTITY_DEFAULT;
3333  else
3334  rel->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
3335 
3336  /*
3337  * Insert relation physical and logical identifiers (OIDs) into the right
3338  * places. For a mapped relation, we set relfilenode to zero and rely on
3339  * RelationInitPhysicalAddr to consult the map.
3340  */
3341  rel->rd_rel->relisshared = shared_relation;
3342 
3343  RelationGetRelid(rel) = relid;
3344 
3345  for (i = 0; i < natts; i++)
3346  TupleDescAttr(rel->rd_att, i)->attrelid = relid;
3347 
3348  rel->rd_rel->reltablespace = reltablespace;
3349 
3350  if (mapped_relation)
3351  {
3352  rel->rd_rel->relfilenode = InvalidOid;
3353  /* Add it to the active mapping information */
3354  RelationMapUpdateMap(relid, relfilenode, shared_relation, true);
3355  }
3356  else
3357  rel->rd_rel->relfilenode = relfilenode;
3358 
3359  RelationInitLockInfo(rel); /* see lmgr.c */
3360 
3362 
3363  rel->rd_rel->relam = accessmtd;
3364 
3365  if (relkind == RELKIND_RELATION ||
3366  relkind == RELKIND_SEQUENCE ||
3367  relkind == RELKIND_TOASTVALUE ||
3368  relkind == RELKIND_MATVIEW)
3370 
3371  /*
3372  * Okay to insert into the relcache hash table.
3373  *
3374  * Ordinarily, there should certainly not be an existing hash entry for
3375  * the same OID; but during bootstrap, when we create a "real" relcache
3376  * entry for one of the bootstrap relations, we'll be overwriting the
3377  * phony one created with formrdesc. So allow that to happen for nailed
3378  * rels.
3379  */
3380  RelationCacheInsert(rel, nailit);
3381 
3382  /*
3383  * Flag relation as needing eoxact cleanup (to clear rd_createSubid). We
3384  * can't do this before storing relid in it.
3385  */
3386  EOXactListAdd(rel);
3387 
3388  /*
3389  * done building relcache entry.
3390  */
3391  MemoryContextSwitchTo(oldcxt);
3392 
3393  /* It's fully valid */
3394  rel->rd_isvalid = true;
3395 
3396  /*
3397  * Caller expects us to pin the returned entry.
3398  */
3400 
3401  return rel;
3402 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
#define EOXactListAdd(rel)
Definition: relcache.c:166
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3173
void RelationInitTableAccessMethod(Relation relation)
Definition: relcache.c:1725
#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:81
Form_pg_class rd_rel
Definition: rel.h:84
NameData relname
Definition: pg_class.h:35
int namestrcpy(Name name, const char *str)
Definition: name.c:250
char relkind
Definition: pg_class.h:81
struct RelationData * Relation
Definition: relcache.h:26
#define ERROR
Definition: elog.h:43
char relpersistence
Definition: pg_class.h:78
Oid relfilenode
Definition: pg_class.h:54
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1256
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:200
#define AssertArg(condition)
Definition: c.h:741
SubTransactionId rd_createSubid
Definition: rel.h:80
#define InvalidBackendId
Definition: backendid.h:23
void * palloc0(Size size)
Definition: mcxt.c:980
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2041
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:239
TupleDesc rd_att
Definition: rel.h:85
#define InvalidOid
Definition: postgres_ext.h:36
#define RelationCacheInsert(RELATION, replace_allowed)
Definition: relcache.c:186
#define CLASS_TUPLE_SIZE
Definition: pg_class.h:142
BackendId rd_backend
Definition: rel.h:59
#define Assert(condition)
Definition: c.h:739
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:707
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
#define InvalidSubTransactionId
Definition: c.h:520
bool IsCatalogNamespace(Oid namespaceId)
Definition: catalog.c:178
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150
int rd_refcnt
Definition: rel.h:58
#define elog(elevel,...)
Definition: elog.h:228
int i
int tdrefcount
Definition: tupdesc.h:84
bool has_not_null
Definition: tupdesc.h:44
#define RelationGetRelid(relation)
Definition: rel.h:428
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 5997 of file relcache.c.

References LWLockRelease().

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

5998 {
5999  LWLockRelease(RelCacheInitLock);
6000 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )

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

5973 {
5974  char localinitfname[MAXPGPATH];
5975  char sharedinitfname[MAXPGPATH];
5976 
5977  if (DatabasePath)
5978  snprintf(localinitfname, sizeof(localinitfname), "%s/%s",
5980  snprintf(sharedinitfname, sizeof(sharedinitfname), "global/%s",
5982 
5983  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
5984 
5985  /*
5986  * The files might not be there if no backend has been started since the
5987  * last removal. But complain about failures other than ENOENT with
5988  * ERROR. Fortunately, it's not too late to abort the transaction if we
5989  * can't get rid of the would-be-obsolete init file.
5990  */
5991  if (DatabasePath)
5992  unlink_initfile(localinitfname, ERROR);
5993  unlink_initfile(sharedinitfname, ERROR);
5994 }
#define ERROR
Definition: elog.h:43
#define MAXPGPATH
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:24
char * DatabasePath
Definition: globals.c:93
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6069
#define snprintf
Definition: port.h:192

◆ RelationCacheInitFileRemove()

void RelationCacheInitFileRemove ( void  )

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

6013 {
6014  const char *tblspcdir = "pg_tblspc";
6015  DIR *dir;
6016  struct dirent *de;
6017  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6018 
6019  snprintf(path, sizeof(path), "global/%s",
6021  unlink_initfile(path, LOG);
6022 
6023  /* Scan everything in the default tablespace */
6025 
6026  /* Scan the tablespace link directory to find non-default tablespaces */
6027  dir = AllocateDir(tblspcdir);
6028 
6029  while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6030  {
6031  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6032  {
6033  /* Scan the tablespace dir for per-database dirs */
6034  snprintf(path, sizeof(path), "%s/%s/%s",
6035  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6037  }
6038  }
6039 
6040  FreeDir(dir);
6041 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6045
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2584
#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:2503
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:24
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6069
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:192
int FreeDir(DIR *dir)
Definition: fd.c:2621

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 3582 of file relcache.c.

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

Referenced by InitPostgres().

3583 {
3584  HASHCTL ctl;
3585 
3586  /*
3587  * make sure cache memory context exists
3588  */
3589  if (!CacheMemoryContext)
3591 
3592  /*
3593  * create hashtable that indexes the relcache
3594  */
3595  MemSet(&ctl, 0, sizeof(ctl));
3596  ctl.keysize = sizeof(Oid);
3597  ctl.entrysize = sizeof(RelIdCacheEnt);
3598  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3599  &ctl, HASH_ELEM | HASH_BLOBS);
3600 
3601  /*
3602  * relation mapper needs to be initialized too
3603  */
3605 }
void RelationMapInitialize(void)
Definition: relmapper.c:584
#define HASH_ELEM
Definition: hsearch.h:87
struct relidcacheent RelIdCacheEnt
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:962
static HTAB * RelationIdCache
Definition: relcache.c:129
unsigned int Oid
Definition: postgres_ext.h:31
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Size keysize
Definition: hsearch.h:72
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
#define INITRELCACHESIZE
Definition: relcache.c:3579
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInitializePhase2()

void RelationCacheInitializePhase2 ( void  )

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

3620 {
3621  MemoryContext oldcxt;
3622 
3623  /*
3624  * relation mapper needs initialized too
3625  */
3627 
3628  /*
3629  * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3630  * nothing.
3631  */
3633  return;
3634 
3635  /*
3636  * switch to cache memory context
3637  */
3639 
3640  /*
3641  * Try to load the shared relcache cache file. If unsuccessful, bootstrap
3642  * the cache with pre-made descriptors for the critical shared catalogs.
3643  */
3644  if (!load_relcache_init_file(true))
3645  {
3646  formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
3647  Natts_pg_database, Desc_pg_database);
3648  formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
3649  Natts_pg_authid, Desc_pg_authid);
3650  formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
3651  Natts_pg_auth_members, Desc_pg_auth_members);
3652  formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
3653  Natts_pg_shseclabel, Desc_pg_shseclabel);
3654  formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
3655  Natts_pg_subscription, Desc_pg_subscription);
3656 
3657 #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
3658  }
3659 
3660  MemoryContextSwitchTo(oldcxt);
3661 }
static const FormData_pg_attribute Desc_pg_auth_members[Natts_pg_auth_members]
Definition: relcache.c:112
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5319
void RelationMapInitializePhase2(void)
Definition: relmapper.c:604
static const FormData_pg_attribute Desc_pg_authid[Natts_pg_authid]
Definition: relcache.c:111
static const FormData_pg_attribute Desc_pg_subscription[Natts_pg_subscription]
Definition: relcache.c:115
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static const FormData_pg_attribute Desc_pg_database[Natts_pg_database]
Definition: relcache.c:110
static const FormData_pg_attribute Desc_pg_shseclabel[Natts_pg_shseclabel]
Definition: relcache.c:114
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:372
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1789
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInitializePhase3()

void RelationCacheInitializePhase3 ( void  )

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

3679 {
3681  RelIdCacheEnt *idhentry;
3682  MemoryContext oldcxt;
3683  bool needNewCacheFile = !criticalSharedRelcachesBuilt;
3684 
3685  /*
3686  * relation mapper needs initialized too
3687  */
3689 
3690  /*
3691  * switch to cache memory context
3692  */
3694 
3695  /*
3696  * Try to load the local relcache cache file. If unsuccessful, bootstrap
3697  * the cache with pre-made descriptors for the critical "nailed-in" system
3698  * catalogs.
3699  */
3700  if (IsBootstrapProcessingMode() ||
3701  !load_relcache_init_file(false))
3702  {
3703  needNewCacheFile = true;
3704 
3705  formrdesc("pg_class", RelationRelation_Rowtype_Id, false,
3706  Natts_pg_class, Desc_pg_class);
3707  formrdesc("pg_attribute", AttributeRelation_Rowtype_Id, false,
3708  Natts_pg_attribute, Desc_pg_attribute);
3709  formrdesc("pg_proc", ProcedureRelation_Rowtype_Id, false,
3710  Natts_pg_proc, Desc_pg_proc);
3711  formrdesc("pg_type", TypeRelation_Rowtype_Id, false,
3712  Natts_pg_type, Desc_pg_type);
3713 
3714 #define NUM_CRITICAL_LOCAL_RELS 4 /* fix if you change list above */
3715  }
3716 
3717  MemoryContextSwitchTo(oldcxt);
3718 
3719  /* In bootstrap mode, the faked-up formrdesc info is all we'll have */
3721  return;
3722 
3723  /*
3724  * If we didn't get the critical system indexes loaded into relcache, do
3725  * so now. These are critical because the catcache and/or opclass cache
3726  * depend on them for fetches done during relcache load. Thus, we have an
3727  * infinite-recursion problem. We can break the recursion by doing
3728  * heapscans instead of indexscans at certain key spots. To avoid hobbling
3729  * performance, we only want to do that until we have the critical indexes
3730  * loaded into relcache. Thus, the flag criticalRelcachesBuilt is used to
3731  * decide whether to do heapscan or indexscan at the key spots, and we set
3732  * it true after we've loaded the critical indexes.
3733  *
3734  * The critical indexes are marked as "nailed in cache", partly to make it
3735  * easy for load_relcache_init_file to count them, but mainly because we
3736  * cannot flush and rebuild them once we've set criticalRelcachesBuilt to
3737  * true. (NOTE: perhaps it would be possible to reload them by
3738  * temporarily setting criticalRelcachesBuilt to false again. For now,
3739  * though, we just nail 'em in.)
3740  *
3741  * RewriteRelRulenameIndexId and TriggerRelidNameIndexId are not critical
3742  * in the same way as the others, because the critical catalogs don't
3743  * (currently) have any rules or triggers, and so these indexes can be
3744  * rebuilt without inducing recursion. However they are used during
3745  * relcache load when a rel does have rules or triggers, so we choose to
3746  * nail them for performance reasons.
3747  */
3749  {
3751  RelationRelationId);
3753  AttributeRelationId);
3755  IndexRelationId);
3757  OperatorClassRelationId);
3759  AccessMethodProcedureRelationId);
3761  RewriteRelationId);
3763  TriggerRelationId);
3764 
3765 #define NUM_CRITICAL_LOCAL_INDEXES 7 /* fix if you change list above */
3766 
3767  criticalRelcachesBuilt = true;
3768  }
3769 
3770  /*
3771  * Process critical shared indexes too.
3772  *
3773  * DatabaseNameIndexId isn't critical for relcache loading, but rather for
3774  * initial lookup of MyDatabaseId, without which we'll never find any
3775  * non-shared catalogs at all. Autovacuum calls InitPostgres with a
3776  * database OID, so it instead depends on DatabaseOidIndexId. We also
3777  * need to nail up some indexes on pg_authid and pg_auth_members for use
3778  * during client authentication. SharedSecLabelObjectIndexId isn't
3779  * critical for the core system, but authentication hooks might be
3780  * interested in it.
3781  */
3783  {
3785  DatabaseRelationId);
3787  DatabaseRelationId);
3789  AuthIdRelationId);
3791  AuthIdRelationId);
3793  AuthMemRelationId);
3795  SharedSecLabelRelationId);
3796 
3797 #define NUM_CRITICAL_SHARED_INDEXES 6 /* fix if you change list above */
3798 
3800  }
3801 
3802  /*
3803  * Now, scan all the relcache entries and update anything that might be
3804  * wrong in the results from formrdesc or the relcache cache file. If we
3805  * faked up relcache entries using formrdesc, then read the real pg_class
3806  * rows and replace the fake entries with them. Also, if any of the
3807  * relcache entries have rules, triggers, or security policies, load that
3808  * info the hard way since it isn't recorded in the cache file.
3809  *
3810  * Whenever we access the catalogs to read data, there is a possibility of
3811  * a shared-inval cache flush causing relcache entries to be removed.
3812  * Since hash_seq_search only guarantees to still work after the *current*
3813  * entry is removed, it's unsafe to continue the hashtable scan afterward.
3814  * We handle this by restarting the scan from scratch after each access.
3815  * This is theoretically O(N^2), but the number of entries that actually
3816  * need to be fixed is small enough that it doesn't matter.
3817  */
3818  hash_seq_init(&status, RelationIdCache);
3819 
3820  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3821  {
3822  Relation relation = idhentry->reldesc;
3823  bool restart = false;
3824 
3825  /*
3826  * Make sure *this* entry doesn't get flushed while we work with it.
3827  */
3829 
3830  /*
3831  * If it's a faked-up entry, read the real pg_class tuple.
3832  */
3833  if (relation->rd_rel->relowner == InvalidOid)
3834  {
3835  HeapTuple htup;
3836  Form_pg_class relp;
3837 
3838  htup = SearchSysCache1(RELOID,
3839  ObjectIdGetDatum(RelationGetRelid(relation)));
3840  if (!HeapTupleIsValid(htup))
3841  elog(FATAL, "cache lookup failed for relation %u",
3842  RelationGetRelid(relation));
3843  relp = (Form_pg_class) GETSTRUCT(htup);
3844 
3845  /*
3846  * Copy tuple to relation->rd_rel. (See notes in
3847  * AllocateRelationDesc())
3848  */
3849  memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
3850 
3851  /* Update rd_options while we have the tuple */
3852  if (relation->rd_options)
3853  pfree(relation->rd_options);
3854  RelationParseRelOptions(relation, htup);
3855 
3856  /*
3857  * Check the values in rd_att were set up correctly. (We cannot
3858  * just copy them over now: formrdesc must have set up the rd_att
3859  * data correctly to start with, because it may already have been
3860  * copied into one or more catcache entries.)
3861  */
3862  Assert(relation->rd_att->tdtypeid == relp->reltype);
3863  Assert(relation->rd_att->tdtypmod == -1);
3864 
3865  ReleaseSysCache(htup);
3866 
3867  /* relowner had better be OK now, else we'll loop forever */
3868  if (relation->rd_rel->relowner == InvalidOid)
3869  elog(ERROR, "invalid relowner in pg_class entry for \"%s\"",
3870  RelationGetRelationName(relation));
3871 
3872  restart = true;
3873  }
3874 
3875  /*
3876  * Fix data that isn't saved in relcache cache file.
3877  *
3878  * relhasrules or relhastriggers could possibly be wrong or out of
3879  * date. If we don't actually find any rules or triggers, clear the
3880  * local copy of the flag so that we don't get into an infinite loop
3881  * here. We don't make any attempt to fix the pg_class entry, though.
3882  */
3883  if (relation->rd_rel->relhasrules && relation->rd_rules == NULL)
3884  {
3885  RelationBuildRuleLock(relation);
3886  if (relation->rd_rules == NULL)
3887  relation->rd_rel->relhasrules = false;
3888  restart = true;
3889  }
3890  if (relation->rd_rel->relhastriggers && relation->trigdesc == NULL)
3891  {
3892  RelationBuildTriggers(relation);
3893  if (relation->trigdesc == NULL)
3894  relation->rd_rel->relhastriggers = false;
3895  restart = true;
3896  }
3897 
3898  /*
3899  * Re-load the row security policies if the relation has them, since
3900  * they are not preserved in the cache. Note that we can never NOT
3901  * have a policy while relrowsecurity is true,
3902  * RelationBuildRowSecurity will create a single default-deny policy
3903  * if there is no policy defined in pg_policy.
3904  */
3905  if (relation->rd_rel->relrowsecurity && relation->rd_rsdesc == NULL)
3906  {
3907  RelationBuildRowSecurity(relation);
3908 
3909  Assert(relation->rd_rsdesc != NULL);
3910  restart = true;
3911  }
3912 
3913  /* Reload tableam data if needed */
3914  if (relation->rd_tableam == NULL &&
3915  (relation->rd_rel->relkind == RELKIND_RELATION ||
3916  relation->rd_rel->relkind == RELKIND_SEQUENCE ||
3917  relation->rd_rel->relkind == RELKIND_TOASTVALUE ||
3918  relation->rd_rel->relkind == RELKIND_MATVIEW))
3919  {
3921  Assert(relation->rd_tableam != NULL);
3922 
3923  restart = true;
3924  }
3925 
3926  /* Release hold on the relation */
3928 
3929  /* Now, restart the hashtable scan if needed */
3930  if (restart)
3931  {
3932  hash_seq_term(&status);
3933  hash_seq_init(&status, RelationIdCache);
3934  }
3935  }
3936 
3937  /*
3938  * Lastly, write out new relcache cache files if needed. We don't bother
3939  * to distinguish cases where only one of the two needs an update.
3940  */
3941  if (needNewCacheFile)
3942  {
3943  /*
3944  * Force all the catcaches to finish initializing and thereby open the
3945  * catalogs and indexes they use. This will preload the relcache with
3946  * entries for all the most important system catalogs and indexes, so
3947  * that the init files will be most useful for future backends.
3948  */
3950 
3951  /* now write the files */
3953  write_relcache_init_file(false);
3954  }
3955 }
#define AttributeRelidNumIndexId
Definition: indexing.h:96
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5319
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define IndexRelidIndexId
Definition: indexing.h:168
#define RewriteRelRulenameIndexId
Definition: indexing.h:220
void RelationBuildRowSecurity(Relation relation)
Definition: policy.c:192
void RelationInitTableAccessMethod(Relation relation)
Definition: relcache.c:1725
Relation reldesc
Definition: relcache.c:126
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool criticalSharedRelcachesBuilt
Definition: relcache.c:141
#define AuthIdOidIndexId
Definition: indexing.h:101
static HTAB * RelationIdCache
Definition: relcache.c:129
Form_pg_class rd_rel
Definition: rel.h:84
#define TriggerRelidNameIndexId
Definition: indexing.h:256
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2054
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
int32 tdtypmod
Definition: tupdesc.h:83
#define FATAL
Definition: elog.h:52
static void write_relcache_init_file(bool shared)
Definition: relcache.c:5715
TriggerDesc * trigdesc
Definition: rel.h:90
static void RelationParseRelOptions(Relation relation, HeapTuple tuple)
Definition: relcache.c:435
static void load_critical_index(Oid indexoid, Oid heapoid)
Definition: relcache.c:3964
static const FormData_pg_attribute Desc_pg_proc[Natts_pg_proc]
Definition: relcache.c:108
#define RelationGetRelationName(relation)
Definition: rel.h:462
#define DatabaseOidIndexId
Definition: indexing.h:146
#define ClassOidIndexId
Definition: indexing.h:114
struct RowSecurityDesc * rd_rsdesc
Definition: rel.h:92
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
#define AccessMethodProcedureIndexId
Definition: indexing.h:84
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2041
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
const struct TableAmRoutine * rd_tableam
Definition: rel.h:146
TupleDesc rd_att
Definition: rel.h:85
#define OpclassOidIndexId
Definition: indexing.h:197
#define InvalidOid
Definition: postgres_ext.h:36
#define CLASS_TUPLE_SIZE
Definition: pg_class.h:142
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:739
#define AuthMemMemRoleIndexId
Definition: indexing.h:106
RuleLock * rd_rules
Definition: rel.h:88
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
#define DatabaseNameIndexId
Definition: indexing.h:144
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
#define SharedSecLabelObjectIndexId
Definition: indexing.h:323
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:372
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150
Oid tdtypeid
Definition: tupdesc.h:82
void RelationBuildTriggers(Relation relation)
Definition: trigger.c:1922
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1789
static const FormData_pg_attribute Desc_pg_class[Natts_pg_class]
Definition: relcache.c:106
#define elog(elevel,...)
Definition: elog.h:228
void RelationMapInitializePhase3(void)
Definition: relmapper.c:625
static void RelationBuildRuleLock(Relation relation)
Definition: relcache.c:726
bool criticalRelcachesBuilt
Definition: relcache.c:135
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:226
#define AuthIdRolnameIndexId
Definition: indexing.h:99
void InitCatalogCachePhase2(void)
Definition: syscache.c:1075
#define RelationGetRelid(relation)
Definition: rel.h:428
static const FormData_pg_attribute Desc_pg_type[Natts_pg_type]
Definition: relcache.c:109
bytea * rd_options
Definition: rel.h:132
void hash_seq_term(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1465
static const FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute]
Definition: relcache.c:107
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInvalidate()

void RelationCacheInvalidate ( void  )

Definition at line 2781 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_isnailed, RelationData::rd_newRelfilenodeSubid, RelationClearRelation(), RelationCloseSmgr, RelationGetRelid, RelationHasReferenceCountZero, RelationInitPhysicalAddr(), RelationIsMapped, RelationMapInvalidateAll(), relcacheInvalsReceived, relidcacheent::reldesc, smgrcloseall(), and status().

Referenced by InvalidateSystemCaches(), and LocalExecuteInvalidationMessage().

2782 {
2784  RelIdCacheEnt *idhentry;
2785  Relation relation;
2786  List *rebuildFirstList = NIL;
2787  List *rebuildList = NIL;
2788  ListCell *l;
2789 
2790  /*
2791  * Reload relation mapping data before starting to reconstruct cache.
2792  */
2794 
2795  /* Phase 1 */
2796  hash_seq_init(&status, RelationIdCache);
2797 
2798  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2799  {
2800  relation = idhentry->reldesc;
2801 
2802  /* Must close all smgr references to avoid leaving dangling ptrs */
2803  RelationCloseSmgr(relation);
2804 
2805  /*
2806  * Ignore new relations; no other backend will manipulate them before
2807  * we commit. Likewise, before replacing a relation's relfilenode, we
2808  * shall have acquired AccessExclusiveLock and drained any applicable
2809  * pending invalidations.
2810  */
2811  if (relation->rd_createSubid != InvalidSubTransactionId ||
2813  continue;
2814 
2816 
2817  if (RelationHasReferenceCountZero(relation))
2818  {
2819  /* Delete this entry immediately */
2820  Assert(!relation->rd_isnailed);
2821  RelationClearRelation(relation, false);
2822  }
2823  else
2824  {
2825  /*
2826  * If it's a mapped relation, immediately update its rd_node in
2827  * case its relfilenode changed. We must do this during phase 1
2828  * in case the relation is consulted during rebuild of other
2829  * relcache entries in phase 2. It's safe since consulting the
2830  * map doesn't involve any access to relcache entries.
2831  */
2832  if (RelationIsMapped(relation))
2833  RelationInitPhysicalAddr(relation);
2834 
2835  /*
2836  * Add this entry to list of stuff to rebuild in second pass.
2837  * pg_class goes to the front of rebuildFirstList while
2838  * pg_class_oid_index goes to the back of rebuildFirstList, so
2839  * they are done first and second respectively. Other nailed
2840  * relations go to the front of rebuildList, so they'll be done
2841  * next in no particular order; and everything else goes to the
2842  * back of rebuildList.
2843  */
2844  if (RelationGetRelid(relation) == RelationRelationId)
2845  rebuildFirstList = lcons(relation, rebuildFirstList);
2846  else if (RelationGetRelid(relation) == ClassOidIndexId)
2847  rebuildFirstList = lappend(rebuildFirstList, relation);
2848  else if (relation->rd_isnailed)
2849  rebuildList = lcons(relation, rebuildList);
2850  else
2851  rebuildList = lappend(rebuildList, relation);
2852  }
2853  }
2854 
2855  /*
2856  * Now zap any remaining smgr cache entries. This must happen before we
2857  * start to rebuild entries, since that may involve catalog fetches which
2858  * will re-open catalog files.
2859  */
2860  smgrcloseall();
2861 
2862  /* Phase 2: rebuild the items found to need rebuild in phase 1 */
2863  foreach(l, rebuildFirstList)
2864  {
2865  relation = (Relation) lfirst(l);
2866  RelationClearRelation(relation, true);
2867  }
2868  list_free(rebuildFirstList);
2869  foreach(l, rebuildList)
2870  {
2871  relation = (Relation) lfirst(l);
2872  RelationClearRelation(relation, true);
2873  }
2874  list_free(rebuildList);
2875 }
#define NIL
Definition: pg_list.h:65
static long relcacheInvalsReceived
Definition: relcache.c:149
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2394
bool rd_isnailed
Definition: rel.h:61
Relation reldesc
Definition: relcache.c:126
#define RelationCloseSmgr(relation)
Definition: rel.h:497
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:81
static HTAB * RelationIdCache
Definition: relcache.c:129
void smgrcloseall(void)
Definition: smgr.c:286
struct RelationData * Relation
Definition: relcache.h:26
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1256
#define ClassOidIndexId
Definition: indexing.h:114
List * lappend(List *list, void *datum)
Definition: list.c:322
#define RelationIsMapped(relation)
Definition: rel.h:477
SubTransactionId rd_createSubid
Definition: rel.h:80
List * lcons(void *datum, List *list)
Definition: list.c:454
#define Assert(condition)
Definition: c.h:739
#define lfirst(lc)
Definition: pg_list.h:190
#define InvalidSubTransactionId
Definition: c.h:520
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:412
void list_free(List *list)
Definition: list.c:1377
void RelationMapInvalidateAll(void)
Definition: relmapper.c:425
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:226
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:428

◆ RelationCacheInvalidateEntry()

void RelationCacheInvalidateEntry ( Oid  relationId)

Definition at line 2737 of file relcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

2738 {
2739  Relation relation;
2740 
2741  RelationIdCacheLookup(relationId, relation);
2742 
2743  if (PointerIsValid(relation))
2744  {
2746  RelationFlushRelation(relation);
2747  }
2748 }
static long relcacheInvalsReceived
Definition: relcache.c:149
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:208
static void RelationFlushRelation(Relation relation)
Definition: relcache.c:2669
#define PointerIsValid(pointer)
Definition: c.h:633

◆ RelationClose()

void RelationClose ( Relation  relation)

Definition at line 2074 of file relcache.c.

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

Referenced by index_close(), relation_close(), ReorderBufferCommit(), ReorderBufferToastReplace(), and ResourceOwnerReleaseInternal().

2075 {
2076  /* Note: no locking manipulations needed */
2078 
2079  /*
2080  * If the relation is no longer open in this session, we can clean up any
2081  * stale partition descriptors it has. This is unlikely, so check to see
2082  * if there are child contexts before expending a call to mcxt.c.
2083  */
2084  if (RelationHasReferenceCountZero(relation) &&
2085  relation->rd_pdcxt != NULL &&
2086  relation->rd_pdcxt->firstchild != NULL)
2088 
2089 #ifdef RELCACHE_FORCE_RELEASE
2090  if (RelationHasReferenceCountZero(relation) &&
2091  relation->rd_createSubid == InvalidSubTransactionId &&
2093  RelationClearRelation(relation, false);
2094 #endif
2095 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2394
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:81
MemoryContext firstchild
Definition: memnodes.h:85
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2054
SubTransactionId rd_createSubid
Definition: rel.h:80
void MemoryContextDeleteChildren(MemoryContext context)
Definition: mcxt.c:256
MemoryContext rd_pdcxt
Definition: rel.h:104
#define InvalidSubTransactionId
Definition: c.h:520
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:412

◆ RelationCloseSmgrByOid()

void RelationCloseSmgrByOid ( Oid  relationId)

Definition at line 2884 of file relcache.c.

References PointerIsValid, RelationCloseSmgr, and RelationIdCacheLookup.

Referenced by swap_relation_files().

2885 {
2886  Relation relation;
2887 
2888  RelationIdCacheLookup(relationId, relation);
2889 
2890  if (!PointerIsValid(relation))
2891  return; /* not in cache, nothing to do */
2892 
2893  RelationCloseSmgr(relation);
2894 }
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:208
#define RelationCloseSmgr(relation)
Definition: rel.h:497
#define PointerIsValid(pointer)
Definition: c.h:633

◆ RelationForgetRelation()

void RelationForgetRelation ( Oid  rid)

Definition at line 2705 of file relcache.c.

References elog, ERROR, PointerIsValid, RelationClearRelation(), RelationHasReferenceCountZero, and RelationIdCacheLookup.

Referenced by heap_drop_with_catalog(), and index_drop().

2706 {
2707  Relation relation;
2708 
2709  RelationIdCacheLookup(rid, relation);
2710 
2711  if (!PointerIsValid(relation))
2712  return; /* not in cache, nothing to do */
2713 
2714  if (!RelationHasReferenceCountZero(relation))
2715  elog(ERROR, "relation %u is still open", rid);
2716 
2717  /* Unconditionally destroy the relcache entry */
2718  RelationClearRelation(relation, false);
2719 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2394
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:208
#define ERROR
Definition: elog.h:43
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:412
#define elog(elevel,...)
Definition: elog.h:228
#define PointerIsValid(pointer)
Definition: c.h:633

◆ RelationGetDummyIndexExpressions()

List* RelationGetDummyIndexExpressions ( Relation  relation)

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

4624 {
4625  List *result;
4626  Datum exprsDatum;
4627  bool isnull;
4628  char *exprsString;
4629  List *rawExprs;
4630  ListCell *lc;
4631 
4632  /* Quick exit if there is nothing to do. */
4633  if (relation->rd_indextuple == NULL ||
4634  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indexprs, NULL))
4635  return NIL;
4636 
4637  /* Extract raw node tree(s) from index tuple. */
4638  exprsDatum = heap_getattr(relation->rd_indextuple,
4639  Anum_pg_index_indexprs,
4641  &isnull);
4642  Assert(!isnull);
4643  exprsString = TextDatumGetCString(exprsDatum);
4644  rawExprs = (List *) stringToNode(exprsString);
4645  pfree(exprsString);
4646 
4647  /* Construct null Consts; the typlen and typbyval are arbitrary. */
4648  result = NIL;
4649  foreach(lc, rawExprs)
4650  {
4651  Node *rawExpr = (Node *) lfirst(lc);
4652 
4653  result = lappend(result,
4654  makeConst(exprType(rawExpr),
4655  exprTypmod(rawExpr),
4656  exprCollation(rawExpr),
4657  1,
4658  (Datum) 0,
4659  true,
4660  true));
4661  }
4662 
4663  return result;
4664 }
#define NIL
Definition: pg_list.h:65
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:275
Definition: nodes.h:525
void * stringToNode(const char *str)
Definition: read.c:89
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:297
struct HeapTupleData * rd_indextuple
Definition: rel.h:151
void pfree(void *pointer)
Definition: mcxt.c:1056
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4041
List * lappend(List *list, void *datum)
Definition: list.c:322
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:84
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:739
#define lfirst(lc)
Definition: pg_list.h:190
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:719
Definition: pg_list.h:50

◆ RelationGetExclusionInfo()

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

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

5002 {
5003  int indnkeyatts;
5004  Oid *ops;
5005  Oid *funcs;
5006  uint16 *strats;
5007  Relation conrel;
5008  SysScanDesc conscan;
5009  ScanKeyData skey[1];
5010  HeapTuple htup;
5011  bool found;
5012  MemoryContext oldcxt;
5013  int i;
5014 
5015  indnkeyatts = IndexRelationGetNumberOfKeyAttributes(indexRelation);
5016 
5017  /* Allocate result space in caller context */
5018  *operators = ops = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5019  *procs = funcs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5020  *strategies = strats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
5021 
5022  /* Quick exit if we have the data cached already */
5023  if (indexRelation->rd_exclstrats != NULL)
5024  {
5025  memcpy(ops, indexRelation->rd_exclops, sizeof(Oid) * indnkeyatts);
5026  memcpy(funcs, indexRelation->rd_exclprocs, sizeof(Oid) * indnkeyatts);
5027  memcpy(strats, indexRelation->rd_exclstrats, sizeof(uint16) * indnkeyatts);
5028  return;
5029  }
5030 
5031  /*
5032  * Search pg_constraint for the constraint associated with the index. To
5033  * make this not too painfully slow, we use the index on conrelid; that
5034  * will hold the parent relation's OID not the index's own OID.
5035  *
5036  * Note: if we wanted to rely on the constraint name matching the index's
5037  * name, we could just do a direct lookup using pg_constraint's unique
5038  * index. For the moment it doesn't seem worth requiring that.
5039  */
5040  ScanKeyInit(&skey[0],
5041  Anum_pg_constraint_conrelid,
5042  BTEqualStrategyNumber, F_OIDEQ,
5043  ObjectIdGetDatum(indexRelation->rd_index->indrelid));
5044 
5045  conrel = table_open(ConstraintRelationId, AccessShareLock);
5046  conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
5047  NULL, 1, skey);
5048  found = false;
5049 
5050  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
5051  {
5053  Datum val;
5054  bool isnull;
5055  ArrayType *arr;
5056  int nelem;
5057 
5058  /* We want the exclusion constraint owning the index */
5059  if (conform->contype != CONSTRAINT_EXCLUSION ||
5060  conform->conindid != RelationGetRelid(indexRelation))
5061  continue;
5062 
5063  /* There should be only one */
5064  if (found)
5065  elog(ERROR, "unexpected exclusion constraint record found for rel %s",
5066  RelationGetRelationName(indexRelation));
5067  found = true;
5068 
5069  /* Extract the operator OIDS from conexclop */
5070  val = fastgetattr(htup,
5071  Anum_pg_constraint_conexclop,
5072  conrel->rd_att, &isnull);
5073  if (isnull)
5074  elog(ERROR, "null conexclop for rel %s",
5075  RelationGetRelationName(indexRelation));
5076 
5077  arr = DatumGetArrayTypeP(val); /* ensure not toasted */
5078  nelem = ARR_DIMS(arr)[0];
5079  if (ARR_NDIM(arr) != 1 ||
5080  nelem != indnkeyatts ||
5081  ARR_HASNULL(arr) ||
5082  ARR_ELEMTYPE(arr) != OIDOID)
5083  elog(ERROR, "conexclop is not a 1-D Oid array");
5084 
5085  memcpy(ops, ARR_DATA_PTR(arr), sizeof(Oid) * indnkeyatts);
5086  }
5087 
5088  systable_endscan(conscan);
5089  table_close(conrel, AccessShareLock);
5090 
5091  if (!found)
5092  elog(ERROR, "exclusion constraint record missing for rel %s",
5093  RelationGetRelationName(indexRelation));
5094 
5095  /* We need the func OIDs and strategy numbers too */
5096  for (i = 0; i < indnkeyatts; i++)
5097  {
5098  funcs[i] = get_opcode(ops[i]);
5099  strats[i] = get_op_opfamily_strategy(ops[i],
5100  indexRelation->rd_opfamily[i]);
5101  /* shouldn't fail, since it was checked at index creation */
5102  if (strats[i] == InvalidStrategy)
5103  elog(ERROR, "could not find strategy for operator %u in family %u",
5104  ops[i], indexRelation->rd_opfamily[i]);
5105  }
5106 
5107  /* Save a copy of the results in the relcache entry. */
5108  oldcxt = MemoryContextSwitchTo(indexRelation->rd_indexcxt);
5109  indexRelation->rd_exclops = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5110  indexRelation->rd_exclprocs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5111  indexRelation->rd_exclstrats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
5112  memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * indnkeyatts);
5113  memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * indnkeyatts);
5114  memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * indnkeyatts);
5115  MemoryContextSwitchTo(oldcxt);
5116 }
#define InvalidStrategy
Definition: stratnum.h:24
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#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:173
#define AccessShareLock
Definition: lockdefs.h:36
Oid * rd_exclprocs
Definition: rel.h:172
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:352
Form_pg_index rd_index
Definition: rel.h:149
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
unsigned short uint16
Definition: c.h:358
#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:462
#define ARR_HASNULL(a)
Definition: array.h:279
Oid * rd_opfamily
Definition: rel.h:164
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition: rel.h:447
Oid * rd_exclops
Definition: rel.h:171
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:85
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1092
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define ARR_NDIM(a)
Definition: array.h:278
#define ConstraintRelidTypidNameIndexId
Definition: indexing.h:128
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition: lsyscache.c:80
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:228
MemoryContext rd_indexcxt
Definition: rel.h:161
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:428
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 4221 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().

4222 {
4223  List *result;
4224  Relation conrel;
4225  SysScanDesc conscan;
4226  ScanKeyData skey;
4227  HeapTuple htup;
4228  List *oldlist;
4229  MemoryContext oldcxt;
4230 
4231  /* Quick exit if we already computed the list. */
4232  if (relation->rd_fkeyvalid)
4233  return relation->rd_fkeylist;
4234 
4235  /* Fast path: non-partitioned tables without triggers can't have FKs */
4236  if (!relation->rd_rel->relhastriggers &&
4237  relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
4238  return NIL;
4239 
4240  /*
4241  * We build the list we intend to return (in the caller's context) while
4242  * doing the scan. After successfully completing the scan, we copy that
4243  * list into the relcache entry. This avoids cache-context memory leakage
4244  * if we get some sort of error partway through.
4245  */
4246  result = NIL;
4247 
4248  /* Prepare to scan pg_constraint for entries having conrelid = this rel. */
4249  ScanKeyInit(&skey,
4250  Anum_pg_constraint_conrelid,
4251  BTEqualStrategyNumber, F_OIDEQ,
4252  ObjectIdGetDatum(RelationGetRelid(relation)));
4253 
4254  conrel = table_open(ConstraintRelationId, AccessShareLock);
4255  conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
4256  NULL, 1, &skey);
4257 
4258  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4259  {
4260  Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(htup);
4261  ForeignKeyCacheInfo *info;
4262 
4263  /* consider only foreign keys */
4264  if (constraint->contype != CONSTRAINT_FOREIGN)
4265  continue;
4266 
4267  info = makeNode(ForeignKeyCacheInfo);
4268  info->conoid = constraint->oid;
4269  info->conrelid = constraint->conrelid;
4270  info->confrelid = constraint->confrelid;
4271 
4272  DeconstructFkConstraintRow(htup, &info->nkeys,
4273  info->conkey,
4274  info->confkey,
4275  info->conpfeqop,
4276  NULL, NULL);
4277 
4278  /* Add FK's node to the result list */
4279  result = lappend(result, info);
4280  }
4281 
4282  systable_endscan(conscan);
4283  table_close(conrel, AccessShareLock);
4284 
4285  /* Now save a copy of the completed list in the relcache entry. */
4287  oldlist = relation->rd_fkeylist;
4288  relation->rd_fkeylist = copyObject(result);
4289  relation->rd_fkeyvalid = true;
4290  MemoryContextSwitchTo(oldcxt);
4291 
4292  /* Don't leak the old list, if there is one */
4293  list_free_deep(oldlist);
4294 
4295  return result;
4296 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#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:236
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
List * rd_fkeylist
Definition: rel.h:95
Form_pg_class rd_rel
Definition: rel.h:84
void list_free_deep(List *list)
Definition: list.c:1391
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
List * lappend(List *list, void *datum)
Definition: list.c:322
#define makeNode(_type_)
Definition: nodes.h:573
Oid conpfeqop[INDEX_MAX_KEYS]
Definition: rel.h:238
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define ConstraintRelidTypidNameIndexId
Definition: indexing.h:128
AttrNumber confkey[INDEX_MAX_KEYS]
Definition: rel.h:237
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define copyObject(obj)
Definition: nodes.h:641
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
bool rd_fkeyvalid
Definition: rel.h:96
#define RelationGetRelid(relation)
Definition: rel.h:428
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationGetIndexAttrBitmap()

Bitmapset* RelationGetIndexAttrBitmap ( Relation  relation,
IndexAttrBitmapKind  attrKind 
)

Definition at line 4760 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(), relhasindex, stringToNode(), and TextDatumGetCString.

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

4761 {
4762  Bitmapset *indexattrs; /* indexed columns */
4763  Bitmapset *uindexattrs; /* columns in unique indexes */
4764  Bitmapset *pkindexattrs; /* columns in the primary index */
4765  Bitmapset *idindexattrs; /* columns in the replica identity */
4766  List *indexoidlist;
4767  List *newindexoidlist;
4768  Oid relpkindex;
4769  Oid relreplindex;
4770  ListCell *l;
4771  MemoryContext oldcxt;
4772 
4773  /* Quick exit if we already computed the result. */
4774  if (relation->rd_indexattr != NULL)
4775  {
4776  switch (attrKind)
4777  {
4778  case INDEX_ATTR_BITMAP_ALL:
4779  return bms_copy(relation->rd_indexattr);
4780  case INDEX_ATTR_BITMAP_KEY:
4781  return bms_copy(relation->rd_keyattr);
4783  return bms_copy(relation->rd_pkattr);
4785  return bms_copy(relation->rd_idattr);
4786  default:
4787  elog(ERROR, "unknown attrKind %u", attrKind);
4788  }
4789  }
4790 
4791  /* Fast path if definitely no indexes */
4792  if (!RelationGetForm(relation)->relhasindex)
4793  return NULL;
4794 
4795  /*
4796  * Get cached list of index OIDs. If we have to start over, we do so here.
4797  */
4798 restart:
4799  indexoidlist = RelationGetIndexList(relation);
4800 
4801  /* Fall out if no indexes (but relhasindex was set) */
4802  if (indexoidlist == NIL)
4803  return NULL;
4804 
4805  /*
4806  * Copy the rd_pkindex and rd_replidindex values computed by
4807  * RelationGetIndexList before proceeding. This is needed because a
4808  * relcache flush could occur inside index_open below, resetting the
4809  * fields managed by RelationGetIndexList. We need to do the work with
4810  * stable values of these fields.
4811  */
4812  relpkindex = relation->rd_pkindex;
4813  relreplindex = relation->rd_replidindex;
4814 
4815  /*
4816  * For each index, add referenced attributes to indexattrs.
4817  *
4818  * Note: we consider all indexes returned by RelationGetIndexList, even if
4819  * they are not indisready or indisvalid. This is important because an
4820  * index for which CREATE INDEX CONCURRENTLY has just started must be
4821  * included in HOT-safety decisions (see README.HOT). If a DROP INDEX
4822  * CONCURRENTLY is far enough along that we should ignore the index, it
4823  * won't be returned at all by RelationGetIndexList.
4824  */
4825  indexattrs = NULL;
4826  uindexattrs = NULL;
4827  pkindexattrs = NULL;
4828  idindexattrs = NULL;
4829  foreach(l, indexoidlist)
4830  {
4831  Oid indexOid = lfirst_oid(l);
4832  Relation indexDesc;
4833  Datum datum;
4834  bool isnull;
4835  Node *indexExpressions;
4836  Node *indexPredicate;
4837  int i;
4838  bool isKey; /* candidate key */
4839  bool isPK; /* primary key */
4840  bool isIDKey; /* replica identity index */
4841 
4842  indexDesc = index_open(indexOid, AccessShareLock);
4843 
4844  /*
4845  * Extract index expressions and index predicate. Note: Don't use
4846  * RelationGetIndexExpressions()/RelationGetIndexPredicate(), because
4847  * those might run constant expressions evaluation, which needs a
4848  * snapshot, which we might not have here. (Also, it's probably more
4849  * sound to collect the bitmaps before any transformations that might
4850  * eliminate columns, but the practical impact of this is limited.)
4851  */
4852 
4853  datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indexprs,
4854  GetPgIndexDescriptor(), &isnull);
4855  if (!isnull)
4856  indexExpressions = stringToNode(TextDatumGetCString(datum));
4857  else
4858  indexExpressions = NULL;
4859 
4860  datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indpred,
4861  GetPgIndexDescriptor(), &isnull);
4862  if (!isnull)
4863  indexPredicate = stringToNode(TextDatumGetCString(datum));
4864  else
4865  indexPredicate = NULL;
4866 
4867  /* Can this index be referenced by a foreign key? */
4868  isKey = indexDesc->rd_index->indisunique &&
4869  indexExpressions == NULL &&
4870  indexPredicate == NULL;
4871 
4872  /* Is this a primary key? */
4873  isPK = (indexOid == relpkindex);
4874 
4875  /* Is this index the configured (or default) replica identity? */
4876  isIDKey = (indexOid == relreplindex);
4877 
4878  /* Collect simple attribute references */
4879  for (i = 0; i < indexDesc->rd_index->indnatts; i++)
4880  {
4881  int attrnum = indexDesc->rd_index->indkey.values[i];
4882 
4883  /*
4884  * Since we have covering indexes with non-key columns, we must
4885  * handle them accurately here. non-key columns must be added into
4886  * indexattrs, since they are in index, and HOT-update shouldn't
4887  * miss them. Obviously, non-key columns couldn't be referenced by
4888  * foreign key or identity key. Hence we do not include them into
4889  * uindexattrs, pkindexattrs and idindexattrs bitmaps.
4890  */
4891  if (attrnum != 0)
4892  {
4893  indexattrs = bms_add_member(indexattrs,
4895 
4896  if (isKey && i < indexDesc->rd_index->indnkeyatts)
4897  uindexattrs = bms_add_member(uindexattrs,
4899 
4900  if (isPK && i < indexDesc->rd_index->indnkeyatts)
4901  pkindexattrs = bms_add_member(pkindexattrs,
4903 
4904  if (isIDKey && i < indexDesc->rd_index->indnkeyatts)
4905  idindexattrs = bms_add_member(idindexattrs,
4907  }
4908  }
4909 
4910  /* Collect all attributes used in expressions, too */
4911  pull_varattnos(indexExpressions, 1, &indexattrs);
4912 
4913  /* Collect all attributes in the index predicate, too */
4914  pull_varattnos(indexPredicate, 1, &indexattrs);
4915 
4916  index_close(indexDesc, AccessShareLock);
4917  }
4918 
4919  /*
4920  * During one of the index_opens in the above loop, we might have received
4921  * a relcache flush event on this relcache entry, which might have been
4922  * signaling a change in the rel's index list. If so, we'd better start
4923  * over to ensure we deliver up-to-date attribute bitmaps.
4924  */
4925  newindexoidlist = RelationGetIndexList(relation);
4926  if (equal(indexoidlist, newindexoidlist) &&
4927  relpkindex == relation->rd_pkindex &&
4928  relreplindex == relation->rd_replidindex)
4929  {
4930  /* Still the same index set, so proceed */
4931  list_free(newindexoidlist);
4932  list_free(indexoidlist);
4933  }
4934  else
4935  {
4936  /* Gotta do it over ... might as well not leak memory */
4937  list_free(newindexoidlist);
4938  list_free(indexoidlist);
4939  bms_free(uindexattrs);
4940  bms_free(pkindexattrs);
4941  bms_free(idindexattrs);
4942  bms_free(indexattrs);
4943 
4944  goto restart;
4945  }
4946 
4947  /* Don't leak the old values of these bitmaps, if any */
4948  bms_free(relation->rd_indexattr);
4949  relation->rd_indexattr = NULL;
4950  bms_free(relation->rd_keyattr);
4951  relation->rd_keyattr = NULL;
4952  bms_free(relation->rd_pkattr);
4953  relation->rd_pkattr = NULL;
4954  bms_free(relation->rd_idattr);
4955  relation->rd_idattr = NULL;
4956 
4957  /*
4958  * Now save copies of the bitmaps in the relcache entry. We intentionally
4959  * set rd_indexattr last, because that's the one that signals validity of
4960  * the values; if we run out of memory before making that copy, we won't
4961  * leave the relcache entry looking like the other ones are valid but
4962  * empty.
4963  */
4965  relation->rd_keyattr = bms_copy(uindexattrs);
4966  relation->rd_pkattr = bms_copy(pkindexattrs);
4967  relation->rd_idattr = bms_copy(idindexattrs);
4968  relation->rd_indexattr = bms_copy(indexattrs);
4969  MemoryContextSwitchTo(oldcxt);
4970 
4971  /* We return our original working copy for caller to play with */
4972  switch (attrKind)
4973  {
4974  case INDEX_ATTR_BITMAP_ALL:
4975  return indexattrs;
4976  case INDEX_ATTR_BITMAP_KEY:
4977  return uindexattrs;
4979  return pkindexattrs;
4981  return idindexattrs;
4982  default:
4983  elog(ERROR, "unknown attrKind %u", attrKind);
4984  return NULL;
4985  }
4986 }
#define NIL
Definition: pg_list.h:65
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:74
Bitmapset * rd_keyattr
Definition: rel.h:121
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3018
Oid rd_replidindex
Definition: rel.h:114
#define RelationGetForm(relation)
Definition: rel.h:422
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:525
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:151
Form_pg_index rd_index
Definition: rel.h:149
#define ERROR
Definition: elog.h:43
Oid rd_pkindex
Definition: rel.h:113
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4041
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:84
uintptr_t Datum
Definition: postgres.h:367
Bitmapset * rd_idattr
Definition: rel.h:123
void bms_free(Bitmapset *a)
Definition: bitmapset.c:208
bool relhasindex
Definition: pg_class.h:72
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4330
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:152
Bitmapset * rd_pkattr
Definition: rel.h:122
void list_free(List *list)
Definition: list.c:1377
#define elog(elevel,...)
Definition: elog.h:228
int i
Definition: pg_list.h:50
Bitmapset * rd_indexattr
Definition: rel.h:120
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:126
#define lfirst_oid(lc)
Definition: pg_list.h:192
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationGetIndexExpressions()

List* RelationGetIndexExpressions ( Relation  relation)

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

4565 {
4566  List *result;
4567  Datum exprsDatum;
4568  bool isnull;
4569  char *exprsString;
4570  MemoryContext oldcxt;
4571 
4572  /* Quick exit if we already computed the result. */
4573  if (relation->rd_indexprs)
4574  return copyObject(relation->rd_indexprs);
4575 
4576  /* Quick exit if there is nothing to do. */
4577  if (relation->rd_indextuple == NULL ||
4578  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indexprs, NULL))
4579  return NIL;
4580 
4581  /*
4582  * We build the tree we intend to return in the caller's context. After
4583  * successfully completing the work, we copy it into the relcache entry.
4584  * This avoids problems if we get some sort of error partway through.
4585  */
4586  exprsDatum = heap_getattr(relation->rd_indextuple,
4587  Anum_pg_index_indexprs,
4589  &isnull);
4590  Assert(!isnull);
4591  exprsString = TextDatumGetCString(exprsDatum);
4592  result = (List *) stringToNode(exprsString);
4593  pfree(exprsString);
4594 
4595  /*
4596  * Run the expressions through eval_const_expressions. This is not just an
4597  * optimization, but is necessary, because the planner will be comparing
4598  * them to similarly-processed qual clauses, and may fail to detect valid
4599  * matches without this. We must not use canonicalize_qual, however,
4600  * since these aren't qual expressions.
4601  */
4602  result = (List *) eval_const_expressions(NULL, (Node *) result);
4603 
4604  /* May as well fix opfuncids too */
4605  fix_opfuncids((Node *) result);
4606 
4607  /* Now save a copy of the completed tree in the relcache entry. */
4608  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4609  relation->rd_indexprs = copyObject(result);
4610  MemoryContextSwitchTo(oldcxt);
4611 
4612  return result;
4613 }
#define NIL
Definition: pg_list.h:65
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1587
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
List * rd_indexprs
Definition: rel.h:169
Definition: nodes.h:525
void * stringToNode(const char *str)
Definition: read.c:89
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2252
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
struct HeapTupleData * rd_indextuple
Definition: rel.h:151
void pfree(void *pointer)
Definition: mcxt.c:1056
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4041
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:84
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:739
MemoryContext rd_indexcxt
Definition: rel.h:161
#define copyObject(obj)
Definition: nodes.h:641
Definition: pg_list.h:50

◆ RelationGetIndexList()

List* RelationGetIndexList ( Relation  relation)

Definition at line 4330 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(), ATExecSetTableSpace(), AttachPartitionEnsureIndexes(), calculate_indexes_size(), calculate_toast_table_size(), cluster(), DefineIndex(), DefineRelation(), ExecInitPartitionInfo(), ExecOpenIndices(), ExecRefreshMatView(), get_relation_info(), GetParentedForeignKeyRefs(), index_get_partition(), infer_arbiter_indexes(), mark_index_clustered(), refresh_by_match_merge(), reindex_relation(), ReindexRelationConcurrently(), relation_mark_replica_identity(), RelationGetIndexAttrBitmap(), RelationGetPrimaryKeyIndex(), RelationGetReplicaIndex(), relationHasPrimaryKey(), RelationTruncateIndexes(), toast_open_indexes(), transformFkeyCheckAttrs(), transformFkeyGetPrimaryKey(), transformTableLikeClause(), triggered_change_notification(), and vac_open_indexes().

4331 {
4332  Relation indrel;
4333  SysScanDesc indscan;
4334  ScanKeyData skey;
4335  HeapTuple htup;
4336  List *result;
4337  List *oldlist;
4338  char replident = relation->rd_rel->relreplident;
4339  Oid pkeyIndex = InvalidOid;
4340  Oid candidateIndex = InvalidOid;
4341  MemoryContext oldcxt;
4342 
4343  /* Quick exit if we already computed the list. */
4344  if (relation->rd_indexvalid)
4345  return list_copy(relation->rd_indexlist);
4346 
4347  /*
4348  * We build the list we intend to return (in the caller's context) while
4349  * doing the scan. After successfully completing the scan, we copy that
4350  * list into the relcache entry. This avoids cache-context memory leakage
4351  * if we get some sort of error partway through.
4352  */
4353  result = NIL;
4354 
4355  /* Prepare to scan pg_index for entries having indrelid = this rel. */
4356  ScanKeyInit(&skey,
4357  Anum_pg_index_indrelid,
4358  BTEqualStrategyNumber, F_OIDEQ,
4359  ObjectIdGetDatum(RelationGetRelid(relation)));
4360 
4361  indrel = table_open(IndexRelationId, AccessShareLock);
4362  indscan = systable_beginscan(indrel, IndexIndrelidIndexId, true,
4363  NULL, 1, &skey);
4364 
4365  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4366  {
4368 
4369  /*
4370  * Ignore any indexes that are currently being dropped. This will
4371  * prevent them from being searched, inserted into, or considered in
4372  * HOT-safety decisions. It's unsafe to touch such an index at all
4373  * since its catalog entries could disappear at any instant.
4374  */
4375  if (!index->indislive)
4376  continue;
4377 
4378  /* add index's OID to result list */
4379  result = lappend_oid(result, index->indexrelid);
4380 
4381  /*
4382  * Invalid, non-unique, non-immediate or predicate indexes aren't
4383  * interesting for either oid indexes or replication identity indexes,
4384  * so don't check them.
4385  */
4386  if (!index->indisvalid || !index->indisunique ||
4387  !index->indimmediate ||
4388  !heap_attisnull(htup, Anum_pg_index_indpred, NULL))
4389  continue;
4390 
4391  /* remember primary key index if any */
4392  if (index->indisprimary)
4393  pkeyIndex = index->indexrelid;
4394 
4395  /* remember explicitly chosen replica index */
4396  if (index->indisreplident)
4397  candidateIndex = index->indexrelid;
4398  }
4399 
4400  systable_endscan(indscan);
4401 
4402  table_close(indrel, AccessShareLock);
4403 
4404  /* Sort the result list into OID order, per API spec. */
4405  list_sort(result, list_oid_cmp);
4406 
4407  /* Now save a copy of the completed list in the relcache entry. */
4409  oldlist = relation->rd_indexlist;
4410  relation->rd_indexlist = list_copy(result);
4411  relation->rd_pkindex = pkeyIndex;
4412  if (replident == REPLICA_IDENTITY_DEFAULT && OidIsValid(pkeyIndex))
4413  relation->rd_replidindex = pkeyIndex;
4414  else if (replident == REPLICA_IDENTITY_INDEX && OidIsValid(candidateIndex))
4415  relation->rd_replidindex = candidateIndex;
4416  else
4417  relation->rd_replidindex = InvalidOid;
4418  relation->rd_indexvalid = true;
4419  MemoryContextSwitchTo(oldcxt);
4420 
4421  /* Don't leak the old list, if there is one */
4422  list_free(oldlist);
4423 
4424  return result;
4425 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid rd_replidindex
Definition: rel.h:114
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
List * list_copy(const List *oldlist)
Definition: list.c:1404
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
Form_pg_class rd_rel
Definition: rel.h:84
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:358
#define OidIsValid(objectId)
Definition: c.h:645
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
Definition: type.h:89
int list_oid_cmp(const ListCell *p1, const ListCell *p2)
Definition: list.c:1499
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
Oid rd_pkindex
Definition: rel.h:113
List * rd_indexlist
Definition: rel.h:112
FormData_pg_index * Form_pg_index
Definition: pg_index.h:66
bool rd_indexvalid
Definition: rel.h:63
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void list_sort(List *list, list_sort_comparator cmp)
Definition: list.c:1482
void list_free(List *list)
Definition: list.c:1377
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:428
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define IndexIndrelidIndexId
Definition: indexing.h:166
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationGetIndexPredicate()

List* RelationGetIndexPredicate ( Relation  relation)

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

4678 {
4679  List *result;
4680  Datum predDatum;
4681  bool isnull;
4682  char *predString;
4683  MemoryContext oldcxt;
4684 
4685  /* Quick exit if we already computed the result. */
4686  if (relation->rd_indpred)
4687  return copyObject(relation->rd_indpred);
4688 
4689  /* Quick exit if there is nothing to do. */
4690  if (relation->rd_indextuple == NULL ||
4691  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indpred, NULL))
4692  return NIL;
4693 
4694  /*
4695  * We build the tree we intend to return in the caller's context. After
4696  * successfully completing the work, we copy it into the relcache entry.
4697  * This avoids problems if we get some sort of error partway through.
4698  */
4699  predDatum = heap_getattr(relation->rd_indextuple,
4700  Anum_pg_index_indpred,
4702  &isnull);
4703  Assert(!isnull);
4704  predString = TextDatumGetCString(predDatum);
4705  result = (List *) stringToNode(predString);
4706  pfree(predString);
4707 
4708  /*
4709  * Run the expression through const-simplification and canonicalization.
4710  * This is not just an optimization, but is necessary, because the planner
4711  * will be comparing it to similarly-processed qual clauses, and may fail
4712  * to detect valid matches without this. This must match the processing
4713  * done to qual clauses in preprocess_expression()! (We can skip the
4714  * stuff involving subqueries, however, since we don't allow any in index
4715  * predicates.)
4716  */
4717  result = (List *) eval_const_expressions(NULL, (Node *) result);
4718 
4719  result = (List *) canonicalize_qual((Expr *) result, false);
4720 
4721  /* Also convert to implicit-AND format */
4722  result = make_ands_implicit((Expr *) result);
4723 
4724  /* May as well fix opfuncids too */
4725  fix_opfuncids((Node *) result);
4726 
4727  /* Now save a copy of the completed tree in the relcache entry. */
4728  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4729  relation->rd_indpred = copyObject(result);
4730  MemoryContextSwitchTo(oldcxt);
4731 
4732  return result;
4733 }
#define NIL
Definition: pg_list.h:65
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1587
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:525
void * stringToNode(const char *str)
Definition: read.c:89
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2252
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
struct HeapTupleData * rd_indextuple
Definition: rel.h:151
void pfree(void *pointer)
Definition: mcxt.c:1056
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4041
Expr * canonicalize_qual(Expr *qual, bool is_check)
Definition: prepqual.c:292
List * rd_indpred
Definition: rel.h:170
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:84
uintptr_t Datum
Definition: postgres.h:367
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:716
#define Assert(condition)
Definition: c.h:739
MemoryContext rd_indexcxt
Definition: rel.h:161
#define copyObject(obj)
Definition: nodes.h:641
Definition: pg_list.h:50

◆ RelationGetPrimaryKeyIndex()

Oid RelationGetPrimaryKeyIndex ( Relation  relation)

Definition at line 4518 of file relcache.c.

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

Referenced by GetRelationIdentityOrPK().

4519 {
4520  List *ilist;
4521 
4522  if (!relation->rd_indexvalid)
4523  {
4524  /* RelationGetIndexList does the heavy lifting. */
4525  ilist = RelationGetIndexList(relation);
4526  list_free(ilist);
4527  Assert(relation->rd_indexvalid);
4528  }
4529 
4530  return relation->rd_pkindex;
4531 }
Oid rd_pkindex
Definition: rel.h:113
bool rd_indexvalid
Definition: rel.h:63
#define Assert(condition)
Definition: c.h:739
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4330
void list_free(List *list)
Definition: list.c:1377
Definition: pg_list.h:50

◆ RelationGetReplicaIndex()

Oid RelationGetReplicaIndex ( Relation  relation)

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

4540 {
4541  List *ilist;
4542 
4543  if (!relation->rd_indexvalid)
4544  {
4545  /* RelationGetIndexList does the heavy lifting. */
4546  ilist = RelationGetIndexList(relation);
4547  list_free(ilist);
4548  Assert(relation->rd_indexvalid);
4549  }
4550 
4551  return relation->rd_replidindex;
4552 }
Oid rd_replidindex
Definition: rel.h:114
bool rd_indexvalid
Definition: rel.h:63
#define Assert(condition)
Definition: c.h:739
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4330
void list_free(List *list)
Definition: list.c:1377
Definition: pg_list.h:50

◆ RelationGetStatExtList()

List* RelationGetStatExtList ( Relation  relation)

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

4450 {
4451  Relation indrel;
4452  SysScanDesc indscan;
4453  ScanKeyData skey;
4454  HeapTuple htup;
4455  List *result;
4456  List *oldlist;
4457  MemoryContext oldcxt;
4458 
4459  /* Quick exit if we already computed the list. */
4460  if (relation->rd_statvalid != 0)
4461  return list_copy(relation->rd_statlist);
4462 
4463  /*
4464  * We build the list we intend to return (in the caller's context) while
4465  * doing the scan. After successfully completing the scan, we copy that
4466  * list into the relcache entry. This avoids cache-context memory leakage
4467  * if we get some sort of error partway through.
4468  */
4469  result = NIL;
4470 
4471  /*
4472  * Prepare to scan pg_statistic_ext for entries having stxrelid = this
4473  * rel.
4474  */
4475  ScanKeyInit(&skey,
4476  Anum_pg_statistic_ext_stxrelid,
4477  BTEqualStrategyNumber, F_OIDEQ,
4478  ObjectIdGetDatum(RelationGetRelid(relation)));
4479 
4480  indrel = table_open(StatisticExtRelationId, AccessShareLock);
4481  indscan = systable_beginscan(indrel, StatisticExtRelidIndexId, true,
4482  NULL, 1, &skey);
4483 
4484  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4485  {
4486  Oid oid = ((Form_pg_statistic_ext) GETSTRUCT(htup))->oid;
4487 
4488  result = lappend_oid(result, oid);
4489  }
4490 
4491  systable_endscan(indscan);
4492 
4493  table_close(indrel, AccessShareLock);
4494 
4495  /* Sort the result list into OID order, per API spec. */
4496  list_sort(result, list_oid_cmp);
4497 
4498  /* Now save a copy of the completed list in the relcache entry. */
4500  oldlist = relation->rd_statlist;
4501  relation->rd_statlist = list_copy(result);
4502 
4503  relation->rd_statvalid = true;
4504  MemoryContextSwitchTo(oldcxt);
4505 
4506  /* Don't leak the old list, if there is one */
4507  list_free(oldlist);
4508 
4509  return result;
4510 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#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:1404
unsigned int Oid
Definition: postgres_ext.h:31
#define StatisticExtRelidIndexId
Definition: indexing.h:238
List * lappend_oid(List *list, Oid datum)
Definition: list.c:358
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
int list_oid_cmp(const ListCell *p1, const ListCell *p2)
Definition: list.c:1499
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#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:1482
void list_free(List *list)
Definition: list.c:1377
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:117
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:428
#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 1975 of file relcache.c.

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

Referenced by relation_open(), ReorderBufferCommit(), ReorderBufferToastReplace(), and try_relation_open().

1976 {
1977  Relation rd;
1978 
1979  /* Make sure we're in an xact, even if this ends up being a cache hit */
1981 
1982  /*
1983  * first try to find reldesc in the cache
1984  */
1985  RelationIdCacheLookup(relationId, rd);
1986 
1987  if (RelationIsValid(rd))
1988  {
1990  /* revalidate cache entry if necessary */
1991  if (!rd->rd_isvalid)
1992  {
1993  /*
1994  * Indexes only have a limited number of possible schema changes,
1995  * and we don't want to use the full-blown procedure because it's
1996  * a headache for indexes that reload itself depends on.
1997  */
1998  if (rd->rd_rel->relkind == RELKIND_INDEX ||
1999  rd->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
2001  else
2002  RelationClearRelation(rd, true);
2003 
2004  /*
2005  * Normally entries need to be valid here, but before the relcache
2006  * has been initialized, not enough infrastructure exists to
2007  * perform pg_class lookups. The structure of such entries doesn't
2008  * change, but we still want to update the rd_rel entry. So
2009  * rd_isvalid = false is left in place for a later lookup.
2010  */
2011  Assert(rd->rd_isvalid ||
2013  }
2014  return rd;
2015  }
2016 
2017  /*
2018  * no reldesc in the cache, so have RelationBuildDesc() build one and add
2019  * it.
2020  */
2021  rd = RelationBuildDesc(relationId, true);
2022  if (RelationIsValid(rd))
2024  return rd;
2025 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2394
bool rd_isnailed
Definition: rel.h:61
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:208
bool rd_isvalid
Definition: rel.h:62
Form_pg_class rd_rel
Definition: rel.h:84
#define RelationIsValid(relation)
Definition: rel.h:401
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2041
static void RelationReloadIndexInfo(Relation relation)
Definition: relcache.c:2125
#define Assert(condition)
Definition: c.h:739
static Relation RelationBuildDesc(Oid targetRelId, bool insertIt)
Definition: relcache.c:1019
bool IsTransactionState(void)
Definition: xact.c:355
bool criticalRelcachesBuilt
Definition: relcache.c:135

◆ RelationIdIsInInitFile()

bool RelationIdIsInInitFile ( Oid  relationId)

Definition at line 5932 of file relcache.c.

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

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

5933 {
5934  if (relationId == SharedSecLabelRelationId ||
5935  relationId == TriggerRelidNameIndexId ||
5936  relationId == DatabaseNameIndexId ||
5937  relationId == SharedSecLabelObjectIndexId)
5938  {
5939  /*
5940  * If this Assert fails, we don't need the applicable special case
5941  * anymore.
5942  */
5943  Assert(!RelationSupportsSysCache(relationId));
5944  return true;
5945  }
5946  return RelationSupportsSysCache(relationId);
5947 }
#define TriggerRelidNameIndexId
Definition: indexing.h:256
#define Assert(condition)
Definition: c.h:739
#define DatabaseNameIndexId
Definition: indexing.h:144
#define SharedSecLabelObjectIndexId
Definition: indexing.h:323
bool RelationSupportsSysCache(Oid relid)
Definition: syscache.c:1521

◆ RelationInitIndexAccessInfo()

void RelationInitIndexAccessInfo ( Relation  relation)

Definition at line 1347 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, RelationGetNumberOfAttributes, RelationGetRelationName, RelationGetRelid, ReleaseSysCache(), SearchSysCache1(), int2vector::values, and oidvector::values.

Referenced by index_create(), and RelationBuildDesc().

1348 {
1349  HeapTuple tuple;
1350  Form_pg_am aform;
1351  Datum indcollDatum;
1352  Datum indclassDatum;
1353  Datum indoptionDatum;
1354  bool isnull;
1355  oidvector *indcoll;
1356  oidvector *indclass;
1357  int2vector *indoption;
1358  MemoryContext indexcxt;
1359  MemoryContext oldcontext;
1360  int indnatts;
1361  int indnkeyatts;
1362  uint16 amsupport;
1363 
1364  /*
1365  * Make a copy of the pg_index entry for the index. Since pg_index
1366  * contains variable-length and possibly-null fields, we have to do this
1367  * honestly rather than just treating it as a Form_pg_index struct.
1368  */
1369  tuple = SearchSysCache1(INDEXRELID,
1370  ObjectIdGetDatum(RelationGetRelid(relation)));
1371  if (!HeapTupleIsValid(tuple))
1372  elog(ERROR, "cache lookup failed for index %u",
1373  RelationGetRelid(relation));
1375  relation->rd_indextuple = heap_copytuple(tuple);
1376  relation->rd_index = (Form_pg_index) GETSTRUCT(relation->rd_indextuple);
1377  MemoryContextSwitchTo(oldcontext);
1378  ReleaseSysCache(tuple);
1379 
1380  /*
1381  * Look up the index's access method, save the OID of its handler function
1382  */
1383  tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(relation->rd_rel->relam));
1384  if (!HeapTupleIsValid(tuple))
1385  elog(ERROR, "cache lookup failed for access method %u",
1386  relation->rd_rel->relam);
1387  aform = (Form_pg_am) GETSTRUCT(tuple);
1388  relation->rd_amhandler = aform->amhandler;
1389  ReleaseSysCache(tuple);
1390 
1391  indnatts = RelationGetNumberOfAttributes(relation);
1392  if (indnatts != IndexRelationGetNumberOfAttributes(relation))
1393  elog(ERROR, "relnatts disagrees with indnatts for index %u",
1394  RelationGetRelid(relation));
1395  indnkeyatts = IndexRelationGetNumberOfKeyAttributes(relation);
1396 
1397  /*
1398  * Make the private context to hold index access info. The reason we need
1399  * a context, and not just a couple of pallocs, is so that we won't leak
1400  * any subsidiary info attached to fmgr lookup records.
1401  */
1403  "index info",
1405  relation->rd_indexcxt = indexcxt;
1407  RelationGetRelationName(relation));
1408 
1409  /*
1410  * Now we can fetch the index AM's API struct
1411  */
1412  InitIndexAmRoutine(relation);
1413 
1414  /*
1415  * Allocate arrays to hold data. Opclasses are not used for included
1416  * columns, so allocate them for indnkeyatts only.
1417  */
1418  relation->rd_opfamily = (Oid *)
1419  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1420  relation->rd_opcintype = (Oid *)
1421  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1422 
1423  amsupport = relation->rd_indam->amsupport;
1424  if (amsupport > 0)
1425  {
1426  int nsupport = indnatts * amsupport;
1427 
1428  relation->rd_support = (RegProcedure *)
1429  MemoryContextAllocZero(indexcxt, nsupport * sizeof(RegProcedure));
1430  relation->rd_supportinfo = (FmgrInfo *)
1431  MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
1432  }
1433  else
1434  {
1435  relation->rd_support = NULL;
1436  relation->rd_supportinfo = NULL;
1437  }
1438 
1439  relation->rd_indcollation = (Oid *)
1440  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1441 
1442  relation->rd_indoption = (int16 *)
1443  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(int16));
1444 
1445  /*
1446  * indcollation cannot be referenced directly through the C struct,
1447  * because it comes after the variable-width indkey field. Must extract
1448  * the datum the hard way...
1449  */
1450  indcollDatum = fastgetattr(relation->rd_indextuple,
1451  Anum_pg_index_indcollation,
1453  &isnull);
1454  Assert(!isnull);
1455  indcoll = (oidvector *) DatumGetPointer(indcollDatum);
1456  memcpy(relation->rd_indcollation, indcoll->values, indnkeyatts * sizeof(Oid));
1457 
1458  /*
1459  * indclass cannot be referenced directly through the C struct, because it
1460  * comes after the variable-width indkey field. Must extract the datum
1461  * the hard way...
1462  */
1463  indclassDatum = fastgetattr(relation->rd_indextuple,
1464  Anum_pg_index_indclass,
1466  &isnull);
1467  Assert(!isnull);
1468  indclass = (oidvector *) DatumGetPointer(indclassDatum);
1469 
1470  /*
1471  * Fill the support procedure OID array, as well as the info about
1472  * opfamilies and opclass input types. (aminfo and supportinfo are left
1473  * as zeroes, and are filled on-the-fly when used)
1474  */
1475  IndexSupportInitialize(indclass, relation->rd_support,
1476  relation->rd_opfamily, relation->rd_opcintype,
1477  amsupport, indnkeyatts);
1478 
1479  /*
1480  * Similarly extract indoption and copy it to the cache entry
1481  */
1482  indoptionDatum = fastgetattr(relation->rd_indextuple,
1483  Anum_pg_index_indoption,
1485  &isnull);
1486  Assert(!isnull);
1487  indoption = (int2vector *) DatumGetPointer(indoptionDatum);
1488  memcpy(relation->rd_indoption, indoption->values, indnkeyatts * sizeof(int16));
1489 
1490  /*
1491  * expressions, predicate, exclusion caches will be filled later
1492  */
1493  relation->rd_indexprs = NIL;
1494  relation->rd_indpred = NIL;
1495  relation->rd_exclops = NULL;
1496  relation->rd_exclprocs = NULL;
1497  relation->rd_exclstrats = NULL;
1498  relation->rd_amcache = NULL;
1499 }
signed short int16
Definition: c.h:346
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
#define NIL
Definition: pg_list.h:65
Definition: c.h:595
struct IndexAmRoutine * rd_indam
Definition: rel.h:163
Definition: fmgr.h:56
uint16 amsupport
Definition: amapi.h:173
#define AllocSetContextCreate
Definition: memutils.h:170
int16 * rd_indoption
Definition: rel.h:168
#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:167
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:434
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:202
regproc RegProcedure
Definition: c.h:512
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
uint16 * rd_exclstrats
Definition: rel.h:173
List * rd_indexprs
Definition: rel.h:169
Oid * rd_exclprocs
Definition: rel.h:172
Form_pg_class rd_rel
Definition: rel.h:84
unsigned int Oid
Definition: postgres_ext.h:31
static void InitIndexAmRoutine(Relation relation)
Definition: relcache.c:1323
static void IndexSupportInitialize(oidvector *indclass, RegProcedure *indexSupport, Oid *opFamily, Oid *opcInType, StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber)
Definition: relcache.c:1515
struct HeapTupleData * rd_indextuple
Definition: rel.h:151
Form_pg_index rd_index
Definition: rel.h:149
unsigned short uint16
Definition: c.h:358
Oid * rd_indcollation
Definition: rel.h:174
Oid rd_amhandler
Definition: rel.h:141
#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:4041
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:603
#define IndexRelationGetNumberOfAttributes(relation)
Definition: rel.h:440
#define RelationGetRelationName(relation)
Definition: rel.h:462
List * rd_indpred
Definition: rel.h:170
Oid * rd_opfamily
Definition: rel.h:164
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition: rel.h:447
Oid * rd_exclops
Definition: rel.h:171
RegProcedure * rd_support
Definition: rel.h:166
FormData_pg_index * Form_pg_index
Definition: pg_index.h:66
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
Definition: c.h:584
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:839
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:739
int16 values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:592
#define DatumGetPointer(X)
Definition: postgres.h:549
FormData_pg_am * Form_pg_am
Definition: pg_am.h:48
#define elog(elevel,...)
Definition: elog.h:228
MemoryContext rd_indexcxt
Definition: rel.h:161
void * rd_amcache
Definition: rel.h:185
Oid * rd_opcintype
Definition: rel.h:165
#define RelationGetRelid(relation)
Definition: rel.h:428
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationInitTableAccessMethod()

void RelationInitTableAccessMethod ( Relation  relation)

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

1726 {
1727  HeapTuple tuple;
1728  Form_pg_am aform;
1729 
1730  if (relation->rd_rel->relkind == RELKIND_SEQUENCE)
1731  {
1732  /*
1733  * Sequences are currently accessed like heap tables, but it doesn't
1734  * seem prudent to show that in the catalog. So just overwrite it
1735  * here.
1736  */
1737  relation->rd_amhandler = HEAP_TABLE_AM_HANDLER_OID;
1738  }
1739  else if (IsCatalogRelation(relation))
1740  {
1741  /*
1742  * Avoid doing a syscache lookup for catalog tables.
1743  */
1744  Assert(relation->rd_rel->relam == HEAP_TABLE_AM_OID);
1745  relation->rd_amhandler = HEAP_TABLE_AM_HANDLER_OID;
1746  }
1747  else
1748  {
1749  /*
1750  * Look up the table access method, save the OID of its handler
1751  * function.
1752  */
1753  Assert(relation->rd_rel->relam != InvalidOid);
1754  tuple = SearchSysCache1(AMOID,
1755  ObjectIdGetDatum(relation->rd_rel->relam));
1756  if (!HeapTupleIsValid(tuple))
1757  elog(ERROR, "cache lookup failed for access method %u",
1758  relation->rd_rel->relam);
1759  aform = (Form_pg_am) GETSTRUCT(tuple);
1760  relation->rd_amhandler = aform->amhandler;
1761  ReleaseSysCache(tuple);
1762  }
1763 
1764  /*
1765  * Now we can fetch the table AM's API struct
1766  */
1767  InitTableAmRoutine(relation);
1768 }
static void InitTableAmRoutine(Relation relation)
Definition: relcache.c:1716
bool IsCatalogRelation(Relation relation)
Definition: catalog.c:99
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Definition: syscache.h:36
Form_pg_class rd_rel
Definition: rel.h:84
Oid rd_amhandler
Definition: rel.h:141
#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:739
FormData_pg_am * Form_pg_am
Definition: pg_am.h:48
#define elog(elevel,...)
Definition: elog.h:228

◆ RelationSetNewRelfilenode()

void RelationSetNewRelfilenode ( Relation  relation,
char  persistence 
)

Definition at line 3420 of file relcache.c.

References Assert, CacheInvalidateRelcache(), CatalogTupleUpdate(), CommandCounterIncrement(), elog, EOXactListAdd, ERROR, GetCurrentSubTransactionId(), GetCurrentTransactionId(), GetNewRelFileNode(), GETSTRUCT, heap_freetuple(), HeapTupleIsValid, InvalidMultiXactId, InvalidTransactionId, ObjectIdGetDatum, RelationData::rd_newRelfilenodeSubid, RelationData::rd_node, RelationData::rd_rel, 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().

3421 {
3422  Oid newrelfilenode;
3423  Relation pg_class;
3424  HeapTuple tuple;
3425  Form_pg_class classform;
3426  MultiXactId minmulti = InvalidMultiXactId;
3427  TransactionId freezeXid = InvalidTransactionId;
3428  RelFileNode newrnode;
3429 
3430  /* Allocate a new relfilenode */
3431  newrelfilenode = GetNewRelFileNode(relation->rd_rel->reltablespace, NULL,
3432  persistence);
3433 
3434  /*
3435  * Get a writable copy of the pg_class tuple for the given relation.
3436  */
3437  pg_class = table_open(RelationRelationId, RowExclusiveLock);
3438 
3439  tuple = SearchSysCacheCopy1(RELOID,
3440  ObjectIdGetDatum(RelationGetRelid(relation)));
3441  if (!HeapTupleIsValid(tuple))
3442  elog(ERROR, "could not find tuple for relation %u",
3443  RelationGetRelid(relation));
3444  classform = (Form_pg_class) GETSTRUCT(tuple);
3445 
3446  /*
3447  * Schedule unlinking of the old storage at transaction commit.
3448  */
3449  RelationDropStorage(relation);
3450 
3451  /*
3452  * Create storage for the main fork of the new relfilenode. If it's a
3453  * table-like object, call into the table AM to do so, which'll also
3454  * create the table's init fork if needed.
3455  *
3456  * NOTE: If relevant for the AM, any conflict in relfilenode value will be
3457  * caught here, if GetNewRelFileNode messes up for any reason.
3458  */
3459  newrnode = relation->rd_node;
3460  newrnode.relNode = newrelfilenode;
3461 
3462  switch (relation->rd_rel->relkind)
3463  {
3464  case RELKIND_INDEX:
3465  case RELKIND_SEQUENCE:
3466  {
3467  /* handle these directly, at least for now */
3468  SMgrRelation srel;
3469 
3470  srel = RelationCreateStorage(newrnode, persistence);
3471  smgrclose(srel);
3472  }
3473  break;
3474 
3475  case RELKIND_RELATION:
3476  case RELKIND_TOASTVALUE:
3477  case RELKIND_MATVIEW:
3478  table_relation_set_new_filenode(relation, &newrnode,
3479  persistence,
3480  &freezeXid, &minmulti);
3481  break;
3482 
3483  default:
3484  /* we shouldn't be called for anything else */
3485  elog(ERROR, "relation \"%s\" does not have storage",
3486  RelationGetRelationName(relation));
3487  break;
3488  }
3489 
3490  /*
3491  * If we're dealing with a mapped index, pg_class.relfilenode doesn't
3492  * change; instead we have to send the update to the relation mapper.
3493  *
3494  * For mapped indexes, we don't actually change the pg_class entry at all;
3495  * this is essential when reindexing pg_class itself. That leaves us with
3496  * possibly-inaccurate values of relpages etc, but those will be fixed up
3497  * later.
3498  */
3499  if (RelationIsMapped(relation))
3500  {
3501  /* This case is only supported for indexes */
3502  Assert(relation->rd_rel->relkind == RELKIND_INDEX);
3503 
3504  /* Since we're not updating pg_class, these had better not change */
3505  Assert(classform->relfrozenxid == freezeXid);
3506  Assert(classform->relminmxid == minmulti);
3507  Assert(classform->relpersistence == persistence);
3508 
3509  /*
3510  * In some code paths it's possible that the tuple update we'd
3511  * otherwise do here is the only thing that would assign an XID for
3512  * the current transaction. However, we must have an XID to delete
3513  * files, so make sure one is assigned.
3514  */
3515  (void) GetCurrentTransactionId();
3516 
3517  /* Do the deed */
3519  newrelfilenode,
3520  relation->rd_rel->relisshared,
3521  false);
3522 
3523  /* Since we're not updating pg_class, must trigger inval manually */
3524  CacheInvalidateRelcache(relation);
3525  }
3526  else
3527  {
3528  /* Normal case, update the pg_class entry */
3529  classform->relfilenode = newrelfilenode;
3530 
3531  /* relpages etc. never change for sequences */
3532  if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
3533  {
3534  classform->relpages = 0; /* it's empty until further notice */
3535  classform->reltuples = 0;
3536  classform->relallvisible = 0;
3537  }
3538  classform->relfrozenxid = freezeXid;
3539  classform->relminmxid = minmulti;
3540  classform->relpersistence = persistence;
3541 
3542  CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
3543  }
3544 
3545  heap_freetuple(tuple);
3546 
3547  table_close(pg_class, RowExclusiveLock);
3548 
3549  /*
3550  * Make the pg_class row change or relation map change visible. This will
3551  * cause the relcache entry to get updated, too.
3552  */
3554 
3555  /*
3556  * Mark the rel as having been given a new relfilenode in the current
3557  * (sub) transaction. This is a hint that can be used to optimize later
3558  * operations on the rel in the same transaction.
3559  */
3561 
3562  /* Flag relation as needing eoxact cleanup (to remove the hint) */
3563  EOXactListAdd(relation);
3564 }
void smgrclose(SMgrRelation reln)
Definition: smgr.c:256
#define EOXactListAdd(rel)
Definition: relcache.c:166
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
uint32 TransactionId
Definition: c.h:514
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:81
Form_pg_class rd_rel
Definition: rel.h:84
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:78
#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:422
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvalidTransactionId
Definition: transam.h:31
#define RelationGetRelationName(relation)
Definition: rel.h:462
#define RelationIsMapped(relation)
Definition: rel.h:477
void RelationDropStorage(Relation rel)
Definition: storage.c:147
void CommandCounterIncrement(void)
Definition: xact.c:1005
#define InvalidMultiXactId
Definition: multixact.h:23
TransactionId MultiXactId
Definition: c.h:524
RelFileNode rd_node
Definition: rel.h:55
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:739
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:707
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
Oid GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
Definition: catalog.c:385
static void table_relation_set_new_filenode(Relation rel, const RelFileNode *newrnode, char persistence, TransactionId *freezeXid, MultiXactId *minmulti)
Definition: tableam.h:1362
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1270
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
#define elog(elevel,...)
Definition: elog.h:228
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define RelationGetRelid(relation)
Definition: rel.h:428
void RelationMapUpdateMap(Oid relationId, Oid fileNode, bool shared, bool immediate)
Definition: relmapper.c:261

Variable Documentation

◆ criticalRelcachesBuilt

◆ criticalSharedRelcachesBuilt

bool criticalSharedRelcachesBuilt