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

Go to the source code of this file.

Typedefs

typedef struct RelationDataRelation
 
typedef RelationRelationPtr
 
typedef enum IndexAttrBitmapKind IndexAttrBitmapKind
 

Enumerations

enum  IndexAttrBitmapKind { INDEX_ATTR_BITMAP_ALL, INDEX_ATTR_BITMAP_KEY, INDEX_ATTR_BITMAP_PRIMARY_KEY, INDEX_ATTR_BITMAP_IDENTITY_KEY }
 

Functions

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

Variables

bool criticalRelcachesBuilt
 
bool criticalSharedRelcachesBuilt
 

Typedef Documentation

Definition at line 21 of file relcache.h.

Definition at line 29 of file relcache.h.

Enumeration Type Documentation

Enumerator
INDEX_ATTR_BITMAP_ALL 
INDEX_ATTR_BITMAP_KEY 
INDEX_ATTR_BITMAP_PRIMARY_KEY 
INDEX_ATTR_BITMAP_IDENTITY_KEY 

Definition at line 48 of file relcache.h.

Function Documentation

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

Definition at line 3066 of file relcache.c.

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

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

Definition at line 2915 of file relcache.c.

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

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

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

Definition at line 5155 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(), errtablecolname(), and errtableconstraint().

5156 {
5160 
5161  return 0; /* return value does not matter */
5162 }
#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:3006
#define RelationGetRelationName(relation)
Definition: rel.h:433
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
#define RelationGetNamespace(relation)
Definition: rel.h:440
int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5172 of file relcache.c.

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

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

