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 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 RelationInitIndexAccessInfo (Relation relation)
 
struct PublicationActionsGetRelationPublicationActions (Relation relation)
 
void RelationInitTableAccessMethod (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 accessmtd, Oid relfilenode, Oid reltablespace, bool shared_relation, bool mapped_relation, char relpersistence, char relkind)
 
void RelationSetNewRelfilenode (Relation relation, char persistence)
 
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 53 of file relcache.h.

Function Documentation

◆ AtEOSubXact_RelationCache()

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

Definition at line 3071 of file relcache.c.

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

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

◆ AtEOXact_RelationCache()

void AtEOXact_RelationCache ( bool  isCommit)

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

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

◆ errtable()

int errtable ( Relation  rel)

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

5190 {
5194 
5195  return 0; /* return value does not matter */
5196 }
#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:3094
#define RelationGetRelationName(relation)
Definition: rel.h:448
int err_generic_string(int field, const char *str)
Definition: elog.c:1178
#define RelationGetNamespace(relation)
Definition: rel.h:455

◆ errtablecol()

int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5206 of file relcache.c.

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

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

5207 {
5208  TupleDesc reldesc = RelationGetDescr(rel);
5209  const char *colname;
5210 
5211  /* Use reldesc if it's a user attribute, else consult the catalogs */
5212  if (attnum > 0 && attnum <= reldesc->natts)
5213  colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
5214  else
5215  colname = get_attname(RelationGetRelid(rel), attnum, false);
5216 
5217  return errtablecolname(rel, colname);
5218 }
#define RelationGetDescr(relation)
Definition: rel.h:440
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
NameData attname
Definition: pg_attribute.h:40
int16 attnum
Definition: pg_attribute.h:79
#define NameStr(name)
Definition: c.h:609
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:775
#define RelationGetRelid(relation)
Definition: rel.h:414
int errtablecolname(Relation rel, const char *colname)
Definition: relcache.c:5230

◆ errtablecolname()

int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5230 of file relcache.c.

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

Referenced by errtablecol().

5231 {
5232  errtable(rel);
5234 
5235  return 0; /* return value does not matter */
5236 }
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:67
int err_generic_string(int field, const char *str)
Definition: elog.c:1178
int errtable(Relation rel)
Definition: relcache.c:5189

◆ errtableconstraint()

int errtableconstraint ( Relation  rel,
const char *  conname 
)

Definition at line 5243 of file relcache.c.

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

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

5244 {
5245  errtable(rel);
5247 
5248  return 0; /* return value does not matter */
5249 }
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:69
int err_generic_string(int field, const char *str)
Definition: elog.c:1178
int errtable(Relation rel)
Definition: relcache.c:5189

◆ GetRelationPublicationActions()

struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

Definition at line 5110 of file relcache.c.

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

Referenced by CheckCmdReplicaIdentity().

