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

3035 {
3037  RelIdCacheEnt *idhentry;
3038  int i;
3039 
3040  /*
3041  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3042  * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3043  * logic as in AtEOXact_RelationCache.
3044  */
3046  {
3047  hash_seq_init(&status, RelationIdCache);
3048  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3049  {
3050  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3051  mySubid, parentSubid);
3052  }
3053  }
3054  else
3055  {
3056  for (i = 0; i < eoxact_list_len; i++)
3057  {
3058  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3059  (void *) &eoxact_list[i],
3060  HASH_FIND,
3061  NULL);
3062  if (idhentry != NULL)
3063  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3064  mySubid, parentSubid);
3065  }
3066  }
3067 
3068  /* Don't reset the list; we still need more cleanup later */
3069 }
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:3080
Relation reldesc
Definition: relcache.c:116
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:904
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:1387
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1377
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 2882 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().

2883 {
2885  RelIdCacheEnt *idhentry;
2886  int i;
2887 
2888  /*
2889  * Unless the eoxact_list[] overflowed, we only need to examine the rels
2890  * listed in it. Otherwise fall back on a hash_seq_search scan.
2891  *
2892  * For simplicity, eoxact_list[] entries are not deleted till end of
2893  * top-level transaction, even though we could remove them at
2894  * subtransaction end in some cases, or remove relations from the list if
2895  * they are cleared for other reasons. Therefore we should expect the
2896  * case that list entries are not found in the hashtable; if not, there's
2897  * nothing to do for them.
2898  */
2900  {
2901  hash_seq_init(&status, RelationIdCache);
2902  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2903  {
2904  AtEOXact_cleanup(idhentry->reldesc, isCommit);
2905  }
2906  }
2907  else
2908  {
2909  for (i = 0; i < eoxact_list_len; i++)
2910  {
2911  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
2912  (void *) &eoxact_list[i],
2913  HASH_FIND,
2914  NULL);
2915  if (idhentry != NULL)
2916  AtEOXact_cleanup(idhentry->reldesc, isCommit);
2917  }
2918  }
2919 
2920  if (EOXactTupleDescArrayLen > 0)
2921  {
2922  Assert(EOXactTupleDescArray != NULL);
2923  for (i = 0; i < NextEOXactTupleDescNum; i++)
2926  EOXactTupleDescArray = NULL;
2927  }
2928 
2929  /* Now we're out of the transaction and can clear the lists */
2930  eoxact_list_len = 0;
2931  eoxact_list_overflowed = false;
2932  NextEOXactTupleDescNum = 0;
2934 }
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:904
static HTAB * RelationIdCache
Definition: relcache.c:119
static void AtEOXact_cleanup(Relation relation, bool isCommit)
Definition: relcache.c:2945
static bool eoxact_list_overflowed
Definition: relcache.c:154
static int NextEOXactTupleDescNum
Definition: relcache.c:170
void pfree(void *pointer)
Definition: mcxt.c:936
#define Assert(condition)
Definition: c.h:680
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1387
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1377
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:289
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 5213 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().

5214 {
5218 
5219  return 0; /* return value does not matter */
5220 }
#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:3066
#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 5230 of file relcache.c.

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

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

5231 {
5232  TupleDesc reldesc = RelationGetDescr(rel);
5233  const char *colname;
5234 
5235  /* Use reldesc if it's a user attribute, else consult the catalogs */
5236  if (attnum > 0 && attnum <= reldesc->natts)
5237  colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
5238  else
5239  colname = get_relid_attribute_name(RelationGetRelid(rel), attnum);
5240 
5241  return errtablecolname(rel, colname);
5242 }
#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:557
#define RelationGetRelid(relation)
Definition: rel.h:425
int errtablecolname(Relation rel, const char *colname)
Definition: relcache.c:5254

◆ errtablecolname()

int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5254 of file relcache.c.

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

Referenced by errtablecol().

5255 {
5256  errtable(rel);
5258 
5259  return 0; /* return value does not matter */
5260 }
#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:5213

◆ errtableconstraint()

int errtableconstraint ( Relation  rel,
const char *  conname 
)

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

5268 {
5269  errtable(rel);
5271 
5272  return 0; /* return value does not matter */
5273 }
#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:5213

◆ GetRelationPublicationActions()

struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

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

5143 {
5144  List *puboids;
5145  ListCell *lc;
5146  MemoryContext oldcxt;
5147  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5148 
5149  if (relation->rd_pubactions)
5150  return memcpy(pubactions, relation->rd_pubactions,
5151  sizeof(PublicationActions));
5152 
5153  /* Fetch the publication membership info. */
5154  puboids = GetRelationPublications(RelationGetRelid(relation));
5155  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5156 
5157  foreach(lc, puboids)
5158  {
5159  Oid pubid = lfirst_oid(lc);
5160  HeapTuple tup;
5161  Form_pg_publication pubform;
5162 
5164 
5165  if (!HeapTupleIsValid(tup))
5166  elog(ERROR, "cache lookup failed for publication %u", pubid);
5167 
5168  pubform = (Form_pg_publication) GETSTRUCT(tup);
5169 
5170  pubactions->pubinsert |= pubform->pubinsert;
5171  pubactions->pubupdate |= pubform->pubupdate;
5172  pubactions->pubdelete |= pubform->pubdelete;
5173 
5174  ReleaseSysCache(tup);
5175 
5176  /*
5177  * If we know everything is replicated, there is no point to check for
5178  * other publications.
5179  */
5180  if (pubactions->pubinsert && pubactions->pubupdate &&
5181  pubactions->pubdelete)
5182  break;
5183  }
5184 
5185  if (relation->rd_pubactions)
5186  {
5187  pfree(relation->rd_pubactions);
5188  relation->rd_pubactions = NULL;
5189  }
5190 
5191  /* Now save copy of the actions in the relcache entry. */
5193  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5194  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5195  MemoryContextSwitchTo(oldcxt);
5196 
5197  return pubactions;
5198 }
#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:936
#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:864
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:835
#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 3145 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().