5173 {
5174  TupleDesc reldesc = RelationGetDescr(rel);
5175  const char *colname;
5176 
5177  /* Use reldesc if it's a user attribute, else consult the catalogs */
5178  if (attnum > 0 && attnum <= reldesc->natts)
5179  colname = NameStr(reldesc->attrs[attnum - 1]->attname);
5180  else
5181  colname = get_relid_attribute_name(RelationGetRelid(rel), attnum);
5182 
5183  return errtablecolname(rel, colname);
5184 }
#define RelationGetDescr(relation)
Definition: rel.h:425
Form_pg_attribute * attrs
Definition: tupdesc.h:74
char * get_relid_attribute_name(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:801
#define NameStr(name)
Definition: c.h:499
#define RelationGetRelid(relation)
Definition: rel.h:413
int errtablecolname(Relation rel, const char *colname)
Definition: relcache.c:5196
int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5196 of file relcache.c.

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

Referenced by errtablecol().

5197 {
5198  errtable(rel);
5200 
5201  return 0; /* return value does not matter */
5202 }
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:67
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
int errtable(Relation rel)
Definition: relcache.c:5155
int errtableconstraint ( Relation  rel,
const char *  conname 
)

Definition at line 5209 of file relcache.c.

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

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

5210 {
5211  errtable(rel);
5213 
5214  return 0; /* return value does not matter */
5215 }
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:69
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
int errtable(Relation rel)
Definition: relcache.c:5155
struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

Definition at line 5084 of file relcache.c.

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

Referenced by CheckCmdReplicaIdentity().

5085 {
5086  List *puboids;
5087  ListCell *lc;
5088  MemoryContext oldcxt;
5089  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5090 
5091  if (relation->rd_pubactions)
5092  return memcpy(pubactions, relation->rd_pubactions,
5093  sizeof(PublicationActions));
5094 
5095  /* Fetch the publication membership info. */
5096  puboids = GetRelationPublications(RelationGetRelid(relation));
5097  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5098 
5099  foreach(lc, puboids)
5100  {
5101  Oid pubid = lfirst_oid(lc);
5102  HeapTuple tup;
5103  Form_pg_publication pubform;
5104 
5106 
5107  if (!HeapTupleIsValid(tup))
5108  elog(ERROR, "cache lookup failed for publication %u", pubid);
5109 
5110  pubform = (Form_pg_publication) GETSTRUCT(tup);
5111 
5112  pubactions->pubinsert |= pubform->pubinsert;
5113  pubactions->pubupdate |= pubform->pubupdate;
5114  pubactions->pubdelete |= pubform->pubdelete;
5115 
5116  ReleaseSysCache(tup);
5117 
5118  /*
5119  * If we know everything is replicated, there is no point to check
5120  * for other publications.
5121  */
5122  if (pubactions->pubinsert && pubactions->pubupdate &&
5123  pubactions->pubdelete)
5124  break;
5125  }
5126 
5127  if (relation->rd_pubactions)
5128  {
5129  pfree(relation->rd_pubactions);
5130  relation->rd_pubactions = NULL;
5131  }
5132 
5133  /* Now save copy of the actions in the relcache entry. */
5135  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5136  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5137  MemoryContextSwitchTo(oldcxt);
5138 
5139  return pubactions;
5140 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
PublicationActions * rd_pubactions
Definition: rel.h:145
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned int Oid
Definition: postgres_ext.h:31
List * list_concat_unique_oid(List *list1, List *list2)
Definition: list.c:1082
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
List * GetRelationPublications(Oid relid)
void pfree(void *pointer)
Definition: mcxt.c:950
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
void * palloc0(Size size)
Definition: mcxt.c:878
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1081
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
List * GetAllTablesPublications(void)
void * palloc(Size size)
Definition: mcxt.c:849
#define elog
Definition: elog.h:219
FormData_pg_publication * Form_pg_publication
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:413
#define lfirst_oid(lc)
Definition: pg_list.h:108
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
Relation RelationBuildLocalRelation ( const char *  relname,
Oid  relnamespace,
TupleDesc  tupDesc,
Oid  relid,
Oid  relfilenode,
Oid  reltablespace,
bool  shared_relation,
bool  mapped_relation,
char  relpersistence,
char  relkind 
)

Definition at line 3178 of file relcache.c.

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

Referenced by heap_create().

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

Definition at line 5978 of file relcache.c.

References LWLockRelease().

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

5979 {
5980  LWLockRelease(RelCacheInitLock);
5981 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
void RelationCacheInitFilePreInvalidate ( void  )

Definition at line 5952 of file relcache.c.

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

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

5953 {
5954  char initfilename[MAXPGPATH];
5955 
5956  snprintf(initfilename, sizeof(initfilename), "%s/%s",
5958 
5959  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
5960 
5961  if (unlink(initfilename) < 0)
5962  {
5963  /*
5964  * The file might not be there if no backend has been started since
5965  * the last removal. But complain about failures other than ENOENT.
5966  * Fortunately, it's not too late to abort the transaction if we can't
5967  * get rid of the would-be-obsolete init file.
5968  */
5969  if (errno != ENOENT)
5970  ereport(ERROR,
5972  errmsg("could not remove cache file \"%s\": %m",
5973  initfilename)));
5974  }
5975 }
#define RELCACHE_INIT_FILENAME
Definition: relcache.c:92
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define ERROR
Definition: elog.h:43
#define MAXPGPATH
int errcode_for_file_access(void)
Definition: elog.c:598
int unlink(const char *filename)
#define ereport(elevel, rest)
Definition: elog.h:122
char * DatabasePath
Definition: globals.c:84
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
int errmsg(const char *fmt,...)
Definition: elog.c:797
void RelationCacheInitFileRemove ( void  )

Definition at line 5993 of file relcache.c.

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

Referenced by StartupXLOG().

5994 {
5995  const char *tblspcdir = "pg_tblspc";
5996  DIR *dir;
5997  struct dirent *de;
5998  char path[MAXPGPATH];
5999 
6000  /*
6001  * We zap the shared cache file too. In theory it can't get out of sync
6002  * enough to be a problem, but in data-corruption cases, who knows ...
6003  */
6004  snprintf(path, sizeof(path), "global/%s",
6006  unlink_initfile(path);
6007 
6008  /* Scan everything in the default tablespace */
6010 
6011  /* Scan the tablespace link directory to find non-default tablespaces */
6012  dir = AllocateDir(tblspcdir);
6013  if (dir == NULL)
6014  {
6015  elog(LOG, "could not open tablespace link directory \"%s\": %m",
6016  tblspcdir);
6017  return;
6018  }
6019 
6020  while ((de = ReadDir(dir, tblspcdir)) != NULL)
6021  {
6022  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6023  {
6024  /* Scan the tablespace dir for per-database dirs */
6025  snprintf(path, sizeof(path), "%s/%s/%s",
6026  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6028  }
6029  }
6030 
6031  FreeDir(dir);
6032 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6036
#define RELCACHE_INIT_FILENAME
Definition: relcache.c:92
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2298
static void unlink_initfile(const char *initfilename)
Definition: relcache.c:6066
#define NULL
Definition: c.h:229
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2364
#define TABLESPACE_VERSION_DIRECTORY
Definition: catalog.h:26
char d_name[MAX_PATH]
Definition: dirent.h:14
#define elog
Definition: elog.h:219
int FreeDir(DIR *dir)
Definition: fd.c:2407
void RelationCacheInitialize ( void  )

Definition at line 3526 of file relcache.c.

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

Referenced by InitPostgres().

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

Definition at line 3563 of file relcache.c.

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

Referenced by InitPostgres().

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

Definition at line 3622 of file relcache.c.

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

Referenced by InitPostgres().

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

Definition at line 2755 of file relcache.c.

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

Referenced by InvalidateSystemCaches(), and LocalExecuteInvalidationMessage().

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

Definition at line 2711 of file relcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

2712 {
2713  Relation relation;
2714 
2715  RelationIdCacheLookup(relationId, relation);
2716 
2717  if (PointerIsValid(relation))
2718  {
2720  RelationFlushRelation(relation);
2721  }
2722 }
static long relcacheInvalsReceived
Definition: relcache.c:142
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:201
static void RelationFlushRelation(Relation relation)
Definition: relcache.c:2643
#define PointerIsValid(pointer)
Definition: c.h:526
void RelationClose ( Relation  relation)

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

2156 {
2157  /* Note: no locking manipulations needed */
2159 
2160 #ifdef RELCACHE_FORCE_RELEASE
2161  if (RelationHasReferenceCountZero(relation) &&
2162  relation->rd_createSubid == InvalidSubTransactionId &&
2164  RelationClearRelation(relation, false);
2165 #endif
2166 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2387
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:110
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2135
SubTransactionId rd_createSubid
Definition: rel.h:109
#define InvalidSubTransactionId
Definition: c.h:403
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:397
void RelationCloseSmgrByOid ( Oid  relationId)

Definition at line 2858 of file relcache.c.

References PointerIsValid, RelationCloseSmgr, and RelationIdCacheLookup.

Referenced by swap_relation_files().

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

Definition at line 2679 of file relcache.c.

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

Referenced by heap_drop_with_catalog(), and index_drop().

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

Definition at line 4966 of file relcache.c.

References AccessShareLock, Anum_pg_constraint_conexclop, Anum_pg_constraint_conrelid, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, BTEqualStrategyNumber, CONSTRAINT_EXCLUSION, ConstraintRelationId, ConstraintRelidIndexId, DatumGetArrayTypeP, elog, ERROR, fastgetattr, get_op_opfamily_strategy(), get_opcode(), GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, i, InvalidStrategy, MemoryContextSwitchTo(), NULL, ObjectIdGetDatum, OIDOID, palloc(), RelationData::rd_att, RelationData::rd_exclops, RelationData::rd_exclprocs, RelationData::rd_exclstrats, RelationData::rd_index, RelationData::rd_indexcxt, RelationData::rd_opfamily, RelationData::rd_rel, RelationGetRelationName, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), and val.

Referenced by BuildIndexInfo(), and CheckIndexCompatible().

4970 {
4971  int ncols = indexRelation->rd_rel->relnatts;
4972  Oid *ops;
4973  Oid *funcs;
4974  uint16 *strats;
4975  Relation conrel;
4976  SysScanDesc conscan;
4977  ScanKeyData skey[1];
4978  HeapTuple htup;
4979  bool found;
4980  MemoryContext oldcxt;
4981  int i;
4982 
4983  /* Allocate result space in caller context */
4984  *operators = ops = (Oid *) palloc(sizeof(Oid) * ncols);
4985  *procs = funcs = (Oid *) palloc(sizeof(Oid) * ncols);
4986  *strategies = strats = (uint16 *) palloc(sizeof(uint16) * ncols);
4987 
4988  /* Quick exit if we have the data cached already */
4989  if (indexRelation->rd_exclstrats != NULL)
4990  {
4991  memcpy(ops, indexRelation->rd_exclops, sizeof(Oid) * ncols);
4992  memcpy(funcs, indexRelation->rd_exclprocs, sizeof(Oid) * ncols);
4993  memcpy(strats, indexRelation->rd_exclstrats, sizeof(uint16) * ncols);
4994  return;
4995  }
4996 
4997  /*
4998  * Search pg_constraint for the constraint associated with the index. To
4999  * make this not too painfully slow, we use the index on conrelid; that
5000  * will hold the parent relation's OID not the index's own OID.
5001  */
5002  ScanKeyInit(&skey[0],
5004  BTEqualStrategyNumber, F_OIDEQ,
5005  ObjectIdGetDatum(indexRelation->rd_index->indrelid));
5006 
5008  conscan = systable_beginscan(conrel, ConstraintRelidIndexId, true,
5009  NULL, 1, skey);
5010  found = false;
5011 
5012  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
5013  {
5015  Datum val;
5016  bool isnull;
5017  ArrayType *arr;
5018  int nelem;
5019 
5020  /* We want the exclusion constraint owning the index */
5021  if (conform->contype != CONSTRAINT_EXCLUSION ||
5022  conform->conindid != RelationGetRelid(indexRelation))
5023  continue;
5024 
5025  /* There should be only one */
5026  if (found)
5027  elog(ERROR, "unexpected exclusion constraint record found for rel %s",
5028  RelationGetRelationName(indexRelation));
5029  found = true;
5030 
5031  /* Extract the operator OIDS from conexclop */
5032  val = fastgetattr(htup,
5034  conrel->rd_att, &isnull);
5035  if (isnull)
5036  elog(ERROR, "null conexclop for rel %s",
5037  RelationGetRelationName(indexRelation));
5038 
5039  arr = DatumGetArrayTypeP(val); /* ensure not toasted */
5040  nelem = ARR_DIMS(arr)[0];
5041  if (ARR_NDIM(arr) != 1 ||
5042  nelem != ncols ||
5043  ARR_HASNULL(arr) ||
5044  ARR_ELEMTYPE(arr) != OIDOID)
5045  elog(ERROR, "conexclop is not a 1-D Oid array");
5046 
5047  memcpy(ops, ARR_DATA_PTR(arr), sizeof(Oid) * ncols);
5048  }
5049 
5050  systable_endscan(conscan);
5051  heap_close(conrel, AccessShareLock);
5052 
5053  if (!found)
5054  elog(ERROR, "exclusion constraint record missing for rel %s",
5055  RelationGetRelationName(indexRelation));
5056 
5057  /* We need the func OIDs and strategy numbers too */
5058  for (i = 0; i < ncols; i++)
5059  {
5060  funcs[i] = get_opcode(ops[i]);
5061  strats[i] = get_op_opfamily_strategy(ops[i],
5062  indexRelation->rd_opfamily[i]);
5063  /* shouldn't fail, since it was checked at index creation */
5064  if (strats[i] == InvalidStrategy)
5065  elog(ERROR, "could not find strategy for operator %u in family %u",
5066  ops[i], indexRelation->rd_opfamily[i]);
5067  }
5068 
5069  /* Save a copy of the results in the relcache entry. */
5070  oldcxt = MemoryContextSwitchTo(indexRelation->rd_indexcxt);
5071  indexRelation->rd_exclops = (Oid *) palloc(sizeof(Oid) * ncols);
5072  indexRelation->rd_exclprocs = (Oid *) palloc(sizeof(Oid) * ncols);
5073  indexRelation->rd_exclstrats = (uint16 *) palloc(sizeof(uint16) * ncols);
5074  memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * ncols);
5075  memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * ncols);
5076  memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * ncols);
5077  MemoryContextSwitchTo(oldcxt);
5078 }
#define InvalidStrategy
Definition: stratnum.h:24
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:719
#define OIDOID
Definition: pg_type.h:328
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
uint16 * rd_exclstrats
Definition: rel.h:187
#define AccessShareLock
Definition: lockdefs.h:36
#define CONSTRAINT_EXCLUSION
#define heap_close(r, l)
Definition: heapam.h:97
Oid * rd_exclprocs
Definition: rel.h:186
Form_pg_class rd_rel
Definition: rel.h:113
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
Form_pg_index rd_index
Definition: rel.h:155
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
unsigned short uint16
Definition: c.h:267
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:275
#define ARR_DATA_PTR(a)
Definition: array.h:303
#define RelationGetRelationName(relation)
Definition: rel.h:433
#define ARR_HASNULL(a)
Definition: array.h:272
Oid * rd_opfamily
Definition: rel.h:178
Oid * rd_exclops
Definition: rel.h:185
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
TupleDesc rd_att
Definition: rel.h:114
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1062
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define ARR_NDIM(a)
Definition: array.h:271
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition: lsyscache.c:80
void * palloc(Size size)
Definition: mcxt.c:849
MemoryContext rd_indexcxt
Definition: rel.h:175
int i
#define Anum_pg_constraint_conrelid
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define ConstraintRelationId
Definition: pg_constraint.h:29
#define elog
Definition: elog.h:219
#define ARR_ELEMTYPE(a)
Definition: array.h:273
#define RelationGetRelid(relation)
Definition: rel.h:413
long val
Definition: informix.c:689
#define Anum_pg_constraint_conexclop
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define ConstraintRelidIndexId
Definition: indexing.h:126
#define DatumGetArrayTypeP(X)
Definition: array.h:242
List* RelationGetFKeyList ( Relation  relation)

Definition at line 4173 of file relcache.c.

References AccessShareLock, Anum_pg_constraint_confkey, Anum_pg_constraint_conkey, Anum_pg_constraint_conpfeqop, Anum_pg_constraint_conrelid, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, BTEqualStrategyNumber, CacheMemoryContext, ForeignKeyCacheInfo::confkey, ForeignKeyCacheInfo::confrelid, ForeignKeyCacheInfo::conkey, ForeignKeyCacheInfo::conpfeqop, ForeignKeyCacheInfo::conrelid, CONSTRAINT_FOREIGN, ConstraintRelationId, ConstraintRelidIndexId, copyObject(), DatumGetArrayTypeP, elog, ERROR, fastgetattr, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, INDEX_MAX_KEYS, INT2OID, lappend(), list_free_deep(), makeNode, MemoryContextSwitchTo(), NIL, ForeignKeyCacheInfo::nkeys, NULL, ObjectIdGetDatum, OIDOID, RelationData::rd_att, RelationData::rd_fkeylist, RelationData::rd_fkeyvalid, RelationData::rd_rel, RelationGetRelationName, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by get_relation_foreign_keys().

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

Definition at line 4759 of file relcache.c.

References AccessShareLock, bms_add_member(), bms_copy(), bms_free(), BuildIndexInfo(), CacheMemoryContext, elog, equal(), ERROR, FirstLowInvalidHeapAttributeNumber, i, IndexInfo::ii_Expressions, IndexInfo::ii_KeyAttrNumbers, IndexInfo::ii_NumIndexAttrs, IndexInfo::ii_Predicate, IndexInfo::ii_Unique, INDEX_ATTR_BITMAP_ALL, INDEX_ATTR_BITMAP_IDENTITY_KEY, INDEX_ATTR_BITMAP_KEY, INDEX_ATTR_BITMAP_PRIMARY_KEY, index_close(), index_open(), lfirst_oid, list_free(), MemoryContextSwitchTo(), NIL, NULL, pull_varattnos(), RelationData::rd_idattr, RelationData::rd_indexattr, RelationData::rd_keyattr, RelationData::rd_pkattr, RelationData::rd_pkindex, RelationData::rd_replidindex, RelationGetForm, and RelationGetIndexList().

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

4760 {
4761  Bitmapset *indexattrs; /* indexed columns */
4762  Bitmapset *uindexattrs; /* columns in unique indexes */
4763  Bitmapset *pkindexattrs; /* columns in the primary index */
4764  Bitmapset *idindexattrs; /* columns in the replica identity */
4765  List *indexoidlist;
4766  List *newindexoidlist;
4767  Oid relpkindex;
4768  Oid relreplindex;
4769  ListCell *l;
4770  MemoryContext oldcxt;
4771 
4772  /* Quick exit if we already computed the result. */
4773  if (relation->rd_indexattr != NULL)
4774  {
4775  switch (attrKind)
4776  {
4777  case INDEX_ATTR_BITMAP_ALL:
4778  return bms_copy(relation->rd_indexattr);
4779  case INDEX_ATTR_BITMAP_KEY:
4780  return bms_copy(relation->rd_keyattr);
4782  return bms_copy(relation->rd_pkattr);
4784  return bms_copy(relation->rd_idattr);
4785  default:
4786  elog(ERROR, "unknown attrKind %u", attrKind);
4787  }
4788  }
4789 
4790  /* Fast path if definitely no indexes */
4791  if (!RelationGetForm(relation)->relhasindex)
4792  return NULL;
4793 
4794  /*
4795  * Get cached list of index OIDs. If we have to start over, we do so here.
4796  */
4797 restart:
4798  indexoidlist = RelationGetIndexList(relation);
4799 
4800  /* Fall out if no indexes (but relhasindex was set) */
4801  if (indexoidlist == NIL)
4802  return NULL;
4803 
4804  /*
4805  * Copy the rd_pkindex and rd_replidindex values computed by
4806  * RelationGetIndexList before proceeding. This is needed because a
4807  * relcache flush could occur inside index_open below, resetting the
4808  * fields managed by RelationGetIndexList. We need to do the work with
4809  * stable values of these fields.
4810  */
4811  relpkindex = relation->rd_pkindex;
4812  relreplindex = relation->rd_replidindex;
4813 
4814  /*
4815  * For each index, add referenced attributes to indexattrs.
4816  *
4817  * Note: we consider all indexes returned by RelationGetIndexList, even if
4818  * they are not indisready or indisvalid. This is important because an
4819  * index for which CREATE INDEX CONCURRENTLY has just started must be
4820  * included in HOT-safety decisions (see README.HOT). If a DROP INDEX
4821  * CONCURRENTLY is far enough along that we should ignore the index, it
4822  * won't be returned at all by RelationGetIndexList.
4823  */
4824  indexattrs = NULL;
4825  uindexattrs = NULL;
4826  pkindexattrs = NULL;
4827  idindexattrs = NULL;
4828  foreach(l, indexoidlist)
4829  {
4830  Oid indexOid = lfirst_oid(l);
4831  Relation indexDesc;
4832  IndexInfo *indexInfo;
4833  int i;
4834  bool isKey; /* candidate key */
4835  bool isPK; /* primary key */
4836  bool isIDKey; /* replica identity index */
4837 
4838  indexDesc = index_open(indexOid, AccessShareLock);
4839 
4840  /* Extract index key information from the index's pg_index row */
4841  indexInfo = BuildIndexInfo(indexDesc);
4842 
4843  /* Can this index be referenced by a foreign key? */
4844  isKey = indexInfo->ii_Unique &&
4845  indexInfo->ii_Expressions == NIL &&
4846  indexInfo->ii_Predicate == NIL;
4847 
4848  /* Is this a primary key? */
4849  isPK = (indexOid == relpkindex);
4850 
4851  /* Is this index the configured (or default) replica identity? */
4852  isIDKey = (indexOid == relreplindex);
4853 
4854  /* Collect simple attribute references */
4855  for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
4856  {
4857  int attrnum = indexInfo->ii_KeyAttrNumbers[i];
4858 
4859  if (attrnum != 0)
4860  {
4861  indexattrs = bms_add_member(indexattrs,
4863 
4864  if (isKey)
4865  uindexattrs = bms_add_member(uindexattrs,
4867 
4868  if (isPK)
4869  pkindexattrs = bms_add_member(pkindexattrs,
4871 
4872  if (isIDKey)
4873  idindexattrs = bms_add_member(idindexattrs,
4875  }
4876  }
4877 
4878  /* Collect all attributes used in expressions, too */
4879  pull_varattnos((Node *) indexInfo->ii_Expressions, 1, &indexattrs);
4880 
4881  /* Collect all attributes in the index predicate, too */
4882  pull_varattnos((Node *) indexInfo->ii_Predicate, 1, &indexattrs);
4883 
4884  index_close(indexDesc, AccessShareLock);
4885  }
4886 
4887  /*
4888  * During one of the index_opens in the above loop, we might have received
4889  * a relcache flush event on this relcache entry, which might have been
4890  * signaling a change in the rel's index list. If so, we'd better start
4891  * over to ensure we deliver up-to-date attribute bitmaps.
4892  */
4893  newindexoidlist = RelationGetIndexList(relation);
4894  if (equal(indexoidlist, newindexoidlist) &&
4895  relpkindex == relation->rd_pkindex &&
4896  relreplindex == relation->rd_replidindex)
4897  {
4898  /* Still the same index set, so proceed */
4899  list_free(newindexoidlist);
4900  list_free(indexoidlist);
4901  }
4902  else
4903  {
4904  /* Gotta do it over ... might as well not leak memory */
4905  list_free(newindexoidlist);
4906  list_free(indexoidlist);
4907  bms_free(uindexattrs);
4908  bms_free(pkindexattrs);
4909  bms_free(idindexattrs);
4910  bms_free(indexattrs);
4911 
4912  goto restart;
4913  }
4914 
4915  /* Don't leak the old values of these bitmaps, if any */
4916  bms_free(relation->rd_indexattr);
4917  relation->rd_indexattr = NULL;
4918  bms_free(relation->rd_keyattr);
4919  relation->rd_keyattr = NULL;
4920  bms_free(relation->rd_pkattr);
4921  relation->rd_pkattr = NULL;
4922  bms_free(relation->rd_idattr);
4923  relation->rd_idattr = NULL;
4924 
4925  /*
4926  * Now save copies of the bitmaps in the relcache entry. We intentionally
4927  * set rd_indexattr last, because that's the one that signals validity of
4928  * the values; if we run out of memory before making that copy, we won't
4929  * leave the relcache entry looking like the other ones are valid but
4930  * empty.
4931  */
4933  relation->rd_keyattr = bms_copy(uindexattrs);
4934  relation->rd_pkattr = bms_copy(pkindexattrs);
4935  relation->rd_idattr = bms_copy(idindexattrs);
4936  relation->rd_indexattr = bms_copy(indexattrs);
4937  MemoryContextSwitchTo(oldcxt);
4938 
4939  /* We return our original working copy for caller to play with */
4940  switch (attrKind)
4941  {
4942  case INDEX_ATTR_BITMAP_ALL:
4943  return indexattrs;
4944  case INDEX_ATTR_BITMAP_KEY:
4945  return uindexattrs;
4947  return bms_copy(relation->rd_pkattr);
4949  return idindexattrs;
4950  default:
4951  elog(ERROR, "unknown attrKind %u", attrKind);
4952  return NULL;
4953  }
4954 }
#define NIL
Definition: pg_list.h:69
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:110
List * ii_Predicate
Definition: execnodes.h:71
Bitmapset * rd_keyattr
Definition: rel.h:141
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2923
Oid rd_replidindex
Definition: rel.h:137
#define RelationGetForm(relation)
Definition: rel.h:407
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:518
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
IndexInfo * BuildIndexInfo(Relation index)
Definition: index.c:1639
unsigned int Oid
Definition: postgres_ext.h:31
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition: var.c:219
#define ERROR
Definition: elog.h:43
Oid rd_pkindex
Definition: rel.h:136
int ii_NumIndexAttrs
Definition: execnodes.h:67
Bitmapset * rd_idattr
Definition: rel.h:143
bool ii_Unique
Definition: execnodes.h:79
void bms_free(Bitmapset *a)
Definition: bitmapset.c:200
#define NULL
Definition: c.h:229
List * ii_Expressions
Definition: execnodes.h:69
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS]
Definition: execnodes.h:68
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:668
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4336
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:176
Bitmapset * rd_pkattr
Definition: rel.h:142
void list_free(List *list)
Definition: list.c:1133
int i
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
Bitmapset * rd_indexattr
Definition: rel.h:140
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:151
#define lfirst_oid(lc)
Definition: pg_list.h:108
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
List* RelationGetIndexExpressions ( Relation  relation)

Definition at line 4613 of file relcache.c.

References Anum_pg_index_indexprs, Assert, canonicalize_qual(), copyObject(), eval_const_expressions(), fix_opfuncids(), GetPgIndexDescriptor(), heap_attisnull(), heap_getattr, MemoryContextSwitchTo(), NIL, NULL, pfree(), RelationData::rd_indexcxt, RelationData::rd_indexprs, RelationData::rd_indextuple, stringToNode(), and TextDatumGetCString.

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

4614 {
4615  List *result;
4616  Datum exprsDatum;
4617  bool isnull;
4618  char *exprsString;
4619  MemoryContext oldcxt;
4620 
4621  /* Quick exit if we already computed the result. */
4622  if (relation->rd_indexprs)
4623  return (List *) copyObject(relation->rd_indexprs);
4624 
4625  /* Quick exit if there is nothing to do. */
4626  if (relation->rd_indextuple == NULL ||
4628  return NIL;
4629 
4630  /*
4631  * We build the tree we intend to return in the caller's context. After
4632  * successfully completing the work, we copy it into the relcache entry.
4633  * This avoids problems if we get some sort of error partway through.
4634  */
4635  exprsDatum = heap_getattr(relation->rd_indextuple,
4638  &isnull);
4639  Assert(!isnull);
4640  exprsString = TextDatumGetCString(exprsDatum);
4641  result = (List *) stringToNode(exprsString);
4642  pfree(exprsString);
4643 
4644  /*
4645  * Run the expressions through eval_const_expressions. This is not just an
4646  * optimization, but is necessary, because the planner will be comparing
4647  * them to similarly-processed qual clauses, and may fail to detect valid
4648  * matches without this. We don't bother with canonicalize_qual, however.
4649  */
4650  result = (List *) eval_const_expressions(NULL, (Node *) result);
4651 
4652  result = (List *) canonicalize_qual((Expr *) result);
4653 
4654  /* May as well fix opfuncids too */
4655  fix_opfuncids((Node *) result);
4656 
4657  /* Now save a copy of the completed tree in the relcache entry. */
4658  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4659  relation->rd_indexprs = (List *) copyObject(result);
4660  MemoryContextSwitchTo(oldcxt);
4661 
4662  return result;
4663 }
#define NIL
Definition: pg_list.h:69
void * stringToNode(char *str)
Definition: read.c:38
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1594
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
List * rd_indexprs
Definition: rel.h:183
Definition: nodes.h:518
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2366
struct HeapTupleData * rd_indextuple
Definition: rel.h:157
void * copyObject(const void *from)
Definition: copyfuncs.c:4592
void pfree(void *pointer)
Definition: mcxt.c:950
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:3989
bool heap_attisnull(HeapTuple tup, int attnum)
Definition: heaptuple.c:297
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:769
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
Expr * canonicalize_qual(Expr *qual)
Definition: prepqual.c:286
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
MemoryContext rd_indexcxt
Definition: rel.h:175
Definition: pg_list.h:45
#define Anum_pg_index_indexprs
Definition: pg_index.h:91
List* RelationGetIndexList ( Relation  relation)

Definition at line 4336 of file relcache.c.

References AccessShareLock, Anum_pg_index_indclass, Anum_pg_index_indpred, Anum_pg_index_indrelid, Assert, BTEqualStrategyNumber, CacheMemoryContext, DatumGetPointer, GetPgIndexDescriptor(), GETSTRUCT, heap_attisnull(), heap_close, heap_getattr, heap_open(), HeapTupleIsValid, IndexIndrelidIndexId, IndexIsLive, IndexIsValid, IndexRelationId, insert_ordered_oid(), InvalidOid, list_copy(), list_free(), MemoryContextSwitchTo(), NIL, NULL, ObjectIdAttributeNumber, ObjectIdGetDatum, OID_BTREE_OPS_OID, OidIsValid, RelationData::rd_indexlist, RelationData::rd_indexvalid, RelationData::rd_oidindex, RelationData::rd_pkindex, RelationData::rd_rel, RelationData::rd_replidindex, RelationGetRelid, REPLICA_IDENTITY_DEFAULT, REPLICA_IDENTITY_INDEX, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), and oidvector::values.

Referenced by AlterIndexNamespaces(), ATExecChangeOwner(), ATExecDropNotNull(), ATExecSetTableSpace(), calculate_indexes_size(), calculate_toast_table_size(), cluster(), ExecOpenIndices(), ExecRefreshMatView(), get_relation_info(), infer_arbiter_indexes(), mark_index_clustered(), refresh_by_match_merge(), reindex_relation(), relation_mark_replica_identity(), RelationGetIndexAttrBitmap(), RelationGetOidIndex(), RelationGetPrimaryKeyIndex(), RelationGetReplicaIndex(), relationHasPrimaryKey(), RelationHasUnloggedIndex(), RelationTruncateIndexes(), toast_open_indexes(), transformFkeyCheckAttrs(), transformFkeyGetPrimaryKey(), transformTableLikeClause(), triggered_change_notification(), and vac_open_indexes().

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

Definition at line 4676 of file relcache.c.

References Anum_pg_index_indpred, Assert, canonicalize_qual(), copyObject(), eval_const_expressions(), fix_opfuncids(), GetPgIndexDescriptor(), heap_attisnull(), heap_getattr, make_ands_implicit(), MemoryContextSwitchTo(), NIL, NULL, pfree(), RelationData::rd_indexcxt, RelationData::rd_indextuple, RelationData::rd_indpred, stringToNode(), and TextDatumGetCString.

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

4677 {
4678  List *result;
4679  Datum predDatum;
4680  bool isnull;
4681  char *predString;
4682  MemoryContext oldcxt;
4683 
4684  /* Quick exit if we already computed the result. */
4685  if (relation->rd_indpred)
4686  return (List *) copyObject(relation->rd_indpred);
4687 
4688  /* Quick exit if there is nothing to do. */
4689  if (relation->rd_indextuple == NULL ||
4691  return NIL;
4692 
4693  /*
4694  * We build the tree we intend to return in the caller's context. After
4695  * successfully completing the work, we copy it into the relcache entry.
4696  * This avoids problems if we get some sort of error partway through.
4697  */
4698  predDatum = heap_getattr(relation->rd_indextuple,
4701  &isnull);
4702  Assert(!isnull);
4703  predString = TextDatumGetCString(predDatum);
4704  result = (List *) stringToNode(predString);
4705  pfree(predString);
4706 
4707  /*
4708  * Run the expression through const-simplification and canonicalization.
4709  * This is not just an optimization, but is necessary, because the planner
4710  * will be comparing it to similarly-processed qual clauses, and may fail
4711  * to detect valid matches without this. This must match the processing
4712  * done to qual clauses in preprocess_expression()! (We can skip the
4713  * stuff involving subqueries, however, since we don't allow any in index
4714  * predicates.)
4715  */
4716  result = (List *) eval_const_expressions(NULL, (Node *) result);
4717 
4718  result = (List *) canonicalize_qual((Expr *) result);
4719 
4720  /* Also convert to implicit-AND format */
4721  result = make_ands_implicit((Expr *) result);
4722 
4723  /* May as well fix opfuncids too */
4724  fix_opfuncids((Node *) result);
4725 
4726  /* Now save a copy of the completed tree in the relcache entry. */
4727  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
4728  relation->rd_indpred = (List *) copyObject(result);
4729  MemoryContextSwitchTo(oldcxt);
4730 
4731  return result;
4732 }
#define NIL
Definition: pg_list.h:69
void * stringToNode(char *str)
Definition: read.c:38
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1594
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:518
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2366
struct HeapTupleData * rd_indextuple
Definition: rel.h:157
void * copyObject(const void *from)
Definition: copyfuncs.c:4592
void pfree(void *pointer)
Definition: mcxt.c:950
List * make_ands_implicit(Expr *clause)
Definition: clauses.c:377
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:3989
bool heap_attisnull(HeapTuple tup, int attnum)
Definition: heaptuple.c:297
List * rd_indpred
Definition: rel.h:184
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:769
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
Expr * canonicalize_qual(Expr *qual)
Definition: prepqual.c:286
#define Anum_pg_index_indpred
Definition: pg_index.h:92
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
MemoryContext rd_indexcxt
Definition: rel.h:175
Definition: pg_list.h:45
Oid RelationGetOidIndex ( Relation  relation)

Definition at line 4539 of file relcache.c.

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

Referenced by GetNewOid().

4540 {
4541  List *ilist;
4542 
4543  /*
4544  * If relation doesn't have OIDs at all, caller is probably confused. (We
4545  * could just silently return InvalidOid, but it seems better to throw an
4546  * assertion.)
4547  */
4548  Assert(relation->rd_rel->relhasoids);
4549 
4550  if (relation->rd_indexvalid == 0)
4551  {
4552  /* RelationGetIndexList does the heavy lifting. */
4553  ilist = RelationGetIndexList(relation);
4554  list_free(ilist);
4555  Assert(relation->rd_indexvalid != 0);
4556  }
4557 
4558  return relation->rd_oidindex;
4559 }
Form_pg_class rd_rel
Definition: rel.h:113
char rd_indexvalid
Definition: rel.h:93
Oid rd_oidindex
Definition: rel.h:135
#define Assert(condition)
Definition: c.h:675
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4336
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45
Oid RelationGetPrimaryKeyIndex ( Relation  relation)

Definition at line 4567 of file relcache.c.

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

Referenced by GetRelationIdentityOrPK().

4568 {
4569  List *ilist;
4570 
4571  if (relation->rd_indexvalid == 0)
4572  {
4573  /* RelationGetIndexList does the heavy lifting. */
4574  ilist = RelationGetIndexList(relation);
4575  list_free(ilist);
4576  Assert(relation->rd_indexvalid != 0);
4577  }
4578 
4579  return relation->rd_pkindex;
4580 }
Oid rd_pkindex
Definition: rel.h:136
char rd_indexvalid
Definition: rel.h:93
#define Assert(condition)
Definition: c.h:675
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4336
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45
Oid RelationGetReplicaIndex ( Relation  relation)

Definition at line 4588 of file relcache.c.

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

Referenced by build_replindex_scan_key(), CheckCmdReplicaIdentity(), ExtractReplicaIdentity(), and GetRelationIdentityOrPK().

4589 {
4590  List *ilist;
4591 
4592  if (relation->rd_indexvalid == 0)
4593  {
4594  /* RelationGetIndexList does the heavy lifting. */
4595  ilist = RelationGetIndexList(relation);
4596  list_free(ilist);
4597  Assert(relation->rd_indexvalid != 0);
4598  }
4599 
4600  return relation->rd_replidindex;
4601 }
Oid rd_replidindex
Definition: rel.h:137
char rd_indexvalid
Definition: rel.h:93
#define Assert(condition)
Definition: c.h:675
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4336
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45
Relation RelationIdGetRelation ( Oid  relationId)

Definition at line 2066 of file relcache.c.

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

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

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

Definition at line 5869 of file relcache.c.

References Assert, RelationSupportsSysCache(), and TriggerRelidNameIndexId.

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

5870 {
5871  if (relationId == TriggerRelidNameIndexId)
5872  {
5873  /* If this Assert fails, we don't need this special case anymore. */
5874  Assert(!RelationSupportsSysCache(relationId));
5875  return true;
5876  }
5877  return RelationSupportsSysCache(relationId);
5878 }
#define TriggerRelidNameIndexId
Definition: indexing.h:242
#define Assert(condition)
Definition: c.h:675
bool RelationSupportsSysCache(Oid relid)
Definition: syscache.c:1366
void RelationInitIndexAccessInfo ( Relation  relation)

Definition at line 1504 of file relcache.c.

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

Referenced by index_create(), and RelationBuildDesc().

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

Definition at line 4509 of file relcache.c.

References Assert, CacheMemoryContext, EOXactListAdd, InvalidOid, list_copy(), list_free(), MemoryContextSwitchTo(), RelationData::rd_indexlist, RelationData::rd_indexvalid, RelationData::rd_isnailed, RelationData::rd_oidindex, RelationData::rd_pkindex, and RelationData::rd_replidindex.

Referenced by reindex_relation().

4510 {
4511  MemoryContext oldcxt;
4512 
4513  Assert(relation->rd_isnailed);
4514  /* Copy the list into the cache context (could fail for lack of mem) */
4516  indexIds = list_copy(indexIds);
4517  MemoryContextSwitchTo(oldcxt);
4518  /* Okay to replace old list */
4519  list_free(relation->rd_indexlist);
4520  relation->rd_indexlist = indexIds;
4521  relation->rd_oidindex = oidIndex;
4522  /*
4523  * For the moment, assume the target rel hasn't got a pk or replica
4524  * index. We'll load them on demand in the API that wraps access to them.
4525  */
4526  relation->rd_pkindex = InvalidOid;
4527  relation->rd_replidindex = InvalidOid;
4528  relation->rd_indexvalid = 2; /* mark list as forced */
4529  /* Flag relation as needing eoxact cleanup (to reset the list) */
4530  EOXactListAdd(relation);
4531 }
#define EOXactListAdd(rel)
Definition: relcache.c:159
Oid rd_replidindex
Definition: rel.h:137
bool rd_isnailed
Definition: rel.h:91
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
List * list_copy(const List *oldlist)
Definition: list.c:1160
Oid rd_pkindex
Definition: rel.h:136
char rd_indexvalid
Definition: rel.h:93
Oid rd_oidindex
Definition: rel.h:135
List * rd_indexlist
Definition: rel.h:134
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:675
void list_free(List *list)
Definition: list.c:1133
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void RelationSetNewRelfilenode ( Relation  relation,
char  persistence,
TransactionId  freezeXid,
MultiXactId  minmulti 
)

Definition at line 3414 of file relcache.c.

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

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

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

Variable Documentation

bool criticalSharedRelcachesBuilt