5111 {
5112  List *puboids;
5113  ListCell *lc;
5114  MemoryContext oldcxt;
5115  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5116 
5117  /*
5118  * If not publishable, it publishes no actions. (pgoutput_change() will
5119  * ignore it.)
5120  */
5121  if (!is_publishable_relation(relation))
5122  return pubactions;
5123 
5124  if (relation->rd_pubactions)
5125  return memcpy(pubactions, relation->rd_pubactions,
5126  sizeof(PublicationActions));
5127 
5128  /* Fetch the publication membership info. */
5129  puboids = GetRelationPublications(RelationGetRelid(relation));
5130  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5131 
5132  foreach(lc, puboids)
5133  {
5134  Oid pubid = lfirst_oid(lc);
5135  HeapTuple tup;
5136  Form_pg_publication pubform;
5137 
5139 
5140  if (!HeapTupleIsValid(tup))
5141  elog(ERROR, "cache lookup failed for publication %u", pubid);
5142 
5143  pubform = (Form_pg_publication) GETSTRUCT(tup);
5144 
5145  pubactions->pubinsert |= pubform->pubinsert;
5146  pubactions->pubupdate |= pubform->pubupdate;
5147  pubactions->pubdelete |= pubform->pubdelete;
5148  pubactions->pubtruncate |= pubform->pubtruncate;
5149 
5150  ReleaseSysCache(tup);
5151 
5152  /*
5153  * If we know everything is replicated, there is no point to check for
5154  * other publications.
5155  */
5156  if (pubactions->pubinsert && pubactions->pubupdate &&
5157  pubactions->pubdelete && pubactions->pubtruncate)
5158  break;
5159  }
5160 
5161  if (relation->rd_pubactions)
5162  {
5163  pfree(relation->rd_pubactions);
5164  relation->rd_pubactions = NULL;
5165  }
5166 
5167  /* Now save copy of the actions in the relcache entry. */
5169  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5170  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5171  MemoryContextSwitchTo(oldcxt);
5172 
5173  return pubactions;
5174 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
PublicationActions * rd_pubactions
Definition: rel.h:120
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned int Oid
Definition: postgres_ext.h:31
List * GetRelationPublications(Oid relid)
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
List * list_concat_unique_oid(List *list1, const List *list2)
Definition: list.c:1283
bool is_publishable_relation(Relation rel)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
void * palloc0(Size size)
Definition: mcxt.c:955
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
List * GetAllTablesPublications(void)
void * palloc(Size size)
Definition: mcxt.c:924
#define elog(elevel,...)
Definition: elog.h:226
FormData_pg_publication * Form_pg_publication
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:414
#define lfirst_oid(lc)
Definition: pg_list.h:192
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationBuildLocalRelation()

Relation RelationBuildLocalRelation ( const char *  relname,
Oid  relnamespace,
TupleDesc  tupDesc,
Oid  relid,
Oid  accessmtd,
Oid  relfilenode,
Oid  reltablespace,
bool  shared_relation,
bool  mapped_relation,
char  relpersistence,
char  relkind 
)

Definition at line 3170 of file relcache.c.

References Assert, AssertArg, BackendIdForTempRelations, CacheMemoryContext, CLASS_TUPLE_SIZE, TupleDescData::constr, CreateCacheMemoryContext(), CreateTupleDescCopy(), elog, EOXactListAdd, ERROR, GetCurrentSubTransactionId(), TupleConstr::has_not_null, i, InvalidBackendId, InvalidOid, InvalidSubTransactionId, IsCatalogNamespace(), IsSharedRelation(), isTempOrTempToastNamespace(), MemoryContextSwitchTo(), namestrcpy(), TupleDescData::natts, palloc0(), 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(), RelationInitTableAccessMethod(), RelationMapUpdateMap(), relfilenode, relkind, relpersistence, TupleDescData::tdrefcount, and TupleDescAttr.

Referenced by heap_create().

3181 {
3182  Relation rel;
3183  MemoryContext oldcxt;
3184  int natts = tupDesc->natts;
3185  int i;
3186  bool has_not_null;
3187  bool nailit;
3188 
3189  AssertArg(natts >= 0);
3190 
3191  /*
3192  * check for creation of a rel that must be nailed in cache.
3193  *
3194  * XXX this list had better match the relations specially handled in
3195  * RelationCacheInitializePhase2/3.
3196  */
3197  switch (relid)
3198  {
3199  case DatabaseRelationId:
3200  case AuthIdRelationId:
3201  case AuthMemRelationId:
3202  case RelationRelationId:
3203  case AttributeRelationId:
3204  case ProcedureRelationId:
3205  case TypeRelationId:
3206  nailit = true;
3207  break;
3208  default:
3209  nailit = false;
3210  break;
3211  }
3212 
3213  /*
3214  * check that hardwired list of shared rels matches what's in the
3215  * bootstrap .bki file. If you get a failure here during initdb, you
3216  * probably need to fix IsSharedRelation() to match whatever you've done
3217  * to the set of shared relations.
3218  */
3219  if (shared_relation != IsSharedRelation(relid))
3220  elog(ERROR, "shared_relation flag for \"%s\" does not match IsSharedRelation(%u)",
3221  relname, relid);
3222 
3223  /* Shared relations had better be mapped, too */
3224  Assert(mapped_relation || !shared_relation);
3225 
3226  /*
3227  * switch to the cache context to create the relcache entry.
3228  */
3229  if (!CacheMemoryContext)
3231 
3233 
3234  /*
3235  * allocate a new relation descriptor and fill in basic state fields.
3236  */
3237  rel = (Relation) palloc0(sizeof(RelationData));
3238 
3239  /* make sure relation is marked as having no open file yet */
3240  rel->rd_smgr = NULL;
3241 
3242  /* mark it nailed if appropriate */
3243  rel->rd_isnailed = nailit;
3244 
3245  rel->rd_refcnt = nailit ? 1 : 0;
3246 
3247  /* it's being created in this transaction */
3250 
3251  /*
3252  * create a new tuple descriptor from the one passed in. We do this
3253  * partly to copy it into the cache context, and partly because the new
3254  * relation can't have any defaults or constraints yet; they have to be
3255  * added in later steps, because they require additions to multiple system
3256  * catalogs. We can copy attnotnull constraints here, however.
3257  */
3258  rel->rd_att = CreateTupleDescCopy(tupDesc);
3259  rel->rd_att->tdrefcount = 1; /* mark as refcounted */
3260  has_not_null = false;
3261  for (i = 0; i < natts; i++)
3262  {
3263  Form_pg_attribute satt = TupleDescAttr(tupDesc, i);
3264  Form_pg_attribute datt = TupleDescAttr(rel->rd_att, i);
3265 
3266  datt->attidentity = satt->attidentity;
3267  datt->attgenerated = satt->attgenerated;
3268  datt->attnotnull = satt->attnotnull;
3269  has_not_null |= satt->attnotnull;
3270  }
3271 
3272  if (has_not_null)
3273  {
3274  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
3275 
3276  constr->has_not_null = true;
3277  rel->rd_att->constr = constr;
3278  }
3279 
3280  /*
3281  * initialize relation tuple form (caller may add/override data later)
3282  */
3284 
3285  namestrcpy(&rel->rd_rel->relname, relname);
3286  rel->rd_rel->relnamespace = relnamespace;
3287 
3288  rel->rd_rel->relkind = relkind;
3289  rel->rd_rel->relnatts = natts;
3290  rel->rd_rel->reltype = InvalidOid;
3291  /* needed when bootstrapping: */
3292  rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;
3293 
3294  /* set up persistence and relcache fields dependent on it */
3295  rel->rd_rel->relpersistence = relpersistence;
3296  switch (relpersistence)
3297  {
3298  case RELPERSISTENCE_UNLOGGED:
3299  case RELPERSISTENCE_PERMANENT:
3301  rel->rd_islocaltemp = false;
3302  break;
3303  case RELPERSISTENCE_TEMP:
3304  Assert(isTempOrTempToastNamespace(relnamespace));
3306  rel->rd_islocaltemp = true;
3307  break;
3308  default:
3309  elog(ERROR, "invalid relpersistence: %c", relpersistence);
3310  break;
3311  }
3312 
3313  /* if it's a materialized view, it's not populated initially */
3314  if (relkind == RELKIND_MATVIEW)
3315  rel->rd_rel->relispopulated = false;
3316  else
3317  rel->rd_rel->relispopulated = true;
3318 
3319  /* set replica identity -- system catalogs and non-tables don't have one */
3320  if (!IsCatalogNamespace(relnamespace) &&
3321  (relkind == RELKIND_RELATION ||
3322  relkind == RELKIND_MATVIEW ||
3323  relkind == RELKIND_PARTITIONED_TABLE))
3324  rel->rd_rel->relreplident = REPLICA_IDENTITY_DEFAULT;
3325  else
3326  rel->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
3327 
3328  /*
3329  * Insert relation physical and logical identifiers (OIDs) into the right
3330  * places. For a mapped relation, we set relfilenode to zero and rely on
3331  * RelationInitPhysicalAddr to consult the map.
3332  */
3333  rel->rd_rel->relisshared = shared_relation;
3334 
3335  RelationGetRelid(rel) = relid;
3336 
3337  for (i = 0; i < natts; i++)
3338  TupleDescAttr(rel->rd_att, i)->attrelid = relid;
3339 
3340  rel->rd_rel->reltablespace = reltablespace;
3341 
3342  if (mapped_relation)
3343  {
3344  rel->rd_rel->relfilenode = InvalidOid;
3345  /* Add it to the active mapping information */
3346  RelationMapUpdateMap(relid, relfilenode, shared_relation, true);
3347  }
3348  else
3349  rel->rd_rel->relfilenode = relfilenode;
3350 
3351  RelationInitLockInfo(rel); /* see lmgr.c */
3352 
3354 
3355  rel->rd_rel->relam = accessmtd;
3356 
3357  if (relkind == RELKIND_RELATION ||
3358  relkind == RELKIND_SEQUENCE ||
3359  relkind == RELKIND_TOASTVALUE ||
3360  relkind == RELKIND_MATVIEW)
3362 
3363  /*
3364  * Okay to insert into the relcache hash table.
3365  *
3366  * Ordinarily, there should certainly not be an existing hash entry for
3367  * the same OID; but during bootstrap, when we create a "real" relcache
3368  * entry for one of the bootstrap relations, we'll be overwriting the
3369  * phony one created with formrdesc. So allow that to happen for nailed
3370  * rels.
3371  */
3372  RelationCacheInsert(rel, nailit);
3373 
3374  /*
3375  * Flag relation as needing eoxact cleanup (to clear rd_createSubid). We
3376  * can't do this before storing relid in it.
3377  */
3378  EOXactListAdd(rel);
3379 
3380  /*
3381  * done building relcache entry.
3382  */
3383  MemoryContextSwitchTo(oldcxt);
3384 
3385  /* It's fully valid */
3386  rel->rd_isvalid = true;
3387 
3388  /*
3389  * Caller expects us to pin the returned entry.
3390  */
3392 
3393  return rel;
3394 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
#define EOXactListAdd(rel)
Definition: relcache.c:172
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3160
void RelationInitTableAccessMethod(Relation relation)
Definition: relcache.c:1741
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
struct SMgrRelationData * rd_smgr
Definition: rel.h:57
bool rd_isnailed
Definition: rel.h:61
bool rd_islocaltemp
Definition: rel.h:60
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool rd_isvalid
Definition: rel.h:62
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:81
Form_pg_class rd_rel
Definition: rel.h:84
NameData relname
Definition: pg_class.h:35
int namestrcpy(Name name, const char *str)
Definition: name.c:250
char relkind
Definition: pg_class.h:81
struct RelationData * Relation
Definition: relcache.h:26
#define ERROR
Definition: elog.h:43
char relpersistence
Definition: pg_class.h:78
Oid relfilenode
Definition: pg_class.h:54
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1272
void RelationInitLockInfo(Relation relation)
Definition: lmgr.c:71
#define BackendIdForTempRelations()
Definition: backendid.h:34
TupleConstr * constr
Definition: tupdesc.h:85
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
#define AssertArg(condition)
Definition: c.h:734
SubTransactionId rd_createSubid
Definition: rel.h:80
#define InvalidBackendId
Definition: backendid.h:23
void * palloc0(Size size)
Definition: mcxt.c:955
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2057
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:240
TupleDesc rd_att
Definition: rel.h:85
#define InvalidOid
Definition: postgres_ext.h:36
#define RelationCacheInsert(RELATION, replace_allowed)
Definition: relcache.c:192
#define CLASS_TUPLE_SIZE
Definition: pg_class.h:142
BackendId rd_backend
Definition: rel.h:59
#define Assert(condition)
Definition: c.h:732
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:708
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
#define InvalidSubTransactionId
Definition: c.h:513
bool IsCatalogNamespace(Oid namespaceId)
Definition: catalog.c:179
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150
int rd_refcnt
Definition: rel.h:58
#define elog(elevel,...)
Definition: elog.h:226
int i
int tdrefcount
Definition: tupdesc.h:84
bool has_not_null
Definition: tupdesc.h:44
#define RelationGetRelid(relation)
Definition: rel.h:414
void RelationMapUpdateMap(Oid relationId, Oid fileNode, bool shared, bool immediate)
Definition: relmapper.c:261
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInitFilePostInvalidate()

void RelationCacheInitFilePostInvalidate ( void  )

Definition at line 6027 of file relcache.c.

References LWLockRelease().

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

6028 {
6029  LWLockRelease(RelCacheInitLock);
6030 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )

Definition at line 6002 of file relcache.c.

References DatabasePath, ERROR, LW_EXCLUSIVE, LWLockAcquire(), MAXPGPATH, RELCACHE_INIT_FILENAME, snprintf, and unlink_initfile().

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

6003 {
6004  char localinitfname[MAXPGPATH];
6005  char sharedinitfname[MAXPGPATH];
6006 
6007  if (DatabasePath)
6008  snprintf(localinitfname, sizeof(localinitfname), "%s/%s",
6010  snprintf(sharedinitfname, sizeof(sharedinitfname), "global/%s",
6012 
6013  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6014 
6015  /*
6016  * The files might not be there if no backend has been started since the
6017  * last removal. But complain about failures other than ENOENT with
6018  * ERROR. Fortunately, it's not too late to abort the transaction if we
6019  * can't get rid of the would-be-obsolete init file.
6020  */
6021  if (DatabasePath)
6022  unlink_initfile(localinitfname, ERROR);
6023  unlink_initfile(sharedinitfname, ERROR);
6024 }
#define ERROR
Definition: elog.h:43
#define MAXPGPATH
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:24
char * DatabasePath
Definition: globals.c:93
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6099
#define snprintf
Definition: port.h:192

◆ RelationCacheInitFileRemove()

void RelationCacheInitFileRemove ( void  )

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

6043 {
6044  const char *tblspcdir = "pg_tblspc";
6045  DIR *dir;
6046  struct dirent *de;
6047  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6048 
6049  snprintf(path, sizeof(path), "global/%s",
6051  unlink_initfile(path, LOG);
6052 
6053  /* Scan everything in the default tablespace */
6055 
6056  /* Scan the tablespace link directory to find non-default tablespaces */
6057  dir = AllocateDir(tblspcdir);
6058 
6059  while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6060  {
6061  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6062  {
6063  /* Scan the tablespace dir for per-database dirs */
6064  snprintf(path, sizeof(path), "%s/%s/%s",
6065  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6067  }
6068  }
6069 
6070  FreeDir(dir);
6071 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6075
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2553
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:26
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2472
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:24
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6099
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:192
int FreeDir(DIR *dir)
Definition: fd.c:2590

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 3574 of file relcache.c.

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

Referenced by InitPostgres().

3575 {
3576  HASHCTL ctl;
3577 
3578  /*
3579  * make sure cache memory context exists
3580  */
3581  if (!CacheMemoryContext)
3583 
3584  /*
3585  * create hashtable that indexes the relcache
3586  */
3587  MemSet(&ctl, 0, sizeof(ctl));
3588  ctl.keysize = sizeof(Oid);
3589  ctl.entrysize = sizeof(RelIdCacheEnt);
3590  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3591  &ctl, HASH_ELEM | HASH_BLOBS);
3592 
3593  /*
3594  * relation mapper needs to be initialized too
3595  */
3597 }
void RelationMapInitialize(void)
Definition: relmapper.c:584
#define HASH_ELEM
Definition: hsearch.h:87
struct relidcacheent RelIdCacheEnt
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:941
static HTAB * RelationIdCache
Definition: relcache.c:135
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:620
#define INITRELCACHESIZE
Definition: relcache.c:3571
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInitializePhase2()

void RelationCacheInitializePhase2 ( void  )

Definition at line 3611 of file relcache.c.

References CacheMemoryContext, Desc_pg_auth_members, Desc_pg_authid, Desc_pg_database, Desc_pg_shseclabel, Desc_pg_subscription, formrdesc(), IsBootstrapProcessingMode, load_relcache_init_file(), MemoryContextSwitchTo(), and RelationMapInitializePhase2().

Referenced by InitPostgres().

3612 {
3613  MemoryContext oldcxt;
3614 
3615  /*
3616  * relation mapper needs initialized too
3617  */
3619 
3620  /*
3621  * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3622  * nothing.
3623  */
3625  return;
3626 
3627  /*
3628  * switch to cache memory context
3629  */
3631 
3632  /*
3633  * Try to load the shared relcache cache file. If unsuccessful, bootstrap
3634  * the cache with pre-made descriptors for the critical shared catalogs.
3635  */
3636  if (!load_relcache_init_file(true))
3637  {
3638  formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
3639  Natts_pg_database, Desc_pg_database);
3640  formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
3641  Natts_pg_authid, Desc_pg_authid);
3642  formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
3643  Natts_pg_auth_members, Desc_pg_auth_members);
3644  formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
3645  Natts_pg_shseclabel, Desc_pg_shseclabel);
3646  formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
3647  Natts_pg_subscription, Desc_pg_subscription);
3648 
3649 #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
3650  }
3651 
3652  MemoryContextSwitchTo(oldcxt);
3653 }
static const FormData_pg_attribute Desc_pg_auth_members[Natts_pg_auth_members]
Definition: relcache.c:118
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5307
void RelationMapInitializePhase2(void)
Definition: relmapper.c:604
static const FormData_pg_attribute Desc_pg_authid[Natts_pg_authid]
Definition: relcache.c:117
static const FormData_pg_attribute Desc_pg_subscription[Natts_pg_subscription]
Definition: relcache.c:121
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static const FormData_pg_attribute Desc_pg_database[Natts_pg_database]
Definition: relcache.c:116
static const FormData_pg_attribute Desc_pg_shseclabel[Natts_pg_shseclabel]
Definition: relcache.c:120
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:374
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1805
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInitializePhase3()

void RelationCacheInitializePhase3 ( void  )

Definition at line 3670 of file relcache.c.

References AccessMethodProcedureIndexId, Assert, AttributeRelidNumIndexId, AuthIdOidIndexId, AuthIdRolnameIndexId, AuthMemMemRoleIndexId, CacheMemoryContext, CLASS_TUPLE_SIZE, ClassOidIndexId, criticalRelcachesBuilt, criticalSharedRelcachesBuilt, DatabaseNameIndexId, DatabaseOidIndexId, 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, IndexRelidIndexId, InitCatalogCachePhase2(), InvalidOid, IsBootstrapProcessingMode, load_critical_index(), load_relcache_init_file(), MemoryContextSwitchTo(), ObjectIdGetDatum, OpclassOidIndexId, pfree(), RelationData::rd_att, RelationData::rd_options, RelationData::rd_partdesc, RelationData::rd_partkey, RelationData::rd_rel, RelationData::rd_rsdesc, RelationData::rd_rules, RelationData::rd_tableam, RelationBuildPartitionDesc(), RelationBuildPartitionKey(), RelationBuildRowSecurity(), RelationBuildRuleLock(), RelationBuildTriggers(), RelationDecrementReferenceCount(), RelationGetRelationName, RelationGetRelid, RelationIncrementReferenceCount(), RelationInitTableAccessMethod(), RelationMapInitializePhase3(), RelationParseRelOptions(), relidcacheent::reldesc, ReleaseSysCache(), RELOID, RewriteRelRulenameIndexId, SearchSysCache1(), SharedSecLabelObjectIndexId, status(), TupleDescData::tdtypeid, TupleDescData::tdtypmod, RelationData::trigdesc, TriggerRelidNameIndexId, and write_relcache_init_file().

Referenced by InitPostgres().

3671 {
3673  RelIdCacheEnt *idhentry;
3674  MemoryContext oldcxt;
3675  bool needNewCacheFile = !criticalSharedRelcachesBuilt;
3676 
3677  /*
3678  * relation mapper needs initialized too
3679  */
3681 
3682  /*
3683  * switch to cache memory context
3684  */
3686 
3687  /*
3688  * Try to load the local relcache cache file. If unsuccessful, bootstrap
3689  * the cache with pre-made descriptors for the critical "nailed-in" system
3690  * catalogs.
3691  */
3692  if (IsBootstrapProcessingMode() ||
3693  !load_relcache_init_file(false))
3694  {
3695  needNewCacheFile = true;
3696 
3697  formrdesc("pg_class", RelationRelation_Rowtype_Id, false,
3698  Natts_pg_class, Desc_pg_class);
3699  formrdesc("pg_attribute", AttributeRelation_Rowtype_Id, false,
3700  Natts_pg_attribute, Desc_pg_attribute);
3701  formrdesc("pg_proc", ProcedureRelation_Rowtype_Id, false,
3702  Natts_pg_proc, Desc_pg_proc);
3703  formrdesc("pg_type", TypeRelation_Rowtype_Id, false,
3704  Natts_pg_type, Desc_pg_type);
3705 
3706 #define NUM_CRITICAL_LOCAL_RELS 4 /* fix if you change list above */
3707  }
3708 
3709  MemoryContextSwitchTo(oldcxt);
3710 
3711  /* In bootstrap mode, the faked-up formrdesc info is all we'll have */
3713  return;
3714 
3715  /*
3716  * If we didn't get the critical system indexes loaded into relcache, do
3717  * so now. These are critical because the catcache and/or opclass cache
3718  * depend on them for fetches done during relcache load. Thus, we have an
3719  * infinite-recursion problem. We can break the recursion by doing
3720  * heapscans instead of indexscans at certain key spots. To avoid hobbling
3721  * performance, we only want to do that until we have the critical indexes
3722  * loaded into relcache. Thus, the flag criticalRelcachesBuilt is used to
3723  * decide whether to do heapscan or indexscan at the key spots, and we set
3724  * it true after we've loaded the critical indexes.
3725  *
3726  * The critical indexes are marked as "nailed in cache", partly to make it
3727  * easy for load_relcache_init_file to count them, but mainly because we
3728  * cannot flush and rebuild them once we've set criticalRelcachesBuilt to
3729  * true. (NOTE: perhaps it would be possible to reload them by
3730  * temporarily setting criticalRelcachesBuilt to false again. For now,
3731  * though, we just nail 'em in.)
3732  *
3733  * RewriteRelRulenameIndexId and TriggerRelidNameIndexId are not critical
3734  * in the same way as the others, because the critical catalogs don't
3735  * (currently) have any rules or triggers, and so these indexes can be
3736  * rebuilt without inducing recursion. However they are used during
3737  * relcache load when a rel does have rules or triggers, so we choose to
3738  * nail them for performance reasons.
3739  */
3741  {
3743  RelationRelationId);
3745  AttributeRelationId);
3747  IndexRelationId);
3749  OperatorClassRelationId);
3751  AccessMethodProcedureRelationId);
3753  RewriteRelationId);
3755  TriggerRelationId);
3756 
3757 #define NUM_CRITICAL_LOCAL_INDEXES 7 /* fix if you change list above */
3758 
3759  criticalRelcachesBuilt = true;
3760  }
3761 
3762  /*
3763  * Process critical shared indexes too.
3764  *
3765  * DatabaseNameIndexId isn't critical for relcache loading, but rather for
3766  * initial lookup of MyDatabaseId, without which we'll never find any
3767  * non-shared catalogs at all. Autovacuum calls InitPostgres with a
3768  * database OID, so it instead depends on DatabaseOidIndexId. We also
3769  * need to nail up some indexes on pg_authid and pg_auth_members for use
3770  * during client authentication. SharedSecLabelObjectIndexId isn't
3771  * critical for the core system, but authentication hooks might be
3772  * interested in it.
3773  */
3775  {
3777  DatabaseRelationId);
3779  DatabaseRelationId);
3781  AuthIdRelationId);
3783  AuthIdRelationId);
3785  AuthMemRelationId);
3787  SharedSecLabelRelationId);
3788 
3789 #define NUM_CRITICAL_SHARED_INDEXES 6 /* fix if you change list above */
3790 
3792  }
3793 
3794  /*
3795  * Now, scan all the relcache entries and update anything that might be
3796  * wrong in the results from formrdesc or the relcache cache file. If we
3797  * faked up relcache entries using formrdesc, then read the real pg_class
3798  * rows and replace the fake entries with them. Also, if any of the
3799  * relcache entries have rules, triggers, or security policies, load that
3800  * info the hard way since it isn't recorded in the cache file.
3801  *
3802  * Whenever we access the catalogs to read data, there is a possibility of
3803  * a shared-inval cache flush causing relcache entries to be removed.
3804  * Since hash_seq_search only guarantees to still work after the *current*
3805  * entry is removed, it's unsafe to continue the hashtable scan afterward.
3806  * We handle this by restarting the scan from scratch after each access.
3807  * This is theoretically O(N^2), but the number of entries that actually
3808  * need to be fixed is small enough that it doesn't matter.
3809  */
3810  hash_seq_init(&status, RelationIdCache);
3811 
3812  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3813  {
3814  Relation relation = idhentry->reldesc;
3815  bool restart = false;
3816 
3817  /*
3818  * Make sure *this* entry doesn't get flushed while we work with it.
3819  */
3821 
3822  /*
3823  * If it's a faked-up entry, read the real pg_class tuple.
3824  */
3825  if (relation->rd_rel->relowner == InvalidOid)
3826  {
3827  HeapTuple htup;
3828  Form_pg_class relp;
3829 
3830  htup = SearchSysCache1(RELOID,
3831  ObjectIdGetDatum(RelationGetRelid(relation)));
3832  if (!HeapTupleIsValid(htup))
3833  elog(FATAL, "cache lookup failed for relation %u",
3834  RelationGetRelid(relation));
3835  relp = (Form_pg_class) GETSTRUCT(htup);
3836 
3837  /*
3838  * Copy tuple to relation->rd_rel. (See notes in
3839  * AllocateRelationDesc())
3840  */
3841  memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
3842 
3843  /* Update rd_options while we have the tuple */
3844  if (relation->rd_options)
3845  pfree(relation->rd_options);
3846  RelationParseRelOptions(relation, htup);
3847 
3848  /*
3849  * Check the values in rd_att were set up correctly. (We cannot
3850  * just copy them over now: formrdesc must have set up the rd_att
3851  * data correctly to start with, because it may already have been
3852  * copied into one or more catcache entries.)
3853  */
3854  Assert(relation->rd_att->tdtypeid == relp->reltype);
3855  Assert(relation->rd_att->tdtypmod == -1);
3856 
3857  ReleaseSysCache(htup);
3858 
3859  /* relowner had better be OK now, else we'll loop forever */
3860  if (relation->rd_rel->relowner == InvalidOid)
3861  elog(ERROR, "invalid relowner in pg_class entry for \"%s\"",
3862  RelationGetRelationName(relation));
3863 
3864  restart = true;
3865  }
3866 
3867  /*
3868  * Fix data that isn't saved in relcache cache file.
3869  *
3870  * relhasrules or relhastriggers could possibly be wrong or out of
3871  * date. If we don't actually find any rules or triggers, clear the
3872  * local copy of the flag so that we don't get into an infinite loop
3873  * here. We don't make any attempt to fix the pg_class entry, though.
3874  */
3875  if (relation->rd_rel->relhasrules && relation->rd_rules == NULL)
3876  {
3877  RelationBuildRuleLock(relation);
3878  if (relation->rd_rules == NULL)
3879  relation->rd_rel->relhasrules = false;
3880  restart = true;
3881  }
3882  if (relation->rd_rel->relhastriggers && relation->trigdesc == NULL)
3883  {
3884  RelationBuildTriggers(relation);
3885  if (relation->trigdesc == NULL)
3886  relation->rd_rel->relhastriggers = false;
3887  restart = true;
3888  }
3889 
3890  /*
3891  * Re-load the row security policies if the relation has them, since
3892  * they are not preserved in the cache. Note that we can never NOT
3893  * have a policy while relrowsecurity is true,
3894  * RelationBuildRowSecurity will create a single default-deny policy
3895  * if there is no policy defined in pg_policy.
3896  */
3897  if (relation->rd_rel->relrowsecurity && relation->rd_rsdesc == NULL)
3898  {
3899  RelationBuildRowSecurity(relation);
3900 
3901  Assert(relation->rd_rsdesc != NULL);
3902  restart = true;
3903  }
3904 
3905  /*
3906  * Reload the partition key and descriptor for a partitioned table.
3907  */
3908  if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
3909  relation->rd_partkey == NULL)
3910  {
3911  RelationBuildPartitionKey(relation);
3912  Assert(relation->rd_partkey != NULL);
3913 
3914  restart = true;
3915  }
3916 
3917  if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
3918  relation->rd_partdesc == NULL)
3919  {
3920  RelationBuildPartitionDesc(relation);
3921  Assert(relation->rd_partdesc != NULL);
3922 
3923  restart = true;
3924  }
3925 
3926  if (relation->rd_tableam == NULL &&
3927  (relation->rd_rel->relkind == RELKIND_RELATION ||
3928  relation->rd_rel->relkind == RELKIND_SEQUENCE ||
3929  relation->rd_rel->relkind == RELKIND_TOASTVALUE ||
3930  relation->rd_rel->relkind == RELKIND_MATVIEW))
3931  {
3933  Assert(relation->rd_tableam != NULL);
3934 
3935  restart = true;
3936  }
3937 
3938  /* Release hold on the relation */
3940 
3941  /* Now, restart the hashtable scan if needed */
3942  if (restart)
3943  {
3944  hash_seq_term(&status);
3945  hash_seq_init(&status, RelationIdCache);
3946  }
3947  }
3948 
3949  /*
3950  * Lastly, write out new relcache cache files if needed. We don't bother
3951  * to distinguish cases where only one of the two needs an update.
3952  */
3953  if (needNewCacheFile)
3954  {
3955  /*
3956  * Force all the catcaches to finish initializing and thereby open the
3957  * catalogs and indexes they use. This will preload the relcache with
3958  * entries for all the most important system catalogs and indexes, so
3959  * that the init files will be most useful for future backends.
3960  */
3962 
3963  /* now write the files */
3965  write_relcache_init_file(false);
3966  }
3967 }
#define AttributeRelidNumIndexId
Definition: indexing.h:96
struct PartitionDescData * rd_partdesc
Definition: rel.h:100
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5307
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define IndexRelidIndexId
Definition: indexing.h:168
#define RewriteRelRulenameIndexId
Definition: indexing.h:220
void RelationBuildRowSecurity(Relation relation)
Definition: policy.c:192
void RelationInitTableAccessMethod(Relation relation)
Definition: relcache.c:1741
Relation reldesc
Definition: relcache.c:132
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool criticalSharedRelcachesBuilt
Definition: relcache.c:147
#define AuthIdOidIndexId
Definition: indexing.h:101
static HTAB * RelationIdCache
Definition: relcache.c:135
Form_pg_class rd_rel
Definition: rel.h:84
#define TriggerRelidNameIndexId
Definition: indexing.h:256
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2070
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
int32 tdtypmod
Definition: tupdesc.h:83
#define FATAL
Definition: elog.h:52
static void write_relcache_init_file(bool shared)
Definition: relcache.c:5703
struct PartitionKeyData * rd_partkey
Definition: rel.h:98
TriggerDesc * trigdesc
Definition: rel.h:90
void RelationBuildPartitionDesc(Relation rel)
Definition: partdesc.c:61
static void RelationParseRelOptions(Relation relation, HeapTuple tuple)
Definition: relcache.c:442
static void load_critical_index(Oid indexoid, Oid heapoid)
Definition: relcache.c:3976
static const FormData_pg_attribute Desc_pg_proc[Natts_pg_proc]
Definition: relcache.c:114
#define RelationGetRelationName(relation)
Definition: rel.h:448
#define DatabaseOidIndexId
Definition: indexing.h:146
#define ClassOidIndexId
Definition: indexing.h:114
struct RowSecurityDesc * rd_rsdesc
Definition: rel.h:92
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
#define AccessMethodProcedureIndexId
Definition: indexing.h:84
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2057
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
const struct TableAmRoutine * rd_tableam
Definition: rel.h:141
TupleDesc rd_att
Definition: rel.h:85
#define OpclassOidIndexId
Definition: indexing.h:197
#define InvalidOid
Definition: postgres_ext.h:36
#define CLASS_TUPLE_SIZE
Definition: pg_class.h:142
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:732
#define AuthMemMemRoleIndexId
Definition: indexing.h:106
RuleLock * rd_rules
Definition: rel.h:88
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
#define DatabaseNameIndexId
Definition: indexing.h:144
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
#define SharedSecLabelObjectIndexId
Definition: indexing.h:323
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:374
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150
void RelationBuildPartitionKey(Relation relation)
Definition: partcache.c:58
Oid tdtypeid
Definition: tupdesc.h:82
void RelationBuildTriggers(Relation relation)
Definition: trigger.c:1930
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1805
static const FormData_pg_attribute Desc_pg_class[Natts_pg_class]
Definition: relcache.c:112
#define elog(elevel,...)
Definition: elog.h:226
void RelationMapInitializePhase3(void)
Definition: relmapper.c:625
static void RelationBuildRuleLock(Relation relation)
Definition: relcache.c:733
bool criticalRelcachesBuilt
Definition: relcache.c:141
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
#define AuthIdRolnameIndexId
Definition: indexing.h:99
void InitCatalogCachePhase2(void)
Definition: syscache.c:1083
#define RelationGetRelid(relation)
Definition: rel.h:414
static const FormData_pg_attribute Desc_pg_type[Natts_pg_type]
Definition: relcache.c:115
bytea * rd_options
Definition: rel.h:127
void hash_seq_term(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1465
static const FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute]
Definition: relcache.c:113
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInvalidate()

