PostgreSQL Source Code  git master
relcache.h File Reference
#include "access/tupdesc.h"
#include "nodes/bitmapset.h"
Include dependency graph for relcache.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define RELCACHE_INIT_FILENAME   "pg_internal.init"
 

Typedefs

typedef struct RelationDataRelation
 
typedef RelationRelationPtr
 
typedef enum IndexAttrBitmapKind IndexAttrBitmapKind
 

Enumerations

enum  IndexAttrBitmapKind { INDEX_ATTR_BITMAP_ALL, INDEX_ATTR_BITMAP_KEY, INDEX_ATTR_BITMAP_PRIMARY_KEY, INDEX_ATTR_BITMAP_IDENTITY_KEY }
 

Functions

Relation RelationIdGetRelation (Oid relationId)
 
void RelationClose (Relation relation)
 
ListRelationGetFKeyList (Relation relation)
 
ListRelationGetIndexList (Relation relation)
 
ListRelationGetStatExtList (Relation relation)
 
Oid 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
 

Macro Definition Documentation

◆ RELCACHE_INIT_FILENAME

#define RELCACHE_INIT_FILENAME   "pg_internal.init"

Typedef Documentation

◆ IndexAttrBitmapKind

◆ Relation

Definition at line 26 of file relcache.h.

◆ RelationPtr

Definition at line 34 of file relcache.h.

Enumeration Type Documentation

◆ IndexAttrBitmapKind

Enumerator
INDEX_ATTR_BITMAP_ALL 
INDEX_ATTR_BITMAP_KEY 
INDEX_ATTR_BITMAP_PRIMARY_KEY 
INDEX_ATTR_BITMAP_IDENTITY_KEY 

Definition at line 54 of file relcache.h.

Function Documentation

◆ AtEOSubXact_RelationCache()

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

Definition at line 3078 of file relcache.c.

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

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

◆ AtEOXact_RelationCache()

void AtEOXact_RelationCache ( bool  isCommit)

Definition at line 2927 of file relcache.c.

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

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

2928 {
2930  RelIdCacheEnt *idhentry;
2931  int i;
2932 
2933  /*
2934  * Unless the eoxact_list[] overflowed, we only need to examine the rels
2935  * listed in it. Otherwise fall back on a hash_seq_search scan.
2936  *
2937  * For simplicity, eoxact_list[] entries are not deleted till end of
2938  * top-level transaction, even though we could remove them at
2939  * subtransaction end in some cases, or remove relations from the list if
2940  * they are cleared for other reasons. Therefore we should expect the
2941  * case that list entries are not found in the hashtable; if not, there's
2942  * nothing to do for them.
2943  */
2945  {
2946  hash_seq_init(&status, RelationIdCache);
2947  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2948  {
2949  AtEOXact_cleanup(idhentry->reldesc, isCommit);
2950  }
2951  }
2952  else
2953  {
2954  for (i = 0; i < eoxact_list_len; i++)
2955  {
2956  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
2957  (void *) &eoxact_list[i],
2958  HASH_FIND,
2959  NULL);
2960  if (idhentry != NULL)
2961  AtEOXact_cleanup(idhentry->reldesc, isCommit);
2962  }
2963  }
2964 
2965  if (EOXactTupleDescArrayLen > 0)
2966  {
2967  Assert(EOXactTupleDescArray != NULL);
2968  for (i = 0; i < NextEOXactTupleDescNum; i++)
2971  EOXactTupleDescArray = NULL;
2972  }
2973 
2974  /* Now we're out of the transaction and can clear the lists */
2975  eoxact_list_len = 0;
2976  eoxact_list_overflowed = false;
2977  NextEOXactTupleDescNum = 0;
2979 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:152
static int EOXactTupleDescArrayLen
Definition: relcache.c:171
Relation reldesc
Definition: relcache.c:116
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
static HTAB * RelationIdCache
Definition: relcache.c:119
static void AtEOXact_cleanup(Relation relation, bool isCommit)
Definition: relcache.c:2990
static bool eoxact_list_overflowed
Definition: relcache.c:154
static int NextEOXactTupleDescNum
Definition: relcache.c:170
void pfree(void *pointer)
Definition: mcxt.c:949
#define Assert(condition)
Definition: c.h:670
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1385
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1375
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:251
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
static int eoxact_list_len
Definition: relcache.c:153
static TupleDesc * EOXactTupleDescArray
Definition: relcache.c:169

◆ errtable()

int errtable ( Relation  rel)

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

5259 {
5263 
5264  return 0; /* return value does not matter */
5265 }
#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:3047
#define RelationGetRelationName(relation)
Definition: rel.h:445
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
#define RelationGetNamespace(relation)
Definition: rel.h:452

◆ errtablecol()

int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5275 of file relcache.c.

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

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

