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

3073 {
3075  RelIdCacheEnt *idhentry;
3076  int i;
3077 
3078  /*
3079  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3080  * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3081  * logic as in AtEOXact_RelationCache.
3082  */
3084  {
3085  hash_seq_init(&status, RelationIdCache);
3086  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3087  {
3088  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3089  mySubid, parentSubid);
3090  }
3091  }
3092  else
3093  {
3094  for (i = 0; i < eoxact_list_len; i++)
3095  {
3096  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3097  (void *) &eoxact_list[i],
3098  HASH_FIND,
3099  NULL);
3100  if (idhentry != NULL)
3101  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3102  mySubid, parentSubid);
3103  }
3104  }
3105 
3106  /* Don't reset the list; we still need more cleanup later */
3107 }
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:3118
Relation reldesc
Definition: relcache.c:120
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:903
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:1386
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1376
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 2920 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().

2921 {
2923  RelIdCacheEnt *idhentry;
2924  int i;
2925 
2926  /*
2927  * Unless the eoxact_list[] overflowed, we only need to examine the rels
2928  * listed in it. Otherwise fall back on a hash_seq_search scan.
2929  *
2930  * For simplicity, eoxact_list[] entries are not deleted till end of
2931  * top-level transaction, even though we could remove them at
2932  * subtransaction end in some cases, or remove relations from the list if
2933  * they are cleared for other reasons. Therefore we should expect the
2934  * case that list entries are not found in the hashtable; if not, there's
2935  * nothing to do for them.
2936  */
2938  {
2939  hash_seq_init(&status, RelationIdCache);
2940  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2941  {
2942  AtEOXact_cleanup(idhentry->reldesc, isCommit);
2943  }
2944  }
2945  else
2946  {
2947  for (i = 0; i < eoxact_list_len; i++)
2948  {
2949  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
2950  (void *) &eoxact_list[i],
2951  HASH_FIND,
2952  NULL);
2953  if (idhentry != NULL)
2954  AtEOXact_cleanup(idhentry->reldesc, isCommit);
2955  }
2956  }
2957 
2958  if (EOXactTupleDescArrayLen > 0)
2959  {
2961  for (i = 0; i < NextEOXactTupleDescNum; i++)
2965  }
2966 
2967  /* Now we're out of the transaction and can clear the lists */
2968  eoxact_list_len = 0;
2969  eoxact_list_overflowed = false;
2970  NextEOXactTupleDescNum = 0;
2972 }
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:903
static HTAB * RelationIdCache
Definition: relcache.c:123
static void AtEOXact_cleanup(Relation relation, bool isCommit)
Definition: relcache.c:2983
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:1386
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1376
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 5247 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().

5248 {
5252 
5253  return 0; /* return value does not matter */
5254 }
#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:436
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
#define RelationGetNamespace(relation)
Definition: rel.h:443
int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5264 of file relcache.c.

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

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

5265 {
5266  TupleDesc reldesc = RelationGetDescr(rel);
5267  const char *colname;
5268 
5269  /* Use reldesc if it's a user attribute, else consult the catalogs */
5270  if (attnum > 0 && attnum <= reldesc->natts)
5271  colname = NameStr(reldesc->attrs[attnum - 1]->attname);
5272  else
5273  colname = get_relid_attribute_name(RelationGetRelid(rel), attnum);
5274 
5275  return errtablecolname(rel, colname);
5276 }
#define RelationGetDescr(relation)
Definition: rel.h:428
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:416
int errtablecolname(Relation rel, const char *colname)
Definition: relcache.c:5288
int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5288 of file relcache.c.

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

Referenced by errtablecol().

5289 {
5290  errtable(rel);
5292 
5293  return 0; /* return value does not matter */
5294 }
#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:5247
int errtableconstraint ( Relation  rel,
const char *  conname 
)

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

5302 {
5303  errtable(rel);
5305 
5306  return 0; /* return value does not matter */
5307 }
#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:5247
struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

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

5177 {
5178  List *puboids;
5179  ListCell *lc;
5180  MemoryContext oldcxt;
5181  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5182 
5183  if (relation->rd_pubactions)
5184  return memcpy(pubactions, relation->rd_pubactions,
5185  sizeof(PublicationActions));
5186 
5187  /* Fetch the publication membership info. */
5188  puboids = GetRelationPublications(RelationGetRelid(relation));
5189  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5190 
5191  foreach(lc, puboids)
5192  {
5193  Oid pubid = lfirst_oid(lc);
5194  HeapTuple tup;
5195  Form_pg_publication pubform;
5196 
5198 
5199  if (!HeapTupleIsValid(tup))
5200  elog(ERROR, "cache lookup failed for publication %u", pubid);
5201 
5202  pubform = (Form_pg_publication) GETSTRUCT(tup);
5203 
5204  pubactions->pubinsert |= pubform->pubinsert;
5205  pubactions->pubupdate |= pubform->pubupdate;
5206  pubactions->pubdelete |= pubform->pubdelete;
5207 
5208  ReleaseSysCache(tup);
5209 
5210  /*
5211  * If we know everything is replicated, there is no point to check for
5212  * other publications.
5213  */
5214  if (pubactions->pubinsert && pubactions->pubupdate &&
5215  pubactions->pubdelete)
5216  break;
5217  }
5218 
5219  if (relation->rd_pubactions)
5220  {
5221  pfree(relation->rd_pubactions);
5222  relation->rd_pubactions = NULL;
5223  }
5224 
5225  /* Now save copy of the actions in the relcache entry. */
5227  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5228  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5229  MemoryContextSwitchTo(oldcxt);
5230 
5231  return pubactions;
5232 }
#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:416
#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 3183 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().

