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

Go to the source code of this file.

Macros

#define RELCACHE_INIT_FILENAME   "pg_internal.init"
 
#define AssertPendingSyncs_RelationCache()   do {} while (0)
 

Typedefs

typedef struct RelationDataRelation
 
typedef RelationRelationPtr
 
typedef enum IndexAttrBitmapKind IndexAttrBitmapKind
 

Enumerations

enum  IndexAttrBitmapKind {
  INDEX_ATTR_BITMAP_KEY , INDEX_ATTR_BITMAP_PRIMARY_KEY , INDEX_ATTR_BITMAP_IDENTITY_KEY , INDEX_ATTR_BITMAP_HOT_BLOCKING ,
  INDEX_ATTR_BITMAP_SUMMARIZED
}
 

Functions

Relation RelationIdGetRelation (Oid relationId)
 
void RelationClose (Relation relation)
 
ListRelationGetFKeyList (Relation relation)
 
ListRelationGetIndexList (Relation relation)
 
ListRelationGetStatExtList (Relation relation)
 
Oid RelationGetPrimaryKeyIndex (Relation relation)
 
Oid RelationGetReplicaIndex (Relation relation)
 
ListRelationGetIndexExpressions (Relation relation)
 
ListRelationGetDummyIndexExpressions (Relation relation)
 
ListRelationGetIndexPredicate (Relation relation)
 
DatumRelationGetIndexRawAttOptions (Relation indexrel)
 
bytea ** RelationGetIndexAttOptions (Relation relation, bool copy)
 
BitmapsetRelationGetIndexAttrBitmap (Relation relation, IndexAttrBitmapKind attrKind)
 
BitmapsetRelationGetIdentityKeyBitmap (Relation relation)
 
void RelationGetExclusionInfo (Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
 
void RelationInitIndexAccessInfo (Relation relation)
 
void RelationBuildPublicationDesc (Relation relation, struct PublicationDesc *pubdesc)
 
void RelationInitTableAccessMethod (Relation relation)
 
int errtable (Relation rel)
 
int errtablecol (Relation rel, int attnum)
 
int errtablecolname (Relation rel, const char *colname)
 
int errtableconstraint (Relation rel, const char *conname)
 
void RelationCacheInitialize (void)
 
void RelationCacheInitializePhase2 (void)
 
void RelationCacheInitializePhase3 (void)
 
Relation RelationBuildLocalRelation (const char *relname, Oid relnamespace, TupleDesc tupDesc, Oid relid, Oid accessmtd, RelFileNumber relfilenumber, Oid reltablespace, bool shared_relation, bool mapped_relation, char relpersistence, char relkind)
 
void RelationSetNewRelfilenumber (Relation relation, char persistence)
 
void RelationAssumeNewRelfilelocator (Relation relation)
 
void RelationForgetRelation (Oid rid)
 
void RelationCacheInvalidateEntry (Oid relationId)
 
void RelationCacheInvalidate (bool debug_discard)
 
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

PGDLLIMPORT bool criticalRelcachesBuilt
 
PGDLLIMPORT bool criticalSharedRelcachesBuilt
 

Macro Definition Documentation

◆ AssertPendingSyncs_RelationCache

#define AssertPendingSyncs_RelationCache ( )    do {} while (0)

Definition at line 138 of file relcache.h.

◆ RELCACHE_INIT_FILENAME

#define RELCACHE_INIT_FILENAME   "pg_internal.init"

Definition at line 25 of file relcache.h.

Typedef Documentation

◆ IndexAttrBitmapKind

◆ Relation

typedef struct RelationData* Relation

Definition at line 27 of file relcache.h.

◆ RelationPtr

Definition at line 35 of file relcache.h.

Enumeration Type Documentation

◆ IndexAttrBitmapKind

Enumerator
INDEX_ATTR_BITMAP_KEY 
INDEX_ATTR_BITMAP_PRIMARY_KEY 
INDEX_ATTR_BITMAP_IDENTITY_KEY 
INDEX_ATTR_BITMAP_HOT_BLOCKING 
INDEX_ATTR_BITMAP_SUMMARIZED 

Definition at line 60 of file relcache.h.

61 {
IndexAttrBitmapKind
Definition: relcache.h:61
@ INDEX_ATTR_BITMAP_KEY
Definition: relcache.h:62
@ INDEX_ATTR_BITMAP_HOT_BLOCKING
Definition: relcache.h:65
@ INDEX_ATTR_BITMAP_PRIMARY_KEY
Definition: relcache.h:63
@ INDEX_ATTR_BITMAP_SUMMARIZED
Definition: relcache.h:66
@ INDEX_ATTR_BITMAP_IDENTITY_KEY
Definition: relcache.h:64

Function Documentation

◆ AtEOSubXact_RelationCache()

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

Definition at line 3330 of file relcache.c.

3332 {
3333  HASH_SEQ_STATUS status;
3334  RelIdCacheEnt *idhentry;
3335  int i;
3336 
3337  /*
3338  * Forget in_progress_list. This is relevant when we're aborting due to
3339  * an error during RelationBuildDesc(). We don't commit subtransactions
3340  * during RelationBuildDesc().
3341  */
3342  Assert(in_progress_list_len == 0 || !isCommit);
3344 
3345  /*
3346  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3347  * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3348  * logic as in AtEOXact_RelationCache.
3349  */
3351  {
3352  hash_seq_init(&status, RelationIdCache);
3353  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3354  {
3355  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3356  mySubid, parentSubid);
3357  }
3358  }
3359  else
3360  {
3361  for (i = 0; i < eoxact_list_len; i++)
3362  {
3363  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3364  &eoxact_list[i],
3365  HASH_FIND,
3366  NULL);
3367  if (idhentry != NULL)
3368  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3369  mySubid, parentSubid);
3370  }
3371  }
3372 
3373  /* Don't reset the list; we still need more cleanup later */
3374 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:953
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1431
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1421
@ HASH_FIND
Definition: hsearch.h:113
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:185
static int in_progress_list_len
Definition: relcache.c:171
static void AtEOSubXact_cleanup(Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
Definition: relcache.c:3385
static int eoxact_list_len
Definition: relcache.c:186
static bool eoxact_list_overflowed
Definition: relcache.c:187
static HTAB * RelationIdCache
Definition: relcache.c:134
Relation reldesc
Definition: relcache.c:131

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

◆ AtEOXact_RelationCache()

void AtEOXact_RelationCache ( bool  isCommit)

Definition at line 3178 of file relcache.c.

3179 {
3180  HASH_SEQ_STATUS status;
3181  RelIdCacheEnt *idhentry;
3182  int i;
3183 
3184  /*
3185  * Forget in_progress_list. This is relevant when we're aborting due to
3186  * an error during RelationBuildDesc().
3187  */
3188  Assert(in_progress_list_len == 0 || !isCommit);
3190 
3191  /*
3192  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3193  * listed in it. Otherwise fall back on a hash_seq_search scan.
3194  *
3195  * For simplicity, eoxact_list[] entries are not deleted till end of
3196  * top-level transaction, even though we could remove them at
3197  * subtransaction end in some cases, or remove relations from the list if
3198  * they are cleared for other reasons. Therefore we should expect the
3199  * case that list entries are not found in the hashtable; if not, there's
3200  * nothing to do for them.
3201  */
3203  {
3204  hash_seq_init(&status, RelationIdCache);
3205  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3206  {
3207  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3208  }
3209  }
3210  else
3211  {
3212  for (i = 0; i < eoxact_list_len; i++)
3213  {
3214  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3215  &eoxact_list[i],
3216  HASH_FIND,
3217  NULL);
3218  if (idhentry != NULL)
3219  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3220  }
3221  }
3222 
3223  if (EOXactTupleDescArrayLen > 0)
3224  {
3225  Assert(EOXactTupleDescArray != NULL);
3226  for (i = 0; i < NextEOXactTupleDescNum; i++)
3229  EOXactTupleDescArray = NULL;
3230  }
3231 
3232  /* Now we're out of the transaction and can clear the lists */
3233  eoxact_list_len = 0;
3234  eoxact_list_overflowed = false;
3237 }
void pfree(void *pointer)
Definition: mcxt.c:1456
static int NextEOXactTupleDescNum
Definition: relcache.c:203
static int EOXactTupleDescArrayLen
Definition: relcache.c:204
static void AtEOXact_cleanup(Relation relation, bool isCommit)
Definition: relcache.c:3248
static TupleDesc * EOXactTupleDescArray
Definition: relcache.c:202
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:309

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

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

◆ errtable()

int errtable ( Relation  rel)

Definition at line 5935 of file relcache.c.

5936 {
5940 
5941  return 0; /* return value does not matter */
5942 }
int err_generic_string(int field, const char *str)
Definition: elog.c:1511
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3348
#define PG_DIAG_SCHEMA_NAME
Definition: postgres_ext.h:64
#define PG_DIAG_TABLE_NAME
Definition: postgres_ext.h:65
#define RelationGetRelationName(relation)
Definition: rel.h:538
#define RelationGetNamespace(relation)
Definition: rel.h:545

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

Referenced by ATPrepChangePersistence(), ATRewriteTable(), BuildRelationExtStatistics(), check_default_partition_contents(), errtablecolname(), errtableconstraint(), ExecFindPartition(), and ExecPartitionCheckEmitError().

◆ errtablecol()

int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5952 of file relcache.c.

5953 {
5954  TupleDesc reldesc = RelationGetDescr(rel);
5955  const char *colname;
5956 
5957  /* Use reldesc if it's a user attribute, else consult the catalogs */
5958  if (attnum > 0 && attnum <= reldesc->natts)
5959  colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
5960  else
5961  colname = get_attname(RelationGetRelid(rel), attnum, false);
5962 
5963  return errtablecolname(rel, colname);
5964 }
#define NameStr(name)
Definition: c.h:735
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:826
NameData attname
Definition: pg_attribute.h:41
int16 attnum
Definition: pg_attribute.h:74
#define RelationGetRelid(relation)
Definition: rel.h:504
#define RelationGetDescr(relation)
Definition: rel.h:530
int errtablecolname(Relation rel, const char *colname)
Definition: relcache.c:5976
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92

References attname, attnum, errtablecolname(), get_attname(), NameStr, RelationGetDescr, RelationGetRelid, and TupleDescAttr.

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

◆ errtablecolname()

int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5976 of file relcache.c.

5977 {
5978  errtable(rel);
5980 
5981  return 0; /* return value does not matter */
5982 }
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:66
int errtable(Relation rel)
Definition: relcache.c:5935

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

Referenced by errtablecol().

◆ errtableconstraint()

int errtableconstraint ( Relation  rel,
const char *  conname 
)

◆ RelationAssumeNewRelfilelocator()

void RelationAssumeNewRelfilelocator ( Relation  relation)

Definition at line 3909 of file relcache.c.

3910 {
3914 
3915  /* Flag relation as needing eoxact cleanup (to clear these fields) */
3916  EOXactListAdd(relation);
3917 }
#define InvalidSubTransactionId
Definition: c.h:647
#define EOXactListAdd(rel)
Definition: relcache.c:189
SubTransactionId rd_firstRelfilelocatorSubid
Definition: rel.h:106
SubTransactionId rd_newRelfilelocatorSubid
Definition: rel.h:104
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:780

References EOXactListAdd, GetCurrentSubTransactionId(), InvalidSubTransactionId, RelationData::rd_firstRelfilelocatorSubid, and RelationData::rd_newRelfilelocatorSubid.

Referenced by ATExecSetTableSpace(), reindex_index(), RelationSetNewRelfilenumber(), and swap_relation_files().

◆ RelationBuildLocalRelation()

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

Definition at line 3467 of file relcache.c.

