PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
relcache.h File Reference
#include "access/tupdesc.h"
#include "nodes/bitmapset.h"
Include dependency graph for relcache.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef struct RelationDataRelation
 
typedef RelationRelationPtr
 
typedef enum IndexAttrBitmapKind IndexAttrBitmapKind
 

Enumerations

enum  IndexAttrBitmapKind { INDEX_ATTR_BITMAP_ALL, INDEX_ATTR_BITMAP_KEY, INDEX_ATTR_BITMAP_PRIMARY_KEY, INDEX_ATTR_BITMAP_IDENTITY_KEY }
 

Functions

Relation RelationIdGetRelation (Oid relationId)
 
void RelationClose (Relation relation)
 
ListRelationGetFKeyList (Relation relation)
 
ListRelationGetIndexList (Relation relation)
 
ListRelationGetStatExtList (Relation relation)
 
Oid RelationGetOidIndex (Relation relation)
 
Oid RelationGetPrimaryKeyIndex (Relation relation)
 
Oid RelationGetReplicaIndex (Relation relation)
 
ListRelationGetIndexExpressions (Relation relation)
 
ListRelationGetIndexPredicate (Relation relation)
 
BitmapsetRelationGetIndexAttrBitmap (Relation relation, IndexAttrBitmapKind keyAttrs)
 