void RelationCacheInvalidate ( void  )

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

Referenced by InvalidateSystemCaches(), and LocalExecuteInvalidationMessage().

2774 {
2776  RelIdCacheEnt *idhentry;
2777  Relation relation;
2778  List *rebuildFirstList = NIL;
2779  List *rebuildList = NIL;
2780  ListCell *l;
2781 
2782  /*
2783  * Reload relation mapping data before starting to reconstruct cache.
2784  */
2786 
2787  /* Phase 1 */
2788  hash_seq_init(&status, RelationIdCache);
2789 
2790  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2791  {
2792  relation = idhentry->reldesc;
2793 
2794  /* Must close all smgr references to avoid leaving dangling ptrs */
2795  RelationCloseSmgr(relation);
2796 
2797  /*
2798  * Ignore new relations; no other backend will manipulate them before
2799  * we commit. Likewise, before replacing a relation's relfilenode, we
2800  * shall have acquired AccessExclusiveLock and drained any applicable
2801  * pending invalidations.
2802  */
2803  if (relation->rd_createSubid != InvalidSubTransactionId ||
2805  continue;
2806 
2808 
2809  if (RelationHasReferenceCountZero(relation))
2810  {
2811  /* Delete this entry immediately */
2812  Assert(!relation->rd_isnailed);
2813  RelationClearRelation(relation, false);
2814  }
2815  else
2816  {
2817  /*
2818  * If it's a mapped relation, immediately update its rd_node in
2819  * case its relfilenode changed. We must do this during phase 1
2820  * in case the relation is consulted during rebuild of other
2821  * relcache entries in phase 2. It's safe since consulting the
2822  * map doesn't involve any access to relcache entries.
2823  */
2824  if (RelationIsMapped(relation))
2825  RelationInitPhysicalAddr(relation);
2826 
2827  /*
2828  * Add this entry to list of stuff to rebuild in second pass.
2829  * pg_class goes to the front of rebuildFirstList while
2830  * pg_class_oid_index goes to the back of rebuildFirstList, so
2831  * they are done first and second respectively. Other nailed
2832  * relations go to the front of rebuildList, so they'll be done
2833  * next in no particular order; and everything else goes to the
2834  * back of rebuildList.
2835  */
2836  if (RelationGetRelid(relation) == RelationRelationId)
2837  rebuildFirstList = lcons(relation, rebuildFirstList);
2838  else if (RelationGetRelid(relation) == ClassOidIndexId)
2839  rebuildFirstList = lappend(rebuildFirstList, relation);
2840  else if (relation->rd_isnailed)
2841  rebuildList = lcons(relation, rebuildList);
2842  else
2843  rebuildList = lappend(rebuildList, relation);
2844  }
2845  }
2846 
2847  /*
2848  * Now zap any remaining smgr cache entries. This must happen before we
2849  * start to rebuild entries, since that may involve catalog fetches which
2850  * will re-open catalog files.
2851  */
2852  smgrcloseall();
2853 
2854  /* Phase 2: rebuild the items found to need rebuild in phase 1 */
2855  foreach(l, rebuildFirstList)
2856  {
2857  relation = (Relation) lfirst(l);
2858  RelationClearRelation(relation, true);
2859  }
2860  list_free(rebuildFirstList);
2861  foreach(l, rebuildList)
2862  {
2863  relation = (Relation) lfirst(l);
2864  RelationClearRelation(relation, true);
2865  }
2866  list_free(rebuildList);
2867 }
#define NIL
Definition: pg_list.h:65
static long relcacheInvalsReceived
Definition: relcache.c:155
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2398
bool rd_isnailed
Definition: rel.h:61
Relation reldesc
Definition: relcache.c:132
#define RelationCloseSmgr(relation)
Definition: rel.h:483
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:81
static HTAB * RelationIdCache
Definition: relcache.c:135
void smgrcloseall(void)
Definition: smgr.c:288
struct RelationData * Relation
Definition: relcache.h:26
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1272
#define ClassOidIndexId
Definition: indexing.h:114
List * lappend(List *list, void *datum)
Definition: list.c:321
#define RelationIsMapped(relation)
Definition: rel.h:463
SubTransactionId rd_createSubid
Definition: rel.h:80
List * lcons(void *datum, List *list)
Definition: list.c:500
#define Assert(condition)
Definition: c.h:732
#define lfirst(lc)
Definition: pg_list.h:190
#define InvalidSubTransactionId
Definition: c.h:513
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:398
void list_free(List *list)
Definition: list.c:1330
void RelationMapInvalidateAll(void)
Definition: relmapper.c:425
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:414

◆ RelationCacheInvalidateEntry()

void RelationCacheInvalidateEntry ( Oid  relationId)

Definition at line 2729 of file relcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

2730 {
2731  Relation relation;
2732 
2733  RelationIdCacheLookup(relationId, relation);
2734 
2735  if (PointerIsValid(relation))
2736  {
2738  RelationFlushRelation(relation);
2739  }
2740 }
static long relcacheInvalsReceived
Definition: relcache.c:155
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:214
static void RelationFlushRelation(Relation relation)
Definition: relcache.c:2661
#define PointerIsValid(pointer)
Definition: c.h:626

◆ RelationClose()

void RelationClose ( Relation  relation)

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

2091 {
2092  /* Note: no locking manipulations needed */
2094 
2095 #ifdef RELCACHE_FORCE_RELEASE
2096  if (RelationHasReferenceCountZero(relation) &&
2097  relation->rd_createSubid == InvalidSubTransactionId &&
2099  RelationClearRelation(relation, false);
2100 #endif
2101 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2398
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:81
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2070
SubTransactionId rd_createSubid
Definition: rel.h:80
#define InvalidSubTransactionId
Definition: c.h:513
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:398

◆ RelationCloseSmgrByOid()

void RelationCloseSmgrByOid ( Oid  relationId)

Definition at line 2876 of file relcache.c.

References PointerIsValid, RelationCloseSmgr, and RelationIdCacheLookup.

Referenced by swap_relation_files().

2877 {
2878  Relation relation;
2879 
2880  RelationIdCacheLookup(relationId, relation);
2881 
2882  if (!PointerIsValid(relation))
2883  return; /* not in cache, nothing to do */
2884 
2885  RelationCloseSmgr(relation);
2886 }
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:214
#define RelationCloseSmgr(relation)
Definition: rel.h:483
#define PointerIsValid(pointer)
Definition: c.h:626

◆ RelationForgetRelation()

void RelationForgetRelation ( Oid  rid)

Definition at line 2697 of file relcache.c.

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

Referenced by heap_drop_with_catalog(), and index_drop().

2698 {
2699  Relation relation;
2700 
2701  RelationIdCacheLookup(rid, relation);
2702 
2703  if (!PointerIsValid(relation))
2704  return; /* not in cache, nothing to do */
2705 
2706  if (!RelationHasReferenceCountZero(relation))
2707  elog(ERROR, "relation %u is still open", rid);
2708 
2709  /* Unconditionally destroy the relcache entry */
2710  RelationClearRelation(relation, false);
2711 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2398
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:214
#define ERROR
Definition: elog.h:43
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:398
#define elog(elevel,...)
Definition: elog.h:226
#define PointerIsValid(pointer)
Definition: c.h:626

◆ RelationGetExclusionInfo()

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

Definition at line 4986 of file relcache.c.

References AccessShareLock, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, BTEqualStrategyNumber, ConstraintRelidTypidNameIndexId, DatumGetArrayTypeP, elog, ERROR, fastgetattr, get_op_opfamily_strategy(), get_opcode(), GETSTRUCT, HeapTupleIsValid, i, IndexRelationGetNumberOfKeyAttributes, InvalidStrategy, MemoryContextSwitchTo(), ObjectIdGetDatum, palloc(), RelationData::rd_att, RelationData::rd_exclops, RelationData::rd_exclprocs, RelationData::rd_exclstrats, RelationData::rd_index, RelationData::rd_indexcxt, RelationData::rd_opfamily, RelationGetRelationName, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), and val.

Referenced by BuildIndexInfo(), and CheckIndexCompatible().

4990 {
4991  int indnkeyatts;
4992  Oid *ops;
4993  Oid *funcs;
4994  uint16 *strats;
4995  Relation conrel;
4996  SysScanDesc conscan;
4997  ScanKeyData skey[1];
4998  HeapTuple htup;
4999  bool found;
5000  MemoryContext oldcxt;
5001  int i;
5002 
5003  indnkeyatts = IndexRelationGetNumberOfKeyAttributes(indexRelation);
5004 
5005  /* Allocate result space in caller context */
5006  *operators = ops = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5007  *procs = funcs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5008  *strategies = strats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
5009 
5010  /* Quick exit if we have the data cached already */
5011  if (indexRelation->rd_exclstrats != NULL)
5012  {
5013  memcpy(ops, indexRelation->rd_exclops, sizeof(Oid) * indnkeyatts);
5014  memcpy(funcs, indexRelation->rd_exclprocs, sizeof(Oid) * indnkeyatts);
5015  memcpy(strats, indexRelation->rd_exclstrats, sizeof(uint16) * indnkeyatts);
5016  return;
5017  }
5018 
5019  /*
5020  * Search pg_constraint for the constraint associated with the index. To
5021  * make this not too painfully slow, we use the index on conrelid; that
5022  * will hold the parent relation's OID not the index's own OID.
5023  *
5024  * Note: if we wanted to rely on the constraint name matching the index's
5025  * name, we could just do a direct lookup using pg_constraint's unique
5026  * index. For the moment it doesn't seem worth requiring that.
5027  */
5028  ScanKeyInit(&skey[0],
5029  Anum_pg_constraint_conrelid,
5030  BTEqualStrategyNumber, F_OIDEQ,
5031  ObjectIdGetDatum(indexRelation->rd_index->indrelid));
5032 
5033  conrel = table_open(ConstraintRelationId, AccessShareLock);
5034  conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
5035  NULL, 1, skey);
5036  found = false;
5037 
5038  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
5039  {
5041  Datum val;
5042  bool isnull;
5043  ArrayType *arr;
5044  int nelem;
5045 
5046  /* We want the exclusion constraint owning the index */
5047  if (conform->contype != CONSTRAINT_EXCLUSION ||
5048  conform->conindid != RelationGetRelid(indexRelation))
5049  continue;
5050 
5051  /* There should be only one */
5052  if (found)
5053  elog(ERROR, "unexpected exclusion constraint record found for rel %s",
5054  RelationGetRelationName(indexRelation));
5055  found = true;
5056 
5057  /* Extract the operator OIDS from conexclop */
5058  val = fastgetattr(htup,
5059  Anum_pg_constraint_conexclop,
5060  conrel->rd_att, &isnull);
5061  if (isnull)
5062  elog(ERROR, "null conexclop for rel %s",
5063  RelationGetRelationName(indexRelation));
5064 
5065  arr = DatumGetArrayTypeP(val); /* ensure not toasted */
5066  nelem = ARR_DIMS(arr)[0];
5067  if (ARR_NDIM(arr) != 1 ||
5068  nelem != indnkeyatts ||
5069  ARR_HASNULL(arr) ||
5070  ARR_ELEMTYPE(arr) != OIDOID)
5071  elog(ERROR, "conexclop is not a 1-D Oid array");
5072 
5073  memcpy(ops, ARR_DATA_PTR(arr), sizeof(Oid) * indnkeyatts);
5074  }
5075 
5076  systable_endscan(conscan);
5077  table_close(conrel, AccessShareLock);
5078 
5079  if (!found)
5080  elog(ERROR, "exclusion constraint record missing for rel %s",
5081  RelationGetRelationName(indexRelation));
5082 
5083  /* We need the func OIDs and strategy numbers too */
5084  for (i = 0; i < indnkeyatts; i++)
5085  {
5086  funcs[i] = get_opcode(ops[i]);
5087  strats[i] = get_op_opfamily_strategy(ops[i],
5088  indexRelation->rd_opfamily[i]);
5089  /* shouldn't fail, since it was checked at index creation */
5090  if (strats[i] == InvalidStrategy)
5091  elog(ERROR, "could not find strategy for operator %u in family %u",
5092  ops[i], indexRelation->rd_opfamily[i]);
5093  }
5094 
5095  /* Save a copy of the results in the relcache entry. */
5096  oldcxt = MemoryContextSwitchTo(indexRelation->rd_indexcxt);
5097  indexRelation->rd_exclops = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5098  indexRelation->rd_exclprocs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5099  indexRelation->rd_exclstrats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
5100  memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * indnkeyatts);
5101  memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * indnkeyatts);
5102  memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * indnkeyatts);
5103  MemoryContextSwitchTo(oldcxt);
5104 }
#define InvalidStrategy
Definition: stratnum.h:24
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:712
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
uint16 * rd_exclstrats
Definition: rel.h:175
#define AccessShareLock
Definition: lockdefs.h:36
Oid * rd_exclprocs
Definition: rel.h:174
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:352
Form_pg_index rd_index
Definition: rel.h:144
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
unsigned short uint16
Definition: c.h:357
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:282
#define ARR_DATA_PTR(a)
Definition: array.h:310
#define RelationGetRelationName(relation)
Definition: rel.h:448
#define ARR_HASNULL(a)
Definition: array.h:279
Oid * rd_opfamily
Definition: rel.h:166
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition: rel.h:433
Oid * rd_exclops
Definition: rel.h:173
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:85
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1092
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define ARR_NDIM(a)
Definition: array.h:278
#define ConstraintRelidTypidNameIndexId
Definition: indexing.h:128
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition: lsyscache.c:80
void * palloc(Size size)
Definition: mcxt.c:924
#define elog(elevel,...)
Definition: elog.h:226
MemoryContext rd_indexcxt
Definition: rel.h:163
int i
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ARR_ELEMTYPE(a)
Definition: array.h:280
#define RelationGetRelid(relation)
Definition: rel.h:414
long val
Definition: informix.c:689
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ RelationGetFKeyList()