3478 {
3479  Relation rel;
3480  MemoryContext oldcxt;
3481  int natts = tupDesc->natts;
3482  int i;
3483  bool has_not_null;
3484  bool nailit;
3485 
3486  Assert(natts >= 0);
3487 
3488  /*
3489  * check for creation of a rel that must be nailed in cache.
3490  *
3491  * XXX this list had better match the relations specially handled in
3492  * RelationCacheInitializePhase2/3.
3493  */
3494  switch (relid)
3495  {
3496  case DatabaseRelationId:
3497  case AuthIdRelationId:
3498  case AuthMemRelationId:
3499  case RelationRelationId:
3500  case AttributeRelationId:
3501  case ProcedureRelationId:
3502  case TypeRelationId:
3503  nailit = true;
3504  break;
3505  default:
3506  nailit = false;
3507  break;
3508  }
3509 
3510  /*
3511  * check that hardwired list of shared rels matches what's in the
3512  * bootstrap .bki file. If you get a failure here during initdb, you
3513  * probably need to fix IsSharedRelation() to match whatever you've done
3514  * to the set of shared relations.
3515  */
3516  if (shared_relation != IsSharedRelation(relid))
3517  elog(ERROR, "shared_relation flag for \"%s\" does not match IsSharedRelation(%u)",
3518  relname, relid);
3519 
3520  /* Shared relations had better be mapped, too */
3521  Assert(mapped_relation || !shared_relation);
3522 
3523  /*
3524  * switch to the cache context to create the relcache entry.
3525  */
3526  if (!CacheMemoryContext)
3528 
3530 
3531  /*
3532  * allocate a new relation descriptor and fill in basic state fields.
3533  */
3534  rel = (Relation) palloc0(sizeof(RelationData));
3535 
3536  /* make sure relation is marked as having no open file yet */
3537  rel->rd_smgr = NULL;
3538 
3539  /* mark it nailed if appropriate */
3540  rel->rd_isnailed = nailit;
3541 
3542  rel->rd_refcnt = nailit ? 1 : 0;
3543 
3544  /* it's being created in this transaction */
3549 
3550  /*
3551  * create a new tuple descriptor from the one passed in. We do this
3552  * partly to copy it into the cache context, and partly because the new
3553  * relation can't have any defaults or constraints yet; they have to be
3554  * added in later steps, because they require additions to multiple system
3555  * catalogs. We can copy attnotnull constraints here, however.
3556  */
3557  rel->rd_att = CreateTupleDescCopy(tupDesc);
3558  rel->rd_att->tdrefcount = 1; /* mark as refcounted */
3559  has_not_null = false;
3560  for (i = 0; i < natts; i++)
3561  {
3562  Form_pg_attribute satt = TupleDescAttr(tupDesc, i);
3563  Form_pg_attribute datt = TupleDescAttr(rel->rd_att, i);
3564 
3565  datt->attidentity = satt->attidentity;
3566  datt->attgenerated = satt->attgenerated;
3567  datt->attnotnull = satt->attnotnull;
3568  has_not_null |= satt->attnotnull;
3569  }
3570 
3571  if (has_not_null)
3572  {
3573  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
3574 
3575  constr->has_not_null = true;
3576  rel->rd_att->constr = constr;
3577  }
3578 
3579  /*
3580  * initialize relation tuple form (caller may add/override data later)
3581  */
3583 
3584  namestrcpy(&rel->rd_rel->relname, relname);
3585  rel->rd_rel->relnamespace = relnamespace;
3586 
3587  rel->rd_rel->relkind = relkind;
3588  rel->rd_rel->relnatts = natts;
3589  rel->rd_rel->reltype = InvalidOid;
3590  /* needed when bootstrapping: */
3591  rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;
3592 
3593  /* set up persistence and relcache fields dependent on it */
3594  rel->rd_rel->relpersistence = relpersistence;
3595  switch (relpersistence)
3596  {
3597  case RELPERSISTENCE_UNLOGGED:
3598  case RELPERSISTENCE_PERMANENT:
3600  rel->rd_islocaltemp = false;
3601  break;
3602  case RELPERSISTENCE_TEMP:
3603  Assert(isTempOrTempToastNamespace(relnamespace));
3605  rel->rd_islocaltemp = true;
3606  break;
3607  default:
3608  elog(ERROR, "invalid relpersistence: %c", relpersistence);
3609  break;
3610  }
3611 
3612  /* if it's a materialized view, it's not populated initially */
3613  if (relkind == RELKIND_MATVIEW)
3614  rel->rd_rel->relispopulated = false;
3615  else
3616  rel->rd_rel->relispopulated = true;
3617 
3618  /* set replica identity -- system catalogs and non-tables don't have one */
3619  if (!IsCatalogNamespace(relnamespace) &&
3620  (relkind == RELKIND_RELATION ||
3621  relkind == RELKIND_MATVIEW ||
3622  relkind == RELKIND_PARTITIONED_TABLE))
3623  rel->rd_rel->relreplident = REPLICA_IDENTITY_DEFAULT;
3624  else
3625  rel->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
3626 
3627  /*
3628  * Insert relation physical and logical identifiers (OIDs) into the right
3629  * places. For a mapped relation, we set relfilenumber to zero and rely
3630  * on RelationInitPhysicalAddr to consult the map.
3631  */
3632  rel->rd_rel->relisshared = shared_relation;
3633 
3634  RelationGetRelid(rel) = relid;
3635 
3636  for (i = 0; i < natts; i++)
3637  TupleDescAttr(rel->rd_att, i)->attrelid = relid;
3638 
3639  rel->rd_rel->reltablespace = reltablespace;
3640 
3641  if (mapped_relation)
3642  {
3643  rel->rd_rel->relfilenode = InvalidRelFileNumber;
3644  /* Add it to the active mapping information */
3645  RelationMapUpdateMap(relid, relfilenumber, shared_relation, true);
3646  }
3647  else
3648  rel->rd_rel->relfilenode = relfilenumber;
3649 
3650  RelationInitLockInfo(rel); /* see lmgr.c */
3651 
3653 
3654  rel->rd_rel->relam = accessmtd;
3655 
3656  /*
3657  * RelationInitTableAccessMethod will do syscache lookups, so we mustn't
3658  * run it in CacheMemoryContext. Fortunately, the remaining steps don't
3659  * require a long-lived current context.
3660  */
3661  MemoryContextSwitchTo(oldcxt);
3662 
3663  if (RELKIND_HAS_TABLE_AM(relkind) || relkind == RELKIND_SEQUENCE)
3665 
3666  /*
3667  * Okay to insert into the relcache hash table.
3668  *
3669  * Ordinarily, there should certainly not be an existing hash entry for
3670  * the same OID; but during bootstrap, when we create a "real" relcache
3671  * entry for one of the bootstrap relations, we'll be overwriting the
3672  * phony one created with formrdesc. So allow that to happen for nailed
3673  * rels.
3674  */
3675  RelationCacheInsert(rel, nailit);
3676 
3677  /*
3678  * Flag relation as needing eoxact cleanup (to clear rd_createSubid). We
3679  * can't do this before storing relid in it.
3680  */
3681  EOXactListAdd(rel);
3682 
3683  /* It's fully valid */
3684  rel->rd_isvalid = true;
3685 
3686  /*
3687  * Caller expects us to pin the returned entry.
3688  */
3690 
3691  return rel;
3692 }
#define BackendIdForTempRelations()
Definition: backendid.h:34
#define InvalidBackendId
Definition: backendid.h:23
bool IsCatalogNamespace(Oid namespaceId)
Definition: catalog.c:184
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:245
void CreateCacheMemoryContext(void)
Definition: catcache.c:614
#define ERROR
Definition: elog.h:39
void RelationInitLockInfo(Relation relation)
Definition: lmgr.c:72
void * palloc0(Size size)
Definition: mcxt.c:1257
MemoryContext CacheMemoryContext
Definition: mcxt.c:144
void namestrcpy(Name name, const char *str)
Definition: name.c:233
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3206
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:138
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
NameData relname
Definition: pg_class.h:38
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define CLASS_TUPLE_SIZE
Definition: pg_class.h:145
#define InvalidOid
Definition: postgres_ext.h:36
#define RelationCacheInsert(RELATION, replace_allowed)
Definition: relcache.c:209
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2127
void RelationInitTableAccessMethod(Relation relation)
Definition: relcache.c:1801
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1311
struct RelationData * Relation
Definition: relcache.h:27
void RelationMapUpdateMap(Oid relationId, RelFileNumber fileNumber, bool shared, bool immediate)
Definition: relmapper.c:325
#define InvalidRelFileNumber
Definition: relpath.h:26
int rd_refcnt
Definition: rel.h:59
bool rd_isvalid
Definition: rel.h:63
bool rd_islocaltemp
Definition: rel.h:61
TupleDesc rd_att
Definition: rel.h:112
bool rd_isnailed
Definition: rel.h:62
BackendId rd_backend
Definition: rel.h:60
SMgrRelation rd_smgr
Definition: rel.h:58
SubTransactionId rd_createSubid
Definition: rel.h:103
SubTransactionId rd_droppedSubid
Definition: rel.h:109
Form_pg_class rd_rel
Definition: rel.h:111
bool has_not_null
Definition: tupdesc.h:44
int tdrefcount
Definition: tupdesc.h:84
TupleConstr * constr
Definition: tupdesc.h:85
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111

References Assert(), BackendIdForTempRelations, CacheMemoryContext, CLASS_TUPLE_SIZE, TupleDescData::constr, CreateCacheMemoryContext(), CreateTupleDescCopy(), elog(), EOXactListAdd, ERROR, GetCurrentSubTransactionId(), TupleConstr::has_not_null, i, InvalidBackendId, InvalidOid, InvalidRelFileNumber, InvalidSubTransactionId, IsCatalogNamespace(), IsSharedRelation(), isTempOrTempToastNamespace(), MemoryContextSwitchTo(), namestrcpy(), TupleDescData::natts, palloc0(), RelationData::rd_att, RelationData::rd_backend, RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_firstRelfilelocatorSubid, RelationData::rd_islocaltemp, RelationData::rd_isnailed, RelationData::rd_isvalid, RelationData::rd_newRelfilelocatorSubid, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_smgr, RelationCacheInsert, RelationGetRelid, RelationIncrementReferenceCount(), RelationInitLockInfo(), RelationInitPhysicalAddr(), RelationInitTableAccessMethod(), RelationMapUpdateMap(), relname, TupleDescData::tdrefcount, and TupleDescAttr.

Referenced by heap_create().

◆ RelationBuildPublicationDesc()

void RelationBuildPublicationDesc ( Relation  relation,
struct PublicationDesc pubdesc 
)

Definition at line 5677 of file relcache.c.

5678 {
5679  List *puboids;
5680  ListCell *lc;
5681  MemoryContext oldcxt;
5682  Oid schemaid;
5683  List *ancestors = NIL;
5684  Oid relid = RelationGetRelid(relation);
5685 
5686  /*
5687  * If not publishable, it publishes no actions. (pgoutput_change() will
5688  * ignore it.)
5689  */
5690  if (!is_publishable_relation(relation))
5691  {
5692  memset(pubdesc, 0, sizeof(PublicationDesc));
5693  pubdesc->rf_valid_for_update = true;
5694  pubdesc->rf_valid_for_delete = true;
5695  pubdesc->cols_valid_for_update = true;
5696  pubdesc->cols_valid_for_delete = true;
5697  return;
5698  }
5699 
5700  if (relation->rd_pubdesc)
5701  {
5702  memcpy(pubdesc, relation->rd_pubdesc, sizeof(PublicationDesc));
5703  return;
5704  }
5705 
5706  memset(pubdesc, 0, sizeof(PublicationDesc));
5707  pubdesc->rf_valid_for_update = true;
5708  pubdesc->rf_valid_for_delete = true;
5709  pubdesc->cols_valid_for_update = true;
5710  pubdesc->cols_valid_for_delete = true;
5711 
5712  /* Fetch the publication membership info. */
5713  puboids = GetRelationPublications(relid);
5714  schemaid = RelationGetNamespace(relation);
5715  puboids = list_concat_unique_oid(puboids, GetSchemaPublications(schemaid));
5716 
5717  if (relation->rd_rel->relispartition)
5718  {
5719  /* Add publications that the ancestors are in too. */
5720  ancestors = get_partition_ancestors(relid);
5721 
5722  foreach(lc, ancestors)
5723  {
5724  Oid ancestor = lfirst_oid(lc);
5725 
5726  puboids = list_concat_unique_oid(puboids,
5727  GetRelationPublications(ancestor));
5728  schemaid = get_rel_namespace(ancestor);
5729  puboids = list_concat_unique_oid(puboids,
5730  GetSchemaPublications(schemaid));
5731  }
5732  }
5733  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5734 
5735  foreach(lc, puboids)
5736  {
5737  Oid pubid = lfirst_oid(lc);
5738  HeapTuple tup;
5739  Form_pg_publication pubform;
5740 
5742 
5743  if (!HeapTupleIsValid(tup))
5744  elog(ERROR, "cache lookup failed for publication %u", pubid);
5745 
5746  pubform = (Form_pg_publication) GETSTRUCT(tup);
5747 
5748  pubdesc->pubactions.pubinsert |= pubform->pubinsert;
5749  pubdesc->pubactions.pubupdate |= pubform->pubupdate;
5750  pubdesc->pubactions.pubdelete |= pubform->pubdelete;
5751  pubdesc->pubactions.pubtruncate |= pubform->pubtruncate;
5752 
5753  /*
5754  * Check if all columns referenced in the filter expression are part
5755  * of the REPLICA IDENTITY index or not.
5756  *
5757  * If the publication is FOR ALL TABLES then it means the table has no
5758  * row filters and we can skip the validation.
5759  */
5760  if (!pubform->puballtables &&
5761  (pubform->pubupdate || pubform->pubdelete) &&
5762  pub_rf_contains_invalid_column(pubid, relation, ancestors,
5763  pubform->pubviaroot))
5764  {
5765  if (pubform->pubupdate)
5766  pubdesc->rf_valid_for_update = false;
5767  if (pubform->pubdelete)
5768  pubdesc->rf_valid_for_delete = false;
5769  }
5770 
5771  /*
5772  * Check if all columns are part of the REPLICA IDENTITY index or not.
5773  *
5774  * If the publication is FOR ALL TABLES then it means the table has no
5775  * column list and we can skip the validation.
5776  */
5777  if (!pubform->puballtables &&
5778  (pubform->pubupdate || pubform->pubdelete) &&
5779  pub_collist_contains_invalid_column(pubid, relation, ancestors,
5780  pubform->pubviaroot))
5781  {
5782  if (pubform->pubupdate)
5783  pubdesc->cols_valid_for_update = false;
5784  if (pubform->pubdelete)
5785  pubdesc->cols_valid_for_delete = false;
5786  }
5787 
5788  ReleaseSysCache(tup);
5789 
5790  /*
5791  * If we know everything is replicated and the row filter is invalid
5792  * for update and delete, there is no point to check for other
5793  * publications.
5794  */
5795  if (pubdesc->pubactions.pubinsert && pubdesc->pubactions.pubupdate &&
5796  pubdesc->pubactions.pubdelete && pubdesc->pubactions.pubtruncate &&
5797  !pubdesc->rf_valid_for_update && !pubdesc->rf_valid_for_delete)
5798  break;
5799 
5800  /*
5801  * If we know everything is replicated and the column list is invalid
5802  * for update and delete, there is no point to check for other
5803  * publications.
5804  */
5805  if (pubdesc->pubactions.pubinsert && pubdesc->pubactions.pubupdate &&
5806  pubdesc->pubactions.pubdelete && pubdesc->pubactions.pubtruncate &&
5807  !pubdesc->cols_valid_for_update && !pubdesc->cols_valid_for_delete)
5808  break;
5809  }
5810 
5811  if (relation->rd_pubdesc)
5812  {
5813  pfree(relation->rd_pubdesc);
5814  relation->rd_pubdesc = NULL;
5815  }
5816 
5817  /* Now save copy of the descriptor in the relcache entry. */
5819  relation->rd_pubdesc = palloc(sizeof(PublicationDesc));
5820  memcpy(relation->rd_pubdesc, pubdesc, sizeof(PublicationDesc));
5821  MemoryContextSwitchTo(oldcxt);
5822 }
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
List * list_concat_unique_oid(List *list1, const List *list2)
Definition: list.c:1468
Oid get_rel_namespace(Oid relid)
Definition: lsyscache.c:1956
void * palloc(Size size)
Definition: mcxt.c:1226
List * get_partition_ancestors(Oid relid)
Definition: partition.c:133
#define NIL
Definition: pg_list.h:68
#define lfirst_oid(lc)
Definition: pg_list.h:174
List * GetSchemaPublications(Oid schemaid)
List * GetRelationPublications(Oid relid)
List * GetAllTablesPublications(void)
bool is_publishable_relation(Relation rel)
FormData_pg_publication * Form_pg_publication
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
unsigned int Oid
Definition: postgres_ext.h:31
bool pub_rf_contains_invalid_column(Oid pubid, Relation relation, List *ancestors, bool pubviaroot)
bool pub_collist_contains_invalid_column(Oid pubid, Relation relation, List *ancestors, bool pubviaroot)
Definition: pg_list.h:54
PublicationActions pubactions
bool cols_valid_for_delete
bool cols_valid_for_update
PublicationDesc * rd_pubdesc
Definition: rel.h:167
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:868
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:820
@ PUBLICATIONOID
Definition: syscache.h:83

References CacheMemoryContext, PublicationDesc::cols_valid_for_delete, PublicationDesc::cols_valid_for_update, elog(), ERROR, get_partition_ancestors(), get_rel_namespace(), GetAllTablesPublications(), GetRelationPublications(), GetSchemaPublications(), GETSTRUCT, HeapTupleIsValid, is_publishable_relation(), lfirst_oid, list_concat_unique_oid(), MemoryContextSwitchTo(), NIL, ObjectIdGetDatum(), palloc(), pfree(), pub_collist_contains_invalid_column(), pub_rf_contains_invalid_column(), PublicationDesc::pubactions, PublicationActions::pubdelete, PublicationActions::pubinsert, PUBLICATIONOID, PublicationActions::pubtruncate, PublicationActions::pubupdate, RelationData::rd_pubdesc, RelationData::rd_rel, RelationGetNamespace, RelationGetRelid, ReleaseSysCache(), PublicationDesc::rf_valid_for_delete, PublicationDesc::rf_valid_for_update, and SearchSysCache1().

Referenced by CheckCmdReplicaIdentity().

◆ RelationCacheInitFilePostInvalidate()

void RelationCacheInitFilePostInvalidate ( void  )

Definition at line 6761 of file relcache.c.

6762 {
6763  LWLockRelease(RelCacheInitLock);
6764 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1808

References LWLockRelease().

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

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )

Definition at line 6736 of file relcache.c.

