PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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.

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 RelationGetOidIndex (Relation relation)
 
Oid RelationGetPrimaryKeyIndex (Relation relation)
 
Oid RelationGetReplicaIndex (Relation relation)
 
ListRelationGetIndexExpressions (Relation relation)
 
ListRelationGetIndexPredicate (Relation relation)
 
BitmapsetRelationGetIndexAttrBitmap (Relation relation, IndexAttrBitmapKind keyAttrs)
 
void RelationGetExclusionInfo (Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
 
void RelationSetIndexList (Relation relation, List *indexIds, Oid oidIndex)
 
void RelationInitIndexAccessInfo (Relation relation)
 
struct PublicationActionsGetRelationPublicationActions (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 relfilenode, Oid reltablespace, bool shared_relation, bool mapped_relation, char relpersistence, char relkind)
 
void RelationSetNewRelfilenode (Relation relation, char persistence, TransactionId freezeXid, MultiXactId minmulti)
 
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
 

Typedef Documentation

Definition at line 21 of file relcache.h.

Definition at line 29 of file relcache.h.

Enumeration Type Documentation

Enumerator
INDEX_ATTR_BITMAP_ALL 
INDEX_ATTR_BITMAP_KEY 
INDEX_ATTR_BITMAP_PRIMARY_KEY 
INDEX_ATTR_BITMAP_IDENTITY_KEY 

Definition at line 49 of file relcache.h.

Function Documentation

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

Definition at line 3067 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, NULL, relidcacheent::reldesc, and status().

Referenced by AbortSubTransaction(), and CommitSubTransaction().

3069 {
3071  RelIdCacheEnt *idhentry;
3072  int i;
3073 
3074  /*
3075  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3076  * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3077  * logic as in AtEOXact_RelationCache.
3078  */
3080  {
3081  hash_seq_init(&status, RelationIdCache);
3082  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3083  {
3084  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3085  mySubid, parentSubid);
3086  }
3087  }
3088  else
3089  {
3090  for (i = 0; i < eoxact_list_len; i++)
3091  {
3092  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3093  (void *) &eoxact_list[i],
3094  HASH_FIND,
3095  NULL);
3096  if (idhentry != NULL)
3097  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3098  mySubid, parentSubid);
3099  }
3100  }
3101 
3102  /* Don't reset the list; we still need more cleanup later */
3103 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:156
static void AtEOSubXact_cleanup(Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
Definition: relcache.c:3114
Relation reldesc
Definition: relcache.c:120
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
static HTAB * RelationIdCache
Definition: relcache.c:123
static bool eoxact_list_overflowed
Definition: relcache.c:158
#define NULL
Definition: c.h:229
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1351
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1341
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224
static int eoxact_list_len
Definition: relcache.c:157
void AtEOXact_RelationCache ( bool  isCommit)

Definition at line 2916 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, NULL, pfree(), relidcacheent::reldesc, and status().

Referenced by AbortTransaction(), CommitTransaction(), and PrepareTransaction().

2917 {
2919  RelIdCacheEnt *idhentry;
2920  int i;
2921 
2922  /*
2923  * Unless the eoxact_list[] overflowed, we only need to examine the rels
2924  * listed in it. Otherwise fall back on a hash_seq_search scan.
2925  *
2926  * For simplicity, eoxact_list[] entries are not deleted till end of
2927  * top-level transaction, even though we could remove them at
2928  * subtransaction end in some cases, or remove relations from the list if
2929  * they are cleared for other reasons. Therefore we should expect the
2930  * case that list entries are not found in the hashtable; if not, there's
2931  * nothing to do for them.
2932  */
2934  {
2935  hash_seq_init(&status, RelationIdCache);
2936  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2937  {
2938  AtEOXact_cleanup(idhentry->reldesc, isCommit);
2939  }
2940  }
2941  else
2942  {
2943  for (i = 0; i < eoxact_list_len; i++)
2944  {
2945  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
2946  (void *) &eoxact_list[i],
2947  HASH_FIND,
2948  NULL);
2949  if (idhentry != NULL)
2950  AtEOXact_cleanup(idhentry->reldesc, isCommit);
2951  }
2952  }
2953 
2954  if (EOXactTupleDescArrayLen > 0)
2955  {
2957  for (i = 0; i < NextEOXactTupleDescNum; i++)
2961  }
2962 
2963  /* Now we're out of the transaction and can clear the lists */
2964  eoxact_list_len = 0;
2965  eoxact_list_overflowed = false;
2966  NextEOXactTupleDescNum = 0;
2968 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:156
static int EOXactTupleDescArrayLen
Definition: relcache.c:175
Relation reldesc
Definition: relcache.c:120
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
static HTAB * RelationIdCache
Definition: relcache.c:123
static void AtEOXact_cleanup(Relation relation, bool isCommit)
Definition: relcache.c:2979
static bool eoxact_list_overflowed
Definition: relcache.c:158
static int NextEOXactTupleDescNum
Definition: relcache.c:174
void pfree(void *pointer)
Definition: mcxt.c:950
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1351
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1341
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:268
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224
static int eoxact_list_len
Definition: relcache.c:157
static TupleDesc * EOXactTupleDescArray
Definition: relcache.c:173
int errtable ( Relation  rel)

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

5244 {
5248 
5249  return 0; /* return value does not matter */
5250 }
#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:3033
#define RelationGetRelationName(relation)
Definition: rel.h:437
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
#define RelationGetNamespace(relation)
Definition: rel.h:444
int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5260 of file relcache.c.

References tupleDesc::attrs, errtablecolname(), get_relid_attribute_name(), NameStr, RelationGetDescr, and RelationGetRelid.

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

5261 {
5262  TupleDesc reldesc = RelationGetDescr(rel);
5263  const char *colname;
5264 
5265  /* Use reldesc if it's a user attribute, else consult the catalogs */
5266  if (attnum > 0 && attnum <= reldesc->natts)
5267  colname = NameStr(reldesc->attrs[attnum - 1]->attname);
5268  else
5269  colname = get_relid_attribute_name(RelationGetRelid(rel), attnum);
5270 
5271  return errtablecolname(rel, colname);
5272 }
#define RelationGetDescr(relation)
Definition: rel.h:429
Form_pg_attribute * attrs
Definition: tupdesc.h:74
char * get_relid_attribute_name(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:801
#define NameStr(name)
Definition: c.h:499
#define RelationGetRelid(relation)
Definition: rel.h:417
int errtablecolname(Relation rel, const char *colname)
Definition: relcache.c:5284
int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5284 of file relcache.c.

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

Referenced by errtablecol().

5285 {
5286  errtable(rel);
5288 
5289  return 0; /* return value does not matter */
5290 }
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:67
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
int errtable(Relation rel)
Definition: relcache.c:5243
int errtableconstraint ( Relation  rel,
const char *  conname 
)

Definition at line 5297 of file relcache.c.

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

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

5298 {
5299  errtable(rel);
5301 
5302  return 0; /* return value does not matter */
5303 }
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:69
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
int errtable(Relation rel)
Definition: relcache.c:5243
struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

Definition at line 5172 of file relcache.c.

References CacheMemoryContext, elog, ERROR, GetAllTablesPublications(), GetRelationPublications(), GETSTRUCT, HeapTupleIsValid, lfirst_oid, list_concat_unique_oid(), MemoryContextSwitchTo(), NULL, ObjectIdGetDatum, palloc(), palloc0(), pfree(), PublicationActions::pubdelete, PublicationActions::pubinsert, PUBLICATIONOID, PublicationActions::pubupdate, RelationData::rd_pubactions, RelationGetRelid, ReleaseSysCache(), and SearchSysCache1.

Referenced by CheckCmdReplicaIdentity().

5173 {
5174  List *puboids;
5175  ListCell *lc;
5176  MemoryContext oldcxt;
5177  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5178 
5179  if (relation->rd_pubactions)
5180  return memcpy(pubactions, relation->rd_pubactions,
5181  sizeof(PublicationActions));
5182 
5183  /* Fetch the publication membership info. */
5184  puboids = GetRelationPublications(RelationGetRelid(relation));
5185  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5186 
5187  foreach(lc, puboids)
5188  {
5189  Oid pubid = lfirst_oid(lc);
5190  HeapTuple tup;
5191  Form_pg_publication pubform;
5192 
5194 
5195  if (!HeapTupleIsValid(tup))
5196  elog(ERROR, "cache lookup failed for publication %u", pubid);
5197 
5198  pubform = (Form_pg_publication) GETSTRUCT(tup);
5199 
5200  pubactions->pubinsert |= pubform->pubinsert;
5201  pubactions->pubupdate |= pubform->pubupdate;
5202  pubactions->pubdelete |= pubform->pubdelete;
5203 
5204  ReleaseSysCache(tup);
5205 
5206  /*
5207  * If we know everything is replicated, there is no point to check for
5208  * other publications.
5209  */
5210  if (pubactions->pubinsert && pubactions->pubupdate &&
5211  pubactions->pubdelete)
5212  break;
5213  }
5214 
5215  if (relation->rd_pubactions)
5216  {
5217  pfree(relation->rd_pubactions);
5218  relation->rd_pubactions = NULL;
5219  }
5220 
5221  /* Now save copy of the actions in the relcache entry. */
5223  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5224  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5225  MemoryContextSwitchTo(oldcxt);
5226 
5227  return pubactions;
5228 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
PublicationActions * rd_pubactions
Definition: rel.h:149
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned int Oid
Definition: postgres_ext.h:31
List * list_concat_unique_oid(List *list1, List *list2)
Definition: list.c:1082
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
List * GetRelationPublications(Oid relid)
void pfree(void *pointer)
Definition: mcxt.c:950
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
void * palloc0(Size size)
Definition: mcxt.c:878
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
List * GetAllTablesPublications(void)
void * palloc(Size size)
Definition: mcxt.c:849
#define elog
Definition: elog.h:219
FormData_pg_publication * Form_pg_publication
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:417
#define lfirst_oid(lc)
Definition: pg_list.h:108
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
Relation RelationBuildLocalRelation ( const char *  relname,
Oid  relnamespace,
TupleDesc  tupDesc,
Oid  relid,
Oid  relfilenode,
Oid  reltablespace,
bool  shared_relation,
bool  mapped_relation,
char  relpersistence,
char  relkind 
)

Definition at line 3179 of file relcache.c.

References Assert, AssertArg, AttributeRelationId, tupleDesc::attrs, AuthIdRelationId, AuthMemRelationId, BackendIdForTempRelations, BOOTSTRAP_SUPERUSERID, CacheMemoryContext, CLASS_TUPLE_SIZE, tupleDesc::constr, CreateCacheMemoryContext(), CreateTupleDescCopy(), DatabaseRelationId, elog, EOXactListAdd, ERROR, GetCurrentSubTransactionId(), tupleConstr::has_not_null, i, InvalidBackendId, InvalidOid, InvalidSubTransactionId, IsSharedRelation(), IsSystemNamespace(), isTempOrTempToastNamespace(), MemoryContextSwitchTo(), namestrcpy(), tupleDesc::natts, NULL, palloc0(), ProcedureRelationId, 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(), RelationMapUpdateMap(), RelationRelationId, RELKIND_MATVIEW, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, RELPERSISTENCE_PERMANENT, RELPERSISTENCE_TEMP, RELPERSISTENCE_UNLOGGED, REPLICA_IDENTITY_DEFAULT, REPLICA_IDENTITY_NOTHING, tupleDesc::tdhasoid, tupleDesc::tdrefcount, and TypeRelationId.

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  rel->rd_att->attrs[i]->attidentity = tupDesc->attrs[i]->attidentity;
3272  rel->rd_att->attrs[i]->attnotnull = tupDesc->attrs[i]->attnotnull;
3273  has_not_null |= tupDesc->attrs[i]->attnotnull;
3274  }
3275 
3276  if (has_not_null)
3277  {
3278  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
3279 
3280  constr->has_not_null = true;
3281  rel->rd_att->constr = constr;
3282  }
3283 
3284  /*
3285  * initialize relation tuple form (caller may add/override data later)
3286  */
3288 
3289  namestrcpy(&rel->rd_rel->relname, relname);
3290  rel->rd_rel->relnamespace = relnamespace;
3291 
3292  rel->rd_rel->relkind = relkind;
3293  rel->rd_rel->relhasoids = rel->rd_att->tdhasoid;
3294  rel->rd_rel->relnatts = natts;
3295  rel->rd_rel->reltype = InvalidOid;
3296  /* needed when bootstrapping: */
3297  rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;
3298 
3299  /* set up persistence and relcache fields dependent on it */
3300  rel->rd_rel->relpersistence = relpersistence;
3301  switch (relpersistence)
3302  {
3306  rel->rd_islocaltemp = false;
3307  break;
3308  case RELPERSISTENCE_TEMP:
3309  Assert(isTempOrTempToastNamespace(relnamespace));
3311  rel->rd_islocaltemp = true;
3312  break;
3313  default:
3314  elog(ERROR, "invalid relpersistence: %c", relpersistence);
3315  break;
3316  }
3317 
3318  /* if it's a materialized view, it's not populated initially */
3319  if (relkind == RELKIND_MATVIEW)
3320  rel->rd_rel->relispopulated = false;
3321  else
3322  rel->rd_rel->relispopulated = true;
3323 
3324  /* system relations and non-table objects don't have one */
3325  if (!IsSystemNamespace(relnamespace) &&
3326  (relkind == RELKIND_RELATION ||
3327  relkind == RELKIND_MATVIEW ||
3328  relkind == RELKIND_PARTITIONED_TABLE))
3329  rel->rd_rel->relreplident = REPLICA_IDENTITY_DEFAULT;
3330  else
3331  rel->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
3332 
3333  /*
3334  * Insert relation physical and logical identifiers (OIDs) into the right
3335  * places. For a mapped relation, we set relfilenode to zero and rely on
3336  * RelationInitPhysicalAddr to consult the map.
3337  */
3338  rel->rd_rel->relisshared = shared_relation;
3339 
3340  RelationGetRelid(rel) = relid;
3341 
3342  for (i = 0; i < natts; i++)
3343  rel->rd_att->attrs[i]->attrelid = relid;
3344 
3345  rel->rd_rel->reltablespace = reltablespace;
3346 
3347  if (mapped_relation)
3348  {
3349  rel->rd_rel->relfilenode = InvalidOid;
3350  /* Add it to the active mapping information */
3351  RelationMapUpdateMap(relid, relfilenode, shared_relation, true);
3352  }
3353  else
3354  rel->rd_rel->relfilenode = relfilenode;
3355 
3356  RelationInitLockInfo(rel); /* see lmgr.c */
3357 
3359 
3360  /*
3361  * Okay to insert into the relcache hash table.
3362  *
3363  * Ordinarily, there should certainly not be an existing hash entry for
3364  * the same OID; but during bootstrap, when we create a "real" relcache
3365  * entry for one of the bootstrap relations, we'll be overwriting the
3366  * phony one created with formrdesc. So allow that to happen for nailed
3367  * rels.
3368  */
3369  RelationCacheInsert(rel, nailit);
3370 
3371  /*
3372  * Flag relation as needing eoxact cleanup (to clear rd_createSubid). We
3373  * can't do this before storing relid in it.
3374  */
3375  EOXactListAdd(rel);
3376 
3377  /*
3378  * done building relcache entry.
3379  */
3380  MemoryContextSwitchTo(oldcxt);
3381 
3382  /* It's fully valid */
3383  rel->rd_isvalid = true;
3384 
3385  /*
3386  * Caller expects us to pin the returned entry.
3387  */
3389 
3390  return rel;
3391 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:141
#define EOXactListAdd(rel)
Definition: relcache.c:160
bool tdhasoid
Definition: tupdesc.h:79
#define RELPERSISTENCE_UNLOGGED
Definition: pg_class.h:171
#define REPLICA_IDENTITY_NOTHING
Definition: pg_class.h:177
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3099
#define ProcedureRelationId
Definition: pg_proc.h:33
#define AuthMemRelationId
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
#define DatabaseRelationId
Definition: pg_database.h:29
#define RelationRelationId
Definition: pg_class.h:29
bool rd_isnailed
Definition: rel.h:91
bool rd_islocaltemp
Definition: rel.h:90
Form_pg_attribute * attrs
Definition: tupdesc.h:74
#define RELKIND_MATVIEW
Definition: pg_class.h:165
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define REPLICA_IDENTITY_DEFAULT
Definition: pg_class.h:175
#define AttributeRelationId
Definition: pg_attribute.h:33
bool rd_isvalid
Definition: rel.h:92
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:111
Form_pg_class rd_rel
Definition: rel.h:114
#define TypeRelationId
Definition: pg_type.h:34
int namestrcpy(Name name, const char *str)
Definition: name.c:217
int natts
Definition: tupdesc.h:73
#define AuthIdRelationId
Definition: pg_authid.h:42
#define RELPERSISTENCE_PERMANENT
Definition: pg_class.h:170
struct RelationData * Relation
Definition: relcache.h:21
#define ERROR
Definition: elog.h:43
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1418
void RelationInitLockInfo(Relation relation)
Definition: lmgr.c:68
#define BackendIdForTempRelations()
Definition: backendid.h:34
#define AssertArg(condition)
Definition: c.h:677
bool has_not_null
Definition: tupdesc.h:43
SubTransactionId rd_createSubid
Definition: rel.h:110
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
#define InvalidBackendId
Definition: backendid.h:23
void * palloc0(Size size)
Definition: mcxt.c:878
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2123
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:219
TupleDesc rd_att
Definition: rel.h:115
bool IsSystemNamespace(Oid namespaceId)
Definition: catalog.c:162
#define InvalidOid
Definition: postgres_ext.h:36
#define RelationCacheInsert(RELATION, replace_allowed)
Definition: relcache.c:180
#define CLASS_TUPLE_SIZE
Definition: pg_class.h:87
#define NULL
Definition: c.h:229
BackendId rd_backend
Definition: rel.h:89
#define Assert(condition)
Definition: c.h:675
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:649
TupleConstr * constr
Definition: tupdesc.h:76
void CreateCacheMemoryContext(void)
Definition: catcache.c:511
#define BOOTSTRAP_SUPERUSERID
Definition: pg_authid.h:102
#define InvalidSubTransactionId
Definition: c.h:403
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
int rd_refcnt
Definition: rel.h:88
int tdrefcount
Definition: tupdesc.h:80
int i
#define elog
Definition: elog.h:219
#define RELPERSISTENCE_TEMP
Definition: pg_class.h:172
#define RELKIND_RELATION
Definition: pg_class.h:160
#define RelationGetRelid(relation)
Definition: rel.h:417
void RelationMapUpdateMap(Oid relationId, Oid fileNode, bool shared, bool immediate)
Definition: relmapper.c:248
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void RelationCacheInitFilePostInvalidate ( void  )

Definition at line 6069 of file relcache.c.

References LWLockRelease().

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

6070 {
6071  LWLockRelease(RelCacheInitLock);
6072 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
void RelationCacheInitFilePreInvalidate ( void  )

Definition at line 6043 of file relcache.c.

References DatabasePath, ereport, errcode_for_file_access(), errmsg(), ERROR, LW_EXCLUSIVE, LWLockAcquire(), MAXPGPATH, RELCACHE_INIT_FILENAME, snprintf(), and unlink().

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

6044 {
6045  char initfilename[MAXPGPATH];
6046 
6047  snprintf(initfilename, sizeof(initfilename), "%s/%s",
6049 
6050  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6051 
6052  if (unlink(initfilename) < 0)
6053  {
6054  /*
6055  * The file might not be there if no backend has been started since
6056  * the last removal. But complain about failures other than ENOENT.
6057  * Fortunately, it's not too late to abort the transaction if we can't
6058  * get rid of the would-be-obsolete init file.
6059  */
6060  if (errno != ENOENT)
6061  ereport(ERROR,
6063  errmsg("could not remove cache file \"%s\": %m",
6064  initfilename)));
6065  }
6066 }
#define RELCACHE_INIT_FILENAME
Definition: relcache.c:93
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define ERROR
Definition: elog.h:43
#define MAXPGPATH
int errcode_for_file_access(void)
Definition: elog.c:598
int unlink(const char *filename)
#define ereport(elevel, rest)
Definition: elog.h:122
char * DatabasePath
Definition: globals.c:84
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
int errmsg(const char *fmt,...)
Definition: elog.c:797
void RelationCacheInitFileRemove ( void  )

Definition at line 6084 of file relcache.c.

References AllocateDir(), dirent::d_name, elog, FreeDir(), LOG, MAXPGPATH, NULL, ReadDir(), RelationCacheInitFileRemoveInDir(), RELCACHE_INIT_FILENAME, snprintf(), TABLESPACE_VERSION_DIRECTORY, and unlink_initfile().

Referenced by StartupXLOG().

6085 {
6086  const char *tblspcdir = "pg_tblspc";
6087  DIR *dir;
6088  struct dirent *de;
6089  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6090 
6091  /*
6092  * We zap the shared cache file too. In theory it can't get out of sync
6093  * enough to be a problem, but in data-corruption cases, who knows ...
6094  */
6095  snprintf(path, sizeof(path), "global/%s",
6097  unlink_initfile(path);
6098 
6099  /* Scan everything in the default tablespace */
6101 
6102  /* Scan the tablespace link directory to find non-default tablespaces */
6103  dir = AllocateDir(tblspcdir);
6104  if (dir == NULL)
6105  {
6106  elog(LOG, "could not open tablespace link directory \"%s\": %m",
6107  tblspcdir);
6108  return;
6109  }
6110 
6111  while ((de = ReadDir(dir, tblspcdir)) != NULL)
6112  {
6113  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6114  {
6115  /* Scan the tablespace dir for per-database dirs */
6116  snprintf(path, sizeof(path), "%s/%s/%s",
6117  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6119  }
6120  }
6121 
6122  FreeDir(dir);
6123 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6127
#define RELCACHE_INIT_FILENAME
Definition: relcache.c:93
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2335
static void unlink_initfile(const char *initfilename)
Definition: relcache.c:6157
#define NULL
Definition: c.h:229
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2401
#define TABLESPACE_VERSION_DIRECTORY
Definition: catalog.h:26
char d_name[MAX_PATH]
Definition: dirent.h:14
#define elog
Definition: elog.h:219
int FreeDir(DIR *dir)
Definition: fd.c:2444
void RelationCacheInitialize ( void  )

Definition at line 3528 of file relcache.c.

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

Referenced by InitPostgres().

3529 {
3530  HASHCTL ctl;
3531 
3532  /*
3533  * make sure cache memory context exists
3534  */
3535  if (!CacheMemoryContext)
3537 
3538  /*
3539  * create hashtable that indexes the relcache
3540  */
3541  MemSet(&ctl, 0, sizeof(ctl));
3542  ctl.keysize = sizeof(Oid);
3543  ctl.entrysize = sizeof(RelIdCacheEnt);
3544  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3545  &ctl, HASH_ELEM | HASH_BLOBS);
3546 
3547  /*
3548  * relation mapper needs to be initialized too
3549  */
3551 }
void RelationMapInitialize(void)
Definition: relmapper.c:562
#define HASH_ELEM
Definition: hsearch.h:87
struct relidcacheent RelIdCacheEnt
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:857
static HTAB * RelationIdCache
Definition: relcache.c:123
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:301
Size keysize
Definition: hsearch.h:72
void CreateCacheMemoryContext(void)
Definition: catcache.c:511
#define INITRELCACHESIZE
Definition: relcache.c:3525
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void RelationCacheInitializePhase2 ( void  )

Definition at line 3565 of file relcache.c.

References AuthIdRelation_Rowtype_Id, AuthMemRelation_Rowtype_Id, CacheMemoryContext, DatabaseRelation_Rowtype_Id, Desc_pg_auth_members, Desc_pg_authid, Desc_pg_database, Desc_pg_shseclabel, Desc_pg_subscription, formrdesc(), IsBootstrapProcessingMode, load_relcache_init_file(), MemoryContextSwitchTo(), Natts_pg_auth_members, Natts_pg_authid, Natts_pg_database, Natts_pg_shseclabel, Natts_pg_subscription, RelationMapInitializePhase2(), SharedSecLabelRelation_Rowtype_Id, and SubscriptionRelation_Rowtype_Id.

Referenced by InitPostgres().

3566 {
3567  MemoryContext oldcxt;
3568 
3569  /*
3570  * relation mapper needs initialized too
3571  */
3573 
3574  /*
3575  * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3576  * nothing.
3577  */
3579  return;
3580 
3581  /*
3582  * switch to cache memory context
3583  */
3585 
3586  /*
3587  * Try to load the shared relcache cache file. If unsuccessful, bootstrap
3588  * the cache with pre-made descriptors for the critical shared catalogs.
3589  */
3590  if (!load_relcache_init_file(true))
3591  {
3592  formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
3594  formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
3596  formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
3598  formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
3600  formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
3602 
3603 #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
3604  }
3605 
3606  MemoryContextSwitchTo(oldcxt);
3607 }
static const FormData_pg_attribute Desc_pg_auth_members[Natts_pg_auth_members]
Definition: relcache.c:106
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5361
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, bool hasoids, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1887
#define SubscriptionRelation_Rowtype_Id
void RelationMapInitializePhase2(void)
Definition: relmapper.c:582
#define Natts_pg_database
Definition: pg_database.h:63
static const FormData_pg_attribute Desc_pg_authid[Natts_pg_authid]
Definition: relcache.c:105
static const FormData_pg_attribute Desc_pg_subscription[Natts_pg_subscription]
Definition: relcache.c:109
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define Natts_pg_auth_members
#define SharedSecLabelRelation_Rowtype_Id
Definition: pg_shseclabel.h:22
#define Natts_pg_subscription
#define AuthIdRelation_Rowtype_Id
Definition: pg_authid.h:43
#define AuthMemRelation_Rowtype_Id
static const FormData_pg_attribute Desc_pg_database[Natts_pg_database]
Definition: relcache.c:104
#define Natts_pg_shseclabel
Definition: pg_shseclabel.h:41
static const FormData_pg_attribute Desc_pg_shseclabel[Natts_pg_shseclabel]
Definition: relcache.c:108
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:365
#define DatabaseRelation_Rowtype_Id
Definition: pg_database.h:30
#define Natts_pg_authid
Definition: pg_authid.h:78
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void RelationCacheInitializePhase3 ( void  )

Definition at line 3624 of file relcache.c.

References AccessMethodProcedureIndexId, AccessMethodProcedureRelationId, Assert, AttributeRelation_Rowtype_Id, AttributeRelationId, AttributeRelidNumIndexId, AuthIdOidIndexId, AuthIdRelationId, AuthIdRolnameIndexId, AuthMemMemRoleIndexId, AuthMemRelationId, CacheMemoryContext, CLASS_TUPLE_SIZE, ClassOidIndexId, criticalRelcachesBuilt, criticalSharedRelcachesBuilt, DatabaseNameIndexId, DatabaseOidIndexId, DatabaseRelationId, 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, IndexRelationId, IndexRelidIndexId, InitCatalogCachePhase2(), InvalidOid, IsBootstrapProcessingMode, load_critical_index(), load_relcache_init_file(), MemoryContextSwitchTo(), Natts_pg_attribute, Natts_pg_class, Natts_pg_proc, Natts_pg_type, NULL, ObjectIdGetDatum, OpclassOidIndexId, OperatorClassRelationId, pfree(), ProcedureRelation_Rowtype_Id, RelationData::rd_att, RelationData::rd_options, RelationData::rd_partdesc, RelationData::rd_partkey, RelationData::rd_rel, RelationData::rd_rsdesc, RelationData::rd_rules, RelationBuildPartitionDesc(), RelationBuildPartitionKey(), RelationBuildRowSecurity(), RelationBuildRuleLock(), RelationBuildTriggers(), RelationDecrementReferenceCount(), RelationGetRelationName, RelationGetRelid, RelationIncrementReferenceCount(), RelationMapInitializePhase3(), RelationParseRelOptions(), RelationRelation_Rowtype_Id, RelationRelationId, relidcacheent::reldesc, ReleaseSysCache(), RELKIND_PARTITIONED_TABLE, RELOID, RewriteRelationId, RewriteRelRulenameIndexId, SearchSysCache1, SharedSecLabelObjectIndexId, SharedSecLabelRelationId, status(), tupleDesc::tdhasoid, tupleDesc::tdtypeid, tupleDesc::tdtypmod, RelationData::trigdesc, TriggerRelationId, TriggerRelidNameIndexId, TypeRelation_Rowtype_Id, and write_relcache_init_file().

Referenced by InitPostgres().

3625 {
3627  RelIdCacheEnt *idhentry;
3628  MemoryContext oldcxt;
3629  bool needNewCacheFile = !criticalSharedRelcachesBuilt;
3630 
3631  /*
3632  * relation mapper needs initialized too
3633  */
3635 
3636  /*
3637  * switch to cache memory context
3638  */
3640 
3641  /*
3642  * Try to load the local relcache cache file. If unsuccessful, bootstrap
3643  * the cache with pre-made descriptors for the critical "nailed-in" system
3644  * catalogs.
3645  */
3646  if (IsBootstrapProcessingMode() ||
3647  !load_relcache_init_file(false))
3648  {
3649  needNewCacheFile = true;
3650 
3651  formrdesc("pg_class", RelationRelation_Rowtype_Id, false,
3652  true, Natts_pg_class, Desc_pg_class);
3653  formrdesc("pg_attribute", AttributeRelation_Rowtype_Id, false,
3655  formrdesc("pg_proc", ProcedureRelation_Rowtype_Id, false,
3656  true, Natts_pg_proc, Desc_pg_proc);
3657  formrdesc("pg_type", TypeRelation_Rowtype_Id, false,
3658  true, Natts_pg_type, Desc_pg_type);
3659 
3660 #define NUM_CRITICAL_LOCAL_RELS 4 /* fix if you change list above */
3661  }
3662 
3663  MemoryContextSwitchTo(oldcxt);
3664 
3665  /* In bootstrap mode, the faked-up formrdesc info is all we'll have */
3667  return;
3668 
3669  /*
3670  * If we didn't get the critical system indexes loaded into relcache, do
3671  * so now. These are critical because the catcache and/or opclass cache
3672  * depend on them for fetches done during relcache load. Thus, we have an
3673  * infinite-recursion problem. We can break the recursion by doing
3674  * heapscans instead of indexscans at certain key spots. To avoid hobbling
3675  * performance, we only want to do that until we have the critical indexes
3676  * loaded into relcache. Thus, the flag criticalRelcachesBuilt is used to
3677  * decide whether to do heapscan or indexscan at the key spots, and we set
3678  * it true after we've loaded the critical indexes.
3679  *
3680  * The critical indexes are marked as "nailed in cache", partly to make it
3681  * easy for load_relcache_init_file to count them, but mainly because we
3682  * cannot flush and rebuild them once we've set criticalRelcachesBuilt to
3683  * true. (NOTE: perhaps it would be possible to reload them by
3684  * temporarily setting criticalRelcachesBuilt to false again. For now,
3685  * though, we just nail 'em in.)
3686  *
3687  * RewriteRelRulenameIndexId and TriggerRelidNameIndexId are not critical
3688  * in the same way as the others, because the critical catalogs don't
3689  * (currently) have any rules or triggers, and so these indexes can be
3690  * rebuilt without inducing recursion. However they are used during
3691  * relcache load when a rel does have rules or triggers, so we choose to
3692  * nail them for performance reasons.
3693  */
3695  {
3701  IndexRelationId);
3710 
3711 #define NUM_CRITICAL_LOCAL_INDEXES 7 /* fix if you change list above */
3712 
3713  criticalRelcachesBuilt = true;
3714  }
3715 
3716  /*
3717  * Process critical shared indexes too.
3718  *
3719  * DatabaseNameIndexId isn't critical for relcache loading, but rather for
3720  * initial lookup of MyDatabaseId, without which we'll never find any
3721  * non-shared catalogs at all. Autovacuum calls InitPostgres with a
3722  * database OID, so it instead depends on DatabaseOidIndexId. We also
3723  * need to nail up some indexes on pg_authid and pg_auth_members for use
3724  * during client authentication. SharedSecLabelObjectIndexId isn't
3725  * critical for the core system, but authentication hooks might be
3726  * interested in it.
3727  */
3729  {
3742 
3743 #define NUM_CRITICAL_SHARED_INDEXES 6 /* fix if you change list above */
3744 
3746  }
3747 
3748  /*
3749  * Now, scan all the relcache entries and update anything that might be
3750  * wrong in the results from formrdesc or the relcache cache file. If we
3751  * faked up relcache entries using formrdesc, then read the real pg_class
3752  * rows and replace the fake entries with them. Also, if any of the
3753  * relcache entries have rules, triggers, or security policies, load that
3754  * info the hard way since it isn't recorded in the cache file.
3755  *
3756  * Whenever we access the catalogs to read data, there is a possibility of
3757  * a shared-inval cache flush causing relcache entries to be removed.
3758  * Since hash_seq_search only guarantees to still work after the *current*
3759  * entry is removed, it's unsafe to continue the hashtable scan afterward.
3760  * We handle this by restarting the scan from scratch after each access.
3761  * This is theoretically O(N^2), but the number of entries that actually
3762  * need to be fixed is small enough that it doesn't matter.
3763  */
3764  hash_seq_init(&status, RelationIdCache);
3765 
3766  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3767  {
3768  Relation relation = idhentry->reldesc;
3769  bool restart = false;
3770 
3771  /*
3772  * Make sure *this* entry doesn't get flushed while we work with it.
3773  */
3775 
3776  /*
3777  * If it's a faked-up entry, read the real pg_class tuple.
3778  */
3779  if (relation->rd_rel->relowner == InvalidOid)
3780  {
3781  HeapTuple htup;
3782  Form_pg_class relp;
3783 
3784  htup = SearchSysCache1(RELOID,
3785  ObjectIdGetDatum(RelationGetRelid(relation)));
3786  if (!HeapTupleIsValid(htup))
3787  elog(FATAL, "cache lookup failed for relation %u",
3788  RelationGetRelid(relation));
3789  relp = (Form_pg_class) GETSTRUCT(htup);
3790 
3791  /*
3792  * Copy tuple to relation->rd_rel. (See notes in
3793  * AllocateRelationDesc())
3794  */
3795  memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
3796 
3797  /* Update rd_options while we have the tuple */
3798  if (relation->rd_options)
3799  pfree(relation->rd_options);
3800  RelationParseRelOptions(relation, htup);
3801 
3802  /*
3803  * Check the values in rd_att were set up correctly. (We cannot
3804  * just copy them over now: formrdesc must have set up the rd_att
3805  * data correctly to start with, because it may already have been
3806  * copied into one or more catcache entries.)
3807  */
3808  Assert(relation->rd_att->tdtypeid == relp->reltype);
3809  Assert(relation->rd_att->tdtypmod == -1);
3810  Assert(relation->rd_att->tdhasoid == relp->relhasoids);
3811 
3812  ReleaseSysCache(htup);
3813 
3814  /* relowner had better be OK now, else we'll loop forever */
3815  if (relation->rd_rel->relowner == InvalidOid)
3816  elog(ERROR, "invalid relowner in pg_class entry for \"%s\"",
3817  RelationGetRelationName(relation));
3818 
3819  restart = true;
3820  }
3821 
3822  /*
3823  * Fix data that isn't saved in relcache cache file.
3824  *
3825  * relhasrules or relhastriggers could possibly be wrong or out of
3826  * date. If we don't actually find any rules or triggers, clear the
3827  * local copy of the flag so that we don't get into an infinite loop
3828  * here. We don't make any attempt to fix the pg_class entry, though.
3829  */
3830  if (relation->rd_rel->relhasrules && relation->rd_rules == NULL)
3831  {
3832  RelationBuildRuleLock(relation);
3833  if (relation->rd_rules == NULL)
3834  relation->rd_rel->relhasrules = false;
3835  restart = true;
3836  }
3837  if (relation->rd_rel->relhastriggers && relation->trigdesc == NULL)
3838  {
3839  RelationBuildTriggers(relation);
3840  if (relation->trigdesc == NULL)
3841  relation->rd_rel->relhastriggers = false;
3842  restart = true;
3843  }
3844 
3845  /*
3846  * Re-load the row security policies if the relation has them, since
3847  * they are not preserved in the cache. Note that we can never NOT
3848  * have a policy while relrowsecurity is true,
3849  * RelationBuildRowSecurity will create a single default-deny policy
3850  * if there is no policy defined in pg_policy.
3851  */
3852  if (relation->rd_rel->relrowsecurity && relation->rd_rsdesc == NULL)
3853  {
3854  RelationBuildRowSecurity(relation);
3855 
3856  Assert(relation->rd_rsdesc != NULL);
3857  restart = true;
3858  }
3859 
3860  /*
3861  * Reload the partition key and descriptor for a partitioned table.
3862  */
3863  if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
3864  relation->rd_partkey == NULL)
3865  {
3866  RelationBuildPartitionKey(relation);
3867  Assert(relation->rd_partkey != NULL);
3868 
3869  restart = true;
3870  }
3871 
3872  if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
3873  relation->rd_partdesc == NULL)
3874  {
3875  RelationBuildPartitionDesc(relation);
3876  Assert(relation->rd_partdesc != NULL);
3877 
3878  restart = true;
3879  }
3880 
3881  /* Release hold on the relation */
3883 
3884  /* Now, restart the hashtable scan if needed */
3885  if (restart)
3886  {
3887  hash_seq_term(&status);
3888  hash_seq_init(&status, RelationIdCache);
3889  }
3890  }
3891 
3892  /*
3893  * Lastly, write out new relcache cache files if needed. We don't bother
3894  * to distinguish cases where only one of the two needs an update.
3895  */
3896  if (needNewCacheFile)
3897  {
3898  /*
3899  * Force all the catcaches to finish initializing and thereby open the
3900  * catalogs and indexes they use. This will preload the relcache with
3901  * entries for all the most important system catalogs and indexes, so
3902  * that the init files will be most useful for future backends.
3903  */
3905 
3906  /* now write the files */
3908  write_relcache_init_file(false);
3909  }
3910 }
#define Natts_pg_class
Definition: pg_class.h:102
#define AttributeRelidNumIndexId
Definition: indexing.h:94
struct PartitionDescData * rd_partdesc
Definition: rel.h:131
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5361
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, bool hasoids, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1887
Oid tdtypeid
Definition: tupdesc.h:77
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define IndexRelidIndexId
Definition: indexing.h:164
bool tdhasoid
Definition: tupdesc.h:79
#define RewriteRelRulenameIndexId
Definition: indexing.h:223
void RelationBuildRowSecurity(Relation relation)
Definition: policy.c:191
#define AuthMemRelationId
#define IndexRelationId
Definition: pg_index.h:29
#define DatabaseRelationId
Definition: pg_database.h:29
#define RelationRelationId
Definition: pg_class.h:29
Relation reldesc
Definition: relcache.c:120
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define OperatorClassRelationId
Definition: pg_opclass.h:49
#define AttributeRelationId
Definition: pg_attribute.h:33
bool criticalSharedRelcachesBuilt
Definition: relcache.c:135
#define AuthIdOidIndexId
Definition: indexing.h:99
static HTAB * RelationIdCache
Definition: relcache.c:123
Form_pg_class rd_rel
Definition: rel.h:114
static void RelationBuildPartitionKey(Relation relation)
Definition: relcache.c:827
void RelationBuildPartitionDesc(Relation rel)
Definition: partition.c:159
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
int32 tdtypmod
Definition: tupdesc.h:78
#define AuthIdRelationId
Definition: pg_authid.h:42
#define TriggerRelidNameIndexId
Definition: indexing.h:249
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2136
void pfree(void *pointer)
Definition: mcxt.c:950
#define Natts_pg_proc
Definition: pg_proc.h:89
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ProcedureRelation_Rowtype_Id
Definition: pg_proc.h:34
#define FATAL
Definition: elog.h:52
static void write_relcache_init_file(bool shared)
Definition: relcache.c:5743
struct PartitionKeyData * rd_partkey
Definition: rel.h:129
TriggerDesc * trigdesc
Definition: rel.h:120
static void RelationParseRelOptions(Relation relation, HeapTuple tuple)
Definition: relcache.c:435
static void load_critical_index(Oid indexoid, Oid heapoid)
Definition: relcache.c:3919
static const FormData_pg_attribute Desc_pg_proc[Natts_pg_proc]
Definition: relcache.c:102
#define RelationGetRelationName(relation)
Definition: rel.h:437
#define DatabaseOidIndexId
Definition: indexing.h:142
#define ClassOidIndexId
Definition: indexing.h:112
struct RowSecurityDesc * rd_rsdesc
Definition: rel.h:122
#define SharedSecLabelRelationId
Definition: pg_shseclabel.h:21
#define AccessMethodProcedureIndexId
Definition: indexing.h:82
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2123
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
TupleDesc rd_att
Definition: rel.h:115
#define OpclassOidIndexId
Definition: indexing.h:200
#define InvalidOid
Definition: postgres_ext.h:36
#define RewriteRelationId
Definition: pg_rewrite.h:32
#define CLASS_TUPLE_SIZE
Definition: pg_class.h:87
#define Natts_pg_type
Definition: pg_type.h:239
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define TriggerRelationId
Definition: pg_trigger.h:34
#define AuthMemMemRoleIndexId
Definition: indexing.h:104
RuleLock * rd_rules
Definition: rel.h:118
#define AttributeRelation_Rowtype_Id
Definition: pg_attribute.h:34
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1351
#define DatabaseNameIndexId
Definition: indexing.h:140
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1341
#define RelationRelation_Rowtype_Id
Definition: pg_class.h:30
#define SharedSecLabelObjectIndexId
Definition: indexing.h:316
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:365
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
void RelationBuildTriggers(Relation relation)
Definition: trigger.c:1624
#define TypeRelation_Rowtype_Id
Definition: pg_type.h:35
static const FormData_pg_attribute Desc_pg_class[Natts_pg_class]
Definition: relcache.c:100
void RelationMapInitializePhase3(void)
Definition: relmapper.c:603
static void RelationBuildRuleLock(Relation relation)
Definition: relcache.c:659
#define Natts_pg_attribute
Definition: pg_attribute.h:194
#define elog
Definition: elog.h:219
bool criticalRelcachesBuilt
Definition: relcache.c:129
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224
#define AuthIdRolnameIndexId
Definition: indexing.h:97
void InitCatalogCachePhase2(void)
Definition: syscache.c:1071
#define AccessMethodProcedureRelationId
Definition: pg_amproc.h:43
#define RelationGetRelid(relation)
Definition: rel.h:417
static const FormData_pg_attribute Desc_pg_type[Natts_pg_type]
Definition: relcache.c:103
bytea * rd_options
Definition: rel.h:156
void hash_seq_term(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1427
static const FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute]
Definition: relcache.c:101
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void RelationCacheInvalidate ( void  )

Definition at line 2756 of file relcache.c.

References Assert, ClassOidIndexId, hash_seq_init(), hash_seq_search(), InvalidSubTransactionId, lappend(), lcons(), lfirst, list_free(), NIL, NULL, RelationData::rd_createSubid, RelationData::rd_isnailed, RelationData::rd_newRelfilenodeSubid, RelationClearRelation(), RelationCloseSmgr, RelationGetRelid, RelationHasReferenceCountZero, RelationInitPhysicalAddr(), RelationIsMapped, RelationMapInvalidateAll(), RelationRelationId, relcacheInvalsReceived, relidcacheent::reldesc, smgrcloseall(), and status().

Referenced by InvalidateSystemCaches(), and LocalExecuteInvalidationMessage().

2757 {
2759  RelIdCacheEnt *idhentry;
2760  Relation relation;
2761  List *rebuildFirstList = NIL;
2762  List *rebuildList = NIL;
2763  ListCell *l;
2764 
2765  /*
2766  * Reload relation mapping data before starting to reconstruct cache.
2767  */
2769 
2770  /* Phase 1 */
2771  hash_seq_init(&status, RelationIdCache);
2772 
2773  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2774  {
2775  relation = idhentry->reldesc;
2776 
2777  /* Must close all smgr references to avoid leaving dangling ptrs */
2778  RelationCloseSmgr(relation);
2779 
2780  /*
2781  * Ignore new relations; no other backend will manipulate them before
2782  * we commit. Likewise, before replacing a relation's relfilenode, we
2783  * shall have acquired AccessExclusiveLock and drained any applicable
2784  * pending invalidations.
2785  */
2786  if (relation->rd_createSubid != InvalidSubTransactionId ||
2788  continue;
2789 
2791 
2792  if (RelationHasReferenceCountZero(relation))
2793  {
2794  /* Delete this entry immediately */
2795  Assert(!relation->rd_isnailed);
2796  RelationClearRelation(relation, false);
2797  }
2798  else
2799  {
2800  /*
2801  * If it's a mapped relation, immediately update its rd_node in
2802  * case its relfilenode changed. We must do this during phase 1
2803  * in case the relation is consulted during rebuild of other
2804  * relcache entries in phase 2. It's safe since consulting the
2805  * map doesn't involve any access to relcache entries.
2806  */
2807  if (RelationIsMapped(relation))
2808  RelationInitPhysicalAddr(relation);
2809 
2810  /*
2811  * Add this entry to list of stuff to rebuild in second pass.
2812  * pg_class goes to the front of rebuildFirstList while
2813  * pg_class_oid_index goes to the back of rebuildFirstList, so
2814  * they are done first and second respectively. Other nailed
2815  * relations go to the front of rebuildList, so they'll be done
2816  * next in no particular order; and everything else goes to the
2817  * back of rebuildList.
2818  */
2819  if (RelationGetRelid(relation) == RelationRelationId)
2820  rebuildFirstList = lcons(relation, rebuildFirstList);
2821  else if (RelationGetRelid(relation) == ClassOidIndexId)
2822  rebuildFirstList = lappend(rebuildFirstList, relation);
2823  else if (relation->rd_isnailed)
2824  rebuildList = lcons(relation, rebuildList);
2825  else
2826  rebuildList = lappend(rebuildList, relation);
2827  }
2828  }
2829 
2830  /*
2831  * Now zap any remaining smgr cache entries. This must happen before we
2832  * start to rebuild entries, since that may involve catalog fetches which
2833  * will re-open catalog files.
2834  */
2835  smgrcloseall();
2836 
2837  /* Phase 2: rebuild the items found to need rebuild in phase 1 */
2838  foreach(l, rebuildFirstList)
2839  {
2840  relation = (Relation) lfirst(l);
2841  RelationClearRelation(relation, true);
2842  }
2843  list_free(rebuildFirstList);
2844  foreach(l, rebuildList)
2845  {
2846  relation = (Relation) lfirst(l);
2847  RelationClearRelation(relation, true);
2848  }
2849  list_free(rebuildList);
2850 }
#define NIL
Definition: pg_list.h:69
static long relcacheInvalsReceived
Definition: relcache.c:143
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2388
#define RelationRelationId
Definition: pg_class.h:29
bool rd_isnailed
Definition: rel.h:91
Relation reldesc
Definition: relcache.c:120
#define RelationCloseSmgr(relation)
Definition: rel.h:473
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:111
static HTAB * RelationIdCache
Definition: relcache.c:123
void smgrcloseall(void)
Definition: smgr.c:326
struct RelationData * Relation
Definition: relcache.h:21
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1418
#define ClassOidIndexId
Definition: indexing.h:112
List * lappend(List *list, void *datum)
Definition: list.c:128
#define RelationIsMapped(relation)
Definition: rel.h:454
SubTransactionId rd_createSubid
Definition: rel.h:110
List * lcons(void *datum, List *list)
Definition: list.c:259
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
#define InvalidSubTransactionId
Definition: c.h:403
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1351
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1341
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:401
void list_free(List *list)
Definition: list.c:1133
void RelationMapInvalidateAll(void)
Definition: relmapper.c:409
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:417
void RelationCacheInvalidateEntry ( Oid  relationId)

Definition at line 2712 of file relcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

2713 {
2714  Relation relation;
2715 
2716  RelationIdCacheLookup(relationId, relation);
2717 
2718  if (PointerIsValid(relation))
2719  {
2721  RelationFlushRelation(relation);
2722  }
2723 }
static long relcacheInvalsReceived
Definition: relcache.c:143
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:202
static void RelationFlushRelation(Relation relation)
Definition: relcache.c:2644
#define PointerIsValid(pointer)
Definition: c.h:526
void RelationClose ( Relation  relation)

Definition at line 2156 of file relcache.c.

References InvalidSubTransactionId, RelationData::rd_createSubid, RelationData::rd_newRelfilenodeSubid, RelationClearRelation(), RelationDecrementReferenceCount(), and RelationHasReferenceCountZero.

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

2157 {
2158  /* Note: no locking manipulations needed */
2160 
2161 #ifdef RELCACHE_FORCE_RELEASE
2162  if (RelationHasReferenceCountZero(relation) &&
2163  relation->rd_createSubid == InvalidSubTransactionId &&
2165  RelationClearRelation(relation, false);
2166 #endif
2167 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2388
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:111
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2136
SubTransactionId rd_createSubid
Definition: rel.h:110
#define InvalidSubTransactionId
Definition: c.h:403
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:401
void RelationCloseSmgrByOid ( Oid  relationId)

Definition at line 2859 of file relcache.c.

References PointerIsValid, RelationCloseSmgr, and RelationIdCacheLookup.

Referenced by swap_relation_files().

2860 {
2861  Relation relation;
2862 
2863  RelationIdCacheLookup(relationId, relation);
2864 
2865  if (!PointerIsValid(relation))
2866  return; /* not in cache, nothing to do */
2867 
2868  RelationCloseSmgr(relation);
2869 }
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:202
#define RelationCloseSmgr(relation)
Definition: rel.h:473
#define PointerIsValid(pointer)
Definition: c.h:526
void RelationForgetRelation ( Oid  rid)

Definition at line 2680 of file relcache.c.

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

Referenced by heap_drop_with_catalog(), and index_drop().

2681 {
2682  Relation relation;
2683 
2684  RelationIdCacheLookup(rid, relation);
2685 
2686  if (!PointerIsValid(relation))
2687  return; /* not in cache, nothing to do */
2688 
2689  if (!RelationHasReferenceCountZero(relation))
2690  elog(ERROR, "relation %u is still open", rid);
2691 
2692  /* Unconditionally destroy the relcache entry */
2693  RelationClearRelation(relation, false);
2694 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2388
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:202
#define ERROR
Definition: elog.h:43
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:401
#define elog
Definition: elog.h:219
#define PointerIsValid(pointer)
Definition: c.h:526
void RelationGetExclusionInfo ( Relation  indexRelation,
Oid **  operators,
Oid **  procs,
uint16 **  strategies 
)

Definition at line 5054 of file relcache.c.

References AccessShareLock, Anum_pg_constraint_conexclop, Anum_pg_constraint_conrelid, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, BTEqualStrategyNumber, CONSTRAINT_EXCLUSION, ConstraintRelationId, ConstraintRelidIndexId, DatumGetArrayTypeP, elog, ERROR, fastgetattr, get_op_opfamily_strategy(), get_opcode(), GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, i, InvalidStrategy, MemoryContextSwitchTo(), NULL, ObjectIdGetDatum, OIDOID, palloc(), RelationData::rd_att, RelationData::rd_exclops, RelationData::rd_exclprocs, RelationData::rd_exclstrats, RelationData::rd_index, RelationData::rd_indexcxt, RelationData::rd_opfamily, RelationData::rd_rel, RelationGetRelationName, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), and val.

Referenced by BuildIndexInfo(), and CheckIndexCompatible().

5058 {
5059  int ncols = indexRelation->rd_rel->relnatts;
5060  Oid *ops;
5061  Oid *funcs;
5062  uint16 *strats;
5063  Relation conrel;
5064  SysScanDesc conscan;
5065  ScanKeyData skey[1];
5066  HeapTuple htup;
5067  bool found;
5068  MemoryContext oldcxt;
5069  int i;
5070 
5071  /* Allocate result space in caller context */
5072  *operators = ops = (Oid *) palloc(sizeof(Oid) * ncols);
5073  *procs = funcs = (Oid *) palloc(sizeof(Oid) * ncols);
5074  *strategies = strats = (uint16 *) palloc(sizeof(uint16) * ncols);
5075 
5076  /* Quick exit if we have the data cached already */
5077  if (indexRelation->rd_exclstrats != NULL)
5078  {
5079  memcpy(ops, indexRelation->rd_exclops, sizeof(Oid) * ncols);
5080  memcpy(funcs, indexRelation->rd_exclprocs, sizeof(Oid) * ncols);
5081  memcpy(strats, indexRelation->rd_exclstrats, sizeof(uint16) * ncols);
5082  return;
5083  }
5084 
5085  /*
5086  * Search pg_constraint for the constraint associated with the index. To
5087  * make this not too painfully slow, we use the index on conrelid; that
5088  * will hold the parent relation's OID not the index's own OID.
5089  */
5090  ScanKeyInit(&skey[0],
5092  BTEqualStrategyNumber, F_OIDEQ,
5093  ObjectIdGetDatum(indexRelation->rd_index->indrelid));
5094 
5096  conscan = systable_beginscan(conrel, ConstraintRelidIndexId, true,
5097  NULL, 1, skey);
5098  found = false;
5099 
5100  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
5101  {
5103  Datum val;
5104  bool isnull;
5105  ArrayType *arr;
5106  int nelem;
5107 
5108  /* We want the exclusion constraint owning the index */
5109  if (conform->contype != CONSTRAINT_EXCLUSION ||
5110  conform->conindid != RelationGetRelid(indexRelation))
5111  continue;
5112 
5113  /* There should be only one */
5114  if (found)
5115  elog(ERROR, "unexpected exclusion constraint record found for rel %s",
5116  RelationGetRelationName(indexRelation));
5117  found = true;
5118 
5119  /* Extract the operator OIDS from conexclop */
5120  val = fastgetattr(htup,
5122  conrel->rd_att, &isnull);
5123  if (isnull)
5124  elog(ERROR, "null conexclop for rel %s",
5125  RelationGetRelationName(indexRelation));
5126 
5127  arr = DatumGetArrayTypeP(val); /* ensure not toasted */
5128  nelem = ARR_DIMS(arr)[0];
5129  if (ARR_NDIM(arr) != 1 ||
5130  nelem != ncols ||
5131  ARR_HASNULL(arr) ||
5132  ARR_ELEMTYPE(arr) != OIDOID)
5133  elog(ERROR, "conexclop is not a 1-D Oid array");
5134 
5135  memcpy(ops, ARR_DATA_PTR(arr), sizeof(Oid) * ncols);
5136  }
5137 
5138  systable_endscan(conscan);
5139  heap_close(conrel, AccessShareLock);
5140 
5141  if (!found)
5142  elog(ERROR, "exclusion constraint record missing for rel %s",
5143  RelationGetRelationName(indexRelation));
5144 
5145  /* We need the func OIDs and strategy numbers too */
5146  for (i = 0; i < ncols; i++)
5147  {
5148  funcs[i] = get_opcode(ops[i]);
5149  strats[i] = get_op_opfamily_strategy(ops[i],
5150  indexRelation->rd_opfamily[i]);
5151  /* shouldn't fail, since it was checked at index creation */
5152  if (strats[i] == InvalidStrategy)
5153  elog(ERROR, "could not find strategy for operator %u in family %u",
5154  ops[i], indexRelation->rd_opfamily[i]);
5155  }
5156 
5157  /* Save a copy of the results in the relcache entry. */
5158  oldcxt = MemoryContextSwitchTo(indexRelation->rd_indexcxt);
5159  indexRelation->rd_exclops = (Oid *) palloc(sizeof(Oid) * ncols);
5160  indexRelation->rd_exclprocs = (Oid *) palloc(sizeof(Oid) * ncols);
5161  indexRelation->rd_exclstrats = (uint16 *) palloc(sizeof(uint16) * ncols);
5162  memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * ncols);
5163  memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * ncols);
5164  memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * ncols);
5165  MemoryContextSwitchTo(oldcxt);
5166 }
#define InvalidStrategy
Definition: stratnum.h:24
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:719
#define OIDOID
Definition: pg_type.h:328
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
uint16 * rd_exclstrats
Definition: rel.h:191
#define AccessShareLock
Definition: lockdefs.h:36
#define CONSTRAINT_EXCLUSION
#define heap_close(r, l)
Definition: heapam.h:97
Oid * rd_exclprocs
Definition: rel.h:190
Form_pg_class rd_rel
Definition: rel.h:114
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:328
Form_pg_index rd_index
Definition: rel.h:159
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
unsigned short uint16
Definition: c.h:267
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:275
#define ARR_DATA_PTR(a)
Definition: array.h:303
#define RelationGetRelationName(relation)
Definition: rel.h:437
#define ARR_HASNULL(a)
Definition: array.h:272
Oid * rd_opfamily
Definition: rel.h:182
Oid * rd_exclops
Definition: rel.h:189
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
TupleDesc rd_att
Definition: rel.h:115
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1094
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define ARR_NDIM(a)
Definition: array.h:271
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition: lsyscache.c:80
void * palloc(Size size)
Definition: mcxt.c:849
MemoryContext rd_indexcxt
Definition: rel.h:179
int i
#define Anum_pg_constraint_conrelid
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define ConstraintRelationId
Definition: pg_constraint.h:29
#define elog
Definition: elog.h:219
#define ARR_ELEMTYPE(a)
Definition: array.h:273
#define RelationGetRelid(relation)
Definition: rel.h:417
long val
Definition: informix.c:689
#define Anum_pg_constraint_conexclop
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define ConstraintRelidIndexId
Definition: indexing.h:126
#define DatumGetArrayTypeP(X)
Definition: array.h:242
List* RelationGetFKeyList ( Relation  relation)

Definition at line 4182 of file relcache.c.

References AccessShareLock, Anum_pg_constraint_confkey, Anum_pg_constraint_conkey, Anum_pg_constraint_conpfeqop, Anum_pg_constraint_conrelid, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, BTEqualStrategyNumber, CacheMemoryContext, ForeignKeyCacheInfo::confkey, ForeignKeyCacheInfo::confrelid, ForeignKeyCacheInfo::conkey, ForeignKeyCacheInfo::conpfeqop, ForeignKeyCacheInfo::conrelid, CONSTRAINT_FOREIGN, ConstraintRelationId, ConstraintRelidIndexId, copyObject, DatumGetArrayTypeP, elog, ERROR, fastgetattr, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, INDEX_MAX_KEYS, INT2OID, lappend(), list_free_deep(), makeNode, MemoryContextSwitchTo(), NIL, ForeignKeyCacheInfo::nkeys, NULL, ObjectIdGetDatum, OIDOID, RelationData::rd_att, RelationData::rd_fkeylist, RelationData::rd_fkeyvalid, RelationData::rd_rel, RelationGetRelationName, RelationGetRelid, result, ScanKeyInit(), systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by get_relation_foreign_keys().

4183 {
4184  List *result;
4185  Relation conrel;
4186  SysScanDesc conscan;
4187  ScanKeyData skey;
4188  HeapTuple htup;
4189  List *oldlist;
4190  MemoryContext oldcxt;
4191 
4192  /* Quick exit if we already computed the list. */
4193  if (relation->rd_fkeyvalid)
4194  return relation->rd_fkeylist;
4195 
4196  /* Fast path: if it doesn't have any triggers, it can't have FKs */
4197  if (!relation->rd_rel->relhastriggers)
4198  return NIL;
4199 
4200  /*
4201  * We build the list we intend to return (in the caller's context) while
4202  * doing the scan. After successfully completing the scan, we copy that
4203  * list into the relcache entry. This avoids cache-context memory leakage
4204  * if we get some sort of error partway through.
4205  */
4206  result = NIL;
4207 
4208  /* Prepare to scan pg_constraint for entries having conrelid = this rel. */
4209  ScanKeyInit(&skey,
4211  BTEqualStrategyNumber, F_OIDEQ,
4212  ObjectIdGetDatum(RelationGetRelid(relation)));
4213 
4215  conscan = systable_beginscan(conrel, ConstraintRelidIndexId, true,
4216  NULL, 1, &skey);
4217 
4218  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4219  {
4220  Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(htup);
4221  ForeignKeyCacheInfo *info;
4222  Datum adatum;
4223  bool isnull;
4224  ArrayType *arr;
4225  int nelem;
4226 
4227  /* consider only foreign keys */
4228  if (constraint->contype != CONSTRAINT_FOREIGN)
4229  continue;
4230 
4231  info = makeNode(ForeignKeyCacheInfo);
4232  info->conrelid = constraint->conrelid;
4233  info->confrelid = constraint->confrelid;
4234 
4235  /* Extract data from conkey field */
4236  adatum = fastgetattr(htup, Anum_pg_constraint_conkey,
4237  conrel->rd_att, &isnull);
4238  if (isnull)
4239  elog(ERROR, "null conkey for rel %s",
4240  RelationGetRelationName(relation));
4241 
4242  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
4243  nelem = ARR_DIMS(arr)[0];
4244  if (ARR_NDIM(arr) != 1 ||
4245  nelem < 1 ||
4246  nelem > INDEX_MAX_KEYS ||
4247  ARR_HASNULL(arr) ||
4248  ARR_ELEMTYPE(arr) != INT2OID)
4249  elog(ERROR, "conkey is not a 1-D smallint array");
4250 
4251  info->nkeys = nelem;
4252  memcpy(info->conkey, ARR_DATA_PTR(arr), nelem * sizeof(AttrNumber));
4253 
4254  /* Likewise for confkey */
4255  adatum = fastgetattr(htup, Anum_pg_constraint_confkey,
4256  conrel->rd_att, &isnull);
4257  if (isnull)
4258  elog(ERROR, "null confkey for rel %s",
4259  RelationGetRelationName(relation));
4260 
4261  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
4262  nelem = ARR_DIMS(arr)[0];
4263  if (ARR_NDIM(arr) != 1 ||
4264  nelem != info->nkeys ||
4265  ARR_HASNULL(arr) ||
4266  ARR_ELEMTYPE(arr) != INT2OID)
4267  elog(ERROR, "confkey is not a 1-D smallint array");
4268 
4269  memcpy(info->confkey, ARR_DATA_PTR(arr), nelem * sizeof(AttrNumber));
4270 
4271  /* Likewise for conpfeqop */
4273  conrel->rd_att, &isnull);
4274  if (isnull)
4275  elog(ERROR, "null conpfeqop for rel %s",
4276  RelationGetRelationName(relation));
4277 
4278  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
4279  nelem = ARR_DIMS(arr)[0];
4280  if (ARR_NDIM(arr) != 1 ||
4281  nelem != info->nkeys ||
4282  ARR_HASNULL(arr) ||
4283  ARR_ELEMTYPE(arr) != OIDOID)
4284  elog(ERROR, "conpfeqop is not a 1-D OID array");
4285 
4286  memcpy(info->conpfeqop, ARR_DATA_PTR(arr), nelem * sizeof(Oid));
4287 
4288  /* Add FK's node to the result list */
4289  result = lappend(result, info);
4290  }
4291 
4292  systable_endscan(conscan);
4293  heap_close(conrel, AccessShareLock);
4294 
4295  /* Now save a copy of the completed list in the relcache entry. */
4297  oldlist = relation->rd_fkeylist;
4298  relation->rd_fkeylist = copyObject(result);
4299  relation->rd_fkeyvalid = true;
4300  MemoryContextSwitchTo(oldcxt);
4301 
4302  /* Don't leak the old list, if there is one */
4303  list_free_deep(oldlist);
4304 
4305  return result;
4306 }
#define NIL
Definition: pg_list.h:69
#define CONSTRAINT_FOREIGN
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define Anum_pg_constraint_confkey
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:719
#define OIDOID
Definition: pg_type.h:328
AttrNumber conkey[INDEX_MAX_KEYS]
Definition: rel.h:243
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
List * rd_fkeylist
Definition: rel.h:125
return result
Definition: formatting.c:1632
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
void list_free_deep(List *list)
Definition: list.c:1147
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:275
#define INT2OID
Definition: pg_type.h:308
#define ARR_DATA_PTR(a)
Definition: array.h:303
#define RelationGetRelationName(relation)
Definition: rel.h:437
#define ARR_HASNULL(a)
Definition: array.h:272
#define Anum_pg_constraint_conkey
List * lappend(List *list, void *datum)
Definition: list.c:128
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
TupleDesc rd_att
Definition: rel.h:115
#define makeNode(_type_)
Definition: nodes.h:557
Oid conpfeqop[INDEX_MAX_KEYS]
Definition: rel.h:245
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define Anum_pg_constraint_conpfeqop
#define INDEX_MAX_KEYS
#define ARR_NDIM(a)
Definition: array.h:271
AttrNumber confkey[INDEX_MAX_KEYS]
Definition: rel.h:244
#define Anum_pg_constraint_conrelid
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define ConstraintRelationId
Definition: pg_constraint.h:29
#define elog
Definition: elog.h:219
#define copyObject(obj)
Definition: nodes.h:621
Definition: pg_list.h:45
bool rd_fkeyvalid
Definition: rel.h:126
#define ARR_ELEMTYPE(a)
Definition: array.h:273
int16 AttrNumber
Definition: attnum.h:21
#define RelationGetRelid(relation)
Definition: rel.h:417
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define ConstraintRelidIndexId
Definition: indexing.h:126
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
#define DatumGetArrayTypeP(X)
Definition: array.h:242
Bitmapset* RelationGetIndexAttrBitmap ( Relation  relation,
IndexAttrBitmapKind  keyAttrs 
)

Definition at line 4847 of file relcache.c.

References AccessShareLock, bms_add_member(), bms_copy(), bms_free(), BuildIndexInfo(), CacheMemoryContext, elog, equal(), ERROR, FirstLowInvalidHeapAttributeNumber, i, IndexInfo::ii_Expressions, IndexInfo::ii_KeyAttrNumbers, IndexInfo::ii_NumIndexAttrs, IndexInfo::ii_Predicate, IndexInfo::ii_Unique, 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, NULL, pull_varattnos(), RelationData::rd_idattr, RelationData::rd_indexattr, RelationData::rd_keyattr, RelationData::rd_pkattr, RelationData::rd_pkindex, RelationData::rd_replidindex, RelationGetForm, and RelationGetIndexList().

Referenced by ExecUpdateLockMode(), heap_update(), logicalrep_rel_open(), logicalrep_write_attrs(), and reindex_relation().

4848 {
4849  Bitmapset *indexattrs; /* indexed columns */
4850  Bitmapset *uindexattrs; /* columns in unique indexes */
4851  Bitmapset *pkindexattrs; /* columns in the primary index */
4852  Bitmapset *idindexattrs; /* columns in the replica identity */
4853  List *indexoidlist;
4854  List *newindexoidlist;
4855  Oid relpkindex;
4856  Oid relreplindex;
4857  ListCell *l;
4858  MemoryContext oldcxt;
4859 
4860  /* Quick exit if we already computed the result. */
4861  if (relation->rd_indexattr != NULL)
4862  {
4863  switch (attrKind)
4864  {
4865  case INDEX_ATTR_BITMAP_ALL:
4866  return bms_copy(relation->rd_indexattr);
4867  case INDEX_ATTR_BITMAP_KEY:
4868  return bms_copy(relation->rd_keyattr);
4870  return bms_copy(relation->rd_pkattr);
4872  return bms_copy(relation->rd_idattr);
4873  default:
4874  elog(ERROR, "unknown attrKind %u", attrKind);
4875  }
4876  }
4877 
4878  /* Fast path if definitely no indexes */
4879  if (!RelationGetForm(relation)->relhasindex)
4880  return NULL;
4881 
4882  /*
4883  * Get cached list of index OIDs. If we have to start over, we do so here.
4884  */
4885 restart:
4886  indexoidlist = RelationGetIndexList(relation);
4887 
4888  /* Fall out if no indexes (but relhasindex was set) */
4889  if (indexoidlist == NIL)
4890  return NULL;
4891 
4892  /*
4893  * Copy the rd_pkindex and rd_replidindex values computed by
4894  * RelationGetIndexList before proceeding. This is needed because a
4895  * relcache flush could occur inside index_open below, resetting the
4896  * fields managed by RelationGetIndexList. We need to do the work with
4897  * stable values of these fields.
4898  */
4899  relpkindex = relation->rd_pkindex;
4900  relreplindex = relation->rd_replidindex;
4901 
4902  /*
4903  * For each index, add referenced attributes to indexattrs.
4904  *
4905  * Note: we consider all indexes returned by RelationGetIndexList, even if
4906  * they are not indisready or indisvalid. This is important because an
4907  * index for which CREATE INDEX CONCURRENTLY has just started must be
4908  * included in HOT-safety decisions (see README.HOT). If a DROP INDEX
4909  * CONCURRENTLY is far enough along that we should ignore the index, it
4910  * won't be returned at all by RelationGetIndexList.
4911  */
4912  indexattrs = NULL;
4913  uindexattrs = NULL;
4914  pkindexattrs = NULL;
4915  idindexattrs = NULL;
4916  foreach(l, indexoidlist)
4917  {
4918  Oid indexOid = lfirst_oid(l);
4919  Relation indexDesc;
4920  IndexInfo *indexInfo;
4921  int i;
4922  bool isKey; /* candidate key */
4923  bool isPK; /* primary key */
4924  bool isIDKey; /* replica identity index */
4925 
4926  indexDesc = index_open(indexOid, AccessShareLock);
4927 
4928  /* Extract index key information from the index's pg_index row */
4929  indexInfo = BuildIndexInfo(indexDesc);
4930 
4931  /* Can this index be referenced by a foreign key? */
4932  isKey = indexInfo->ii_Unique &&
4933  indexInfo->ii_Expressions == NIL &&
4934  indexInfo->ii_Predicate == NIL;
4935 
4936  /* Is this a primary key? */
4937  isPK = (indexOid == relpkindex);
4938 
4939  /* Is this index the configured (or default) replica identity? */
4940  isIDKey = (indexOid == relreplindex);
4941 
4942  /* Collect simple attribute references */
4943  for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
4944  {
4945  int attrnum = indexInfo->ii_KeyAttrNumbers[i];
4946 
4947  if (attrnum != 0)
4948  {
4949  indexattrs = bms_add_member(indexattrs,
4951 
4952  if (isKey)
4953  uindexattrs = bms_add_member(uindexattrs,
4955 
4956  if (isPK)
4957  pkindexattrs = bms_add_member(pkindexattrs,
4959 
4960  if (isIDKey)
4961  idindexattrs = bms_add_member(idindexattrs,
4963  }
4964  }
4965 
4966  /* Collect all attributes used in expressions, too */
4967  pull_varattnos((Node *) indexInfo->ii_Expressions, 1, &indexattrs);
4968 
4969  /* Collect all attributes in the index predicate, too */
4970  pull_varattnos((Node *) indexInfo->ii_Predicate, 1, &indexattrs);
4971 
4972  index_close(indexDesc, AccessShareLock);
4973  }
4974 
4975  /*
4976  * During one of the index_opens in the above loop, we might have received
4977  * a relcache flush event on this relcache entry, which might have been
4978  * signaling a change in the rel's index list. If so, we'd better start
4979  * over to ensure we deliver up-to-date attribute bitmaps.
4980  */
4981  newindexoidlist = RelationGetIndexList(relation);
4982  if (equal(indexoidlist, newindexoidlist) &&
4983  relpkindex == relation->rd_pkindex &&
4984  relreplindex == relation->rd_replidindex)
4985  {
4986  /* Still the same index set, so proceed */
4987  list_free(newindexoidlist);
4988  list_free(indexoidlist);
4989  }
4990  else
4991  {
4992  /* Gotta do it over ... might as well not leak memory */
4993  list_free(newindexoidlist);
4994  list_free(indexoidlist);
4995  bms_free(uindexattrs);
4996  bms_free(pkindexattrs);
4997  bms_free(idindexattrs);
4998  bms_free(indexattrs);
4999 
5000  goto restart;
5001  }
5002 
5003  /* Don't leak the old values of these bitmaps, if any */
5004  bms_free(relation->rd_indexattr);
5005  relation->rd_indexattr = NULL;
5006  bms_free(relation->rd_keyattr);
5007  relation->rd_keyattr = NULL;
5008  bms_free(relation->rd_pkattr);
5009  relation->rd_pkattr = NULL;
5010  bms_free(relation->rd_idattr);
5011  relation->rd_idattr = NULL;
5012 
5013  /*
5014  * Now save copies of the bitmaps in the relcache entry. We intentionally
5015  * set rd_indexattr last, because that's the one that signals validity of
5016  * the values; if we run out of memory before making that copy, we won't
5017  * leave the relcache entry looking like the other ones are valid but
5018  * empty.
5019  */
5021  relation->rd_keyattr = bms_copy(uindexattrs);
5022  relation->rd_pkattr = bms_copy(pkindexattrs);
5023  relation->rd_idattr = bms_copy(idindexattrs);
5024  relation->rd_indexattr = bms_copy(indexattrs);
5025  MemoryContextSwitchTo(oldcxt);
5026 
5027  /* We return our original working copy for caller to play with */
5028  switch (attrKind)
5029  {
5030  case INDEX_ATTR_BITMAP_ALL:
5031  return indexattrs;
5032  case INDEX_ATTR_BITMAP_KEY:
5033  return uindexattrs;
5035  return bms_copy(relation->rd_pkattr);
5037  return idindexattrs;
5038  default:
5039  elog(ERROR, "unknown attrKind %u", attrKind);
5040  return NULL;
5041  }
5042 }
#define NIL
Definition: pg_list.h:69
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:111
List * ii_Predicate
Definition: execnodes.h:138
Bitmapset * rd_keyattr
Definition: rel.h:145
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2962
Oid rd_replidindex
Definition: rel.h:138
#define RelationGetForm(relation)
Definition: rel.h:411
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:509
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
IndexInfo * BuildIndexInfo(Relation index)
Definition: index.c:1640
unsigned int Oid
Definition: postgres_ext.h:31
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition: var.c:219
#define ERROR
Definition: elog.h:43
Oid rd_pkindex
Definition: rel.h:137
int ii_NumIndexAttrs
Definition: execnodes.h:134
Bitmapset * rd_idattr
Definition: rel.h:147
bool ii_Unique
Definition: execnodes.h:146
void bms_free(Bitmapset *a)
Definition: bitmapset.c:201
#define NULL
Definition: c.h:229
List * ii_Expressions
Definition: execnodes.h:136
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS]
Definition: execnodes.h:135
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4345
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:176
Bitmapset * rd_pkattr
Definition: rel.h:146
void list_free(List *list)
Definition: list.c:1133
int i
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
Bitmapset * rd_indexattr
Definition: rel.h:144
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:151
#define lfirst_oid(lc)
Definition: pg_list.h:108
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
List* RelationGetIndexExpressions ( Relation  relation)

Definition at line 4701 of file relcache.c.

References Anum_pg_index_indexprs, Assert, canonicalize_qual(), copyObject, eval_const_expressions(), fix_opfuncids(), GetPgIndexDescriptor(), heap_attisnull(), heap_getattr, MemoryContextSwitchTo(), NIL, NULL, pfree(), RelationData::rd_indexcxt, RelationData::rd_indexprs, RelationData::rd_indextuple, result, stringToNode(), and TextDatumGetCString.

Referenced by ATExecReplicaIdentity(), BuildIndexInfo(), ExecRefreshMatView(), get_relation_info(), infer_arbiter_indexes(), refresh_by_match_merge(), and transformIndexConstraint().

4702 {
4703  List *result;
4704  Datum exprsDatum;
4705  bool isnull;
4706  char *exprsString;
4707  MemoryContext oldcxt;
4708 
4709  /* Quick exit if we already computed the result. */
4710  if (relation->rd_indexprs)
4711  return copyObject(relation->rd_indexprs);
4712 
4713  /* Quick exit if there is nothing to do. */
4714  if (relation->rd_indextuple == NULL ||
4716  return NIL;
4717 
4718  /*
4719  * We build the tree we intend to return in the caller's context. After
4720  * successfully completing the work, we copy it into the relcache entry.
4721  * This avoids problems if we get some sort of error partway through.
4722  */
4723  exprsDatum = heap_getattr(relation->rd_indextuple,
4726  &isnull);
4727  Assert(!isnull);
4728  exprsString = TextDatumGetCString(exprsDatum);
4729  result = (List *) stringToNode(exprsString);
4730  pfree(exprsString);
4731 
4732  /*
4733  * Run the expressions through eval_const_expressions. This is not just an
4734  * optimization, but is necessary, because the planner will be comparing
4735  * them to similarly-processed qual clauses, and may fail to detect valid
4736  * matches without this. We don't bother with canonicalize_qual, however.
4737  */
4738  result = (List *) eval_const_expressions(NULL, (Node *) result);
4739 
4740  result = (List *) canonicalize_qual((Expr *) result);
4741 
4742  /* May as well fix opfuncids too */
4743  fix_opfuncids((Node *) result);
4744 
4745  /* Now save a copy of the completed tree in the relcache entry. */
4746  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4747  relation->rd_indexprs = copyObject(result);
4748  MemoryContextSwitchTo(oldcxt);
4749 
4750  return result;
4751 }
#define NIL
Definition: pg_list.h:69
void * stringToNode(char *str)
Definition: read.c:38
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1604
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
List * rd_indexprs
Definition: rel.h:187
Definition: nodes.h:509
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2400
return result
Definition: formatting.c:1632
struct HeapTupleData * rd_indextuple
Definition: rel.h:161
void pfree(void *pointer)
Definition: mcxt.c:950
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:3998
bool heap_attisnull(HeapTuple tup, int attnum)
Definition: heaptuple.c:297
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:769
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
Expr * canonicalize_qual(Expr *qual)
Definition: prepqual.c:286
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
MemoryContext rd_indexcxt
Definition: rel.h:179
#define copyObject(obj)
Definition: nodes.h:621
Definition: pg_list.h:45
#define Anum_pg_index_indexprs
Definition: pg_index.h:91
List* RelationGetIndexList ( Relation  relation)

Definition at line 4345 of file relcache.c.

References AccessShareLock, Anum_pg_index_indclass, Anum_pg_index_indpred, Anum_pg_index_indrelid, Assert, BTEqualStrategyNumber, CacheMemoryContext, DatumGetPointer, GetPgIndexDescriptor(), GETSTRUCT, heap_attisnull(), heap_close, heap_getattr, heap_open(), HeapTupleIsValid, IndexIndrelidIndexId, IndexIsLive, IndexIsValid, IndexRelationId, insert_ordered_oid(), InvalidOid, list_copy(), list_free(), MemoryContextSwitchTo(), NIL, NULL, ObjectIdAttributeNumber, ObjectIdGetDatum, OID_BTREE_OPS_OID, OidIsValid, RelationData::rd_indexlist, RelationData::rd_indexvalid, RelationData::rd_oidindex, RelationData::rd_pkindex, RelationData::rd_rel, RelationData::rd_replidindex, RelationGetRelid, REPLICA_IDENTITY_DEFAULT, REPLICA_IDENTITY_INDEX, result, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), and oidvector::values.

Referenced by AlterIndexNamespaces(), ATExecChangeOwner(), ATExecDropNotNull(), ATExecSetTableSpace(), calculate_indexes_size(), calculate_toast_table_size(), cluster(), ExecOpenIndices(), ExecRefreshMatView(), get_relation_info(), infer_arbiter_indexes(), mark_index_clustered(), refresh_by_match_merge(), reindex_relation(), relation_mark_replica_identity(), RelationGetIndexAttrBitmap(), RelationGetOidIndex(), RelationGetPrimaryKeyIndex(), RelationGetReplicaIndex(), relationHasPrimaryKey(), RelationHasUnloggedIndex(), RelationTruncateIndexes(), toast_open_indexes(), transformFkeyCheckAttrs(), transformFkeyGetPrimaryKey(), transformTableLikeClause(), triggered_change_notification(), and vac_open_indexes().

4346 {
4347  Relation indrel;
4348  SysScanDesc indscan;
4349  ScanKeyData skey;
4350  HeapTuple htup;
4351  List *result;
4352  List *oldlist;
4353  char replident = relation->rd_rel->relreplident;
4354  Oid oidIndex = InvalidOid;
4355  Oid pkeyIndex = InvalidOid;
4356  Oid candidateIndex = InvalidOid;
4357  MemoryContext oldcxt;
4358 
4359  /* Quick exit if we already computed the list. */
4360  if (relation->rd_indexvalid != 0)
4361  return list_copy(relation->rd_indexlist);
4362 
4363  /*
4364  * We build the list we intend to return (in the caller's context) while
4365  * doing the scan. After successfully completing the scan, we copy that
4366  * list into the relcache entry. This avoids cache-context memory leakage
4367  * if we get some sort of error partway through.
4368  */
4369  result = NIL;
4370  oidIndex = InvalidOid;
4371 
4372  /* Prepare to scan pg_index for entries having indrelid = this rel. */
4373  ScanKeyInit(&skey,
4375  BTEqualStrategyNumber, F_OIDEQ,
4376  ObjectIdGetDatum(RelationGetRelid(relation)));
4377 
4379  indscan = systable_beginscan(indrel, IndexIndrelidIndexId, true,
4380  NULL, 1, &skey);
4381 
4382  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4383  {
4385  Datum indclassDatum;
4386  oidvector *indclass;
4387  bool isnull;
4388 
4389  /*
4390  * Ignore any indexes that are currently being dropped. This will
4391  * prevent them from being searched, inserted into, or considered in
4392  * HOT-safety decisions. It's unsafe to touch such an index at all
4393  * since its catalog entries could disappear at any instant.
4394  */
4395  if (!IndexIsLive(index))
4396  continue;
4397 
4398  /* Add index's OID to result list in the proper order */
4399  result = insert_ordered_oid(result, index->indexrelid);
4400 
4401  /*
4402  * indclass cannot be referenced directly through the C struct,
4403  * because it comes after the variable-width indkey field. Must
4404  * extract the datum the hard way...
4405  */
4406  indclassDatum = heap_getattr(htup,
4409  &isnull);
4410  Assert(!isnull);
4411  indclass = (oidvector *) DatumGetPointer(indclassDatum);
4412 
4413  /*
4414  * Invalid, non-unique, non-immediate or predicate indexes aren't
4415  * interesting for either oid indexes or replication identity indexes,
4416  * so don't check them.
4417  */
4418  if (!IndexIsValid(index) || !index->indisunique ||
4419  !index->indimmediate ||
4421  continue;
4422 
4423  /* Check to see if is a usable btree index on OID */
4424  if (index->indnatts == 1 &&
4425  index->indkey.values[0] == ObjectIdAttributeNumber &&
4426  indclass->values[0] == OID_BTREE_OPS_OID)
4427  oidIndex = index->indexrelid;
4428 
4429  /* remember primary key index if any */
4430  if (index->indisprimary)
4431  pkeyIndex = index->indexrelid;
4432 
4433  /* remember explicitly chosen replica index */
4434  if (index->indisreplident)
4435  candidateIndex = index->indexrelid;
4436  }
4437 
4438  systable_endscan(indscan);
4439 
4440  heap_close(indrel, AccessShareLock);
4441 
4442  /* Now save a copy of the completed list in the relcache entry. */
4444  oldlist = relation->rd_indexlist;
4445  relation->rd_indexlist = list_copy(result);
4446  relation->rd_oidindex = oidIndex;
4447  relation->rd_pkindex = pkeyIndex;
4448  if (replident == REPLICA_IDENTITY_DEFAULT && OidIsValid(pkeyIndex))
4449  relation->rd_replidindex = pkeyIndex;
4450  else if (replident == REPLICA_IDENTITY_INDEX && OidIsValid(candidateIndex))
4451  relation->rd_replidindex = candidateIndex;
4452  else
4453  relation->rd_replidindex = InvalidOid;
4454  relation->rd_indexvalid = 1;
4455  MemoryContextSwitchTo(oldcxt);
4456 
4457  /* Don't leak the old list, if there is one */
4458  list_free(oldlist);
4459 
4460  return result;
4461 }
#define NIL
Definition: pg_list.h:69
Definition: c.h:478
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define IndexIsValid(indexForm)
Definition: pg_index.h:107
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
Oid rd_replidindex
Definition: rel.h:138
#define IndexRelationId
Definition: pg_index.h:29
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define REPLICA_IDENTITY_DEFAULT
Definition: pg_class.h:175
#define Anum_pg_index_indclass
Definition: pg_index.h:89
#define AccessShareLock
Definition: lockdefs.h:36
static List * insert_ordered_oid(List *list, Oid datum)
Definition: relcache.c:4551
List * list_copy(const List *oldlist)
Definition: list.c:1160
#define IndexIsLive(indexForm)
Definition: pg_index.h:109
#define OID_BTREE_OPS_OID
Definition: pg_opclass.h:145
return result
Definition: formatting.c:1632
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:538
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
#define Anum_pg_index_indrelid
Definition: pg_index.h:75
Definition: type.h:90
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
Oid rd_pkindex
Definition: rel.h:137
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:3998
char rd_indexvalid
Definition: rel.h:93
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:486
bool heap_attisnull(HeapTuple tup, int attnum)
Definition: heaptuple.c:297
Oid rd_oidindex
Definition: rel.h:136
List * rd_indexlist
Definition: rel.h:135
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:769
FormData_pg_index * Form_pg_index
Definition: pg_index.h:67
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define InvalidOid
Definition: postgres_ext.h:36
#define Anum_pg_index_indpred
Definition: pg_index.h:92
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define DatumGetPointer(X)
Definition: postgres.h:555
void list_free(List *list)
Definition: list.c:1133
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define REPLICA_IDENTITY_INDEX
Definition: pg_class.h:185
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:417
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define IndexIndrelidIndexId
Definition: indexing.h:162
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
List* RelationGetIndexPredicate ( Relation  relation)

Definition at line 4764 of file relcache.c.

References Anum_pg_index_indpred, Assert, canonicalize_qual(), copyObject, eval_const_expressions(), fix_opfuncids(), GetPgIndexDescriptor(), heap_attisnull(), heap_getattr, make_ands_implicit(), MemoryContextSwitchTo(), NIL, NULL, pfree(), RelationData::rd_indexcxt, RelationData::rd_indextuple, RelationData::rd_indpred, result, stringToNode(), and TextDatumGetCString.

Referenced by ATExecReplicaIdentity(), BuildIndexInfo(), ExecRefreshMatView(), get_relation_info(), infer_arbiter_indexes(), refresh_by_match_merge(), and transformIndexConstraint().

4765 {
4766  List *result;
4767  Datum predDatum;
4768  bool isnull;
4769  char *predString;
4770  MemoryContext oldcxt;
4771 
4772  /* Quick exit if we already computed the result. */
4773  if (relation->rd_indpred)
4774  return copyObject(relation->rd_indpred);
4775 
4776  /* Quick exit if there is nothing to do. */
4777  if (relation->rd_indextuple == NULL ||
4779  return NIL;
4780 
4781  /*
4782  * We build the tree we intend to return in the caller's context. After
4783  * successfully completing the work, we copy it into the relcache entry.
4784  * This avoids problems if we get some sort of error partway through.
4785  */
4786  predDatum = heap_getattr(relation->rd_indextuple,
4789  &isnull);
4790  Assert(!isnull);
4791  predString = TextDatumGetCString(predDatum);
4792  result = (List *) stringToNode(predString);
4793  pfree(predString);
4794 
4795  /*
4796  * Run the expression through const-simplification and canonicalization.
4797  * This is not just an optimization, but is necessary, because the planner
4798  * will be comparing it to similarly-processed qual clauses, and may fail
4799  * to detect valid matches without this. This must match the processing
4800  * done to qual clauses in preprocess_expression()! (We can skip the
4801  * stuff involving subqueries, however, since we don't allow any in index
4802  * predicates.)
4803  */
4804  result = (List *) eval_const_expressions(NULL, (Node *) result);
4805 
4806  result = (List *) canonicalize_qual((Expr *) result);
4807 
4808  /* Also convert to implicit-AND format */
4809  result = make_ands_implicit((Expr *) result);
4810 
4811  /* May as well fix opfuncids too */
4812  fix_opfuncids((Node *) result);
4813 
4814  /* Now save a copy of the completed tree in the relcache entry. */
4815  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4816  relation->rd_indpred = copyObject(result);
4817  MemoryContextSwitchTo(oldcxt);
4818 
4819  return result;
4820 }
#define NIL
Definition: pg_list.h:69
void * stringToNode(char *str)
Definition: read.c:38
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1604
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:509
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2400
return result
Definition: formatting.c:1632
struct HeapTupleData * rd_indextuple
Definition: rel.h:161
void pfree(void *pointer)
Definition: mcxt.c:950
List * make_ands_implicit(Expr *clause)
Definition: clauses.c:378
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:3998
bool heap_attisnull(HeapTuple tup, int attnum)
Definition: heaptuple.c:297
List * rd_indpred
Definition: rel.h:188
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:769
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
Expr * canonicalize_qual(Expr *qual)
Definition: prepqual.c:286
#define Anum_pg_index_indpred
Definition: pg_index.h:92
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
MemoryContext rd_indexcxt
Definition: rel.h:179
#define copyObject(obj)
Definition: nodes.h:621
Definition: pg_list.h:45
Oid RelationGetOidIndex ( Relation  relation)

Definition at line 4627 of file relcache.c.

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

Referenced by GetNewOid().

4628 {
4629  List *ilist;
4630 
4631  /*
4632  * If relation doesn't have OIDs at all, caller is probably confused. (We
4633  * could just silently return InvalidOid, but it seems better to throw an
4634  * assertion.)
4635  */
4636  Assert(relation->rd_rel->relhasoids);
4637 
4638  if (relation->rd_indexvalid == 0)
4639  {
4640  /* RelationGetIndexList does the heavy lifting. */
4641  ilist = RelationGetIndexList(relation);
4642  list_free(ilist);
4643  Assert(relation->rd_indexvalid != 0);
4644  }
4645 
4646  return relation->rd_oidindex;
4647 }
Form_pg_class rd_rel
Definition: rel.h:114
char rd_indexvalid
Definition: rel.h:93
Oid rd_oidindex
Definition: rel.h:136
#define Assert(condition)
Definition: c.h:675
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4345
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45
Oid RelationGetPrimaryKeyIndex ( Relation  relation)

Definition at line 4655 of file relcache.c.

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

Referenced by GetRelationIdentityOrPK().

4656 {
4657  List *ilist;
4658 
4659  if (relation->rd_indexvalid == 0)
4660  {
4661  /* RelationGetIndexList does the heavy lifting. */
4662  ilist = RelationGetIndexList(relation);
4663  list_free(ilist);
4664  Assert(relation->rd_indexvalid != 0);
4665  }
4666 
4667  return relation->rd_pkindex;
4668 }
Oid rd_pkindex
Definition: rel.h:137
char rd_indexvalid
Definition: rel.h:93
#define Assert(condition)
Definition: c.h:675
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4345
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45
Oid RelationGetReplicaIndex ( Relation  relation)

Definition at line 4676 of file relcache.c.

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

Referenced by build_replindex_scan_key(), CheckCmdReplicaIdentity(), ExtractReplicaIdentity(), GetRelationIdentityOrPK(), and pg_get_replica_identity_index().

4677 {
4678  List *ilist;
4679 
4680  if (relation->rd_indexvalid == 0)
4681  {
4682  /* RelationGetIndexList does the heavy lifting. */
4683  ilist = RelationGetIndexList(relation);
4684  list_free(ilist);
4685  Assert(relation->rd_indexvalid != 0);
4686  }
4687 
4688  return relation->rd_replidindex;
4689 }
Oid rd_replidindex
Definition: rel.h:138
char rd_indexvalid
Definition: rel.h:93
#define Assert(condition)
Definition: c.h:675
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4345
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45
List* RelationGetStatExtList ( Relation  relation)

Definition at line 4485 of file relcache.c.

References AccessShareLock, Anum_pg_statistic_ext_stxrelid, BTEqualStrategyNumber, CacheMemoryContext, heap_close, heap_open(), HeapTupleGetOid, HeapTupleIsValid, insert_ordered_oid(), list_copy(), list_free(), MemoryContextSwitchTo(), NIL, NULL, ObjectIdGetDatum, RelationData::rd_statlist, RelationData::rd_statvalid, RelationGetRelid, result, ScanKeyInit(), StatisticExtRelationId, StatisticExtRelidIndexId, systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by get_relation_statistics().

4486 {
4487  Relation indrel;
4488  SysScanDesc indscan;
4489  ScanKeyData skey;
4490  HeapTuple htup;
4491  List *result;
4492  List *oldlist;
4493  MemoryContext oldcxt;
4494 
4495  /* Quick exit if we already computed the list. */
4496  if (relation->rd_statvalid != 0)
4497  return list_copy(relation->rd_statlist);
4498 
4499  /*
4500  * We build the list we intend to return (in the caller's context) while
4501  * doing the scan. After successfully completing the scan, we copy that
4502  * list into the relcache entry. This avoids cache-context memory leakage
4503  * if we get some sort of error partway through.
4504  */
4505  result = NIL;
4506 
4507  /*
4508  * Prepare to scan pg_statistic_ext for entries having stxrelid = this
4509  * rel.
4510  */
4511  ScanKeyInit(&skey,
4513  BTEqualStrategyNumber, F_OIDEQ,
4514  ObjectIdGetDatum(RelationGetRelid(relation)));
4515 
4517  indscan = systable_beginscan(indrel, StatisticExtRelidIndexId, true,
4518  NULL, 1, &skey);
4519 
4520  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4521  result = insert_ordered_oid(result, HeapTupleGetOid(htup));
4522 
4523  systable_endscan(indscan);
4524 
4525  heap_close(indrel, AccessShareLock);
4526 
4527  /* Now save a copy of the completed list in the relcache entry. */
4529  oldlist = relation->rd_statlist;
4530  relation->rd_statlist = list_copy(result);
4531 
4532  relation->rd_statvalid = true;
4533  MemoryContextSwitchTo(oldcxt);
4534 
4535  /* Don't leak the old list, if there is one */
4536  list_free(oldlist);
4537 
4538  return result;
4539 }
#define Anum_pg_statistic_ext_stxrelid
#define NIL
Definition: pg_list.h:69
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
static List * insert_ordered_oid(List *list, Oid datum)
Definition: relcache.c:4551
List * list_copy(const List *oldlist)
Definition: list.c:1160
return result
Definition: formatting.c:1632
#define heap_close(r, l)
Definition: heapam.h:97
#define StatisticExtRelidIndexId
Definition: indexing.h:190
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define StatisticExtRelationId
bool rd_statvalid
Definition: rel.h:95
void list_free(List *list)
Definition: list.c:1133
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
List * rd_statlist
Definition: rel.h:141
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:417
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
Relation RelationIdGetRelation ( Oid  relationId)

Definition at line 2067 of file relcache.c.

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

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

2068 {
2069  Relation rd;
2070 
2071  /* Make sure we're in an xact, even if this ends up being a cache hit */
2073 
2074  /*
2075  * first try to find reldesc in the cache
2076  */
2077  RelationIdCacheLookup(relationId, rd);
2078 
2079  if (RelationIsValid(rd))
2080  {
2082  /* revalidate cache entry if necessary */
2083  if (!rd->rd_isvalid)
2084  {
2085  /*
2086  * Indexes only have a limited number of possible schema changes,
2087  * and we don't want to use the full-blown procedure because it's
2088  * a headache for indexes that reload itself depends on.
2089  */
2090  if (rd->rd_rel->relkind == RELKIND_INDEX)
2092  else
2093  RelationClearRelation(rd, true);
2094  Assert(rd->rd_isvalid);
2095  }
2096  return rd;
2097  }
2098 
2099  /*
2100  * no reldesc in the cache, so have RelationBuildDesc() build one and add
2101  * it.
2102  */
2103  rd = RelationBuildDesc(relationId, true);
2104  if (RelationIsValid(rd))
2106  return rd;
2107 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2388
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:202
bool rd_isvalid
Definition: rel.h:92
Form_pg_class rd_rel
Definition: rel.h:114
#define RelationIsValid(relation)
Definition: rel.h:390
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2123
static void RelationReloadIndexInfo(Relation relation)
Definition: relcache.c:2197
#define Assert(condition)
Definition: c.h:675
static Relation RelationBuildDesc(Oid targetRelId, bool insertIt)
Definition: relcache.c:1233
bool IsTransactionState(void)
Definition: xact.c:350
#define RELKIND_INDEX
Definition: pg_class.h:161
bool RelationIdIsInInitFile ( Oid  relationId)

Definition at line 5960 of file relcache.c.

References Assert, RelationSupportsSysCache(), and TriggerRelidNameIndexId.

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

5961 {
5962  if (relationId == TriggerRelidNameIndexId)
5963  {
5964  /* If this Assert fails, we don't need this special case anymore. */
5965  Assert(!RelationSupportsSysCache(relationId));
5966  return true;
5967  }
5968  return RelationSupportsSysCache(relationId);
5969 }
#define TriggerRelidNameIndexId
Definition: indexing.h:249
#define Assert(condition)
Definition: c.h:675
bool RelationSupportsSysCache(Oid relid)
Definition: syscache.c:1423
void RelationInitIndexAccessInfo ( Relation  relation)

Definition at line 1505 of file relcache.c.

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate(), AMOID, IndexAmRoutine::amsupport, Anum_pg_index_indclass, Anum_pg_index_indcollation, Anum_pg_index_indoption, Assert, CacheMemoryContext, DatumGetPointer, elog, ERROR, fastgetattr, GetPgIndexDescriptor(), GETSTRUCT, heap_copytuple(), HeapTupleIsValid, INDEXRELID, IndexSupportInitialize(), InitIndexAmRoutine(), MemoryContextAllocZero(), MemoryContextSwitchTo(), NIL, NULL, ObjectIdGetDatum, RelationData::rd_amcache, RelationData::rd_amhandler, RelationData::rd_amroutine, RelationData::rd_exclops, RelationData::rd_exclprocs, RelationData::rd_exclstrats, 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, RelationGetRelationName, RelationGetRelid, ReleaseSysCache(), SearchSysCache1, int2vector::values, and oidvector::values.

Referenced by index_create(), and RelationBuildDesc().

1506 {
1507  HeapTuple tuple;
1508  Form_pg_am aform;
1509  Datum indcollDatum;
1510  Datum indclassDatum;
1511  Datum indoptionDatum;
1512  bool isnull;
1513  oidvector *indcoll;
1514  oidvector *indclass;
1515  int2vector *indoption;
1516  MemoryContext indexcxt;
1517  MemoryContext oldcontext;
1518  int natts;
1519  uint16 amsupport;
1520 
1521  /*
1522  * Make a copy of the pg_index entry for the index. Since pg_index
1523  * contains variable-length and possibly-null fields, we have to do this
1524  * honestly rather than just treating it as a Form_pg_index struct.
1525  */
1526  tuple = SearchSysCache1(INDEXRELID,
1527  ObjectIdGetDatum(RelationGetRelid(relation)));
1528  if (!HeapTupleIsValid(tuple))
1529  elog(ERROR, "cache lookup failed for index %u",
1530  RelationGetRelid(relation));
1532  relation->rd_indextuple = heap_copytuple(tuple);
1533  relation->rd_index = (Form_pg_index) GETSTRUCT(relation->rd_indextuple);
1534  MemoryContextSwitchTo(oldcontext);
1535  ReleaseSysCache(tuple);
1536 
1537  /*
1538  * Look up the index's access method, save the OID of its handler function
1539  */
1540  tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(relation->rd_rel->relam));
1541  if (!HeapTupleIsValid(tuple))
1542  elog(ERROR, "cache lookup failed for access method %u",
1543  relation->rd_rel->relam);
1544  aform = (Form_pg_am) GETSTRUCT(tuple);
1545  relation->rd_amhandler = aform->amhandler;
1546  ReleaseSysCache(tuple);
1547 
1548  natts = relation->rd_rel->relnatts;
1549  if (natts != relation->rd_index->indnatts)
1550  elog(ERROR, "relnatts disagrees with indnatts for index %u",
1551  RelationGetRelid(relation));
1552 
1553  /*
1554  * Make the private context to hold index access info. The reason we need
1555  * a context, and not just a couple of pallocs, is so that we won't leak
1556  * any subsidiary info attached to fmgr lookup records.
1557  */
1559  RelationGetRelationName(relation),
1561  relation->rd_indexcxt = indexcxt;
1562 
1563  /*
1564  * Now we can fetch the index AM's API struct
1565  */
1566  InitIndexAmRoutine(relation);
1567 
1568  /*
1569  * Allocate arrays to hold data
1570  */
1571  relation->rd_opfamily = (Oid *)
1572  MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
1573  relation->rd_opcintype = (Oid *)
1574  MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
1575 
1576  amsupport = relation->rd_amroutine->amsupport;
1577  if (amsupport > 0)
1578  {
1579  int nsupport = natts * amsupport;
1580 
1581  relation->rd_support = (RegProcedure *)
1582  MemoryContextAllocZero(indexcxt, nsupport * sizeof(RegProcedure));
1583  relation->rd_supportinfo = (FmgrInfo *)
1584  MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
1585  }
1586  else
1587  {
1588  relation->rd_support = NULL;
1589  relation->rd_supportinfo = NULL;
1590  }
1591 
1592  relation->rd_indcollation = (Oid *)
1593  MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
1594 
1595  relation->rd_indoption = (int16 *)
1596  MemoryContextAllocZero(indexcxt, natts * sizeof(int16));
1597 
1598  /*
1599  * indcollation cannot be referenced directly through the C struct,
1600  * because it comes after the variable-width indkey field. Must extract
1601  * the datum the hard way...
1602  */
1603  indcollDatum = fastgetattr(relation->rd_indextuple,
1606  &isnull);
1607  Assert(!isnull);
1608  indcoll = (oidvector *) DatumGetPointer(indcollDatum);
1609  memcpy(relation->rd_indcollation, indcoll->values, natts * sizeof(Oid));
1610 
1611  /*
1612  * indclass cannot be referenced directly through the C struct, because it
1613  * comes after the variable-width indkey field. Must extract the datum
1614  * the hard way...
1615  */
1616  indclassDatum = fastgetattr(relation->rd_indextuple,
1619  &isnull);
1620  Assert(!isnull);
1621  indclass = (oidvector *) DatumGetPointer(indclassDatum);
1622 
1623  /*
1624  * Fill the support procedure OID array, as well as the info about
1625  * opfamilies and opclass input types. (aminfo and supportinfo are left
1626  * as zeroes, and are filled on-the-fly when used)
1627  */
1628  IndexSupportInitialize(indclass, relation->rd_support,
1629  relation->rd_opfamily, relation->rd_opcintype,
1630  amsupport, natts);
1631 
1632  /*
1633  * Similarly extract indoption and copy it to the cache entry
1634  */
1635  indoptionDatum = fastgetattr(relation->rd_indextuple,
1638  &isnull);
1639  Assert(!isnull);
1640  indoption = (int2vector *) DatumGetPointer(indoptionDatum);
1641  memcpy(relation->rd_indoption, indoption->values, natts * sizeof(int16));
1642 
1643  /*
1644  * expressions, predicate, exclusion caches will be filled later
1645  */
1646  relation->rd_indexprs = NIL;
1647  relation->rd_indpred = NIL;
1648  relation->rd_exclops = NULL;
1649  relation->rd_exclprocs = NULL;
1650  relation->rd_exclstrats = NULL;
1651  relation->rd_amcache = NULL;
1652 }
signed short int16
Definition: c.h:255
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:608
#define NIL
Definition: pg_list.h:69
Definition: c.h:478
Definition: fmgr.h:56
uint16 amsupport
Definition: amapi.h:169
int16 * rd_indoption
Definition: rel.h:186
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:719
Definition: syscache.h:36
FmgrInfo * rd_supportinfo
Definition: rel.h:185
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:175
regproc RegProcedure
Definition: c.h:395
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
uint16 * rd_exclstrats
Definition: rel.h:191
List * rd_indexprs
Definition: rel.h:187
#define Anum_pg_index_indclass
Definition: pg_index.h:89
Oid * rd_exclprocs
Definition: rel.h:190
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
struct IndexAmRoutine * rd_amroutine
Definition: rel.h:181
static void InitIndexAmRoutine(Relation relation)
Definition: relcache.c:1481
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
static void IndexSupportInitialize(oidvector *indclass, RegProcedure *indexSupport, Oid *opFamily, Oid *opcInType, StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber)
Definition: relcache.c:1668
struct HeapTupleData * rd_indextuple
Definition: rel.h:161
Form_pg_index rd_index
Definition: rel.h:159
unsigned short uint16
Definition: c.h:267
Oid * rd_indcollation
Definition: rel.h:193
Oid rd_amhandler
Definition: rel.h:178
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:3998
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:486
#define RelationGetRelationName(relation)
Definition: rel.h:437
List * rd_indpred
Definition: rel.h:188
Oid * rd_opfamily
Definition: rel.h:182
Oid * rd_exclops
Definition: rel.h:189
RegProcedure * rd_support
Definition: rel.h:184
FormData_pg_index * Form_pg_index
Definition: pg_index.h:67
Definition: c.h:467
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:742
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
int16 values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:475
#define DatumGetPointer(X)
Definition: postgres.h:555
#define Anum_pg_index_indcollation
Definition: pg_index.h:88
FormData_pg_am * Form_pg_am
Definition: pg_am.h:46
MemoryContext rd_indexcxt
Definition: rel.h:179
#define elog
Definition: elog.h:219
void * rd_amcache
Definition: rel.h:192
Oid * rd_opcintype
Definition: rel.h:183
#define RelationGetRelid(relation)
Definition: rel.h:417
#define Anum_pg_index_indoption
Definition: pg_index.h:90
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void RelationSetIndexList ( Relation  relation,
List indexIds,
Oid  oidIndex 
)

Definition at line 4596 of file relcache.c.

References Assert, CacheMemoryContext, EOXactListAdd, InvalidOid, list_copy(), list_free(), MemoryContextSwitchTo(), RelationData::rd_indexlist, RelationData::rd_indexvalid, RelationData::rd_isnailed, RelationData::rd_oidindex, RelationData::rd_pkindex, and RelationData::rd_replidindex.

Referenced by reindex_relation().

4597 {
4598  MemoryContext oldcxt;
4599 
4600  Assert(relation->rd_isnailed);
4601  /* Copy the list into the cache context (could fail for lack of mem) */
4603  indexIds = list_copy(indexIds);
4604  MemoryContextSwitchTo(oldcxt);
4605  /* Okay to replace old list */
4606  list_free(relation->rd_indexlist);
4607  relation->rd_indexlist = indexIds;
4608  relation->rd_oidindex = oidIndex;
4609 
4610  /*
4611  * For the moment, assume the target rel hasn't got a pk or replica index.
4612  * We'll load them on demand in the API that wraps access to them.
4613  */
4614  relation->rd_pkindex = InvalidOid;
4615  relation->rd_replidindex = InvalidOid;
4616  relation->rd_indexvalid = 2; /* mark list as forced */
4617  /* Flag relation as needing eoxact cleanup (to reset the list) */
4618  EOXactListAdd(relation);
4619 }
#define EOXactListAdd(rel)
Definition: relcache.c:160
Oid rd_replidindex
Definition: rel.h:138
bool rd_isnailed
Definition: rel.h:91
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
List * list_copy(const List *oldlist)
Definition: list.c:1160
Oid rd_pkindex
Definition: rel.h:137
char rd_indexvalid
Definition: rel.h:93
Oid rd_oidindex
Definition: rel.h:136
List * rd_indexlist
Definition: rel.h:135
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:675
void list_free(List *list)
Definition: list.c:1133
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void RelationSetNewRelfilenode ( Relation  relation,
char  persistence,
TransactionId  freezeXid,
MultiXactId  minmulti 
)

Definition at line 3416 of file relcache.c.

References Assert, RelFileNodeBackend::backend, CatalogTupleUpdate(), CommandCounterIncrement(), elog, EOXactListAdd, ERROR, GetCurrentSubTransactionId(), GetNewRelFileNode(), GETSTRUCT, heap_close, heap_freetuple(), heap_open(), HeapTupleIsValid, InvalidTransactionId, MultiXactIdIsValid, RelFileNodeBackend::node, NULL, ObjectIdGetDatum, RelationData::rd_backend, RelationData::rd_newRelfilenodeSubid, RelationData::rd_node, RelationData::rd_rel, RelationCreateStorage(), RelationDropStorage(), RelationGetRelid, RelationIsMapped, RelationMapUpdateMap(), RelationRelationId, RELKIND_INDEX, RELKIND_SEQUENCE, RelFileNode::relNode, RELOID, RowExclusiveLock, SearchSysCacheCopy1, smgrclosenode(), HeapTupleData::t_self, and TransactionIdIsNormal.

Referenced by ExecuteTruncate(), reindex_index(), and ResetSequence().

3418 {
3419  Oid newrelfilenode;
3420  RelFileNodeBackend newrnode;
3421  Relation pg_class;
3422  HeapTuple tuple;
3423  Form_pg_class classform;
3424 
3425  /* Indexes, sequences must have Invalid frozenxid; other rels must not */
3426  Assert((relation->rd_rel->relkind == RELKIND_INDEX ||
3427  relation->rd_rel->relkind == RELKIND_SEQUENCE) ?
3428  freezeXid == InvalidTransactionId :
3429  TransactionIdIsNormal(freezeXid));
3430  Assert(TransactionIdIsNormal(freezeXid) == MultiXactIdIsValid(minmulti));
3431 
3432  /* Allocate a new relfilenode */
3433  newrelfilenode = GetNewRelFileNode(relation->rd_rel->reltablespace, NULL,
3434  persistence);
3435 
3436  /*
3437  * Get a writable copy of the pg_class tuple for the given relation.
3438  */
3440 
3441  tuple = SearchSysCacheCopy1(RELOID,
3442  ObjectIdGetDatum(RelationGetRelid(relation)));
3443  if (!HeapTupleIsValid(tuple))
3444  elog(ERROR, "could not find tuple for relation %u",
3445  RelationGetRelid(relation));
3446  classform = (Form_pg_class) GETSTRUCT(tuple);
3447 
3448  /*
3449  * Create storage for the main fork of the new relfilenode.
3450  *
3451  * NOTE: any conflict in relfilenode value will be caught here, if
3452  * GetNewRelFileNode messes up for any reason.
3453  */
3454  newrnode.node = relation->rd_node;
3455  newrnode.node.relNode = newrelfilenode;
3456  newrnode.backend = relation->rd_backend;
3457  RelationCreateStorage(newrnode.node, persistence);
3458  smgrclosenode(newrnode);
3459 
3460  /*
3461  * Schedule unlinking of the old storage at transaction commit.
3462  */
3463  RelationDropStorage(relation);
3464 
3465  /*
3466  * Now update the pg_class row. However, if we're dealing with a mapped
3467  * index, pg_class.relfilenode doesn't change; instead we have to send the
3468  * update to the relation mapper.
3469  */
3470  if (RelationIsMapped(relation))
3472  newrelfilenode,
3473  relation->rd_rel->relisshared,
3474  false);
3475  else
3476  classform->relfilenode = newrelfilenode;
3477 
3478  /* These changes are safe even for a mapped relation */
3479  if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
3480  {
3481  classform->relpages = 0; /* it's empty until further notice */
3482  classform->reltuples = 0;
3483  classform->relallvisible = 0;
3484  }
3485  classform->relfrozenxid = freezeXid;
3486  classform->relminmxid = minmulti;
3487  classform->relpersistence = persistence;
3488 
3489  CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
3490 
3491  heap_freetuple(tuple);
3492 
3493  heap_close(pg_class, RowExclusiveLock);
3494 
3495  /*
3496  * Make the pg_class row change visible, as well as the relation map
3497  * change if any. This will cause the relcache entry to get updated, too.
3498  */
3500 
3501  /*
3502  * Mark the rel as having been given a new relfilenode in the current
3503  * (sub) transaction. This is a hint that can be used to optimize later
3504  * operations on the rel in the same transaction.
3505  */
3507 
3508  /* Flag relation as needing eoxact cleanup (to remove the hint) */
3509  EOXactListAdd(relation);
3510 }
#define EOXactListAdd(rel)
Definition: relcache.c:160
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define RelationRelationId
Definition: pg_class.h:29
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:111
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:114
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1372
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvalidTransactionId
Definition: transam.h:31
#define MultiXactIdIsValid(multi)
Definition: multixact.h:27
void smgrclosenode(RelFileNodeBackend rnode)
Definition: smgr.c:350
#define RelationIsMapped(relation)
Definition: rel.h:454
void RelationDropStorage(Relation rel)
Definition: storage.c:145
void CommandCounterIncrement(void)
Definition: xact.c:922
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
RelFileNode node
Definition: relfilenode.h:74
RelFileNode rd_node
Definition: rel.h:85
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
BackendId rd_backend
Definition: rel.h:89
#define Assert(condition)
Definition: c.h:675
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:649
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
BackendId backend
Definition: relfilenode.h:75
Oid GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
Definition: catalog.c:386
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:165
#define RELKIND_INDEX
Definition: pg_class.h:161
#define elog
Definition: elog.h:219
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
#define RELKIND_SEQUENCE
Definition: pg_class.h:162
void RelationCreateStorage(RelFileNode rnode, char relpersistence)
Definition: storage.c:78
#define RelationGetRelid(relation)
Definition: rel.h:417
void RelationMapUpdateMap(Oid relationId, Oid fileNode, bool shared, bool immediate)
Definition: relmapper.c:248

Variable Documentation

bool criticalSharedRelcachesBuilt