3193 {
3194  Relation rel;
3195  MemoryContext oldcxt;
3196  int natts = tupDesc->natts;
3197  int i;
3198  bool has_not_null;
3199  bool nailit;
3200 
3201  AssertArg(natts >= 0);
3202 
3203  /*
3204  * check for creation of a rel that must be nailed in cache.
3205  *
3206  * XXX this list had better match the relations specially handled in
3207  * RelationCacheInitializePhase2/3.
3208  */
3209  switch (relid)
3210  {
3211  case DatabaseRelationId:
3212  case AuthIdRelationId:
3213  case AuthMemRelationId:
3214  case RelationRelationId:
3215  case AttributeRelationId:
3216  case ProcedureRelationId:
3217  case TypeRelationId:
3218  nailit = true;
3219  break;
3220  default:
3221  nailit = false;
3222  break;
3223  }
3224 
3225  /*
3226  * check that hardwired list of shared rels matches what's in the
3227  * bootstrap .bki file. If you get a failure here during initdb, you
3228  * probably need to fix IsSharedRelation() to match whatever you've done
3229  * to the set of shared relations.
3230  */
3231  if (shared_relation != IsSharedRelation(relid))
3232  elog(ERROR, "shared_relation flag for \"%s\" does not match IsSharedRelation(%u)",
3233  relname, relid);
3234 
3235  /* Shared relations had better be mapped, too */
3236  Assert(mapped_relation || !shared_relation);
3237 
3238  /*
3239  * switch to the cache context to create the relcache entry.
3240  */
3241  if (!CacheMemoryContext)
3243 
3245 
3246  /*
3247  * allocate a new relation descriptor and fill in basic state fields.
3248  */
3249  rel = (Relation) palloc0(sizeof(RelationData));
3250 
3251  /* make sure relation is marked as having no open file yet */
3252  rel->rd_smgr = NULL;
3253 
3254  /* mark it nailed if appropriate */
3255  rel->rd_isnailed = nailit;
3256 
3257  rel->rd_refcnt = nailit ? 1 : 0;
3258 
3259  /* it's being created in this transaction */
3262 
3263  /*
3264  * create a new tuple descriptor from the one passed in. We do this
3265  * partly to copy it into the cache context, and partly because the new
3266  * relation can't have any defaults or constraints yet; they have to be
3267  * added in later steps, because they require additions to multiple system
3268  * catalogs. We can copy attnotnull constraints here, however.
3269  */
3270  rel->rd_att = CreateTupleDescCopy(tupDesc);
3271  rel->rd_att->tdrefcount = 1; /* mark as refcounted */
3272  has_not_null = false;
3273  for (i = 0; i < natts; i++)
3274  {
3275  rel->rd_att->attrs[i]->attidentity = tupDesc->attrs[i]->attidentity;
3276  rel->rd_att->attrs[i]->attnotnull = tupDesc->attrs[i]->attnotnull;
3277  has_not_null |= tupDesc->attrs[i]->attnotnull;
3278  }
3279 
3280  if (has_not_null)
3281  {
3282  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
3283 
3284  constr->has_not_null = true;
3285  rel->rd_att->constr = constr;
3286  }
3287 
3288  /*
3289  * initialize relation tuple form (caller may add/override data later)
3290  */
3292 
3293  namestrcpy(&rel->rd_rel->relname, relname);
3294  rel->rd_rel->relnamespace = relnamespace;
3295 
3296  rel->rd_rel->relkind = relkind;
3297  rel->rd_rel->relhasoids = rel->rd_att->tdhasoid;
3298  rel->rd_rel->relnatts = natts;
3299  rel->rd_rel->reltype = InvalidOid;
3300  /* needed when bootstrapping: */
3301  rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;
3302 
3303  /* set up persistence and relcache fields dependent on it */
3304  rel->rd_rel->relpersistence = relpersistence;
3305  switch (relpersistence)
3306  {
3310  rel->rd_islocaltemp = false;
3311  break;
3312  case RELPERSISTENCE_TEMP:
3313  Assert(isTempOrTempToastNamespace(relnamespace));
3315  rel->rd_islocaltemp = true;
3316  break;
3317  default:
3318  elog(ERROR, "invalid relpersistence: %c", relpersistence);
3319  break;
3320  }
3321 
3322  /* if it's a materialized view, it's not populated initially */
3323  if (relkind == RELKIND_MATVIEW)
3324  rel->rd_rel->relispopulated = false;
3325  else
3326  rel->rd_rel->relispopulated = true;
3327 
3328  /* system relations and non-table objects don't have one */
3329  if (!IsSystemNamespace(relnamespace) &&
3330  (relkind == RELKIND_RELATION ||
3331  relkind == RELKIND_MATVIEW ||
3332  relkind == RELKIND_PARTITIONED_TABLE))
3333  rel->rd_rel->relreplident = REPLICA_IDENTITY_DEFAULT;
3334  else
3335  rel->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
3336 
3337  /*
3338  * Insert relation physical and logical identifiers (OIDs) into the right
3339  * places. For a mapped relation, we set relfilenode to zero and rely on
3340  * RelationInitPhysicalAddr to consult the map.
3341  */
3342  rel->rd_rel->relisshared = shared_relation;
3343 
3344  RelationGetRelid(rel) = relid;
3345 
3346  for (i = 0; i < natts; i++)
3347  rel->rd_att->attrs[i]->attrelid = relid;
3348 
3349  rel->rd_rel->reltablespace = reltablespace;
3350 
3351  if (mapped_relation)
3352  {
3353  rel->rd_rel->relfilenode = InvalidOid;
3354  /* Add it to the active mapping information */
3355  RelationMapUpdateMap(relid, relfilenode, shared_relation, true);
3356  }
3357  else
3358  rel->rd_rel->relfilenode = relfilenode;
3359 
3360  RelationInitLockInfo(rel); /* see lmgr.c */
3361 
3363 
3364  /*
3365  * Okay to insert into the relcache hash table.
3366  *
3367  * Ordinarily, there should certainly not be an existing hash entry for
3368  * the same OID; but during bootstrap, when we create a "real" relcache
3369  * entry for one of the bootstrap relations, we'll be overwriting the
3370  * phony one created with formrdesc. So allow that to happen for nailed
3371  * rels.
3372  */
3373  RelationCacheInsert(rel, nailit);
3374 
3375  /*
3376  * Flag relation as needing eoxact cleanup (to clear rd_createSubid). We
3377  * can't do this before storing relid in it.
3378  */
3379  EOXactListAdd(rel);
3380 
3381  /*
3382  * done building relcache entry.
3383  */
3384  MemoryContextSwitchTo(oldcxt);
3385 
3386  /* It's fully valid */
3387  rel->rd_isvalid = true;
3388 
3389  /*
3390  * Caller expects us to pin the returned entry.
3391  */
3393 
3394  return rel;
3395 }
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:3142
#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:216
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:1422
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:2127
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:220
TupleDesc rd_att
Definition: rel.h:115
bool IsSystemNamespace(Oid namespaceId)
Definition: catalog.c:163
#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:416
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 6073 of file relcache.c.

References LWLockRelease().

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