6737 {
6738  char localinitfname[MAXPGPATH];
6739  char sharedinitfname[MAXPGPATH];
6740 
6741  if (DatabasePath)
6742  snprintf(localinitfname, sizeof(localinitfname), "%s/%s",
6744  snprintf(sharedinitfname, sizeof(sharedinitfname), "global/%s",
6746 
6747  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6748 
6749  /*
6750  * The files might not be there if no backend has been started since the
6751  * last removal. But complain about failures other than ENOENT with
6752  * ERROR. Fortunately, it's not too late to abort the transaction if we
6753  * can't get rid of the would-be-obsolete init file.
6754  */
6755  if (DatabasePath)
6756  unlink_initfile(localinitfname, ERROR);
6757  unlink_initfile(sharedinitfname, ERROR);
6758 }
char * DatabasePath
Definition: globals.c:97
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1195
@ LW_EXCLUSIVE
Definition: lwlock.h:116
#define MAXPGPATH
#define snprintf
Definition: port.h:238
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6833
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25

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

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

◆ RelationCacheInitFileRemove()

void RelationCacheInitFileRemove ( void  )

Definition at line 6776 of file relcache.c.

6777 {
6778  const char *tblspcdir = "pg_tblspc";
6779  DIR *dir;
6780  struct dirent *de;
6781  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6782 
6783  snprintf(path, sizeof(path), "global/%s",
6785  unlink_initfile(path, LOG);
6786 
6787  /* Scan everything in the default tablespace */
6789 
6790  /* Scan the tablespace link directory to find non-default tablespaces */
6791  dir = AllocateDir(tblspcdir);
6792 
6793  while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6794  {
6795  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6796  {
6797  /* Scan the tablespace dir for per-database dirs */
6798  snprintf(path, sizeof(path), "%s/%s/%s",
6799  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6801  }
6802  }
6803 
6804  FreeDir(dir);
6805 }
#define LOG
Definition: elog.h:31
int FreeDir(DIR *dir)
Definition: fd.c:2906
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2869
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2788
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6809
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:33
Definition: dirent.c:26
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15

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

Referenced by StartupXLOG().

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 3935 of file relcache.c.

3936 {
3937  HASHCTL ctl;
3938  int allocsize;
3939 
3940  /*
3941  * make sure cache memory context exists
3942  */
3943  if (!CacheMemoryContext)
3945 
3946  /*
3947  * create hashtable that indexes the relcache
3948  */
3949  ctl.keysize = sizeof(Oid);
3950  ctl.entrysize = sizeof(RelIdCacheEnt);
3951  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3952  &ctl, HASH_ELEM | HASH_BLOBS);
3953 
3954  /*
3955  * reserve enough in_progress_list slots for many cases
3956  */
3957  allocsize = 4;
3960  allocsize * sizeof(*in_progress_list));
3961  in_progress_list_maxlen = allocsize;
3962 
3963  /*
3964  * relation mapper needs to be initialized too
3965  */
3967 }
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:350
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1021
static int in_progress_list_maxlen
Definition: relcache.c:172
#define INITRELCACHESIZE
Definition: relcache.c:3932
struct relidcacheent RelIdCacheEnt
static InProgressEnt * in_progress_list
Definition: relcache.c:170
void RelationMapInitialize(void)
Definition: relmapper.c:649
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76

References CacheMemoryContext, CreateCacheMemoryContext(), HASHCTL::entrysize, HASH_BLOBS, hash_create(), HASH_ELEM, in_progress_list, in_progress_list_maxlen, INITRELCACHESIZE, HASHCTL::keysize, MemoryContextAlloc(), RelationIdCache, and RelationMapInitialize().

Referenced by InitPostgres().

◆ RelationCacheInitializePhase2()

void RelationCacheInitializePhase2 ( void  )

Definition at line 3981 of file relcache.c.

3982 {
3983  MemoryContext oldcxt;
3984 
3985  /*
3986  * relation mapper needs initialized too
3987  */
3989 
3990  /*
3991  * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3992  * nothing.
3993  */
3995  return;
3996 
3997  /*
3998  * switch to cache memory context
3999  */
4001 
4002  /*
4003  * Try to load the shared relcache cache file. If unsuccessful, bootstrap
4004  * the cache with pre-made descriptors for the critical shared catalogs.
4005  */
4006  if (!load_relcache_init_file(true))
4007  {
4008  formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
4009  Natts_pg_database, Desc_pg_database);
4010  formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
4011  Natts_pg_authid, Desc_pg_authid);
4012  formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
4013  Natts_pg_auth_members, Desc_pg_auth_members);
4014  formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
4015  Natts_pg_shseclabel, Desc_pg_shseclabel);
4016  formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
4017  Natts_pg_subscription, Desc_pg_subscription);
4018 
4019 #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
4020  }
4021 
4022  MemoryContextSwitchTo(oldcxt);
4023 }
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:414
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:6053
static const FormData_pg_attribute Desc_pg_shseclabel[Natts_pg_shseclabel]
Definition: relcache.c:119
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1866
static const FormData_pg_attribute Desc_pg_database[Natts_pg_database]
Definition: relcache.c:115
static const FormData_pg_attribute Desc_pg_authid[Natts_pg_authid]
Definition: relcache.c:116
static const FormData_pg_attribute Desc_pg_subscription[Natts_pg_subscription]
Definition: relcache.c:120
static const FormData_pg_attribute Desc_pg_auth_members[Natts_pg_auth_members]
Definition: relcache.c:117
void RelationMapInitializePhase2(void)
Definition: relmapper.c:669

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

Referenced by InitPostgres().

◆ RelationCacheInitializePhase3()

void RelationCacheInitializePhase3 ( void  )

Definition at line 4040 of file relcache.c.

4041 {
4042  HASH_SEQ_STATUS status;
4043  RelIdCacheEnt *idhentry;
4044  MemoryContext oldcxt;
4045  bool needNewCacheFile = !criticalSharedRelcachesBuilt;
4046 
4047  /*
4048  * relation mapper needs initialized too
4049  */
4051 
4052  /*
4053  * switch to cache memory context
4054  */
4056 
4057  /*
4058  * Try to load the local relcache cache file. If unsuccessful, bootstrap
4059  * the cache with pre-made descriptors for the critical "nailed-in" system
4060  * catalogs.
4061  */
4062  if (IsBootstrapProcessingMode() ||
4063  !load_relcache_init_file(false))
4064  {
4065  needNewCacheFile = true;
4066 
4067  formrdesc("pg_class", RelationRelation_Rowtype_Id, false,
4068  Natts_pg_class, Desc_pg_class);
4069  formrdesc("pg_attribute", AttributeRelation_Rowtype_Id, false,
4070  Natts_pg_attribute, Desc_pg_attribute);
4071  formrdesc("pg_proc", ProcedureRelation_Rowtype_Id, false,
4072  Natts_pg_proc, Desc_pg_proc);
4073  formrdesc("pg_type", TypeRelation_Rowtype_Id, false,
4074  Natts_pg_type, Desc_pg_type);
4075 
4076 #define NUM_CRITICAL_LOCAL_RELS 4 /* fix if you change list above */
4077  }
4078 
4079  MemoryContextSwitchTo(oldcxt);
4080 
4081  /* In bootstrap mode, the faked-up formrdesc info is all we'll have */
4083  return;
4084 
4085  /*
4086  * If we didn't get the critical system indexes loaded into relcache, do
4087  * so now. These are critical because the catcache and/or opclass cache
4088  * depend on them for fetches done during relcache load. Thus, we have an
4089  * infinite-recursion problem. We can break the recursion by doing
4090  * heapscans instead of indexscans at certain key spots. To avoid hobbling
4091  * performance, we only want to do that until we have the critical indexes
4092  * loaded into relcache. Thus, the flag criticalRelcachesBuilt is used to
4093  * decide whether to do heapscan or indexscan at the key spots, and we set
4094  * it true after we've loaded the critical indexes.
4095  *
4096  * The critical indexes are marked as "nailed in cache", partly to make it
4097  * easy for load_relcache_init_file to count them, but mainly because we
4098  * cannot flush and rebuild them once we've set criticalRelcachesBuilt to
4099  * true. (NOTE: perhaps it would be possible to reload them by
4100  * temporarily setting criticalRelcachesBuilt to false again. For now,
4101  * though, we just nail 'em in.)
4102  *
4103  * RewriteRelRulenameIndexId and TriggerRelidNameIndexId are not critical
4104  * in the same way as the others, because the critical catalogs don't
4105  * (currently) have any rules or triggers, and so these indexes can be
4106  * rebuilt without inducing recursion. However they are used during
4107  * relcache load when a rel does have rules or triggers, so we choose to
4108  * nail them for performance reasons.
4109  */
4111  {
4112  load_critical_index(ClassOidIndexId,
4113  RelationRelationId);
4114  load_critical_index(AttributeRelidNumIndexId,
4115  AttributeRelationId);
4116  load_critical_index(IndexRelidIndexId,
4117  IndexRelationId);
4118  load_critical_index(OpclassOidIndexId,
4119  OperatorClassRelationId);
4120  load_critical_index(AccessMethodProcedureIndexId,
4121  AccessMethodProcedureRelationId);
4122  load_critical_index(RewriteRelRulenameIndexId,
4123  RewriteRelationId);
4124  load_critical_index(TriggerRelidNameIndexId,
4125  TriggerRelationId);
4126 
4127 #define NUM_CRITICAL_LOCAL_INDEXES 7 /* fix if you change list above */
4128 
4129  criticalRelcachesBuilt = true;
4130  }
4131 
4132  /*
4133  * Process critical shared indexes too.
4134  *
4135  * DatabaseNameIndexId isn't critical for relcache loading, but rather for
4136  * initial lookup of MyDatabaseId, without which we'll never find any
4137  * non-shared catalogs at all. Autovacuum calls InitPostgres with a
4138  * database OID, so it instead depends on DatabaseOidIndexId. We also
4139  * need to nail up some indexes on pg_authid and pg_auth_members for use
4140  * during client authentication. SharedSecLabelObjectIndexId isn't
4141  * critical for the core system, but authentication hooks might be
4142  * interested in it.
4143  */
4145  {
4146  load_critical_index(DatabaseNameIndexId,
4147  DatabaseRelationId);
4148  load_critical_index(DatabaseOidIndexId,
4149  DatabaseRelationId);
4150  load_critical_index(AuthIdRolnameIndexId,
4151  AuthIdRelationId);
4152  load_critical_index(AuthIdOidIndexId,
4153  AuthIdRelationId);
4154  load_critical_index(AuthMemMemRoleIndexId,
4155  AuthMemRelationId);
4156  load_critical_index(SharedSecLabelObjectIndexId,
4157  SharedSecLabelRelationId);
4158 
4159 #define NUM_CRITICAL_SHARED_INDEXES 6 /* fix if you change list above */
4160 
4162  }
4163 
4164  /*
4165  * Now, scan all the relcache entries and update anything that might be
4166  * wrong in the results from formrdesc or the relcache cache file. If we
4167  * faked up relcache entries using formrdesc, then read the real pg_class
4168  * rows and replace the fake entries with them. Also, if any of the
4169  * relcache entries have rules, triggers, or security policies, load that
4170  * info the hard way since it isn't recorded in the cache file.
4171  *
4172  * Whenever we access the catalogs to read data, there is a possibility of
4173  * a shared-inval cache flush causing relcache entries to be removed.
4174  * Since hash_seq_search only guarantees to still work after the *current*
4175  * entry is removed, it's unsafe to continue the hashtable scan afterward.
4176  * We handle this by restarting the scan from scratch after each access.
4177  * This is theoretically O(N^2), but the number of entries that actually
4178  * need to be fixed is small enough that it doesn't matter.
4179  */
4180  hash_seq_init(&status, RelationIdCache);
4181 
4182  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
4183  {
4184  Relation relation = idhentry->reldesc;
4185  bool restart = false;
4186 
4187  /*
4188  * Make sure *this* entry doesn't get flushed while we work with it.
4189  */
4191 
4192  /*
4193  * If it's a faked-up entry, read the real pg_class tuple.
4194  */
4195  if (relation->rd_rel->relowner == InvalidOid)
4196  {
4197  HeapTuple htup;
4198  Form_pg_class relp;
4199 
4200  htup = SearchSysCache1(RELOID,
4201  ObjectIdGetDatum(RelationGetRelid(relation)));
4202  if (!HeapTupleIsValid(htup))
4203  elog(FATAL, "cache lookup failed for relation %u",
4204  RelationGetRelid(relation));
4205  relp = (Form_pg_class) GETSTRUCT(htup);
4206 
4207  /*
4208  * Copy tuple to relation->rd_rel. (See notes in
4209  * AllocateRelationDesc())
4210  */
4211  memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
4212 
4213  /* Update rd_options while we have the tuple */
4214  if (relation->rd_options)
4215  pfree(relation->rd_options);
4216  RelationParseRelOptions(relation, htup);
4217 
4218  /*
4219  * Check the values in rd_att were set up correctly. (We cannot
4220  * just copy them over now: formrdesc must have set up the rd_att
4221  * data correctly to start with, because it may already have been
4222  * copied into one or more catcache entries.)
4223  */
4224  Assert(relation->rd_att->tdtypeid == relp->reltype);
4225  Assert(relation->rd_att->tdtypmod == -1);
4226 
4227  ReleaseSysCache(htup);
4228 
4229  /* relowner had better be OK now, else we'll loop forever */
4230  if (relation->rd_rel->relowner == InvalidOid)
4231  elog(ERROR, "invalid relowner in pg_class entry for \"%s\"",
4232  RelationGetRelationName(relation));
4233 
4234  restart = true;
4235  }
4236 
4237  /*
4238  * Fix data that isn't saved in relcache cache file.
4239  *
4240  * relhasrules or relhastriggers could possibly be wrong or out of
4241  * date. If we don't actually find any rules or triggers, clear the
4242  * local copy of the flag so that we don't get into an infinite loop
4243  * here. We don't make any attempt to fix the pg_class entry, though.
4244  */
4245  if (relation->rd_rel->relhasrules && relation->rd_rules == NULL)
4246  {
4247  RelationBuildRuleLock(relation);
4248  if (relation->rd_rules == NULL)
4249  relation->rd_rel->relhasrules = false;
4250  restart = true;
4251  }
4252  if (relation->rd_rel->relhastriggers && relation->trigdesc == NULL)
4253  {
4254  RelationBuildTriggers(relation);
4255  if (relation->trigdesc == NULL)
4256  relation->rd_rel->relhastriggers = false;
4257  restart = true;
4258  }
4259 
4260  /*
4261  * Re-load the row security policies if the relation has them, since
4262  * they are not preserved in the cache. Note that we can never NOT
4263  * have a policy while relrowsecurity is true,
4264  * RelationBuildRowSecurity will create a single default-deny policy
4265  * if there is no policy defined in pg_policy.
4266  */
4267  if (relation->rd_rel->relrowsecurity && relation->rd_rsdesc == NULL)
4268  {
4269  RelationBuildRowSecurity(relation);
4270 
4271  Assert(relation->rd_rsdesc != NULL);
4272  restart = true;
4273  }
4274 
4275  /* Reload tableam data if needed */
4276  if (relation->rd_tableam == NULL &&
4277  (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind) || relation->rd_rel->relkind == RELKIND_SEQUENCE))
4278  {
4280  Assert(relation->rd_tableam != NULL);
4281 
4282  restart = true;
4283  }
4284 
4285  /* Release hold on the relation */
4287 
4288  /* Now, restart the hashtable scan if needed */
4289  if (restart)
4290  {
4291  hash_seq_term(&status);
4292  hash_seq_init(&status, RelationIdCache);
4293  }
4294  }
4295 
4296  /*
4297  * Lastly, write out new relcache cache files if needed. We don't bother
4298  * to distinguish cases where only one of the two needs an update.
4299  */
4300  if (needNewCacheFile)
4301  {
4302  /*
4303  * Force all the catcaches to finish initializing and thereby open the
4304  * catalogs and indexes they use. This will preload the relcache with
4305  * entries for all the most important system catalogs and indexes, so
4306  * that the init files will be most useful for future backends.
4307  */
4309 
4310  /* now write the files */
4312  write_relcache_init_file(false);
4313  }
4314 }
void hash_seq_term(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1507
#define FATAL
Definition: elog.h:41
void RelationBuildRowSecurity(Relation relation)
Definition: policy.c:196
static void RelationParseRelOptions(Relation relation, HeapTuple tuple)
Definition: relcache.c:462
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2140
bool criticalRelcachesBuilt
Definition: relcache.c:140
bool criticalSharedRelcachesBuilt
Definition: relcache.c:146
static const FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute]
Definition: relcache.c:112
static const FormData_pg_attribute Desc_pg_class[Natts_pg_class]
Definition: relcache.c:111
static void RelationBuildRuleLock(Relation relation)
Definition: relcache.c:731
static const FormData_pg_attribute Desc_pg_proc[Natts_pg_proc]
Definition: relcache.c:113
static void write_relcache_init_file(bool shared)
Definition: relcache.c:6469
static const FormData_pg_attribute Desc_pg_type[Natts_pg_type]
Definition: relcache.c:114
static void load_critical_index(Oid indexoid, Oid heapoid)
Definition: relcache.c:4323
void RelationMapInitializePhase3(void)
Definition: relmapper.c:690
const struct TableAmRoutine * rd_tableam
Definition: rel.h:188
struct RowSecurityDesc * rd_rsdesc
Definition: rel.h:119
TriggerDesc * trigdesc
Definition: rel.h:117
RuleLock * rd_rules
Definition: rel.h:115
bytea * rd_options
Definition: rel.h:174
int32 tdtypmod
Definition: tupdesc.h:83
Oid tdtypeid
Definition: tupdesc.h:82
void InitCatalogCachePhase2(void)
Definition: syscache.c:779
@ RELOID
Definition: syscache.h:89
void RelationBuildTriggers(Relation relation)
Definition: trigger.c:1862

