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

Go to the source code of this file.

Typedefs

typedef struct RelationDataRelation
 
typedef RelationRelationPtr
 
typedef enum IndexAttrBitmapKind IndexAttrBitmapKind
 

Enumerations

enum  IndexAttrBitmapKind { INDEX_ATTR_BITMAP_ALL, INDEX_ATTR_BITMAP_KEY, INDEX_ATTR_BITMAP_PRIMARY_KEY, INDEX_ATTR_BITMAP_IDENTITY_KEY }
 

Functions

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

Variables

bool criticalRelcachesBuilt
 
bool criticalSharedRelcachesBuilt
 

Typedef Documentation

Definition at line 21 of file relcache.h.

Definition at line 29 of file relcache.h.

Enumeration Type Documentation

Enumerator
INDEX_ATTR_BITMAP_ALL 
INDEX_ATTR_BITMAP_KEY 
INDEX_ATTR_BITMAP_PRIMARY_KEY 
INDEX_ATTR_BITMAP_IDENTITY_KEY 

Definition at line 49 of file relcache.h.

Function Documentation

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

Definition at line 3075 of file relcache.c.

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

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

Definition at line 2924 of file relcache.c.

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

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

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

Definition at line 5255 of file relcache.c.

References err_generic_string(), get_namespace_name(), PG_DIAG_SCHEMA_NAME, PG_DIAG_TABLE_NAME, RelationGetNamespace, and RelationGetRelationName.

Referenced by ATPrepChangePersistence(), BuildRelationExtStatistics(), errtablecolname(), and errtableconstraint().

5256 {
5260 
5261  return 0; /* return value does not matter */
5262 }
#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:3033
#define RelationGetRelationName(relation)
Definition: rel.h:436
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
#define RelationGetNamespace(relation)
Definition: rel.h:443
int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5272 of file relcache.c.

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

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

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

Definition at line 5296 of file relcache.c.

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

Referenced by errtablecol().

5297 {
5298  errtable(rel);
5300 
5301  return 0; /* return value does not matter */
5302 }
#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:5255
int errtableconstraint ( Relation  rel,
const char *  conname 
)

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

5310 {
5311  errtable(rel);
5313 
5314  return 0; /* return value does not matter */
5315 }
#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:5255
struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

Definition at line 5184 of file relcache.c.

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

Referenced by CheckCmdReplicaIdentity().

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

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

Referenced by heap_create().

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

References LWLockRelease().

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