5276 {
5277  TupleDesc reldesc = RelationGetDescr(rel);
5278  const char *colname;
5279 
5280  /* Use reldesc if it's a user attribute, else consult the catalogs */
5281  if (attnum > 0 && attnum <= reldesc->natts)
5282  colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
5283  else
5284  colname = get_relid_attribute_name(RelationGetRelid(rel), attnum);
5285 
5286  return errtablecolname(rel, colname);
5287 }
#define RelationGetDescr(relation)
Definition: rel.h:437
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
char * get_relid_attribute_name(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:801
#define NameStr(name)
Definition: c.h:547
#define RelationGetRelid(relation)
Definition: rel.h:425
int errtablecolname(Relation rel, const char *colname)
Definition: relcache.c:5299

◆ errtablecolname()

int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5299 of file relcache.c.

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

Referenced by errtablecol().

5300 {
5301  errtable(rel);
5303 
5304  return 0; /* return value does not matter */
5305 }
#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:5258

◆ errtableconstraint()

int errtableconstraint ( Relation  rel,
const char *  conname 
)

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

5313 {
5314  errtable(rel);
5316 
5317  return 0; /* return value does not matter */
5318 }
#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:5258

◆ GetRelationPublicationActions()

struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

Definition at line 5187 of file relcache.c.

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

Referenced by CheckCmdReplicaIdentity().

5188 {
5189  List *puboids;
5190  ListCell *lc;
5191  MemoryContext oldcxt;
5192  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5193 
5194  if (relation->rd_pubactions)
5195  return memcpy(pubactions, relation->rd_pubactions,
5196  sizeof(PublicationActions));
5197 
5198  /* Fetch the publication membership info. */
5199  puboids = GetRelationPublications(RelationGetRelid(relation));
5200  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5201 
5202  foreach(lc, puboids)
5203  {
5204  Oid pubid = lfirst_oid(lc);
5205  HeapTuple tup;
5206  Form_pg_publication pubform;
5207 
5209 
5210  if (!HeapTupleIsValid(tup))
5211  elog(ERROR, "cache lookup failed for publication %u", pubid);
5212 
5213  pubform = (Form_pg_publication) GETSTRUCT(tup);
5214 
5215  pubactions->pubinsert |= pubform->pubinsert;
5216  pubactions->pubupdate |= pubform->pubupdate;
5217  pubactions->pubdelete |= pubform->pubdelete;
5218 
5219  ReleaseSysCache(tup);
5220 
5221  /*
5222  * If we know everything is replicated, there is no point to check for
5223  * other publications.
5224  */
5225  if (pubactions->pubinsert && pubactions->pubupdate &&
5226  pubactions->pubdelete)
5227  break;
5228  }
5229 
5230  if (relation->rd_pubactions)
5231  {
5232  pfree(relation->rd_pubactions);
5233  relation->rd_pubactions = NULL;
5234  }
5235 
5236  /* Now save copy of the actions in the relcache entry. */
5238  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5239  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5240  MemoryContextSwitchTo(oldcxt);
5241 
5242  return pubactions;
5243 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
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
List * GetRelationPublications(Oid relid)
void pfree(void *pointer)
Definition: mcxt.c:949
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void * palloc0(Size size)
Definition: mcxt.c:877
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
List * GetAllTablesPublications(void)
void * palloc(Size size)
Definition: mcxt.c:848
#define elog
Definition: elog.h:219
FormData_pg_publication * Form_pg_publication
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:425
#define lfirst_oid(lc)
Definition: pg_list.h:108
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ RelationBuildLocalRelation()

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 3190 of file relcache.c.

References Assert, AssertArg, AttributeRelationId, 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, 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, TupleDescAttr, and TypeRelationId.

Referenced by heap_create().

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

◆ RelationCacheInitFilePostInvalidate()

void RelationCacheInitFilePostInvalidate ( void  )

Definition at line 6087 of file relcache.c.

References LWLockRelease().

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

6088 {
6089  LWLockRelease(RelCacheInitLock);
6090 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )

Definition at line 6061 of file relcache.c.

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

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

6062 {
6063  char initfilename[MAXPGPATH];
6064 
6065  snprintf(initfilename, sizeof(initfilename), "%s/%s",
6067 
6068  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6069 
6070  if (unlink(initfilename) < 0)
6071  {
6072  /*
6073  * The file might not be there if no backend has been started since
6074  * the last removal. But complain about failures other than ENOENT.
6075  * Fortunately, it's not too late to abort the transaction if we can't
6076  * get rid of the would-be-obsolete init file.
6077  */
6078  if (errno != ENOENT)
6079  ereport(ERROR,
6081  errmsg("could not remove cache file \"%s\": %m",
6082  initfilename)));
6083  }
6084 }
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
#define ereport(elevel, rest)
Definition: elog.h:122
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:24
char * DatabasePath
Definition: globals.c:85
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ RelationCacheInitFileRemove()

void RelationCacheInitFileRemove ( void  )

Definition at line 6102 of file relcache.c.

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

Referenced by StartupXLOG().

6103 {
6104  const char *tblspcdir = "pg_tblspc";
6105  DIR *dir;
6106  struct dirent *de;
6107  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6108 
6109  /*
6110  * We zap the shared cache file too. In theory it can't get out of sync
6111  * enough to be a problem, but in data-corruption cases, who knows ...
6112  */
6113  snprintf(path, sizeof(path), "global/%s",
6115  unlink_initfile(path);
6116 
6117  /* Scan everything in the default tablespace */
6119 
6120  /* Scan the tablespace link directory to find non-default tablespaces */
6121  dir = AllocateDir(tblspcdir);
6122  if (dir == NULL)
6123  {
6124  elog(LOG, "could not open tablespace link directory \"%s\": %m",
6125  tblspcdir);
6126  return;
6127  }
6128 
6129  while ((de = ReadDir(dir, tblspcdir)) != NULL)
6130  {
6131  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6132  {
6133  /* Scan the tablespace dir for per-database dirs */
6134  snprintf(path, sizeof(path), "%s/%s/%s",
6135  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6137  }
6138  }
6139 
6140  FreeDir(dir);
6141 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6145
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:2373
static void unlink_initfile(const char *initfilename)
Definition: relcache.c:6175
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:24
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2439
#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:2482

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 3542 of file relcache.c.

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

Referenced by InitPostgres().

3543 {
3544  HASHCTL ctl;
3545 
3546  /*
3547  * make sure cache memory context exists
3548  */
3549  if (!CacheMemoryContext)
3551 
3552  /*
3553  * create hashtable that indexes the relcache
3554  */
3555  MemSet(&ctl, 0, sizeof(ctl));
3556  ctl.keysize = sizeof(Oid);
3557  ctl.entrysize = sizeof(RelIdCacheEnt);
3558  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3559  &ctl, HASH_ELEM | HASH_BLOBS);
3560 
3561  /*
3562  * relation mapper needs to be initialized too
3563  */
3565 }
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:853
static HTAB * RelationIdCache
Definition: relcache.c:119
unsigned int Oid
Definition: postgres_ext.h:31
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Size keysize
Definition: hsearch.h:72
void CreateCacheMemoryContext(void)
Definition: catcache.c:636
#define INITRELCACHESIZE
Definition: relcache.c:3539
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ RelationCacheInitializePhase2()

void RelationCacheInitializePhase2 ( void  )

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

3580 {
3581  MemoryContext oldcxt;
3582 
3583  /*
3584  * relation mapper needs initialized too
3585  */
3587 
3588  /*
3589  * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3590  * nothing.
3591  */
3593  return;
3594 
3595  /*
3596  * switch to cache memory context
3597  */
3599 
3600  /*
3601  * Try to load the shared relcache cache file. If unsuccessful, bootstrap
3602  * the cache with pre-made descriptors for the critical shared catalogs.
3603  */
3604  if (!load_relcache_init_file(true))
3605  {
3606  formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
3608  formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
3610  formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
3612  formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
3614  formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
3616 
3617 #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
3618  }
3619 
3620  MemoryContextSwitchTo(oldcxt);
3621 }
static const FormData_pg_attribute Desc_pg_auth_members[Natts_pg_auth_members]
Definition: relcache.c:102
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5376
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, bool hasoids, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1898
#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:101
static const FormData_pg_attribute Desc_pg_subscription[Natts_pg_subscription]
Definition: relcache.c:105
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:100
#define Natts_pg_shseclabel
Definition: pg_shseclabel.h:41
static const FormData_pg_attribute Desc_pg_shseclabel[Natts_pg_shseclabel]
Definition: relcache.c:104
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:367
#define DatabaseRelation_Rowtype_Id
Definition: pg_database.h:30
#define Natts_pg_authid
Definition: pg_authid.h:78
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ RelationCacheInitializePhase3()

void RelationCacheInitializePhase3 ( void  )

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

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

◆ RelationCacheInvalidate()

void RelationCacheInvalidate ( void  )

Definition at line 2767 of file relcache.c.

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

Referenced by InvalidateSystemCaches(), and LocalExecuteInvalidationMessage().

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

◆ RelationCacheInvalidateEntry()

void RelationCacheInvalidateEntry ( Oid  relationId)

Definition at line 2723 of file relcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

2724 {
2725  Relation relation;
2726 
2727  RelationIdCacheLookup(relationId, relation);
2728 
2729  if (PointerIsValid(relation))
2730  {
2732  RelationFlushRelation(relation);
2733  }
2734 }
static long relcacheInvalsReceived
Definition: relcache.c:139
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:198
static void RelationFlushRelation(Relation relation)
Definition: relcache.c:2655
#define PointerIsValid(pointer)
Definition: c.h:564

◆ RelationClose()

void RelationClose ( Relation  relation)

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

2168 {
2169  /* Note: no locking manipulations needed */
2171 
2172 #ifdef RELCACHE_FORCE_RELEASE
2173  if (RelationHasReferenceCountZero(relation) &&
2174  relation->rd_createSubid == InvalidSubTransactionId &&
2176  RelationClearRelation(relation, false);
2177 #endif
2178 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2399
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:111
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2147
SubTransactionId rd_createSubid
Definition: rel.h:110
#define InvalidSubTransactionId
Definition: c.h:451
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:409

◆ RelationCloseSmgrByOid()

void RelationCloseSmgrByOid ( Oid  relationId)

Definition at line 2870 of file relcache.c.

References PointerIsValid, RelationCloseSmgr, and RelationIdCacheLookup.

Referenced by swap_relation_files().

2871 {
2872  Relation relation;
2873 
2874  RelationIdCacheLookup(relationId, relation);
2875 
2876  if (!PointerIsValid(relation))
2877  return; /* not in cache, nothing to do */
2878 
2879  RelationCloseSmgr(relation);
2880 }
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:198
#define RelationCloseSmgr(relation)
Definition: rel.h:481
#define PointerIsValid(pointer)
Definition: c.h:564

◆ RelationForgetRelation()

void RelationForgetRelation ( Oid  rid)

Definition at line 2691 of file relcache.c.

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

Referenced by heap_drop_with_catalog(), and index_drop().

2692 {
2693  Relation relation;
2694 
2695  RelationIdCacheLookup(rid, relation);
2696 
2697  if (!PointerIsValid(relation))
2698  return; /* not in cache, nothing to do */
2699 
2700  if (!RelationHasReferenceCountZero(relation))
2701  elog(ERROR, "relation %u is still open", rid);
2702 
2703  /* Unconditionally destroy the relcache entry */
2704  RelationClearRelation(relation, false);
2705 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2399
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:198
#define ERROR
Definition: elog.h:43
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:409
#define elog
Definition: elog.h:219
#define PointerIsValid(pointer)
Definition: c.h:564

◆ RelationGetExclusionInfo()

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

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

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

◆ RelationGetFKeyList()

List* RelationGetFKeyList ( Relation  relation)

Definition at line 4197 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, ObjectIdGetDatum, OIDOID, RelationData::rd_att, RelationData::rd_fkeylist, RelationData::rd_fkeyvalid, RelationData::rd_rel, RelationGetRelationName, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by get_relation_foreign_keys().

4198 {
4199  List *result;
4200  Relation conrel;
4201  SysScanDesc conscan;
4202  ScanKeyData skey;
4203  HeapTuple htup;
4204  List *oldlist;
4205  MemoryContext oldcxt;
4206 
4207  /* Quick exit if we already computed the list. */
4208  if (relation->rd_fkeyvalid)
4209  return relation->rd_fkeylist;
4210 
4211  /* Fast path: if it doesn't have any triggers, it can't have FKs */
4212  if (!relation->rd_rel->relhastriggers)
4213  return NIL;
4214 
4215  /*
4216  * We build the list we intend to return (in the caller's context) while
4217  * doing the scan. After successfully completing the scan, we copy that
4218  * list into the relcache entry. This avoids cache-context memory leakage
4219  * if we get some sort of error partway through.
4220  */
4221  result = NIL;
4222 
4223  /* Prepare to scan pg_constraint for entries having conrelid = this rel. */
4224  ScanKeyInit(&skey,
4226  BTEqualStrategyNumber, F_OIDEQ,
4227  ObjectIdGetDatum(RelationGetRelid(relation)));
4228 
4230  conscan = systable_beginscan(conrel, ConstraintRelidIndexId, true,
4231  NULL, 1, &skey);
4232 
4233  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4234  {
4235  Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(htup);
4236  ForeignKeyCacheInfo *info;
4237  Datum adatum;
4238  bool isnull;
4239  ArrayType *arr;
4240  int nelem;
4241 
4242  /* consider only foreign keys */
4243  if (constraint->contype != CONSTRAINT_FOREIGN)
4244  continue;
4245 
4246  info = makeNode(ForeignKeyCacheInfo);
4247  info->conrelid = constraint->conrelid;
4248  info->confrelid = constraint->confrelid;
4249 
4250  /* Extract data from conkey field */
4251  adatum = fastgetattr(htup, Anum_pg_constraint_conkey,
4252  conrel->rd_att, &isnull);
4253  if (isnull)
4254  elog(ERROR, "null conkey for rel %s",
4255  RelationGetRelationName(relation));
4256 
4257  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
4258  nelem = ARR_DIMS(arr)[0];
4259  if (ARR_NDIM(arr) != 1 ||
4260  nelem < 1 ||
4261  nelem > INDEX_MAX_KEYS ||
4262  ARR_HASNULL(arr) ||
4263  ARR_ELEMTYPE(arr) != INT2OID)
4264  elog(ERROR, "conkey is not a 1-D smallint array");
4265 
4266  info->nkeys = nelem;
4267  memcpy(info->conkey, ARR_DATA_PTR(arr), nelem * sizeof(AttrNumber));
4268 
4269  /* Likewise for confkey */
4270  adatum = fastgetattr(htup, Anum_pg_constraint_confkey,
4271  conrel->rd_att, &isnull);
4272  if (isnull)
4273  elog(ERROR, "null confkey for rel %s",
4274  RelationGetRelationName(relation));
4275 
4276  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
4277  nelem = ARR_DIMS(arr)[0];
4278  if (ARR_NDIM(arr) != 1 ||
4279  nelem != info->nkeys ||
4280  ARR_HASNULL(arr) ||
4281  ARR_ELEMTYPE(arr) != INT2OID)
4282  elog(ERROR, "confkey is not a 1-D smallint array");
4283 
4284  memcpy(info->confkey, ARR_DATA_PTR(arr), nelem * sizeof(AttrNumber));
4285 
4286  /* Likewise for conpfeqop */
4288  conrel->rd_att, &isnull);
4289  if (isnull)
4290  elog(ERROR, "null conpfeqop for rel %s",
4291  RelationGetRelationName(relation));
4292 
4293  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
4294  nelem = ARR_DIMS(arr)[0];
4295  if (ARR_NDIM(arr) != 1 ||
4296  nelem != info->nkeys ||
4297  ARR_HASNULL(arr) ||
4298  ARR_ELEMTYPE(arr) != OIDOID)
4299  elog(ERROR, "conpfeqop is not a 1-D OID array");
4300 
4301  memcpy(info->conpfeqop, ARR_DATA_PTR(arr), nelem * sizeof(Oid));
4302 
4303  /* Add FK's node to the result list */
4304  result = lappend(result, info);
4305  }
4306 
4307  systable_endscan(conscan);
4308  heap_close(conrel, AccessShareLock);
4309 
4310  /* Now save a copy of the completed list in the relcache entry. */
4312  oldlist = relation->rd_fkeylist;
4313  relation->rd_fkeylist = copyObject(result);
4314  relation->rd_fkeyvalid = true;
4315  MemoryContextSwitchTo(oldcxt);
4316 
4317  /* Don't leak the old list, if there is one */
4318  list_free_deep(oldlist);
4319 
4320  return result;
4321 }
#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:661
#define Anum_pg_constraint_confkey
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:724
#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
#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:279
#define INT2OID
Definition: pg_type.h:308
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define RelationGetRelationName(relation)
Definition: rel.h:445
#define ARR_HASNULL(a)
Definition: array.h:276
#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:1290
TupleDesc rd_att
Definition: rel.h:115
#define makeNode(_type_)
Definition: nodes.h:558
Oid conpfeqop[INDEX_MAX_KEYS]
Definition: rel.h:245
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Anum_pg_constraint_conpfeqop
#define INDEX_MAX_KEYS
#define ARR_NDIM(a)
Definition: array.h:275
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:623
Definition: pg_list.h:45
bool rd_fkeyvalid
Definition: rel.h:126
#define ARR_ELEMTYPE(a)
Definition: array.h:277
int16 AttrNumber
Definition: attnum.h:21
#define RelationGetRelid(relation)
Definition: rel.h:425
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define ConstraintRelidIndexId
Definition: indexing.h:126
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
#define DatumGetArrayTypeP(X)
Definition: array.h:246

◆ RelationGetIndexAttrBitmap()

Bitmapset* RelationGetIndexAttrBitmap ( Relation  relation,
IndexAttrBitmapKind  keyAttrs 
)

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

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

◆ RelationGetIndexExpressions()

List* RelationGetIndexExpressions ( Relation  relation)

Definition at line 4716 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, pfree(), RelationData::rd_indexcxt, RelationData::rd_indexprs, RelationData::rd_indextuple, stringToNode(), and TextDatumGetCString.

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

4717 {
4718  List *result;
4719  Datum exprsDatum;
4720  bool isnull;
4721  char *exprsString;
4722  MemoryContext oldcxt;
4723 
4724  /* Quick exit if we already computed the result. */
4725  if (relation->rd_indexprs)
4726  return copyObject(relation->rd_indexprs);
4727 
4728  /* Quick exit if there is nothing to do. */
4729  if (relation->rd_indextuple == NULL ||
4731  return NIL;
4732 
4733  /*
4734  * We build the tree we intend to return in the caller's context. After
4735  * successfully completing the work, we copy it into the relcache entry.
4736  * This avoids problems if we get some sort of error partway through.
4737  */
4738  exprsDatum = heap_getattr(relation->rd_indextuple,
4741  &isnull);
4742  Assert(!isnull);
4743  exprsString = TextDatumGetCString(exprsDatum);
4744  result = (List *) stringToNode(exprsString);
4745  pfree(exprsString);
4746 
4747  /*
4748  * Run the expressions through eval_const_expressions. This is not just an
4749  * optimization, but is necessary, because the planner will be comparing
4750  * them to similarly-processed qual clauses, and may fail to detect valid
4751  * matches without this. We don't bother with canonicalize_qual, however.
4752  */
4753  result = (List *) eval_const_expressions(NULL, (Node *) result);
4754 
4755  result = (List *) canonicalize_qual((Expr *) result);
4756 
4757  /* May as well fix opfuncids too */
4758  fix_opfuncids((Node *) result);
4759 
4760  /* Now save a copy of the completed tree in the relcache entry. */
4761  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4762  relation->rd_indexprs = copyObject(result);
4763  MemoryContextSwitchTo(oldcxt);
4764 
4765  return result;
4766 }
#define NIL
Definition: pg_list.h:69
void * stringToNode(char *str)
Definition: read.c:38
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1582
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
List * rd_indexprs
Definition: rel.h:187
Definition: nodes.h:510
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2459
struct HeapTupleData * rd_indextuple
Definition: rel.h:161
void pfree(void *pointer)
Definition: mcxt.c:949
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4012
bool heap_attisnull(HeapTuple tup, int attnum)
Definition: heaptuple.c:296
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:774
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
Expr * canonicalize_qual(Expr *qual)
Definition: prepqual.c:286
#define Assert(condition)
Definition: c.h:670
MemoryContext rd_indexcxt
Definition: rel.h:179
#define copyObject(obj)
Definition: nodes.h:623
Definition: pg_list.h:45
#define Anum_pg_index_indexprs
Definition: pg_index.h:91

◆ RelationGetIndexList()

List* RelationGetIndexList ( Relation  relation)

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

4361 {
4362  Relation indrel;
4363  SysScanDesc indscan;
4364  ScanKeyData skey;
4365  HeapTuple htup;
4366  List *result;
4367  List *oldlist;
4368  char replident = relation->rd_rel->relreplident;
4369  Oid oidIndex = InvalidOid;
4370  Oid pkeyIndex = InvalidOid;
4371  Oid candidateIndex = InvalidOid;
4372  MemoryContext oldcxt;
4373 
4374  /* Quick exit if we already computed the list. */
4375  if (relation->rd_indexvalid != 0)
4376  return list_copy(relation->rd_indexlist);
4377 
4378  /*
4379  * We build the list we intend to return (in the caller's context) while
4380  * doing the scan. After successfully completing the scan, we copy that
4381  * list into the relcache entry. This avoids cache-context memory leakage
4382  * if we get some sort of error partway through.
4383  */
4384  result = NIL;
4385  oidIndex = InvalidOid;
4386 
4387  /* Prepare to scan pg_index for entries having indrelid = this rel. */
4388  ScanKeyInit(&skey,
4390  BTEqualStrategyNumber, F_OIDEQ,
4391  ObjectIdGetDatum(RelationGetRelid(relation)));
4392 
4394  indscan = systable_beginscan(indrel, IndexIndrelidIndexId, true,
4395  NULL, 1, &skey);
4396 
4397  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4398  {
4400  Datum indclassDatum;
4401  oidvector *indclass;
4402  bool isnull;
4403 
4404  /*
4405  * Ignore any indexes that are currently being dropped. This will
4406  * prevent them from being searched, inserted into, or considered in
4407  * HOT-safety decisions. It's unsafe to touch such an index at all
4408  * since its catalog entries could disappear at any instant.
4409  */
4410  if (!IndexIsLive(index))
4411  continue;
4412 
4413  /* Add index's OID to result list in the proper order */
4414  result = insert_ordered_oid(result, index->indexrelid);
4415 
4416  /*
4417  * indclass cannot be referenced directly through the C struct,
4418  * because it comes after the variable-width indkey field. Must
4419  * extract the datum the hard way...
4420  */
4421  indclassDatum = heap_getattr(htup,
4424  &isnull);
4425  Assert(!isnull);
4426  indclass = (oidvector *) DatumGetPointer(indclassDatum);
4427 
4428  /*
4429  * Invalid, non-unique, non-immediate or predicate indexes aren't
4430  * interesting for either oid indexes or replication identity indexes,
4431  * so don't check them.
4432  */
4433  if (!IndexIsValid(index) || !index->indisunique ||
4434  !index->indimmediate ||
4436  continue;
4437 
4438  /* Check to see if is a usable btree index on OID */
4439  if (index->indnatts == 1 &&
4440  index->indkey.values[0] == ObjectIdAttributeNumber &&
4441  indclass->values[0] == OID_BTREE_OPS_OID)
4442  oidIndex = index->indexrelid;
4443 
4444  /* remember primary key index if any */
4445  if (index->indisprimary)
4446  pkeyIndex = index->indexrelid;
4447 
4448  /* remember explicitly chosen replica index */
4449  if (index->indisreplident)
4450  candidateIndex = index->indexrelid;
4451  }
4452 
4453  systable_endscan(indscan);
4454 
4455  heap_close(indrel, AccessShareLock);
4456 
4457  /* Now save a copy of the completed list in the relcache entry. */
4459  oldlist = relation->rd_indexlist;
4460  relation->rd_indexlist = list_copy(result);
4461  relation->rd_oidindex = oidIndex;
4462  relation->rd_pkindex = pkeyIndex;
4463  if (replident == REPLICA_IDENTITY_DEFAULT && OidIsValid(pkeyIndex))
4464  relation->rd_replidindex = pkeyIndex;
4465  else if (replident == REPLICA_IDENTITY_INDEX && OidIsValid(candidateIndex))
4466  relation->rd_replidindex = candidateIndex;
4467  else
4468  relation->rd_replidindex = InvalidOid;
4469  relation->rd_indexvalid = 1;
4470  MemoryContextSwitchTo(oldcxt);
4471 
4472  /* Don't leak the old list, if there is one */
4473  list_free(oldlist);
4474 
4475  return result;
4476 }
#define NIL
Definition: pg_list.h:69
Definition: c.h:526
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#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:4566
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
#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:576
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
#define Anum_pg_index_indrelid
Definition: pg_index.h:75
Definition: type.h:89
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
Oid rd_pkindex
Definition: rel.h:137
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4012
char rd_indexvalid
Definition: rel.h:93
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:534
bool heap_attisnull(HeapTuple tup, int attnum)
Definition: heaptuple.c:296
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:774
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:1290
#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 Assert(condition)
Definition: c.h:670
#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:425
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define IndexIndrelidIndexId
Definition: indexing.h:162
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ RelationGetIndexPredicate()

List* RelationGetIndexPredicate ( Relation  relation)

Definition at line 4779 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, pfree(), RelationData::rd_indexcxt, RelationData::rd_indextuple, RelationData::rd_indpred, stringToNode(), and TextDatumGetCString.

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

4780 {
4781  List *result;
4782  Datum predDatum;
4783  bool isnull;
4784  char *predString;
4785  MemoryContext oldcxt;
4786 
4787  /* Quick exit if we already computed the result. */
4788  if (relation->rd_indpred)
4789  return copyObject(relation->rd_indpred);
4790 
4791  /* Quick exit if there is nothing to do. */
4792  if (relation->rd_indextuple == NULL ||
4794  return NIL;
4795 
4796  /*
4797  * We build the tree we intend to return in the caller's context. After
4798  * successfully completing the work, we copy it into the relcache entry.
4799  * This avoids problems if we get some sort of error partway through.
4800  */
4801  predDatum = heap_getattr(relation->rd_indextuple,
4804  &isnull);
4805  Assert(!isnull);
4806  predString = TextDatumGetCString(predDatum);
4807  result = (List *) stringToNode(predString);
4808  pfree(predString);
4809 
4810  /*
4811  * Run the expression through const-simplification and canonicalization.
4812  * This is not just an optimization, but is necessary, because the planner
4813  * will be comparing it to similarly-processed qual clauses, and may fail
4814  * to detect valid matches without this. This must match the processing
4815  * done to qual clauses in preprocess_expression()! (We can skip the
4816  * stuff involving subqueries, however, since we don't allow any in index
4817  * predicates.)
4818  */
4819  result = (List *) eval_const_expressions(NULL, (Node *) result);
4820 
4821  result = (List *) canonicalize_qual((Expr *) result);
4822 
4823  /* Also convert to implicit-AND format */
4824  result = make_ands_implicit((Expr *) result);
4825 
4826  /* May as well fix opfuncids too */
4827  fix_opfuncids((Node *) result);
4828 
4829  /* Now save a copy of the completed tree in the relcache entry. */
4830  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4831  relation->rd_indpred = copyObject(result);
4832  MemoryContextSwitchTo(oldcxt);
4833 
4834  return result;
4835 }
#define NIL
Definition: pg_list.h:69
void * stringToNode(char *str)
Definition: read.c:38
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1582
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:510
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2459
struct HeapTupleData * rd_indextuple
Definition: rel.h:161
void pfree(void *pointer)
Definition: mcxt.c:949
List * make_ands_implicit(Expr *clause)
Definition: clauses.c:378
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4012
bool heap_attisnull(HeapTuple tup, int attnum)
Definition: heaptuple.c:296
List * rd_indpred
Definition: rel.h:188
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:774
#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 Assert(condition)
Definition: c.h:670
MemoryContext rd_indexcxt
Definition: rel.h:179
#define copyObject(obj)
Definition: nodes.h:623
Definition: pg_list.h:45

◆ RelationGetOidIndex()

Oid RelationGetOidIndex ( Relation  relation)

Definition at line 4642 of file relcache.c.

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

Referenced by GetNewOid().

4643 {
4644  List *ilist;
4645 
4646  /*
4647  * If relation doesn't have OIDs at all, caller is probably confused. (We
4648  * could just silently return InvalidOid, but it seems better to throw an
4649  * assertion.)
4650  */
4651  Assert(relation->rd_rel->relhasoids);
4652 
4653  if (relation->rd_indexvalid == 0)
4654  {
4655  /* RelationGetIndexList does the heavy lifting. */
4656  ilist = RelationGetIndexList(relation);
4657  list_free(ilist);
4658  Assert(relation->rd_indexvalid != 0);
4659  }
4660 
4661  return relation->rd_oidindex;
4662 }
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:670
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4360
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45

◆ RelationGetPrimaryKeyIndex()

Oid RelationGetPrimaryKeyIndex ( Relation  relation)

Definition at line 4670 of file relcache.c.

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

Referenced by GetRelationIdentityOrPK().

4671 {
4672  List *ilist;
4673 
4674  if (relation->rd_indexvalid == 0)
4675  {
4676  /* RelationGetIndexList does the heavy lifting. */
4677  ilist = RelationGetIndexList(relation);
4678  list_free(ilist);
4679  Assert(relation->rd_indexvalid != 0);
4680  }
4681 
4682  return relation->rd_pkindex;
4683 }
Oid rd_pkindex
Definition: rel.h:137
char rd_indexvalid
Definition: rel.h:93
#define Assert(condition)
Definition: c.h:670
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4360
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45

◆ RelationGetReplicaIndex()

Oid RelationGetReplicaIndex ( Relation  relation)

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

4692 {
4693  List *ilist;
4694 
4695  if (relation->rd_indexvalid == 0)
4696  {
4697  /* RelationGetIndexList does the heavy lifting. */
4698  ilist = RelationGetIndexList(relation);
4699  list_free(ilist);
4700  Assert(relation->rd_indexvalid != 0);
4701  }
4702 
4703  return relation->rd_replidindex;
4704 }
Oid rd_replidindex
Definition: rel.h:138
char rd_indexvalid
Definition: rel.h:93
#define Assert(condition)
Definition: c.h:670
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4360
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45

◆ RelationGetStatExtList()

List* RelationGetStatExtList ( Relation  relation)

Definition at line 4500 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, ObjectIdGetDatum, RelationData::rd_statlist, RelationData::rd_statvalid, RelationGetRelid, ScanKeyInit(), StatisticExtRelationId, StatisticExtRelidIndexId, systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by get_relation_statistics().

4501 {
4502  Relation indrel;
4503  SysScanDesc indscan;
4504  ScanKeyData skey;
4505  HeapTuple htup;
4506  List *result;
4507  List *oldlist;
4508  MemoryContext oldcxt;
4509 
4510  /* Quick exit if we already computed the list. */
4511  if (relation->rd_statvalid != 0)
4512  return list_copy(relation->rd_statlist);
4513 
4514  /*
4515  * We build the list we intend to return (in the caller's context) while
4516  * doing the scan. After successfully completing the scan, we copy that
4517  * list into the relcache entry. This avoids cache-context memory leakage
4518  * if we get some sort of error partway through.
4519  */
4520  result = NIL;
4521 
4522  /*
4523  * Prepare to scan pg_statistic_ext for entries having stxrelid = this
4524  * rel.
4525  */
4526  ScanKeyInit(&skey,
4528  BTEqualStrategyNumber, F_OIDEQ,
4529  ObjectIdGetDatum(RelationGetRelid(relation)));
4530 
4532  indscan = systable_beginscan(indrel, StatisticExtRelidIndexId, true,
4533  NULL, 1, &skey);
4534 
4535  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4536  result = insert_ordered_oid(result, HeapTupleGetOid(htup));
4537 
4538  systable_endscan(indscan);
4539 
4540  heap_close(indrel, AccessShareLock);
4541 
4542  /* Now save a copy of the completed list in the relcache entry. */
4544  oldlist = relation->rd_statlist;
4545  relation->rd_statlist = list_copy(result);
4546 
4547  relation->rd_statvalid = true;
4548  MemoryContextSwitchTo(oldcxt);
4549 
4550  /* Don't leak the old list, if there is one */
4551  list_free(oldlist);
4552 
4553  return result;
4554 }
#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:4566
List * list_copy(const List *oldlist)
Definition: list.c:1160
#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:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#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:700
List * rd_statlist
Definition: rel.h:141
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:425
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ RelationIdGetRelation()

Relation RelationIdGetRelation ( Oid  relationId)

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

2079 {
2080  Relation rd;
2081 
2082  /* Make sure we're in an xact, even if this ends up being a cache hit */
2084 
2085  /*
2086  * first try to find reldesc in the cache
2087  */
2088  RelationIdCacheLookup(relationId, rd);
2089 
2090  if (RelationIsValid(rd))
2091  {
2093  /* revalidate cache entry if necessary */
2094  if (!rd->rd_isvalid)
2095  {
2096  /*
2097  * Indexes only have a limited number of possible schema changes,
2098  * and we don't want to use the full-blown procedure because it's
2099  * a headache for indexes that reload itself depends on.
2100  */
2101  if (rd->rd_rel->relkind == RELKIND_INDEX)
2103  else
2104  RelationClearRelation(rd, true);
2105  Assert(rd->rd_isvalid);
2106  }
2107  return rd;
2108  }
2109 
2110  /*
2111  * no reldesc in the cache, so have RelationBuildDesc() build one and add
2112  * it.
2113  */
2114  rd = RelationBuildDesc(relationId, true);
2115  if (RelationIsValid(rd))
2117  return rd;
2118 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2399
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:198
bool rd_isvalid
Definition: rel.h:92
Form_pg_class rd_rel
Definition: rel.h:114
#define RelationIsValid(relation)
Definition: rel.h:398
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2134
static void RelationReloadIndexInfo(Relation relation)
Definition: relcache.c:2208
#define Assert(condition)
Definition: c.h:670
static Relation RelationBuildDesc(Oid targetRelId, bool insertIt)
Definition: relcache.c:1244
bool IsTransactionState(void)
Definition: xact.c:351
#define RELKIND_INDEX
Definition: pg_class.h:161

◆ RelationIdIsInInitFile()

bool RelationIdIsInInitFile ( Oid  relationId)

Definition at line 5978 of file relcache.c.

References Assert, RelationSupportsSysCache(), and TriggerRelidNameIndexId.

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

5979 {
5980  if (relationId == TriggerRelidNameIndexId)
5981  {
5982  /* If this Assert fails, we don't need this special case anymore. */
5983  Assert(!RelationSupportsSysCache(relationId));
5984  return true;
5985  }
5986  return RelationSupportsSysCache(relationId);
5987 }
#define TriggerRelidNameIndexId
Definition: indexing.h:249
#define Assert(condition)
Definition: c.h:670
bool RelationSupportsSysCache(Oid relid)
Definition: syscache.c:1512

◆ RelationInitIndexAccessInfo()

void RelationInitIndexAccessInfo ( Relation  relation)

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

1517 {
1518  HeapTuple tuple;
1519  Form_pg_am aform;
1520  Datum indcollDatum;
1521  Datum indclassDatum;
1522  Datum indoptionDatum;
1523  bool isnull;
1524  oidvector *indcoll;
1525  oidvector *indclass;
1526  int2vector *indoption;
1527  MemoryContext indexcxt;
1528  MemoryContext oldcontext;
1529  int natts;
1530  uint16 amsupport;
1531 
1532  /*
1533  * Make a copy of the pg_index entry for the index. Since pg_index
1534  * contains variable-length and possibly-null fields, we have to do this
1535  * honestly rather than just treating it as a Form_pg_index struct.
1536  */
1537  tuple = SearchSysCache1(INDEXRELID,
1538  ObjectIdGetDatum(RelationGetRelid(relation)));
1539  if (!HeapTupleIsValid(tuple))
1540  elog(ERROR, "cache lookup failed for index %u",
1541  RelationGetRelid(relation));
1543  relation->rd_indextuple = heap_copytuple(tuple);
1544  relation->rd_index = (Form_pg_index) GETSTRUCT(relation->rd_indextuple);
1545  MemoryContextSwitchTo(oldcontext);
1546  ReleaseSysCache(tuple);
1547 
1548  /*
1549  * Look up the index's access method, save the OID of its handler function
1550  */
1551  tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(relation->rd_rel->relam));
1552  if (!HeapTupleIsValid(tuple))
1553  elog(ERROR, "cache lookup failed for access method %u",
1554  relation->rd_rel->relam);
1555  aform = (Form_pg_am) GETSTRUCT(tuple);
1556  relation->rd_amhandler = aform->amhandler;
1557  ReleaseSysCache(tuple);
1558 
1559  natts = relation->rd_rel->relnatts;
1560  if (natts != relation->rd_index->indnatts)
1561  elog(ERROR, "relnatts disagrees with indnatts for index %u",
1562  RelationGetRelid(relation));
1563 
1564  /*
1565  * Make the private context to hold index access info. The reason we need
1566  * a context, and not just a couple of pallocs, is so that we won't leak
1567  * any subsidiary info attached to fmgr lookup records.
1568  */
1570  RelationGetRelationName(relation),
1572  relation->rd_indexcxt = indexcxt;
1573 
1574  /*
1575  * Now we can fetch the index AM's API struct
1576  */
1577  InitIndexAmRoutine(relation);
1578 
1579  /*
1580  * Allocate arrays to hold data
1581  */
1582  relation->rd_opfamily = (Oid *)
1583  MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
1584  relation->rd_opcintype = (Oid *)
1585  MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
1586 
1587  amsupport = relation->rd_amroutine->amsupport;
1588  if (amsupport > 0)
1589  {
1590  int nsupport = natts * amsupport;
1591 
1592  relation->rd_support = (RegProcedure *)
1593  MemoryContextAllocZero(indexcxt, nsupport * sizeof(RegProcedure));
1594  relation->rd_supportinfo = (FmgrInfo *)
1595  MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
1596  }
1597  else
1598  {
1599  relation->rd_support = NULL;
1600  relation->rd_supportinfo = NULL;
1601  }
1602 
1603  relation->rd_indcollation = (Oid *)
1604  MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
1605 
1606  relation->rd_indoption = (int16 *)
1607  MemoryContextAllocZero(indexcxt, natts * sizeof(int16));
1608 
1609  /*
1610  * indcollation cannot be referenced directly through the C struct,
1611  * because it comes after the variable-width indkey field. Must extract
1612  * the datum the hard way...
1613  */
1614  indcollDatum = fastgetattr(relation->rd_indextuple,
1617  &isnull);
1618  Assert(!isnull);
1619  indcoll = (oidvector *) DatumGetPointer(indcollDatum);
1620  memcpy(relation->rd_indcollation, indcoll->values, natts * sizeof(Oid));
1621 
1622  /*
1623  * indclass cannot be referenced directly through the C struct, because it
1624  * comes after the variable-width indkey field. Must extract the datum
1625  * the hard way...
1626  */
1627  indclassDatum = fastgetattr(relation->rd_indextuple,
1630  &isnull);
1631  Assert(!isnull);
1632  indclass = (oidvector *) DatumGetPointer(indclassDatum);
1633 
1634  /*
1635  * Fill the support procedure OID array, as well as the info about
1636  * opfamilies and opclass input types. (aminfo and supportinfo are left
1637  * as zeroes, and are filled on-the-fly when used)
1638  */
1639  IndexSupportInitialize(indclass, relation->rd_support,
1640  relation->rd_opfamily, relation->rd_opcintype,
1641  amsupport, natts);
1642 
1643  /*
1644  * Similarly extract indoption and copy it to the cache entry
1645  */
1646  indoptionDatum = fastgetattr(relation->rd_indextuple,
1649  &isnull);
1650  Assert(!isnull);
1651  indoption = (int2vector *) DatumGetPointer(indoptionDatum);
1652  memcpy(relation->rd_indoption, indoption->values, natts * sizeof(int16));
1653 
1654  /*
1655  * expressions, predicate, exclusion caches will be filled later
1656  */
1657  relation->rd_indexprs = NIL;
1658  relation->rd_indpred = NIL;
1659  relation->rd_exclops = NULL;
1660  relation->rd_exclprocs = NULL;
1661  relation->rd_exclstrats = NULL;
1662  relation->rd_amcache = NULL;
1663 }
signed short int16
Definition: c.h:283
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:611
#define NIL
Definition: pg_list.h:69
Definition: c.h:526
Definition: fmgr.h:56
uint16 amsupport
Definition: amapi.h:169
int16 * rd_indoption
Definition: rel.h:186
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:724
Definition: syscache.h:36
FmgrInfo * rd_supportinfo
Definition: rel.h:185
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:175
regproc RegProcedure
Definition: c.h:443
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:1492
static void IndexSupportInitialize(oidvector *indclass, RegProcedure *indexSupport, Oid *opFamily, Oid *opcInType, StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber)
Definition: relcache.c:1679
struct HeapTupleData * rd_indextuple
Definition: rel.h:161
Form_pg_index rd_index
Definition: rel.h:159
unsigned short uint16
Definition: c.h:295
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:4012
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:534
#define RelationGetRelationName(relation)
Definition: rel.h:445
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
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
Definition: c.h:515
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:1160
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:741
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:670
int16 values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:523
#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:425
#define Anum_pg_index_indoption
Definition: pg_index.h:90
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ RelationSetIndexList()

void RelationSetIndexList ( Relation  relation,
List indexIds,
Oid  oidIndex 
)

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

4612 {
4613  MemoryContext oldcxt;
4614 
4615  Assert(relation->rd_isnailed);
4616  /* Copy the list into the cache context (could fail for lack of mem) */
4618  indexIds = list_copy(indexIds);
4619  MemoryContextSwitchTo(oldcxt);
4620  /* Okay to replace old list */
4621  list_free(relation->rd_indexlist);
4622  relation->rd_indexlist = indexIds;
4623  relation->rd_oidindex = oidIndex;
4624 
4625  /*
4626  * For the moment, assume the target rel hasn't got a pk or replica index.
4627  * We'll load them on demand in the API that wraps access to them.
4628  */
4629  relation->rd_pkindex = InvalidOid;
4630  relation->rd_replidindex = InvalidOid;
4631  relation->rd_indexvalid = 2; /* mark list as forced */
4632  /* Flag relation as needing eoxact cleanup (to reset the list) */
4633  EOXactListAdd(relation);
4634 }
#define EOXactListAdd(rel)
Definition: relcache.c:156
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:670
void list_free(List *list)
Definition: list.c:1133
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ RelationSetNewRelfilenode()

void RelationSetNewRelfilenode ( Relation  relation,
char  persistence,
TransactionId  freezeXid,
MultiXactId  minmulti 
)

Definition at line 3430 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, ObjectIdGetDatum, RelationData::rd_backend, RelationData::rd_newRelfilenodeSubid, RelationData::rd_node, RelationData::rd_rel, RelationCreateStorage(), RelationDropStorage(), RelationGetRelid, RelationIsMapped, RelationMapUpdateMap(), RelationRelationId, RELKIND_INDEX, RELKIND_SEQUENCE, RelFileNode::relNode, RELOID, RowExclusiveLock, SearchSysCacheCopy1, smgrclosenode(), HeapTupleData::t_self, and TransactionIdIsNormal.

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

3432 {
3433  Oid newrelfilenode;
3434  RelFileNodeBackend newrnode;
3435  Relation pg_class;
3436  HeapTuple tuple;
3437  Form_pg_class classform;
3438 
3439  /* Indexes, sequences must have Invalid frozenxid; other rels must not */
3440  Assert((relation->rd_rel->relkind == RELKIND_INDEX ||
3441  relation->rd_rel->relkind == RELKIND_SEQUENCE) ?
3442  freezeXid == InvalidTransactionId :
3443  TransactionIdIsNormal(freezeXid));
3444  Assert(TransactionIdIsNormal(freezeXid) == MultiXactIdIsValid(minmulti));
3445 
3446  /* Allocate a new relfilenode */
3447  newrelfilenode = GetNewRelFileNode(relation->rd_rel->reltablespace, NULL,
3448  persistence);
3449 
3450  /*
3451  * Get a writable copy of the pg_class tuple for the given relation.
3452  */
3454 
3455  tuple = SearchSysCacheCopy1(RELOID,
3456  ObjectIdGetDatum(RelationGetRelid(relation)));
3457  if (!HeapTupleIsValid(tuple))
3458  elog(ERROR, "could not find tuple for relation %u",
3459  RelationGetRelid(relation));
3460  classform = (Form_pg_class) GETSTRUCT(tuple);
3461 
3462  /*
3463  * Create storage for the main fork of the new relfilenode.
3464  *
3465  * NOTE: any conflict in relfilenode value will be caught here, if
3466  * GetNewRelFileNode messes up for any reason.
3467  */
3468  newrnode.node = relation->rd_node;
3469  newrnode.node.relNode = newrelfilenode;
3470  newrnode.backend = relation->rd_backend;
3471  RelationCreateStorage(newrnode.node, persistence);
3472  smgrclosenode(newrnode);
3473 
3474  /*
3475  * Schedule unlinking of the old storage at transaction commit.
3476  */
3477  RelationDropStorage(relation);
3478 
3479  /*
3480  * Now update the pg_class row. However, if we're dealing with a mapped
3481  * index, pg_class.relfilenode doesn't change; instead we have to send the
3482  * update to the relation mapper.
3483  */
3484  if (RelationIsMapped(relation))
3486  newrelfilenode,
3487  relation->rd_rel->relisshared,
3488  false);
3489  else
3490  classform->relfilenode = newrelfilenode;
3491 
3492  /* These changes are safe even for a mapped relation */
3493  if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
3494  {
3495  classform->relpages = 0; /* it's empty until further notice */
3496  classform->reltuples = 0;
3497  classform->relallvisible = 0;
3498  }
3499  classform->relfrozenxid = freezeXid;
3500  classform->relminmxid = minmulti;
3501  classform->relpersistence = persistence;
3502 
3503  CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
3504 
3505  heap_freetuple(tuple);
3506 
3507  heap_close(pg_class, RowExclusiveLock);
3508 
3509  /*
3510  * Make the pg_class row change visible, as well as the relation map
3511  * change if any. This will cause the relcache entry to get updated, too.
3512  */
3514 
3515  /*
3516  * Mark the rel as having been given a new relfilenode in the current
3517  * (sub) transaction. This is a hint that can be used to optimize later
3518  * operations on the rel in the same transaction.
3519  */
3521 
3522  /* Flag relation as needing eoxact cleanup (to remove the hint) */
3523  EOXactListAdd(relation);
3524 }
#define EOXactListAdd(rel)
Definition: relcache.c:156
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#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:1373
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:462
void RelationDropStorage(Relation rel)
Definition: storage.c:145
void CommandCounterIncrement(void)
Definition: xact.c:915
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
RelFileNode node
Definition: relfilenode.h:74
RelFileNode rd_node
Definition: rel.h:85
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
BackendId rd_backend
Definition: rel.h:89
#define Assert(condition)
Definition: c.h:670
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:642
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
BackendId backend
Definition: relfilenode.h:75
Oid GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
Definition: catalog.c:395
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
#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:425
void RelationMapUpdateMap(Oid relationId, Oid fileNode, bool shared, bool immediate)
Definition: relmapper.c:248

Variable Documentation

◆ criticalRelcachesBuilt

◆ criticalSharedRelcachesBuilt

bool criticalSharedRelcachesBuilt