References Assert(), CacheMemoryContext, CLASS_TUPLE_SIZE, criticalRelcachesBuilt, criticalSharedRelcachesBuilt, 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, InitCatalogCachePhase2(), InvalidOid, IsBootstrapProcessingMode, load_critical_index(), load_relcache_init_file(), MemoryContextSwitchTo(), ObjectIdGetDatum(), pfree(), RelationData::rd_att, RelationData::rd_options, RelationData::rd_rel, RelationData::rd_rsdesc, RelationData::rd_rules, RelationData::rd_tableam, RelationBuildRowSecurity(), RelationBuildRuleLock(), RelationBuildTriggers(), RelationDecrementReferenceCount(), RelationGetRelationName, RelationGetRelid, RelationIdCache, RelationIncrementReferenceCount(), RelationInitTableAccessMethod(), RelationMapInitializePhase3(), RelationParseRelOptions(), relidcacheent::reldesc, ReleaseSysCache(), RELOID, SearchSysCache1(), TupleDescData::tdtypeid, TupleDescData::tdtypmod, RelationData::trigdesc, and write_relcache_init_file().

Referenced by InitPostgres().

◆ RelationCacheInvalidate()

void RelationCacheInvalidate ( bool  debug_discard)

Definition at line 2934 of file relcache.c.

2935 {
2936  HASH_SEQ_STATUS status;
2937  RelIdCacheEnt *idhentry;
2938  Relation relation;
2939  List *rebuildFirstList = NIL;
2940  List *rebuildList = NIL;
2941  ListCell *l;
2942  int i;
2943 
2944  /*
2945  * Reload relation mapping data before starting to reconstruct cache.
2946  */
2948 
2949  /* Phase 1 */
2950  hash_seq_init(&status, RelationIdCache);
2951 
2952  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2953  {
2954  relation = idhentry->reldesc;
2955 
2956  /* Must close all smgr references to avoid leaving dangling ptrs */
2957  RelationCloseSmgr(relation);
2958 
2959  /*
2960  * Ignore new relations; no other backend will manipulate them before
2961  * we commit. Likewise, before replacing a relation's relfilelocator,
2962  * we shall have acquired AccessExclusiveLock and drained any
2963  * applicable pending invalidations.
2964  */
2965  if (relation->rd_createSubid != InvalidSubTransactionId ||
2967  continue;
2968 
2970 
2971  if (RelationHasReferenceCountZero(relation))
2972  {
2973  /* Delete this entry immediately */
2974  Assert(!relation->rd_isnailed);
2975  RelationClearRelation(relation, false);
2976  }
2977  else
2978  {
2979  /*
2980  * If it's a mapped relation, immediately update its rd_locator in
2981  * case its relfilenumber changed. We must do this during phase 1
2982  * in case the relation is consulted during rebuild of other
2983  * relcache entries in phase 2. It's safe since consulting the
2984  * map doesn't involve any access to relcache entries.
2985  */
2986  if (RelationIsMapped(relation))
2987  RelationInitPhysicalAddr(relation);
2988 
2989  /*
2990  * Add this entry to list of stuff to rebuild in second pass.
2991  * pg_class goes to the front of rebuildFirstList while
2992  * pg_class_oid_index goes to the back of rebuildFirstList, so
2993  * they are done first and second respectively. Other nailed
2994  * relations go to the front of rebuildList, so they'll be done
2995  * next in no particular order; and everything else goes to the
2996  * back of rebuildList.
2997  */
2998  if (RelationGetRelid(relation) == RelationRelationId)
2999  rebuildFirstList = lcons(relation, rebuildFirstList);
3000  else if (RelationGetRelid(relation) == ClassOidIndexId)
3001  rebuildFirstList = lappend(rebuildFirstList, relation);
3002  else if (relation->rd_isnailed)
3003  rebuildList = lcons(relation, rebuildList);
3004  else
3005  rebuildList = lappend(rebuildList, relation);
3006  }
3007  }
3008 
3009  /*
3010  * Now zap any remaining smgr cache entries. This must happen before we
3011  * start to rebuild entries, since that may involve catalog fetches which
3012  * will re-open catalog files.
3013  */
3014  smgrcloseall();
3015 
3016  /* Phase 2: rebuild the items found to need rebuild in phase 1 */
3017  foreach(l, rebuildFirstList)
3018  {
3019  relation = (Relation) lfirst(l);
3020  RelationClearRelation(relation, true);
3021  }
3022  list_free(rebuildFirstList);
3023  foreach(l, rebuildList)
3024  {
3025  relation = (Relation) lfirst(l);
3026  RelationClearRelation(relation, true);
3027  }
3028  list_free(rebuildList);
3029 
3030  if (!debug_discard)
3031  /* Any RelationBuildDesc() on the stack must start over. */
3032  for (i = 0; i < in_progress_list_len; i++)
3033  in_progress_list[i].invalidated = true;
3034 }
List * lappend(List *list, void *datum)
Definition: list.c:338
void list_free(List *list)
Definition: list.c:1545
List * lcons(void *datum, List *list)
Definition: list.c:494
#define lfirst(lc)
Definition: pg_list.h:172
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:488
#define RelationIsMapped(relation)
Definition: rel.h:553
static void RelationCloseSmgr(Relation relation)
Definition: rel.h:584
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2496
static long relcacheInvalsReceived
Definition: relcache.c:154
void RelationMapInvalidateAll(void)
Definition: relmapper.c:490
void smgrcloseall(void)
Definition: smgr.c:327

References Assert(), hash_seq_init(), hash_seq_search(), i, in_progress_list, in_progress_list_len, InvalidSubTransactionId, lappend(), lcons(), lfirst, list_free(), NIL, RelationData::rd_createSubid, RelationData::rd_firstRelfilelocatorSubid, RelationData::rd_isnailed, RelationClearRelation(), RelationCloseSmgr(), RelationGetRelid, RelationHasReferenceCountZero, RelationIdCache, RelationInitPhysicalAddr(), RelationIsMapped, RelationMapInvalidateAll(), relcacheInvalsReceived, relidcacheent::reldesc, and smgrcloseall().

Referenced by InvalidateSystemCachesExtended(), and LocalExecuteInvalidationMessage().

◆ RelationCacheInvalidateEntry()

void RelationCacheInvalidateEntry ( Oid  relationId)

Definition at line 2878 of file relcache.c.

2879 {
2880  Relation relation;
2881 
2882  RelationIdCacheLookup(relationId, relation);
2883 
2884  if (PointerIsValid(relation))
2885  {
2887  RelationFlushRelation(relation);
2888  }
2889  else
2890  {
2891  int i;
2892 
2893  for (i = 0; i < in_progress_list_len; i++)
2894  if (in_progress_list[i].reloid == relationId)
2895  in_progress_list[i].invalidated = true;
2896  }
2897 }
#define PointerIsValid(pointer)
Definition: c.h:752
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:231
static void RelationFlushRelation(Relation relation)
Definition: relcache.c:2801
bool invalidated
Definition: relcache.c:167

References i, in_progress_list, in_progress_list_len, inprogressent::invalidated, PointerIsValid, RelationFlushRelation(), RelationIdCacheLookup, and relcacheInvalsReceived.

Referenced by LocalExecuteInvalidationMessage().

◆ RelationClose()

void RelationClose ( Relation  relation)

Definition at line 2160 of file relcache.c.

2161 {
2162  /* Note: no locking manipulations needed */
2164 
2165  /*
2166  * If the relation is no longer open in this session, we can clean up any
2167  * stale partition descriptors it has. This is unlikely, so check to see
2168  * if there are child contexts before expending a call to mcxt.c.
2169  */
2170  if (RelationHasReferenceCountZero(relation))
2171  {
2172  if (relation->rd_pdcxt != NULL &&
2173  relation->rd_pdcxt->firstchild != NULL)
2175 
2176  if (relation->rd_pddcxt != NULL &&
2177  relation->rd_pddcxt->firstchild != NULL)
2179  }
2180 
2181 #ifdef RELCACHE_FORCE_RELEASE
2182  if (RelationHasReferenceCountZero(relation) &&
2183  relation->rd_createSubid == InvalidSubTransactionId &&
2185  RelationClearRelation(relation, false);
2186 #endif
2187 }
void MemoryContextDeleteChildren(MemoryContext context)
Definition: mcxt.c:448
MemoryContext firstchild
Definition: memnodes.h:90
MemoryContext rd_pdcxt
Definition: rel.h:131
MemoryContext rd_pddcxt
Definition: rel.h:135

References MemoryContextData::firstchild, InvalidSubTransactionId, MemoryContextDeleteChildren(), RelationData::rd_createSubid, RelationData::rd_firstRelfilelocatorSubid, RelationData::rd_pdcxt, RelationData::rd_pddcxt, RelationClearRelation(), RelationDecrementReferenceCount(), and RelationHasReferenceCountZero.

Referenced by index_close(), init_tuple_slot(), maybe_send_schema(), pgoutput_change(), pgoutput_column_list_init(), pgoutput_row_filter_init(), relation_close(), RelationGetIdentityKeyBitmap(), ReorderBufferProcessTXN(), ReorderBufferToastReplace(), and ResourceOwnerReleaseInternal().

◆ RelationCloseSmgrByOid()

void RelationCloseSmgrByOid ( Oid  relationId)

Definition at line 3043 of file relcache.c.

3044 {
3045  Relation relation;
3046 
3047  RelationIdCacheLookup(relationId, relation);
3048 
3049  if (!PointerIsValid(relation))
3050  return; /* not in cache, nothing to do */
3051 
3052  RelationCloseSmgr(relation);
3053 }

References PointerIsValid, RelationCloseSmgr(), and RelationIdCacheLookup.

Referenced by swap_relation_files().

◆ RelationForgetRelation()

void RelationForgetRelation ( Oid  rid)

Definition at line 2834 of file relcache.c.

2835 {
2836  Relation relation;
2837 
2838  RelationIdCacheLookup(rid, relation);
2839 
2840  if (!PointerIsValid(relation))
2841  return; /* not in cache, nothing to do */
2842 
2843  if (!RelationHasReferenceCountZero(relation))
2844  elog(ERROR, "relation %u is still open", rid);
2845 
2847  if (relation->rd_createSubid != InvalidSubTransactionId ||
2849  {
2850  /*
2851  * In the event of subtransaction rollback, we must not forget
2852  * rd_*Subid. Mark the entry "dropped" so RelationClearRelation()
2853  * invalidates it in lieu of destroying it. (If we're in a top
2854  * transaction, we could opt to destroy the entry.)
2855  */
2857  }
2858 
2859  RelationClearRelation(relation, false);
2860 }

References Assert(), elog(), ERROR, GetCurrentSubTransactionId(), InvalidSubTransactionId, PointerIsValid, RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_firstRelfilelocatorSubid, RelationClearRelation(), RelationHasReferenceCountZero, and RelationIdCacheLookup.

Referenced by heap_drop_with_catalog(), and index_drop().

◆ RelationGetDummyIndexExpressions()

List* RelationGetDummyIndexExpressions ( Relation  relation)

Definition at line 5055 of file relcache.c.

5056 {
5057  List *result;
5058  Datum exprsDatum;
5059  bool isnull;
5060  char *exprsString;
5061  List *rawExprs;
5062  ListCell *lc;
5063 
5064  /* Quick exit if there is nothing to do. */
5065  if (relation->rd_indextuple == NULL ||
5066  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indexprs, NULL))
5067  return NIL;
5068 
5069  /* Extract raw node tree(s) from index tuple. */
5070  exprsDatum = heap_getattr(relation->rd_indextuple,
5071  Anum_pg_index_indexprs,
5073  &isnull);
5074  Assert(!isnull);
5075  exprsString = TextDatumGetCString(exprsDatum);
5076  rawExprs = (List *) stringToNode(exprsString);
5077  pfree(exprsString);
5078 
5079  /* Construct null Consts; the typlen and typbyval are arbitrary. */
5080  result = NIL;
5081  foreach(lc, rawExprs)
5082  {
5083  Node *rawExpr = (Node *) lfirst(lc);
5084 
5085  result = lappend(result,
5086  makeConst(exprType(rawExpr),
5087  exprTypmod(rawExpr),
5088  exprCollation(rawExpr),
5089  1,
5090  (Datum) 0,
5091  true,
5092  true));
5093  }
5094 
5095  return result;
5096 }
#define TextDatumGetCString(d)
Definition: builtins.h:95
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:447
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:302
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:43
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:282
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:786
uintptr_t Datum
Definition: postgres.h:64
void * stringToNode(const char *str)
Definition: read.c:90
static TupleDesc GetPgIndexDescriptor(void)
Definition: relcache.c:4402
Definition: nodes.h:129
struct HeapTupleData * rd_indextuple
Definition: rel.h:193

References Assert(), exprCollation(), exprType(), exprTypmod(), GetPgIndexDescriptor(), heap_attisnull(), heap_getattr(), lappend(), lfirst, makeConst(), NIL, pfree(), RelationData::rd_indextuple, stringToNode(), and TextDatumGetCString.

Referenced by BuildDummyIndexInfo().

◆ RelationGetExclusionInfo()

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

Definition at line 5545 of file relcache.c.

5549 {
5550  int indnkeyatts;
5551  Oid *ops;
5552  Oid *funcs;
5553  uint16 *strats;
5554  Relation conrel;
5555  SysScanDesc conscan;
5556  ScanKeyData skey[1];
5557  HeapTuple htup;
5558  bool found;
5559  MemoryContext oldcxt;
5560  int i;
5561 
5562  indnkeyatts = IndexRelationGetNumberOfKeyAttributes(indexRelation);
5563 
5564  /* Allocate result space in caller context */
5565  *operators = ops = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5566  *procs = funcs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5567  *strategies = strats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
5568 
5569  /* Quick exit if we have the data cached already */
5570  if (indexRelation->rd_exclstrats != NULL)
5571  {
5572  memcpy(ops, indexRelation->rd_exclops, sizeof(Oid) * indnkeyatts);
5573  memcpy(funcs, indexRelation->rd_exclprocs, sizeof(Oid) * indnkeyatts);
5574  memcpy(strats, indexRelation->rd_exclstrats, sizeof(uint16) * indnkeyatts);
5575  return;
5576  }
5577 
5578  /*
5579  * Search pg_constraint for the constraint associated with the index. To
5580  * make this not too painfully slow, we use the index on conrelid; that
5581  * will hold the parent relation's OID not the index's own OID.
5582  *
5583  * Note: if we wanted to rely on the constraint name matching the index's
5584  * name, we could just do a direct lookup using pg_constraint's unique
5585  * index. For the moment it doesn't seem worth requiring that.
5586  */
5587  ScanKeyInit(&skey[0],
5588  Anum_pg_constraint_conrelid,
5589  BTEqualStrategyNumber, F_OIDEQ,
5590  ObjectIdGetDatum(indexRelation->rd_index->indrelid));
5591 
5592  conrel = table_open(ConstraintRelationId, AccessShareLock);
5593  conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
5594  NULL, 1, skey);
5595  found = false;
5596 
5597  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
5598  {
5600  Datum val;
5601  bool isnull;
5602  ArrayType *arr;
5603  int nelem;
5604 
5605  /* We want the exclusion constraint owning the index */
5606  if (conform->contype != CONSTRAINT_EXCLUSION ||
5607  conform->conindid != RelationGetRelid(indexRelation))
5608  continue;
5609 
5610  /* There should be only one */
5611  if (found)
5612  elog(ERROR, "unexpected exclusion constraint record found for rel %s",
5613  RelationGetRelationName(indexRelation));
5614  found = true;
5615 
5616  /* Extract the operator OIDS from conexclop */
5617  val = fastgetattr(htup,
5618  Anum_pg_constraint_conexclop,
5619  conrel->rd_att, &isnull);
5620  if (isnull)
5621  elog(ERROR, "null conexclop for rel %s",
5622  RelationGetRelationName(indexRelation));
5623 
5624  arr = DatumGetArrayTypeP(val); /* ensure not toasted */
5625  nelem = ARR_DIMS(arr)[0];
5626  if (ARR_NDIM(arr) != 1 ||
5627  nelem != indnkeyatts ||
5628  ARR_HASNULL(arr) ||
5629  ARR_ELEMTYPE(arr) != OIDOID)
5630  elog(ERROR, "conexclop is not a 1-D Oid array");
5631 
5632  memcpy(ops, ARR_DATA_PTR(arr), sizeof(Oid) * indnkeyatts);
5633  }
5634 
5635  systable_endscan(conscan);
5636  table_close(conrel, AccessShareLock);
5637 
5638  if (!found)
5639  elog(ERROR, "exclusion constraint record missing for rel %s",
5640  RelationGetRelationName(indexRelation));
5641 
5642  /* We need the func OIDs and strategy numbers too */
5643  for (i = 0; i < indnkeyatts; i++)
5644  {
5645  funcs[i] = get_opcode(ops[i]);
5646  strats[i] = get_op_opfamily_strategy(ops[i],
5647  indexRelation->rd_opfamily[i]);
5648  /* shouldn't fail, since it was checked at index creation */
5649  if (strats[i] == InvalidStrategy)
5650  elog(ERROR, "could not find strategy for operator %u in family %u",
5651  ops[i], indexRelation->rd_opfamily[i]);
5652  }
5653 
5654  /* Save a copy of the results in the relcache entry. */
5655  oldcxt = MemoryContextSwitchTo(indexRelation->rd_indexcxt);
5656  indexRelation->rd_exclops = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5657  indexRelation->rd_exclprocs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
5658  indexRelation->rd_exclstrats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
5659  memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * indnkeyatts);
5660  memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * indnkeyatts);
5661  memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * indnkeyatts);
5662  MemoryContextSwitchTo(oldcxt);
5663 }
#define ARR_NDIM(a)
Definition: array.h:283
#define ARR_DATA_PTR(a)
Definition: array.h:315
#define DatumGetArrayTypeP(X)
Definition: array.h:254
#define ARR_ELEMTYPE(a)
Definition: array.h:285
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_HASNULL(a)
Definition: array.h:284
unsigned short uint16
Definition: c.h:494
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:599
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:506
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
static Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:749
long val
Definition: informix.c:664
#define AccessShareLock
Definition: lockdefs.h:36
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1289
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition: lsyscache.c:82
FormData_pg_constraint * Form_pg_constraint
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition: rel.h:523
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define InvalidStrategy
Definition: stratnum.h:24
#define BTEqualStrategyNumber
Definition: stratnum.h:31
Oid * rd_exclprocs
Definition: rel.h:214
uint16 * rd_exclstrats
Definition: rel.h:215
Oid * rd_exclops
Definition: rel.h:213
Form_pg_index rd_index
Definition: rel.h:191
MemoryContext rd_indexcxt
Definition: rel.h:203
Oid * rd_opfamily
Definition: rel.h:206
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

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