6074 {
6075  LWLockRelease(RelCacheInitLock);
6076 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
void RelationCacheInitFilePreInvalidate ( void  )

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

6048 {
6049  char initfilename[MAXPGPATH];
6050 
6051  snprintf(initfilename, sizeof(initfilename), "%s/%s",
6053 
6054  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6055 
6056  if (unlink(initfilename) < 0)
6057  {
6058  /*
6059  * The file might not be there if no backend has been started since
6060  * the last removal. But complain about failures other than ENOENT.
6061  * Fortunately, it's not too late to abort the transaction if we can't
6062  * get rid of the would-be-obsolete init file.
6063  */
6064  if (errno != ENOENT)
6065  ereport(ERROR,
6067  errmsg("could not remove cache file \"%s\": %m",
6068  initfilename)));
6069  }
6070 }
#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:85
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 6088 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().

6089 {
6090  const char *tblspcdir = "pg_tblspc";
6091  DIR *dir;
6092  struct dirent *de;
6093  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6094 
6095  /*
6096  * We zap the shared cache file too. In theory it can't get out of sync
6097  * enough to be a problem, but in data-corruption cases, who knows ...
6098  */
6099  snprintf(path, sizeof(path), "global/%s",
6101  unlink_initfile(path);
6102 
6103  /* Scan everything in the default tablespace */
6105 
6106  /* Scan the tablespace link directory to find non-default tablespaces */
6107  dir = AllocateDir(tblspcdir);
6108  if (dir == NULL)
6109  {
6110  elog(LOG, "could not open tablespace link directory \"%s\": %m",
6111  tblspcdir);
6112  return;
6113  }
6114 
6115  while ((de = ReadDir(dir, tblspcdir)) != NULL)
6116  {
6117  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6118  {
6119  /* Scan the tablespace dir for per-database dirs */
6120  snprintf(path, sizeof(path), "%s/%s/%s",
6121  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6123  }
6124  }
6125 
6126  FreeDir(dir);
6127 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6131
#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:6161
#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 3532 of file relcache.c.

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

Referenced by InitPostgres().

3533 {
3534  HASHCTL ctl;
3535 
3536  /*
3537  * make sure cache memory context exists
3538  */
3539  if (!CacheMemoryContext)
3541 
3542  /*
3543  * create hashtable that indexes the relcache
3544  */
3545  MemSet(&ctl, 0, sizeof(ctl));
3546  ctl.keysize = sizeof(Oid);
3547  ctl.entrysize = sizeof(RelIdCacheEnt);
3548  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3549  &ctl, HASH_ELEM | HASH_BLOBS);
3550 
3551  /*
3552  * relation mapper needs to be initialized too
3553  */
3555 }
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:316
Size keysize
Definition: hsearch.h:72
void CreateCacheMemoryContext(void)
Definition: catcache.c:511
#define INITRELCACHESIZE
Definition: relcache.c:3529
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void RelationCacheInitializePhase2 ( void  )

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

3570 {
3571  MemoryContext oldcxt;
3572 
3573  /*
3574  * relation mapper needs initialized too
3575  */
3577 
3578  /*
3579  * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3580  * nothing.
3581  */
3583  return;
3584 
3585  /*
3586  * switch to cache memory context
3587  */
3589 
3590  /*
3591  * Try to load the shared relcache cache file. If unsuccessful, bootstrap
3592  * the cache with pre-made descriptors for the critical shared catalogs.
3593  */
3594  if (!load_relcache_init_file(true))
3595  {
3596  formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
3598  formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
3600  formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
3602  formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
3604  formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
3606 
3607 #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
3608  }
3609 
3610  MemoryContextSwitchTo(oldcxt);
3611 }
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:5365
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, bool hasoids, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1891
#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:368
#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 3628 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().

3629 {
3631  RelIdCacheEnt *idhentry;
3632  MemoryContext oldcxt;
3633  bool needNewCacheFile = !criticalSharedRelcachesBuilt;
3634 
3635  /*
3636  * relation mapper needs initialized too
3637  */
3639 
3640  /*
3641  * switch to cache memory context
3642  */
3644 
3645  /*
3646  * Try to load the local relcache cache file. If unsuccessful, bootstrap
3647  * the cache with pre-made descriptors for the critical "nailed-in" system
3648  * catalogs.
3649  */
3650  if (IsBootstrapProcessingMode() ||
3651  !load_relcache_init_file(false))
3652  {
3653  needNewCacheFile = true;
3654 
3655  formrdesc("pg_class", RelationRelation_Rowtype_Id, false,
3656  true, Natts_pg_class, Desc_pg_class);
3657  formrdesc("pg_attribute", AttributeRelation_Rowtype_Id, false,
3659  formrdesc("pg_proc", ProcedureRelation_Rowtype_Id, false,
3660  true, Natts_pg_proc, Desc_pg_proc);
3661  formrdesc("pg_type", TypeRelation_Rowtype_Id, false,
3662  true, Natts_pg_type, Desc_pg_type);
3663 
3664 #define NUM_CRITICAL_LOCAL_RELS 4 /* fix if you change list above */
3665  }
3666 
3667  MemoryContextSwitchTo(oldcxt);
3668 
3669  /* In bootstrap mode, the faked-up formrdesc info is all we'll have */
3671  return;
3672 
3673  /*
3674  * If we didn't get the critical system indexes loaded into relcache, do
3675  * so now. These are critical because the catcache and/or opclass cache
3676  * depend on them for fetches done during relcache load. Thus, we have an
3677  * infinite-recursion problem. We can break the recursion by doing
3678  * heapscans instead of indexscans at certain key spots. To avoid hobbling
3679  * performance, we only want to do that until we have the critical indexes
3680  * loaded into relcache. Thus, the flag criticalRelcachesBuilt is used to
3681  * decide whether to do heapscan or indexscan at the key spots, and we set
3682  * it true after we've loaded the critical indexes.
3683  *
3684  * The critical indexes are marked as "nailed in cache", partly to make it
3685  * easy for load_relcache_init_file to count them, but mainly because we
3686  * cannot flush and rebuild them once we've set criticalRelcachesBuilt to
3687  * true. (NOTE: perhaps it would be possible to reload them by
3688  * temporarily setting criticalRelcachesBuilt to false again. For now,
3689  * though, we just nail 'em in.)
3690  *
3691  * RewriteRelRulenameIndexId and TriggerRelidNameIndexId are not critical
3692  * in the same way as the others, because the critical catalogs don't
3693  * (currently) have any rules or triggers, and so these indexes can be
3694  * rebuilt without inducing recursion. However they are used during
3695  * relcache load when a rel does have rules or triggers, so we choose to
3696  * nail them for performance reasons.
3697  */
3699  {
3705  IndexRelationId);
3714 
3715 #define NUM_CRITICAL_LOCAL_INDEXES 7 /* fix if you change list above */
3716 
3717  criticalRelcachesBuilt = true;
3718  }
3719 
3720  /*
3721  * Process critical shared indexes too.
3722  *
3723  * DatabaseNameIndexId isn't critical for relcache loading, but rather for
3724  * initial lookup of MyDatabaseId, without which we'll never find any
3725  * non-shared catalogs at all. Autovacuum calls InitPostgres with a
3726  * database OID, so it instead depends on DatabaseOidIndexId. We also
3727  * need to nail up some indexes on pg_authid and pg_auth_members for use
3728  * during client authentication. SharedSecLabelObjectIndexId isn't
3729  * critical for the core system, but authentication hooks might be
3730  * interested in it.
3731  */
3733  {
3746 
3747 #define NUM_CRITICAL_SHARED_INDEXES 6 /* fix if you change list above */
3748 
3750  }
3751 
3752  /*
3753  * Now, scan all the relcache entries and update anything that might be
3754  * wrong in the results from formrdesc or the relcache cache file. If we
3755  * faked up relcache entries using formrdesc, then read the real pg_class
3756  * rows and replace the fake entries with them. Also, if any of the
3757  * relcache entries have rules, triggers, or security policies, load that
3758  * info the hard way since it isn't recorded in the cache file.
3759  *
3760  * Whenever we access the catalogs to read data, there is a possibility of
3761  * a shared-inval cache flush causing relcache entries to be removed.
3762  * Since hash_seq_search only guarantees to still work after the *current*
3763  * entry is removed, it's unsafe to continue the hashtable scan afterward.
3764  * We handle this by restarting the scan from scratch after each access.
3765  * This is theoretically O(N^2), but the number of entries that actually
3766  * need to be fixed is small enough that it doesn't matter.
3767  */
3768  hash_seq_init(&status, RelationIdCache);
3769 
3770  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3771  {
3772  Relation relation = idhentry->reldesc;
3773  bool restart = false;
3774 
3775  /*
3776  * Make sure *this* entry doesn't get flushed while we work with it.
3777  */
3779 
3780  /*
3781  * If it's a faked-up entry, read the real pg_class tuple.
3782  */
3783  if (relation->rd_rel->relowner == InvalidOid)
3784  {
3785  HeapTuple htup;
3786  Form_pg_class relp;
3787 
3788  htup = SearchSysCache1(RELOID,
3789  ObjectIdGetDatum(RelationGetRelid(relation)));
3790  if (!HeapTupleIsValid(htup))
3791  elog(FATAL, "cache lookup failed for relation %u",
3792  RelationGetRelid(relation));
3793  relp = (Form_pg_class) GETSTRUCT(htup);
3794 
3795  /*
3796  * Copy tuple to relation->rd_rel. (See notes in
3797  * AllocateRelationDesc())
3798  */
3799  memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
3800 
3801  /* Update rd_options while we have the tuple */
3802  if (relation->rd_options)
3803  pfree(relation->rd_options);
3804  RelationParseRelOptions(relation, htup);
3805 
3806  /*
3807  * Check the values in rd_att were set up correctly. (We cannot
3808  * just copy them over now: formrdesc must have set up the rd_att
3809  * data correctly to start with, because it may already have been
3810  * copied into one or more catcache entries.)
3811  */
3812  Assert(relation->rd_att->tdtypeid == relp->reltype);
3813  Assert(relation->rd_att->tdtypmod == -1);
3814  Assert(relation->rd_att->tdhasoid == relp->relhasoids);
3815 
3816  ReleaseSysCache(htup);
3817 
3818  /* relowner had better be OK now, else we'll loop forever */
3819  if (relation->rd_rel->relowner == InvalidOid)
3820  elog(ERROR, "invalid relowner in pg_class entry for \"%s\"",
3821  RelationGetRelationName(relation));
3822 
3823  restart = true;
3824  }
3825 
3826  /*
3827  * Fix data that isn't saved in relcache cache file.
3828  *
3829  * relhasrules or relhastriggers could possibly be wrong or out of
3830  * date. If we don't actually find any rules or triggers, clear the
3831  * local copy of the flag so that we don't get into an infinite loop
3832  * here. We don't make any attempt to fix the pg_class entry, though.
3833  */
3834  if (relation->rd_rel->relhasrules && relation->rd_rules == NULL)
3835  {
3836  RelationBuildRuleLock(relation);
3837  if (relation->rd_rules == NULL)
3838  relation->rd_rel->relhasrules = false;
3839  restart = true;
3840  }
3841  if (relation->rd_rel->relhastriggers && relation->trigdesc == NULL)
3842  {
3843  RelationBuildTriggers(relation);
3844  if (relation->trigdesc == NULL)
3845  relation->rd_rel->relhastriggers = false;
3846  restart = true;
3847  }
3848 
3849  /*
3850  * Re-load the row security policies if the relation has them, since
3851  * they are not preserved in the cache. Note that we can never NOT
3852  * have a policy while relrowsecurity is true,
3853  * RelationBuildRowSecurity will create a single default-deny policy
3854  * if there is no policy defined in pg_policy.
3855  */
3856  if (relation->rd_rel->relrowsecurity && relation->rd_rsdesc == NULL)
3857  {
3858  RelationBuildRowSecurity(relation);
3859 
3860  Assert(relation->rd_rsdesc != NULL);
3861  restart = true;
3862  }
3863 
3864  /*
3865  * Reload the partition key and descriptor for a partitioned table.
3866  */
3867  if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
3868  relation->rd_partkey == NULL)
3869  {
3870  RelationBuildPartitionKey(relation);
3871  Assert(relation->rd_partkey != NULL);
3872 
3873  restart = true;
3874  }
3875 
3876  if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
3877  relation->rd_partdesc == NULL)
3878  {
3879  RelationBuildPartitionDesc(relation);
3880  Assert(relation->rd_partdesc != NULL);
3881 
3882  restart = true;
3883  }
3884 
3885  /* Release hold on the relation */
3887 
3888  /* Now, restart the hashtable scan if needed */
3889  if (restart)
3890  {
3891  hash_seq_term(&status);
3892  hash_seq_init(&status, RelationIdCache);
3893  }
3894  }
3895 
3896  /*
3897  * Lastly, write out new relcache cache files if needed. We don't bother
3898  * to distinguish cases where only one of the two needs an update.
3899  */
3900  if (needNewCacheFile)
3901  {
3902  /*
3903  * Force all the catcaches to finish initializing and thereby open the
3904  * catalogs and indexes they use. This will preload the relcache with
3905  * entries for all the most important system catalogs and indexes, so
3906  * that the init files will be most useful for future backends.
3907  */
3909 
3910  /* now write the files */
3912  write_relcache_init_file(false);
3913  }
3914 }
#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:5365
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, bool hasoids, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1891
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:151
#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:2140
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:5747
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:3923
static const FormData_pg_attribute Desc_pg_proc[Natts_pg_proc]
Definition: relcache.c:102
#define RelationGetRelationName(relation)
Definition: rel.h:436
#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:2127
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:1386
#define DatabaseNameIndexId
Definition: indexing.h:140
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1376
#define RelationRelation_Rowtype_Id
Definition: pg_class.h:30
#define SharedSecLabelObjectIndexId
Definition: indexing.h:316
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:368
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
void RelationBuildTriggers(Relation relation)
Definition: trigger.c:1657
#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:416
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:1462
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 2760 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().

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

Definition at line 2716 of file relcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

2717 {
2718  Relation relation;
2719 
2720  RelationIdCacheLookup(relationId, relation);
2721 
2722  if (PointerIsValid(relation))
2723  {
2725  RelationFlushRelation(relation);
2726  }
2727 }
static long relcacheInvalsReceived
Definition: relcache.c:143
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:202
static void RelationFlushRelation(Relation relation)
Definition: relcache.c:2648
#define PointerIsValid(pointer)
Definition: c.h:526
void RelationClose ( Relation  relation)

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

2161 {
2162  /* Note: no locking manipulations needed */
2164 
2165 #ifdef RELCACHE_FORCE_RELEASE
2166  if (RelationHasReferenceCountZero(relation) &&
2167  relation->rd_createSubid == InvalidSubTransactionId &&
2169  RelationClearRelation(relation, false);
2170 #endif
2171 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2392
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:111
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2140
SubTransactionId rd_createSubid
Definition: rel.h:110
#define InvalidSubTransactionId
Definition: c.h:403
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:400
void RelationCloseSmgrByOid ( Oid  relationId)

Definition at line 2863 of file relcache.c.

References PointerIsValid, RelationCloseSmgr, and RelationIdCacheLookup.

Referenced by swap_relation_files().

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

Definition at line 2684 of file relcache.c.

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

Referenced by heap_drop_with_catalog(), and index_drop().

2685 {
2686  Relation relation;
2687 
2688  RelationIdCacheLookup(rid, relation);
2689 
2690  if (!PointerIsValid(relation))
2691  return; /* not in cache, nothing to do */
2692 
2693  if (!RelationHasReferenceCountZero(relation))
2694  elog(ERROR, "relation %u is still open", rid);
2695 
2696  /* Unconditionally destroy the relcache entry */
2697  RelationClearRelation(relation, false);
2698 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2392
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:202
#define ERROR
Definition: elog.h:43
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:400
#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 5058 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().

5062 {
5063  int ncols = indexRelation->rd_rel->relnatts;
5064  Oid *ops;
5065  Oid *funcs;
5066  uint16 *strats;
5067  Relation conrel;
5068  SysScanDesc conscan;
5069  ScanKeyData skey[1];
5070  HeapTuple htup;
5071  bool found;
5072  MemoryContext oldcxt;
5073  int i;
5074 
5075  /* Allocate result space in caller context */
5076  *operators = ops = (Oid *) palloc(sizeof(Oid) * ncols);
5077  *procs = funcs = (Oid *) palloc(sizeof(Oid) * ncols);
5078  *strategies = strats = (uint16 *) palloc(sizeof(uint16) * ncols);
5079 
5080  /* Quick exit if we have the data cached already */
5081  if (indexRelation->rd_exclstrats != NULL)
5082  {
5083  memcpy(ops, indexRelation->rd_exclops, sizeof(Oid) * ncols);
5084  memcpy(funcs, indexRelation->rd_exclprocs, sizeof(Oid) * ncols);
5085  memcpy(strats, indexRelation->rd_exclstrats, sizeof(uint16) * ncols);
5086  return;
5087  }
5088 
5089  /*
5090  * Search pg_constraint for the constraint associated with the index. To
5091  * make this not too painfully slow, we use the index on conrelid; that
5092  * will hold the parent relation's OID not the index's own OID.
5093  */
5094  ScanKeyInit(&skey[0],
5096  BTEqualStrategyNumber, F_OIDEQ,
5097  ObjectIdGetDatum(indexRelation->rd_index->indrelid));
5098 
5100  conscan = systable_beginscan(conrel, ConstraintRelidIndexId, true,
5101  NULL, 1, skey);
5102  found = false;
5103 
5104  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
5105  {
5107  Datum val;
5108  bool isnull;
5109  ArrayType *arr;
5110  int nelem;
5111 
5112  /* We want the exclusion constraint owning the index */
5113  if (conform->contype != CONSTRAINT_EXCLUSION ||
5114  conform->conindid != RelationGetRelid(indexRelation))
5115  continue;
5116 
5117  /* There should be only one */
5118  if (found)
5119  elog(ERROR, "unexpected exclusion constraint record found for rel %s",
5120  RelationGetRelationName(indexRelation));
5121  found = true;
5122 
5123  /* Extract the operator OIDS from conexclop */
5124  val = fastgetattr(htup,
5126  conrel->rd_att, &isnull);
5127  if (isnull)
5128  elog(ERROR, "null conexclop for rel %s",
5129  RelationGetRelationName(indexRelation));
5130 
5131  arr = DatumGetArrayTypeP(val); /* ensure not toasted */
5132  nelem = ARR_DIMS(arr)[0];
5133  if (ARR_NDIM(arr) != 1 ||
5134  nelem != ncols ||
5135  ARR_HASNULL(arr) ||
5136  ARR_ELEMTYPE(arr) != OIDOID)
5137  elog(ERROR, "conexclop is not a 1-D Oid array");
5138 
5139  memcpy(ops, ARR_DATA_PTR(arr), sizeof(Oid) * ncols);
5140  }
5141 
5142  systable_endscan(conscan);
5143  heap_close(conrel, AccessShareLock);
5144 
5145  if (!found)
5146  elog(ERROR, "exclusion constraint record missing for rel %s",
5147  RelationGetRelationName(indexRelation));
5148 
5149  /* We need the func OIDs and strategy numbers too */
5150  for (i = 0; i < ncols; i++)
5151  {
5152  funcs[i] = get_opcode(ops[i]);
5153  strats[i] = get_op_opfamily_strategy(ops[i],
5154  indexRelation->rd_opfamily[i]);
5155  /* shouldn't fail, since it was checked at index creation */
5156  if (strats[i] == InvalidStrategy)
5157  elog(ERROR, "could not find strategy for operator %u in family %u",
5158  ops[i], indexRelation->rd_opfamily[i]);
5159  }
5160 
5161  /* Save a copy of the results in the relcache entry. */
5162  oldcxt = MemoryContextSwitchTo(indexRelation->rd_indexcxt);
5163  indexRelation->rd_exclops = (Oid *) palloc(sizeof(Oid) * ncols);
5164  indexRelation->rd_exclprocs = (Oid *) palloc(sizeof(Oid) * ncols);
5165  indexRelation->rd_exclstrats = (uint16 *) palloc(sizeof(uint16) * ncols);
5166  memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * ncols);
5167  memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * ncols);
5168  memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * ncols);
5169  MemoryContextSwitchTo(oldcxt);
5170 }
#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:436
#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:416
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 4186 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().

4187 {
4188  List *result;
4189  Relation conrel;
4190  SysScanDesc conscan;
4191  ScanKeyData skey;
4192  HeapTuple htup;
4193  List *oldlist;
4194  MemoryContext oldcxt;
4195 
4196  /* Quick exit if we already computed the list. */
4197  if (relation->rd_fkeyvalid)
4198  return relation->rd_fkeylist;
4199 
4200  /* Fast path: if it doesn't have any triggers, it can't have FKs */
4201  if (!relation->rd_rel->relhastriggers)
4202  return NIL;
4203 
4204  /*
4205  * We build the list we intend to return (in the caller's context) while
4206  * doing the scan. After successfully completing the scan, we copy that
4207  * list into the relcache entry. This avoids cache-context memory leakage
4208  * if we get some sort of error partway through.
4209  */
4210  result = NIL;
4211 
4212  /* Prepare to scan pg_constraint for entries having conrelid = this rel. */
4213  ScanKeyInit(&skey,
4215  BTEqualStrategyNumber, F_OIDEQ,
4216  ObjectIdGetDatum(RelationGetRelid(relation)));
4217 
4219  conscan = systable_beginscan(conrel, ConstraintRelidIndexId, true,
4220  NULL, 1, &skey);
4221 
4222  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4223  {
4224  Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(htup);
4225  ForeignKeyCacheInfo *info;
4226  Datum adatum;
4227  bool isnull;
4228  ArrayType *arr;
4229  int nelem;
4230 
4231  /* consider only foreign keys */
4232  if (constraint->contype != CONSTRAINT_FOREIGN)
4233  continue;
4234 
4235  info = makeNode(ForeignKeyCacheInfo);
4236  info->conrelid = constraint->conrelid;
4237  info->confrelid = constraint->confrelid;
4238 
4239  /* Extract data from conkey field */
4240  adatum = fastgetattr(htup, Anum_pg_constraint_conkey,
4241  conrel->rd_att, &isnull);
4242  if (isnull)
4243  elog(ERROR, "null conkey for rel %s",
4244  RelationGetRelationName(relation));
4245 
4246  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
4247  nelem = ARR_DIMS(arr)[0];
4248  if (ARR_NDIM(arr) != 1 ||
4249  nelem < 1 ||
4250  nelem > INDEX_MAX_KEYS ||
4251  ARR_HASNULL(arr) ||
4252  ARR_ELEMTYPE(arr) != INT2OID)
4253  elog(ERROR, "conkey is not a 1-D smallint array");
4254 
4255  info->nkeys = nelem;
4256  memcpy(info->conkey, ARR_DATA_PTR(arr), nelem * sizeof(AttrNumber));
4257 
4258  /* Likewise for confkey */
4259  adatum = fastgetattr(htup, Anum_pg_constraint_confkey,
4260  conrel->rd_att, &isnull);
4261  if (isnull)
4262  elog(ERROR, "null confkey for rel %s",
4263  RelationGetRelationName(relation));
4264 
4265  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
4266  nelem = ARR_DIMS(arr)[0];
4267  if (ARR_NDIM(arr) != 1 ||
4268  nelem != info->nkeys ||
4269  ARR_HASNULL(arr) ||
4270  ARR_ELEMTYPE(arr) != INT2OID)
4271  elog(ERROR, "confkey is not a 1-D smallint array");
4272 
4273  memcpy(info->confkey, ARR_DATA_PTR(arr), nelem * sizeof(AttrNumber));
4274 
4275  /* Likewise for conpfeqop */
4277  conrel->rd_att, &isnull);
4278  if (isnull)
4279  elog(ERROR, "null conpfeqop for rel %s",
4280  RelationGetRelationName(relation));
4281 
4282  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
4283  nelem = ARR_DIMS(arr)[0];
4284  if (ARR_NDIM(arr) != 1 ||
4285  nelem != info->nkeys ||
4286  ARR_HASNULL(arr) ||
4287  ARR_ELEMTYPE(arr) != OIDOID)
4288  elog(ERROR, "conpfeqop is not a 1-D OID array");
4289 
4290  memcpy(info->conpfeqop, ARR_DATA_PTR(arr), nelem * sizeof(Oid));
4291 
4292  /* Add FK's node to the result list */
4293  result = lappend(result, info);
4294  }
4295 
4296  systable_endscan(conscan);
4297  heap_close(conrel, AccessShareLock);
4298 
4299  /* Now save a copy of the completed list in the relcache entry. */
4301  oldlist = relation->rd_fkeylist;
4302  relation->rd_fkeylist = copyObject(result);
4303  relation->rd_fkeyvalid = true;
4304  MemoryContextSwitchTo(oldcxt);
4305 
4306  /* Don't leak the old list, if there is one */
4307  list_free_deep(oldlist);
4308 
4309  return result;
4310 }
#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:1633
#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:436
#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:622
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:416
#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 4851 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().

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