List* RelationGetFKeyList ( Relation  relation)

Definition at line 4233 of file relcache.c.

References AccessShareLock, BTEqualStrategyNumber, CacheMemoryContext, ForeignKeyCacheInfo::confkey, ForeignKeyCacheInfo::confrelid, ForeignKeyCacheInfo::conkey, ForeignKeyCacheInfo::conoid, ForeignKeyCacheInfo::conpfeqop, ForeignKeyCacheInfo::conrelid, ConstraintRelidTypidNameIndexId, copyObject, DeconstructFkConstraintRow(), GETSTRUCT, HeapTupleIsValid, lappend(), list_free_deep(), makeNode, MemoryContextSwitchTo(), NIL, ForeignKeyCacheInfo::nkeys, ObjectIdGetDatum, RelationData::rd_fkeylist, RelationData::rd_fkeyvalid, RelationData::rd_rel, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by addFkRecurseReferencing(), ATExecDetachPartition(), CloneFkReferencing(), and get_relation_foreign_keys().

4234 {
4235  List *result;
4236  Relation conrel;
4237  SysScanDesc conscan;
4238  ScanKeyData skey;
4239  HeapTuple htup;
4240  List *oldlist;
4241  MemoryContext oldcxt;
4242 
4243  /* Quick exit if we already computed the list. */
4244  if (relation->rd_fkeyvalid)
4245  return relation->rd_fkeylist;
4246 
4247  /* Fast path: non-partitioned tables without triggers can't have FKs */
4248  if (!relation->rd_rel->relhastriggers &&
4249  relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
4250  return NIL;
4251 
4252  /*
4253  * We build the list we intend to return (in the caller's context) while
4254  * doing the scan. After successfully completing the scan, we copy that
4255  * list into the relcache entry. This avoids cache-context memory leakage
4256  * if we get some sort of error partway through.
4257  */
4258  result = NIL;
4259 
4260  /* Prepare to scan pg_constraint for entries having conrelid = this rel. */
4261  ScanKeyInit(&skey,
4262  Anum_pg_constraint_conrelid,
4263  BTEqualStrategyNumber, F_OIDEQ,
4264  ObjectIdGetDatum(RelationGetRelid(relation)));
4265 
4266  conrel = table_open(ConstraintRelationId, AccessShareLock);
4267  conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
4268  NULL, 1, &skey);
4269 
4270  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4271  {
4272  Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(htup);
4273  ForeignKeyCacheInfo *info;
4274 
4275  /* consider only foreign keys */
4276  if (constraint->contype != CONSTRAINT_FOREIGN)
4277  continue;
4278 
4279  info = makeNode(ForeignKeyCacheInfo);
4280  info->conoid = constraint->oid;
4281  info->conrelid = constraint->conrelid;
4282  info->confrelid = constraint->confrelid;
4283 
4284  DeconstructFkConstraintRow(htup, &info->nkeys,
4285  info->conkey,
4286  info->confkey,
4287  info->conpfeqop,
4288  NULL, NULL);
4289 
4290  /* Add FK's node to the result list */
4291  result = lappend(result, info);
4292  }
4293 
4294  systable_endscan(conscan);
4295  table_close(conrel, AccessShareLock);
4296 
4297  /* Now save a copy of the completed list in the relcache entry. */
4299  oldlist = relation->rd_fkeylist;
4300  relation->rd_fkeylist = copyObject(result);
4301  relation->rd_fkeyvalid = true;
4302  MemoryContextSwitchTo(oldcxt);
4303 
4304  /* Don't leak the old list, if there is one */
4305  list_free_deep(oldlist);
4306 
4307  return result;
4308 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void DeconstructFkConstraintRow(HeapTuple tuple, int *numfks, AttrNumber *conkey, AttrNumber *confkey, Oid *pf_eq_oprs, Oid *pp_eq_oprs, Oid *ff_eq_oprs)
AttrNumber conkey[INDEX_MAX_KEYS]
Definition: rel.h:228
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
List * rd_fkeylist
Definition: rel.h:95
Form_pg_class rd_rel
Definition: rel.h:84
void list_free_deep(List *list)
Definition: list.c:1344
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
List * lappend(List *list, void *datum)
Definition: list.c:321
#define makeNode(_type_)
Definition: nodes.h:572
Oid conpfeqop[INDEX_MAX_KEYS]
Definition: rel.h:230
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define ConstraintRelidTypidNameIndexId
Definition: indexing.h:128
AttrNumber confkey[INDEX_MAX_KEYS]
Definition: rel.h:229
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define copyObject(obj)
Definition: nodes.h:640
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
bool rd_fkeyvalid
Definition: rel.h:96
#define RelationGetRelid(relation)
Definition: rel.h:414
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationGetIndexAttrBitmap()

Bitmapset* RelationGetIndexAttrBitmap ( Relation  relation,
IndexAttrBitmapKind  keyAttrs 
)

Definition at line 4748 of file relcache.c.

References AccessShareLock, bms_add_member(), bms_copy(), bms_free(), CacheMemoryContext, elog, equal(), ERROR, FirstLowInvalidHeapAttributeNumber, GetPgIndexDescriptor(), heap_getattr, i, 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_index, RelationData::rd_indexattr, RelationData::rd_indextuple, RelationData::rd_keyattr, RelationData::rd_pkattr, RelationData::rd_pkindex, RelationData::rd_replidindex, RelationGetForm, RelationGetIndexList(), relhasindex, stringToNode(), and TextDatumGetCString.

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

4749 {
4750  Bitmapset *indexattrs; /* indexed columns */
4751  Bitmapset *uindexattrs; /* columns in unique indexes */
4752  Bitmapset *pkindexattrs; /* columns in the primary index */
4753  Bitmapset *idindexattrs; /* columns in the replica identity */
4754  List *indexoidlist;
4755  List *newindexoidlist;
4756  Oid relpkindex;
4757  Oid relreplindex;
4758  ListCell *l;
4759  MemoryContext oldcxt;
4760 
4761  /* Quick exit if we already computed the result. */
4762  if (relation->rd_indexattr != NULL)
4763  {
4764  switch (attrKind)
4765  {
4766  case INDEX_ATTR_BITMAP_ALL:
4767  return bms_copy(relation->rd_indexattr);
4768  case INDEX_ATTR_BITMAP_KEY:
4769  return bms_copy(relation->rd_keyattr);
4771  return bms_copy(relation->rd_pkattr);
4773  return bms_copy(relation->rd_idattr);
4774  default:
4775  elog(ERROR, "unknown attrKind %u", attrKind);
4776  }
4777  }
4778 
4779  /* Fast path if definitely no indexes */
4780  if (!RelationGetForm(relation)->relhasindex)
4781  return NULL;
4782 
4783  /*
4784  * Get cached list of index OIDs. If we have to start over, we do so here.
4785  */
4786 restart:
4787  indexoidlist = RelationGetIndexList(relation);
4788 
4789  /* Fall out if no indexes (but relhasindex was set) */
4790  if (indexoidlist == NIL)
4791  return NULL;
4792 
4793  /*
4794  * Copy the rd_pkindex and rd_replidindex values computed by
4795  * RelationGetIndexList before proceeding. This is needed because a
4796  * relcache flush could occur inside index_open below, resetting the
4797  * fields managed by RelationGetIndexList. We need to do the work with
4798  * stable values of these fields.
4799  */
4800  relpkindex = relation->rd_pkindex;
4801  relreplindex = relation->rd_replidindex;
4802 
4803  /*
4804  * For each index, add referenced attributes to indexattrs.
4805  *
4806  * Note: we consider all indexes returned by RelationGetIndexList, even if
4807  * they are not indisready or indisvalid. This is important because an
4808  * index for which CREATE INDEX CONCURRENTLY has just started must be
4809  * included in HOT-safety decisions (see README.HOT). If a DROP INDEX
4810  * CONCURRENTLY is far enough along that we should ignore the index, it
4811  * won't be returned at all by RelationGetIndexList.
4812  */
4813  indexattrs = NULL;
4814  uindexattrs = NULL;
4815  pkindexattrs = NULL;
4816  idindexattrs = NULL;
4817  foreach(l, indexoidlist)
4818  {
4819  Oid indexOid = lfirst_oid(l);
4820  Relation indexDesc;
4821  Datum datum;
4822  bool isnull;
4823  Node *indexExpressions;
4824  Node *indexPredicate;
4825  int i;
4826  bool isKey; /* candidate key */
4827  bool isPK; /* primary key */
4828  bool isIDKey; /* replica identity index */
4829 
4830  indexDesc = index_open(indexOid, AccessShareLock);
4831 
4832  /*
4833  * Extract index expressions and index predicate. Note: Don't use
4834  * RelationGetIndexExpressions()/RelationGetIndexPredicate(), because
4835  * those might run constant expressions evaluation, which needs a
4836  * snapshot, which we might not have here. (Also, it's probably more
4837  * sound to collect the bitmaps before any transformations that might
4838  * eliminate columns, but the practical impact of this is limited.)
4839  */
4840 
4841  datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indexprs,
4842  GetPgIndexDescriptor(), &isnull);
4843  if (!isnull)
4844  indexExpressions = stringToNode(TextDatumGetCString(datum));
4845  else
4846  indexExpressions = NULL;
4847 
4848  datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indpred,
4849  GetPgIndexDescriptor(), &isnull);
4850  if (!isnull)
4851  indexPredicate = stringToNode(TextDatumGetCString(datum));
4852  else
4853  indexPredicate = NULL;
4854 
4855  /* Can this index be referenced by a foreign key? */
4856  isKey = indexDesc->rd_index->indisunique &&
4857  indexExpressions == NULL &&
4858  indexPredicate == NULL;
4859 
4860  /* Is this a primary key? */
4861  isPK = (indexOid == relpkindex);
4862 
4863  /* Is this index the configured (or default) replica identity? */
4864  isIDKey = (indexOid == relreplindex);
4865 
4866  /* Collect simple attribute references */
4867  for (i = 0; i < indexDesc->rd_index->indnatts; i++)
4868  {
4869  int attrnum = indexDesc->rd_index->indkey.values[i];
4870 
4871  /*
4872  * Since we have covering indexes with non-key columns, we must
4873  * handle them accurately here. non-key columns must be added into
4874  * indexattrs, since they are in index, and HOT-update shouldn't
4875  * miss them. Obviously, non-key columns couldn't be referenced by
4876  * foreign key or identity key. Hence we do not include them into
4877  * uindexattrs, pkindexattrs and idindexattrs bitmaps.
4878  */
4879  if (attrnum != 0)
4880  {
4881  indexattrs = bms_add_member(indexattrs,
4883 
4884  if (isKey && i < indexDesc->rd_index->indnkeyatts)
4885  uindexattrs = bms_add_member(uindexattrs,
4887 
4888  if (isPK && i < indexDesc->rd_index->indnkeyatts)
4889  pkindexattrs = bms_add_member(pkindexattrs,
4891 
4892  if (isIDKey && i < indexDesc->rd_index->indnkeyatts)
4893  idindexattrs = bms_add_member(idindexattrs,
4895  }
4896  }
4897 
4898  /* Collect all attributes used in expressions, too */
4899  pull_varattnos(indexExpressions, 1, &indexattrs);
4900 
4901  /* Collect all attributes in the index predicate, too */
4902  pull_varattnos(indexPredicate, 1, &indexattrs);
4903 
4904  index_close(indexDesc, AccessShareLock);
4905  }
4906 
4907  /*
4908  * During one of the index_opens in the above loop, we might have received
4909  * a relcache flush event on this relcache entry, which might have been
4910  * signaling a change in the rel's index list. If so, we'd better start
4911  * over to ensure we deliver up-to-date attribute bitmaps.
4912  */
4913  newindexoidlist = RelationGetIndexList(relation);
4914  if (equal(indexoidlist, newindexoidlist) &&
4915  relpkindex == relation->rd_pkindex &&
4916  relreplindex == relation->rd_replidindex)
4917  {
4918  /* Still the same index set, so proceed */
4919  list_free(newindexoidlist);
4920  list_free(indexoidlist);
4921  }
4922  else
4923  {
4924  /* Gotta do it over ... might as well not leak memory */
4925  list_free(newindexoidlist);
4926  list_free(indexoidlist);
4927  bms_free(uindexattrs);
4928  bms_free(pkindexattrs);
4929  bms_free(idindexattrs);
4930  bms_free(indexattrs);
4931 
4932  goto restart;
4933  }
4934 
4935  /* Don't leak the old values of these bitmaps, if any */
4936  bms_free(relation->rd_indexattr);
4937  relation->rd_indexattr = NULL;
4938  bms_free(relation->rd_keyattr);
4939  relation->rd_keyattr = NULL;
4940  bms_free(relation->rd_pkattr);
4941  relation->rd_pkattr = NULL;
4942  bms_free(relation->rd_idattr);
4943  relation->rd_idattr = NULL;
4944 
4945  /*
4946  * Now save copies of the bitmaps in the relcache entry. We intentionally
4947  * set rd_indexattr last, because that's the one that signals validity of
4948  * the values; if we run out of memory before making that copy, we won't
4949  * leave the relcache entry looking like the other ones are valid but
4950  * empty.
4951  */
4953  relation->rd_keyattr = bms_copy(uindexattrs);
4954  relation->rd_pkattr = bms_copy(pkindexattrs);
4955  relation->rd_idattr = bms_copy(idindexattrs);
4956  relation->rd_indexattr = bms_copy(indexattrs);
4957  MemoryContextSwitchTo(oldcxt);
4958 
4959  /* We return our original working copy for caller to play with */
4960  switch (attrKind)
4961  {
4962  case INDEX_ATTR_BITMAP_ALL:
4963  return indexattrs;
4964  case INDEX_ATTR_BITMAP_KEY:
4965  return uindexattrs;
4967  return pkindexattrs;
4969  return idindexattrs;
4970  default:
4971  elog(ERROR, "unknown attrKind %u", attrKind);
4972  return NULL;
4973  }
4974 }
#define NIL
Definition: pg_list.h:65
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:74
Bitmapset * rd_keyattr
Definition: rel.h:116
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2998
Oid rd_replidindex
Definition: rel.h:109
#define RelationGetForm(relation)
Definition: rel.h:408
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:524
void * stringToNode(const char *str)
Definition: read.c:89
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
unsigned int Oid
Definition: postgres_ext.h:31
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition: var.c:219
struct HeapTupleData * rd_indextuple
Definition: rel.h:146
Form_pg_index rd_index
Definition: rel.h:144
#define ERROR
Definition: elog.h:43
Oid rd_pkindex
Definition: rel.h:108
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4053
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:84
uintptr_t Datum
Definition: postgres.h:367
Bitmapset * rd_idattr
Definition: rel.h:118
void bms_free(Bitmapset *a)
Definition: bitmapset.c:208
bool relhasindex
Definition: pg_class.h:72
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4342
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:152
Bitmapset * rd_pkattr
Definition: rel.h:117
void list_free(List *list)
Definition: list.c:1330
#define elog(elevel,...)
Definition: elog.h:226
int i
Definition: pg_list.h:50
Bitmapset * rd_indexattr
Definition: rel.h:115
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:126
#define lfirst_oid(lc)
Definition: pg_list.h:192
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationGetIndexExpressions()

List* RelationGetIndexExpressions ( Relation  relation)

Definition at line 4603 of file relcache.c.

References Assert, 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(), get_relation_info(), infer_arbiter_indexes(), plan_create_index_workers(), and transformIndexConstraint().

4604 {
4605  List *result;
4606  Datum exprsDatum;
4607  bool isnull;
4608  char *exprsString;
4609  MemoryContext oldcxt;
4610 
4611  /* Quick exit if we already computed the result. */
4612  if (relation->rd_indexprs)
4613  return copyObject(relation->rd_indexprs);
4614 
4615  /* Quick exit if there is nothing to do. */
4616  if (relation->rd_indextuple == NULL ||
4617  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indexprs, NULL))
4618  return NIL;
4619 
4620  /*
4621  * We build the tree we intend to return in the caller's context. After
4622  * successfully completing the work, we copy it into the relcache entry.
4623  * This avoids problems if we get some sort of error partway through.
4624  */
4625  exprsDatum = heap_getattr(relation->rd_indextuple,
4626  Anum_pg_index_indexprs,
4628  &isnull);
4629  Assert(!isnull);
4630  exprsString = TextDatumGetCString(exprsDatum);
4631  result = (List *) stringToNode(exprsString);
4632  pfree(exprsString);
4633 
4634  /*
4635  * Run the expressions through eval_const_expressions. This is not just an
4636  * optimization, but is necessary, because the planner will be comparing
4637  * them to similarly-processed qual clauses, and may fail to detect valid
4638  * matches without this. We must not use canonicalize_qual, however,
4639  * since these aren't qual expressions.
4640  */
4641  result = (List *) eval_const_expressions(NULL, (Node *) result);
4642 
4643  /* May as well fix opfuncids too */
4644  fix_opfuncids((Node *) result);
4645 
4646  /* Now save a copy of the completed tree in the relcache entry. */
4647  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4648  relation->rd_indexprs = copyObject(result);
4649  MemoryContextSwitchTo(oldcxt);
4650 
4651  return result;
4652 }
#define NIL
Definition: pg_list.h:65
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1588
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
List * rd_indexprs
Definition: rel.h:171
Definition: nodes.h:524
void * stringToNode(const char *str)
Definition: read.c:89
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2254
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
struct HeapTupleData * rd_indextuple
Definition: rel.h:146
void pfree(void *pointer)
Definition: mcxt.c:1031
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4053
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:84
uintptr_t Datum
Definition: postgres.h:367
#define Assert(condition)
Definition: c.h:732
MemoryContext rd_indexcxt
Definition: rel.h:163
#define copyObject(obj)
Definition: nodes.h:640
Definition: pg_list.h:50

◆ RelationGetIndexList()

List* RelationGetIndexList ( Relation  relation)

Definition at line 4342 of file relcache.c.

References AccessShareLock, BTEqualStrategyNumber, CacheMemoryContext, GETSTRUCT, heap_attisnull(), HeapTupleIsValid, IndexIndrelidIndexId, insert_ordered_oid(), InvalidOid, list_copy(), list_free(), MemoryContextSwitchTo(), NIL, ObjectIdGetDatum, OidIsValid, RelationData::rd_indexlist, RelationData::rd_indexvalid, RelationData::rd_pkindex, RelationData::rd_rel, RelationData::rd_replidindex, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by AlterIndexNamespaces(), ATExecChangeOwner(), ATExecDetachPartition(), ATExecDropNotNull(), ATExecSetTableSpace(), AttachPartitionEnsureIndexes(), calculate_indexes_size(), calculate_toast_table_size(), cluster(), DefineIndex(), DefineRelation(), ExecInitPartitionInfo(), ExecOpenIndices(), ExecRefreshMatView(), get_relation_info(), GetParentedForeignKeyRefs(), index_get_partition(), infer_arbiter_indexes(), mark_index_clustered(), refresh_by_match_merge(), reindex_relation(), ReindexRelationConcurrently(), relation_mark_replica_identity(), RelationGetIndexAttrBitmap(), RelationGetPrimaryKeyIndex(), RelationGetReplicaIndex(), relationHasPrimaryKey(), RelationHasUnloggedIndex(), RelationTruncateIndexes(), toast_open_indexes(), transformFkeyCheckAttrs(), transformFkeyGetPrimaryKey(), transformTableLikeClause(), triggered_change_notification(), and vac_open_indexes().

4343 {
4344  Relation indrel;
4345  SysScanDesc indscan;
4346  ScanKeyData skey;
4347  HeapTuple htup;
4348  List *result;
4349  List *oldlist;
4350  char replident = relation->rd_rel->relreplident;
4351  Oid pkeyIndex = InvalidOid;
4352  Oid candidateIndex = InvalidOid;
4353  MemoryContext oldcxt;
4354 
4355  /* Quick exit if we already computed the list. */
4356  if (relation->rd_indexvalid)
4357  return list_copy(relation->rd_indexlist);
4358 
4359  /*
4360  * We build the list we intend to return (in the caller's context) while
4361  * doing the scan. After successfully completing the scan, we copy that
4362  * list into the relcache entry. This avoids cache-context memory leakage
4363  * if we get some sort of error partway through.
4364  */
4365  result = NIL;
4366 
4367  /* Prepare to scan pg_index for entries having indrelid = this rel. */
4368  ScanKeyInit(&skey,
4369  Anum_pg_index_indrelid,
4370  BTEqualStrategyNumber, F_OIDEQ,
4371  ObjectIdGetDatum(RelationGetRelid(relation)));
4372 
4373  indrel = table_open(IndexRelationId, AccessShareLock);
4374  indscan = systable_beginscan(indrel, IndexIndrelidIndexId, true,
4375  NULL, 1, &skey);
4376 
4377  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4378  {
4380 
4381  /*
4382  * Ignore any indexes that are currently being dropped. This will
4383  * prevent them from being searched, inserted into, or considered in
4384  * HOT-safety decisions. It's unsafe to touch such an index at all
4385  * since its catalog entries could disappear at any instant.
4386  */
4387  if (!index->indislive)
4388  continue;
4389 
4390  /* Add index's OID to result list in the proper order */
4391  result = insert_ordered_oid(result, index->indexrelid);
4392 
4393  /*
4394  * Invalid, non-unique, non-immediate or predicate indexes aren't
4395  * interesting for either oid indexes or replication identity indexes,
4396  * so don't check them.
4397  */
4398  if (!index->indisvalid || !index->indisunique ||
4399  !index->indimmediate ||
4400  !heap_attisnull(htup, Anum_pg_index_indpred, NULL))
4401  continue;
4402 
4403  /* remember primary key index if any */
4404  if (index->indisprimary)
4405  pkeyIndex = index->indexrelid;
4406 
4407  /* remember explicitly chosen replica index */
4408  if (index->indisreplident)
4409  candidateIndex = index->indexrelid;
4410  }
4411 
4412  systable_endscan(indscan);
4413 
4414  table_close(indrel, AccessShareLock);
4415 
4416  /* Now save a copy of the completed list in the relcache entry. */
4418  oldlist = relation->rd_indexlist;
4419  relation->rd_indexlist = list_copy(result);
4420  relation->rd_pkindex = pkeyIndex;
4421  if (replident == REPLICA_IDENTITY_DEFAULT && OidIsValid(pkeyIndex))
4422  relation->rd_replidindex = pkeyIndex;
4423  else if (replident == REPLICA_IDENTITY_INDEX && OidIsValid(candidateIndex))
4424  relation->rd_replidindex = candidateIndex;
4425  else
4426  relation->rd_replidindex = InvalidOid;
4427  relation->rd_indexvalid = true;
4428  MemoryContextSwitchTo(oldcxt);
4429 
4430  /* Don't leak the old list, if there is one */
4431  list_free(oldlist);
4432 
4433  return result;
4434 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Oid rd_replidindex
Definition: rel.h:109
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:4528
List * list_copy(const List *oldlist)
Definition: list.c:1357
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
Form_pg_class rd_rel
Definition: rel.h:84
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:638
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
Definition: type.h:89
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
Oid rd_pkindex
Definition: rel.h:108
List * rd_indexlist
Definition: rel.h:107
FormData_pg_index * Form_pg_index
Definition: pg_index.h:66
bool rd_indexvalid
Definition: rel.h:63
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void list_free(List *list)
Definition: list.c:1330
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:414
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define IndexIndrelidIndexId
Definition: indexing.h:166
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationGetIndexPredicate()

List* RelationGetIndexPredicate ( Relation  relation)

Definition at line 4665 of file relcache.c.

References 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(), get_relation_info(), infer_arbiter_indexes(), is_usable_unique_index(), plan_create_index_workers(), and transformIndexConstraint().

4666 {
4667  List *result;
4668  Datum predDatum;
4669  bool isnull;
4670  char *predString;
4671  MemoryContext oldcxt;
4672 
4673  /* Quick exit if we already computed the result. */
4674  if (relation->rd_indpred)
4675  return copyObject(relation->rd_indpred);
4676 
4677  /* Quick exit if there is nothing to do. */
4678  if (relation->rd_indextuple == NULL ||
4679  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indpred, NULL))
4680  return NIL;
4681 
4682  /*
4683  * We build the tree we intend to return in the caller's context. After
4684  * successfully completing the work, we copy it into the relcache entry.
4685  * This avoids problems if we get some sort of error partway through.
4686  */
4687  predDatum = heap_getattr(relation->rd_indextuple,
4688  Anum_pg_index_indpred,
4690  &isnull);
4691  Assert(!isnull);
4692  predString = TextDatumGetCString(predDatum);
4693  result = (List *) stringToNode(predString);
4694  pfree(predString);
4695 
4696  /*
4697  * Run the expression through const-simplification and canonicalization.
4698  * This is not just an optimization, but is necessary, because the planner
4699  * will be comparing it to similarly-processed qual clauses, and may fail
4700  * to detect valid matches without this. This must match the processing
4701  * done to qual clauses in preprocess_expression()! (We can skip the
4702  * stuff involving subqueries, however, since we don't allow any in index
4703  * predicates.)
4704  */
4705  result = (List *) eval_const_expressions(NULL, (Node *) result);
4706 
4707  result = (List *) canonicalize_qual((Expr *) result, false);
4708 
4709  /* Also convert to implicit-AND format */
4710  result = make_ands_implicit((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_indpred = copyObject(result);
4718  MemoryContextSwitchTo(oldcxt);
4719 
4720  return result;
4721 }
#define NIL
Definition: pg_list.h:65
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1588
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:524
void * stringToNode(const char *str)
Definition: read.c:89
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2254
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
struct HeapTupleData * rd_indextuple
Definition: rel.h:146
void pfree(void *pointer)
Definition: mcxt.c:1031
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4053
Expr * canonicalize_qual(Expr *qual, bool is_check)
Definition: prepqual.c:292
List * rd_indpred
Definition: rel.h:172
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:84
uintptr_t Datum
Definition: postgres.h:367
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:717
#define Assert(condition)
Definition: c.h:732
MemoryContext rd_indexcxt
Definition: rel.h:163
#define copyObject(obj)
Definition: nodes.h:640
Definition: pg_list.h:50

◆ RelationGetPrimaryKeyIndex()

Oid RelationGetPrimaryKeyIndex ( Relation  relation)

Definition at line 4557 of file relcache.c.

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

Referenced by GetRelationIdentityOrPK().

4558 {
4559  List *ilist;
4560 
4561  if (!relation->rd_indexvalid)
4562  {
4563  /* RelationGetIndexList does the heavy lifting. */
4564  ilist = RelationGetIndexList(relation);
4565  list_free(ilist);
4566  Assert(relation->rd_indexvalid);
4567  }
4568 
4569  return relation->rd_pkindex;
4570 }
Oid rd_pkindex
Definition: rel.h:108
bool rd_indexvalid
Definition: rel.h:63
#define Assert(condition)
Definition: c.h:732
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4342
void list_free(List *list)
Definition: list.c:1330
Definition: pg_list.h:50

◆ RelationGetReplicaIndex()

Oid RelationGetReplicaIndex ( Relation  relation)

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

4579 {
4580  List *ilist;
4581 
4582  if (!relation->rd_indexvalid)
4583  {
4584  /* RelationGetIndexList does the heavy lifting. */
4585  ilist = RelationGetIndexList(relation);
4586  list_free(ilist);
4587  Assert(relation->rd_indexvalid);
4588  }
4589 
4590  return relation->rd_replidindex;
4591 }
Oid rd_replidindex
Definition: rel.h:109
bool rd_indexvalid
Definition: rel.h:63
#define Assert(condition)
Definition: c.h:732
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4342
void list_free(List *list)
Definition: list.c:1330
Definition: pg_list.h:50

◆ RelationGetStatExtList()

List* RelationGetStatExtList ( Relation  relation)

Definition at line 4458 of file relcache.c.

References AccessShareLock, BTEqualStrategyNumber, CacheMemoryContext, GETSTRUCT, HeapTupleIsValid, insert_ordered_oid(), list_copy(), list_free(), MemoryContextSwitchTo(), NIL, ObjectIdGetDatum, RelationData::rd_statlist, RelationData::rd_statvalid, RelationGetRelid, ScanKeyInit(), StatisticExtRelidIndexId, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by get_relation_statistics(), and transformTableLikeClause().

4459 {
4460  Relation indrel;
4461  SysScanDesc indscan;
4462  ScanKeyData skey;
4463  HeapTuple htup;
4464  List *result;
4465  List *oldlist;
4466  MemoryContext oldcxt;
4467 
4468  /* Quick exit if we already computed the list. */
4469  if (relation->rd_statvalid != 0)
4470  return list_copy(relation->rd_statlist);
4471 
4472  /*
4473  * We build the list we intend to return (in the caller's context) while
4474  * doing the scan. After successfully completing the scan, we copy that
4475  * list into the relcache entry. This avoids cache-context memory leakage
4476  * if we get some sort of error partway through.
4477  */
4478  result = NIL;
4479 
4480  /*
4481  * Prepare to scan pg_statistic_ext for entries having stxrelid = this
4482  * rel.
4483  */
4484  ScanKeyInit(&skey,
4485  Anum_pg_statistic_ext_stxrelid,
4486  BTEqualStrategyNumber, F_OIDEQ,
4487  ObjectIdGetDatum(RelationGetRelid(relation)));
4488 
4489  indrel = table_open(StatisticExtRelationId, AccessShareLock);
4490  indscan = systable_beginscan(indrel, StatisticExtRelidIndexId, true,
4491  NULL, 1, &skey);
4492 
4493  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4494  {
4495  Oid oid = ((Form_pg_statistic_ext) GETSTRUCT(htup))->oid;
4496 
4497  result = insert_ordered_oid(result, oid);
4498  }
4499 
4500  systable_endscan(indscan);
4501 
4502  table_close(indrel, AccessShareLock);
4503 
4504  /* Now save a copy of the completed list in the relcache entry. */
4506  oldlist = relation->rd_statlist;
4507  relation->rd_statlist = list_copy(result);
4508 
4509  relation->rd_statvalid = true;
4510  MemoryContextSwitchTo(oldcxt);
4511 
4512  /* Don't leak the old list, if there is one */
4513  list_free(oldlist);
4514 
4515  return result;
4516 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
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:4528
List * list_copy(const List *oldlist)
Definition: list.c:1357
unsigned int Oid
Definition: postgres_ext.h:31
#define StatisticExtRelidIndexId
Definition: indexing.h:238
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
bool rd_statvalid
Definition: rel.h:65
void list_free(List *list)
Definition: list.c:1330
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
List * rd_statlist
Definition: rel.h:112
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:414
#define BTEqualStrategyNumber
Definition: stratnum.h:31
FormData_pg_statistic_ext * Form_pg_statistic_ext
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationIdGetRelation()

Relation RelationIdGetRelation ( Oid  relationId)

Definition at line 1991 of file relcache.c.

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

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

1992 {
1993  Relation rd;
1994 
1995  /* Make sure we're in an xact, even if this ends up being a cache hit */
1997 
1998  /*
1999  * first try to find reldesc in the cache
2000  */
2001  RelationIdCacheLookup(relationId, rd);
2002 
2003  if (RelationIsValid(rd))
2004  {
2006  /* revalidate cache entry if necessary */
2007  if (!rd->rd_isvalid)
2008  {
2009  /*
2010  * Indexes only have a limited number of possible schema changes,
2011  * and we don't want to use the full-blown procedure because it's
2012  * a headache for indexes that reload itself depends on.
2013  */
2014  if (rd->rd_rel->relkind == RELKIND_INDEX ||
2015  rd->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
2017  else
2018  RelationClearRelation(rd, true);
2019 
2020  /*
2021  * Normally entries need to be valid here, but before the relcache
2022  * has been initialized, not enough infrastructure exists to
2023  * perform pg_class lookups. The structure of such entries doesn't
2024  * change, but we still want to update the rd_rel entry. So
2025  * rd_isvalid = false is left in place for a later lookup.
2026  */
2027  Assert(rd->rd_isvalid ||
2029  }
2030  return rd;
2031  }
2032 
2033  /*
2034  * no reldesc in the cache, so have RelationBuildDesc() build one and add
2035  * it.
2036  */
2037  rd = RelationBuildDesc(relationId, true);
2038  if (RelationIsValid(rd))
2040  return rd;
2041 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2398
bool rd_isnailed
Definition: rel.h:61
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:214
bool rd_isvalid
Definition: rel.h:62
Form_pg_class rd_rel
Definition: rel.h:84
#define RelationIsValid(relation)
Definition: rel.h:387
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2057
static void RelationReloadIndexInfo(Relation relation)
Definition: relcache.c:2131
#define Assert(condition)
Definition: c.h:732
static Relation RelationBuildDesc(Oid targetRelId, bool insertIt)
Definition: relcache.c:1026
bool IsTransactionState(void)
Definition: xact.c:356
bool criticalRelcachesBuilt
Definition: relcache.c:141

◆ RelationIdIsInInitFile()

bool RelationIdIsInInitFile ( Oid  relationId)

Definition at line 5920 of file relcache.c.

References Assert, DatabaseNameIndexId, RelationSupportsSysCache(), SharedSecLabelObjectIndexId, and TriggerRelidNameIndexId.

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

5921 {
5922  if (relationId == SharedSecLabelRelationId ||
5923  relationId == TriggerRelidNameIndexId ||
5924  relationId == DatabaseNameIndexId ||
5925  relationId == SharedSecLabelObjectIndexId)
5926  {
5927  /*
5928  * If this Assert fails, we don't need the applicable special case
5929  * anymore.
5930  */
5931  Assert(!RelationSupportsSysCache(relationId));
5932  return true;
5933  }
5934  return RelationSupportsSysCache(relationId);
5935 }
#define TriggerRelidNameIndexId
Definition: indexing.h:256
#define Assert(condition)
Definition: c.h:732
#define DatabaseNameIndexId
Definition: indexing.h:144
#define SharedSecLabelObjectIndexId
Definition: indexing.h:323
bool RelationSupportsSysCache(Oid relid)
Definition: syscache.c:1529

◆ RelationInitIndexAccessInfo()

void RelationInitIndexAccessInfo ( Relation  relation)

Definition at line 1363 of file relcache.c.

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

Referenced by index_create(), and RelationBuildDesc().

1364 {
1365  HeapTuple tuple;
1366  Form_pg_am aform;
1367  Datum indcollDatum;
1368  Datum indclassDatum;
1369  Datum indoptionDatum;
1370  bool isnull;
1371  oidvector *indcoll;
1372  oidvector *indclass;
1373  int2vector *indoption;
1374  MemoryContext indexcxt;
1375  MemoryContext oldcontext;
1376  int indnatts;
1377  int indnkeyatts;
1378  uint16 amsupport;
1379 
1380  /*
1381  * Make a copy of the pg_index entry for the index. Since pg_index
1382  * contains variable-length and possibly-null fields, we have to do this
1383  * honestly rather than just treating it as a Form_pg_index struct.
1384  */
1385  tuple = SearchSysCache1(INDEXRELID,
1386  ObjectIdGetDatum(RelationGetRelid(relation)));
1387  if (!HeapTupleIsValid(tuple))
1388  elog(ERROR, "cache lookup failed for index %u",
1389  RelationGetRelid(relation));
1391  relation->rd_indextuple = heap_copytuple(tuple);
1392  relation->rd_index = (Form_pg_index) GETSTRUCT(relation->rd_indextuple);
1393  MemoryContextSwitchTo(oldcontext);
1394  ReleaseSysCache(tuple);
1395 
1396  /*
1397  * Look up the index's access method, save the OID of its handler function
1398  */
1399  tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(relation->rd_rel->relam));
1400  if (!HeapTupleIsValid(tuple))
1401  elog(ERROR, "cache lookup failed for access method %u",
1402  relation->rd_rel->relam);
1403  aform = (Form_pg_am) GETSTRUCT(tuple);
1404  relation->rd_amhandler = aform->amhandler;
1405  ReleaseSysCache(tuple);
1406 
1407  indnatts = RelationGetNumberOfAttributes(relation);
1408  if (indnatts != IndexRelationGetNumberOfAttributes(relation))
1409  elog(ERROR, "relnatts disagrees with indnatts for index %u",
1410  RelationGetRelid(relation));
1411  indnkeyatts = IndexRelationGetNumberOfKeyAttributes(relation);
1412 
1413  /*
1414  * Make the private context to hold index access info. The reason we need
1415  * a context, and not just a couple of pallocs, is so that we won't leak
1416  * any subsidiary info attached to fmgr lookup records.
1417  */
1419  "index info",
1421  relation->rd_indexcxt = indexcxt;
1423  RelationGetRelationName(relation));
1424 
1425  /*
1426  * Now we can fetch the index AM's API struct
1427  */
1428  InitIndexAmRoutine(relation);
1429 
1430  /*
1431  * Allocate arrays to hold data. Opclasses are not used for included
1432  * columns, so allocate them for indnkeyatts only.
1433  */
1434  relation->rd_opfamily = (Oid *)
1435  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1436  relation->rd_opcintype = (Oid *)
1437  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1438 
1439  amsupport = relation->rd_indam->amsupport;
1440  if (amsupport > 0)
1441  {
1442  int nsupport = indnatts * amsupport;
1443 
1444  relation->rd_support = (RegProcedure *)
1445  MemoryContextAllocZero(indexcxt, nsupport * sizeof(RegProcedure));
1446  relation->rd_supportinfo = (FmgrInfo *)
1447  MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
1448  }
1449  else
1450  {
1451  relation->rd_support = NULL;
1452  relation->rd_supportinfo = NULL;
1453  }
1454 
1455  relation->rd_indcollation = (Oid *)
1456  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1457 
1458  relation->rd_indoption = (int16 *)
1459  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(int16));
1460 
1461  /*
1462  * indcollation cannot be referenced directly through the C struct,
1463  * because it comes after the variable-width indkey field. Must extract
1464  * the datum the hard way...
1465  */
1466  indcollDatum = fastgetattr(relation->rd_indextuple,
1467  Anum_pg_index_indcollation,
1469  &isnull);
1470  Assert(!isnull);
1471  indcoll = (oidvector *) DatumGetPointer(indcollDatum);
1472  memcpy(relation->rd_indcollation, indcoll->values, indnkeyatts * sizeof(Oid));
1473 
1474  /*
1475  * indclass cannot be referenced directly through the C struct, because it
1476  * comes after the variable-width indkey field. Must extract the datum
1477  * the hard way...
1478  */
1479  indclassDatum = fastgetattr(relation->rd_indextuple,
1480  Anum_pg_index_indclass,
1482  &isnull);
1483  Assert(!isnull);
1484  indclass = (oidvector *) DatumGetPointer(indclassDatum);
1485 
1486  /*
1487  * Fill the support procedure OID array, as well as the info about
1488  * opfamilies and opclass input types. (aminfo and supportinfo are left
1489  * as zeroes, and are filled on-the-fly when used)
1490  */
1491  IndexSupportInitialize(indclass, relation->rd_support,
1492  relation->rd_opfamily, relation->rd_opcintype,
1493  amsupport, indnkeyatts);
1494 
1495  /*
1496  * Similarly extract indoption and copy it to the cache entry
1497  */
1498  indoptionDatum = fastgetattr(relation->rd_indextuple,
1499  Anum_pg_index_indoption,
1501  &isnull);
1502  Assert(!isnull);
1503  indoption = (int2vector *) DatumGetPointer(indoptionDatum);
1504  memcpy(relation->rd_indoption, indoption->values, indnkeyatts * sizeof(int16));
1505 
1506  /*
1507  * expressions, predicate, exclusion caches will be filled later
1508  */
1509  relation->rd_indexprs = NIL;
1510  relation->rd_indpred = NIL;
1511  relation->rd_exclops = NULL;
1512  relation->rd_exclprocs = NULL;
1513  relation->rd_exclstrats = NULL;
1514  relation->rd_amcache = NULL;
1515 }
signed short int16
Definition: c.h:345
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
#define NIL
Definition: pg_list.h:65
Definition: c.h:588
struct IndexAmRoutine * rd_indam
Definition: rel.h:165
Definition: fmgr.h:56
uint16 amsupport
Definition: amapi.h:173
#define AllocSetContextCreate
Definition: memutils.h:169
int16 * rd_indoption
Definition: rel.h:170
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:712
Definition: syscache.h:36
FmgrInfo * rd_supportinfo
Definition: rel.h:169
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:420
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:201
regproc RegProcedure
Definition: c.h:505
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
uint16 * rd_exclstrats
Definition: rel.h:175
List * rd_indexprs
Definition: rel.h:171
Oid * rd_exclprocs
Definition: rel.h:174
Form_pg_class rd_rel
Definition: rel.h:84
unsigned int Oid
Definition: postgres_ext.h:31
static void InitIndexAmRoutine(Relation relation)
Definition: relcache.c:1339
static void IndexSupportInitialize(oidvector *indclass, RegProcedure *indexSupport, Oid *opFamily, Oid *opcInType, StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber)
Definition: relcache.c:1531
struct HeapTupleData * rd_indextuple
Definition: rel.h:146
Form_pg_index rd_index
Definition: rel.h:144
unsigned short uint16
Definition: c.h:357
Oid * rd_indcollation
Definition: rel.h:177
Oid rd_amhandler
Definition: rel.h:136
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define MemoryContextCopyAndSetIdentifier(cxt, id)
Definition: memutils.h:96
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4053
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:596
#define IndexRelationGetNumberOfAttributes(relation)
Definition: rel.h:426
#define RelationGetRelationName(relation)
Definition: rel.h:448
List * rd_indpred
Definition: rel.h:172
Oid * rd_opfamily
Definition: rel.h:166
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition: rel.h:433
Oid * rd_exclops
Definition: rel.h:173
RegProcedure * rd_support
Definition: rel.h:168
FormData_pg_index * Form_pg_index
Definition: pg_index.h:66
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
Definition: c.h:577
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:814
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:732
int16 values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:585
#define DatumGetPointer(X)
Definition: postgres.h:549
FormData_pg_am * Form_pg_am
Definition: pg_am.h:48
#define elog(elevel,...)
Definition: elog.h:226
MemoryContext rd_indexcxt
Definition: rel.h:163
void * rd_amcache
Definition: rel.h:176
Oid * rd_opcintype
Definition: rel.h:167
#define RelationGetRelid(relation)
Definition: rel.h:414
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationInitTableAccessMethod()

void RelationInitTableAccessMethod ( Relation  relation)

Definition at line 1741 of file relcache.c.

References AMOID, Assert, elog, ERROR, GETSTRUCT, HeapTupleIsValid, InitTableAmRoutine(), InvalidOid, IsCatalogRelation(), ObjectIdGetDatum, RelationData::rd_amhandler, RelationData::rd_rel, ReleaseSysCache(), and SearchSysCache1().

Referenced by load_relcache_init_file(), RelationBuildDesc(), RelationBuildLocalRelation(), and RelationCacheInitializePhase3().

1742 {
1743  HeapTuple tuple;
1744  Form_pg_am aform;
1745 
1746  if (relation->rd_rel->relkind == RELKIND_SEQUENCE)
1747  {
1748  /*
1749  * Sequences are currently accessed like heap tables, but it doesn't
1750  * seem prudent to show that in the catalog. So just overwrite it
1751  * here.
1752  */
1753  relation->rd_amhandler = HEAP_TABLE_AM_HANDLER_OID;
1754  }
1755  else if (IsCatalogRelation(relation))
1756  {
1757  /*
1758  * Avoid doing a syscache lookup for catalog tables.
1759  */
1760  Assert(relation->rd_rel->relam == HEAP_TABLE_AM_OID);
1761  relation->rd_amhandler = HEAP_TABLE_AM_HANDLER_OID;
1762  }
1763  else
1764  {
1765  /*
1766  * Look up the table access method, save the OID of its handler
1767  * function.
1768  */
1769  Assert(relation->rd_rel->relam != InvalidOid);
1770  tuple = SearchSysCache1(AMOID,
1771  ObjectIdGetDatum(relation->rd_rel->relam));
1772  if (!HeapTupleIsValid(tuple))
1773  elog(ERROR, "cache lookup failed for access method %u",
1774  relation->rd_rel->relam);
1775  aform = (Form_pg_am) GETSTRUCT(tuple);
1776  relation->rd_amhandler = aform->amhandler;
1777  ReleaseSysCache(tuple);
1778  }
1779 
1780  /*
1781  * Now we can fetch the table AM's API struct
1782  */
1783  InitTableAmRoutine(relation);
1784 }
static void InitTableAmRoutine(Relation relation)
Definition: relcache.c:1732
bool IsCatalogRelation(Relation relation)
Definition: catalog.c:100
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
Definition: syscache.h:36
Form_pg_class rd_rel
Definition: rel.h:84
Oid rd_amhandler
Definition: rel.h:136
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:732
FormData_pg_am * Form_pg_am
Definition: pg_am.h:48
#define elog(elevel,...)
Definition: elog.h:226

◆ RelationSetNewRelfilenode()

void RelationSetNewRelfilenode ( Relation  relation,
char  persistence 
)

Definition at line 3412 of file relcache.c.

References Assert, CacheInvalidateRelcache(), CatalogTupleUpdate(), CommandCounterIncrement(), elog, EOXactListAdd, ERROR, GetCurrentSubTransactionId(), GetCurrentTransactionId(), GetNewRelFileNode(), GETSTRUCT, heap_freetuple(), HeapTupleIsValid, InvalidMultiXactId, InvalidTransactionId, ObjectIdGetDatum, RelationData::rd_newRelfilenodeSubid, RelationData::rd_node, RelationData::rd_rel, RelationCreateStorage(), RelationDropStorage(), RelationGetRelationName, RelationGetRelid, RelationIsMapped, RelationMapUpdateMap(), RelFileNode::relNode, RELOID, RowExclusiveLock, SearchSysCacheCopy1, smgrclose(), HeapTupleData::t_self, table_close(), table_open(), and table_relation_set_new_filenode().

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

3413 {
3414  Oid newrelfilenode;
3415  Relation pg_class;
3416  HeapTuple tuple;
3417  Form_pg_class classform;
3418  MultiXactId minmulti = InvalidMultiXactId;
3419  TransactionId freezeXid = InvalidTransactionId;
3420  RelFileNode newrnode;
3421 
3422  /* Allocate a new relfilenode */
3423  newrelfilenode = GetNewRelFileNode(relation->rd_rel->reltablespace, NULL,
3424  persistence);
3425 
3426  /*
3427  * Get a writable copy of the pg_class tuple for the given relation.
3428  */
3429  pg_class = table_open(RelationRelationId, RowExclusiveLock);
3430 
3431  tuple = SearchSysCacheCopy1(RELOID,
3432  ObjectIdGetDatum(RelationGetRelid(relation)));
3433  if (!HeapTupleIsValid(tuple))
3434  elog(ERROR, "could not find tuple for relation %u",
3435  RelationGetRelid(relation));
3436  classform = (Form_pg_class) GETSTRUCT(tuple);
3437 
3438  /*
3439  * Schedule unlinking of the old storage at transaction commit.
3440  */
3441  RelationDropStorage(relation);
3442 
3443  /*
3444  * Create storage for the main fork of the new relfilenode. If it's a
3445  * table-like object, call into the table AM to do so, which'll also
3446  * create the table's init fork if needed.
3447  *
3448  * NOTE: If relevant for the AM, any conflict in relfilenode value will be
3449  * caught here, if GetNewRelFileNode messes up for any reason.
3450  */
3451  newrnode = relation->rd_node;
3452  newrnode.relNode = newrelfilenode;
3453 
3454  switch (relation->rd_rel->relkind)
3455  {
3456  case RELKIND_INDEX:
3457  case RELKIND_SEQUENCE:
3458  {
3459  /* handle these directly, at least for now */
3460  SMgrRelation srel;
3461 
3462  srel = RelationCreateStorage(newrnode, persistence);
3463  smgrclose(srel);
3464  }
3465  break;
3466 
3467  case RELKIND_RELATION:
3468  case RELKIND_TOASTVALUE:
3469  case RELKIND_MATVIEW:
3470  table_relation_set_new_filenode(relation, &newrnode,
3471  persistence,
3472  &freezeXid, &minmulti);
3473  break;
3474 
3475  default:
3476  /* we shouldn't be called for anything else */
3477  elog(ERROR, "relation \"%s\" does not have storage",
3478  RelationGetRelationName(relation));
3479  break;
3480  }
3481 
3482  /*
3483  * If we're dealing with a mapped index, pg_class.relfilenode doesn't
3484  * change; instead we have to send the update to the relation mapper.
3485  *
3486  * For mapped indexes, we don't actually change the pg_class entry at all;
3487  * this is essential when reindexing pg_class itself. That leaves us with
3488  * possibly-inaccurate values of relpages etc, but those will be fixed up
3489  * later.
3490  */
3491  if (RelationIsMapped(relation))
3492  {
3493  /* This case is only supported for indexes */
3494  Assert(relation->rd_rel->relkind == RELKIND_INDEX);
3495 
3496  /* Since we're not updating pg_class, these had better not change */
3497  Assert(classform->relfrozenxid == freezeXid);
3498  Assert(classform->relminmxid == minmulti);
3499  Assert(classform->relpersistence == persistence);
3500 
3501  /*
3502  * In some code paths it's possible that the tuple update we'd
3503  * otherwise do here is the only thing that would assign an XID for
3504  * the current transaction. However, we must have an XID to delete
3505  * files, so make sure one is assigned.
3506  */
3507  (void) GetCurrentTransactionId();
3508 
3509  /* Do the deed */
3511  newrelfilenode,
3512  relation->rd_rel->relisshared,
3513  false);
3514 
3515  /* Since we're not updating pg_class, must trigger inval manually */
3516  CacheInvalidateRelcache(relation);
3517  }
3518  else
3519  {
3520  /* Normal case, update the pg_class entry */
3521  classform->relfilenode = newrelfilenode;
3522 
3523  /* relpages etc. never change for sequences */
3524  if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
3525  {
3526  classform->relpages = 0; /* it's empty until further notice */
3527  classform->reltuples = 0;
3528  classform->relallvisible = 0;
3529  }
3530  classform->relfrozenxid = freezeXid;
3531  classform->relminmxid = minmulti;
3532  classform->relpersistence = persistence;
3533 
3534  CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
3535  }
3536 
3537  heap_freetuple(tuple);
3538 
3539  table_close(pg_class, RowExclusiveLock);
3540 
3541  /*
3542  * Make the pg_class row change or relation map change visible. This will
3543  * cause the relcache entry to get updated, too.
3544  */
3546 
3547  /*
3548  * Mark the rel as having been given a new relfilenode in the current
3549  * (sub) transaction. This is a hint that can be used to optimize later
3550  * operations on the rel in the same transaction.
3551  */
3553 
3554  /* Flag relation as needing eoxact cleanup (to remove the hint) */
3555  EOXactListAdd(relation);
3556 }
void smgrclose(SMgrRelation reln)
Definition: smgr.c:258
#define EOXactListAdd(rel)
Definition: relcache.c:172
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
uint32 TransactionId
Definition: c.h:507
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:81
Form_pg_class rd_rel
Definition: rel.h:84
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
SMgrRelation RelationCreateStorage(RelFileNode rnode, char relpersistence)
Definition: storage.c:79
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
TransactionId GetCurrentTransactionId(void)
Definition: xact.c:423
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvalidTransactionId
Definition: transam.h:31
#define RelationGetRelationName(relation)
Definition: rel.h:448
#define RelationIsMapped(relation)
Definition: rel.h:463
void RelationDropStorage(Relation rel)
Definition: storage.c:148
void CommandCounterIncrement(void)
Definition: xact.c:1003
#define InvalidMultiXactId
Definition: multixact.h:23
TransactionId MultiXactId
Definition: c.h:517
RelFileNode rd_node
Definition: rel.h:55
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:732
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:708
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
Oid GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
Definition: catalog.c:393
static void table_relation_set_new_filenode(Relation rel, const RelFileNode *newrnode, char persistence, TransactionId *freezeXid, MultiXactId *minmulti)
Definition: tableam.h:1345
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1270
FormData_pg_class * Form_pg_class
Definition: pg_class.h:150
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:174
#define elog(elevel,...)
Definition: elog.h:226
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define RelationGetRelid(relation)
Definition: rel.h:414
void RelationMapUpdateMap(Oid relationId, Oid fileNode, bool shared, bool immediate)
Definition: relmapper.c:261

Variable Documentation

◆ criticalRelcachesBuilt

◆ criticalSharedRelcachesBuilt

bool criticalSharedRelcachesBuilt