Referenced by BuildIndexInfo(), and CheckIndexCompatible().

◆ RelationGetFKeyList()

List* RelationGetFKeyList ( Relation  relation)

Definition at line 4631 of file relcache.c.

4632 {
4633  List *result;
4634  Relation conrel;
4635  SysScanDesc conscan;
4636  ScanKeyData skey;
4637  HeapTuple htup;
4638  List *oldlist;
4639  MemoryContext oldcxt;
4640 
4641  /* Quick exit if we already computed the list. */
4642  if (relation->rd_fkeyvalid)
4643  return relation->rd_fkeylist;
4644 
4645  /* Fast path: non-partitioned tables without triggers can't have FKs */
4646  if (!relation->rd_rel->relhastriggers &&
4647  relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
4648  return NIL;
4649 
4650  /*
4651  * We build the list we intend to return (in the caller's context) while
4652  * doing the scan. After successfully completing the scan, we copy that
4653  * list into the relcache entry. This avoids cache-context memory leakage
4654  * if we get some sort of error partway through.
4655  */
4656  result = NIL;
4657 
4658  /* Prepare to scan pg_constraint for entries having conrelid = this rel. */
4659  ScanKeyInit(&skey,
4660  Anum_pg_constraint_conrelid,
4661  BTEqualStrategyNumber, F_OIDEQ,
4662  ObjectIdGetDatum(RelationGetRelid(relation)));
4663 
4664  conrel = table_open(ConstraintRelationId, AccessShareLock);
4665  conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
4666  NULL, 1, &skey);
4667 
4668  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4669  {
4670  Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(htup);
4671  ForeignKeyCacheInfo *info;
4672 
4673  /* consider only foreign keys */
4674  if (constraint->contype != CONSTRAINT_FOREIGN)
4675  continue;
4676 
4677  info = makeNode(ForeignKeyCacheInfo);
4678  info->conoid = constraint->oid;
4679  info->conrelid = constraint->conrelid;
4680  info->confrelid = constraint->confrelid;
4681 
4682  DeconstructFkConstraintRow(htup, &info->nkeys,
4683  info->conkey,
4684  info->confkey,
4685  info->conpfeqop,
4686  NULL, NULL, NULL, NULL);
4687 
4688  /* Add FK's node to the result list */
4689  result = lappend(result, info);
4690  }
4691 
4692  systable_endscan(conscan);
4693  table_close(conrel, AccessShareLock);
4694 
4695  /* Now save a copy of the completed list in the relcache entry. */
4697  oldlist = relation->rd_fkeylist;
4698  relation->rd_fkeylist = copyObject(result);
4699  relation->rd_fkeyvalid = true;
4700  MemoryContextSwitchTo(oldcxt);
4701 
4702  /* Don't leak the old list, if there is one */
4703  list_free_deep(oldlist);
4704 
4705  return result;
4706 }
void list_free_deep(List *list)
Definition: list.c:1559
#define copyObject(obj)
Definition: nodes.h:244
#define makeNode(_type_)
Definition: nodes.h:176
void DeconstructFkConstraintRow(HeapTuple tuple, int *numfks, AttrNumber *conkey, AttrNumber *confkey, Oid *pf_eq_oprs, Oid *pp_eq_oprs, Oid *ff_eq_oprs, int *num_fk_del_set_cols, AttrNumber *fk_del_set_cols)
List * rd_fkeylist
Definition: rel.h:122
bool rd_fkeyvalid
Definition: rel.h:123

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

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

◆ RelationGetIdentityKeyBitmap()

Bitmapset* RelationGetIdentityKeyBitmap ( Relation  relation)

Definition at line 5471 of file relcache.c.