6085 {
6086  LWLockRelease(RelCacheInitLock);
6087 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
void RelationCacheInitFilePreInvalidate ( void  )

Definition at line 6058 of file relcache.c.

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

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

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

Definition at line 6099 of file relcache.c.

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

Referenced by StartupXLOG().

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

Definition at line 3539 of file relcache.c.

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

Referenced by InitPostgres().

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

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

3577 {
3578  MemoryContext oldcxt;
3579 
3580  /*
3581  * relation mapper needs initialized too
3582  */
3584 
3585  /*
3586  * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3587  * nothing.
3588  */
3590  return;
3591 
3592  /*
3593  * switch to cache memory context
3594  */
3596 
3597  /*
3598  * Try to load the shared relcache cache file. If unsuccessful, bootstrap
3599  * the cache with pre-made descriptors for the critical shared catalogs.
3600  */
3601  if (!load_relcache_init_file(true))
3602  {
3603  formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
3605  formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
3607  formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
3609  formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
3611  formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
3613 
3614 #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
3615  }
3616 
3617  MemoryContextSwitchTo(oldcxt);
3618 }
static const FormData_pg_attribute Desc_pg_auth_members[Natts_pg_auth_members]
Definition: relcache.c:106
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5373
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, bool hasoids, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1895
#define SubscriptionRelation_Rowtype_Id
void RelationMapInitializePhase2(void)
Definition: relmapper.c:582
#define Natts_pg_database
Definition: pg_database.h:63
static const FormData_pg_attribute Desc_pg_authid[Natts_pg_authid]
Definition: relcache.c:105
static const FormData_pg_attribute Desc_pg_subscription[Natts_pg_subscription]
Definition: relcache.c:109
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define Natts_pg_auth_members
#define SharedSecLabelRelation_Rowtype_Id
Definition: pg_shseclabel.h:22
#define Natts_pg_subscription
#define AuthIdRelation_Rowtype_Id
Definition: pg_authid.h:43
#define AuthMemRelation_Rowtype_Id
static const FormData_pg_attribute Desc_pg_database[Natts_pg_database]
Definition: relcache.c:104
#define Natts_pg_shseclabel
Definition: pg_shseclabel.h:41
static const FormData_pg_attribute Desc_pg_shseclabel[Natts_pg_shseclabel]
Definition: relcache.c:108
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:368
#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 3635 of file relcache.c.

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

Referenced by InitPostgres().

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

Definition at line 2764 of file relcache.c.

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

Referenced by InvalidateSystemCaches(), and LocalExecuteInvalidationMessage().

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

Definition at line 2720 of file relcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

2721 {
2722  Relation relation;
2723 
2724  RelationIdCacheLookup(relationId, relation);
2725 
2726  if (PointerIsValid(relation))
2727  {
2729  RelationFlushRelation(relation);
2730  }
2731 }
static long relcacheInvalsReceived
Definition: relcache.c:143
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:202
static void RelationFlushRelation(Relation relation)
Definition: relcache.c:2652
#define PointerIsValid(pointer)
Definition: c.h:520
void RelationClose ( Relation  relation)

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

2165 {
2166  /* Note: no locking manipulations needed */
2168 
2169 #ifdef RELCACHE_FORCE_RELEASE
2170  if (RelationHasReferenceCountZero(relation) &&
2171  relation->rd_createSubid == InvalidSubTransactionId &&
2173  RelationClearRelation(relation, false);
2174 #endif
2175 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2396
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:111
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2144
SubTransactionId rd_createSubid
Definition: rel.h:110
#define InvalidSubTransactionId
Definition: c.h:397
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:400
void RelationCloseSmgrByOid ( Oid  relationId)

Definition at line 2867 of file relcache.c.

References PointerIsValid, RelationCloseSmgr, and RelationIdCacheLookup.

Referenced by swap_relation_files().

2868 {
2869  Relation relation;
2870 
2871  RelationIdCacheLookup(relationId, relation);
2872 
2873  if (!PointerIsValid(relation))
2874  return; /* not in cache, nothing to do */
2875 
2876  RelationCloseSmgr(relation);
2877 }
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:202
#define RelationCloseSmgr(relation)
Definition: rel.h:472
#define PointerIsValid(pointer)
Definition: c.h:520
void RelationForgetRelation ( Oid  rid)

Definition at line 2688 of file relcache.c.

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

Referenced by heap_drop_with_catalog(), and index_drop().

2689 {
2690  Relation relation;
2691 
2692  RelationIdCacheLookup(rid, relation);
2693 
2694  if (!PointerIsValid(relation))
2695  return; /* not in cache, nothing to do */
2696 
2697  if (!RelationHasReferenceCountZero(relation))
2698  elog(ERROR, "relation %u is still open", rid);
2699 
2700  /* Unconditionally destroy the relcache entry */
2701  RelationClearRelation(relation, false);
2702 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2396
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:202
#define ERROR
Definition: elog.h:43
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:400
#define elog
Definition: elog.h:219
#define PointerIsValid(pointer)
Definition: c.h:520
void RelationGetExclusionInfo ( Relation  indexRelation,
Oid **  operators,
Oid **  procs,
uint16 **  strategies 
)

Definition at line 5066 of file relcache.c.

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

Referenced by BuildIndexInfo(), and CheckIndexCompatible().

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

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

Referenced by get_relation_foreign_keys().

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

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

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

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

Definition at line 4713 of file relcache.c.

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

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

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

Definition at line 4357 of file relcache.c.

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

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

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

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

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

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

Definition at line 4639 of file relcache.c.

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

Referenced by GetNewOid().

4640 {
4641  List *ilist;
4642 
4643  /*
4644  * If relation doesn't have OIDs at all, caller is probably confused. (We
4645  * could just silently return InvalidOid, but it seems better to throw an
4646  * assertion.)
4647  */
4648  Assert(relation->rd_rel->relhasoids);
4649 
4650  if (relation->rd_indexvalid == 0)
4651  {
4652  /* RelationGetIndexList does the heavy lifting. */
4653  ilist = RelationGetIndexList(relation);
4654  list_free(ilist);
4655  Assert(relation->rd_indexvalid != 0);
4656  }
4657 
4658  return relation->rd_oidindex;
4659 }
Form_pg_class rd_rel
Definition: rel.h:114
char rd_indexvalid
Definition: rel.h:93
Oid rd_oidindex
Definition: rel.h:136
#define Assert(condition)
Definition: c.h:664
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4357
void list_free(List *list)
Definition: list.c:1133
Definition: pg_list.h:45
Oid RelationGetPrimaryKeyIndex ( Relation  relation)

Definition at line 4667 of file relcache.c.

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

Referenced by GetRelationIdentityOrPK().

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

Definition at line 4688 of file relcache.c.

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

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

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

Definition at line 4497 of file relcache.c.

References AccessShareLock, Anum_pg_statistic_ext_stxrelid, BTEqualStrategyNumber, CacheMemoryContext, heap_close, heap_open(), HeapTupleGetOid, HeapTupleIsValid, insert_ordered_oid(), list_copy(), list_free(), MemoryContextSwitchTo(), NIL, ObjectIdGetDatum, RelationData::rd_statlist, RelationData::rd_statvalid, RelationGetRelid, ScanKeyInit(), StatisticExtRelationId, StatisticExtRelidIndexId, systable_beginscan(), systable_endscan(), and systable_getnext().

Referenced by get_relation_statistics().

4498 {
4499  Relation indrel;
4500  SysScanDesc indscan;
4501  ScanKeyData skey;
4502  HeapTuple htup;
4503  List *result;
4504  List *oldlist;
4505  MemoryContext oldcxt;
4506 
4507  /* Quick exit if we already computed the list. */
4508  if (relation->rd_statvalid != 0)
4509  return list_copy(relation->rd_statlist);
4510 
4511  /*
4512  * We build the list we intend to return (in the caller's context) while
4513  * doing the scan. After successfully completing the scan, we copy that
4514  * list into the relcache entry. This avoids cache-context memory leakage
4515  * if we get some sort of error partway through.
4516  */
4517  result = NIL;
4518 
4519  /*
4520  * Prepare to scan pg_statistic_ext for entries having stxrelid = this
4521  * rel.
4522  */
4523  ScanKeyInit(&skey,
4525  BTEqualStrategyNumber, F_OIDEQ,
4526  ObjectIdGetDatum(RelationGetRelid(relation)));
4527 
4529  indscan = systable_beginscan(indrel, StatisticExtRelidIndexId, true,
4530  NULL, 1, &skey);
4531 
4532  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4533  result = insert_ordered_oid(result, HeapTupleGetOid(htup));
4534 
4535  systable_endscan(indscan);
4536 
4537  heap_close(indrel, AccessShareLock);
4538 
4539  /* Now save a copy of the completed list in the relcache entry. */
4541  oldlist = relation->rd_statlist;
4542  relation->rd_statlist = list_copy(result);
4543 
4544  relation->rd_statvalid = true;
4545  MemoryContextSwitchTo(oldcxt);
4546 
4547  /* Don't leak the old list, if there is one */
4548  list_free(oldlist);
4549 
4550  return result;
4551 }
#define Anum_pg_statistic_ext_stxrelid
#define NIL
Definition: pg_list.h:69
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
static List * insert_ordered_oid(List *list, Oid datum)
Definition: relcache.c:4563
List * list_copy(const List *oldlist)
Definition: list.c:1160
#define heap_close(r, l)
Definition: heapam.h:97
#define StatisticExtRelidIndexId
Definition: indexing.h:190
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define StatisticExtRelationId
bool rd_statvalid
Definition: rel.h:95
void list_free(List *list)
Definition: list.c:1133
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
List * rd_statlist
Definition: rel.h:141
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:416
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
Relation RelationIdGetRelation ( Oid  relationId)

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

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

Definition at line 5975 of file relcache.c.

References Assert, RelationSupportsSysCache(), and TriggerRelidNameIndexId.

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

5976 {
5977  if (relationId == TriggerRelidNameIndexId)
5978  {
5979  /* If this Assert fails, we don't need this special case anymore. */
5980  Assert(!RelationSupportsSysCache(relationId));
5981  return true;
5982  }
5983  return RelationSupportsSysCache(relationId);
5984 }
#define TriggerRelidNameIndexId
Definition: indexing.h:249
#define Assert(condition)
Definition: c.h:664
bool RelationSupportsSysCache(Oid relid)
Definition: syscache.c:1469
void RelationInitIndexAccessInfo ( Relation  relation)

Definition at line 1513 of file relcache.c.

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

Referenced by index_create(), and RelationBuildDesc().

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

4609 {
4610  MemoryContext oldcxt;
4611 
4612  Assert(relation->rd_isnailed);
4613  /* Copy the list into the cache context (could fail for lack of mem) */
4615  indexIds = list_copy(indexIds);
4616  MemoryContextSwitchTo(oldcxt);
4617  /* Okay to replace old list */
4618  list_free(relation->rd_indexlist);
4619  relation->rd_indexlist = indexIds;
4620  relation->rd_oidindex = oidIndex;
4621 
4622  /*
4623  * For the moment, assume the target rel hasn't got a pk or replica index.
4624  * We'll load them on demand in the API that wraps access to them.
4625  */
4626  relation->rd_pkindex = InvalidOid;
4627  relation->rd_replidindex = InvalidOid;
4628  relation->rd_indexvalid = 2; /* mark list as forced */
4629  /* Flag relation as needing eoxact cleanup (to reset the list) */
4630  EOXactListAdd(relation);
4631 }
#define EOXactListAdd(rel)
Definition: relcache.c:160
Oid rd_replidindex
Definition: rel.h:138
bool rd_isnailed
Definition: rel.h:91
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
List * list_copy(const List *oldlist)
Definition: list.c:1160
Oid rd_pkindex
Definition: rel.h:137
char rd_indexvalid
Definition: rel.h:93
Oid rd_oidindex
Definition: rel.h:136
List * rd_indexlist
Definition: rel.h:135
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:664
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 3427 of file relcache.c.

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

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

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

Variable Documentation

bool criticalSharedRelcachesBuilt