3155 {
3156  Relation rel;
3157  MemoryContext oldcxt;
3158  int natts = tupDesc->natts;
3159  int i;
3160  bool has_not_null;
3161  bool nailit;
3162 
3163  AssertArg(natts >= 0);
3164 
3165  /*
3166  * check for creation of a rel that must be nailed in cache.
3167  *
3168  * XXX this list had better match the relations specially handled in
3169  * RelationCacheInitializePhase2/3.
3170  */
3171  switch (relid)
3172  {
3173  case DatabaseRelationId:
3174  case AuthIdRelationId:
3175  case AuthMemRelationId:
3176  case RelationRelationId:
3177  case AttributeRelationId:
3178  case ProcedureRelationId:
3179  case TypeRelationId:
3180  nailit = true;
3181  break;
3182  default:
3183  nailit = false;
3184  break;
3185  }
3186 
3187  /*
3188  * check that hardwired list of shared rels matches what's in the
3189  * bootstrap .bki file. If you get a failure here during initdb, you
3190  * probably need to fix IsSharedRelation() to match whatever you've done
3191  * to the set of shared relations.
3192  */
3193  if (shared_relation != IsSharedRelation(relid))
3194  elog(ERROR, "shared_relation flag for \"%s\" does not match IsSharedRelation(%u)",
3195  relname, relid);
3196 
3197  /* Shared relations had better be mapped, too */
3198  Assert(mapped_relation || !shared_relation);
3199 
3200  /*
3201  * switch to the cache context to create the relcache entry.
3202  */
3203  if (!CacheMemoryContext)
3205 
3207 
3208  /*
3209  * allocate a new relation descriptor and fill in basic state fields.
3210  */
3211  rel = (Relation) palloc0(sizeof(RelationData));
3212 
3213  /* make sure relation is marked as having no open file yet */
3214  rel->rd_smgr = NULL;
3215 
3216  /* mark it nailed if appropriate */
3217  rel->rd_isnailed = nailit;
3218 
3219  rel->rd_refcnt = nailit ? 1 : 0;
3220 
3221  /* it's being created in this transaction */
3224 
3225  /*
3226  * create a new tuple descriptor from the one passed in. We do this
3227  * partly to copy it into the cache context, and partly because the new
3228  * relation can't have any defaults or constraints yet; they have to be
3229  * added in later steps, because they require additions to multiple system
3230  * catalogs. We can copy attnotnull constraints here, however.
3231  */
3232  rel->rd_att = CreateTupleDescCopy(tupDesc);
3233  rel->rd_att->tdrefcount = 1; /* mark as refcounted */
3234  has_not_null = false;
3235  for (i = 0; i < natts; i++)
3236  {
3237  Form_pg_attribute satt = TupleDescAttr(tupDesc, i);
3238  Form_pg_attribute datt = TupleDescAttr(rel->rd_att, i);
3239 
3240  datt->attidentity = satt->attidentity;
3241  datt->attnotnull = satt->attnotnull;
3242  has_not_null |= satt->attnotnull;
3243  }
3244 
3245  if (has_not_null)
3246  {
3247  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
3248 
3249  constr->has_not_null = true;
3250  rel->rd_att->constr = constr;
3251  }
3252 
3253  /*
3254  * initialize relation tuple form (caller may add/override data later)
3255  */
3257 
3258  namestrcpy(&rel->rd_rel->relname, relname);
3259  rel->rd_rel->relnamespace = relnamespace;
3260 
3261  rel->rd_rel->relkind = relkind;
3262  rel->rd_rel->relhasoids = rel->rd_att->tdhasoid;
3263  rel->rd_rel->relnatts = natts;
3264  rel->rd_rel->reltype = InvalidOid;
3265  /* needed when bootstrapping: */
3266  rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;
3267 
3268  /* set up persistence and relcache fields dependent on it */
3269  rel->rd_rel->relpersistence = relpersistence;
3270  switch (relpersistence)
3271  {
3275  rel->rd_islocaltemp = false;
3276  break;
3277  case RELPERSISTENCE_TEMP:
3278  Assert(isTempOrTempToastNamespace(relnamespace));
3280  rel->rd_islocaltemp = true;
3281  break;
3282  default:
3283  elog(ERROR, "invalid relpersistence: %c", relpersistence);
3284  break;
3285  }
3286 
3287  /* if it's a materialized view, it's not populated initially */
3288  if (relkind == RELKIND_MATVIEW)
3289  rel->rd_rel->relispopulated = false;
3290  else
3291  rel->rd_rel->relispopulated = true;
3292 
3293  /* system relations and non-table objects don't have one */
3294  if (!IsSystemNamespace(relnamespace) &&
3295  (relkind == RELKIND_RELATION ||
3296  relkind == RELKIND_MATVIEW ||
3297  relkind == RELKIND_PARTITIONED_TABLE))
3298  rel->rd_rel->relreplident = REPLICA_IDENTITY_DEFAULT;
3299  else
3300  rel->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
3301 
3302  /*
3303  * Insert relation physical and logical identifiers (OIDs) into the right
3304  * places. For a mapped relation, we set relfilenode to zero and rely on
3305  * RelationInitPhysicalAddr to consult the map.
3306  */
3307  rel->rd_rel->relisshared = shared_relation;
3308 
3309  RelationGetRelid(rel) = relid;
3310 
3311  for (i = 0; i < natts; i++)
3312  TupleDescAttr(rel->rd_att, i)->attrelid = relid;
3313 
3314  rel->rd_rel->reltablespace = reltablespace;
3315 
3316  if (mapped_relation)
3317  {
3318  rel->rd_rel->relfilenode = InvalidOid;
3319  /* Add it to the active mapping information */
3320  RelationMapUpdateMap(relid, relfilenode, shared_relation, true);
3321  }
3322  else
3323  rel->rd_rel->relfilenode = relfilenode;
3324 
3325  RelationInitLockInfo(rel); /* see lmgr.c */
3326 
3328 
3329  /*
3330  * Okay to insert into the relcache hash table.
3331  *
3332  * Ordinarily, there should certainly not be an existing hash entry for
3333  * the same OID; but during bootstrap, when we create a "real" relcache
3334  * entry for one of the bootstrap relations, we'll be overwriting the
3335  * phony one created with formrdesc. So allow that to happen for nailed
3336  * rels.
3337  */
3338  RelationCacheInsert(rel, nailit);
3339 
3340  /*
3341  * Flag relation as needing eoxact cleanup (to clear rd_createSubid). We
3342  * can't do this before storing relid in it.
3343  */
3344  EOXactListAdd(rel);
3345 
3346  /*
3347  * done building relcache entry.
3348  */
3349  MemoryContextSwitchTo(oldcxt);
3350 
3351  /* It's fully valid */
3352  rel->rd_isvalid = true;
3353 
3354  /*
3355  * Caller expects us to pin the returned entry.
3356  */
3358 
3359  return rel;
3360 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
#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:1383
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:682
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:864
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2089
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:680
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:461
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 6044 of file relcache.c.

References LWLockRelease().

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

6045 {
6046  LWLockRelease(RelCacheInitLock);
6047 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1724

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )

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

6019 {
6020  char initfilename[MAXPGPATH];
6021 
6022  snprintf(initfilename, sizeof(initfilename), "%s/%s",
6024 
6025  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6026 
6027  if (unlink(initfilename) < 0)
6028  {
6029  /*
6030  * The file might not be there if no backend has been started since
6031  * the last removal. But complain about failures other than ENOENT.
6032  * Fortunately, it's not too late to abort the transaction if we can't
6033  * get rid of the would-be-obsolete init file.
6034  */
6035  if (errno != ENOENT)
6036  ereport(ERROR,
6038  errmsg("could not remove cache file \"%s\": %m",
6039  initfilename)));
6040  }
6041 }
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:1120
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ RelationCacheInitFileRemove()

void RelationCacheInitFileRemove ( void  )

Definition at line 6059 of file relcache.c.

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

Referenced by StartupXLOG().

6060 {
6061  const char *tblspcdir = "pg_tblspc";
6062  DIR *dir;
6063  struct dirent *de;
6064  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6065 
6066  /*
6067  * We zap the shared cache file too. In theory it can't get out of sync
6068  * enough to be a problem, but in data-corruption cases, who knows ...
6069  */
6070  snprintf(path, sizeof(path), "global/%s",
6072  unlink_initfile(path);
6073 
6074  /* Scan everything in the default tablespace */
6076 
6077  /* Scan the tablespace link directory to find non-default tablespaces */
6078  dir = AllocateDir(tblspcdir);
6079 
6080  while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6081  {
6082  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6083  {
6084  /* Scan the tablespace dir for per-database dirs */
6085  snprintf(path, sizeof(path), "%s/%s/%s",
6086  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6088  }
6089  }
6090 
6091  FreeDir(dir);
6092 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6096
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2678
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:2597
static void unlink_initfile(const char *initfilename)
Definition: relcache.c:6120
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:24
#define TABLESPACE_VERSION_DIRECTORY
Definition: catalog.h:26
char d_name[MAX_PATH]
Definition: dirent.h:14
int FreeDir(DIR *dir)
Definition: fd.c:2715

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 3497 of file relcache.c.

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

Referenced by InitPostgres().

3498 {
3499  HASHCTL ctl;
3500 
3501  /*
3502  * make sure cache memory context exists
3503  */
3504  if (!CacheMemoryContext)
3506 
3507  /*
3508  * create hashtable that indexes the relcache
3509  */
3510  MemSet(&ctl, 0, sizeof(ctl));
3511  ctl.keysize = sizeof(Oid);
3512  ctl.entrysize = sizeof(RelIdCacheEnt);
3513  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3514  &ctl, HASH_ELEM | HASH_BLOBS);
3515 
3516  /*
3517  * relation mapper needs to be initialized too
3518  */
3520 }
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:877
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:3494
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ RelationCacheInitializePhase2()

void RelationCacheInitializePhase2 ( void  )

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

3535 {
3536  MemoryContext oldcxt;
3537 
3538  /*
3539  * relation mapper needs initialized too
3540  */
3542 
3543  /*
3544  * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3545  * nothing.
3546  */
3548  return;
3549 
3550  /*
3551  * switch to cache memory context
3552  */
3554 
3555  /*
3556  * Try to load the shared relcache cache file. If unsuccessful, bootstrap
3557  * the cache with pre-made descriptors for the critical shared catalogs.
3558  */
3559  if (!load_relcache_init_file(true))
3560  {
3561  formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
3563  formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
3565  formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
3567  formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
3569  formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
3571 
3572 #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
3573  }
3574 
3575  MemoryContextSwitchTo(oldcxt);
3576 }
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:5331
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, bool hasoids, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1853
#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 3593 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().

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

2723 {
2725  RelIdCacheEnt *idhentry;
2726  Relation relation;
2727  List *rebuildFirstList = NIL;
2728  List *rebuildList = NIL;
2729  ListCell *l;
2730 
2731  /*
2732  * Reload relation mapping data before starting to reconstruct cache.
2733  */
2735 
2736  /* Phase 1 */
2737  hash_seq_init(&status, RelationIdCache);
2738 
2739  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2740  {
2741  relation = idhentry->reldesc;
2742 
2743  /* Must close all smgr references to avoid leaving dangling ptrs */
2744  RelationCloseSmgr(relation);
2745 
2746  /*
2747  * Ignore new relations; no other backend will manipulate them before
2748  * we commit. Likewise, before replacing a relation's relfilenode, we
2749  * shall have acquired AccessExclusiveLock and drained any applicable
2750  * pending invalidations.
2751  */
2752  if (relation->rd_createSubid != InvalidSubTransactionId ||
2754  continue;
2755 
2757 
2758  if (RelationHasReferenceCountZero(relation))
2759  {
2760  /* Delete this entry immediately */
2761  Assert(!relation->rd_isnailed);
2762  RelationClearRelation(relation, false);
2763  }
2764  else
2765  {
2766  /*
2767  * If it's a mapped relation, immediately update its rd_node in
2768  * case its relfilenode changed. We must do this during phase 1
2769  * in case the relation is consulted during rebuild of other
2770  * relcache entries in phase 2. It's safe since consulting the
2771  * map doesn't involve any access to relcache entries.
2772  */
2773  if (RelationIsMapped(relation))
2774  RelationInitPhysicalAddr(relation);
2775 
2776  /*
2777  * Add this entry to list of stuff to rebuild in second pass.
2778  * pg_class goes to the front of rebuildFirstList while
2779  * pg_class_oid_index goes to the back of rebuildFirstList, so
2780  * they are done first and second respectively. Other nailed
2781  * relations go to the front of rebuildList, so they'll be done
2782  * next in no particular order; and everything else goes to the
2783  * back of rebuildList.
2784  */
2785  if (RelationGetRelid(relation) == RelationRelationId)
2786  rebuildFirstList = lcons(relation, rebuildFirstList);
2787  else if (RelationGetRelid(relation) == ClassOidIndexId)
2788  rebuildFirstList = lappend(rebuildFirstList, relation);
2789  else if (relation->rd_isnailed)
2790  rebuildList = lcons(relation, rebuildList);
2791  else
2792  rebuildList = lappend(rebuildList, relation);
2793  }
2794  }
2795 
2796  /*
2797  * Now zap any remaining smgr cache entries. This must happen before we
2798  * start to rebuild entries, since that may involve catalog fetches which
2799  * will re-open catalog files.
2800  */
2801  smgrcloseall();
2802 
2803  /* Phase 2: rebuild the items found to need rebuild in phase 1 */
2804  foreach(l, rebuildFirstList)
2805  {
2806  relation = (Relation) lfirst(l);
2807  RelationClearRelation(relation, true);
2808  }
2809  list_free(rebuildFirstList);
2810  foreach(l, rebuildList)
2811  {
2812  relation = (Relation) lfirst(l);
2813  RelationClearRelation(relation, true);
2814  }
2815  list_free(rebuildList);
2816 }
#define NIL
Definition: pg_list.h:69
static long relcacheInvalsReceived
Definition: relcache.c:139
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2354
#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:1383
#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:680
#define lfirst(lc)
Definition: pg_list.h:106
#define InvalidSubTransactionId
Definition: c.h:461
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1387
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1377
#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 2678 of file relcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

2679 {
2680  Relation relation;
2681 
2682  RelationIdCacheLookup(relationId, relation);
2683 
2684  if (PointerIsValid(relation))
2685  {
2687  RelationFlushRelation(relation);
2688  }
2689 }
static long relcacheInvalsReceived
Definition: relcache.c:139
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:198
static void RelationFlushRelation(Relation relation)
Definition: relcache.c:2610
#define PointerIsValid(pointer)
Definition: c.h:574

◆ RelationClose()

void RelationClose ( Relation  relation)

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

2123 {
2124  /* Note: no locking manipulations needed */
2126 
2127 #ifdef RELCACHE_FORCE_RELEASE
2128  if (RelationHasReferenceCountZero(relation) &&
2129  relation->rd_createSubid == InvalidSubTransactionId &&
2131  RelationClearRelation(relation, false);
2132 #endif
2133 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2354
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:111
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2102
SubTransactionId rd_createSubid
Definition: rel.h:110
#define InvalidSubTransactionId
Definition: c.h:461
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:409

◆ RelationCloseSmgrByOid()

void RelationCloseSmgrByOid ( Oid  relationId)

Definition at line 2825 of file relcache.c.

References PointerIsValid, RelationCloseSmgr, and RelationIdCacheLookup.

Referenced by swap_relation_files().

2826 {
2827  Relation relation;
2828 
2829  RelationIdCacheLookup(relationId, relation);
2830 
2831  if (!PointerIsValid(relation))
2832  return; /* not in cache, nothing to do */
2833 
2834  RelationCloseSmgr(relation);
2835 }
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:198
#define RelationCloseSmgr(relation)
Definition: rel.h:481
#define PointerIsValid(pointer)
Definition: c.h:574

◆ RelationForgetRelation()

void RelationForgetRelation ( Oid  rid)

Definition at line 2646 of file relcache.c.

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

Referenced by heap_drop_with_catalog(), and index_drop().

2647 {
2648  Relation relation;
2649 
2650  RelationIdCacheLookup(rid, relation);
2651 
2652  if (!PointerIsValid(relation))
2653  return; /* not in cache, nothing to do */
2654 
2655  if (!RelationHasReferenceCountZero(relation))
2656  elog(ERROR, "relation %u is still open", rid);
2657 
2658  /* Unconditionally destroy the relcache entry */
2659  RelationClearRelation(relation, false);
2660 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2354
#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:574

◆ RelationGetExclusionInfo()

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

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

5028 {
5029  int ncols = indexRelation->rd_rel->relnatts;
5030  Oid *ops;
5031  Oid *funcs;
5032  uint16 *strats;
5033  Relation conrel;
5034  SysScanDesc conscan;
5035  ScanKeyData skey[1];
5036  HeapTuple htup;
5037  bool found;
5038  MemoryContext oldcxt;
5039  int i;
5040 
5041  /* Allocate result space in caller context */
5042  *operators = ops = (Oid *) palloc(sizeof(Oid) * ncols);
5043  *procs = funcs = (Oid *) palloc(sizeof(Oid) * ncols);
5044  *strategies = strats = (uint16 *) palloc(sizeof(uint16) * ncols);
5045 
5046  /* Quick exit if we have the data cached already */
5047  if (indexRelation->rd_exclstrats != NULL)
5048  {
5049  memcpy(ops, indexRelation->rd_exclops, sizeof(Oid) * ncols);
5050  memcpy(funcs, indexRelation->rd_exclprocs, sizeof(Oid) * ncols);
5051  memcpy(strats, indexRelation->rd_exclstrats, sizeof(uint16) * ncols);
5052  return;
5053  }
5054 
5055  /*
5056  * Search pg_constraint for the constraint associated with the index. To
5057  * make this not too painfully slow, we use the index on conrelid; that
5058  * will hold the parent relation's OID not the index's own OID.
5059  */
5060  ScanKeyInit(&skey[0],
5062  BTEqualStrategyNumber, F_OIDEQ,
5063  ObjectIdGetDatum(indexRelation->rd_index->indrelid));
5064 
5066  conscan = systable_beginscan(conrel, ConstraintRelidIndexId, true,
5067  NULL, 1, skey);
5068  found = false;
5069 
5070  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
5071  {
5073  Datum val;
5074  bool isnull;
5075  ArrayType *arr;
5076  int nelem;
5077 
5078  /* We want the exclusion constraint owning the index */
5079  if (conform->contype != CONSTRAINT_EXCLUSION ||
5080  conform->conindid != RelationGetRelid(indexRelation))
5081  continue;
5082 
5083  /* There should be only one */
5084  if (found)
5085  elog(ERROR, "unexpected exclusion constraint record found for rel %s",
5086  RelationGetRelationName(indexRelation));
5087  found = true;
5088 
5089  /* Extract the operator OIDS from conexclop */
5090  val = fastgetattr(htup,
5092  conrel->rd_att, &isnull);
5093  if (isnull)
5094  elog(ERROR, "null conexclop for rel %s",
5095  RelationGetRelationName(indexRelation));
5096 
5097  arr = DatumGetArrayTypeP(val); /* ensure not toasted */
5098  nelem = ARR_DIMS(arr)[0];
5099  if (ARR_NDIM(arr) != 1 ||
5100  nelem != ncols ||
5101  ARR_HASNULL(arr) ||
5102  ARR_ELEMTYPE(arr) != OIDOID)
5103  elog(ERROR, "conexclop is not a 1-D Oid array");
5104 
5105  memcpy(ops, ARR_DATA_PTR(arr), sizeof(Oid) * ncols);
5106  }
5107 
5108  systable_endscan(conscan);
5109  heap_close(conrel, AccessShareLock);
5110 
5111  if (!found)
5112  elog(ERROR, "exclusion constraint record missing for rel %s",
5113  RelationGetRelationName(indexRelation));
5114 
5115  /* We need the func OIDs and strategy numbers too */
5116  for (i = 0; i < ncols; i++)
5117  {
5118  funcs[i] = get_opcode(ops[i]);
5119  strats[i] = get_op_opfamily_strategy(ops[i],
5120  indexRelation->rd_opfamily[i]);
5121  /* shouldn't fail, since it was checked at index creation */
5122  if (strats[i] == InvalidStrategy)
5123  elog(ERROR, "could not find strategy for operator %u in family %u",
5124  ops[i], indexRelation->rd_opfamily[i]);
5125  }
5126 
5127  /* Save a copy of the results in the relcache entry. */
5128  oldcxt = MemoryContextSwitchTo(indexRelation->rd_indexcxt);
5129  indexRelation->rd_exclops = (Oid *) palloc(sizeof(Oid) * ncols);
5130  indexRelation->rd_exclprocs = (Oid *) palloc(sizeof(Oid) * ncols);
5131  indexRelation->rd_exclstrats = (uint16 *) palloc(sizeof(uint16) * ncols);
5132  memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * ncols);
5133  memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * ncols);
5134  memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * ncols);
5135  MemoryContextSwitchTo(oldcxt);
5136 }
#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:305
#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:835
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 4152 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().

4153 {
4154  List *result;
4155  Relation conrel;
4156  SysScanDesc conscan;
4157  ScanKeyData skey;
4158  HeapTuple htup;
4159  List *oldlist;
4160  MemoryContext oldcxt;
4161 
4162  /* Quick exit if we already computed the list. */
4163  if (relation->rd_fkeyvalid)
4164  return relation->rd_fkeylist;
4165 
4166  /* Fast path: if it doesn't have any triggers, it can't have FKs */
4167  if (!relation->rd_rel->relhastriggers)
4168  return NIL;
4169 
4170  /*
4171  * We build the list we intend to return (in the caller's context) while
4172  * doing the scan. After successfully completing the scan, we copy that
4173  * list into the relcache entry. This avoids cache-context memory leakage
4174  * if we get some sort of error partway through.
4175  */
4176  result = NIL;
4177 
4178  /* Prepare to scan pg_constraint for entries having conrelid = this rel. */
4179  ScanKeyInit(&skey,
4181  BTEqualStrategyNumber, F_OIDEQ,
4182  ObjectIdGetDatum(RelationGetRelid(relation)));
4183 
4185  conscan = systable_beginscan(conrel, ConstraintRelidIndexId, true,
4186  NULL, 1, &skey);
4187 
4188  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4189  {
4190  Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(htup);
4191  ForeignKeyCacheInfo *info;
4192  Datum adatum;
4193  bool isnull;
4194  ArrayType *arr;
4195  int nelem;
4196 
4197  /* consider only foreign keys */
4198  if (constraint->contype != CONSTRAINT_FOREIGN)
4199  continue;
4200 
4201  info = makeNode(ForeignKeyCacheInfo);
4202  info->conrelid = constraint->conrelid;
4203  info->confrelid = constraint->confrelid;
4204 
4205  /* Extract data from conkey field */
4206  adatum = fastgetattr(htup, Anum_pg_constraint_conkey,
4207  conrel->rd_att, &isnull);
4208  if (isnull)
4209  elog(ERROR, "null conkey for rel %s",
4210  RelationGetRelationName(relation));
4211 
4212  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
4213  nelem = ARR_DIMS(arr)[0];
4214  if (ARR_NDIM(arr) != 1 ||
4215  nelem < 1 ||
4216  nelem > INDEX_MAX_KEYS ||
4217  ARR_HASNULL(arr) ||
4218  ARR_ELEMTYPE(arr) != INT2OID)
4219  elog(ERROR, "conkey is not a 1-D smallint array");
4220 
4221  info->nkeys = nelem;
4222  memcpy(info->conkey, ARR_DATA_PTR(arr), nelem * sizeof(AttrNumber));
4223 
4224  /* Likewise for confkey */
4225  adatum = fastgetattr(htup, Anum_pg_constraint_confkey,
4226  conrel->rd_att, &isnull);
4227  if (isnull)
4228  elog(ERROR, "null confkey for rel %s",
4229  RelationGetRelationName(relation));
4230 
4231  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
4232  nelem = ARR_DIMS(arr)[0];
4233  if (ARR_NDIM(arr) != 1 ||
4234  nelem != info->nkeys ||
4235  ARR_HASNULL(arr) ||
4236  ARR_ELEMTYPE(arr) != INT2OID)
4237  elog(ERROR, "confkey is not a 1-D smallint array");
4238 
4239  memcpy(info->confkey, ARR_DATA_PTR(arr), nelem * sizeof(AttrNumber));
4240 
4241  /* Likewise for conpfeqop */
4243  conrel->rd_att, &isnull);
4244  if (isnull)
4245  elog(ERROR, "null conpfeqop for rel %s",
4246  RelationGetRelationName(relation));
4247 
4248  arr = DatumGetArrayTypeP(adatum); /* ensure not toasted */
4249  nelem = ARR_DIMS(arr)[0];
4250  if (ARR_NDIM(arr) != 1 ||
4251  nelem != info->nkeys ||
4252  ARR_HASNULL(arr) ||
4253  ARR_ELEMTYPE(arr) != OIDOID)
4254  elog(ERROR, "conpfeqop is not a 1-D OID array");
4255 
4256  memcpy(info->conpfeqop, ARR_DATA_PTR(arr), nelem * sizeof(Oid));
4257 
4258  /* Add FK's node to the result list */
4259  result = lappend(result, info);
4260  }
4261 
4262  systable_endscan(conscan);
4263  heap_close(conrel, AccessShareLock);
4264 
4265  /* Now save a copy of the completed list in the relcache entry. */
4267  oldlist = relation->rd_fkeylist;
4268  relation->rd_fkeylist = copyObject(result);
4269  relation->rd_fkeyvalid = true;
4270  MemoryContextSwitchTo(oldcxt);
4271 
4272  /* Don't leak the old list, if there is one */
4273  list_free_deep(oldlist);
4274 
4275  return result;
4276 }
#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:560
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:625
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 4817 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().

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

4672 {
4673  List *result;
4674  Datum exprsDatum;
4675  bool isnull;
4676  char *exprsString;
4677  MemoryContext oldcxt;
4678 
4679  /* Quick exit if we already computed the result. */
4680  if (relation->rd_indexprs)
4681  return copyObject(relation->rd_indexprs);
4682 
4683  /* Quick exit if there is nothing to do. */
4684  if (relation->rd_indextuple == NULL ||
4686  return NIL;
4687 
4688  /*
4689  * We build the tree we intend to return in the caller's context. After
4690  * successfully completing the work, we copy it into the relcache entry.
4691  * This avoids problems if we get some sort of error partway through.
4692  */
4693  exprsDatum = heap_getattr(relation->rd_indextuple,
4696  &isnull);
4697  Assert(!isnull);
4698  exprsString = TextDatumGetCString(exprsDatum);
4699  result = (List *) stringToNode(exprsString);
4700  pfree(exprsString);
4701 
4702  /*
4703  * Run the expressions through eval_const_expressions. This is not just an
4704  * optimization, but is necessary, because the planner will be comparing
4705  * them to similarly-processed qual clauses, and may fail to detect valid
4706  * matches without this. We don't bother with canonicalize_qual, however.
4707  */
4708  result = (List *) eval_const_expressions(NULL, (Node *) result);
4709 
4710  result = (List *) canonicalize_qual((Expr *) result);
4711 
4712  /* May as well fix opfuncids too */
4713  fix_opfuncids((Node *) result);
4714 
4715  /* Now save a copy of the completed tree in the relcache entry. */
4716  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4717  relation->rd_indexprs = copyObject(result);
4718  MemoryContextSwitchTo(oldcxt);
4719 
4720  return result;
4721 }
#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:512
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2462
struct HeapTupleData * rd_indextuple
Definition: rel.h:161
void pfree(void *pointer)
Definition: mcxt.c:936
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:3967
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:680
MemoryContext rd_indexcxt
Definition: rel.h:179
#define copyObject(obj)
Definition: nodes.h:625
Definition: pg_list.h:45
#define Anum_pg_index_indexprs
Definition: pg_index.h:91

◆ RelationGetIndexList()

List* RelationGetIndexList ( Relation  relation)

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

4316 {
4317  Relation indrel;
4318  SysScanDesc indscan;
4319  ScanKeyData skey;
4320  HeapTuple htup;
4321  List *result;
4322  List *oldlist;
4323  char replident = relation->rd_rel->relreplident;
4324  Oid oidIndex = InvalidOid;
4325  Oid pkeyIndex = InvalidOid;
4326  Oid candidateIndex = InvalidOid;
4327  MemoryContext oldcxt;
4328 
4329  /* Quick exit if we already computed the list. */
4330  if (relation->rd_indexvalid != 0)
4331  return list_copy(relation->rd_indexlist);
4332 
4333  /*
4334  * We build the list we intend to return (in the caller's context) while
4335  * doing the scan. After successfully completing the scan, we copy that
4336  * list into the relcache entry. This avoids cache-context memory leakage
4337  * if we get some sort of error partway through.
4338  */
4339  result = NIL;
4340  oidIndex = InvalidOid;
4341 
4342  /* Prepare to scan pg_index for entries having indrelid = this rel. */
4343  ScanKeyInit(&skey,
4345  BTEqualStrategyNumber, F_OIDEQ,
4346  ObjectIdGetDatum(RelationGetRelid(relation)));
4347 
4349  indscan = systable_beginscan(indrel, IndexIndrelidIndexId, true,
4350  NULL, 1, &skey);
4351 
4352  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4353  {
4355  Datum indclassDatum;
4356  oidvector *indclass;
4357  bool isnull;
4358 
4359  /*
4360  * Ignore any indexes that are currently being dropped. This will
4361  * prevent them from being searched, inserted into, or considered in
4362  * HOT-safety decisions. It's unsafe to touch such an index at all
4363  * since its catalog entries could disappear at any instant.
4364  */
4365  if (!IndexIsLive(index))
4366  continue;
4367 
4368  /* Add index's OID to result list in the proper order */
4369  result = insert_ordered_oid(result, index->indexrelid);
4370 
4371  /*
4372  * indclass cannot be referenced directly through the C struct,
4373  * because it comes after the variable-width indkey field. Must
4374  * extract the datum the hard way...
4375  */
4376  indclassDatum = heap_getattr(htup,
4379  &isnull);
4380  Assert(!isnull);
4381  indclass = (oidvector *) DatumGetPointer(indclassDatum);
4382 
4383  /*
4384  * Invalid, non-unique, non-immediate or predicate indexes aren't
4385  * interesting for either oid indexes or replication identity indexes,
4386  * so don't check them.
4387  */
4388  if (!IndexIsValid(index) || !index->indisunique ||
4389  !index->indimmediate ||
4391  continue;
4392 
4393  /* Check to see if is a usable btree index on OID */
4394  if (index->indnatts == 1 &&
4395  index->indkey.values[0] == ObjectIdAttributeNumber &&
4396  indclass->values[0] == OID_BTREE_OPS_OID)
4397  oidIndex = index->indexrelid;
4398 
4399  /* remember primary key index if any */
4400  if (index->indisprimary)
4401  pkeyIndex = index->indexrelid;
4402 
4403  /* remember explicitly chosen replica index */
4404  if (index->indisreplident)
4405  candidateIndex = index->indexrelid;
4406  }
4407 
4408  systable_endscan(indscan);
4409 
4410  heap_close(indrel, AccessShareLock);
4411 
4412  /* Now save a copy of the completed list in the relcache entry. */
4414  oldlist = relation->rd_indexlist;
4415  relation->rd_indexlist = list_copy(result);
4416  relation->rd_oidindex = oidIndex;
4417  relation->rd_pkindex = pkeyIndex;
4418  if (replident == REPLICA_IDENTITY_DEFAULT && OidIsValid(pkeyIndex))
4419  relation->rd_replidindex = pkeyIndex;
4420  else if (replident == REPLICA_IDENTITY_INDEX && OidIsValid(candidateIndex))
4421  relation->rd_replidindex = candidateIndex;
4422  else
4423  relation->rd_replidindex = InvalidOid;
4424  relation->rd_indexvalid = 1;
4425  MemoryContextSwitchTo(oldcxt);
4426 
4427  /* Don't leak the old list, if there is one */
4428  list_free(oldlist);
4429 
4430  return result;
4431 }
#define NIL
Definition: pg_list.h:69
Definition: c.h:536
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:4521
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:586
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:3967
char rd_indexvalid
Definition: rel.h:93
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:544
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:680
#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 4734 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().

4735 {
4736  List *result;
4737  Datum predDatum;
4738  bool isnull;
4739  char *predString;
4740  MemoryContext oldcxt;
4741 
4742  /* Quick exit if we already computed the result. */
4743  if (relation->rd_indpred)
4744  return copyObject(relation->rd_indpred);
4745 
4746  /* Quick exit if there is nothing to do. */
4747  if (relation->rd_indextuple == NULL ||
4749  return NIL;
4750 
4751  /*
4752  * We build the tree we intend to return in the caller's context. After
4753  * successfully completing the work, we copy it into the relcache entry.
4754  * This avoids problems if we get some sort of error partway through.
4755  */
4756  predDatum = heap_getattr(relation->rd_indextuple,
4759  &isnull);
4760  Assert(!isnull);
4761  predString = TextDatumGetCString(predDatum);
4762  result = (List *) stringToNode(predString);
4763  pfree(predString);
4764 
4765  /*
4766  * Run the expression through const-simplification and canonicalization.
4767  * This is not just an optimization, but is necessary, because the planner
4768  * will be comparing it to similarly-processed qual clauses, and may fail
4769  * to detect valid matches without this. This must match the processing
4770  * done to qual clauses in preprocess_expression()! (We can skip the
4771  * stuff involving subqueries, however, since we don't allow any in index
4772  * predicates.)
4773  */
4774  result = (List *) eval_const_expressions(NULL, (Node *) result);
4775 
4776  result = (List *) canonicalize_qual((Expr *) result);
4777 
4778  /* Also convert to implicit-AND format */
4779  result = make_ands_implicit((Expr *) result);
4780 
4781  /* May as well fix opfuncids too */
4782  fix_opfuncids((Node *) result);
4783 
4784  /* Now save a copy of the completed tree in the relcache entry. */
4785  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4786  relation->rd_indpred = copyObject(result);
4787  MemoryContextSwitchTo(oldcxt);
4788 
4789  return result;
4790 }
#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:512
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2462
struct HeapTupleData * rd_indextuple
Definition: rel.h:161
void pfree(void *pointer)
Definition: mcxt.c:936
List * make_ands_implicit(Expr *clause)
Definition: clauses.c:381
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:3967
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:680
MemoryContext rd_indexcxt
Definition: rel.h:179
#define copyObject(obj)
Definition: nodes.h:625
Definition: pg_list.h:45

◆ RelationGetOidIndex()

Oid RelationGetOidIndex ( Relation  relation)

Definition at line 4597 of file relcache.c.

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

Referenced by GetNewOid().

4598 {
4599  List *ilist;
4600 
4601  /*
4602  * If relation doesn't have OIDs at all, caller is probably confused. (We
4603  * could just silently return InvalidOid, but it seems better to throw an
4604  * assertion.)
4605  */
4606  Assert(relation->rd_rel->relhasoids);
4607 
4608  if (relation->rd_indexvalid == 0)
4609  {
4610  /* RelationGetIndexList does the heavy lifting. */
4611  ilist = RelationGetIndexList(relation);
4612  list_free(ilist);
4613  Assert(relation->rd_indexvalid != 0);
4614  }
4615 
4616  return relation->rd_oidindex;
4617 }
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:680
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4315
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45

◆ RelationGetPrimaryKeyIndex()

Oid RelationGetPrimaryKeyIndex ( Relation  relation)

Definition at line 4625 of file relcache.c.

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

Referenced by GetRelationIdentityOrPK().

4626 {
4627  List *ilist;
4628 
4629  if (relation->rd_indexvalid == 0)
4630  {
4631  /* RelationGetIndexList does the heavy lifting. */
4632  ilist = RelationGetIndexList(relation);
4633  list_free(ilist);
4634  Assert(relation->rd_indexvalid != 0);
4635  }
4636 
4637  return relation->rd_pkindex;
4638 }
Oid rd_pkindex
Definition: rel.h:137
char rd_indexvalid
Definition: rel.h:93
#define Assert(condition)
Definition: c.h:680
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4315
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45

◆ RelationGetReplicaIndex()

Oid RelationGetReplicaIndex ( Relation  relation)

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

4647 {
4648  List *ilist;
4649 
4650  if (relation->rd_indexvalid == 0)
4651  {
4652  /* RelationGetIndexList does the heavy lifting. */
4653  ilist = RelationGetIndexList(relation);
4654  list_free(ilist);
4655  Assert(relation->rd_indexvalid != 0);
4656  }
4657 
4658  return relation->rd_replidindex;
4659 }
Oid rd_replidindex
Definition: rel.h:138
char rd_indexvalid
Definition: rel.h:93
#define Assert(condition)
Definition: c.h:680
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4315
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45

◆ RelationGetStatExtList()

List* RelationGetStatExtList ( Relation  relation)

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

4456 {
4457  Relation indrel;
4458  SysScanDesc indscan;
4459  ScanKeyData skey;
4460  HeapTuple htup;
4461  List *result;
4462  List *oldlist;
4463  MemoryContext oldcxt;
4464 
4465  /* Quick exit if we already computed the list. */
4466  if (relation->rd_statvalid != 0)
4467  return list_copy(relation->rd_statlist);
4468 
4469  /*
4470  * We build the list we intend to return (in the caller's context) while
4471  * doing the scan. After successfully completing the scan, we copy that
4472  * list into the relcache entry. This avoids cache-context memory leakage
4473  * if we get some sort of error partway through.
4474  */
4475  result = NIL;
4476 
4477  /*
4478  * Prepare to scan pg_statistic_ext for entries having stxrelid = this
4479  * rel.
4480  */
4481  ScanKeyInit(&skey,
4483  BTEqualStrategyNumber, F_OIDEQ,
4484  ObjectIdGetDatum(RelationGetRelid(relation)));
4485 
4487  indscan = systable_beginscan(indrel, StatisticExtRelidIndexId, true,
4488  NULL, 1, &skey);
4489 
4490  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4491  result = insert_ordered_oid(result, HeapTupleGetOid(htup));
4492 
4493  systable_endscan(indscan);
4494 
4495  heap_close(indrel, AccessShareLock);
4496 
4497  /* Now save a copy of the completed list in the relcache entry. */
4499  oldlist = relation->rd_statlist;
4500  relation->rd_statlist = list_copy(result);
4501 
4502  relation->rd_statvalid = true;
4503  MemoryContextSwitchTo(oldcxt);
4504 
4505  /* Don't leak the old list, if there is one */
4506  list_free(oldlist);
4507 
4508  return result;
4509 }
#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:4521
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 2033 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().

2034 {
2035  Relation rd;
2036 
2037  /* Make sure we're in an xact, even if this ends up being a cache hit */
2039 
2040  /*
2041  * first try to find reldesc in the cache
2042  */
2043  RelationIdCacheLookup(relationId, rd);
2044 
2045  if (RelationIsValid(rd))
2046  {
2048  /* revalidate cache entry if necessary */
2049  if (!rd->rd_isvalid)
2050  {
2051  /*
2052  * Indexes only have a limited number of possible schema changes,
2053  * and we don't want to use the full-blown procedure because it's
2054  * a headache for indexes that reload itself depends on.
2055  */
2056  if (rd->rd_rel->relkind == RELKIND_INDEX)
2058  else
2059  RelationClearRelation(rd, true);
2060  Assert(rd->rd_isvalid);
2061  }
2062  return rd;
2063  }
2064 
2065  /*
2066  * no reldesc in the cache, so have RelationBuildDesc() build one and add
2067  * it.
2068  */
2069  rd = RelationBuildDesc(relationId, true);
2070  if (RelationIsValid(rd))
2072  return rd;
2073 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2354
#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:2089
static void RelationReloadIndexInfo(Relation relation)
Definition: relcache.c:2163
#define Assert(condition)
Definition: c.h:680
static Relation RelationBuildDesc(Oid targetRelId, bool insertIt)
Definition: relcache.c:1198
bool IsTransactionState(void)
Definition: xact.c:351
#define RELKIND_INDEX
Definition: pg_class.h:161

◆ RelationIdIsInInitFile()

bool RelationIdIsInInitFile ( Oid  relationId)

Definition at line 5935 of file relcache.c.

References Assert, RelationSupportsSysCache(), and TriggerRelidNameIndexId.

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

5936 {
5937  if (relationId == TriggerRelidNameIndexId)
5938  {
5939  /* If this Assert fails, we don't need this special case anymore. */
5940  Assert(!RelationSupportsSysCache(relationId));
5941  return true;
5942  }
5943  return RelationSupportsSysCache(relationId);
5944 }
#define TriggerRelidNameIndexId
Definition: indexing.h:249
#define Assert(condition)
Definition: c.h:680
bool RelationSupportsSysCache(Oid relid)
Definition: syscache.c:1512

◆ RelationInitIndexAccessInfo()

void RelationInitIndexAccessInfo ( Relation  relation)

Definition at line 1470 of file relcache.c.

References ALLOCSET_SMALL_SIZES, AllocSetContextCreateExtended(), 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(), MEMCONTEXT_COPY_NAME, 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().

1471 {
1472  HeapTuple tuple;
1473  Form_pg_am aform;
1474  Datum indcollDatum;
1475  Datum indclassDatum;
1476  Datum indoptionDatum;
1477  bool isnull;
1478  oidvector *indcoll;
1479  oidvector *indclass;
1480  int2vector *indoption;
1481  MemoryContext indexcxt;
1482  MemoryContext oldcontext;
1483  int natts;
1484  uint16 amsupport;
1485 
1486  /*
1487  * Make a copy of the pg_index entry for the index. Since pg_index
1488  * contains variable-length and possibly-null fields, we have to do this
1489  * honestly rather than just treating it as a Form_pg_index struct.
1490  */
1491  tuple = SearchSysCache1(INDEXRELID,
1492  ObjectIdGetDatum(RelationGetRelid(relation)));
1493  if (!HeapTupleIsValid(tuple))
1494  elog(ERROR, "cache lookup failed for index %u",
1495  RelationGetRelid(relation));
1497  relation->rd_indextuple = heap_copytuple(tuple);
1498  relation->rd_index = (Form_pg_index) GETSTRUCT(relation->rd_indextuple);
1499  MemoryContextSwitchTo(oldcontext);
1500  ReleaseSysCache(tuple);
1501 
1502  /*
1503  * Look up the index's access method, save the OID of its handler function
1504  */
1505  tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(relation->rd_rel->relam));
1506  if (!HeapTupleIsValid(tuple))
1507  elog(ERROR, "cache lookup failed for access method %u",
1508  relation->rd_rel->relam);
1509  aform = (Form_pg_am) GETSTRUCT(tuple);
1510  relation->rd_amhandler = aform->amhandler;
1511  ReleaseSysCache(tuple);
1512 
1513  natts = relation->rd_rel->relnatts;
1514  if (natts != relation->rd_index->indnatts)
1515  elog(ERROR, "relnatts disagrees with indnatts for index %u",
1516  RelationGetRelid(relation));
1517 
1518  /*
1519  * Make the private context to hold index access info. The reason we need
1520  * a context, and not just a couple of pallocs, is so that we won't leak
1521  * any subsidiary info attached to fmgr lookup records.
1522  */
1524  RelationGetRelationName(relation),
1527  relation->rd_indexcxt = indexcxt;
1528 
1529  /*
1530  * Now we can fetch the index AM's API struct
1531  */
1532  InitIndexAmRoutine(relation);
1533 
1534  /*
1535  * Allocate arrays to hold data
1536  */
1537  relation->rd_opfamily = (Oid *)
1538  MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
1539  relation->rd_opcintype = (Oid *)
1540  MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
1541 
1542  amsupport = relation->rd_amroutine->amsupport;
1543  if (amsupport > 0)
1544  {
1545  int nsupport = natts * amsupport;
1546 
1547  relation->rd_support = (RegProcedure *)
1548  MemoryContextAllocZero(indexcxt, nsupport * sizeof(RegProcedure));
1549  relation->rd_supportinfo = (FmgrInfo *)
1550  MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
1551  }
1552  else
1553  {
1554  relation->rd_support = NULL;
1555  relation->rd_supportinfo = NULL;
1556  }
1557 
1558  relation->rd_indcollation = (Oid *)
1559  MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
1560 
1561  relation->rd_indoption = (int16 *)
1562  MemoryContextAllocZero(indexcxt, natts * sizeof(int16));
1563 
1564  /*
1565  * indcollation cannot be referenced directly through the C struct,
1566  * because it comes after the variable-width indkey field. Must extract
1567  * the datum the hard way...
1568  */
1569  indcollDatum = fastgetattr(relation->rd_indextuple,
1572  &isnull);
1573  Assert(!isnull);
1574  indcoll = (oidvector *) DatumGetPointer(indcollDatum);
1575  memcpy(relation->rd_indcollation, indcoll->values, natts * sizeof(Oid));
1576 
1577  /*
1578  * indclass cannot be referenced directly through the C struct, because it
1579  * comes after the variable-width indkey field. Must extract the datum
1580  * the hard way...
1581  */
1582  indclassDatum = fastgetattr(relation->rd_indextuple,
1585  &isnull);
1586  Assert(!isnull);
1587  indclass = (oidvector *) DatumGetPointer(indclassDatum);
1588 
1589  /*
1590  * Fill the support procedure OID array, as well as the info about
1591  * opfamilies and opclass input types. (aminfo and supportinfo are left
1592  * as zeroes, and are filled on-the-fly when used)
1593  */
1594  IndexSupportInitialize(indclass, relation->rd_support,
1595  relation->rd_opfamily, relation->rd_opcintype,
1596  amsupport, natts);
1597 
1598  /*
1599  * Similarly extract indoption and copy it to the cache entry
1600  */
1601  indoptionDatum = fastgetattr(relation->rd_indextuple,
1604  &isnull);
1605  Assert(!isnull);
1606  indoption = (int2vector *) DatumGetPointer(indoptionDatum);
1607  memcpy(relation->rd_indoption, indoption->values, natts * sizeof(int16));
1608 
1609  /*
1610  * expressions, predicate, exclusion caches will be filled later
1611  */
1612  relation->rd_indexprs = NIL;
1613  relation->rd_indpred = NIL;
1614  relation->rd_exclops = NULL;
1615  relation->rd_exclprocs = NULL;
1616  relation->rd_exclstrats = NULL;
1617  relation->rd_amcache = NULL;
1618 }
signed short int16
Definition: c.h:293
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:611
#define NIL
Definition: pg_list.h:69
Definition: c.h:536
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 MEMCONTEXT_COPY_NAME
Definition: memutils.h:188
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:207
regproc RegProcedure
Definition: c.h:453
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:1446
static void IndexSupportInitialize(oidvector *indclass, RegProcedure *indexSupport, Oid *opFamily, Oid *opcInType, StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber)
Definition: relcache.c:1634
struct HeapTupleData * rd_indextuple
Definition: rel.h:161
Form_pg_index rd_index
Definition: rel.h:159
unsigned short uint16
Definition: c.h:305
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
MemoryContext AllocSetContextCreateExtended(MemoryContext parent, const char *name, int flags, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:394
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:3967
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:544
#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:525
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:728
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:680
int16 values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:533
#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 4566 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().

4567 {
4568  MemoryContext oldcxt;
4569 
4570  Assert(relation->rd_isnailed);
4571  /* Copy the list into the cache context (could fail for lack of mem) */
4573  indexIds = list_copy(indexIds);
4574  MemoryContextSwitchTo(oldcxt);
4575  /* Okay to replace old list */
4576  list_free(relation->rd_indexlist);
4577  relation->rd_indexlist = indexIds;
4578  relation->rd_oidindex = oidIndex;
4579 
4580  /*
4581  * For the moment, assume the target rel hasn't got a pk or replica index.
4582  * We'll load them on demand in the API that wraps access to them.
4583  */
4584  relation->rd_pkindex = InvalidOid;
4585  relation->rd_replidindex = InvalidOid;
4586  relation->rd_indexvalid = 2; /* mark list as forced */
4587  /* Flag relation as needing eoxact cleanup (to reset the list) */
4588  EOXactListAdd(relation);
4589 }
#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:680
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 3385 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().

3387 {
3388  Oid newrelfilenode;
3389  RelFileNodeBackend newrnode;
3390  Relation pg_class;
3391  HeapTuple tuple;
3392  Form_pg_class classform;
3393 
3394  /* Indexes, sequences must have Invalid frozenxid; other rels must not */
3395  Assert((relation->rd_rel->relkind == RELKIND_INDEX ||
3396  relation->rd_rel->relkind == RELKIND_SEQUENCE) ?
3397  freezeXid == InvalidTransactionId :
3398  TransactionIdIsNormal(freezeXid));
3399  Assert(TransactionIdIsNormal(freezeXid) == MultiXactIdIsValid(minmulti));
3400 
3401  /* Allocate a new relfilenode */
3402  newrelfilenode = GetNewRelFileNode(relation->rd_rel->reltablespace, NULL,
3403  persistence);
3404 
3405  /*
3406  * Get a writable copy of the pg_class tuple for the given relation.
3407  */
3409 
3410  tuple = SearchSysCacheCopy1(RELOID,
3411  ObjectIdGetDatum(RelationGetRelid(relation)));
3412  if (!HeapTupleIsValid(tuple))
3413  elog(ERROR, "could not find tuple for relation %u",
3414  RelationGetRelid(relation));
3415  classform = (Form_pg_class) GETSTRUCT(tuple);
3416 
3417  /*
3418  * Create storage for the main fork of the new relfilenode.
3419  *
3420  * NOTE: any conflict in relfilenode value will be caught here, if
3421  * GetNewRelFileNode messes up for any reason.
3422  */
3423  newrnode.node = relation->rd_node;
3424  newrnode.node.relNode = newrelfilenode;
3425  newrnode.backend = relation->rd_backend;
3426  RelationCreateStorage(newrnode.node, persistence);
3427  smgrclosenode(newrnode);
3428 
3429  /*
3430  * Schedule unlinking of the old storage at transaction commit.
3431  */
3432  RelationDropStorage(relation);
3433 
3434  /*
3435  * Now update the pg_class row. However, if we're dealing with a mapped
3436  * index, pg_class.relfilenode doesn't change; instead we have to send the
3437  * update to the relation mapper.
3438  */
3439  if (RelationIsMapped(relation))
3441  newrelfilenode,
3442  relation->rd_rel->relisshared,
3443  false);
3444  else
3445  classform->relfilenode = newrelfilenode;
3446 
3447  /* These changes are safe even for a mapped relation */
3448  if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
3449  {
3450  classform->relpages = 0; /* it's empty until further notice */
3451  classform->reltuples = 0;
3452  classform->relallvisible = 0;
3453  }
3454  classform->relfrozenxid = freezeXid;
3455  classform->relminmxid = minmulti;
3456  classform->relpersistence = persistence;
3457 
3458  CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
3459 
3460  heap_freetuple(tuple);
3461 
3462  heap_close(pg_class, RowExclusiveLock);
3463 
3464  /*
3465  * Make the pg_class row change visible, as well as the relation map
3466  * change if any. This will cause the relcache entry to get updated, too.
3467  */
3469 
3470  /*
3471  * Mark the rel as having been given a new relfilenode in the current
3472  * (sub) transaction. This is a hint that can be used to optimize later
3473  * operations on the rel in the same transaction.
3474  */
3476 
3477  /* Flag relation as needing eoxact cleanup (to remove the hint) */
3478  EOXactListAdd(relation);
3479 }
#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:680
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