4706 {
4707  List *result;
4708  Datum exprsDatum;
4709  bool isnull;
4710  char *exprsString;
4711  MemoryContext oldcxt;
4712 
4713  /* Quick exit if we already computed the result. */
4714  if (relation->rd_indexprs)
4715  return copyObject(relation->rd_indexprs);
4716 
4717  /* Quick exit if there is nothing to do. */
4718  if (relation->rd_indextuple == NULL ||
4720  return NIL;
4721 
4722  /*
4723  * We build the tree we intend to return in the caller's context. After
4724  * successfully completing the work, we copy it into the relcache entry.
4725  * This avoids problems if we get some sort of error partway through.
4726  */
4727  exprsDatum = heap_getattr(relation->rd_indextuple,
4730  &isnull);
4731  Assert(!isnull);
4732  exprsString = TextDatumGetCString(exprsDatum);
4733  result = (List *) stringToNode(exprsString);
4734  pfree(exprsString);
4735 
4736  /*
4737  * Run the expressions through eval_const_expressions. This is not just an
4738  * optimization, but is necessary, because the planner will be comparing
4739  * them to similarly-processed qual clauses, and may fail to detect valid
4740  * matches without this. We don't bother with canonicalize_qual, however.
4741  */
4742  result = (List *) eval_const_expressions(NULL, (Node *) result);
4743 
4744  result = (List *) canonicalize_qual((Expr *) result);
4745 
4746  /* May as well fix opfuncids too */
4747  fix_opfuncids((Node *) result);
4748 
4749  /* Now save a copy of the completed tree in the relcache entry. */
4750  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4751  relation->rd_indexprs = copyObject(result);
4752  MemoryContextSwitchTo(oldcxt);
4753 
4754  return result;
4755 }
#define NIL
Definition: pg_list.h:69
void * stringToNode(char *str)
Definition: read.c:38
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1582
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:2421
return result
Definition: formatting.c:1633
struct HeapTupleData * rd_indextuple
Definition: rel.h:161
void pfree(void *pointer)
Definition: mcxt.c:950
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4002
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:622
Definition: pg_list.h:45
#define Anum_pg_index_indexprs
Definition: pg_index.h:91
List* RelationGetIndexList ( Relation  relation)

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

4350 {
4351  Relation indrel;
4352  SysScanDesc indscan;
4353  ScanKeyData skey;
4354  HeapTuple htup;
4355  List *result;
4356  List *oldlist;
4357  char replident = relation->rd_rel->relreplident;
4358  Oid oidIndex = InvalidOid;
4359  Oid pkeyIndex = InvalidOid;
4360  Oid candidateIndex = InvalidOid;
4361  MemoryContext oldcxt;
4362 
4363  /* Quick exit if we already computed the list. */
4364  if (relation->rd_indexvalid != 0)
4365  return list_copy(relation->rd_indexlist);
4366 
4367  /*
4368  * We build the list we intend to return (in the caller's context) while
4369  * doing the scan. After successfully completing the scan, we copy that
4370  * list into the relcache entry. This avoids cache-context memory leakage
4371  * if we get some sort of error partway through.
4372  */
4373  result = NIL;
4374  oidIndex = InvalidOid;
4375 
4376  /* Prepare to scan pg_index for entries having indrelid = this rel. */
4377  ScanKeyInit(&skey,
4379  BTEqualStrategyNumber, F_OIDEQ,
4380  ObjectIdGetDatum(RelationGetRelid(relation)));
4381 
4383  indscan = systable_beginscan(indrel, IndexIndrelidIndexId, true,
4384  NULL, 1, &skey);
4385 
4386  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4387  {
4389  Datum indclassDatum;
4390  oidvector *indclass;
4391  bool isnull;
4392 
4393  /*
4394  * Ignore any indexes that are currently being dropped. This will
4395  * prevent them from being searched, inserted into, or considered in
4396  * HOT-safety decisions. It's unsafe to touch such an index at all
4397  * since its catalog entries could disappear at any instant.
4398  */
4399  if (!IndexIsLive(index))
4400  continue;
4401 
4402  /* Add index's OID to result list in the proper order */
4403  result = insert_ordered_oid(result, index->indexrelid);
4404 
4405  /*
4406  * indclass cannot be referenced directly through the C struct,
4407  * because it comes after the variable-width indkey field. Must
4408  * extract the datum the hard way...
4409  */
4410  indclassDatum = heap_getattr(htup,
4413  &isnull);
4414  Assert(!isnull);
4415  indclass = (oidvector *) DatumGetPointer(indclassDatum);
4416 
4417  /*
4418  * Invalid, non-unique, non-immediate or predicate indexes aren't
4419  * interesting for either oid indexes or replication identity indexes,
4420  * so don't check them.
4421  */
4422  if (!IndexIsValid(index) || !index->indisunique ||
4423  !index->indimmediate ||
4425  continue;
4426 
4427  /* Check to see if is a usable btree index on OID */
4428  if (index->indnatts == 1 &&
4429  index->indkey.values[0] == ObjectIdAttributeNumber &&
4430  indclass->values[0] == OID_BTREE_OPS_OID)
4431  oidIndex = index->indexrelid;
4432 
4433  /* remember primary key index if any */
4434  if (index->indisprimary)
4435  pkeyIndex = index->indexrelid;
4436 
4437  /* remember explicitly chosen replica index */
4438  if (index->indisreplident)
4439  candidateIndex = index->indexrelid;
4440  }
4441 
4442  systable_endscan(indscan);
4443 
4444  heap_close(indrel, AccessShareLock);
4445 
4446  /* Now save a copy of the completed list in the relcache entry. */
4448  oldlist = relation->rd_indexlist;
4449  relation->rd_indexlist = list_copy(result);
4450  relation->rd_oidindex = oidIndex;
4451  relation->rd_pkindex = pkeyIndex;
4452  if (replident == REPLICA_IDENTITY_DEFAULT && OidIsValid(pkeyIndex))
4453  relation->rd_replidindex = pkeyIndex;
4454  else if (replident == REPLICA_IDENTITY_INDEX && OidIsValid(candidateIndex))
4455  relation->rd_replidindex = candidateIndex;
4456  else
4457  relation->rd_replidindex = InvalidOid;
4458  relation->rd_indexvalid = 1;
4459  MemoryContextSwitchTo(oldcxt);
4460 
4461  /* Don't leak the old list, if there is one */
4462  list_free(oldlist);
4463 
4464  return result;
4465 }
#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:4555
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:1633
#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:89
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:4002
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:416
#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 4768 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().

4769 {
4770  List *result;
4771  Datum predDatum;
4772  bool isnull;
4773  char *predString;
4774  MemoryContext oldcxt;
4775 
4776  /* Quick exit if we already computed the result. */
4777  if (relation->rd_indpred)
4778  return copyObject(relation->rd_indpred);
4779 
4780  /* Quick exit if there is nothing to do. */
4781  if (relation->rd_indextuple == NULL ||
4783  return NIL;
4784 
4785  /*
4786  * We build the tree we intend to return in the caller's context. After
4787  * successfully completing the work, we copy it into the relcache entry.
4788  * This avoids problems if we get some sort of error partway through.
4789  */
4790  predDatum = heap_getattr(relation->rd_indextuple,
4793  &isnull);
4794  Assert(!isnull);
4795  predString = TextDatumGetCString(predDatum);
4796  result = (List *) stringToNode(predString);
4797  pfree(predString);
4798 
4799  /*
4800  * Run the expression through const-simplification and canonicalization.
4801  * This is not just an optimization, but is necessary, because the planner
4802  * will be comparing it to similarly-processed qual clauses, and may fail
4803  * to detect valid matches without this. This must match the processing
4804  * done to qual clauses in preprocess_expression()! (We can skip the
4805  * stuff involving subqueries, however, since we don't allow any in index
4806  * predicates.)
4807  */
4808  result = (List *) eval_const_expressions(NULL, (Node *) result);
4809 
4810  result = (List *) canonicalize_qual((Expr *) result);
4811 
4812  /* Also convert to implicit-AND format */
4813  result = make_ands_implicit((Expr *) result);
4814 
4815  /* May as well fix opfuncids too */
4816  fix_opfuncids((Node *) result);
4817 
4818  /* Now save a copy of the completed tree in the relcache entry. */
4819  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4820  relation->rd_indpred = copyObject(result);
4821  MemoryContextSwitchTo(oldcxt);
4822 
4823  return result;
4824 }
#define NIL
Definition: pg_list.h:69
void * stringToNode(char *str)
Definition: read.c:38
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1582
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:509
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2421
return result
Definition: formatting.c:1633
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:4002
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:622
Definition: pg_list.h:45
Oid RelationGetOidIndex ( Relation  relation)

Definition at line 4631 of file relcache.c.

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

Referenced by GetNewOid().

4632 {
4633  List *ilist;
4634 
4635  /*
4636  * If relation doesn't have OIDs at all, caller is probably confused. (We
4637  * could just silently return InvalidOid, but it seems better to throw an
4638  * assertion.)
4639  */
4640  Assert(relation->rd_rel->relhasoids);
4641 
4642  if (relation->rd_indexvalid == 0)
4643  {
4644  /* RelationGetIndexList does the heavy lifting. */
4645  ilist = RelationGetIndexList(relation);
4646  list_free(ilist);
4647  Assert(relation->rd_indexvalid != 0);
4648  }
4649 
4650  return relation->rd_oidindex;
4651 }
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:4349
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45
Oid RelationGetPrimaryKeyIndex ( Relation  relation)

Definition at line 4659 of file relcache.c.

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

Referenced by GetRelationIdentityOrPK().

4660 {
4661  List *ilist;
4662 
4663  if (relation->rd_indexvalid == 0)
4664  {
4665  /* RelationGetIndexList does the heavy lifting. */
4666  ilist = RelationGetIndexList(relation);
4667  list_free(ilist);
4668  Assert(relation->rd_indexvalid != 0);
4669  }
4670 
4671  return relation->rd_pkindex;
4672 }
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:4349
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45
Oid RelationGetReplicaIndex ( Relation  relation)

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

4681 {
4682  List *ilist;
4683 
4684  if (relation->rd_indexvalid == 0)
4685  {
4686  /* RelationGetIndexList does the heavy lifting. */
4687  ilist = RelationGetIndexList(relation);
4688  list_free(ilist);
4689  Assert(relation->rd_indexvalid != 0);
4690  }
4691 
4692  return relation->rd_replidindex;
4693 }
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:4349
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45
List* RelationGetStatExtList ( Relation  relation)

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

4490 {
4491  Relation indrel;
4492  SysScanDesc indscan;
4493  ScanKeyData skey;
4494  HeapTuple htup;
4495  List *result;
4496  List *oldlist;
4497  MemoryContext oldcxt;
4498 
4499  /* Quick exit if we already computed the list. */
4500  if (relation->rd_statvalid != 0)
4501  return list_copy(relation->rd_statlist);
4502 
4503  /*
4504  * We build the list we intend to return (in the caller's context) while
4505  * doing the scan. After successfully completing the scan, we copy that
4506  * list into the relcache entry. This avoids cache-context memory leakage
4507  * if we get some sort of error partway through.
4508  */
4509  result = NIL;
4510 
4511  /*
4512  * Prepare to scan pg_statistic_ext for entries having stxrelid = this
4513  * rel.
4514  */
4515  ScanKeyInit(&skey,
4517  BTEqualStrategyNumber, F_OIDEQ,
4518  ObjectIdGetDatum(RelationGetRelid(relation)));
4519 
4521  indscan = systable_beginscan(indrel, StatisticExtRelidIndexId, true,
4522  NULL, 1, &skey);
4523 
4524  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4525  result = insert_ordered_oid(result, HeapTupleGetOid(htup));
4526 
4527  systable_endscan(indscan);
4528 
4529  heap_close(indrel, AccessShareLock);
4530 
4531  /* Now save a copy of the completed list in the relcache entry. */
4533  oldlist = relation->rd_statlist;
4534  relation->rd_statlist = list_copy(result);
4535 
4536  relation->rd_statvalid = true;
4537  MemoryContextSwitchTo(oldcxt);
4538 
4539  /* Don't leak the old list, if there is one */
4540  list_free(oldlist);
4541 
4542  return result;
4543 }
#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:4555
List * list_copy(const List *oldlist)
Definition: list.c:1160
return result
Definition: formatting.c:1633
#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:416
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
Relation RelationIdGetRelation ( Oid  relationId)

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

2072 {
2073  Relation rd;
2074 
2075  /* Make sure we're in an xact, even if this ends up being a cache hit */
2077 
2078  /*
2079  * first try to find reldesc in the cache
2080  */
2081  RelationIdCacheLookup(relationId, rd);
2082 
2083  if (RelationIsValid(rd))
2084  {
2086  /* revalidate cache entry if necessary */
2087  if (!rd->rd_isvalid)
2088  {
2089  /*
2090  * Indexes only have a limited number of possible schema changes,
2091  * and we don't want to use the full-blown procedure because it's
2092  * a headache for indexes that reload itself depends on.
2093  */
2094  if (rd->rd_rel->relkind == RELKIND_INDEX)
2096  else
2097  RelationClearRelation(rd, true);
2098  Assert(rd->rd_isvalid);
2099  }
2100  return rd;
2101  }
2102 
2103  /*
2104  * no reldesc in the cache, so have RelationBuildDesc() build one and add
2105  * it.
2106  */
2107  rd = RelationBuildDesc(relationId, true);
2108  if (RelationIsValid(rd))
2110  return rd;
2111 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2392
#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:389
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2127
static void RelationReloadIndexInfo(Relation relation)
Definition: relcache.c:2201
#define Assert(condition)
Definition: c.h:675
static Relation RelationBuildDesc(Oid targetRelId, bool insertIt)
Definition: relcache.c:1237
bool IsTransactionState(void)
Definition: xact.c:350
#define RELKIND_INDEX
Definition: pg_class.h:161
bool RelationIdIsInInitFile ( Oid  relationId)

Definition at line 5964 of file relcache.c.

References Assert, RelationSupportsSysCache(), and TriggerRelidNameIndexId.

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

5965 {
5966  if (relationId == TriggerRelidNameIndexId)
5967  {
5968  /* If this Assert fails, we don't need this special case anymore. */
5969  Assert(!RelationSupportsSysCache(relationId));
5970  return true;
5971  }
5972  return RelationSupportsSysCache(relationId);
5973 }
#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 1509 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().

1510 {
1511  HeapTuple tuple;
1512  Form_pg_am aform;
1513  Datum indcollDatum;
1514  Datum indclassDatum;
1515  Datum indoptionDatum;
1516  bool isnull;
1517  oidvector *indcoll;
1518  oidvector *indclass;
1519  int2vector *indoption;
1520  MemoryContext indexcxt;
1521  MemoryContext oldcontext;
1522  int natts;
1523  uint16 amsupport;
1524 
1525  /*
1526  * Make a copy of the pg_index entry for the index. Since pg_index
1527  * contains variable-length and possibly-null fields, we have to do this
1528  * honestly rather than just treating it as a Form_pg_index struct.
1529  */
1530  tuple = SearchSysCache1(INDEXRELID,
1531  ObjectIdGetDatum(RelationGetRelid(relation)));
1532  if (!HeapTupleIsValid(tuple))
1533  elog(ERROR, "cache lookup failed for index %u",
1534  RelationGetRelid(relation));
1536  relation->rd_indextuple = heap_copytuple(tuple);
1537  relation->rd_index = (Form_pg_index) GETSTRUCT(relation->rd_indextuple);
1538  MemoryContextSwitchTo(oldcontext);
1539  ReleaseSysCache(tuple);
1540 
1541  /*
1542  * Look up the index's access method, save the OID of its handler function
1543  */
1544  tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(relation->rd_rel->relam));
1545  if (!HeapTupleIsValid(tuple))
1546  elog(ERROR, "cache lookup failed for access method %u",
1547  relation->rd_rel->relam);
1548  aform = (Form_pg_am) GETSTRUCT(tuple);
1549  relation->rd_amhandler = aform->amhandler;
1550  ReleaseSysCache(tuple);
1551 
1552  natts = relation->rd_rel->relnatts;
1553  if (natts != relation->rd_index->indnatts)
1554  elog(ERROR, "relnatts disagrees with indnatts for index %u",
1555  RelationGetRelid(relation));
1556 
1557  /*
1558  * Make the private context to hold index access info. The reason we need
1559  * a context, and not just a couple of pallocs, is so that we won't leak
1560  * any subsidiary info attached to fmgr lookup records.
1561  */
1563  RelationGetRelationName(relation),
1565  relation->rd_indexcxt = indexcxt;
1566 
1567  /*
1568  * Now we can fetch the index AM's API struct
1569  */
1570  InitIndexAmRoutine(relation);
1571 
1572  /*
1573  * Allocate arrays to hold data
1574  */
1575  relation->rd_opfamily = (Oid *)
1576  MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
1577  relation->rd_opcintype = (Oid *)
1578  MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
1579 
1580  amsupport = relation->rd_amroutine->amsupport;
1581  if (amsupport > 0)
1582  {
1583  int nsupport = natts * amsupport;
1584 
1585  relation->rd_support = (RegProcedure *)
1586  MemoryContextAllocZero(indexcxt, nsupport * sizeof(RegProcedure));
1587  relation->rd_supportinfo = (FmgrInfo *)
1588  MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
1589  }
1590  else
1591  {
1592  relation->rd_support = NULL;
1593  relation->rd_supportinfo = NULL;
1594  }
1595 
1596  relation->rd_indcollation = (Oid *)
1597  MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
1598 
1599  relation->rd_indoption = (int16 *)
1600  MemoryContextAllocZero(indexcxt, natts * sizeof(int16));
1601 
1602  /*
1603  * indcollation cannot be referenced directly through the C struct,
1604  * because it comes after the variable-width indkey field. Must extract
1605  * the datum the hard way...
1606  */
1607  indcollDatum = fastgetattr(relation->rd_indextuple,
1610  &isnull);
1611  Assert(!isnull);
1612  indcoll = (oidvector *) DatumGetPointer(indcollDatum);
1613  memcpy(relation->rd_indcollation, indcoll->values, natts * sizeof(Oid));
1614 
1615  /*
1616  * indclass cannot be referenced directly through the C struct, because it
1617  * comes after the variable-width indkey field. Must extract the datum
1618  * the hard way...
1619  */
1620  indclassDatum = fastgetattr(relation->rd_indextuple,
1623  &isnull);
1624  Assert(!isnull);
1625  indclass = (oidvector *) DatumGetPointer(indclassDatum);
1626 
1627  /*
1628  * Fill the support procedure OID array, as well as the info about
1629  * opfamilies and opclass input types. (aminfo and supportinfo are left
1630  * as zeroes, and are filled on-the-fly when used)
1631  */
1632  IndexSupportInitialize(indclass, relation->rd_support,
1633  relation->rd_opfamily, relation->rd_opcintype,
1634  amsupport, natts);
1635 
1636  /*
1637  * Similarly extract indoption and copy it to the cache entry
1638  */
1639  indoptionDatum = fastgetattr(relation->rd_indextuple,
1642  &isnull);
1643  Assert(!isnull);
1644  indoption = (int2vector *) DatumGetPointer(indoptionDatum);
1645  memcpy(relation->rd_indoption, indoption->values, natts * sizeof(int16));
1646 
1647  /*
1648  * expressions, predicate, exclusion caches will be filled later
1649  */
1650  relation->rd_indexprs = NIL;
1651  relation->rd_indpred = NIL;
1652  relation->rd_exclops = NULL;
1653  relation->rd_exclprocs = NULL;
1654  relation->rd_exclstrats = NULL;
1655  relation->rd_amcache = NULL;
1656 }
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:1485
#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:1672
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:4002
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:486
#define RelationGetRelationName(relation)
Definition: rel.h:436
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:416
#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 4600 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().

4601 {
4602  MemoryContext oldcxt;
4603 
4604  Assert(relation->rd_isnailed);
4605  /* Copy the list into the cache context (could fail for lack of mem) */
4607  indexIds = list_copy(indexIds);
4608  MemoryContextSwitchTo(oldcxt);
4609  /* Okay to replace old list */
4610  list_free(relation->rd_indexlist);
4611  relation->rd_indexlist = indexIds;
4612  relation->rd_oidindex = oidIndex;
4613 
4614  /*
4615  * For the moment, assume the target rel hasn't got a pk or replica index.
4616  * We'll load them on demand in the API that wraps access to them.
4617  */
4618  relation->rd_pkindex = InvalidOid;
4619  relation->rd_replidindex = InvalidOid;
4620  relation->rd_indexvalid = 2; /* mark list as forced */
4621  /* Flag relation as needing eoxact cleanup (to reset the list) */
4622  EOXactListAdd(relation);
4623 }
#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 3420 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 AlterSequence(), ExecuteTruncate(), reindex_index(), and ResetSequence().

3422 {
3423  Oid newrelfilenode;
3424  RelFileNodeBackend newrnode;
3425  Relation pg_class;
3426  HeapTuple tuple;
3427  Form_pg_class classform;
3428 
3429  /* Indexes, sequences must have Invalid frozenxid; other rels must not */
3430  Assert((relation->rd_rel->relkind == RELKIND_INDEX ||
3431  relation->rd_rel->relkind == RELKIND_SEQUENCE) ?
3432  freezeXid == InvalidTransactionId :
3433  TransactionIdIsNormal(freezeXid));
3434  Assert(TransactionIdIsNormal(freezeXid) == MultiXactIdIsValid(minmulti));
3435 
3436  /* Allocate a new relfilenode */
3437  newrelfilenode = GetNewRelFileNode(relation->rd_rel->reltablespace, NULL,
3438  persistence);
3439 
3440  /*
3441  * Get a writable copy of the pg_class tuple for the given relation.
3442  */
3444 
3445  tuple = SearchSysCacheCopy1(RELOID,
3446  ObjectIdGetDatum(RelationGetRelid(relation)));
3447  if (!HeapTupleIsValid(tuple))
3448  elog(ERROR, "could not find tuple for relation %u",
3449  RelationGetRelid(relation));
3450  classform = (Form_pg_class) GETSTRUCT(tuple);
3451 
3452  /*
3453  * Create storage for the main fork of the new relfilenode.
3454  *
3455  * NOTE: any conflict in relfilenode value will be caught here, if
3456  * GetNewRelFileNode messes up for any reason.
3457  */
3458  newrnode.node = relation->rd_node;
3459  newrnode.node.relNode = newrelfilenode;
3460  newrnode.backend = relation->rd_backend;
3461  RelationCreateStorage(newrnode.node, persistence);
3462  smgrclosenode(newrnode);
3463 
3464  /*
3465  * Schedule unlinking of the old storage at transaction commit.
3466  */
3467  RelationDropStorage(relation);
3468 
3469  /*
3470  * Now update the pg_class row. However, if we're dealing with a mapped
3471  * index, pg_class.relfilenode doesn't change; instead we have to send the
3472  * update to the relation mapper.
3473  */
3474  if (RelationIsMapped(relation))
3476  newrelfilenode,
3477  relation->rd_rel->relisshared,
3478  false);
3479  else
3480  classform->relfilenode = newrelfilenode;
3481 
3482  /* These changes are safe even for a mapped relation */
3483  if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
3484  {
3485  classform->relpages = 0; /* it's empty until further notice */
3486  classform->reltuples = 0;
3487  classform->relallvisible = 0;
3488  }
3489  classform->relfrozenxid = freezeXid;
3490  classform->relminmxid = minmulti;
3491  classform->relpersistence = persistence;
3492 
3493  CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
3494 
3495  heap_freetuple(tuple);
3496 
3497  heap_close(pg_class, RowExclusiveLock);
3498 
3499  /*
3500  * Make the pg_class row change visible, as well as the relation map
3501  * change if any. This will cause the relcache entry to get updated, too.
3502  */
3504 
3505  /*
3506  * Mark the rel as having been given a new relfilenode in the current
3507  * (sub) transaction. This is a hint that can be used to optimize later
3508  * operations on the rel in the same transaction.
3509  */
3511 
3512  /* Flag relation as needing eoxact cleanup (to remove the hint) */
3513  EOXactListAdd(relation);
3514 }
#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:453
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:395
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:416
void RelationMapUpdateMap(Oid relationId, Oid fileNode, bool shared, bool immediate)
Definition: relmapper.c:248

Variable Documentation

bool criticalSharedRelcachesBuilt