5472 {
5473  Bitmapset *idindexattrs = NULL; /* columns in the replica identity */
5474  Relation indexDesc;
5475  int i;
5476  Oid replidindex;
5477  MemoryContext oldcxt;
5478 
5479  /* Quick exit if we already computed the result */
5480  if (relation->rd_idattr != NULL)
5481  return bms_copy(relation->rd_idattr);
5482 
5483  /* Fast path if definitely no indexes */
5484  if (!RelationGetForm(relation)->relhasindex)
5485  return NULL;
5486 
5487  /* Historic snapshot must be set. */
5489 
5490  replidindex = RelationGetReplicaIndex(relation);
5491 
5492  /* Fall out if there is no replica identity index */
5493  if (!OidIsValid(replidindex))
5494  return NULL;
5495 
5496  /* Look up the description for the replica identity index */
5497  indexDesc = RelationIdGetRelation(replidindex);
5498 
5499  if (!RelationIsValid(indexDesc))
5500  elog(ERROR, "could not open relation with OID %u",
5501  relation->rd_replidindex);
5502 
5503  /* Add referenced attributes to idindexattrs */
5504  for (i = 0; i < indexDesc->rd_index->indnatts; i++)
5505  {
5506  int attrnum = indexDesc->rd_index->indkey.values[i];
5507 
5508  /*
5509  * We don't include non-key columns into idindexattrs bitmaps. See
5510  * RelationGetIndexAttrBitmap.
5511  */
5512  if (attrnum != 0)
5513  {
5514  if (i < indexDesc->rd_index->indnkeyatts)
5515  idindexattrs = bms_add_member(idindexattrs,
5517  }
5518  }
5519 
5520  RelationClose(indexDesc);
5521 
5522  /* Don't leak the old values of these bitmaps, if any */
5523  bms_free(relation->rd_idattr);
5524  relation->rd_idattr = NULL;
5525 
5526  /* Now save copy of the bitmap in the relcache entry */
5528  relation->rd_idattr = bms_copy(idindexattrs);
5529  MemoryContextSwitchTo(oldcxt);
5530 
5531  /* We return our original working copy for caller to play with */
5532  return idindexattrs;
5533 }
void bms_free(Bitmapset *a)
Definition: bitmapset.c:194
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:753
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:80
#define OidIsValid(objectId)
Definition: c.h:764
#define RelationGetForm(relation)
Definition: rel.h:498
#define RelationIsValid(relation)
Definition: rel.h:477
Oid RelationGetReplicaIndex(Relation relation)
Definition: relcache.c:4971
Relation RelationIdGetRelation(Oid relationId)
Definition: relcache.c:2054
void RelationClose(Relation relation)
Definition: relcache.c:2160
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:1647
Oid rd_replidindex
Definition: rel.h:154
Bitmapset * rd_idattr
Definition: rel.h:163
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27

References Assert(), bms_add_member(), bms_copy(), bms_free(), CacheMemoryContext, elog(), ERROR, FirstLowInvalidHeapAttributeNumber, HistoricSnapshotActive(), i, MemoryContextSwitchTo(), OidIsValid, RelationData::rd_idattr, RelationData::rd_index, RelationData::rd_replidindex, RelationClose(), RelationGetForm, RelationGetReplicaIndex(), RelationIdGetRelation(), and RelationIsValid.

Referenced by logicalrep_write_attrs().

◆ RelationGetIndexAttOptions()

bytea** RelationGetIndexAttOptions ( Relation  relation,
bool  copy 
)

Definition at line 5874 of file relcache.c.

5875 {
5876  MemoryContext oldcxt;
5877  bytea **opts = relation->rd_opcoptions;
5878  Oid relid = RelationGetRelid(relation);
5879  int natts = RelationGetNumberOfAttributes(relation); /* XXX
5880  * IndexRelationGetNumberOfKeyAttributes */
5881  int i;
5882 
5883  /* Try to copy cached options. */
5884  if (opts)
5885  return copy ? CopyIndexAttOptions(opts, natts) : opts;
5886 
5887  /* Get and parse opclass options. */
5888  opts = palloc0(sizeof(*opts) * natts);
5889 
5890  for (i = 0; i < natts; i++)
5891  {
5892  if (criticalRelcachesBuilt && relid != AttributeRelidNumIndexId)
5893  {
5894  Datum attoptions = get_attoptions(relid, i + 1);
5895 
5896  opts[i] = index_opclass_options(relation, i + 1, attoptions, false);
5897 
5898  if (attoptions != (Datum) 0)
5899  pfree(DatumGetPointer(attoptions));
5900  }
5901  }
5902 
5903  /* Copy parsed options to the cache. */
5904  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
5905  relation->rd_opcoptions = CopyIndexAttOptions(opts, natts);
5906  MemoryContextSwitchTo(oldcxt);
5907 
5908  if (copy)
5909  return opts;
5910 
5911  for (i = 0; i < natts; i++)
5912  {
5913  if (opts[i])
5914  pfree(opts[i]);
5915  }
5916 
5917  pfree(opts);
5918 
5919  return relation->rd_opcoptions;
5920 }
bytea * index_opclass_options(Relation indrel, AttrNumber attnum, Datum attoptions, bool validate)
Definition: indexam.c:947
Datum get_attoptions(Oid relid, int16 attnum)
Definition: lsyscache.c:996
static AmcheckOptions opts
Definition: pg_amcheck.c:110
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:510
static bytea ** CopyIndexAttOptions(bytea **srcopts, int natts)
Definition: relcache.c:5854
bytea ** rd_opcoptions
Definition: rel.h:217
Definition: c.h:676

References CopyIndexAttOptions(), criticalRelcachesBuilt, DatumGetPointer(), get_attoptions(), i, index_opclass_options(), MemoryContextSwitchTo(), opts, palloc0(), pfree(), RelationData::rd_indexcxt, RelationData::rd_opcoptions, RelationGetNumberOfAttributes, and RelationGetRelid.

Referenced by get_relation_info(), index_getprocinfo(), load_critical_index(), and RelationInitIndexAccessInfo().

◆ RelationGetIndexAttrBitmap()

Bitmapset* RelationGetIndexAttrBitmap ( Relation  relation,
IndexAttrBitmapKind  attrKind 
)

Definition at line 5198 of file relcache.c.

5199 {
5200  Bitmapset *uindexattrs; /* columns in unique indexes */
5201  Bitmapset *pkindexattrs; /* columns in the primary index */
5202  Bitmapset *idindexattrs; /* columns in the replica identity */
5203  Bitmapset *hotblockingattrs; /* columns with HOT blocking indexes */
5204  Bitmapset *summarizedattrs; /* columns with summarizing indexes */
5205  List *indexoidlist;
5206  List *newindexoidlist;
5207  Oid relpkindex;
5208  Oid relreplindex;
5209  ListCell *l;
5210  MemoryContext oldcxt;
5211 
5212  /* Quick exit if we already computed the result. */
5213  if (relation->rd_attrsvalid)
5214  {
5215  switch (attrKind)
5216  {
5217  case INDEX_ATTR_BITMAP_KEY:
5218  return bms_copy(relation->rd_keyattr);
5220  return bms_copy(relation->rd_pkattr);
5222  return bms_copy(relation->rd_idattr);
5224  return bms_copy(relation->rd_hotblockingattr);
5226  return bms_copy(relation->rd_summarizedattr);
5227  default:
5228  elog(ERROR, "unknown attrKind %u", attrKind);
5229  }
5230  }
5231 
5232  /* Fast path if definitely no indexes */
5233  if (!RelationGetForm(relation)->relhasindex)
5234  return NULL;
5235 
5236  /*
5237  * Get cached list of index OIDs. If we have to start over, we do so here.
5238  */
5239 restart:
5240  indexoidlist = RelationGetIndexList(relation);
5241 
5242  /* Fall out if no indexes (but relhasindex was set) */
5243  if (indexoidlist == NIL)
5244  return NULL;
5245 
5246  /*
5247  * Copy the rd_pkindex and rd_replidindex values computed by
5248  * RelationGetIndexList before proceeding. This is needed because a
5249  * relcache flush could occur inside index_open below, resetting the
5250  * fields managed by RelationGetIndexList. We need to do the work with
5251  * stable values of these fields.
5252  */
5253  relpkindex = relation->rd_pkindex;
5254  relreplindex = relation->rd_replidindex;
5255 
5256  /*
5257  * For each index, add referenced attributes to indexattrs.
5258  *
5259  * Note: we consider all indexes returned by RelationGetIndexList, even if
5260  * they are not indisready or indisvalid. This is important because an
5261  * index for which CREATE INDEX CONCURRENTLY has just started must be
5262  * included in HOT-safety decisions (see README.HOT). If a DROP INDEX
5263  * CONCURRENTLY is far enough along that we should ignore the index, it
5264  * won't be returned at all by RelationGetIndexList.
5265  */
5266  uindexattrs = NULL;
5267  pkindexattrs = NULL;
5268  idindexattrs = NULL;
5269  hotblockingattrs = NULL;
5270  summarizedattrs = NULL;
5271  foreach(l, indexoidlist)
5272  {
5273  Oid indexOid = lfirst_oid(l);
5274  Relation indexDesc;
5275  Datum datum;
5276  bool isnull;
5277  Node *indexExpressions;
5278  Node *indexPredicate;
5279  int i;
5280  bool isKey; /* candidate key */
5281  bool isPK; /* primary key */
5282  bool isIDKey; /* replica identity index */
5283  Bitmapset **attrs;
5284 
5285  indexDesc = index_open(indexOid, AccessShareLock);
5286 
5287  /*
5288  * Extract index expressions and index predicate. Note: Don't use
5289  * RelationGetIndexExpressions()/RelationGetIndexPredicate(), because
5290  * those might run constant expressions evaluation, which needs a
5291  * snapshot, which we might not have here. (Also, it's probably more
5292  * sound to collect the bitmaps before any transformations that might
5293  * eliminate columns, but the practical impact of this is limited.)
5294  */
5295 
5296  datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indexprs,
5297  GetPgIndexDescriptor(), &isnull);
5298  if (!isnull)
5299  indexExpressions = stringToNode(TextDatumGetCString(datum));
5300  else
5301  indexExpressions = NULL;
5302 
5303  datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indpred,
5304  GetPgIndexDescriptor(), &isnull);
5305  if (!isnull)
5306  indexPredicate = stringToNode(TextDatumGetCString(datum));
5307  else
5308  indexPredicate = NULL;
5309 
5310  /* Can this index be referenced by a foreign key? */
5311  isKey = indexDesc->rd_index->indisunique &&
5312  indexExpressions == NULL &&
5313  indexPredicate == NULL;
5314 
5315  /* Is this a primary key? */
5316  isPK = (indexOid == relpkindex);
5317 
5318  /* Is this index the configured (or default) replica identity? */
5319  isIDKey = (indexOid == relreplindex);
5320 
5321  /*
5322  * If the index is summarizing, it doesn't block HOT updates, but we
5323  * may still need to update it (if the attributes were modified). So
5324  * decide which bitmap we'll update in the following loop.
5325  */
5326  if (indexDesc->rd_indam->amsummarizing)
5327  attrs = &summarizedattrs;
5328  else
5329  attrs = &hotblockingattrs;
5330 
5331  /* Collect simple attribute references */
5332  for (i = 0; i < indexDesc->rd_index->indnatts; i++)
5333  {
5334  int attrnum = indexDesc->rd_index->indkey.values[i];
5335 
5336  /*
5337  * Since we have covering indexes with non-key columns, we must
5338  * handle them accurately here. non-key columns must be added into
5339  * hotblockingattrs or summarizedattrs, since they are in index,
5340  * and update shouldn't miss them.
5341  *
5342  * Summarizing indexes do not block HOT, but do need to be updated
5343  * when the column value changes, thus require a separate
5344  * attribute bitmapset.
5345  *
5346  * Obviously, non-key columns couldn't be referenced by foreign
5347  * key or identity key. Hence we do not include them into
5348  * uindexattrs, pkindexattrs and idindexattrs bitmaps.
5349  */
5350  if (attrnum != 0)
5351  {
5352  *attrs = bms_add_member(*attrs,
5354 
5355  if (isKey && i < indexDesc->rd_index->indnkeyatts)
5356  uindexattrs = bms_add_member(uindexattrs,
5358 
5359  if (isPK && i < indexDesc->rd_index->indnkeyatts)
5360  pkindexattrs = bms_add_member(pkindexattrs,
5362 
5363  if (isIDKey && i < indexDesc->rd_index->indnkeyatts)
5364  idindexattrs = bms_add_member(idindexattrs,
5366  }
5367  }
5368 
5369  /* Collect all attributes used in expressions, too */
5370  pull_varattnos(indexExpressions, 1, attrs);
5371 
5372  /* Collect all attributes in the index predicate, too */
5373  pull_varattnos(indexPredicate, 1, attrs);
5374 
5375  index_close(indexDesc, AccessShareLock);
5376  }
5377 
5378  /*
5379  * During one of the index_opens in the above loop, we might have received
5380  * a relcache flush event on this relcache entry, which might have been
5381  * signaling a change in the rel's index list. If so, we'd better start
5382  * over to ensure we deliver up-to-date attribute bitmaps.
5383  */
5384  newindexoidlist = RelationGetIndexList(relation);
5385  if (equal(indexoidlist, newindexoidlist) &&
5386  relpkindex == relation->rd_pkindex &&
5387  relreplindex == relation->rd_replidindex)
5388  {
5389  /* Still the same index set, so proceed */
5390  list_free(newindexoidlist);
5391  list_free(indexoidlist);
5392  }
5393  else
5394  {
5395  /* Gotta do it over ... might as well not leak memory */
5396  list_free(newindexoidlist);
5397  list_free(indexoidlist);
5398  bms_free(uindexattrs);
5399  bms_free(pkindexattrs);
5400  bms_free(idindexattrs);
5401  bms_free(hotblockingattrs);
5402  bms_free(summarizedattrs);
5403 
5404  goto restart;
5405  }
5406 
5407  /* Don't leak the old values of these bitmaps, if any */
5408  relation->rd_attrsvalid = false;
5409  bms_free(relation->rd_keyattr);
5410  relation->rd_keyattr = NULL;
5411  bms_free(relation->rd_pkattr);
5412  relation->rd_pkattr = NULL;
5413  bms_free(relation->rd_idattr);
5414  relation->rd_idattr = NULL;
5415  bms_free(relation->rd_hotblockingattr);
5416  relation->rd_hotblockingattr = NULL;
5417  bms_free(relation->rd_summarizedattr);
5418  relation->rd_summarizedattr = NULL;
5419 
5420  /*
5421  * Now save copies of the bitmaps in the relcache entry. We intentionally
5422  * set rd_attrsvalid last, because that's the one that signals validity of
5423  * the values; if we run out of memory before making that copy, we won't
5424  * leave the relcache entry looking like the other ones are valid but
5425  * empty.
5426  */
5428  relation->rd_keyattr = bms_copy(uindexattrs);
5429  relation->rd_pkattr = bms_copy(pkindexattrs);
5430  relation->rd_idattr = bms_copy(idindexattrs);
5431  relation->rd_hotblockingattr = bms_copy(hotblockingattrs);
5432  relation->rd_summarizedattr = bms_copy(summarizedattrs);
5433  relation->rd_attrsvalid = true;
5434  MemoryContextSwitchTo(oldcxt);
5435 
5436  /* We return our original working copy for caller to play with */
5437  switch (attrKind)
5438  {
5439  case INDEX_ATTR_BITMAP_KEY:
5440  return uindexattrs;
5442  return pkindexattrs;
5444  return idindexattrs;
5446  return hotblockingattrs;
5448  return summarizedattrs;
5449  default:
5450  elog(ERROR, "unknown attrKind %u", attrKind);
5451  return NULL;
5452  }
5453 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:223
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:158
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:132
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4740
bool amsummarizing
Definition: amapi.h:248
Bitmapset * rd_keyattr
Definition: rel.h:161
struct IndexAmRoutine * rd_indam
Definition: rel.h:205
bool rd_attrsvalid
Definition: rel.h:160
Bitmapset * rd_hotblockingattr
Definition: rel.h:164
Oid rd_pkindex
Definition: rel.h:153
Bitmapset * rd_summarizedattr
Definition: rel.h:165
Bitmapset * rd_pkattr
Definition: rel.h:162
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition: var.c:291

References AccessShareLock, IndexAmRoutine::amsummarizing, bms_add_member(), bms_copy(), bms_free(), CacheMemoryContext, elog(), equal(), ERROR, FirstLowInvalidHeapAttributeNumber, GetPgIndexDescriptor(), heap_getattr(), i, INDEX_ATTR_BITMAP_HOT_BLOCKING, INDEX_ATTR_BITMAP_IDENTITY_KEY, INDEX_ATTR_BITMAP_KEY, INDEX_ATTR_BITMAP_PRIMARY_KEY, INDEX_ATTR_BITMAP_SUMMARIZED, index_close(), index_open(), lfirst_oid, list_free(), MemoryContextSwitchTo(), NIL, pull_varattnos(), RelationData::rd_attrsvalid, RelationData::rd_hotblockingattr, RelationData::rd_idattr, RelationData::rd_indam, RelationData::rd_index, RelationData::rd_indextuple, RelationData::rd_keyattr, RelationData::rd_pkattr, RelationData::rd_pkindex, RelationData::rd_replidindex, RelationData::rd_summarizedattr, RelationGetForm, RelationGetIndexList(), stringToNode(), and TextDatumGetCString.

Referenced by ATExecDropNotNull(), ATInheritAdjustNotNulls(), dropconstraint_internal(), ExecUpdateLockMode(), ExtractReplicaIdentity(), GetParentedForeignKeyRefs(), heap_update(), logicalrep_rel_mark_updatable(), MergeAttributes(), pub_collist_contains_invalid_column(), pub_rf_contains_invalid_column(), and transformTableLikeClause().

◆ RelationGetIndexExpressions()

List* RelationGetIndexExpressions ( Relation  relation)

Definition at line 4996 of file relcache.c.

4997 {
4998  List *result;
4999  Datum exprsDatum;
5000  bool isnull;
5001  char *exprsString;
5002  MemoryContext oldcxt;
5003 
5004  /* Quick exit if we already computed the result. */
5005  if (relation->rd_indexprs)
5006  return copyObject(relation->rd_indexprs);
5007 
5008  /* Quick exit if there is nothing to do. */
5009  if (relation->rd_indextuple == NULL ||
5010  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indexprs, NULL))
5011  return NIL;
5012 
5013  /*
5014  * We build the tree we intend to return in the caller's context. After
5015  * successfully completing the work, we copy it into the relcache entry.
5016  * This avoids problems if we get some sort of error partway through.
5017  */
5018  exprsDatum = heap_getattr(relation->rd_indextuple,
5019  Anum_pg_index_indexprs,
5021  &isnull);
5022  Assert(!isnull);
5023  exprsString = TextDatumGetCString(exprsDatum);
5024  result = (List *) stringToNode(exprsString);
5025  pfree(exprsString);
5026 
5027  /*
5028  * Run the expressions through eval_const_expressions. This is not just an
5029  * optimization, but is necessary, because the planner will be comparing
5030  * them to similarly-processed qual clauses, and may fail to detect valid
5031  * matches without this. We must not use canonicalize_qual, however,
5032  * since these aren't qual expressions.
5033  */
5034  result = (List *) eval_const_expressions(NULL, (Node *) result);
5035 
5036  /* May as well fix opfuncids too */
5037  fix_opfuncids((Node *) result);
5038 
5039  /* Now save a copy of the completed tree in the relcache entry. */
5040  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
5041  relation->rd_indexprs = copyObject(result);
5042  MemoryContextSwitchTo(oldcxt);
5043 
5044  return result;
5045 }
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2171
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1748
List * rd_indexprs
Definition: rel.h:211

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

Referenced by ATExecReplicaIdentity(), BuildIndexInfo(), get_relation_info(), GetIndexInputType(), index_unchanged_by_update(), infer_arbiter_indexes(), plan_create_index_workers(), and transformIndexConstraint().

◆ RelationGetIndexList()

List* RelationGetIndexList ( Relation  relation)

Definition at line 4740 of file relcache.c.

4741 {
4742  Relation indrel;
4743  SysScanDesc indscan;
4744  ScanKeyData skey;
4745  HeapTuple htup;
4746  List *result;
4747  List *oldlist;
4748  char replident = relation->rd_rel->relreplident;
4749  Oid pkeyIndex = InvalidOid;
4750  Oid candidateIndex = InvalidOid;
4751  MemoryContext oldcxt;
4752 
4753  /* Quick exit if we already computed the list. */
4754  if (relation->rd_indexvalid)
4755  return list_copy(relation->rd_indexlist);
4756 
4757  /*
4758  * We build the list we intend to return (in the caller's context) while
4759  * doing the scan. After successfully completing the scan, we copy that
4760  * list into the relcache entry. This avoids cache-context memory leakage
4761  * if we get some sort of error partway through.
4762  */
4763  result = NIL;
4764 
4765  /* Prepare to scan pg_index for entries having indrelid = this rel. */
4766  ScanKeyInit(&skey,
4767  Anum_pg_index_indrelid,
4768  BTEqualStrategyNumber, F_OIDEQ,
4769  ObjectIdGetDatum(RelationGetRelid(relation)));
4770 
4771  indrel = table_open(IndexRelationId, AccessShareLock);
4772  indscan = systable_beginscan(indrel, IndexIndrelidIndexId, true,
4773  NULL, 1, &skey);
4774 
4775  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4776  {
4778 
4779  /*
4780  * Ignore any indexes that are currently being dropped. This will
4781  * prevent them from being searched, inserted into, or considered in
4782  * HOT-safety decisions. It's unsafe to touch such an index at all
4783  * since its catalog entries could disappear at any instant.
4784  */
4785  if (!index->indislive)
4786  continue;
4787 
4788  /* add index's OID to result list */
4789  result = lappend_oid(result, index->indexrelid);
4790 
4791  /*
4792  * Non-unique, non-immediate or predicate indexes aren't interesting
4793  * for either oid indexes or replication identity indexes, so don't
4794  * check them.
4795  */
4796  if (!index->indisunique ||
4797  !index->indimmediate ||
4798  !heap_attisnull(htup, Anum_pg_index_indpred, NULL))
4799  continue;
4800 
4801  /*
4802  * Remember primary key index, if any. We do this only if the index
4803  * is valid; but if the table is partitioned, then we do it even if
4804  * it's invalid.
4805  *
4806  * The reason for returning invalid primary keys for foreign tables is
4807  * because of pg_dump of NOT NULL constraints, and the fact that PKs
4808  * remain marked invalid until the partitions' PKs are attached to it.
4809  * If we make rd_pkindex invalid, then the attnotnull flag is reset
4810  * after the PK is created, which causes the ALTER INDEX ATTACH
4811  * PARTITION to fail with 'column ... is not marked NOT NULL'. With
4812  * this, dropconstraint_internal() will believe that the columns must
4813  * not have attnotnull reset, so the PKs-on-partitions can be attached
4814  * correctly, until finally the PK-on-parent is marked valid.
4815  *
4816  * Also, this doesn't harm anything, because rd_pkindex is not a
4817  * "real" index anyway, but a RELKIND_PARTITIONED_INDEX.
4818  */
4819  if (index->indisprimary &&
4820  (index->indisvalid ||
4821  relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
4822  pkeyIndex = index->indexrelid;
4823 
4824  if (!index->indisvalid)
4825  continue;
4826 
4827  /* remember explicitly chosen replica index */
4828  if (index->indisreplident)
4829  candidateIndex = index->indexrelid;
4830  }
4831 
4832  systable_endscan(indscan);
4833 
4834  table_close(indrel, AccessShareLock);
4835 
4836  /* Sort the result list into OID order, per API spec. */
4837  list_sort(result, list_oid_cmp);
4838 
4839  /* Now save a copy of the completed list in the relcache entry. */
4841  oldlist = relation->rd_indexlist;
4842  relation->rd_indexlist = list_copy(result);
4843  relation->rd_pkindex = pkeyIndex;
4844  if (replident == REPLICA_IDENTITY_DEFAULT && OidIsValid(pkeyIndex))
4845  relation->rd_replidindex = pkeyIndex;
4846  else if (replident == REPLICA_IDENTITY_INDEX && OidIsValid(candidateIndex))
4847  relation->rd_replidindex = candidateIndex;
4848  else
4849  relation->rd_replidindex = InvalidOid;
4850  relation->rd_indexvalid = true;
4851  MemoryContextSwitchTo(oldcxt);
4852 
4853  /* Don't leak the old list, if there is one */
4854  list_free(oldlist);
4855 
4856  return result;
4857 }
void list_sort(List *list, list_sort_comparator cmp)
Definition: list.c:1673
List * lappend_oid(List *list, Oid datum)
Definition: list.c:374
List * list_copy(const List *oldlist)
Definition: list.c:1572
int list_oid_cmp(const ListCell *p1, const ListCell *p2)
Definition: list.c:1706
FormData_pg_index * Form_pg_index
Definition: pg_index.h:70
bool rd_indexvalid
Definition: rel.h:64
List * rd_indexlist
Definition: rel.h:152
Definition: type.h:95

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

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

◆ RelationGetIndexPredicate()

List* RelationGetIndexPredicate ( Relation  relation)

Definition at line 5109 of file relcache.c.

5110 {
5111  List *result;
5112  Datum predDatum;
5113  bool isnull;
5114  char *predString;
5115  MemoryContext oldcxt;
5116 
5117  /* Quick exit if we already computed the result. */
5118  if (relation->rd_indpred)
5119  return copyObject(relation->rd_indpred);
5120 
5121  /* Quick exit if there is nothing to do. */
5122  if (relation->rd_indextuple == NULL ||
5123  heap_attisnull(relation->rd_indextuple, Anum_pg_index_indpred, NULL))
5124  return NIL;
5125 
5126  /*
5127  * We build the tree we intend to return in the caller's context. After
5128  * successfully completing the work, we copy it into the relcache entry.
5129  * This avoids problems if we get some sort of error partway through.
5130  */
5131  predDatum = heap_getattr(relation->rd_indextuple,
5132  Anum_pg_index_indpred,
5134  &isnull);
5135  Assert(!isnull);
5136  predString = TextDatumGetCString(predDatum);
5137  result = (List *) stringToNode(predString);
5138  pfree(predString);
5139 
5140  /*
5141  * Run the expression through const-simplification and canonicalization.
5142  * This is not just an optimization, but is necessary, because the planner
5143  * will be comparing it to similarly-processed qual clauses, and may fail
5144  * to detect valid matches without this. This must match the processing
5145  * done to qual clauses in preprocess_expression()! (We can skip the
5146  * stuff involving subqueries, however, since we don't allow any in index
5147  * predicates.)
5148  */
5149  result = (List *) eval_const_expressions(NULL, (Node *) result);
5150 
5151  result = (List *) canonicalize_qual((Expr *) result, false);
5152 
5153  /* Also convert to implicit-AND format */
5154  result = make_ands_implicit((Expr *) result);
5155 
5156  /* May as well fix opfuncids too */
5157  fix_opfuncids((Node *) result);
5158 
5159  /* Now save a copy of the completed tree in the relcache entry. */
5160  oldcxt = MemoryContextSwitchTo(relation->rd_indexcxt);
5161  relation->rd_indpred = copyObject(result);
5162  MemoryContextSwitchTo(oldcxt);
5163 
5164  return result;
5165 }
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:722
Expr * canonicalize_qual(Expr *qual, bool is_check)
Definition: prepqual.c:294
List * rd_indpred
Definition: rel.h:212

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

Referenced by ATExecReplicaIdentity(), BuildIndexInfo(), get_relation_info(), infer_arbiter_indexes(), is_usable_unique_index(), plan_create_index_workers(), and transformIndexConstraint().

◆ RelationGetIndexRawAttOptions()

Datum* RelationGetIndexRawAttOptions ( Relation  indexrel)

Definition at line 5828 of file relcache.c.

5829 {
5830  Oid indexrelid = RelationGetRelid(indexrel);
5831  int16 natts = RelationGetNumberOfAttributes(indexrel);
5832  Datum *options = NULL;
5833  int16 attnum;
5834 
5835  for (attnum = 1; attnum <= natts; attnum++)
5836  {
5837  if (indexrel->rd_indam->amoptsprocnum == 0)
5838  continue;
5839 
5840  if (!OidIsValid(index_getprocid(indexrel, attnum,
5841  indexrel->rd_indam->amoptsprocnum)))
5842  continue;
5843 
5844  if (!options)
5845  options = palloc0(sizeof(Datum) * natts);
5846 
5847  options[attnum - 1] = get_attoptions(indexrelid, attnum);
5848  }
5849 
5850  return options;
5851 }
signed short int16
Definition: c.h:482
RegProcedure index_getprocid(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:777
static char ** options
uint16 amoptsprocnum
Definition: amapi.h:218

References IndexAmRoutine::amoptsprocnum, attnum, get_attoptions(), index_getprocid(), OidIsValid, options, palloc0(), RelationData::rd_indam, RelationGetNumberOfAttributes, and RelationGetRelid.

Referenced by BuildIndexInfo(), and CheckIndexCompatible().

◆ RelationGetPrimaryKeyIndex()

Oid RelationGetPrimaryKeyIndex ( Relation  relation)

Definition at line 4950 of file relcache.c.

4951 {
4952  List *ilist;
4953 
4954  if (!relation->rd_indexvalid)
4955  {
4956  /* RelationGetIndexList does the heavy lifting. */
4957  ilist = RelationGetIndexList(relation);
4958  list_free(ilist);
4959  Assert(relation->rd_indexvalid);
4960  }
4961 
4962  return relation->rd_pkindex;
4963 }

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

Referenced by GetRelationIdentityOrPK().

◆ RelationGetReplicaIndex()

Oid RelationGetReplicaIndex ( Relation  relation)

Definition at line 4971 of file relcache.c.

4972 {
4973  List *ilist;
4974 
4975  if (!relation->rd_indexvalid)
4976  {
4977  /* RelationGetIndexList does the heavy lifting. */
4978  ilist = RelationGetIndexList(relation);
4979  list_free(ilist);
4980  Assert(relation->rd_indexvalid);
4981  }
4982 
4983  return relation->rd_replidindex;
4984 }

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

Referenced by CheckCmdReplicaIdentity(), GetRelationIdentityOrPK(), pg_get_replica_identity_index(), and RelationGetIdentityKeyBitmap().

◆ RelationGetStatExtList()

List* RelationGetStatExtList ( Relation  relation)

Definition at line 4881 of file relcache.c.

4882 {
4883  Relation indrel;
4884  SysScanDesc indscan;
4885  ScanKeyData skey;
4886  HeapTuple htup;
4887  List *result;
4888  List *oldlist;
4889  MemoryContext oldcxt;
4890 
4891  /* Quick exit if we already computed the list. */
4892  if (relation->rd_statvalid != 0)
4893  return list_copy(relation->rd_statlist);
4894 
4895  /*
4896  * We build the list we intend to return (in the caller's context) while
4897  * doing the scan. After successfully completing the scan, we copy that
4898  * list into the relcache entry. This avoids cache-context memory leakage
4899  * if we get some sort of error partway through.
4900  */
4901  result = NIL;
4902 
4903  /*
4904  * Prepare to scan pg_statistic_ext for entries having stxrelid = this
4905  * rel.
4906  */
4907  ScanKeyInit(&skey,
4908  Anum_pg_statistic_ext_stxrelid,
4909  BTEqualStrategyNumber, F_OIDEQ,
4910  ObjectIdGetDatum(RelationGetRelid(relation)));
4911 
4912  indrel = table_open(StatisticExtRelationId, AccessShareLock);
4913  indscan = systable_beginscan(indrel, StatisticExtRelidIndexId, true,
4914  NULL, 1, &skey);
4915 
4916  while (HeapTupleIsValid(htup = systable_getnext(indscan)))
4917  {
4918  Oid oid = ((Form_pg_statistic_ext) GETSTRUCT(htup))->oid;
4919 
4920  result = lappend_oid(result, oid);
4921  }
4922 
4923  systable_endscan(indscan);
4924 
4925  table_close(indrel, AccessShareLock);
4926 
4927  /* Sort the result list into OID order, per API spec. */
4928  list_sort(result, list_oid_cmp);
4929 
4930  /* Now save a copy of the completed list in the relcache entry. */
4932  oldlist = relation->rd_statlist;
4933  relation->rd_statlist = list_copy(result);
4934 
4935  relation->rd_statvalid = true;
4936  MemoryContextSwitchTo(oldcxt);
4937 
4938  /* Don't leak the old list, if there is one */
4939  list_free(oldlist);
4940 
4941  return result;
4942 }
FormData_pg_statistic_ext * Form_pg_statistic_ext
bool rd_statvalid
Definition: rel.h:66
List * rd_statlist
Definition: rel.h:157

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

Referenced by get_relation_statistics(), and transformTableLikeClause().

◆ RelationIdGetRelation()

Relation RelationIdGetRelation ( Oid  relationId)

Definition at line 2054 of file relcache.c.

2055 {
2056  Relation rd;
2057 
2058  /* Make sure we're in an xact, even if this ends up being a cache hit */
2060 
2061  /*
2062  * first try to find reldesc in the cache
2063  */
2064  RelationIdCacheLookup(relationId, rd);
2065 
2066  if (RelationIsValid(rd))
2067  {
2068  /* return NULL for dropped relations */
2070  {
2071  Assert(!rd->rd_isvalid);
2072  return NULL;
2073  }
2074 
2076  /* revalidate cache entry if necessary */
2077  if (!rd->rd_isvalid)
2078  {
2079  /*
2080  * Indexes only have a limited number of possible schema changes,
2081  * and we don't want to use the full-blown procedure because it's
2082  * a headache for indexes that reload itself depends on.
2083  */
2084  if (rd->rd_rel->relkind == RELKIND_INDEX ||
2085  rd->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
2087  else
2088  RelationClearRelation(rd, true);
2089 
2090  /*
2091  * Normally entries need to be valid here, but before the relcache
2092  * has been initialized, not enough infrastructure exists to
2093  * perform pg_class lookups. The structure of such entries doesn't
2094  * change, but we still want to update the rd_rel entry. So
2095  * rd_isvalid = false is left in place for a later lookup.
2096  */
2097  Assert(rd->rd_isvalid ||
2099  }
2100  return rd;
2101  }
2102 
2103  /*
2104  * no reldesc in the cache, so have RelationBuildDesc() build one and add
2105  * it.
2106  */
2107  rd = RelationBuildDesc(relationId, true);
2108  if (RelationIsValid(rd))
2110  return rd;
2111 }
static Relation RelationBuildDesc(Oid targetRelId, bool insertIt)
Definition: relcache.c:1038
static void RelationReloadIndexInfo(Relation relation)
Definition: relcache.c:2217
bool IsTransactionState(void)
Definition: xact.c:378

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

Referenced by init_tuple_slot(), maybe_send_schema(), pgoutput_change(), pgoutput_column_list_init(), pgoutput_ensure_entry_cxt(), pgoutput_row_filter_init(), relation_open(), RelationGetIdentityKeyBitmap(), ReorderBufferProcessTXN(), ReorderBufferToastReplace(), and try_relation_open().

◆ RelationIdIsInInitFile()

bool RelationIdIsInInitFile ( Oid  relationId)

Definition at line 6696 of file relcache.c.

6697 {
6698  if (relationId == SharedSecLabelRelationId ||
6699  relationId == TriggerRelidNameIndexId ||
6700  relationId == DatabaseNameIndexId ||
6701  relationId == SharedSecLabelObjectIndexId)
6702  {
6703  /*
6704  * If this Assert fails, we don't need the applicable special case
6705  * anymore.
6706  */
6707  Assert(!RelationSupportsSysCache(relationId));
6708  return true;
6709  }
6710  return RelationSupportsSysCache(relationId);
6711 }
bool RelationSupportsSysCache(Oid relid)
Definition: syscache.c:1251

References Assert(), and RelationSupportsSysCache().

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

◆ RelationInitIndexAccessInfo()

void RelationInitIndexAccessInfo ( Relation  relation)

Definition at line 1417 of file relcache.c.

1418 {
1419  HeapTuple tuple;
1420  Form_pg_am aform;
1421  Datum indcollDatum;
1422  Datum indclassDatum;
1423  Datum indoptionDatum;
1424  bool isnull;
1425  oidvector *indcoll;
1426  oidvector *indclass;
1427  int2vector *indoption;
1428  MemoryContext indexcxt;
1429  MemoryContext oldcontext;
1430  int indnatts;
1431  int indnkeyatts;
1432  uint16 amsupport;
1433 
1434  /*
1435  * Make a copy of the pg_index entry for the index. Since pg_index
1436  * contains variable-length and possibly-null fields, we have to do this
1437  * honestly rather than just treating it as a Form_pg_index struct.
1438  */
1439  tuple = SearchSysCache1(INDEXRELID,
1440  ObjectIdGetDatum(RelationGetRelid(relation)));
1441  if (!HeapTupleIsValid(tuple))
1442  elog(ERROR, "cache lookup failed for index %u",
1443  RelationGetRelid(relation));
1445  relation->rd_indextuple = heap_copytuple(tuple);
1446  relation->rd_index = (Form_pg_index) GETSTRUCT(relation->rd_indextuple);
1447  MemoryContextSwitchTo(oldcontext);
1448  ReleaseSysCache(tuple);
1449 
1450  /*
1451  * Look up the index's access method, save the OID of its handler function
1452  */
1453  Assert(relation->rd_rel->relam != InvalidOid);
1454  tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(relation->rd_rel->relam));
1455  if (!HeapTupleIsValid(tuple))
1456  elog(ERROR, "cache lookup failed for access method %u",
1457  relation->rd_rel->relam);
1458  aform = (Form_pg_am) GETSTRUCT(tuple);
1459  relation->rd_amhandler = aform->amhandler;
1460  ReleaseSysCache(tuple);
1461 
1462  indnatts = RelationGetNumberOfAttributes(relation);
1463  if (indnatts != IndexRelationGetNumberOfAttributes(relation))
1464  elog(ERROR, "relnatts disagrees with indnatts for index %u",
1465  RelationGetRelid(relation));
1466  indnkeyatts = IndexRelationGetNumberOfKeyAttributes(relation);
1467 
1468  /*
1469  * Make the private context to hold index access info. The reason we need
1470  * a context, and not just a couple of pallocs, is so that we won't leak
1471  * any subsidiary info attached to fmgr lookup records.
1472  */
1474  "index info",
1476  relation->rd_indexcxt = indexcxt;
1478  RelationGetRelationName(relation));
1479 
1480  /*
1481  * Now we can fetch the index AM's API struct
1482  */
1483  InitIndexAmRoutine(relation);
1484 
1485  /*
1486  * Allocate arrays to hold data. Opclasses are not used for included
1487  * columns, so allocate them for indnkeyatts only.
1488  */
1489  relation->rd_opfamily = (Oid *)
1490  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1491  relation->rd_opcintype = (Oid *)
1492  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1493 
1494  amsupport = relation->rd_indam->amsupport;
1495  if (amsupport > 0)
1496  {
1497  int nsupport = indnatts * amsupport;
1498 
1499  relation->rd_support = (RegProcedure *)
1500  MemoryContextAllocZero(indexcxt, nsupport * sizeof(RegProcedure));
1501  relation->rd_supportinfo = (FmgrInfo *)
1502  MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
1503  }
1504  else
1505  {
1506  relation->rd_support = NULL;
1507  relation->rd_supportinfo = NULL;
1508  }
1509 
1510  relation->rd_indcollation = (Oid *)
1511  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(Oid));
1512 
1513  relation->rd_indoption = (int16 *)
1514  MemoryContextAllocZero(indexcxt, indnkeyatts * sizeof(int16));
1515 
1516  /*
1517  * indcollation cannot be referenced directly through the C struct,
1518  * because it comes after the variable-width indkey field. Must extract
1519  * the datum the hard way...
1520  */
1521  indcollDatum = fastgetattr(relation->rd_indextuple,
1522  Anum_pg_index_indcollation,
1524  &isnull);
1525  Assert(!isnull);
1526  indcoll = (oidvector *) DatumGetPointer(indcollDatum);
1527  memcpy(relation->rd_indcollation, indcoll->values, indnkeyatts * sizeof(Oid));
1528 
1529  /*
1530  * indclass cannot be referenced directly through the C struct, because it
1531  * comes after the variable-width indkey field. Must extract the datum
1532  * the hard way...
1533  */
1534  indclassDatum = fastgetattr(relation->rd_indextuple,
1535  Anum_pg_index_indclass,
1537  &isnull);
1538  Assert(!isnull);
1539  indclass = (oidvector *) DatumGetPointer(indclassDatum);
1540 
1541  /*
1542  * Fill the support procedure OID array, as well as the info about
1543  * opfamilies and opclass input types. (aminfo and supportinfo are left
1544  * as zeroes, and are filled on-the-fly when used)
1545  */
1546  IndexSupportInitialize(indclass, relation->rd_support,
1547  relation->rd_opfamily, relation->rd_opcintype,
1548  amsupport, indnkeyatts);
1549 
1550  /*
1551  * Similarly extract indoption and copy it to the cache entry
1552  */
1553  indoptionDatum = fastgetattr(relation->rd_indextuple,
1554  Anum_pg_index_indoption,
1556  &isnull);
1557  Assert(!isnull);
1558  indoption = (int2vector *) DatumGetPointer(indoptionDatum);
1559  memcpy(relation->rd_indoption, indoption->values, indnkeyatts * sizeof(int16));
1560 
1561  (void) RelationGetIndexAttOptions(relation, false);
1562 
1563  /*
1564  * expressions, predicate, exclusion caches will be filled later
1565  */
1566  relation->rd_indexprs = NIL;
1567  relation->rd_indpred = NIL;
1568  relation->rd_exclops = NULL;
1569  relation->rd_exclprocs = NULL;
1570  relation->rd_exclstrats = NULL;
1571  relation->rd_amcache = NULL;
1572 }
regproc RegProcedure
Definition: c.h:639
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:768
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1064
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:163
#define MemoryContextCopyAndSetIdentifier(cxt, id)
Definition: memutils.h:101
FormData_pg_am * Form_pg_am
Definition: pg_am.h:48
#define IndexRelationGetNumberOfAttributes(relation)
Definition: rel.h:516
static void InitIndexAmRoutine(Relation relation)
Definition: relcache.c:1393
static void IndexSupportInitialize(oidvector *indclass, RegProcedure *indexSupport, Oid *opFamily, Oid *opcInType, StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber)
Definition: relcache.c:1588
bytea ** RelationGetIndexAttOptions(Relation relation, bool copy)
Definition: relcache.c:5874
Definition: fmgr.h:57
uint16 amsupport
Definition: amapi.h:216
RegProcedure * rd_support
Definition: rel.h:208
Oid * rd_opcintype
Definition: rel.h:207
int16 * rd_indoption
Definition: rel.h:210
void * rd_amcache
Definition: rel.h:228
Oid rd_amhandler
Definition: rel.h:183
struct FmgrInfo * rd_supportinfo
Definition: rel.h:209
Oid * rd_indcollation
Definition: rel.h:216
Definition: c.h:704
int16 values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:711
Definition: c.h:715
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:722
@ AMOID
Definition: syscache.h:36
@ INDEXRELID
Definition: syscache.h:66

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

Referenced by index_create(), and RelationBuildDesc().

◆ RelationInitTableAccessMethod()

void RelationInitTableAccessMethod ( Relation  relation)

Definition at line 1801 of file relcache.c.

1802 {
1803  HeapTuple tuple;
1804  Form_pg_am aform;
1805 
1806  if (relation->rd_rel->relkind == RELKIND_SEQUENCE)
1807  {
1808  /*
1809  * Sequences are currently accessed like heap tables, but it doesn't
1810  * seem prudent to show that in the catalog. So just overwrite it
1811  * here.
1812  */
1813  Assert(relation->rd_rel->relam == InvalidOid);
1814  relation->rd_amhandler = F_HEAP_TABLEAM_HANDLER;
1815  }
1816  else if (IsCatalogRelation(relation))
1817  {
1818  /*
1819  * Avoid doing a syscache lookup for catalog tables.
1820  */
1821  Assert(relation->rd_rel->relam == HEAP_TABLE_AM_OID);
1822  relation->rd_amhandler = F_HEAP_TABLEAM_HANDLER;
1823  }
1824  else
1825  {
1826  /*
1827  * Look up the table access method, save the OID of its handler
1828  * function.
1829  */
1830  Assert(relation->rd_rel->relam != InvalidOid);
1831  tuple = SearchSysCache1(AMOID,
1832  ObjectIdGetDatum(relation->rd_rel->relam));
1833  if (!HeapTupleIsValid(tuple))
1834  elog(ERROR, "cache lookup failed for access method %u",
1835  relation->rd_rel->relam);
1836  aform = (Form_pg_am) GETSTRUCT(tuple);
1837  relation->rd_amhandler = aform->amhandler;
1838  ReleaseSysCache(tuple);
1839  }
1840 
1841  /*
1842  * Now we can fetch the table AM's API struct
1843  */
1844  InitTableAmRoutine(relation);
1845 }
bool IsCatalogRelation(Relation relation)
Definition: catalog.c:105
static void InitTableAmRoutine(Relation relation)
Definition: relcache.c:1792

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

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

◆ RelationSetNewRelfilenumber()

void RelationSetNewRelfilenumber ( Relation  relation,
char  persistence 
)

Definition at line 3710 of file relcache.c.

3711 {
3712  RelFileNumber newrelfilenumber;
3713  Relation pg_class;
3714  HeapTuple tuple;
3715  Form_pg_class classform;
3716  MultiXactId minmulti = InvalidMultiXactId;
3717  TransactionId freezeXid = InvalidTransactionId;
3718  RelFileLocator newrlocator;
3719 
3720  if (!IsBinaryUpgrade)
3721  {
3722  /* Allocate a new relfilenumber */
3723  newrelfilenumber = GetNewRelFileNumber(relation->rd_rel->reltablespace,
3724  NULL, persistence);
3725  }
3726  else if (relation->rd_rel->relkind == RELKIND_INDEX)
3727  {
3729  ereport(ERROR,
3730  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3731  errmsg("index relfilenumber value not set when in binary upgrade mode")));
3732 
3735  }
3736  else if (relation->rd_rel->relkind == RELKIND_RELATION)
3737  {
3739  ereport(ERROR,
3740  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3741  errmsg("heap relfilenumber value not set when in binary upgrade mode")));
3742 
3745  }
3746  else
3747  ereport(ERROR,
3748  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3749  errmsg("unexpected request for new relfilenumber in binary upgrade mode")));
3750 
3751  /*
3752  * Get a writable copy of the pg_class tuple for the given relation.
3753  */
3754  pg_class = table_open(RelationRelationId, RowExclusiveLock);
3755 
3756  tuple = SearchSysCacheCopy1(RELOID,
3757  ObjectIdGetDatum(RelationGetRelid(relation)));
3758  if (!HeapTupleIsValid(tuple))
3759  elog(ERROR, "could not find tuple for relation %u",
3760  RelationGetRelid(relation));
3761  classform = (Form_pg_class) GETSTRUCT(tuple);
3762 
3763  /*
3764  * Schedule unlinking of the old storage at transaction commit, except
3765  * when performing a binary upgrade, when we must do it immediately.
3766  */
3767  if (IsBinaryUpgrade)
3768  {
3769  SMgrRelation srel;
3770 
3771  /*
3772  * During a binary upgrade, we use this code path to ensure that
3773  * pg_largeobject and its index have the same relfilenumbers as in the
3774  * old cluster. This is necessary because pg_upgrade treats
3775  * pg_largeobject like a user table, not a system table. It is however
3776  * possible that a table or index may need to end up with the same
3777  * relfilenumber in the new cluster as what it had in the old cluster.
3778  * Hence, we can't wait until commit time to remove the old storage.
3779  *
3780  * In general, this function needs to have transactional semantics,
3781  * and removing the old storage before commit time surely isn't.
3782  * However, it doesn't really matter, because if a binary upgrade
3783  * fails at this stage, the new cluster will need to be recreated
3784  * anyway.
3785  */
3786  srel = smgropen(relation->rd_locator, relation->rd_backend);
3787  smgrdounlinkall(&srel, 1, false);
3788  smgrclose(srel);
3789  }
3790  else
3791  {
3792  /* Not a binary upgrade, so just schedule it to happen later. */
3793  RelationDropStorage(relation);
3794  }
3795 
3796  /*
3797  * Create storage for the main fork of the new relfilenumber. If it's a
3798  * table-like object, call into the table AM to do so, which'll also
3799  * create the table's init fork if needed.
3800  *
3801  * NOTE: If relevant for the AM, any conflict in relfilenumber value will
3802  * be caught here, if GetNewRelFileNumber messes up for any reason.
3803  */
3804  newrlocator = relation->rd_locator;
3805  newrlocator.relNumber = newrelfilenumber;
3806 
3807  if (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind))
3808  {
3809  table_relation_set_new_filelocator(relation, &newrlocator,
3810  persistence,
3811  &freezeXid, &minmulti);
3812  }
3813  else if (RELKIND_HAS_STORAGE(relation->rd_rel->relkind))
3814  {
3815  /* handle these directly, at least for now */
3816  SMgrRelation srel;
3817 
3818  srel = RelationCreateStorage(newrlocator, persistence, true);
3819  smgrclose(srel);
3820  }
3821  else
3822  {
3823  /* we shouldn't be called for anything else */
3824  elog(ERROR, "relation \"%s\" does not have storage",
3825  RelationGetRelationName(relation));
3826  }
3827 
3828  /*
3829  * If we're dealing with a mapped index, pg_class.relfilenode doesn't
3830  * change; instead we have to send the update to the relation mapper.
3831  *
3832  * For mapped indexes, we don't actually change the pg_class entry at all;
3833  * this is essential when reindexing pg_class itself. That leaves us with
3834  * possibly-inaccurate values of relpages etc, but those will be fixed up
3835  * later.
3836  */
3837  if (RelationIsMapped(relation))
3838  {
3839  /* This case is only supported for indexes */
3840  Assert(relation->rd_rel->relkind == RELKIND_INDEX);
3841 
3842  /* Since we're not updating pg_class, these had better not change */
3843  Assert(classform->relfrozenxid == freezeXid);
3844  Assert(classform->relminmxid == minmulti);
3845  Assert(classform->relpersistence == persistence);
3846 
3847  /*
3848  * In some code paths it's possible that the tuple update we'd
3849  * otherwise do here is the only thing that would assign an XID for
3850  * the current transaction. However, we must have an XID to delete
3851  * files, so make sure one is assigned.
3852  */
3853  (void) GetCurrentTransactionId();
3854 
3855  /* Do the deed */
3857  newrelfilenumber,
3858  relation->rd_rel->relisshared,
3859  false);
3860 
3861  /* Since we're not updating pg_class, must trigger inval manually */
3862  CacheInvalidateRelcache(relation);
3863  }
3864  else
3865  {
3866  /* Normal case, update the pg_class entry */
3867  classform->relfilenode = newrelfilenumber;
3868 
3869  /* relpages etc. never change for sequences */
3870  if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
3871  {
3872  classform->relpages = 0; /* it's empty until further notice */
3873  classform->reltuples = -1;
3874  classform->relallvisible = 0;
3875  }
3876  classform->relfrozenxid = freezeXid;
3877  classform->relminmxid = minmulti;
3878  classform->relpersistence = persistence;
3879 
3880  CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
3881  }
3882 
3883  heap_freetuple(tuple);
3884 
3885  table_close(pg_class, RowExclusiveLock);
3886 
3887  /*
3888  * Make the pg_class row change or relation map change visible. This will
3889  * cause the relcache entry to get updated, too.
3890  */
3892 
3894 }
TransactionId MultiXactId
Definition: c.h:651
uint32 TransactionId
Definition: c.h:641
RelFileNumber GetNewRelFileNumber(Oid reltablespace, Relation pg_class, char relpersistence)
Definition: catalog.c:502
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ereport(elevel,...)
Definition: elog.h:149
bool IsBinaryUpgrade
Definition: globals.c:114
RelFileNumber binary_upgrade_next_heap_pg_class_relfilenumber
Definition: heap.c:81
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1426
RelFileNumber binary_upgrade_next_index_pg_class_relfilenumber
Definition: index.c:91
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
void CacheInvalidateRelcache(Relation relation)
Definition: inval.c:1363
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvalidMultiXactId
Definition: multixact.h:24
void RelationAssumeNewRelfilelocator(Relation relation)
Definition: relcache.c:3909
Oid RelFileNumber
Definition: relpath.h:25
void smgrclose(SMgrRelation reln)
Definition: smgr.c:260
SMgrRelation smgropen(RelFileLocator rlocator, BackendId backend)
Definition: smgr.c:150
void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
Definition: smgr.c:425
SMgrRelation RelationCreateStorage(RelFileLocator rlocator, char relpersistence, bool register_delete)
Definition: storage.c:120
void RelationDropStorage(Relation rel)
Definition: storage.c:205
ItemPointerData t_self
Definition: htup.h:65
RelFileNumber relNumber
RelFileLocator rd_locator
Definition: rel.h:57
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:182
static void table_relation_set_new_filelocator(Relation rel, const RelFileLocator *newrlocator, char persistence, TransactionId *freezeXid, MultiXactId *minmulti)
Definition: tableam.h:1616
#define InvalidTransactionId
Definition: transam.h:31
void CommandCounterIncrement(void)
Definition: xact.c:1078
TransactionId GetCurrentTransactionId(void)
Definition: xact.c:445

References Assert(), binary_upgrade_next_heap_pg_class_relfilenumber, binary_upgrade_next_index_pg_class_relfilenumber, CacheInvalidateRelcache(), CatalogTupleUpdate(), CommandCounterIncrement(), elog(), ereport, errcode(), errmsg(), ERROR, GetCurrentTransactionId(), GetNewRelFileNumber(), GETSTRUCT, heap_freetuple(), HeapTupleIsValid, InvalidMultiXactId, InvalidOid, InvalidTransactionId, IsBinaryUpgrade, ObjectIdGetDatum(), OidIsValid, RelationData::rd_backend, RelationData::rd_locator, RelationData::rd_rel, RelationAssumeNewRelfilelocator(), RelationCreateStorage(), RelationDropStorage(), RelationGetRelationName, RelationGetRelid, RelationIsMapped, RelationMapUpdateMap(), RelFileLocator::relNumber, RELOID, RowExclusiveLock, SearchSysCacheCopy1, smgrclose(), smgrdounlinkall(), smgropen(), HeapTupleData::t_self, table_close(), table_open(), and table_relation_set_new_filelocator().

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

Variable Documentation

◆ criticalRelcachesBuilt

◆ criticalSharedRelcachesBuilt