void RelationGetExclusionInfo (Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
 
void RelationSetIndexList (Relation relation, List *indexIds, Oid oidIndex)
 
void RelationInitIndexAccessInfo (Relation relation)
 
struct PublicationActionsGetRelationPublicationActions (Relation relation)
 
int errtable (Relation rel)
 
int errtablecol (Relation rel, int attnum)
 
int errtablecolname (Relation rel, const char *colname)
 
int errtableconstraint (Relation rel, const char *conname)
 
void RelationCacheInitialize (void)
 
void RelationCacheInitializePhase2 (void)
 
void RelationCacheInitializePhase3 (void)
 
Relation RelationBuildLocalRelation (const char *relname, Oid relnamespace, TupleDesc tupDesc, Oid relid, Oid relfilenode, Oid reltablespace, bool shared_relation, bool mapped_relation, char relpersistence, char relkind)
 
void RelationSetNewRelfilenode (Relation relation, char persistence, TransactionId freezeXid, MultiXactId minmulti)
 
void RelationForgetRelation (Oid rid)
 
void RelationCacheInvalidateEntry (Oid relationId)
 
void RelationCacheInvalidate (void)
 
void RelationCloseSmgrByOid (Oid relationId)
 
void AtEOXact_RelationCache (bool isCommit)
 
void AtEOSubXact_RelationCache (bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
 
bool RelationIdIsInInitFile (Oid relationId)
 
void RelationCacheInitFilePreInvalidate (void)
 
void RelationCacheInitFilePostInvalidate (void)
 
void RelationCacheInitFileRemove (void)
 

Variables

bool criticalRelcachesBuilt
 
bool criticalSharedRelcachesBuilt
 

Typedef Documentation

Definition at line 21 of file relcache.h.

Definition at line 29 of file relcache.h.

Enumeration Type Documentation

Enumerator
INDEX_ATTR_BITMAP_ALL 
INDEX_ATTR_BITMAP_KEY 
INDEX_ATTR_BITMAP_PRIMARY_KEY 
INDEX_ATTR_BITMAP_IDENTITY_KEY 

Definition at line 49 of file relcache.h.

Function Documentation

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

Definition at line 3067 of file relcache.c.

References AtEOSubXact_cleanup(), eoxact_list, eoxact_list_len, eoxact_list_overflowed, HASH_FIND, hash_search(), hash_seq_init(), hash_seq_search(), i, NULL, relidcacheent::reldesc, and status().

Referenced by AbortSubTransaction(), and CommitSubTransaction().

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

Definition at line 2916 of file relcache.c.

References Assert, AtEOXact_cleanup(), eoxact_list, eoxact_list_len, eoxact_list_overflowed, EOXactTupleDescArrayLen, FreeTupleDesc(), HASH_FIND, hash_search(), hash_seq_init(), hash_seq_search(), i, NextEOXactTupleDescNum, NULL, pfree(), relidcacheent::reldesc, and status().

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

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

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

Definition at line 5249 of file relcache.c.

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

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

5250 {
5251  TupleDesc reldesc = RelationGetDescr(rel);
5252  const char *colname;
5253 
5254  /* Use reldesc if it's a user attribute, else consult the catalogs */
5255  if (attnum > 0 && attnum <= reldesc->natts)
5256  colname = NameStr(reldesc->attrs[attnum - 1]->attname);
5257  else
5258  colname = get_relid_attribute_name(RelationGetRelid(rel), attnum);
5259 
5260  return errtablecolname(rel, colname);
5261 }
#define RelationGetDescr(relation)
Definition: rel.h:429
Form_pg_attribute * attrs
Definition: tupdesc.h:74
char * get_relid_attribute_name(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:801
#define NameStr(name)
Definition: c.h:499
#define RelationGetRelid(relation)
Definition: rel.h:417
int errtablecolname(Relation rel, const char *colname)
Definition: relcache.c:5273
int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5273 of file relcache.c.

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

Referenced by errtablecol().

5274 {
5275  errtable(rel);
5277 
5278  return 0; /* return value does not matter */
5279 }
#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:5232
int errtableconstraint ( Relation  rel,
const char *  conname 
)

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

5287 {
5288  errtable(rel);
5290 
5291  return 0; /* return value does not matter */
5292 }
#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:5232
struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

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

5162 {
5163  List *puboids;
5164  ListCell *lc;
5165  MemoryContext oldcxt;
5166  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5167 
5168  if (relation->rd_pubactions)
5169  return memcpy(pubactions, relation->rd_pubactions,
5170  sizeof(PublicationActions));
5171 
5172  /* Fetch the publication membership info. */
5173  puboids = GetRelationPublications(RelationGetRelid(relation));
5174  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5175 
5176  foreach(lc, puboids)
5177  {
5178  Oid pubid = lfirst_oid(lc);
5179  HeapTuple tup;
5180  Form_pg_publication pubform;
5181 
5183 
5184  if (!HeapTupleIsValid(tup))
5185  elog(ERROR, "cache lookup failed for publication %u", pubid);
5186 
5187  pubform = (Form_pg_publication) GETSTRUCT(tup);
5188 
5189  pubactions->pubinsert |= pubform->pubinsert;
5190  pubactions->pubupdate |= pubform->pubupdate;
5191  pubactions->pubdelete |= pubform->pubdelete;
5192 
5193  ReleaseSysCache(tup);
5194 
5195  /*
5196  * If we know everything is replicated, there is no point to check
5197  * for other publications.
5198  */
5199  if (pubactions->pubinsert && pubactions->pubupdate &&
5200  pubactions->pubdelete)
5201  break;
5202  }
5203 
5204  if (relation->rd_pubactions)
5205  {
5206  pfree(relation->rd_pubactions);
5207  relation->rd_pubactions = NULL;
5208  }
5209 
5210  /* Now save copy of the actions in the relcache entry. */
5212  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5213  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5214  MemoryContextSwitchTo(oldcxt);
5215 
5216  return pubactions;
5217 }
#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:152
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:1116
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
List * GetAllTablesPublications(void)
void * palloc(Size size)
Definition: mcxt.c:849
#define elog
Definition: elog.h:219
FormData_pg_publication * Form_pg_publication
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:417
#define lfirst_oid(lc)
Definition: pg_list.h:108
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
Relation RelationBuildLocalRelation ( const char *  relname,
Oid  relnamespace,
TupleDesc  tupDesc,
Oid  relid,
Oid  relfilenode,
Oid  reltablespace,
bool  shared_relation,
bool  mapped_relation,
char  relpersistence,
char  relkind 
)

Definition at line 3179 of file relcache.c.

References Assert, AssertArg, AttributeRelationId, tupleDesc::attrs, AuthIdRelationId, AuthMemRelationId, BackendIdForTempRelations, BOOTSTRAP_SUPERUSERID, CacheMemoryContext, CLASS_TUPLE_SIZE, tupleDesc::constr, CreateCacheMemoryContext(), CreateTupleDescCopy(), DatabaseRelationId, elog, EOXactListAdd, ERROR, GetCurrentSubTransactionId(), tupleConstr::has_not_null, i, InvalidBackendId, InvalidOid, InvalidSubTransactionId, IsSharedRelation(), IsSystemNamespace(), isTempOrTempToastNamespace(), MemoryContextSwitchTo(), namestrcpy(), tupleDesc::natts, NULL, palloc0(), ProcedureRelationId, RelationData::rd_att, RelationData::rd_backend, RelationData::rd_createSubid, RelationData::rd_islocaltemp, RelationData::rd_isnailed, RelationData::rd_isvalid, RelationData::rd_newRelfilenodeSubid, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_smgr, RelationCacheInsert, RelationGetRelid, RelationIncrementReferenceCount(), RelationInitLockInfo(), RelationInitPhysicalAddr(), RelationMapUpdateMap(), RelationRelationId, RELKIND_MATVIEW, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, RELPERSISTENCE_PERMANENT, RELPERSISTENCE_TEMP, RELPERSISTENCE_UNLOGGED, REPLICA_IDENTITY_DEFAULT, REPLICA_IDENTITY_NOTHING, tupleDesc::tdhasoid, tupleDesc::tdrefcount, and TypeRelationId.

Referenced by heap_create().

3189 {
3190  Relation rel;
3191  MemoryContext oldcxt;
3192  int natts = tupDesc->natts;
3193  int i;
3194  bool has_not_null;
3195  bool nailit;
3196 
3197  AssertArg(natts >= 0);
3198 
3199  /*
3200  * check for creation of a rel that must be nailed in cache.
3201  *
3202  * XXX this list had better match the relations specially handled in
3203  * RelationCacheInitializePhase2/3.
3204  */
3205  switch (relid)
3206  {
3207  case DatabaseRelationId:
3208  case AuthIdRelationId:
3209  case AuthMemRelationId:
3210  case RelationRelationId:
3211  case AttributeRelationId:
3212  case ProcedureRelationId:
3213  case TypeRelationId:
3214  nailit = true;
3215  break;
3216  default:
3217  nailit = false;
3218  break;
3219  }
3220 
3221  /*
3222  * check that hardwired list of shared rels matches what's in the
3223  * bootstrap .bki file. If you get a failure here during initdb, you
3224  * probably need to fix IsSharedRelation() to match whatever you've done
3225  * to the set of shared relations.
3226  */
3227  if (shared_relation != IsSharedRelation(relid))
3228  elog(ERROR, "shared_relation flag for \"%s\" does not match IsSharedRelation(%u)",
3229  relname, relid);
3230 
3231  /* Shared relations had better be mapped, too */
3232  Assert(mapped_relation || !shared_relation);
3233 
3234  /*
3235  * switch to the cache context to create the relcache entry.
3236  */
3237  if (!CacheMemoryContext)
3239 
3241 
3242  /*
3243  * allocate a new relation descriptor and fill in basic state fields.
3244  */
3245  rel = (Relation) palloc0(sizeof(RelationData));
3246 
3247  /* make sure relation is marked as having no open file yet */
3248  rel->rd_smgr = NULL;
3249 
3250  /* mark it nailed if appropriate */
3251  rel->rd_isnailed = nailit;
3252 
3253  rel->rd_refcnt = nailit ? 1 : 0;
3254 
3255  /* it's being created in this transaction */
3258 
3259  /*
3260  * create a new tuple descriptor from the one passed in. We do this
3261  * partly to copy it into the cache context, and partly because the new
3262  * relation can't have any defaults or constraints yet; they have to be
3263  * added in later steps, because they require additions to multiple system
3264  * catalogs. We can copy attnotnull constraints here, however.
3265  */
3266  rel->rd_att = CreateTupleDescCopy(tupDesc);
3267  rel->rd_att->tdrefcount = 1; /* mark as refcounted */
3268  has_not_null = false;
3269  for (i = 0; i < natts; i++)
3270  {
3271  rel->rd_att->attrs[i]->attidentity = tupDesc->attrs[i]->attidentity;
3272  rel->rd_att->attrs[i]->attnotnull = tupDesc->attrs[i]->attnotnull;
3273  has_not_null |= tupDesc->attrs[i]->attnotnull;
3274  }
3275 
3276  if (has_not_null)
3277  {
3278  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
3279 
3280  constr->has_not_null = true;
3281  rel->rd_att->constr = constr;
3282  }
3283 
3284  /*
3285  * initialize relation tuple form (caller may add/override data later)
3286  */
3288 
3289  namestrcpy(&rel->rd_rel->relname, relname);
3290  rel->rd_rel->relnamespace = relnamespace;
3291 
3292  rel->rd_rel->relkind = relkind;
3293  rel->rd_rel->relhasoids = rel->rd_att->tdhasoid;
3294  rel->rd_rel->relnatts = natts;
3295  rel->rd_rel->reltype = InvalidOid;
3296  /* needed when bootstrapping: */
3297  rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;
3298 
3299  /* set up persistence and relcache fields dependent on it */
3300  rel->rd_rel->relpersistence = relpersistence;
3301  switch (relpersistence)
3302  {
3306  rel->rd_islocaltemp = false;
3307  break;
3308  case RELPERSISTENCE_TEMP:
3309  Assert(isTempOrTempToastNamespace(relnamespace));
3311  rel->rd_islocaltemp = true;
3312  break;
3313  default:
3314  elog(ERROR, "invalid relpersistence: %c", relpersistence);
3315  break;
3316  }
3317 
3318  /* if it's a materialized view, it's not populated initially */
3319  if (relkind == RELKIND_MATVIEW)
3320  rel->rd_rel->relispopulated = false;
3321  else
3322  rel->rd_rel->relispopulated = true;
3323 
3324  /* system relations and non-table objects don't have one */
3325  if (!IsSystemNamespace(relnamespace) &&
3326  (relkind == RELKIND_RELATION ||
3327  relkind == RELKIND_MATVIEW ||
3328  relkind == RELKIND_PARTITIONED_TABLE))
3329  rel->rd_rel->relreplident = REPLICA_IDENTITY_DEFAULT;
3330  else
3331  rel->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
3332 
3333  /*
3334  * Insert relation physical and logical identifiers (OIDs) into the right
3335  * places. For a mapped relation, we set relfilenode to zero and rely on
3336  * RelationInitPhysicalAddr to consult the map.
3337  */
3338  rel->rd_rel->relisshared = shared_relation;
3339 
3340  RelationGetRelid(rel) = relid;
3341 
3342  for (i = 0; i < natts; i++)
3343  rel->rd_att->attrs[i]->attrelid = relid;
3344 
3345  rel->rd_rel->reltablespace = reltablespace;
3346 
3347  if (mapped_relation)
3348  {
3349  rel->rd_rel->relfilenode = InvalidOid;
3350  /* Add it to the active mapping information */
3351  RelationMapUpdateMap(relid, relfilenode, shared_relation, true);
3352  }
3353  else
3354  rel->rd_rel->relfilenode = relfilenode;
3355 
3356  RelationInitLockInfo(rel); /* see lmgr.c */
3357 
3359 
3360  /*
3361  * Okay to insert into the relcache hash table.
3362  *
3363  * Ordinarily, there should certainly not be an existing hash entry for
3364  * the same OID; but during bootstrap, when we create a "real" relcache
3365  * entry for one of the bootstrap relations, we'll be overwriting the
3366  * phony one created with formrdesc. So allow that to happen for nailed
3367  * rels.
3368  */
3369  RelationCacheInsert(rel, nailit);
3370 
3371  /*
3372  * Flag relation as needing eoxact cleanup (to clear rd_createSubid). We
3373  * can't do this before storing relid in it.
3374  */
3375  EOXactListAdd(rel);
3376 
3377  /*
3378  * done building relcache entry.
3379  */
3380  MemoryContextSwitchTo(oldcxt);
3381 
3382  /* It's fully valid */
3383  rel->rd_isvalid = true;
3384 
3385  /*
3386  * Caller expects us to pin the returned entry.
3387  */
3389 
3390  return rel;
3391 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:141
#define EOXactListAdd(rel)
Definition: relcache.c:160
bool tdhasoid
Definition: tupdesc.h:79
#define RELPERSISTENCE_UNLOGGED
Definition: pg_class.h:171
#define REPLICA_IDENTITY_NOTHING
Definition: pg_class.h:177
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3032
#define ProcedureRelationId
Definition: pg_proc.h:33
#define AuthMemRelationId
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
#define DatabaseRelationId
Definition: pg_database.h:29
#define RelationRelationId
Definition: pg_class.h:29
bool rd_isnailed
Definition: rel.h:91
bool rd_islocaltemp
Definition: rel.h:90
Form_pg_attribute * attrs
Definition: tupdesc.h:74
#define RELKIND_MATVIEW
Definition: pg_class.h:165
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define REPLICA_IDENTITY_DEFAULT
Definition: pg_class.h:175
#define AttributeRelationId
Definition: pg_attribute.h:33
bool rd_isvalid
Definition: rel.h:92
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:111
Form_pg_class rd_rel
Definition: rel.h:114
#define TypeRelationId
Definition: pg_type.h:34
int namestrcpy(Name name, const char *str)
Definition: name.c:217
int natts
Definition: tupdesc.h:73
#define AuthIdRelationId
Definition: pg_authid.h:42
#define RELPERSISTENCE_PERMANENT
Definition: pg_class.h:170
struct RelationData * Relation
Definition: relcache.h:21
#define ERROR
Definition: elog.h:43
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1418
void RelationInitLockInfo(Relation relation)
Definition: lmgr.c:68
#define BackendIdForTempRelations()
Definition: backendid.h:34
#define AssertArg(condition)
Definition: c.h:677
bool has_not_null
Definition: tupdesc.h:43
SubTransactionId rd_createSubid
Definition: rel.h:110
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
#define InvalidBackendId
Definition: backendid.h:23
void * palloc0(Size size)
Definition: mcxt.c:878
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2123
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:219
TupleDesc rd_att
Definition: rel.h:115
bool IsSystemNamespace(Oid namespaceId)
Definition: catalog.c:162
#define InvalidOid
Definition: postgres_ext.h:36
#define RelationCacheInsert(RELATION, replace_allowed)
Definition: relcache.c:180
#define CLASS_TUPLE_SIZE
Definition: pg_class.h:87
#define NULL
Definition: c.h:229
BackendId rd_backend
Definition: rel.h:89
#define Assert(condition)
Definition: c.h:675
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:649
TupleConstr * constr
Definition: tupdesc.h:76
void CreateCacheMemoryContext(void)
Definition: catcache.c:525
#define BOOTSTRAP_SUPERUSERID
Definition: pg_authid.h:108
#define InvalidSubTransactionId
Definition: c.h:403
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
int rd_refcnt
Definition: rel.h:88
int tdrefcount
Definition: tupdesc.h:80
int i
#define elog
Definition: elog.h:219
#define RELPERSISTENCE_TEMP
Definition: pg_class.h:172
#define RELKIND_RELATION
Definition: pg_class.h:160
#define RelationGetRelid(relation)
Definition: rel.h:417
void RelationMapUpdateMap(Oid relationId, Oid fileNode, bool shared, bool immediate)
Definition: relmapper.c:248
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void RelationCacheInitFilePostInvalidate ( void  )

Definition at line 6057 of file relcache.c.

References LWLockRelease().

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

6058 {
6059  LWLockRelease(RelCacheInitLock);
6060 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
void RelationCacheInitFilePreInvalidate ( void  )

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

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

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

6073 {
6074  const char *tblspcdir = "pg_tblspc";
6075  DIR *dir;
6076  struct dirent *de;
6077  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6078 
6079  /*
6080  * We zap the shared cache file too. In theory it can't get out of sync
6081  * enough to be a problem, but in data-corruption cases, who knows ...
6082  */
6083  snprintf(path, sizeof(path), "global/%s",
6085  unlink_initfile(path);
6086 
6087  /* Scan everything in the default tablespace */
6089 
6090  /* Scan the tablespace link directory to find non-default tablespaces */
6091  dir = AllocateDir(tblspcdir);
6092  if (dir == NULL)
6093  {
6094  elog(LOG, "could not open tablespace link directory \"%s\": %m",
6095  tblspcdir);
6096  return;
6097  }
6098 
6099  while ((de = ReadDir(dir, tblspcdir)) != NULL)
6100  {
6101  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6102  {
6103  /* Scan the tablespace dir for per-database dirs */
6104  snprintf(path, sizeof(path), "%s/%s/%s",
6105  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6107  }
6108  }
6109 
6110  FreeDir(dir);
6111 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6115
#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:6145
#define NULL
Definition: c.h:229
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2401
#define TABLESPACE_VERSION_DIRECTORY
Definition: catalog.h:26
char d_name[MAX_PATH]
Definition: dirent.h:14
#define elog
Definition: elog.h:219
int FreeDir(DIR *dir)
Definition: fd.c:2444
void RelationCacheInitialize ( void  )

Definition at line 3528 of file relcache.c.

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

Referenced by InitPostgres().

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

Definition at line 3565 of file relcache.c.

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

Referenced by InitPostgres().

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

Definition at line 3624 of file relcache.c.

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

Referenced by InitPostgres().

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

Definition at line 2756 of file relcache.c.

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

Referenced by InvalidateSystemCaches(), and LocalExecuteInvalidationMessage().

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

Definition at line 2712 of file relcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

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

Definition at line 2156 of file relcache.c.

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

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

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

Definition at line 2859 of file relcache.c.

References PointerIsValid, RelationCloseSmgr, and RelationIdCacheLookup.

Referenced by swap_relation_files().

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

Definition at line 2680 of file relcache.c.

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

Referenced by heap_drop_with_catalog(), and index_drop().

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 4616 of file relcache.c.

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

Referenced by GetNewOid().

4617 {
4618  List *ilist;
4619 
4620  /*
4621  * If relation doesn't have OIDs at all, caller is probably confused. (We
4622  * could just silently return InvalidOid, but it seems better to throw an
4623  * assertion.)
4624  */
4625  Assert(relation->rd_rel->relhasoids);
4626 
4627  if (relation->rd_indexvalid == 0)
4628  {
4629  /* RelationGetIndexList does the heavy lifting. */
4630  ilist = RelationGetIndexList(relation);
4631  list_free(ilist);
4632  Assert(relation->rd_indexvalid != 0);
4633  }
4634 
4635  return relation->rd_oidindex;
4636 }
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:4338
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45
Oid RelationGetPrimaryKeyIndex ( Relation  relation)

Definition at line 4644 of file relcache.c.

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

Referenced by GetRelationIdentityOrPK().

4645 {
4646  List *ilist;
4647 
4648  if (relation->rd_indexvalid == 0)
4649  {
4650  /* RelationGetIndexList does the heavy lifting. */
4651  ilist = RelationGetIndexList(relation);
4652  list_free(ilist);
4653  Assert(relation->rd_indexvalid != 0);
4654  }
4655 
4656  return relation->rd_pkindex;
4657 }
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:4338
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45
Oid RelationGetReplicaIndex ( Relation  relation)

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

4666 {
4667  List *ilist;
4668 
4669  if (relation->rd_indexvalid == 0)
4670  {
4671  /* RelationGetIndexList does the heavy lifting. */
4672  ilist = RelationGetIndexList(relation);
4673  list_free(ilist);
4674  Assert(relation->rd_indexvalid != 0);
4675  }
4676 
4677  return relation->rd_replidindex;
4678 }
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:4338
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45
List* RelationGetStatExtList ( Relation  relation)

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

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

Definition at line 2067 of file relcache.c.

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

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

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

Definition at line 5948 of file relcache.c.

References Assert, RelationSupportsSysCache(), and TriggerRelidNameIndexId.

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

5949 {
5950  if (relationId == TriggerRelidNameIndexId)
5951  {
5952  /* If this Assert fails, we don't need this special case anymore. */
5953  Assert(!RelationSupportsSysCache(relationId));
5954  return true;
5955  }
5956  return RelationSupportsSysCache(relationId);
5957 }
#define TriggerRelidNameIndexId
Definition: indexing.h:249
#define Assert(condition)
Definition: c.h:675
bool RelationSupportsSysCache(Oid relid)
Definition: syscache.c:1401
void RelationInitIndexAccessInfo ( Relation  relation)

Definition at line 1505 of file relcache.c.

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate(), AMOID, IndexAmRoutine::amsupport, Anum_pg_index_indclass, Anum_pg_index_indcollation, Anum_pg_index_indoption, Assert, CacheMemoryContext, DatumGetPointer, elog, ERROR, fastgetattr, GetPgIndexDescriptor(), GETSTRUCT, heap_copytuple(), HeapTupleIsValid, INDEXRELID, IndexSupportInitialize(), InitIndexAmRoutine(), MemoryContextAllocZero(), MemoryContextSwitchTo(), NIL, NULL, ObjectIdGetDatum, RelationData::rd_amcache, RelationData::rd_amhandler, RelationData::rd_amroutine, RelationData::rd_exclops, RelationData::rd_exclprocs, RelationData::rd_exclstrats, RelationData::rd_indcollation, RelationData::rd_index, RelationData::rd_indexcxt, RelationData::rd_indexprs, RelationData::rd_indextuple, RelationData::rd_indoption, RelationData::rd_indpred, RelationData::rd_opcintype, RelationData::rd_opfamily, RelationData::rd_rel, RelationData::rd_support, RelationData::rd_supportinfo, RelationGetRelationName, RelationGetRelid, ReleaseSysCache(), SearchSysCache1, int2vector::values, and oidvector::values.

Referenced by index_create(), and RelationBuildDesc().

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

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

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

Definition at line 3416 of file relcache.c.

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

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

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

Variable Documentation

bool criticalSharedRelcachesBuilt