PostgreSQL Source Code  git master
relcache.c File Reference
#include "postgres.h"
#include <sys/file.h>
#include <fcntl.h>
#include <unistd.h>
#include "access/htup_details.h"
#include "access/multixact.h"
#include "access/nbtree.h"
#include "access/parallel.h"
#include "access/reloptions.h"
#include "access/sysattr.h"
#include "access/table.h"
#include "access/tableam.h"
#include "access/tupdesc_details.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "catalog/catalog.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_am.h"
#include "catalog/pg_amproc.h"
#include "catalog/pg_attrdef.h"
#include "catalog/pg_auth_members.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_database.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_publication.h"
#include "catalog/pg_rewrite.h"
#include "catalog/pg_shseclabel.h"
#include "catalog/pg_statistic_ext.h"
#include "catalog/pg_subscription.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
#include "catalog/schemapg.h"
#include "catalog/storage.h"
#include "commands/policy.h"
#include "commands/trigger.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/optimizer.h"
#include "rewrite/rewriteDefine.h"
#include "rewrite/rowsecurity.h"
#include "storage/lmgr.h"
#include "storage/smgr.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/relmapper.h"
#include "utils/resowner_private.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
Include dependency graph for relcache.c:

Go to the source code of this file.

Data Structures

struct  relidcacheent
 
struct  opclasscacheent
 

Macros

#define RELCACHE_INIT_FILEMAGIC   0x573266 /* version ID value */
 
#define RECOVER_RELATION_BUILD_MEMORY   0
 
#define MAX_EOXACT_LIST   32
 
#define EOXactListAdd(rel)
 
#define RelationCacheInsert(RELATION, replace_allowed)
 
#define RelationIdCacheLookup(ID, RELATION)
 
#define RelationCacheDelete(RELATION)
 
#define SWAPFIELD(fldtype, fldname)
 
#define INITRELCACHESIZE   400
 
#define NUM_CRITICAL_SHARED_RELS   5 /* fix if you change list above */
 
#define NUM_CRITICAL_LOCAL_RELS   4 /* fix if you change list above */
 
#define NUM_CRITICAL_LOCAL_INDEXES   7 /* fix if you change list above */
 
#define NUM_CRITICAL_SHARED_INDEXES   6 /* fix if you change list above */
 

Typedefs

typedef struct relidcacheent RelIdCacheEnt
 
typedef struct opclasscacheent OpClassCacheEnt
 

Functions

static void RelationDestroyRelation (Relation relation, bool remember_tupdesc)
 
static void RelationClearRelation (Relation relation, bool rebuild)
 
static void RelationReloadIndexInfo (Relation relation)
 
static void RelationReloadNailed (Relation relation)
 
static void RelationFlushRelation (Relation relation)
 
static void RememberToFreeTupleDescAtEOX (TupleDesc td)
 
static void AtEOXact_cleanup (Relation relation, bool isCommit)
 
static void AtEOSubXact_cleanup (Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
 
static bool load_relcache_init_file (bool shared)
 
static void write_relcache_init_file (bool shared)
 
static void write_item (const void *data, Size len, FILE *fp)
 
static void formrdesc (const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
 
static HeapTuple ScanPgRelation (Oid targetRelId, bool indexOK, bool force_non_historic)
 
static Relation AllocateRelationDesc (Form_pg_class relp)
 
static void RelationParseRelOptions (Relation relation, HeapTuple tuple)
 
static void RelationBuildTupleDesc (Relation relation)
 
static Relation RelationBuildDesc (Oid targetRelId, bool insertIt)
 
static void RelationInitPhysicalAddr (Relation relation)
 
static void load_critical_index (Oid indexoid, Oid heapoid)
 
static TupleDesc GetPgClassDescriptor (void)
 
static TupleDesc GetPgIndexDescriptor (void)
 
static void AttrDefaultFetch (Relation relation)
 
static void CheckConstraintFetch (Relation relation)
 
static int CheckConstraintCmp (const void *a, const void *b)
 
static void InitIndexAmRoutine (Relation relation)
 
static void IndexSupportInitialize (oidvector *indclass, RegProcedure *indexSupport, Oid *opFamily, Oid *opcInType, StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber)
 
static OpClassCacheEntLookupOpclassInfo (Oid operatorClassOid, StrategyNumber numSupport)
 
static void RelationCacheInitFileRemoveInDir (const char *tblspcpath)
 
static void unlink_initfile (const char *initfilename, int elevel)
 
static void RelationBuildRuleLock (Relation relation)
 
static bool equalRuleLocks (RuleLock *rlock1, RuleLock *rlock2)
 
static bool equalPolicy (RowSecurityPolicy *policy1, RowSecurityPolicy *policy2)
 
static bool equalRSDesc (RowSecurityDesc *rsdesc1, RowSecurityDesc *rsdesc2)
 
void RelationInitIndexAccessInfo (Relation relation)
 
static void InitTableAmRoutine (Relation relation)
 
void RelationInitTableAccessMethod (Relation relation)
 
Relation RelationIdGetRelation (Oid relationId)
 
void RelationIncrementReferenceCount (Relation rel)
 
void RelationDecrementReferenceCount (Relation rel)
 
void RelationClose (Relation relation)
 
void RelationForgetRelation (Oid rid)
 
void RelationCacheInvalidateEntry (Oid relationId)
 
void RelationCacheInvalidate (void)
 
void RelationCloseSmgrByOid (Oid relationId)
 
void AtEOXact_RelationCache (bool isCommit)
 
void AtEOSubXact_RelationCache (bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
 
Relation RelationBuildLocalRelation (const char *relname, Oid relnamespace, TupleDesc tupDesc, Oid relid, Oid accessmtd, Oid relfilenode, Oid reltablespace, bool shared_relation, bool mapped_relation, char relpersistence, char relkind)
 
void RelationSetNewRelfilenode (Relation relation, char persistence)
 
void RelationAssumeNewRelfilenode (Relation relation)
 
void RelationCacheInitialize (void)
 
void RelationCacheInitializePhase2 (void)
 
void RelationCacheInitializePhase3 (void)
 
static TupleDesc BuildHardcodedDescriptor (int natts, const FormData_pg_attribute *attrs)
 
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)
 
BitmapsetRelationGetIndexAttrBitmap (Relation relation, IndexAttrBitmapKind attrKind)
 
void RelationGetExclusionInfo (Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
 
struct PublicationActionsGetRelationPublicationActions (Relation relation)
 
DatumRelationGetIndexRawAttOptions (Relation indexrel)
 
static bytea ** CopyIndexAttOptions (bytea **srcopts, int natts)
 
bytea ** RelationGetIndexAttOptions (Relation relation, bool copy)
 
int errtable (Relation rel)
 
int errtablecol (Relation rel, int attnum)
 
int errtablecolname (Relation rel, const char *colname)
 
int errtableconstraint (Relation rel, const char *conname)
 
bool RelationIdIsInInitFile (Oid relationId)
 
void RelationCacheInitFilePreInvalidate (void)
 
void RelationCacheInitFilePostInvalidate (void)
 
void RelationCacheInitFileRemove (void)
 

Variables

static const FormData_pg_attribute Desc_pg_class [Natts_pg_class] = {Schema_pg_class}
 
static const FormData_pg_attribute Desc_pg_attribute [Natts_pg_attribute] = {Schema_pg_attribute}
 
static const FormData_pg_attribute Desc_pg_proc [Natts_pg_proc] = {Schema_pg_proc}
 
static const FormData_pg_attribute Desc_pg_type [Natts_pg_type] = {Schema_pg_type}
 
static const FormData_pg_attribute Desc_pg_database [Natts_pg_database] = {Schema_pg_database}
 
static const FormData_pg_attribute Desc_pg_authid [Natts_pg_authid] = {Schema_pg_authid}
 
static const FormData_pg_attribute Desc_pg_auth_members [Natts_pg_auth_members] = {Schema_pg_auth_members}
 
static const FormData_pg_attribute Desc_pg_index [Natts_pg_index] = {Schema_pg_index}
 
static const FormData_pg_attribute Desc_pg_shseclabel [Natts_pg_shseclabel] = {Schema_pg_shseclabel}
 
static const FormData_pg_attribute Desc_pg_subscription [Natts_pg_subscription] = {Schema_pg_subscription}
 
static HTABRelationIdCache
 
bool criticalRelcachesBuilt = false
 
bool criticalSharedRelcachesBuilt = false
 
static long relcacheInvalsReceived = 0L
 
static Oid eoxact_list [MAX_EOXACT_LIST]
 
static int eoxact_list_len = 0
 
static bool eoxact_list_overflowed = false
 
static TupleDescEOXactTupleDescArray
 
static int NextEOXactTupleDescNum = 0
 
static int EOXactTupleDescArrayLen = 0
 
static HTABOpClassCache = NULL
 

Macro Definition Documentation

◆ EOXactListAdd

#define EOXactListAdd (   rel)
Value:
do { \
eoxact_list[eoxact_list_len++] = (rel)->rd_id; \
else \
eoxact_list_overflowed = true; \
} while (0)
#define MAX_EOXACT_LIST
Definition: relcache.c:162
static int eoxact_list_len
Definition: relcache.c:164

Definition at line 167 of file relcache.c.

Referenced by RelationAssumeNewRelfilenode(), and RelationBuildLocalRelation().

◆ INITRELCACHESIZE

#define INITRELCACHESIZE   400

Definition at line 3752 of file relcache.c.

Referenced by RelationCacheInitialize().

◆ MAX_EOXACT_LIST

#define MAX_EOXACT_LIST   32

Definition at line 162 of file relcache.c.

◆ NUM_CRITICAL_LOCAL_INDEXES

#define NUM_CRITICAL_LOCAL_INDEXES   7 /* fix if you change list above */

Referenced by load_relcache_init_file().

◆ NUM_CRITICAL_LOCAL_RELS

#define NUM_CRITICAL_LOCAL_RELS   4 /* fix if you change list above */

Referenced by load_relcache_init_file().

◆ NUM_CRITICAL_SHARED_INDEXES

#define NUM_CRITICAL_SHARED_INDEXES   6 /* fix if you change list above */

Referenced by load_relcache_init_file().

◆ NUM_CRITICAL_SHARED_RELS

#define NUM_CRITICAL_SHARED_RELS   5 /* fix if you change list above */

Referenced by load_relcache_init_file().

◆ RECOVER_RELATION_BUILD_MEMORY

#define RECOVER_RELATION_BUILD_MEMORY   0

Definition at line 100 of file relcache.c.

◆ RelationCacheDelete

#define RelationCacheDelete (   RELATION)
Value:
do { \
RelIdCacheEnt *hentry; \
(void *) &((RELATION)->rd_id), \
HASH_REMOVE, NULL); \
if (hentry == NULL) \
elog(WARNING, "failed to delete relcache entry for OID %u", \
(RELATION)->rd_id); \
} while(0)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:907
static HTAB * RelationIdCache
Definition: relcache.c:130
#define WARNING
Definition: elog.h:40

Definition at line 221 of file relcache.c.

Referenced by RelationClearRelation().

◆ RelationCacheInsert

#define RelationCacheInsert (   RELATION,
  replace_allowed 
)
Value:
do { \
RelIdCacheEnt *hentry; bool found; \
(void *) &((RELATION)->rd_id), \
HASH_ENTER, &found); \
if (found) \
{ \
/* see comments in RelationBuildDesc and RelationBuildLocalRelation */ \
Relation _old_rel = hentry->reldesc; \
Assert(replace_allowed); \
hentry->reldesc = (RELATION); \
RelationDestroyRelation(_old_rel, false); \
elog(WARNING, "leaking still-referenced relcache entry for \"%s\"", \
} \
else \
hentry->reldesc = (RELATION); \
} while(0)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:907
static HTAB * RelationIdCache
Definition: relcache.c:130
#define RelationGetRelationName(relation)
Definition: rel.h:490
#define WARNING
Definition: elog.h:40
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:440
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:392

Definition at line 187 of file relcache.c.

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

◆ RelationIdCacheLookup

#define RelationIdCacheLookup (   ID,
  RELATION 
)
Value:
do { \
RelIdCacheEnt *hentry; \
(void *) &(ID), \
HASH_FIND, NULL); \
if (hentry) \
RELATION = hentry->reldesc; \
else \
RELATION = NULL; \
} while(0)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:907
static HTAB * RelationIdCache
Definition: relcache.c:130

Definition at line 209 of file relcache.c.

Referenced by RelationCacheInvalidateEntry(), RelationCloseSmgrByOid(), RelationForgetRelation(), and RelationIdGetRelation().

◆ RELCACHE_INIT_FILEMAGIC

#define RELCACHE_INIT_FILEMAGIC   0x573266 /* version ID value */

Definition at line 89 of file relcache.c.

Referenced by load_relcache_init_file(), and write_relcache_init_file().

◆ SWAPFIELD

#define SWAPFIELD (   fldtype,
  fldname 
)
Value:
do { \
fldtype _tmp = newrel->fldname; \
newrel->fldname = relation->fldname; \
relation->fldname = _tmp; \
} while (0)

Referenced by RelationClearRelation().

Typedef Documentation

◆ OpClassCacheEnt

◆ RelIdCacheEnt

typedef struct relidcacheent RelIdCacheEnt

Function Documentation

◆ AllocateRelationDesc()

static Relation AllocateRelationDesc ( Form_pg_class  relp)
static

Definition at line 384 of file relcache.c.

References CacheMemoryContext, CLASS_TUPLE_SIZE, CreateTemplateTupleDesc(), MemoryContextSwitchTo(), palloc(), palloc0(), RelationData::rd_att, RelationData::rd_rel, RelationData::rd_smgr, and TupleDescData::tdrefcount.

Referenced by RelationBuildDesc().

385 {
386  Relation relation;
387  MemoryContext oldcxt;
388  Form_pg_class relationForm;
389 
390  /* Relcache entries must live in CacheMemoryContext */
392 
393  /*
394  * allocate and zero space for new relation descriptor
395  */
396  relation = (Relation) palloc0(sizeof(RelationData));
397 
398  /* make sure relation is marked as having no open file yet */
399  relation->rd_smgr = NULL;
400 
401  /*
402  * Copy the relation tuple form
403  *
404  * We only allocate space for the fixed fields, ie, CLASS_TUPLE_SIZE. The
405  * variable-length fields (relacl, reloptions) are NOT stored in the
406  * relcache --- there'd be little point in it, since we don't copy the
407  * tuple's nulls bitmap and hence wouldn't know if the values are valid.
408  * Bottom line is that relacl *cannot* be retrieved from the relcache. Get
409  * it from the syscache if you need it. The same goes for the original
410  * form of reloptions (however, we do store the parsed form of reloptions
411  * in rd_options).
412  */
413  relationForm = (Form_pg_class) palloc(CLASS_TUPLE_SIZE);
414 
415  memcpy(relationForm, relp, CLASS_TUPLE_SIZE);
416 
417  /* initialize relation tuple form */
418  relation->rd_rel = relationForm;
419 
420  /* and allocate attribute tuple form storage */
421  relation->rd_att = CreateTemplateTupleDesc(relationForm->relnatts);
422  /* which we mark as a reference-counted tupdesc */
423  relation->rd_att->tdrefcount = 1;
424 
425  MemoryContextSwitchTo(oldcxt);
426 
427  return relation;
428 }
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:44
struct SMgrRelationData * rd_smgr
Definition: rel.h:57
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Form_pg_class rd_rel
Definition: rel.h:109
struct RelationData * Relation
Definition: relcache.h:27
void * palloc0(Size size)
Definition: mcxt.c:980
TupleDesc rd_att
Definition: rel.h:110
#define CLASS_TUPLE_SIZE
Definition: pg_class.h:145
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
void * palloc(Size size)
Definition: mcxt.c:949
int tdrefcount
Definition: tupdesc.h:84
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ AtEOSubXact_cleanup()

static void AtEOSubXact_cleanup ( Relation  relation,
bool  isCommit,
SubTransactionId  mySubid,
SubTransactionId  parentSubid 
)
static

Definition at line 3252 of file relcache.c.

References Assert, elog, InvalidSubTransactionId, RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_firstRelfilenodeSubid, RelationData::rd_newRelfilenodeSubid, RelationClearRelation(), RelationGetRelationName, RelationHasReferenceCountZero, and WARNING.

Referenced by AtEOSubXact_RelationCache().

3254 {
3255  /*
3256  * Is it a relation created in the current subtransaction?
3257  *
3258  * During subcommit, mark it as belonging to the parent, instead, as long
3259  * as it has not been dropped. Otherwise simply delete the relcache entry.
3260  * --- it isn't interesting any longer.
3261  */
3262  if (relation->rd_createSubid == mySubid)
3263  {
3264  /*
3265  * Valid rd_droppedSubid means the corresponding relation is dropped
3266  * but the relcache entry is preserved for at-commit pending sync. We
3267  * need to drop it explicitly here not to make the entry orphan.
3268  */
3269  Assert(relation->rd_droppedSubid == mySubid ||
3271  if (isCommit && relation->rd_droppedSubid == InvalidSubTransactionId)
3272  relation->rd_createSubid = parentSubid;
3273  else if (RelationHasReferenceCountZero(relation))
3274  {
3275  /* allow the entry to be removed */
3280  RelationClearRelation(relation, false);
3281  return;
3282  }
3283  else
3284  {
3285  /*
3286  * Hmm, somewhere there's a (leaked?) reference to the relation.
3287  * We daren't remove the entry for fear of dereferencing a
3288  * dangling pointer later. Bleat, and transfer it to the parent
3289  * subtransaction so we can try again later. This must be just a
3290  * WARNING to avoid error-during-error-recovery loops.
3291  */
3292  relation->rd_createSubid = parentSubid;
3293  elog(WARNING, "cannot remove relcache entry for \"%s\" because it has nonzero refcount",
3294  RelationGetRelationName(relation));
3295  }
3296  }
3297 
3298  /*
3299  * Likewise, update or drop any new-relfilenode-in-subtransaction record
3300  * or drop record.
3301  */
3302  if (relation->rd_newRelfilenodeSubid == mySubid)
3303  {
3304  if (isCommit)
3305  relation->rd_newRelfilenodeSubid = parentSubid;
3306  else
3308  }
3309 
3310  if (relation->rd_firstRelfilenodeSubid == mySubid)
3311  {
3312  if (isCommit)
3313  relation->rd_firstRelfilenodeSubid = parentSubid;
3314  else
3316  }
3317 
3318  if (relation->rd_droppedSubid == mySubid)
3319  {
3320  if (isCommit)
3321  relation->rd_droppedSubid = parentSubid;
3322  else
3324  }
3325 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2422
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:103
#define RelationGetRelationName(relation)
Definition: rel.h:490
#define WARNING
Definition: elog.h:40
SubTransactionId rd_createSubid
Definition: rel.h:102
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
#define Assert(condition)
Definition: c.h:738
#define InvalidSubTransactionId
Definition: c.h:519
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:440
#define elog(elevel,...)
Definition: elog.h:214
SubTransactionId rd_droppedSubid
Definition: rel.h:107

◆ AtEOSubXact_RelationCache()

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

Definition at line 3205 of file relcache.c.

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

3207 {
3209  RelIdCacheEnt *idhentry;
3210  int i;
3211 
3212  /*
3213  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3214  * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3215  * logic as in AtEOXact_RelationCache.
3216  */
3218  {
3219  hash_seq_init(&status, RelationIdCache);
3220  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3221  {
3222  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3223  mySubid, parentSubid);
3224  }
3225  }
3226  else
3227  {
3228  for (i = 0; i < eoxact_list_len; i++)
3229  {
3230  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3231  (void *) &eoxact_list[i],
3232  HASH_FIND,
3233  NULL);
3234  if (idhentry != NULL)
3235  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3236  mySubid, parentSubid);
3237  }
3238  }
3239 
3240  /* Don't reset the list; we still need more cleanup later */
3241 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:163
static void AtEOSubXact_cleanup(Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
Definition: relcache.c:3252
Relation reldesc
Definition: relcache.c:127
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:907
static HTAB * RelationIdCache
Definition: relcache.c:130
static bool eoxact_list_overflowed
Definition: relcache.c:165
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1390
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1380
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
static int eoxact_list_len
Definition: relcache.c:164

◆ AtEOXact_cleanup()

static void AtEOXact_cleanup ( Relation  relation,
bool  isCommit 
)
static

Definition at line 3123 of file relcache.c.

References Assert, elog, InvalidSubTransactionId, IsBootstrapProcessingMode, RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_firstRelfilenodeSubid, RelationData::rd_isnailed, RelationData::rd_newRelfilenodeSubid, RelationData::rd_refcnt, RelationClearRelation(), RelationGetRelationName, RelationHasReferenceCountZero, and WARNING.

Referenced by AtEOXact_RelationCache().

3124 {
3125  bool clear_relcache = false;
3126 
3127  /*
3128  * The relcache entry's ref count should be back to its normal
3129  * not-in-a-transaction state: 0 unless it's nailed in cache.
3130  *
3131  * In bootstrap mode, this is NOT true, so don't check it --- the
3132  * bootstrap code expects relations to stay open across start/commit
3133  * transaction calls. (That seems bogus, but it's not worth fixing.)
3134  *
3135  * Note: ideally this check would be applied to every relcache entry, not
3136  * just those that have eoxact work to do. But it's not worth forcing a
3137  * scan of the whole relcache just for this. (Moreover, doing so would
3138  * mean that assert-enabled testing never tests the hash_search code path
3139  * above, which seems a bad idea.)
3140  */
3141 #ifdef USE_ASSERT_CHECKING
3143  {
3144  int expected_refcnt;
3145 
3146  expected_refcnt = relation->rd_isnailed ? 1 : 0;
3147  Assert(relation->rd_refcnt == expected_refcnt);
3148  }
3149 #endif
3150 
3151  /*
3152  * Is the relation live after this transaction ends?
3153  *
3154  * During commit, clear the relcache entry if it is preserved after
3155  * relation drop, in order not to orphan the entry. During rollback,
3156  * clear the relcache entry if the relation is created in the current
3157  * transaction since it isn't interesting any longer once we are out of
3158  * the transaction.
3159  */
3160  clear_relcache =
3161  (isCommit ?
3164 
3165  /*
3166  * Since we are now out of the transaction, reset the subids to zero. That
3167  * also lets RelationClearRelation() drop the relcache entry.
3168  */
3173 
3174  if (clear_relcache)
3175  {
3176  if (RelationHasReferenceCountZero(relation))
3177  {
3178  RelationClearRelation(relation, false);
3179  return;
3180  }
3181  else
3182  {
3183  /*
3184  * Hmm, somewhere there's a (leaked?) reference to the relation.
3185  * We daren't remove the entry for fear of dereferencing a
3186  * dangling pointer later. Bleat, and mark it as not belonging to
3187  * the current transaction. Hopefully it'll get cleaned up
3188  * eventually. This must be just a WARNING to avoid
3189  * error-during-error-recovery loops.
3190  */
3191  elog(WARNING, "cannot remove relcache entry for \"%s\" because it has nonzero refcount",
3192  RelationGetRelationName(relation));
3193  }
3194  }
3195 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2422
bool rd_isnailed
Definition: rel.h:61
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:103
#define RelationGetRelationName(relation)
Definition: rel.h:490
#define WARNING
Definition: elog.h:40
SubTransactionId rd_createSubid
Definition: rel.h:102
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
#define Assert(condition)
Definition: c.h:738
#define InvalidSubTransactionId
Definition: c.h:519
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:440
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:392
int rd_refcnt
Definition: rel.h:58
#define elog(elevel,...)
Definition: elog.h:214
SubTransactionId rd_droppedSubid
Definition: rel.h:107

◆ AtEOXact_RelationCache()

void AtEOXact_RelationCache ( bool  isCommit)

Definition at line 3060 of file relcache.c.

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

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

3061 {
3063  RelIdCacheEnt *idhentry;
3064  int i;
3065 
3066  /*
3067  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3068  * listed in it. Otherwise fall back on a hash_seq_search scan.
3069  *
3070  * For simplicity, eoxact_list[] entries are not deleted till end of
3071  * top-level transaction, even though we could remove them at
3072  * subtransaction end in some cases, or remove relations from the list if
3073  * they are cleared for other reasons. Therefore we should expect the
3074  * case that list entries are not found in the hashtable; if not, there's
3075  * nothing to do for them.
3076  */
3078  {
3079  hash_seq_init(&status, RelationIdCache);
3080  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3081  {
3082  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3083  }
3084  }
3085  else
3086  {
3087  for (i = 0; i < eoxact_list_len; i++)
3088  {
3089  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3090  (void *) &eoxact_list[i],
3091  HASH_FIND,
3092  NULL);
3093  if (idhentry != NULL)
3094  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3095  }
3096  }
3097 
3098  if (EOXactTupleDescArrayLen > 0)
3099  {
3100  Assert(EOXactTupleDescArray != NULL);
3101  for (i = 0; i < NextEOXactTupleDescNum; i++)
3104  EOXactTupleDescArray = NULL;
3105  }
3106 
3107  /* Now we're out of the transaction and can clear the lists */
3108  eoxact_list_len = 0;
3109  eoxact_list_overflowed = false;
3110  NextEOXactTupleDescNum = 0;
3112 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:163
static int EOXactTupleDescArrayLen
Definition: relcache.c:182
Relation reldesc
Definition: relcache.c:127
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:907
static HTAB * RelationIdCache
Definition: relcache.c:130
static void AtEOXact_cleanup(Relation relation, bool isCommit)
Definition: relcache.c:3123
static bool eoxact_list_overflowed
Definition: relcache.c:165
static int NextEOXactTupleDescNum
Definition: relcache.c:181
void pfree(void *pointer)
Definition: mcxt.c:1056
#define Assert(condition)
Definition: c.h:738
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1390
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1380
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:313
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
static int eoxact_list_len
Definition: relcache.c:164
static TupleDesc * EOXactTupleDescArray
Definition: relcache.c:180

◆ AttrDefaultFetch()

static void AttrDefaultFetch ( Relation  relation)
static

Definition at line 4232 of file relcache.c.

References AccessShareLock, AttrDefault::adbin, AttrDefault::adnum, AttrDefaultIndexId, BTEqualStrategyNumber, CacheMemoryContext, TupleDescData::constr, TupleConstr::defval, elog, fastgetattr, GETSTRUCT, HeapTupleIsValid, i, MemoryContextStrdup(), NameStr, TupleConstr::num_defval, ObjectIdGetDatum, pfree(), RelationData::rd_att, RelationGetRelationName, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TextDatumGetCString, TupleDescAttr, val, and WARNING.

Referenced by RelationBuildTupleDesc().

4233 {
4234  AttrDefault *attrdef = relation->rd_att->constr->defval;
4235  int ndef = relation->rd_att->constr->num_defval;
4236  Relation adrel;
4237  SysScanDesc adscan;
4238  ScanKeyData skey;
4239  HeapTuple htup;
4240  Datum val;
4241  bool isnull;
4242  int found;
4243  int i;
4244 
4245  ScanKeyInit(&skey,
4246  Anum_pg_attrdef_adrelid,
4247  BTEqualStrategyNumber, F_OIDEQ,
4248  ObjectIdGetDatum(RelationGetRelid(relation)));
4249 
4250  adrel = table_open(AttrDefaultRelationId, AccessShareLock);
4251  adscan = systable_beginscan(adrel, AttrDefaultIndexId, true,
4252  NULL, 1, &skey);
4253  found = 0;
4254 
4255  while (HeapTupleIsValid(htup = systable_getnext(adscan)))
4256  {
4257  Form_pg_attrdef adform = (Form_pg_attrdef) GETSTRUCT(htup);
4258  Form_pg_attribute attr = TupleDescAttr(relation->rd_att, adform->adnum - 1);
4259 
4260  for (i = 0; i < ndef; i++)
4261  {
4262  if (adform->adnum != attrdef[i].adnum)
4263  continue;
4264  if (attrdef[i].adbin != NULL)
4265  elog(WARNING, "multiple attrdef records found for attr %s of rel %s",
4266  NameStr(attr->attname),
4267  RelationGetRelationName(relation));
4268  else
4269  found++;
4270 
4271  val = fastgetattr(htup,
4272  Anum_pg_attrdef_adbin,
4273  adrel->rd_att, &isnull);
4274  if (isnull)
4275  elog(WARNING, "null adbin for attr %s of rel %s",
4276  NameStr(attr->attname),
4277  RelationGetRelationName(relation));
4278  else
4279  {
4280  /* detoast and convert to cstring in caller's context */
4281  char *s = TextDatumGetCString(val);
4282 
4284  pfree(s);
4285  }
4286  break;
4287  }
4288 
4289  if (i >= ndef)
4290  elog(WARNING, "unexpected attrdef record found for attr %d of rel %s",
4291  adform->adnum, RelationGetRelationName(relation));
4292  }
4293 
4294  systable_endscan(adscan);
4295  table_close(adrel, AccessShareLock);
4296 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:712
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define AccessShareLock
Definition: lockdefs.h:36
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
AttrDefault * defval
Definition: tupdesc.h:39
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define AttrDefaultIndexId
Definition: indexing.h:89
TupleConstr * constr
Definition: tupdesc.h:85
#define RelationGetRelationName(relation)
Definition: rel.h:490
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
FormData_pg_attrdef * Form_pg_attrdef
Definition: pg_attrdef.h:47
#define WARNING
Definition: elog.h:40
#define TextDatumGetCString(d)
Definition: builtins.h:88
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:110
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
uint16 num_defval
Definition: tupdesc.h:42
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1173
#define elog(elevel,...)
Definition: elog.h:214
int i
AttrNumber adnum
Definition: tupdesc.h:24
char * adbin
Definition: tupdesc.h:25
#define NameStr(name)
Definition: c.h:615
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define RelationGetRelid(relation)
Definition: rel.h:456
long val
Definition: informix.c:664
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ BuildHardcodedDescriptor()

static TupleDesc BuildHardcodedDescriptor ( int  natts,
const FormData_pg_attribute attrs 
)
static

Definition at line 4173 of file relcache.c.

References ATTRIBUTE_FIXED_PART_SIZE, CacheMemoryContext, CreateTemplateTupleDesc(), i, MemoryContextSwitchTo(), TupleDescData::tdtypeid, TupleDescData::tdtypmod, and TupleDescAttr.

Referenced by GetPgClassDescriptor(), and GetPgIndexDescriptor().

4174 {
4175  TupleDesc result;
4176  MemoryContext oldcxt;
4177  int i;
4178 
4180 
4181  result = CreateTemplateTupleDesc(natts);
4182  result->tdtypeid = RECORDOID; /* not right, but we don't care */
4183  result->tdtypmod = -1;
4184 
4185  for (i = 0; i < natts; i++)
4186  {
4187  memcpy(TupleDescAttr(result, i), &attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
4188  /* make sure attcacheoff is valid */
4189  TupleDescAttr(result, i)->attcacheoff = -1;
4190  }
4191 
4192  /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
4193  TupleDescAttr(result, 0)->attcacheoff = 0;
4194 
4195  /* Note: we don't bother to set up a TupleConstr entry */
4196 
4197  MemoryContextSwitchTo(oldcxt);
4198 
4199  return result;
4200 }
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:44
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int32 tdtypmod
Definition: tupdesc.h:83
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:185
Oid tdtypeid
Definition: tupdesc.h:82
int i
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ CheckConstraintCmp()

static int CheckConstraintCmp ( const void *  a,
const void *  b 
)
static

Definition at line 4373 of file relcache.c.

References ConstrCheck::ccname.

Referenced by CheckConstraintFetch().

4374 {
4375  const ConstrCheck *ca = (const ConstrCheck *) a;
4376  const ConstrCheck *cb = (const ConstrCheck *) b;
4377 
4378  return strcmp(ca->ccname, cb->ccname);
4379 }
char * ccname
Definition: tupdesc.h:30

◆ CheckConstraintFetch()

static void CheckConstraintFetch ( Relation  relation)
static

Definition at line 4302 of file relcache.c.

References AccessShareLock, BTEqualStrategyNumber, CacheMemoryContext, ConstrCheck::ccbin, ConstrCheck::ccname, ConstrCheck::ccnoinherit, ConstrCheck::ccvalid, TupleConstr::check, CheckConstraintCmp(), TupleDescData::constr, ConstraintRelidTypidNameIndexId, elog, ERROR, fastgetattr, GETSTRUCT, HeapTupleIsValid, MemoryContextStrdup(), NameStr, TupleConstr::num_check, ObjectIdGetDatum, pfree(), qsort, RelationData::rd_att, RelationGetRelationName, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TextDatumGetCString, and val.

Referenced by RelationBuildTupleDesc().

4303 {
4304  ConstrCheck *check = relation->rd_att->constr->check;
4305  int ncheck = relation->rd_att->constr->num_check;
4306  Relation conrel;
4307  SysScanDesc conscan;
4308  ScanKeyData skey[1];
4309  HeapTuple htup;
4310  int found = 0;
4311 
4312  ScanKeyInit(&skey[0],
4313  Anum_pg_constraint_conrelid,
4314  BTEqualStrategyNumber, F_OIDEQ,
4315  ObjectIdGetDatum(RelationGetRelid(relation)));
4316 
4317  conrel = table_open(ConstraintRelationId, AccessShareLock);
4318  conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
4319  NULL, 1, skey);
4320 
4321  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4322  {
4324  Datum val;
4325  bool isnull;
4326  char *s;
4327 
4328  /* We want check constraints only */
4329  if (conform->contype != CONSTRAINT_CHECK)
4330  continue;
4331 
4332  if (found >= ncheck)
4333  elog(ERROR, "unexpected constraint record found for rel %s",
4334  RelationGetRelationName(relation));
4335 
4336  check[found].ccvalid = conform->convalidated;
4337  check[found].ccnoinherit = conform->connoinherit;
4339  NameStr(conform->conname));
4340 
4341  /* Grab and test conbin is actually set */
4342  val = fastgetattr(htup,
4343  Anum_pg_constraint_conbin,
4344  conrel->rd_att, &isnull);
4345  if (isnull)
4346  elog(ERROR, "null conbin for rel %s",
4347  RelationGetRelationName(relation));
4348 
4349  /* detoast and convert to cstring in caller's context */
4350  s = TextDatumGetCString(val);
4351  check[found].ccbin = MemoryContextStrdup(CacheMemoryContext, s);
4352  pfree(s);
4353 
4354  found++;
4355  }
4356 
4357  systable_endscan(conscan);
4358  table_close(conrel, AccessShareLock);
4359 
4360  if (found != ncheck)
4361  elog(ERROR, "%d constraint record(s) missing for rel %s",
4362  ncheck - found, RelationGetRelationName(relation));
4363 
4364  /* Sort the records so that CHECKs are applied in a deterministic order */
4365  if (ncheck > 1)
4366  qsort(check, ncheck, sizeof(ConstrCheck), CheckConstraintCmp);
4367 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:712
static int CheckConstraintCmp(const void *a, const void *b)
Definition: relcache.c:4373
#define AccessShareLock
Definition: lockdefs.h:36
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
TupleConstr * constr
Definition: tupdesc.h:85
char * ccname
Definition: tupdesc.h:30
#define RelationGetRelationName(relation)
Definition: rel.h:490
#define TextDatumGetCString(d)
Definition: builtins.h:88
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:110
uint16 num_check
Definition: tupdesc.h:43
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define ConstraintRelidTypidNameIndexId
Definition: indexing.h:128
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1173
#define elog(elevel,...)
Definition: elog.h:214
#define NameStr(name)
Definition: c.h:615
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
ConstrCheck * check
Definition: tupdesc.h:40
bool ccvalid
Definition: tupdesc.h:32
#define qsort(a, b, c, d)
Definition: port.h:479
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
char * ccbin
Definition: tupdesc.h:31
#define RelationGetRelid(relation)
Definition: rel.h:456
long val
Definition: informix.c:664
#define BTEqualStrategyNumber
Definition: stratnum.h:31
bool ccnoinherit
Definition: tupdesc.h:33
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ CopyIndexAttOptions()

static bytea** CopyIndexAttOptions ( bytea **  srcopts,
int  natts 
)
static

Definition at line 5393 of file relcache.c.

References datumCopy(), DatumGetPointer, i, palloc(), and PointerGetDatum.

Referenced by RelationGetIndexAttOptions().

5394 {
5395  bytea **opts = palloc(sizeof(*opts) * natts);
5396 
5397  for (int i = 0; i < natts; i++)
5398  {
5399  bytea *opt = srcopts[i];
5400 
5401  opts[i] = !opt ? NULL : (bytea *)
5402  DatumGetPointer(datumCopy(PointerGetDatum(opt), false, -1));
5403  }
5404 
5405  return opts;
5406 }
#define PointerGetDatum(X)
Definition: postgres.h:556
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:131
#define DatumGetPointer(X)
Definition: postgres.h:549
void * palloc(Size size)
Definition: mcxt.c:949
int i
Definition: c.h:555

◆ equalPolicy()

static bool equalPolicy ( RowSecurityPolicy policy1,
RowSecurityPolicy policy2 
)
static

Definition at line 939 of file relcache.c.

References ARR_DATA_PTR, ARR_DIMS, equal(), RowSecurityPolicy::hassublinks, i, RowSecurityPolicy::polcmd, RowSecurityPolicy::policy_name, RowSecurityPolicy::qual, RowSecurityPolicy::roles, and RowSecurityPolicy::with_check_qual.

Referenced by equalRSDesc().

940 {
941  int i;
942  Oid *r1,
943  *r2;
944 
945  if (policy1 != NULL)
946  {
947  if (policy2 == NULL)
948  return false;
949 
950  if (policy1->polcmd != policy2->polcmd)
951  return false;
952  if (policy1->hassublinks != policy2->hassublinks)
953  return false;
954  if (strcmp(policy1->policy_name, policy2->policy_name) != 0)
955  return false;
956  if (ARR_DIMS(policy1->roles)[0] != ARR_DIMS(policy2->roles)[0])
957  return false;
958 
959  r1 = (Oid *) ARR_DATA_PTR(policy1->roles);
960  r2 = (Oid *) ARR_DATA_PTR(policy2->roles);
961 
962  for (i = 0; i < ARR_DIMS(policy1->roles)[0]; i++)
963  {
964  if (r1[i] != r2[i])
965  return false;
966  }
967 
968  if (!equal(policy1->qual, policy2->qual))
969  return false;
970  if (!equal(policy1->with_check_qual, policy2->with_check_qual))
971  return false;
972  }
973  else if (policy2 != NULL)
974  return false;
975 
976  return true;
977 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3030
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_DIMS(a)
Definition: array.h:282
#define ARR_DATA_PTR(a)
Definition: array.h:310
Expr * with_check_qual
Definition: rowsecurity.h:27
ArrayType * roles
Definition: rowsecurity.h:24
int i

◆ equalRSDesc()

static bool equalRSDesc ( RowSecurityDesc rsdesc1,
RowSecurityDesc rsdesc2 
)
static

Definition at line 985 of file relcache.c.

References equalPolicy(), forboth, lfirst, list_length(), and RowSecurityDesc::policies.

Referenced by RelationClearRelation().

986 {
987  ListCell *lc,
988  *rc;
989 
990  if (rsdesc1 == NULL && rsdesc2 == NULL)
991  return true;
992 
993  if ((rsdesc1 != NULL && rsdesc2 == NULL) ||
994  (rsdesc1 == NULL && rsdesc2 != NULL))
995  return false;
996 
997  if (list_length(rsdesc1->policies) != list_length(rsdesc2->policies))
998  return false;
999 
1000  /* RelationBuildRowSecurity should build policies in order */
1001  forboth(lc, rsdesc1->policies, rc, rsdesc2->policies)
1002  {
1005 
1006  if (!equalPolicy(l, r))
1007  return false;
1008  }
1009 
1010  return true;
1011 }
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:419
static bool equalPolicy(RowSecurityPolicy *policy1, RowSecurityPolicy *policy2)
Definition: relcache.c:939
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169

◆ equalRuleLocks()

static bool equalRuleLocks ( RuleLock rlock1,
RuleLock rlock2 
)
static

Definition at line 894 of file relcache.c.

References RewriteRule::actions, RewriteRule::enabled, equal(), RewriteRule::event, i, RewriteRule::isInstead, RuleLock::numLocks, RewriteRule::qual, RewriteRule::ruleId, and RuleLock::rules.

Referenced by RelationClearRelation().

895 {
896  int i;
897 
898  /*
899  * As of 7.3 we assume the rule ordering is repeatable, because
900  * RelationBuildRuleLock should read 'em in a consistent order. So just
901  * compare corresponding slots.
902  */
903  if (rlock1 != NULL)
904  {
905  if (rlock2 == NULL)
906  return false;
907  if (rlock1->numLocks != rlock2->numLocks)
908  return false;
909  for (i = 0; i < rlock1->numLocks; i++)
910  {
911  RewriteRule *rule1 = rlock1->rules[i];
912  RewriteRule *rule2 = rlock2->rules[i];
913 
914  if (rule1->ruleId != rule2->ruleId)
915  return false;
916  if (rule1->event != rule2->event)
917  return false;
918  if (rule1->enabled != rule2->enabled)
919  return false;
920  if (rule1->isInstead != rule2->isInstead)
921  return false;
922  if (!equal(rule1->qual, rule2->qual))
923  return false;
924  if (!equal(rule1->actions, rule2->actions))
925  return false;
926  }
927  }
928  else if (rlock2 != NULL)
929  return false;
930  return true;
931 }
Node * qual
Definition: prs2lock.h:28
int numLocks
Definition: prs2lock.h:42
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3030
bool isInstead
Definition: prs2lock.h:31
CmdType event
Definition: prs2lock.h:27
RewriteRule ** rules
Definition: prs2lock.h:43
List * actions
Definition: prs2lock.h:29
int i
Oid ruleId
Definition: prs2lock.h:26
char enabled
Definition: prs2lock.h:30

◆ errtable()

int errtable ( Relation  rel)

Definition at line 5473 of file relcache.c.

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

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

5474 {
5478 
5479  return 0; /* return value does not matter */
5480 }
#define PG_DIAG_SCHEMA_NAME
Definition: postgres_ext.h:65
#define PG_DIAG_TABLE_NAME
Definition: postgres_ext.h:66
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3155
#define RelationGetRelationName(relation)
Definition: rel.h:490
int err_generic_string(int field, const char *str)
Definition: elog.c:1265
#define RelationGetNamespace(relation)
Definition: rel.h:497

◆ errtablecol()

int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5490 of file relcache.c.

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

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

5491 {
5492  TupleDesc reldesc = RelationGetDescr(rel);
5493  const char *colname;
5494 
5495  /* Use reldesc if it's a user attribute, else consult the catalogs */
5496  if (attnum > 0 && attnum <= reldesc->natts)
5497  colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
5498  else
5499  colname = get_attname(RelationGetRelid(rel), attnum, false);
5500 
5501  return errtablecolname(rel, colname);
5502 }
#define RelationGetDescr(relation)
Definition: rel.h:482
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
NameData attname
Definition: pg_attribute.h:40
int16 attnum
Definition: pg_attribute.h:79
#define NameStr(name)
Definition: c.h:615
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:776
#define RelationGetRelid(relation)
Definition: rel.h:456
int errtablecolname(Relation rel, const char *colname)
Definition: relcache.c:5514

◆ errtablecolname()

int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5514 of file relcache.c.

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

Referenced by errtablecol().

5515 {
5516  errtable(rel);
5518 
5519  return 0; /* return value does not matter */
5520 }
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:67
int err_generic_string(int field, const char *str)
Definition: elog.c:1265
int errtable(Relation rel)
Definition: relcache.c:5473

◆ errtableconstraint()

int errtableconstraint ( Relation  rel,
const char *  conname 
)

Definition at line 5527 of file relcache.c.

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

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

5528 {
5529  errtable(rel);
5531 
5532  return 0; /* return value does not matter */
5533 }
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:69
int err_generic_string(int field, const char *str)
Definition: elog.c:1265
int errtable(Relation rel)
Definition: relcache.c:5473

◆ formrdesc()

static void formrdesc ( const char *  relationName,
Oid  relationReltype,
bool  isshared,
int  natts,
const FormData_pg_attribute attrs 
)
static

Definition at line 1807 of file relcache.c.

References ATTRIBUTE_FIXED_PART_SIZE, CLASS_TUPLE_SIZE, TupleDescData::constr, CreateTemplateTupleDesc(), GetHeapamTableAmRoutine(), TupleConstr::has_not_null, i, InvalidBackendId, InvalidOid, InvalidSubTransactionId, IsBootstrapProcessingMode, namestrcpy(), palloc0(), RelationData::rd_att, RelationData::rd_backend, RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_firstRelfilenodeSubid, RelationData::rd_islocaltemp, RelationData::rd_isnailed, RelationData::rd_isvalid, RelationData::rd_newRelfilenodeSubid, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_smgr, RelationData::rd_tableam, RelationCacheInsert, RelationGetRelid, RelationInitLockInfo(), RelationInitPhysicalAddr(), RelationMapUpdateMap(), TupleDescData::tdrefcount, TupleDescData::tdtypeid, TupleDescData::tdtypmod, and TupleDescAttr.

Referenced by RelationCacheInitializePhase2(), and RelationCacheInitializePhase3().

1810 {
1811  Relation relation;
1812  int i;
1813  bool has_not_null;
1814 
1815  /*
1816  * allocate new relation desc, clear all fields of reldesc
1817  */
1818  relation = (Relation) palloc0(sizeof(RelationData));
1819 
1820  /* make sure relation is marked as having no open file yet */
1821  relation->rd_smgr = NULL;
1822 
1823  /*
1824  * initialize reference count: 1 because it is nailed in cache
1825  */
1826  relation->rd_refcnt = 1;
1827 
1828  /*
1829  * all entries built with this routine are nailed-in-cache; none are for
1830  * new or temp relations.
1831  */
1832  relation->rd_isnailed = true;
1837  relation->rd_backend = InvalidBackendId;
1838  relation->rd_islocaltemp = false;
1839 
1840  /*
1841  * initialize relation tuple form
1842  *
1843  * The data we insert here is pretty incomplete/bogus, but it'll serve to
1844  * get us launched. RelationCacheInitializePhase3() will read the real
1845  * data from pg_class and replace what we've done here. Note in
1846  * particular that relowner is left as zero; this cues
1847  * RelationCacheInitializePhase3 that the real data isn't there yet.
1848  */
1850 
1851  namestrcpy(&relation->rd_rel->relname, relationName);
1852  relation->rd_rel->relnamespace = PG_CATALOG_NAMESPACE;
1853  relation->rd_rel->reltype = relationReltype;
1854 
1855  /*
1856  * It's important to distinguish between shared and non-shared relations,
1857  * even at bootstrap time, to make sure we know where they are stored.
1858  */
1859  relation->rd_rel->relisshared = isshared;
1860  if (isshared)
1861  relation->rd_rel->reltablespace = GLOBALTABLESPACE_OID;
1862 
1863  /* formrdesc is used only for permanent relations */
1864  relation->rd_rel->relpersistence = RELPERSISTENCE_PERMANENT;
1865 
1866  /* ... and they're always populated, too */
1867  relation->rd_rel->relispopulated = true;
1868 
1869  relation->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
1870  relation->rd_rel->relpages = 0;
1871  relation->rd_rel->reltuples = 0;
1872  relation->rd_rel->relallvisible = 0;
1873  relation->rd_rel->relkind = RELKIND_RELATION;
1874  relation->rd_rel->relnatts = (int16) natts;
1875  relation->rd_rel->relam = HEAP_TABLE_AM_OID;
1876 
1877  /*
1878  * initialize attribute tuple form
1879  *
1880  * Unlike the case with the relation tuple, this data had better be right
1881  * because it will never be replaced. The data comes from
1882  * src/include/catalog/ headers via genbki.pl.
1883  */
1884  relation->rd_att = CreateTemplateTupleDesc(natts);
1885  relation->rd_att->tdrefcount = 1; /* mark as refcounted */
1886 
1887  relation->rd_att->tdtypeid = relationReltype;
1888  relation->rd_att->tdtypmod = -1; /* unnecessary, but... */
1889 
1890  /*
1891  * initialize tuple desc info
1892  */
1893  has_not_null = false;
1894  for (i = 0; i < natts; i++)
1895  {
1896  memcpy(TupleDescAttr(relation->rd_att, i),
1897  &attrs[i],
1899  has_not_null |= attrs[i].attnotnull;
1900  /* make sure attcacheoff is valid */
1901  TupleDescAttr(relation->rd_att, i)->attcacheoff = -1;
1902  }
1903 
1904  /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
1905  TupleDescAttr(relation->rd_att, 0)->attcacheoff = 0;
1906 
1907  /* mark not-null status */
1908  if (has_not_null)
1909  {
1910  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
1911 
1912  constr->has_not_null = true;
1913  relation->rd_att->constr = constr;
1914  }
1915 
1916  /*
1917  * initialize relation id from info in att array (my, this is ugly)
1918  */
1919  RelationGetRelid(relation) = TupleDescAttr(relation->rd_att, 0)->attrelid;
1920 
1921  /*
1922  * All relations made with formrdesc are mapped. This is necessarily so
1923  * because there is no other way to know what filenode they currently
1924  * have. In bootstrap mode, add them to the initial relation mapper data,
1925  * specifying that the initial filenode is the same as the OID.
1926  */
1927  relation->rd_rel->relfilenode = InvalidOid;
1930  RelationGetRelid(relation),
1931  isshared, true);
1932 
1933  /*
1934  * initialize the relation lock manager information
1935  */
1936  RelationInitLockInfo(relation); /* see lmgr.c */
1937 
1938  /*
1939  * initialize physical addressing information for the relation
1940  */
1941  RelationInitPhysicalAddr(relation);
1942 
1943  /*
1944  * initialize the table am handler
1945  */
1946  relation->rd_rel->relam = HEAP_TABLE_AM_OID;
1947  relation->rd_tableam = GetHeapamTableAmRoutine();
1948 
1949  /*
1950  * initialize the rel-has-index flag, using hardwired knowledge
1951  */
1953  {
1954  /* In bootstrap mode, we have no indexes */
1955  relation->rd_rel->relhasindex = false;
1956  }
1957  else
1958  {
1959  /* Otherwise, all the rels formrdesc is used for have indexes */
1960  relation->rd_rel->relhasindex = true;
1961  }
1962 
1963  /*
1964  * add new reldesc to relcache
1965  */
1966  RelationCacheInsert(relation, false);
1967 
1968  /* It's fully valid */
1969  relation->rd_isvalid = true;
1970 }
signed short int16
Definition: c.h:354
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:44
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
struct SMgrRelationData * rd_smgr
Definition: rel.h:57
bool rd_isnailed
Definition: rel.h:61
bool rd_islocaltemp
Definition: rel.h:60
bool rd_isvalid
Definition: rel.h:62
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:103
Form_pg_class rd_rel
Definition: rel.h:109
int namestrcpy(Name name, const char *str)
Definition: name.c:250
struct RelationData * Relation
Definition: relcache.h:27
int32 tdtypmod
Definition: tupdesc.h:83
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1272
void RelationInitLockInfo(Relation relation)
Definition: lmgr.c:71
TupleConstr * constr
Definition: tupdesc.h:85
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:185
SubTransactionId rd_createSubid
Definition: rel.h:102
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
#define InvalidBackendId
Definition: backendid.h:23
void * palloc0(Size size)
Definition: mcxt.c:980
const struct TableAmRoutine * rd_tableam
Definition: rel.h:171
TupleDesc rd_att
Definition: rel.h:110
#define InvalidOid
Definition: postgres_ext.h:36
#define RelationCacheInsert(RELATION, replace_allowed)
Definition: relcache.c:187
#define CLASS_TUPLE_SIZE
Definition: pg_class.h:145
BackendId rd_backend
Definition: rel.h:59
#define InvalidSubTransactionId
Definition: c.h:519
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:392
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
Oid tdtypeid
Definition: tupdesc.h:82
int rd_refcnt
Definition: rel.h:58
int i
int tdrefcount
Definition: tupdesc.h:84
bool has_not_null
Definition: tupdesc.h:44
#define RelationGetRelid(relation)
Definition: rel.h:456
SubTransactionId rd_droppedSubid
Definition: rel.h:107
void RelationMapUpdateMap(Oid relationId, Oid fileNode, bool shared, bool immediate)
Definition: relmapper.c:261
const TableAmRoutine * GetHeapamTableAmRoutine(void)

◆ GetPgClassDescriptor()

static TupleDesc GetPgClassDescriptor ( void  )
static

Definition at line 4203 of file relcache.c.

References BuildHardcodedDescriptor(), and Desc_pg_class.

Referenced by RelationParseRelOptions().

4204 {
4205  static TupleDesc pgclassdesc = NULL;
4206 
4207  /* Already done? */
4208  if (pgclassdesc == NULL)
4209  pgclassdesc = BuildHardcodedDescriptor(Natts_pg_class,
4210  Desc_pg_class);
4211 
4212  return pgclassdesc;
4213 }
static TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:4173
static const FormData_pg_attribute Desc_pg_class[Natts_pg_class]
Definition: relcache.c:107

◆ GetPgIndexDescriptor()

static TupleDesc GetPgIndexDescriptor ( void  )
static

Definition at line 4216 of file relcache.c.

References BuildHardcodedDescriptor(), and Desc_pg_index.

Referenced by RelationGetDummyIndexExpressions(), RelationGetIndexAttrBitmap(), RelationGetIndexExpressions(), RelationGetIndexPredicate(), and RelationInitIndexAccessInfo().

4217 {
4218  static TupleDesc pgindexdesc = NULL;
4219 
4220  /* Already done? */
4221  if (pgindexdesc == NULL)
4222  pgindexdesc = BuildHardcodedDescriptor(Natts_pg_index,
4223  Desc_pg_index);
4224 
4225  return pgindexdesc;
4226 }
static const FormData_pg_attribute Desc_pg_index[Natts_pg_index]
Definition: relcache.c:114
static TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:4173

◆ GetRelationPublicationActions()

struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

Definition at line 5297 of file relcache.c.

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

Referenced by CheckCmdReplicaIdentity().

5298 {
5299  List *puboids;
5300  ListCell *lc;
5301  MemoryContext oldcxt;
5302  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5303 
5304  /*
5305  * If not publishable, it publishes no actions. (pgoutput_change() will
5306  * ignore it.)
5307  */
5308  if (!is_publishable_relation(relation))
5309  return pubactions;
5310 
5311  if (relation->rd_pubactions)
5312  return memcpy(pubactions, relation->rd_pubactions,
5313  sizeof(PublicationActions));
5314 
5315  /* Fetch the publication membership info. */
5316  puboids = GetRelationPublications(RelationGetRelid(relation));
5317  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5318 
5319  foreach(lc, puboids)
5320  {
5321  Oid pubid = lfirst_oid(lc);
5322  HeapTuple tup;
5323  Form_pg_publication pubform;
5324 
5326 
5327  if (!HeapTupleIsValid(tup))
5328  elog(ERROR, "cache lookup failed for publication %u", pubid);
5329 
5330  pubform = (Form_pg_publication) GETSTRUCT(tup);
5331 
5332  pubactions->pubinsert |= pubform->pubinsert;
5333  pubactions->pubupdate |= pubform->pubupdate;
5334  pubactions->pubdelete |= pubform->pubdelete;
5335  pubactions->pubtruncate |= pubform->pubtruncate;
5336 
5337  ReleaseSysCache(tup);
5338 
5339  /*
5340  * If we know everything is replicated, there is no point to check for
5341  * other publications.
5342  */
5343  if (pubactions->pubinsert && pubactions->pubupdate &&
5344  pubactions->pubdelete && pubactions->pubtruncate)
5345  break;
5346  }
5347 
5348  if (relation->rd_pubactions)
5349  {
5350  pfree(relation->rd_pubactions);
5351  relation->rd_pubactions = NULL;
5352  }
5353 
5354  /* Now save copy of the actions in the relcache entry. */
5356  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5357  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5358  MemoryContextSwitchTo(oldcxt);
5359 
5360  return pubactions;
5361 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
PublicationActions * rd_pubactions
Definition: rel.h:150
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned int Oid
Definition: postgres_ext.h:31
List * GetRelationPublications(Oid relid)
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
List * list_concat_unique_oid(List *list1, const List *list2)
Definition: list.c:1302
bool is_publishable_relation(Relation rel)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
void * palloc0(Size size)
Definition: mcxt.c:980
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
List * GetAllTablesPublications(void)
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:214
FormData_pg_publication * Form_pg_publication
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:456
#define lfirst_oid(lc)
Definition: pg_list.h:192
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ IndexSupportInitialize()

static void IndexSupportInitialize ( oidvector indclass,
RegProcedure indexSupport,
Oid opFamily,
Oid opcInType,
StrategyNumber  maxSupportNumber,
AttrNumber  maxAttributeNumber 
)
static

Definition at line 1533 of file relcache.c.

References elog, ERROR, LookupOpclassInfo(), OidIsValid, opclasscacheent::opcfamily, opclasscacheent::opcintype, opclasscacheent::supportProcs, and oidvector::values.

Referenced by RelationInitIndexAccessInfo().

1539 {
1540  int attIndex;
1541 
1542  for (attIndex = 0; attIndex < maxAttributeNumber; attIndex++)
1543  {
1544  OpClassCacheEnt *opcentry;
1545 
1546  if (!OidIsValid(indclass->values[attIndex]))
1547  elog(ERROR, "bogus pg_index tuple");
1548 
1549  /* look up the info for this opclass, using a cache */
1550  opcentry = LookupOpclassInfo(indclass->values[attIndex],
1551  maxSupportNumber);
1552 
1553  /* copy cached data into relcache entry */
1554  opFamily[attIndex] = opcentry->opcfamily;
1555  opcInType[attIndex] = opcentry->opcintype;
1556  if (maxSupportNumber > 0)
1557  memcpy(&indexSupport[attIndex * maxSupportNumber],
1558  opcentry->supportProcs,
1559  maxSupportNumber * sizeof(RegProcedure));
1560  }
1561 }
regproc RegProcedure
Definition: c.h:511
#define OidIsValid(objectId)
Definition: c.h:644
#define ERROR
Definition: elog.h:43
RegProcedure * supportProcs
Definition: relcache.c:246
static OpClassCacheEnt * LookupOpclassInfo(Oid operatorClassOid, StrategyNumber numSupport)
Definition: relcache.c:1584
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:602
#define elog(elevel,...)
Definition: elog.h:214

◆ InitIndexAmRoutine()

static void InitIndexAmRoutine ( Relation  relation)
static

Definition at line 1339 of file relcache.c.

References GetIndexAmRoutine(), MemoryContextAlloc(), pfree(), RelationData::rd_amhandler, RelationData::rd_indam, and RelationData::rd_indexcxt.

Referenced by load_relcache_init_file(), and RelationInitIndexAccessInfo().

1340 {
1341  IndexAmRoutine *cached,
1342  *tmp;
1343 
1344  /*
1345  * Call the amhandler in current, short-lived memory context, just in case
1346  * it leaks anything (it probably won't, but let's be paranoid).
1347  */
1348  tmp = GetIndexAmRoutine(relation->rd_amhandler);
1349 
1350  /* OK, now transfer the data into relation's rd_indexcxt. */
1351  cached = (IndexAmRoutine *) MemoryContextAlloc(relation->rd_indexcxt,
1352  sizeof(IndexAmRoutine));
1353  memcpy(cached, tmp, sizeof(IndexAmRoutine));
1354  relation->rd_indam = cached;
1355 
1356  pfree(tmp);
1357 }
struct IndexAmRoutine * rd_indam
Definition: rel.h:188
void pfree(void *pointer)
Definition: mcxt.c:1056
Oid rd_amhandler
Definition: rel.h:166
IndexAmRoutine * GetIndexAmRoutine(Oid amhandler)
Definition: amapi.c:33
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
MemoryContext rd_indexcxt
Definition: rel.h:186

◆ InitTableAmRoutine()

static void InitTableAmRoutine ( Relation  relation)
static

Definition at line 1734 of file relcache.c.

References GetTableAmRoutine(), RelationData::rd_amhandler, and RelationData::rd_tableam.

Referenced by RelationInitTableAccessMethod().

1735 {
1736  relation->rd_tableam = GetTableAmRoutine(relation->rd_amhandler);
1737 }
Oid rd_amhandler
Definition: rel.h:166
const TableAmRoutine * GetTableAmRoutine(Oid amhandler)
Definition: tableamapi.c:34
const struct TableAmRoutine * rd_tableam
Definition: rel.h:171

◆ load_critical_index()

static void load_critical_index ( Oid  indexoid,
Oid  heapoid 
)
static

Definition at line 4137 of file relcache.c.

References AccessShareLock, elog, LockRelationOid(), PANIC, RelationData::rd_isnailed, RelationData::rd_refcnt, RelationBuildDesc(), RelationGetIndexAttOptions(), and UnlockRelationOid().

Referenced by RelationCacheInitializePhase3().

4138 {
4139  Relation ird;
4140 
4141  /*
4142  * We must lock the underlying catalog before locking the index to avoid
4143  * deadlock, since RelationBuildDesc might well need to read the catalog,
4144  * and if anyone else is exclusive-locking this catalog and index they'll
4145  * be doing it in that order.
4146  */
4147  LockRelationOid(heapoid, AccessShareLock);
4148  LockRelationOid(indexoid, AccessShareLock);
4149  ird = RelationBuildDesc(indexoid, true);
4150  if (ird == NULL)
4151  elog(PANIC, "could not open critical system index %u", indexoid);
4152  ird->rd_isnailed = true;
4153  ird->rd_refcnt = 1;
4156 
4157  (void) RelationGetIndexAttOptions(ird, false);
4158 }
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:199
bool rd_isnailed
Definition: rel.h:61
#define AccessShareLock
Definition: lockdefs.h:36
#define PANIC
Definition: elog.h:53
static Relation RelationBuildDesc(Oid targetRelId, bool insertIt)
Definition: relcache.c:1026
int rd_refcnt
Definition: rel.h:58
#define elog(elevel,...)
Definition: elog.h:214
bytea ** RelationGetIndexAttOptions(Relation relation, bool copy)
Definition: relcache.c:5413
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:108

◆ load_relcache_init_file()

static bool load_relcache_init_file ( bool  shared)
static

Definition at line 5591 of file relcache.c.

References AllocateFile(), ALLOCSET_SMALL_SIZES, AllocSetContextCreate, IndexAmRoutine::amsupport, Assert, ATTRIBUTE_FIXED_PART_SIZE, CacheMemoryContext, TupleDescData::constr, CreateTemplateTupleDesc(), criticalRelcachesBuilt, criticalSharedRelcachesBuilt, DatabasePath, elog, FreeFile(), GETSTRUCT, TupleConstr::has_not_null, HEAPTUPLESIZE, i, InitIndexAmRoutine(), InvalidOid, InvalidSubTransactionId, MAXPGPATH, MemoryContextAlloc(), MemoryContextAllocZero(), MemoryContextCopyAndSetIdentifier, MemSet, NIL, NUM_CRITICAL_LOCAL_INDEXES, NUM_CRITICAL_LOCAL_RELS, NUM_CRITICAL_SHARED_INDEXES, NUM_CRITICAL_SHARED_RELS, palloc(), palloc0(), pfree(), PG_BINARY_R, RelationData::pgstat_info, RelationData::rd_amcache, RelationData::rd_att, RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_exclops, RelationData::rd_exclprocs, RelationData::rd_exclstrats, RelationData::rd_fdwroutine, RelationData::rd_firstRelfilenodeSubid, RelationData::rd_fkeylist, RelationData::rd_fkeyvalid, RelationData::rd_idattr, RelationData::rd_indam, RelationData::rd_indcollation, RelationData::rd_index, RelationData::rd_indexattr, RelationData::rd_indexcxt, RelationData::rd_indexlist, RelationData::rd_indexprs, RelationData::rd_indextuple, RelationData::rd_indexvalid, RelationData::rd_indoption, RelationData::rd_indpred, RelationData::rd_isnailed, RelationData::rd_keyattr, RelationData::rd_newRelfilenodeSubid, RelationData::rd_opcintype, RelationData::rd_opcoptions, RelationData::rd_opfamily, RelationData::rd_options, RelationData::rd_partcheck, RelationData::rd_partcheckcxt, RelationData::rd_partcheckvalid, RelationData::rd_partdesc, RelationData::rd_partkey, RelationData::rd_partkeycxt, RelationData::rd_pdcxt, RelationData::rd_pkattr, RelationData::rd_pkindex, RelationData::rd_pubactions, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_replidindex, RelationData::rd_rsdesc, RelationData::rd_rules, RelationData::rd_rulescxt, RelationData::rd_smgr, RelationData::rd_statlist, RelationData::rd_statvalid, RelationData::rd_support, RelationData::rd_supportinfo, RelationCacheInsert, RelationGetRelationName, RelationInitLockInfo(), RelationInitPhysicalAddr(), RelationInitTableAccessMethod(), RELCACHE_INIT_FILEMAGIC, RELCACHE_INIT_FILENAME, repalloc(), snprintf, HeapTupleData::t_data, TupleDescData::tdrefcount, TupleDescData::tdtypeid, TupleDescData::tdtypmod, RelationData::trigdesc, TupleDescAttr, VARSIZE, and WARNING.

Referenced by RelationCacheInitializePhase2(), and RelationCacheInitializePhase3().

5592 {
5593  FILE *fp;
5594  char initfilename[MAXPGPATH];
5595  Relation *rels;
5596  int relno,
5597  num_rels,
5598  max_rels,
5599  nailed_rels,
5600  nailed_indexes,
5601  magic;
5602  int i;
5603 
5604  if (shared)
5605  snprintf(initfilename, sizeof(initfilename), "global/%s",
5607  else
5608  snprintf(initfilename, sizeof(initfilename), "%s/%s",
5610 
5611  fp = AllocateFile(initfilename, PG_BINARY_R);
5612  if (fp == NULL)
5613  return false;
5614 
5615  /*
5616  * Read the index relcache entries from the file. Note we will not enter
5617  * any of them into the cache if the read fails partway through; this
5618  * helps to guard against broken init files.
5619  */
5620  max_rels = 100;
5621  rels = (Relation *) palloc(max_rels * sizeof(Relation));
5622  num_rels = 0;
5623  nailed_rels = nailed_indexes = 0;
5624 
5625  /* check for correct magic number (compatible version) */
5626  if (fread(&magic, 1, sizeof(magic), fp) != sizeof(magic))
5627  goto read_failed;
5628  if (magic != RELCACHE_INIT_FILEMAGIC)
5629  goto read_failed;
5630 
5631  for (relno = 0;; relno++)
5632  {
5633  Size len;
5634  size_t nread;
5635  Relation rel;
5636  Form_pg_class relform;
5637  bool has_not_null;
5638 
5639  /* first read the relation descriptor length */
5640  nread = fread(&len, 1, sizeof(len), fp);
5641  if (nread != sizeof(len))
5642  {
5643  if (nread == 0)
5644  break; /* end of file */
5645  goto read_failed;
5646  }
5647 
5648  /* safety check for incompatible relcache layout */
5649  if (len != sizeof(RelationData))
5650  goto read_failed;
5651 
5652  /* allocate another relcache header */
5653  if (num_rels >= max_rels)
5654  {
5655  max_rels *= 2;
5656  rels = (Relation *) repalloc(rels, max_rels * sizeof(Relation));
5657  }
5658 
5659  rel = rels[num_rels++] = (Relation) palloc(len);
5660 
5661  /* then, read the Relation structure */
5662  if (fread(rel, 1, len, fp) != len)
5663  goto read_failed;
5664 
5665  /* next read the relation tuple form */
5666  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5667  goto read_failed;
5668 
5669  relform = (Form_pg_class) palloc(len);
5670  if (fread(relform, 1, len, fp) != len)
5671  goto read_failed;
5672 
5673  rel->rd_rel = relform;
5674 
5675  /* initialize attribute tuple forms */
5676  rel->rd_att = CreateTemplateTupleDesc(relform->relnatts);
5677  rel->rd_att->tdrefcount = 1; /* mark as refcounted */
5678 
5679  rel->rd_att->tdtypeid = relform->reltype;
5680  rel->rd_att->tdtypmod = -1; /* unnecessary, but... */
5681 
5682  /* next read all the attribute tuple form data entries */
5683  has_not_null = false;
5684  for (i = 0; i < relform->relnatts; i++)
5685  {
5686  Form_pg_attribute attr = TupleDescAttr(rel->rd_att, i);
5687 
5688  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5689  goto read_failed;
5690  if (len != ATTRIBUTE_FIXED_PART_SIZE)
5691  goto read_failed;
5692  if (fread(attr, 1, len, fp) != len)
5693  goto read_failed;
5694 
5695  has_not_null |= attr->attnotnull;
5696  }
5697 
5698  /* next read the access method specific field */
5699  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5700  goto read_failed;
5701  if (len > 0)
5702  {
5703  rel->rd_options = palloc(len);
5704  if (fread(rel->rd_options, 1, len, fp) != len)
5705  goto read_failed;
5706  if (len != VARSIZE(rel->rd_options))
5707  goto read_failed; /* sanity check */
5708  }
5709  else
5710  {
5711  rel->rd_options = NULL;
5712  }
5713 
5714  /* mark not-null status */
5715  if (has_not_null)
5716  {
5717  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
5718 
5719  constr->has_not_null = true;
5720  rel->rd_att->constr = constr;
5721  }
5722 
5723  /*
5724  * If it's an index, there's more to do. Note we explicitly ignore
5725  * partitioned indexes here.
5726  */
5727  if (rel->rd_rel->relkind == RELKIND_INDEX)
5728  {
5729  MemoryContext indexcxt;
5730  Oid *opfamily;
5731  Oid *opcintype;
5732  RegProcedure *support;
5733  int nsupport;
5734  int16 *indoption;
5735  Oid *indcollation;
5736 
5737  /* Count nailed indexes to ensure we have 'em all */
5738  if (rel->rd_isnailed)
5739  nailed_indexes++;
5740 
5741  /* next, read the pg_index tuple */
5742  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5743  goto read_failed;
5744 
5745  rel->rd_indextuple = (HeapTuple) palloc(len);
5746  if (fread(rel->rd_indextuple, 1, len, fp) != len)
5747  goto read_failed;
5748 
5749  /* Fix up internal pointers in the tuple -- see heap_copytuple */
5750  rel->rd_indextuple->t_data = (HeapTupleHeader) ((char *) rel->rd_indextuple + HEAPTUPLESIZE);
5752 
5753  /*
5754  * prepare index info context --- parameters should match
5755  * RelationInitIndexAccessInfo
5756  */
5758  "index info",
5760  rel->rd_indexcxt = indexcxt;
5763 
5764  /*
5765  * Now we can fetch the index AM's API struct. (We can't store
5766  * that in the init file, since it contains function pointers that
5767  * might vary across server executions. Fortunately, it should be
5768  * safe to call the amhandler even while bootstrapping indexes.)
5769  */
5770  InitIndexAmRoutine(rel);
5771 
5772  /* next, read the vector of opfamily OIDs */
5773  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5774  goto read_failed;
5775 
5776  opfamily = (Oid *) MemoryContextAlloc(indexcxt, len);
5777  if (fread(opfamily, 1, len, fp) != len)
5778  goto read_failed;
5779 
5780  rel->rd_opfamily = opfamily;
5781 
5782  /* next, read the vector of opcintype OIDs */
5783  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5784  goto read_failed;
5785 
5786  opcintype = (Oid *) MemoryContextAlloc(indexcxt, len);
5787  if (fread(opcintype, 1, len, fp) != len)
5788  goto read_failed;
5789 
5790  rel->rd_opcintype = opcintype;
5791 
5792  /* next, read the vector of support procedure OIDs */
5793  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5794  goto read_failed;
5795  support = (RegProcedure *) MemoryContextAlloc(indexcxt, len);
5796  if (fread(support, 1, len, fp) != len)
5797  goto read_failed;
5798 
5799  rel->rd_support = support;
5800 
5801  /* next, read the vector of collation OIDs */
5802  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5803  goto read_failed;
5804 
5805  indcollation = (Oid *) MemoryContextAlloc(indexcxt, len);
5806  if (fread(indcollation, 1, len, fp) != len)
5807  goto read_failed;
5808 
5809  rel->rd_indcollation = indcollation;
5810 
5811  /* finally, read the vector of indoption values */
5812  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5813  goto read_failed;
5814 
5815  indoption = (int16 *) MemoryContextAlloc(indexcxt, len);
5816  if (fread(indoption, 1, len, fp) != len)
5817  goto read_failed;
5818 
5819  rel->rd_indoption = indoption;
5820 
5821  /* finally, read the vector of opcoptions values */
5822  rel->rd_opcoptions = (bytea **)
5823  MemoryContextAllocZero(indexcxt, sizeof(*rel->rd_opcoptions) * relform->relnatts);
5824 
5825  for (i = 0; i < relform->relnatts; i++)
5826  {
5827  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5828  goto read_failed;
5829 
5830  if (len > 0)
5831  {
5832  rel->rd_opcoptions[i] = (bytea *) MemoryContextAlloc(indexcxt, len);
5833  if (fread(rel->rd_opcoptions[i], 1, len, fp) != len)
5834  goto read_failed;
5835  }
5836  }
5837 
5838  /* set up zeroed fmgr-info vector */
5839  nsupport = relform->relnatts * rel->rd_indam->amsupport;
5840  rel->rd_supportinfo = (FmgrInfo *)
5841  MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
5842  }
5843  else
5844  {
5845  /* Count nailed rels to ensure we have 'em all */
5846  if (rel->rd_isnailed)
5847  nailed_rels++;
5848 
5849  /* Load table AM data */
5850  if (rel->rd_rel->relkind == RELKIND_RELATION ||
5851  rel->rd_rel->relkind == RELKIND_SEQUENCE ||
5852  rel->rd_rel->relkind == RELKIND_TOASTVALUE ||
5853  rel->rd_rel->relkind == RELKIND_MATVIEW)
5855 
5856  Assert(rel->rd_index == NULL);
5857  Assert(rel->rd_indextuple == NULL);
5858  Assert(rel->rd_indexcxt == NULL);
5859  Assert(rel->rd_indam == NULL);
5860  Assert(rel->rd_opfamily == NULL);
5861  Assert(rel->rd_opcintype == NULL);
5862  Assert(rel->rd_support == NULL);
5863  Assert(rel->rd_supportinfo == NULL);
5864  Assert(rel->rd_indoption == NULL);
5865  Assert(rel->rd_indcollation == NULL);
5866  Assert(rel->rd_opcoptions == NULL);
5867  }
5868 
5869  /*
5870  * Rules and triggers are not saved (mainly because the internal
5871  * format is complex and subject to change). They must be rebuilt if
5872  * needed by RelationCacheInitializePhase3. This is not expected to
5873  * be a big performance hit since few system catalogs have such. Ditto
5874  * for RLS policy data, partition info, index expressions, predicates,
5875  * exclusion info, and FDW info.
5876  */
5877  rel->rd_rules = NULL;
5878  rel->rd_rulescxt = NULL;
5879  rel->trigdesc = NULL;
5880  rel->rd_rsdesc = NULL;
5881  rel->rd_partkey = NULL;
5882  rel->rd_partkeycxt = NULL;
5883  rel->rd_partdesc = NULL;
5884  rel->rd_pdcxt = NULL;
5885  rel->rd_partcheck = NIL;
5886  rel->rd_partcheckvalid = false;
5887  rel->rd_partcheckcxt = NULL;
5888  rel->rd_indexprs = NIL;
5889  rel->rd_indpred = NIL;
5890  rel->rd_exclops = NULL;
5891  rel->rd_exclprocs = NULL;
5892  rel->rd_exclstrats = NULL;
5893  rel->rd_fdwroutine = NULL;
5894 
5895  /*
5896  * Reset transient-state fields in the relcache entry
5897  */
5898  rel->rd_smgr = NULL;
5899  if (rel->rd_isnailed)
5900  rel->rd_refcnt = 1;
5901  else
5902  rel->rd_refcnt = 0;
5903  rel->rd_indexvalid = false;
5904  rel->rd_indexlist = NIL;
5905  rel->rd_pkindex = InvalidOid;
5906  rel->rd_replidindex = InvalidOid;
5907  rel->rd_indexattr = NULL;
5908  rel->rd_keyattr = NULL;
5909  rel->rd_pkattr = NULL;
5910  rel->rd_idattr = NULL;
5911  rel->rd_pubactions = NULL;
5912  rel->rd_statvalid = false;
5913  rel->rd_statlist = NIL;
5914  rel->rd_fkeyvalid = false;
5915  rel->rd_fkeylist = NIL;
5920  rel->rd_amcache = NULL;
5921  MemSet(&rel->pgstat_info, 0, sizeof(rel->pgstat_info));
5922 
5923  /*
5924  * Recompute lock and physical addressing info. This is needed in
5925  * case the pg_internal.init file was copied from some other database
5926  * by CREATE DATABASE.
5927  */
5928  RelationInitLockInfo(rel);
5930  }
5931 
5932  /*
5933  * We reached the end of the init file without apparent problem. Did we
5934  * get the right number of nailed items? This is a useful crosscheck in
5935  * case the set of critical rels or indexes changes. However, that should
5936  * not happen in a normally-running system, so let's bleat if it does.
5937  *
5938  * For the shared init file, we're called before client authentication is
5939  * done, which means that elog(WARNING) will go only to the postmaster
5940  * log, where it's easily missed. To ensure that developers notice bad
5941  * values of NUM_CRITICAL_SHARED_RELS/NUM_CRITICAL_SHARED_INDEXES, we put
5942  * an Assert(false) there.
5943  */
5944  if (shared)
5945  {
5946  if (nailed_rels != NUM_CRITICAL_SHARED_RELS ||
5947  nailed_indexes != NUM_CRITICAL_SHARED_INDEXES)
5948  {
5949  elog(WARNING, "found %d nailed shared rels and %d nailed shared indexes in init file, but expected %d and %d respectively",
5950  nailed_rels, nailed_indexes,
5952  /* Make sure we get developers' attention about this */
5953  Assert(false);
5954  /* In production builds, recover by bootstrapping the relcache */
5955  goto read_failed;
5956  }
5957  }
5958  else
5959  {
5960  if (nailed_rels != NUM_CRITICAL_LOCAL_RELS ||
5961  nailed_indexes != NUM_CRITICAL_LOCAL_INDEXES)
5962  {
5963  elog(WARNING, "found %d nailed rels and %d nailed indexes in init file, but expected %d and %d respectively",
5964  nailed_rels, nailed_indexes,
5966  /* We don't need an Assert() in this case */
5967  goto read_failed;
5968  }
5969  }
5970 
5971  /*
5972  * OK, all appears well.
5973  *
5974  * Now insert all the new relcache entries into the cache.
5975  */
5976  for (relno = 0; relno < num_rels; relno++)
5977  {
5978  RelationCacheInsert(rels[relno], false);
5979  }
5980 
5981  pfree(rels);
5982  FreeFile(fp);
5983 
5984  if (shared)
5986  else
5987  criticalRelcachesBuilt = true;
5988  return true;
5989 
5990  /*
5991  * init file is broken, so do it the hard way. We don't bother trying to
5992  * free the clutter we just allocated; it's not in the relcache so it
5993  * won't hurt.
5994  */
5995 read_failed:
5996  pfree(rels);
5997  FreeFile(fp);
5998 
5999  return false;
6000 }
struct FdwRoutine * rd_fdwroutine
Definition: rel.h:222
signed short int16
Definition: c.h:354
#define NIL
Definition: pg_list.h:65
struct IndexAmRoutine * rd_indam
Definition: rel.h:188
Definition: fmgr.h:56
uint16 amsupport
Definition: amapi.h:173
#define AllocSetContextCreate
Definition: memutils.h:170
HeapTupleData * HeapTuple
Definition: htup.h:71
int16 * rd_indoption
Definition: rel.h:193
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
PublicationActions * rd_pubactions
Definition: rel.h:150
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:44
struct FmgrInfo * rd_supportinfo
Definition: rel.h:192
Bitmapset * rd_keyattr
Definition: rel.h:146
#define VARSIZE(PTR)
Definition: postgres.h:303
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
void RelationInitTableAccessMethod(Relation relation)
Definition: relcache.c:1743
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
Oid rd_replidindex
Definition: rel.h:139
struct SMgrRelationData * rd_smgr
Definition: rel.h:57
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:202
bool rd_isnailed
Definition: rel.h:61
regproc RegProcedure
Definition: c.h:511
uint16 * rd_exclstrats
Definition: rel.h:198
#define NUM_CRITICAL_LOCAL_INDEXES
List * rd_indexprs
Definition: rel.h:194
bytea ** rd_opcoptions
Definition: rel.h:200
List * rd_fkeylist
Definition: rel.h:120
bool rd_partcheckvalid
Definition: rel.h:133
#define MemSet(start, val, len)
Definition: c.h:971
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:103
MemoryContext rd_rulescxt
Definition: rel.h:114
bool criticalSharedRelcachesBuilt
Definition: relcache.c:142
Oid * rd_exclprocs
Definition: rel.h:197
Form_pg_class rd_rel
Definition: rel.h:109
unsigned int Oid
Definition: postgres_ext.h:31
#define NUM_CRITICAL_SHARED_INDEXES
#define PG_BINARY_R
Definition: c.h:1236
#define NUM_CRITICAL_SHARED_RELS
static void InitIndexAmRoutine(Relation relation)
Definition: relcache.c:1339
struct HeapTupleData * rd_indextuple
Definition: rel.h:176
HeapTupleHeader t_data
Definition: htup.h:68
struct RelationData * Relation
Definition: relcache.h:27
Form_pg_index rd_index
Definition: rel.h:174
PartitionKey rd_partkey
Definition: rel.h:124
void pfree(void *pointer)
Definition: mcxt.c:1056
#define NUM_CRITICAL_LOCAL_RELS
Oid * rd_indcollation
Definition: rel.h:199
int32 tdtypmod
Definition: tupdesc.h:83
Oid rd_pkindex
Definition: rel.h:138
#define MAXPGPATH
TriggerDesc * trigdesc
Definition: rel.h:115
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1272
void RelationInitLockInfo(Relation relation)
Definition: lmgr.c:71
#define MemoryContextCopyAndSetIdentifier(cxt, id)
Definition: memutils.h:97
TupleConstr * constr
Definition: tupdesc.h:85
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2320
#define RELCACHE_INIT_FILEMAGIC
Definition: relcache.c:89
#define RelationGetRelationName(relation)
Definition: rel.h:490
List * rd_indpred
Definition: rel.h:195
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
Oid * rd_opfamily
Definition: rel.h:189
Oid * rd_exclops
Definition: rel.h:196
PartitionDesc rd_partdesc
Definition: rel.h:128
List * rd_indexlist
Definition: rel.h:137
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:185
struct RowSecurityDesc * rd_rsdesc
Definition: rel.h:117
RegProcedure * rd_support
Definition: rel.h:191
#define WARNING
Definition: elog.h:40
FormData_pg_index * Form_pg_index
Definition: pg_index.h:66
SubTransactionId rd_createSubid
Definition: rel.h:102
bool rd_indexvalid
Definition: rel.h:63
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
void * palloc0(Size size)
Definition: mcxt.c:980
TupleDesc rd_att
Definition: rel.h:110
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:839
#define InvalidOid
Definition: postgres_ext.h:36
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25
Bitmapset * rd_idattr
Definition: rel.h:148
#define RelationCacheInsert(RELATION, replace_allowed)
Definition: relcache.c:187
char * DatabasePath
Definition: globals.c:93
MemoryContext rd_pdcxt
Definition: rel.h:129
#define Assert(condition)
Definition: c.h:738
MemoryContext rd_partkeycxt
Definition: rel.h:125
RuleLock * rd_rules
Definition: rel.h:113
size_t Size
Definition: c.h:466
struct PgStat_TableStatus * pgstat_info
Definition: rel.h:236
#define InvalidSubTransactionId
Definition: c.h:519
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
int FreeFile(FILE *file)
Definition: fd.c:2519
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
Bitmapset * rd_pkattr
Definition: rel.h:147
Oid tdtypeid
Definition: tupdesc.h:82
bool rd_statvalid
Definition: rel.h:65
void * palloc(Size size)
Definition: mcxt.c:949
int rd_refcnt
Definition: rel.h:58
#define HEAPTUPLESIZE
Definition: htup.h:73
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
#define elog(elevel,...)
Definition: elog.h:214
MemoryContext rd_indexcxt
Definition: rel.h:186
int i
int tdrefcount
Definition: tupdesc.h:84
Definition: c.h:555
MemoryContext rd_partcheckcxt
Definition: rel.h:134
bool criticalRelcachesBuilt
Definition: relcache.c:136
void * rd_amcache
Definition: rel.h:211
Oid * rd_opcintype
Definition: rel.h:190
bool has_not_null
Definition: tupdesc.h:44
List * rd_statlist
Definition: rel.h:142
#define snprintf
Definition: port.h:193
bool rd_fkeyvalid
Definition: rel.h:121
List * rd_partcheck
Definition: rel.h:132
Bitmapset * rd_indexattr
Definition: rel.h:145
bytea * rd_options
Definition: rel.h:157
SubTransactionId rd_droppedSubid
Definition: rel.h:107
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ LookupOpclassInfo()

static OpClassCacheEnt * LookupOpclassInfo ( Oid  operatorClassOid,
StrategyNumber  numSupport 
)
static

Definition at line 1584 of file relcache.c.

References AccessMethodProcedureIndexId, AccessShareLock, Assert, BTEqualStrategyNumber, CacheMemoryContext, CreateCacheMemoryContext(), criticalRelcachesBuilt, elog, HASHCTL::entrysize, ERROR, GETSTRUCT, HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), HeapTupleIsValid, HASHCTL::keysize, MemoryContextAllocZero(), MemSet, opclasscacheent::numSupport, ObjectIdGetDatum, opclasscacheent::opcfamily, opclasscacheent::opcintype, OpclassOidIndexId, ScanKeyInit(), opclasscacheent::supportProcs, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), and opclasscacheent::valid.

Referenced by IndexSupportInitialize().

1586 {
1587  OpClassCacheEnt *opcentry;
1588  bool found;
1589  Relation rel;
1590  SysScanDesc scan;
1591  ScanKeyData skey[3];
1592  HeapTuple htup;
1593  bool indexOK;
1594 
1595  if (OpClassCache == NULL)
1596  {
1597  /* First time through: initialize the opclass cache */
1598  HASHCTL ctl;
1599 
1600  MemSet(&ctl, 0, sizeof(ctl));
1601  ctl.keysize = sizeof(Oid);
1602  ctl.entrysize = sizeof(OpClassCacheEnt);
1603  OpClassCache = hash_create("Operator class cache", 64,
1604  &ctl, HASH_ELEM | HASH_BLOBS);
1605 
1606  /* Also make sure CacheMemoryContext exists */
1607  if (!CacheMemoryContext)
1609  }
1610 
1611  opcentry = (OpClassCacheEnt *) hash_search(OpClassCache,
1612  (void *) &operatorClassOid,
1613  HASH_ENTER, &found);
1614 
1615  if (!found)
1616  {
1617  /* Need to allocate memory for new entry */
1618  opcentry->valid = false; /* until known OK */
1619  opcentry->numSupport = numSupport;
1620 
1621  if (numSupport > 0)
1622  opcentry->supportProcs = (RegProcedure *)
1624  (numSupport + 1) * sizeof(RegProcedure));
1625  else
1626  opcentry->supportProcs = NULL;
1627  }
1628  else
1629  {
1630  Assert(numSupport == opcentry->numSupport);
1631  }
1632 
1633  /*
1634  * When testing for cache-flush hazards, we intentionally disable the
1635  * operator class cache and force reloading of the info on each call. This
1636  * is helpful because we want to test the case where a cache flush occurs
1637  * while we are loading the info, and it's very hard to provoke that if
1638  * this happens only once per opclass per backend.
1639  */
1640 #if defined(CLOBBER_CACHE_ALWAYS)
1641  opcentry->valid = false;
1642 #endif
1643 
1644  if (opcentry->valid)
1645  return opcentry;
1646 
1647  /*
1648  * Need to fill in new entry.
1649  *
1650  * To avoid infinite recursion during startup, force heap scans if we're
1651  * looking up info for the opclasses used by the indexes we would like to
1652  * reference here.
1653  */
1654  indexOK = criticalRelcachesBuilt ||
1655  (operatorClassOid != OID_BTREE_OPS_OID &&
1656  operatorClassOid != INT2_BTREE_OPS_OID);
1657 
1658  /*
1659  * We have to fetch the pg_opclass row to determine its opfamily and
1660  * opcintype, which are needed to look up related operators and functions.
1661  * It'd be convenient to use the syscache here, but that probably doesn't
1662  * work while bootstrapping.
1663  */
1664  ScanKeyInit(&skey[0],
1665  Anum_pg_opclass_oid,
1666  BTEqualStrategyNumber, F_OIDEQ,
1667  ObjectIdGetDatum(operatorClassOid));
1668  rel = table_open(OperatorClassRelationId, AccessShareLock);
1669  scan = systable_beginscan(rel, OpclassOidIndexId, indexOK,
1670  NULL, 1, skey);
1671 
1672  if (HeapTupleIsValid(htup = systable_getnext(scan)))
1673  {
1674  Form_pg_opclass opclassform = (Form_pg_opclass) GETSTRUCT(htup);
1675 
1676  opcentry->opcfamily = opclassform->opcfamily;
1677  opcentry->opcintype = opclassform->opcintype;
1678  }
1679  else
1680  elog(ERROR, "could not find tuple for opclass %u", operatorClassOid);
1681 
1682  systable_endscan(scan);
1684 
1685  /*
1686  * Scan pg_amproc to obtain support procs for the opclass. We only fetch
1687  * the default ones (those with lefttype = righttype = opcintype).
1688  */
1689  if (numSupport > 0)
1690  {
1691  ScanKeyInit(&skey[0],
1692  Anum_pg_amproc_amprocfamily,
1693  BTEqualStrategyNumber, F_OIDEQ,
1694  ObjectIdGetDatum(opcentry->opcfamily));
1695  ScanKeyInit(&skey[1],
1696  Anum_pg_amproc_amproclefttype,
1697  BTEqualStrategyNumber, F_OIDEQ,
1698  ObjectIdGetDatum(opcentry->opcintype));
1699  ScanKeyInit(&skey[2],
1700  Anum_pg_amproc_amprocrighttype,
1701  BTEqualStrategyNumber, F_OIDEQ,
1702  ObjectIdGetDatum(opcentry->opcintype));
1703  rel = table_open(AccessMethodProcedureRelationId, AccessShareLock);
1704  scan = systable_beginscan(rel, AccessMethodProcedureIndexId, indexOK,
1705  NULL, 3, skey);
1706 
1707  while (HeapTupleIsValid(htup = systable_getnext(scan)))
1708  {
1709  Form_pg_amproc amprocform = (Form_pg_amproc) GETSTRUCT(htup);
1710 
1711  if (amprocform->amprocnum <= 0 ||
1712  (StrategyNumber) amprocform->amprocnum > numSupport)
1713  elog(ERROR, "invalid amproc number %d for opclass %u",
1714  amprocform->amprocnum, operatorClassOid);
1715 
1716  opcentry->supportProcs[amprocform->amprocnum - 1] =
1717  amprocform->amproc;
1718  }
1719 
1720  systable_endscan(scan);
1722  }
1723 
1724  opcentry->valid = true;
1725  return opcentry;
1726 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
struct opclasscacheent OpClassCacheEnt
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define HASH_ELEM
Definition: hsearch.h:87
FormData_pg_amproc * Form_pg_amproc
Definition: pg_amproc.h:68
regproc RegProcedure
Definition: c.h:511
#define AccessShareLock
Definition: lockdefs.h:36
Size entrysize
Definition: hsearch.h:73
uint16 StrategyNumber
Definition: stratnum.h:22
#define MemSet(start, val, len)
Definition: c.h:971
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:907
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
StrategyNumber numSupport
Definition: relcache.c:243
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
RegProcedure * supportProcs
Definition: relcache.c:246
static HTAB * OpClassCache
Definition: relcache.c:249
#define HASH_BLOBS
Definition: hsearch.h:88
#define AccessMethodProcedureIndexId
Definition: indexing.h:84
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:317
Size keysize
Definition: hsearch.h:72
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:839
#define OpclassOidIndexId
Definition: indexing.h:197
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:738
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
#define elog(elevel,...)
Definition: elog.h:214
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
bool criticalRelcachesBuilt
Definition: relcache.c:136
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:83
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationAssumeNewRelfilenode()

void RelationAssumeNewRelfilenode ( Relation  relation)

Definition at line 3729 of file relcache.c.

References EOXactListAdd, GetCurrentSubTransactionId(), InvalidSubTransactionId, RelationData::rd_firstRelfilenodeSubid, and RelationData::rd_newRelfilenodeSubid.

Referenced by ATExecSetTableSpace(), RelationSetNewRelfilenode(), and swap_relation_files().

3730 {
3733  relation->rd_firstRelfilenodeSubid = relation->rd_newRelfilenodeSubid;
3734 
3735  /* Flag relation as needing eoxact cleanup (to clear these fields) */
3736  EOXactListAdd(relation);
3737 }
#define EOXactListAdd(rel)
Definition: relcache.c:167
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:103
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:707
#define InvalidSubTransactionId
Definition: c.h:519

◆ RelationBuildDesc()

static Relation RelationBuildDesc ( Oid  targetRelId,
bool  insertIt 
)
static

Definition at line 1026 of file relcache.c.

References AllocateRelationDesc(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, BackendIdForTempRelations, CurrentMemoryContext, elog, ERROR, GETSTRUCT, GetTempNamespaceBackendId(), heap_freetuple(), HeapTupleIsValid, InvalidBackendId, InvalidOid, InvalidSubTransactionId, IsParallelWorker, isTempOrTempToastNamespace(), MemoryContextDelete(), MemoryContextSwitchTo(), NIL, RelationData::rd_backend, RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_firstRelfilenodeSubid, RelationData::rd_fkeylist, RelationData::rd_fkeyvalid, RelationData::rd_islocaltemp, RelationData::rd_isnailed, RelationData::rd_isvalid, RelationData::rd_newRelfilenodeSubid, RelationData::rd_node, RelationData::rd_partcheck, RelationData::rd_partcheckcxt, RelationData::rd_partcheckvalid, RelationData::rd_partdesc, RelationData::rd_partkey, RelationData::rd_partkeycxt, RelationData::rd_pdcxt, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_rsdesc, RelationData::rd_rules, RelationData::rd_rulescxt, RelationData::rd_smgr, RelationBuildRowSecurity(), RelationBuildRuleLock(), RelationBuildTriggers(), RelationBuildTupleDesc(), RelationCacheInsert, RelationGetRelid, RelationInitIndexAccessInfo(), RelationInitLockInfo(), RelationInitPhysicalAddr(), RelationInitTableAccessMethod(), RelationParseRelOptions(), RelFileNodeSkippingWAL(), ScanPgRelation(), TopSubTransactionId, and RelationData::trigdesc.

Referenced by load_critical_index(), RelationClearRelation(), and RelationIdGetRelation().

1027 {
1028  Relation relation;
1029  Oid relid;
1030  HeapTuple pg_class_tuple;
1031  Form_pg_class relp;
1032 
1033  /*
1034  * This function and its subroutines can allocate a good deal of transient
1035  * data in CurrentMemoryContext. Traditionally we've just leaked that
1036  * data, reasoning that the caller's context is at worst of transaction
1037  * scope, and relcache loads shouldn't happen so often that it's essential
1038  * to recover transient data before end of statement/transaction. However
1039  * that's definitely not true in clobber-cache test builds, and perhaps
1040  * it's not true in other cases. If RECOVER_RELATION_BUILD_MEMORY is not
1041  * zero, arrange to allocate the junk in a temporary context that we'll
1042  * free before returning. Make it a child of caller's context so that it
1043  * will get cleaned up appropriately if we error out partway through.
1044  */
1045 #if RECOVER_RELATION_BUILD_MEMORY
1046  MemoryContext tmpcxt;
1047  MemoryContext oldcxt;
1048 
1050  "RelationBuildDesc workspace",
1052  oldcxt = MemoryContextSwitchTo(tmpcxt);
1053 #endif
1054 
1055  /*
1056  * find the tuple in pg_class corresponding to the given relation id
1057  */
1058  pg_class_tuple = ScanPgRelation(targetRelId, true, false);
1059 
1060  /*
1061  * if no such tuple exists, return NULL
1062  */
1063  if (!HeapTupleIsValid(pg_class_tuple))
1064  {
1065 #if RECOVER_RELATION_BUILD_MEMORY
1066  /* Return to caller's context, and blow away the temporary context */
1067  MemoryContextSwitchTo(oldcxt);
1068  MemoryContextDelete(tmpcxt);
1069 #endif
1070  return NULL;
1071  }
1072 
1073  /*
1074  * get information from the pg_class_tuple
1075  */
1076  relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);
1077  relid = relp->oid;
1078  Assert(relid == targetRelId);
1079 
1080  /*
1081  * allocate storage for the relation descriptor, and copy pg_class_tuple
1082  * to relation->rd_rel.
1083  */
1084  relation = AllocateRelationDesc(relp);
1085 
1086  /*
1087  * initialize the relation's relation id (relation->rd_id)
1088  */
1089  RelationGetRelid(relation) = relid;
1090 
1091  /*
1092  * Normal relations are not nailed into the cache. Since we don't flush
1093  * new relations, it won't be new. It could be temp though.
1094  */
1095  relation->rd_refcnt = 0;
1096  relation->rd_isnailed = false;
1101  switch (relation->rd_rel->relpersistence)
1102  {
1103  case RELPERSISTENCE_UNLOGGED:
1104  case RELPERSISTENCE_PERMANENT:
1105  relation->rd_backend = InvalidBackendId;
1106  relation->rd_islocaltemp = false;
1107  break;
1108  case RELPERSISTENCE_TEMP:
1109  if (isTempOrTempToastNamespace(relation->rd_rel->relnamespace))
1110  {
1111  relation->rd_backend = BackendIdForTempRelations();
1112  relation->rd_islocaltemp = true;
1113  }
1114  else
1115  {
1116  /*
1117  * If it's a temp table, but not one of ours, we have to use
1118  * the slow, grotty method to figure out the owning backend.
1119  *
1120  * Note: it's possible that rd_backend gets set to MyBackendId
1121  * here, in case we are looking at a pg_class entry left over
1122  * from a crashed backend that coincidentally had the same
1123  * BackendId we're using. We should *not* consider such a
1124  * table to be "ours"; this is why we need the separate
1125  * rd_islocaltemp flag. The pg_class entry will get flushed
1126  * if/when we clean out the corresponding temp table namespace
1127  * in preparation for using it.
1128  */
1129  relation->rd_backend =
1130  GetTempNamespaceBackendId(relation->rd_rel->relnamespace);
1131  Assert(relation->rd_backend != InvalidBackendId);
1132  relation->rd_islocaltemp = false;
1133  }
1134  break;
1135  default:
1136  elog(ERROR, "invalid relpersistence: %c",
1137  relation->rd_rel->relpersistence);
1138  break;
1139  }
1140 
1141  /*
1142  * initialize the tuple descriptor (relation->rd_att).
1143  */
1144  RelationBuildTupleDesc(relation);
1145 
1146  /*
1147  * Fetch rules and triggers that affect this relation
1148  */
1149  if (relation->rd_rel->relhasrules)
1150  RelationBuildRuleLock(relation);
1151  else
1152  {
1153  relation->rd_rules = NULL;
1154  relation->rd_rulescxt = NULL;
1155  }
1156 
1157  if (relation->rd_rel->relhastriggers)
1158  RelationBuildTriggers(relation);
1159  else
1160  relation->trigdesc = NULL;
1161 
1162  if (relation->rd_rel->relrowsecurity)
1163  RelationBuildRowSecurity(relation);
1164  else
1165  relation->rd_rsdesc = NULL;
1166 
1167  /* foreign key data is not loaded till asked for */
1168  relation->rd_fkeylist = NIL;
1169  relation->rd_fkeyvalid = false;
1170 
1171  /* partitioning data is not loaded till asked for */
1172  relation->rd_partkey = NULL;
1173  relation->rd_partkeycxt = NULL;
1174  relation->rd_partdesc = NULL;
1175  relation->rd_pdcxt = NULL;
1176  relation->rd_partcheck = NIL;
1177  relation->rd_partcheckvalid = false;
1178  relation->rd_partcheckcxt = NULL;
1179 
1180  /*
1181  * initialize access method information
1182  */
1183  switch (relation->rd_rel->relkind)
1184  {
1185  case RELKIND_INDEX:
1186  case RELKIND_PARTITIONED_INDEX:
1187  Assert(relation->rd_rel->relam != InvalidOid);
1188  RelationInitIndexAccessInfo(relation);
1189  break;
1190  case RELKIND_RELATION:
1191  case RELKIND_TOASTVALUE:
1192  case RELKIND_MATVIEW:
1193  Assert(relation->rd_rel->relam != InvalidOid);
1195  break;
1196  case RELKIND_SEQUENCE:
1197  Assert(relation->rd_rel->relam == InvalidOid);
1199  break;
1200  case RELKIND_VIEW:
1201  case RELKIND_COMPOSITE_TYPE:
1202  case RELKIND_FOREIGN_TABLE:
1203  case RELKIND_PARTITIONED_TABLE:
1204  Assert(relation->rd_rel->relam == InvalidOid);
1205  break;
1206  }
1207 
1208  /* extract reloptions if any */
1209  RelationParseRelOptions(relation, pg_class_tuple);
1210 
1211  /*
1212  * initialize the relation lock manager information
1213  */
1214  RelationInitLockInfo(relation); /* see lmgr.c */
1215 
1216  /*
1217  * initialize physical addressing information for the relation
1218  */
1219  RelationInitPhysicalAddr(relation);
1220 
1221  /* make sure relation is marked as having no open file yet */
1222  relation->rd_smgr = NULL;
1223 
1224  /*
1225  * now we can free the memory allocated for pg_class_tuple
1226  */
1227  heap_freetuple(pg_class_tuple);
1228 
1229  /*
1230  * Insert newly created relation into relcache hash table, if requested.
1231  *
1232  * There is one scenario in which we might find a hashtable entry already
1233  * present, even though our caller failed to find it: if the relation is a
1234  * system catalog or index that's used during relcache load, we might have
1235  * recursively created the same relcache entry during the preceding steps.
1236  * So allow RelationCacheInsert to delete any already-present relcache
1237  * entry for the same OID. The already-present entry should have refcount
1238  * zero (else somebody forgot to close it); in the event that it doesn't,
1239  * we'll elog a WARNING and leak the already-present entry.
1240  */
1241  if (insertIt)
1242  RelationCacheInsert(relation, true);
1243 
1244  /*
1245  * For RelationNeedsWAL() to answer correctly on parallel workers, restore
1246  * rd_firstRelfilenodeSubid. No subtransactions start or end while in
1247  * parallel mode, so the specific SubTransactionId does not matter.
1248  */
1249  if (IsParallelWorker() && RelFileNodeSkippingWAL(relation->rd_node))
1251 
1252  /* It's fully valid */
1253  relation->rd_isvalid = true;
1254 
1255 #if RECOVER_RELATION_BUILD_MEMORY
1256  /* Return to caller's context, and blow away the temporary context */
1257  MemoryContextSwitchTo(oldcxt);
1258  MemoryContextDelete(tmpcxt);
1259 #endif
1260 
1261  return relation;
1262 }
#define NIL
Definition: pg_list.h:65
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define AllocSetContextCreate
Definition: memutils.h:170
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void RelationBuildRowSecurity(Relation relation)
Definition: policy.c:192
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3181
void RelationInitTableAccessMethod(Relation relation)
Definition: relcache.c:1743
struct SMgrRelationData * rd_smgr
Definition: rel.h:57
bool rd_isnailed
Definition: rel.h:61
bool rd_islocaltemp
Definition: rel.h:60
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
List * rd_fkeylist
Definition: rel.h:120
bool rd_partcheckvalid
Definition: rel.h:133
bool rd_isvalid
Definition: rel.h:62
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:103
int GetTempNamespaceBackendId(Oid namespaceId)
Definition: namespace.c:3274
MemoryContext rd_rulescxt
Definition: rel.h:114
Form_pg_class rd_rel
Definition: rel.h:109
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
static Relation AllocateRelationDesc(Form_pg_class relp)
Definition: relcache.c:384
#define TopSubTransactionId
Definition: c.h:520
PartitionKey rd_partkey
Definition: rel.h:124
#define ERROR
Definition: elog.h:43
TriggerDesc * trigdesc
Definition: rel.h:115
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1272
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
void RelationInitLockInfo(Relation relation)
Definition: lmgr.c:71
#define BackendIdForTempRelations()
Definition: backendid.h:34
static void RelationParseRelOptions(Relation relation, HeapTuple tuple)
Definition: relcache.c:439
static void RelationBuildTupleDesc(Relation relation)
Definition: relcache.c:496
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
PartitionDesc rd_partdesc
Definition: rel.h:128
struct RowSecurityDesc * rd_rsdesc
Definition: rel.h:117
#define IsParallelWorker()
Definition: parallel.h:61
SubTransactionId rd_createSubid
Definition: rel.h:102
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
#define InvalidBackendId
Definition: backendid.h:23
#define InvalidOid
Definition: postgres_ext.h:36
#define RelationCacheInsert(RELATION, replace_allowed)
Definition: relcache.c:187
RelFileNode rd_node
Definition: rel.h:55
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
MemoryContext rd_pdcxt
Definition: rel.h:129
BackendId rd_backend
Definition: rel.h:59
#define Assert(condition)
Definition: c.h:738
MemoryContext rd_partkeycxt
Definition: rel.h:125
RuleLock * rd_rules
Definition: rel.h:113
#define InvalidSubTransactionId
Definition: c.h:519
bool RelFileNodeSkippingWAL(RelFileNode rnode)
Definition: storage.c:496
void RelationInitIndexAccessInfo(Relation relation)
Definition: relcache.c:1363
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
void RelationBuildTriggers(Relation relation)
Definition: trigger.c:1592
int rd_refcnt
Definition: rel.h:58
static HeapTuple ScanPgRelation(Oid targetRelId, bool indexOK, bool force_non_historic)
Definition: relcache.c:314
#define elog(elevel,...)
Definition: elog.h:214
static void RelationBuildRuleLock(Relation relation)
Definition: relcache.c:733
MemoryContext rd_partcheckcxt
Definition: rel.h:134
bool rd_fkeyvalid
Definition: rel.h:121
#define RelationGetRelid(relation)
Definition: rel.h:456
List * rd_partcheck
Definition: rel.h:132
SubTransactionId rd_droppedSubid
Definition: rel.h:107

◆ RelationBuildLocalRelation()

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

Definition at line 3334 of file relcache.c.

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

Referenced by heap_create().

3345 {
3346  Relation rel;
3347  MemoryContext oldcxt;
3348  int natts = tupDesc->natts;
3349  int i;
3350  bool has_not_null;
3351  bool nailit;
3352 
3353  AssertArg(natts >= 0);
3354 
3355  /*
3356  * check for creation of a rel that must be nailed in cache.
3357  *
3358  * XXX this list had better match the relations specially handled in
3359  * RelationCacheInitializePhase2/3.
3360  */
3361  switch (relid)
3362  {
3363  case DatabaseRelationId:
3364  case AuthIdRelationId:
3365  case AuthMemRelationId:
3366  case RelationRelationId:
3367  case AttributeRelationId:
3368  case ProcedureRelationId:
3369  case TypeRelationId:
3370  nailit = true;
3371  break;
3372  default:
3373  nailit = false;
3374  break;
3375  }
3376 
3377  /*
3378  * check that hardwired list of shared rels matches what's in the
3379  * bootstrap .bki file. If you get a failure here during initdb, you
3380  * probably need to fix IsSharedRelation() to match whatever you've done
3381  * to the set of shared relations.
3382  */
3383  if (shared_relation != IsSharedRelation(relid))
3384  elog(ERROR, "shared_relation flag for \"%s\" does not match IsSharedRelation(%u)",
3385  relname, relid);
3386 
3387  /* Shared relations had better be mapped, too */
3388  Assert(mapped_relation || !shared_relation);
3389 
3390  /*
3391  * switch to the cache context to create the relcache entry.
3392  */
3393  if (!CacheMemoryContext)
3395 
3397 
3398  /*
3399  * allocate a new relation descriptor and fill in basic state fields.
3400  */
3401  rel = (Relation) palloc0(sizeof(RelationData));
3402 
3403  /* make sure relation is marked as having no open file yet */
3404  rel->rd_smgr = NULL;
3405 
3406  /* mark it nailed if appropriate */
3407  rel->rd_isnailed = nailit;
3408 
3409  rel->rd_refcnt = nailit ? 1 : 0;
3410 
3411  /* it's being created in this transaction */
3416 
3417  /*
3418  * create a new tuple descriptor from the one passed in. We do this
3419  * partly to copy it into the cache context, and partly because the new
3420  * relation can't have any defaults or constraints yet; they have to be
3421  * added in later steps, because they require additions to multiple system
3422  * catalogs. We can copy attnotnull constraints here, however.
3423  */
3424  rel->rd_att = CreateTupleDescCopy(tupDesc);
3425  rel->rd_att->tdrefcount = 1; /* mark as refcounted */
3426  has_not_null = false;
3427  for (i = 0; i < natts; i++)
3428  {
3429  Form_pg_attribute satt = TupleDescAttr(tupDesc, i);
3430  Form_pg_attribute datt = TupleDescAttr(rel->rd_att, i);
3431 
3432  datt->attidentity = satt->attidentity;
3433  datt->attgenerated = satt->attgenerated;
3434  datt->attnotnull = satt->attnotnull;
3435  has_not_null |= satt->attnotnull;
3436  }
3437 
3438  if (has_not_null)
3439  {
3440  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
3441 
3442  constr->has_not_null = true;
3443  rel->rd_att->constr = constr;
3444  }
3445 
3446  /*
3447  * initialize relation tuple form (caller may add/override data later)
3448  */
3450 
3451  namestrcpy(&rel->rd_rel->relname, relname);
3452  rel->rd_rel->relnamespace = relnamespace;
3453 
3454  rel->rd_rel->relkind = relkind;
3455  rel->rd_rel->relnatts = natts;
3456  rel->rd_rel->reltype = InvalidOid;
3457  /* needed when bootstrapping: */
3458  rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;
3459 
3460  /* set up persistence and relcache fields dependent on it */
3461  rel->rd_rel->relpersistence = relpersistence;
3462  switch (relpersistence)
3463  {
3464  case RELPERSISTENCE_UNLOGGED:
3465  case RELPERSISTENCE_PERMANENT:
3467  rel->rd_islocaltemp = false;
3468  break;
3469  case RELPERSISTENCE_TEMP:
3470  Assert(isTempOrTempToastNamespace(relnamespace));
3472  rel->rd_islocaltemp = true;
3473  break;
3474  default:
3475  elog(ERROR, "invalid relpersistence: %c", relpersistence);
3476  break;
3477  }
3478 
3479  /* if it's a materialized view, it's not populated initially */
3480  if (relkind == RELKIND_MATVIEW)
3481  rel->rd_rel->relispopulated = false;
3482  else
3483  rel->rd_rel->relispopulated = true;
3484 
3485  /* set replica identity -- system catalogs and non-tables don't have one */
3486  if (!IsCatalogNamespace(relnamespace) &&
3487  (relkind == RELKIND_RELATION ||
3488  relkind == RELKIND_MATVIEW ||
3489  relkind == RELKIND_PARTITIONED_TABLE))
3490  rel->rd_rel->relreplident = REPLICA_IDENTITY_DEFAULT;
3491  else
3492  rel->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
3493 
3494  /*
3495  * Insert relation physical and logical identifiers (OIDs) into the right
3496  * places. For a mapped relation, we set relfilenode to zero and rely on
3497  * RelationInitPhysicalAddr to consult the map.
3498  */
3499  rel->rd_rel->relisshared = shared_relation;
3500 
3501  RelationGetRelid(rel) = relid;
3502 
3503  for (i = 0; i < natts; i++)
3504  TupleDescAttr(rel->rd_att, i)->attrelid = relid;
3505 
3506  rel->rd_rel->reltablespace = reltablespace;
3507 
3508  if (mapped_relation)
3509  {
3510  rel->rd_rel->relfilenode = InvalidOid;
3511  /* Add it to the active mapping information */
3512  RelationMapUpdateMap(relid, relfilenode, shared_relation, true);
3513  }
3514  else
3515  rel->rd_rel->relfilenode = relfilenode;
3516 
3517  RelationInitLockInfo(rel); /* see lmgr.c */
3518 
3520 
3521  rel->rd_rel->relam = accessmtd;
3522 
3523  if (relkind == RELKIND_RELATION ||
3524  relkind == RELKIND_SEQUENCE ||
3525  relkind == RELKIND_TOASTVALUE ||
3526  relkind == RELKIND_MATVIEW)
3528 
3529  /*
3530  * Okay to insert into the relcache hash table.
3531  *
3532  * Ordinarily, there should certainly not be an existing hash entry for
3533  * the same OID; but during bootstrap, when we create a "real" relcache
3534  * entry for one of the bootstrap relations, we'll be overwriting the
3535  * phony one created with formrdesc. So allow that to happen for nailed
3536  * rels.
3537  */
3538  RelationCacheInsert(rel, nailit);
3539 
3540  /*
3541  * Flag relation as needing eoxact cleanup (to clear rd_createSubid). We
3542  * can't do this before storing relid in it.
3543  */
3544  EOXactListAdd(rel);
3545 
3546  /*
3547  * done building relcache entry.
3548  */
3549  MemoryContextSwitchTo(oldcxt);
3550 
3551  /* It's fully valid */
3552  rel->rd_isvalid = true;
3553 
3554  /*
3555  * Caller expects us to pin the returned entry.
3556  */
3558 
3559  return rel;
3560 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
#define EOXactListAdd(rel)
Definition: relcache.c:167
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3181
void RelationInitTableAccessMethod(Relation relation)
Definition: relcache.c:1743
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
struct SMgrRelationData * rd_smgr
Definition: rel.h:57
bool rd_isnailed
Definition: rel.h:61
bool rd_islocaltemp
Definition: rel.h:60
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool rd_isvalid
Definition: rel.h:62
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:103
Form_pg_class rd_rel
Definition: rel.h:109
NameData relname
Definition: pg_class.h:38
int namestrcpy(Name name, const char *str)
Definition: name.c:250
struct RelationData * Relation
Definition: relcache.h:27
#define ERROR
Definition: elog.h:43
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1272
void RelationInitLockInfo(Relation relation)
Definition: lmgr.c:71
#define BackendIdForTempRelations()
Definition: backendid.h:34
TupleConstr * constr
Definition: tupdesc.h:85
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
#define AssertArg(condition)
Definition: c.h:740
SubTransactionId rd_createSubid
Definition: rel.h:102
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
#define InvalidBackendId
Definition: backendid.h:23
void * palloc0(Size size)
Definition: mcxt.c:980
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2068
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:238
TupleDesc rd_att
Definition: rel.h:110
#define InvalidOid
Definition: postgres_ext.h:36
#define RelationCacheInsert(RELATION, replace_allowed)
Definition: relcache.c:187
#define CLASS_TUPLE_SIZE
Definition: pg_class.h:145
BackendId rd_backend
Definition: rel.h:59
#define Assert(condition)
Definition: c.h:738
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:707
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
#define InvalidSubTransactionId
Definition: c.h:519
bool IsCatalogNamespace(Oid namespaceId)
Definition: catalog.c:177
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
int rd_refcnt
Definition: rel.h:58
#define elog(elevel,...)
Definition: elog.h:214
int i
int tdrefcount
Definition: tupdesc.h:84
bool has_not_null
Definition: tupdesc.h:44
#define RelationGetRelid(relation)
Definition: rel.h:456
SubTransactionId rd_droppedSubid
Definition: rel.h:107
void RelationMapUpdateMap(Oid relationId, Oid fileNode, bool shared, bool immediate)
Definition: relmapper.c:261
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationBuildRuleLock()

static void RelationBuildRuleLock ( Relation  relation)
static

Definition at line 733 of file relcache.c.

References AccessShareLock, RewriteRule::actions, ALLOCSET_SMALL_SIZES, AllocSetContextCreate, Assert, BTEqualStrategyNumber, CacheMemoryContext, RewriteRule::enabled, RewriteRule::event, GETSTRUCT, heap_getattr, HeapTupleIsValid, RewriteRule::isInstead, sort-test::key, MemoryContextAlloc(), MemoryContextCopyAndSetIdentifier, MemoryContextDelete(), MemoryContextSwitchTo(), RuleLock::numLocks, ObjectIdGetDatum, pfree(), RewriteRule::qual, RelationData::rd_rel, RelationData::rd_rules, RelationData::rd_rulescxt, RelationGetDescr, RelationGetRelationName, RelationGetRelid, repalloc(), RewriteRelRulenameIndexId, RewriteRule::ruleId, RuleLock::rules, rules, ScanKeyInit(), setRuleCheckAsUser(), stringToNode(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), and TextDatumGetCString.

Referenced by RelationBuildDesc(), and RelationCacheInitializePhase3().

734 {
735  MemoryContext rulescxt;
736  MemoryContext oldcxt;
737  HeapTuple rewrite_tuple;
738  Relation rewrite_desc;
739  TupleDesc rewrite_tupdesc;
740  SysScanDesc rewrite_scan;
742  RuleLock *rulelock;
743  int numlocks;
744  RewriteRule **rules;
745  int maxlocks;
746 
747  /*
748  * Make the private context. Assume it'll not contain much data.
749  */
751  "relation rules",
753  relation->rd_rulescxt = rulescxt;
755  RelationGetRelationName(relation));
756 
757  /*
758  * allocate an array to hold the rewrite rules (the array is extended if
759  * necessary)
760  */
761  maxlocks = 4;
762  rules = (RewriteRule **)
763  MemoryContextAlloc(rulescxt, sizeof(RewriteRule *) * maxlocks);
764  numlocks = 0;
765 
766  /*
767  * form a scan key
768  */
769  ScanKeyInit(&key,
770  Anum_pg_rewrite_ev_class,
771  BTEqualStrategyNumber, F_OIDEQ,
773 
774  /*
775  * open pg_rewrite and begin a scan
776  *
777  * Note: since we scan the rules using RewriteRelRulenameIndexId, we will
778  * be reading the rules in name order, except possibly during
779  * emergency-recovery operations (ie, IgnoreSystemIndexes). This in turn
780  * ensures that rules will be fired in name order.
781  */
782  rewrite_desc = table_open(RewriteRelationId, AccessShareLock);
783  rewrite_tupdesc = RelationGetDescr(rewrite_desc);
784  rewrite_scan = systable_beginscan(rewrite_desc,
786  true, NULL,
787  1, &key);
788 
789  while (HeapTupleIsValid(rewrite_tuple = systable_getnext(rewrite_scan)))
790  {
791  Form_pg_rewrite rewrite_form = (Form_pg_rewrite) GETSTRUCT(rewrite_tuple);
792  bool isnull;
793  Datum rule_datum;
794  char *rule_str;
795  RewriteRule *rule;
796 
797  rule = (RewriteRule *) MemoryContextAlloc(rulescxt,
798  sizeof(RewriteRule));
799 
800  rule->ruleId = rewrite_form->oid;
801 
802  rule->event = rewrite_form->ev_type - '0';
803  rule->enabled = rewrite_form->ev_enabled;
804  rule->isInstead = rewrite_form->is_instead;
805 
806  /*
807  * Must use heap_getattr to fetch ev_action and ev_qual. Also, the
808  * rule strings are often large enough to be toasted. To avoid
809  * leaking memory in the caller's context, do the detoasting here so
810  * we can free the detoasted version.
811  */
812  rule_datum = heap_getattr(rewrite_tuple,
813  Anum_pg_rewrite_ev_action,
814  rewrite_tupdesc,
815  &isnull);
816  Assert(!isnull);
817  rule_str = TextDatumGetCString(rule_datum);
818  oldcxt = MemoryContextSwitchTo(rulescxt);
819  rule->actions = (List *) stringToNode(rule_str);
820  MemoryContextSwitchTo(oldcxt);
821  pfree(rule_str);
822 
823  rule_datum = heap_getattr(rewrite_tuple,
824  Anum_pg_rewrite_ev_qual,
825  rewrite_tupdesc,
826  &isnull);
827  Assert(!isnull);
828  rule_str = TextDatumGetCString(rule_datum);
829  oldcxt = MemoryContextSwitchTo(rulescxt);
830  rule->qual = (Node *) stringToNode(rule_str);
831  MemoryContextSwitchTo(oldcxt);
832  pfree(rule_str);
833 
834  /*
835  * We want the rule's table references to be checked as though by the
836  * table owner, not the user referencing the rule. Therefore, scan
837  * through the rule's actions and set the checkAsUser field on all
838  * rtable entries. We have to look at the qual as well, in case it
839  * contains sublinks.
840  *
841  * The reason for doing this when the rule is loaded, rather than when
842  * it is stored, is that otherwise ALTER TABLE OWNER would have to
843  * grovel through stored rules to update checkAsUser fields. Scanning
844  * the rule tree during load is relatively cheap (compared to
845  * constructing it in the first place), so we do it here.
846  */
847  setRuleCheckAsUser((Node *) rule->actions, relation->rd_rel->relowner);
848  setRuleCheckAsUser(rule->qual, relation->rd_rel->relowner);
849 
850  if (numlocks >= maxlocks)
851  {
852  maxlocks *= 2;
853  rules = (RewriteRule **)
854  repalloc(rules, sizeof(RewriteRule *) * maxlocks);
855  }
856  rules[numlocks++] = rule;
857  }
858 
859  /*
860  * end the scan and close the attribute relation
861  */
862  systable_endscan(rewrite_scan);
863  table_close(rewrite_desc, AccessShareLock);
864 
865  /*
866  * there might not be any rules (if relhasrules is out-of-date)
867  */
868  if (numlocks == 0)
869  {
870  relation->rd_rules = NULL;
871  relation->rd_rulescxt = NULL;
872  MemoryContextDelete(rulescxt);
873  return;
874  }
875 
876  /*
877  * form a RuleLock and insert into relation
878  */
879  rulelock = (RuleLock *) MemoryContextAlloc(rulescxt, sizeof(RuleLock));
880  rulelock->numLocks = numlocks;
881  rulelock->rules = rules;
882 
883  relation->rd_rules = rulelock;
884 }
Node * qual
Definition: prs2lock.h:28
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define AllocSetContextCreate
Definition: memutils.h:170
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
int numLocks
Definition: prs2lock.h:42
void setRuleCheckAsUser(Node *node, Oid userid)
#define RelationGetDescr(relation)
Definition: rel.h:482
#define RewriteRelRulenameIndexId
Definition: indexing.h:217
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:202
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:526
void * stringToNode(const char *str)
Definition: read.c:89
MemoryContext rd_rulescxt
Definition: rel.h:114
Form_pg_class rd_rel
Definition: rel.h:109
bool isInstead
Definition: prs2lock.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
Definition: localtime.c:79
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define MemoryContextCopyAndSetIdentifier(cxt, id)
Definition: memutils.h:97
CmdType event
Definition: prs2lock.h:27
static struct rule * rules
Definition: zic.c:278
#define RelationGetRelationName(relation)
Definition: rel.h:490
RewriteRule ** rules
Definition: prs2lock.h:43
List * actions
Definition: prs2lock.h:29
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:88
uintptr_t Datum
Definition: postgres.h:367
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:738
RuleLock * rd_rules
Definition: rel.h:113
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
FormData_pg_rewrite * Form_pg_rewrite
Definition: pg_rewrite.h:52
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:456
Oid ruleId
Definition: prs2lock.h:26
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:47
char enabled
Definition: prs2lock.h:30

◆ RelationBuildTupleDesc()

static void RelationBuildTupleDesc ( Relation  relation)
static

Definition at line 496 of file relcache.c.

References AccessShareLock, AttrDefault::adbin, AttrDefault::adnum, AttrMissing::am_present, AttrMissing::am_value, array_get_element(), Assert, attnum, AttrDefaultFetch(), ATTRIBUTE_FIXED_PART_SIZE, AttributeRelidNumIndexId, BTEqualStrategyNumber, BTGreaterStrategyNumber, CacheMemoryContext, TupleConstr::check, CheckConstraintFetch(), TupleDescData::constr, criticalRelcachesBuilt, datumCopy(), TupleConstr::defval, elog, ERROR, GETSTRUCT, TupleConstr::has_generated_stored, TupleConstr::has_not_null, heap_getattr, HeapTupleIsValid, i, Int16GetDatum, MemoryContextAlloc(), MemoryContextAllocZero(), MemoryContextSwitchTo(), TupleConstr::missing, TupleConstr::num_check, TupleConstr::num_defval, ObjectIdGetDatum, pfree(), RelationData::rd_att, RelationData::rd_rel, RelationGetNumberOfAttributes, RelationGetRelationName, RelationGetRelid, repalloc(), ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TupleDescData::tdtypeid, TupleDescData::tdtypmod, and TupleDescAttr.

Referenced by RelationBuildDesc().

497 {
498  HeapTuple pg_attribute_tuple;
499  Relation pg_attribute_desc;
500  SysScanDesc pg_attribute_scan;
501  ScanKeyData skey[2];
502  int need;
503  TupleConstr *constr;
504  AttrDefault *attrdef = NULL;
505  AttrMissing *attrmiss = NULL;
506  int ndef = 0;
507 
508  /* copy some fields from pg_class row to rd_att */
509  relation->rd_att->tdtypeid = relation->rd_rel->reltype;
510  relation->rd_att->tdtypmod = -1; /* unnecessary, but... */
511 
513  sizeof(TupleConstr));
514  constr->has_not_null = false;
515  constr->has_generated_stored = false;
516 
517  /*
518  * Form a scan key that selects only user attributes (attnum > 0).
519  * (Eliminating system attribute rows at the index level is lots faster
520  * than fetching them.)
521  */
522  ScanKeyInit(&skey[0],
523  Anum_pg_attribute_attrelid,
524  BTEqualStrategyNumber, F_OIDEQ,
526  ScanKeyInit(&skey[1],
527  Anum_pg_attribute_attnum,
528  BTGreaterStrategyNumber, F_INT2GT,
529  Int16GetDatum(0));
530 
531  /*
532  * Open pg_attribute and begin a scan. Force heap scan if we haven't yet
533  * built the critical relcache entries (this includes initdb and startup
534  * without a pg_internal.init file).
535  */
536  pg_attribute_desc = table_open(AttributeRelationId, AccessShareLock);
537  pg_attribute_scan = systable_beginscan(pg_attribute_desc,
540  NULL,
541  2, skey);
542 
543  /*
544  * add attribute data to relation->rd_att
545  */
546  need = RelationGetNumberOfAttributes(relation);
547 
548  while (HeapTupleIsValid(pg_attribute_tuple = systable_getnext(pg_attribute_scan)))
549  {
550  Form_pg_attribute attp;
551  int attnum;
552 
553  attp = (Form_pg_attribute) GETSTRUCT(pg_attribute_tuple);
554 
555  attnum = attp->attnum;
556  if (attnum <= 0 || attnum > RelationGetNumberOfAttributes(relation))
557  elog(ERROR, "invalid attribute number %d for %s",
558  attp->attnum, RelationGetRelationName(relation));
559 
560 
561  memcpy(TupleDescAttr(relation->rd_att, attnum - 1),
562  attp,
564 
565  /* Update constraint/default info */
566  if (attp->attnotnull)
567  constr->has_not_null = true;
568  if (attp->attgenerated == ATTRIBUTE_GENERATED_STORED)
569  constr->has_generated_stored = true;
570 
571  /* If the column has a default, fill it into the attrdef array */
572  if (attp->atthasdef)
573  {
574  if (attrdef == NULL)
575  attrdef = (AttrDefault *)
578  sizeof(AttrDefault));
579  attrdef[ndef].adnum = attnum;
580  attrdef[ndef].adbin = NULL;
581 
582  ndef++;
583  }
584 
585  /* Likewise for a missing value */
586  if (attp->atthasmissing)
587  {
588  Datum missingval;
589  bool missingNull;
590 
591  /* Do we have a missing value? */
592  missingval = heap_getattr(pg_attribute_tuple,
593  Anum_pg_attribute_attmissingval,
594  pg_attribute_desc->rd_att,
595  &missingNull);
596  if (!missingNull)
597  {
598  /* Yes, fetch from the array */
599  MemoryContext oldcxt;
600  bool is_null;
601  int one = 1;
602  Datum missval;
603 
604  if (attrmiss == NULL)
605  attrmiss = (AttrMissing *)
607  relation->rd_rel->relnatts *
608  sizeof(AttrMissing));
609 
610  missval = array_get_element(missingval,
611  1,
612  &one,
613  -1,
614  attp->attlen,
615  attp->attbyval,
616  attp->attalign,
617  &is_null);
618  Assert(!is_null);
619  if (attp->attbyval)
620  {
621  /* for copy by val just copy the datum direct */
622  attrmiss[attnum - 1].am_value = missval;
623  }
624  else
625  {
626  /* otherwise copy in the correct context */
628  attrmiss[attnum - 1].am_value = datumCopy(missval,
629  attp->attbyval,
630  attp->attlen);
631  MemoryContextSwitchTo(oldcxt);
632  }
633  attrmiss[attnum - 1].am_present = true;
634  }
635  }
636  need--;
637  if (need == 0)
638  break;
639  }
640 
641  /*
642  * end the scan and close the attribute relation
643  */
644  systable_endscan(pg_attribute_scan);
645  table_close(pg_attribute_desc, AccessShareLock);
646 
647  if (need != 0)
648  elog(ERROR, "catalog is missing %d attribute(s) for relid %u",
649  need, RelationGetRelid(relation));
650 
651  /*
652  * The attcacheoff values we read from pg_attribute should all be -1
653  * ("unknown"). Verify this if assert checking is on. They will be
654  * computed when and if needed during tuple access.
655  */
656 #ifdef USE_ASSERT_CHECKING
657  {
658  int i;
659 
660  for (i = 0; i < RelationGetNumberOfAttributes(relation); i++)
661  Assert(TupleDescAttr(relation->rd_att, i)->attcacheoff == -1);
662  }
663 #endif
664 
665  /*
666  * However, we can easily set the attcacheoff value for the first
667  * attribute: it must be zero. This eliminates the need for special cases
668  * for attnum=1 that used to exist in fastgetattr() and index_getattr().
669  */
670  if (RelationGetNumberOfAttributes(relation) > 0)
671  TupleDescAttr(relation->rd_att, 0)->attcacheoff = 0;
672 
673  /*
674  * Set up constraint/default info
675  */
676  if (constr->has_not_null ||
677  constr->has_generated_stored ||
678  ndef > 0 ||
679  attrmiss ||
680  relation->rd_rel->relchecks)
681  {
682  relation->rd_att->constr = constr;
683 
684  if (ndef > 0) /* DEFAULTs */
685  {
686  if (ndef < RelationGetNumberOfAttributes(relation))
687  constr->defval = (AttrDefault *)
688  repalloc(attrdef, ndef * sizeof(AttrDefault));
689  else
690  constr->defval = attrdef;
691  constr->num_defval = ndef;
692  AttrDefaultFetch(relation);
693  }
694  else
695  constr->num_defval = 0;
696 
697  constr->missing = attrmiss;
698 
699  if (relation->rd_rel->relchecks > 0) /* CHECKs */
700  {
701  constr->num_check = relation->rd_rel->relchecks;
702  constr->check = (ConstrCheck *)
704  constr->num_check * sizeof(ConstrCheck));
705  CheckConstraintFetch(relation);
706  }
707  else
708  constr->num_check = 0;
709  }
710  else
711  {
712  pfree(constr);
713  relation->rd_att->constr = NULL;
714  }
715 }
#define AttributeRelidNumIndexId
Definition: indexing.h:96
static void AttrDefaultFetch(Relation relation)
Definition: relcache.c:4232
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:529
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:462
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define Int16GetDatum(X)
Definition: postgres.h:451
#define AccessShareLock
Definition: lockdefs.h:36
Form_pg_class rd_rel
Definition: rel.h:109
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:356
AttrDefault * defval
Definition: tupdesc.h:39
struct AttrDefault AttrDefault
bool has_generated_stored
Definition: tupdesc.h:45
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:448
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
int32 tdtypmod
Definition: tupdesc.h:83
TupleConstr * constr
Definition: tupdesc.h:85
#define RelationGetRelationName(relation)
Definition: rel.h:490
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:185
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:131
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:110
uint16 num_check
Definition: tupdesc.h:43
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:839
int16 attnum
Definition: pg_attribute.h:79
Datum array_get_element(Datum arraydatum, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
Definition: arrayfuncs.c:1819
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:738
static void CheckConstraintFetch(Relation relation)
Definition: relcache.c:4302
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
struct AttrMissing * missing
Definition: tupdesc.h:41
uint16 num_defval
Definition: tupdesc.h:42
Oid tdtypeid
Definition: tupdesc.h:82
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
#define elog(elevel,...)
Definition: elog.h:214
int i
AttrNumber adnum
Definition: tupdesc.h:24
char * adbin
Definition: tupdesc.h:25
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
ConstrCheck * check
Definition: tupdesc.h:40
bool criticalRelcachesBuilt
Definition: relcache.c:136
bool has_not_null
Definition: tupdesc.h:44
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define RelationGetRelid(relation)
Definition: rel.h:456
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInitFilePostInvalidate()

void RelationCacheInitFilePostInvalidate ( void  )

Definition at line 6299 of file relcache.c.

References LWLockRelease().

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

6300 {
6301  LWLockRelease(RelCacheInitLock);
6302 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1727

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )

Definition at line 6274 of file relcache.c.

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

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

6275 {
6276  char localinitfname[MAXPGPATH];
6277  char sharedinitfname[MAXPGPATH];
6278 
6279  if (DatabasePath)
6280  snprintf(localinitfname, sizeof(localinitfname), "%s/%s",
6282  snprintf(sharedinitfname, sizeof(sharedinitfname), "global/%s",
6284 
6285  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6286 
6287  /*
6288  * The files might not be there if no backend has been started since the
6289  * last removal. But complain about failures other than ENOENT with
6290  * ERROR. Fortunately, it's not too late to abort the transaction if we
6291  * can't get rid of the would-be-obsolete init file.
6292  */
6293  if (DatabasePath)
6294  unlink_initfile(localinitfname, ERROR);
6295  unlink_initfile(sharedinitfname, ERROR);
6296 }
#define ERROR
Definition: elog.h:43
#define MAXPGPATH
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25
char * DatabasePath
Definition: globals.c:93
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1123
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6371
#define snprintf
Definition: port.h:193

◆ RelationCacheInitFileRemove()

void RelationCacheInitFileRemove ( void  )

Definition at line 6314 of file relcache.c.

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

Referenced by StartupXLOG().

6315 {
6316  const char *tblspcdir = "pg_tblspc";
6317  DIR *dir;
6318  struct dirent *de;
6319  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6320 
6321  snprintf(path, sizeof(path), "global/%s",
6323  unlink_initfile(path, LOG);
6324 
6325  /* Scan everything in the default tablespace */
6327 
6328  /* Scan the tablespace link directory to find non-default tablespaces */
6329  dir = AllocateDir(tblspcdir);
6330 
6331  while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6332  {
6333  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6334  {
6335  /* Scan the tablespace dir for per-database dirs */
6336  snprintf(path, sizeof(path), "%s/%s/%s",
6337  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6339  }
6340  }
6341 
6342  FreeDir(dir);
6343 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6347
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2662
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:26
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2581
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6371
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:193
int FreeDir(DIR *dir)
Definition: fd.c:2699

◆ RelationCacheInitFileRemoveInDir()

static void RelationCacheInitFileRemoveInDir ( const char *  tblspcpath)
static

Definition at line 6347 of file relcache.c.

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

Referenced by RelationCacheInitFileRemove().

6348 {
6349  DIR *dir;
6350  struct dirent *de;
6351  char initfilename[MAXPGPATH * 2];
6352 
6353  /* Scan the tablespace directory to find per-database directories */
6354  dir = AllocateDir(tblspcpath);
6355 
6356  while ((de = ReadDirExtended(dir, tblspcpath, LOG)) != NULL)
6357  {
6358  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6359  {
6360  /* Try to remove the init file in each database */
6361  snprintf(initfilename, sizeof(initfilename), "%s/%s/%s",
6362  tblspcpath, de->d_name, RELCACHE_INIT_FILENAME);
6363  unlink_initfile(initfilename, LOG);
6364  }
6365  }
6366 
6367  FreeDir(dir);
6368 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2662
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2581
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6371
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:193
int FreeDir(DIR *dir)
Definition: fd.c:2699

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 3755 of file relcache.c.

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

Referenced by InitPostgres().

3756 {
3757  HASHCTL ctl;
3758 
3759  /*
3760  * make sure cache memory context exists
3761  */
3762  if (!CacheMemoryContext)
3764 
3765  /*
3766  * create hashtable that indexes the relcache
3767  */
3768  MemSet(&ctl, 0, sizeof(ctl));
3769  ctl.keysize = sizeof(Oid);
3770  ctl.entrysize = sizeof(RelIdCacheEnt);
3771  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3772  &ctl, HASH_ELEM | HASH_BLOBS);
3773 
3774  /*
3775  * relation mapper needs to be initialized too
3776  */
3778 }
void RelationMapInitialize(void)
Definition: relmapper.c:584
#define HASH_ELEM
Definition: hsearch.h:87
struct relidcacheent RelIdCacheEnt
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:971
static HTAB * RelationIdCache
Definition: relcache.c:130
unsigned int Oid
Definition: postgres_ext.h:31
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:317
Size keysize
Definition: hsearch.h:72
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
#define INITRELCACHESIZE
Definition: relcache.c:3752
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInitializePhase2()

void RelationCacheInitializePhase2 ( void  )

Definition at line 3792 of file relcache.c.

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

Referenced by InitPostgres().

3793 {
3794  MemoryContext oldcxt;
3795 
3796  /*
3797  * relation mapper needs initialized too
3798  */
3800 
3801  /*
3802  * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3803  * nothing.
3804  */
3806  return;
3807 
3808  /*
3809  * switch to cache memory context
3810  */
3812 
3813  /*
3814  * Try to load the shared relcache cache file. If unsuccessful, bootstrap
3815  * the cache with pre-made descriptors for the critical shared catalogs.
3816  */
3817  if (!load_relcache_init_file(true))
3818  {
3819  formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
3820  Natts_pg_database, Desc_pg_database);
3821  formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
3822  Natts_pg_authid, Desc_pg_authid);
3823  formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
3824  Natts_pg_auth_members, Desc_pg_auth_members);
3825  formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
3826  Natts_pg_shseclabel, Desc_pg_shseclabel);
3827  formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
3828  Natts_pg_subscription, Desc_pg_subscription);
3829 
3830 #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
3831  }
3832 
3833  MemoryContextSwitchTo(oldcxt);
3834 }
static const FormData_pg_attribute Desc_pg_auth_members[Natts_pg_auth_members]
Definition: relcache.c:113
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5591
void RelationMapInitializePhase2(void)
Definition: relmapper.c:604
static const FormData_pg_attribute Desc_pg_authid[Natts_pg_authid]
Definition: relcache.c:112
static const FormData_pg_attribute Desc_pg_subscription[Natts_pg_subscription]
Definition: relcache.c:116
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static const FormData_pg_attribute Desc_pg_database[Natts_pg_database]
Definition: relcache.c:111
static const FormData_pg_attribute Desc_pg_shseclabel[Natts_pg_shseclabel]
Definition: relcache.c:115
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:392
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1807
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInitializePhase3()

void RelationCacheInitializePhase3 ( void  )

Definition at line 3851 of file relcache.c.

References AccessMethodProcedureIndexId, Assert, AttributeRelidNumIndexId, AuthIdOidIndexId, AuthIdRolnameIndexId, AuthMemMemRoleIndexId, CacheMemoryContext, CLASS_TUPLE_SIZE, ClassOidIndexId, criticalRelcachesBuilt, criticalSharedRelcachesBuilt, DatabaseNameIndexId, DatabaseOidIndexId, Desc_pg_attribute, Desc_pg_class, Desc_pg_proc, Desc_pg_type, elog, ERROR, FATAL, formrdesc(), GETSTRUCT, hash_seq_init(), hash_seq_search(), hash_seq_term(), HeapTupleIsValid, IndexRelidIndexId, InitCatalogCachePhase2(), InvalidOid, IsBootstrapProcessingMode, load_critical_index(), load_relcache_init_file(), MemoryContextSwitchTo(), ObjectIdGetDatum, OpclassOidIndexId, pfree(), RelationData::rd_att, RelationData::rd_options, RelationData::rd_rel, RelationData::rd_rsdesc, RelationData::rd_rules, RelationData::rd_tableam, RelationBuildRowSecurity(), RelationBuildRuleLock(), RelationBuildTriggers(), RelationDecrementReferenceCount(), RelationGetRelationName, RelationGetRelid, RelationIncrementReferenceCount(), RelationInitTableAccessMethod(), RelationMapInitializePhase3(), RelationParseRelOptions(), relidcacheent::reldesc, ReleaseSysCache(), RELOID, RewriteRelRulenameIndexId, SearchSysCache1(), SharedSecLabelObjectIndexId, status(), TupleDescData::tdtypeid, TupleDescData::tdtypmod, RelationData::trigdesc, TriggerRelidNameIndexId, and write_relcache_init_file().

Referenced by InitPostgres().

3852 {
3854  RelIdCacheEnt *idhentry;
3855  MemoryContext oldcxt;
3856  bool needNewCacheFile = !criticalSharedRelcachesBuilt;
3857 
3858  /*
3859  * relation mapper needs initialized too
3860  */
3862 
3863  /*
3864  * switch to cache memory context
3865  */
3867 
3868  /*
3869  * Try to load the local relcache cache file. If unsuccessful, bootstrap
3870  * the cache with pre-made descriptors for the critical "nailed-in" system
3871  * catalogs.
3872  */
3873  if (IsBootstrapProcessingMode() ||
3874  !load_relcache_init_file(false))
3875  {
3876  needNewCacheFile = true;
3877 
3878  formrdesc("pg_class", RelationRelation_Rowtype_Id, false,
3879  Natts_pg_class, Desc_pg_class);
3880  formrdesc("pg_attribute", AttributeRelation_Rowtype_Id, false,
3881  Natts_pg_attribute, Desc_pg_attribute);
3882  formrdesc("pg_proc", ProcedureRelation_Rowtype_Id, false,
3883  Natts_pg_proc, Desc_pg_proc);
3884  formrdesc("pg_type", TypeRelation_Rowtype_Id, false,
3885  Natts_pg_type, Desc_pg_type);
3886 
3887 #define NUM_CRITICAL_LOCAL_RELS 4 /* fix if you change list above */
3888  }
3889 
3890  MemoryContextSwitchTo(oldcxt);
3891 
3892  /* In bootstrap mode, the faked-up formrdesc info is all we'll have */
3894  return;
3895 
3896  /*
3897  * If we didn't get the critical system indexes loaded into relcache, do
3898  * so now. These are critical because the catcache and/or opclass cache
3899  * depend on them for fetches done during relcache load. Thus, we have an
3900  * infinite-recursion problem. We can break the recursion by doing
3901  * heapscans instead of indexscans at certain key spots. To avoid hobbling
3902  * performance, we only want to do that until we have the critical indexes
3903  * loaded into relcache. Thus, the flag criticalRelcachesBuilt is used to
3904  * decide whether to do heapscan or indexscan at the key spots, and we set
3905  * it true after we've loaded the critical indexes.
3906  *
3907  * The critical indexes are marked as "nailed in cache", partly to make it
3908  * easy for load_relcache_init_file to count them, but mainly because we
3909  * cannot flush and rebuild them once we've set criticalRelcachesBuilt to
3910  * true. (NOTE: perhaps it would be possible to reload them by
3911  * temporarily setting criticalRelcachesBuilt to false again. For now,
3912  * though, we just nail 'em in.)
3913  *
3914  * RewriteRelRulenameIndexId and TriggerRelidNameIndexId are not critical
3915  * in the same way as the others, because the critical catalogs don't
3916  * (currently) have any rules or triggers, and so these indexes can be
3917  * rebuilt without inducing recursion. However they are used during
3918  * relcache load when a rel does have rules or triggers, so we choose to
3919  * nail them for performance reasons.
3920  */
3922  {
3924  RelationRelationId);
3926  AttributeRelationId);
3928  IndexRelationId);
3930  OperatorClassRelationId);
3932  AccessMethodProcedureRelationId);
3934  RewriteRelationId);
3936  TriggerRelationId);
3937 
3938 #define NUM_CRITICAL_LOCAL_INDEXES 7 /* fix if you change list above */
3939 
3940  criticalRelcachesBuilt = true;
3941  }
3942 
3943  /*
3944  * Process critical shared indexes too.
3945  *
3946  * DatabaseNameIndexId isn't critical for relcache loading, but rather for
3947  * initial lookup of MyDatabaseId, without which we'll never find any
3948  * non-shared catalogs at all. Autovacuum calls InitPostgres with a
3949  * database OID, so it instead depends on DatabaseOidIndexId. We also
3950  * need to nail up some indexes on pg_authid and pg_auth_members for use
3951  * during client authentication. SharedSecLabelObjectIndexId isn't
3952  * critical for the core system, but authentication hooks might be
3953  * interested in it.
3954  */
3956  {
3958  DatabaseRelationId);
3960  DatabaseRelationId);
3962  AuthIdRelationId);
3964  AuthIdRelationId);
3966  AuthMemRelationId);
3968  SharedSecLabelRelationId);
3969 
3970 #define NUM_CRITICAL_SHARED_INDEXES 6 /* fix if you change list above */
3971 
3973  }
3974 
3975  /*
3976  * Now, scan all the relcache entries and update anything that might be
3977  * wrong in the results from formrdesc or the relcache cache file. If we
3978  * faked up relcache entries using formrdesc, then read the real pg_class
3979  * rows and replace the fake entries with them. Also, if any of the
3980  * relcache entries have rules, triggers, or security policies, load that
3981  * info the hard way since it isn't recorded in the cache file.
3982  *
3983  * Whenever we access the catalogs to read data, there is a possibility of
3984  * a shared-inval cache flush causing relcache entries to be removed.
3985  * Since hash_seq_search only guarantees to still work after the *current*
3986  * entry is removed, it's unsafe to continue the hashtable scan afterward.
3987  * We handle this by restarting the scan from scratch after each access.
3988  * This is theoretically O(N^2), but the number of entries that actually
3989  * need to be fixed is small enough that it doesn't matter.
3990  */
3991  hash_seq_init(&status, RelationIdCache);
3992 
3993  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3994  {
3995  Relation relation = idhentry->reldesc;
3996  bool restart = false;
3997 
3998  /*
3999  * Make sure *this* entry doesn't get flushed while we work with it.
4000  */
4002 
4003  /*
4004  * If it's a faked-up entry, read the real pg_class tuple.
4005  */
4006  if (relation->rd_rel->relowner == InvalidOid)
4007  {
4008  HeapTuple htup;
4009  Form_pg_class relp;
4010 
4011  htup = SearchSysCache1(RELOID,
4012  ObjectIdGetDatum(RelationGetRelid(relation)));
4013  if (!HeapTupleIsValid(htup))
4014  elog(FATAL, "cache lookup failed for relation %u",
4015  RelationGetRelid(relation));
4016  relp = (Form_pg_class) GETSTRUCT(htup);
4017 
4018  /*
4019  * Copy tuple to relation->rd_rel. (See notes in
4020  * AllocateRelationDesc())
4021  */
4022  memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
4023 
4024  /* Update rd_options while we have the tuple */
4025  if (relation->rd_options)
4026  pfree(relation->rd_options);
4027  RelationParseRelOptions(relation, htup);
4028 
4029  /*
4030  * Check the values in rd_att were set up correctly. (We cannot
4031  * just copy them over now: formrdesc must have set up the rd_att
4032  * data correctly to start with, because it may already have been
4033  * copied into one or more catcache entries.)
4034  */
4035  Assert(relation->rd_att->tdtypeid == relp->reltype);
4036  Assert(relation->rd_att->tdtypmod == -1);
4037 
4038  ReleaseSysCache(htup);
4039 
4040  /* relowner had better be OK now, else we'll loop forever */
4041  if (relation->rd_rel->relowner == InvalidOid)
4042  elog(ERROR, "invalid relowner in pg_class entry for \"%s\"",
4043  RelationGetRelationName(relation));
4044 
4045  restart = true;
4046  }
4047 
4048  /*
4049  * Fix data that isn't saved in relcache cache file.
4050  *
4051  * relhasrules or relhastriggers could possibly be wrong or out of
4052  * date. If we don't actually find any rules or triggers, clear the
4053  * local copy of the flag so that we don't get into an infinite loop
4054  * here. We don't make any attempt to fix the pg_class entry, though.
4055  */
4056  if (relation->rd_rel->relhasrules && relation->rd_rules == NULL)
4057  {
4058  RelationBuildRuleLock(relation);
4059  if (relation->rd_rules == NULL)
4060  relation->rd_rel->relhasrules = false;
4061  restart = true;
4062  }
4063  if (relation->rd_rel->relhastriggers && relation->trigdesc == NULL)
4064  {
4065  RelationBuildTriggers(relation);
4066  if (relation->trigdesc == NULL)
4067  relation->rd_rel->relhastriggers = false;
4068  restart = true;
4069  }
4070 
4071  /*
4072  * Re-load the row security policies if the relation has them, since
4073  * they are not preserved in the cache. Note that we can never NOT
4074  * have a policy while relrowsecurity is true,
4075  * RelationBuildRowSecurity will create a single default-deny policy
4076  * if there is no policy defined in pg_policy.
4077  */
4078  if (relation->rd_rel->relrowsecurity && relation->rd_rsdesc == NULL)
4079  {
4080  RelationBuildRowSecurity(relation);
4081 
4082  Assert(relation->rd_rsdesc != NULL);
4083  restart = true;
4084  }
4085 
4086  /* Reload tableam data if needed */
4087  if (relation->rd_tableam == NULL &&
4088  (relation->rd_rel->relkind == RELKIND_RELATION ||
4089  relation->rd_rel->relkind == RELKIND_SEQUENCE ||
4090  relation->rd_rel->relkind == RELKIND_TOASTVALUE ||
4091  relation->rd_rel->relkind == RELKIND_MATVIEW))
4092  {
4094  Assert(relation->rd_tableam != NULL);
4095 
4096  restart = true;
4097  }
4098 
4099  /* Release hold on the relation */
4101 
4102  /* Now, restart the hashtable scan if needed */
4103  if (restart)
4104  {
4105  hash_seq_term(&status);
4106  hash_seq_init(&status, RelationIdCache);
4107  }
4108  }
4109 
4110  /*
4111  * Lastly, write out new relcache cache files if needed. We don't bother
4112  * to distinguish cases where only one of the two needs an update.
4113  */
4114  if (needNewCacheFile)
4115  {
4116  /*
4117  * Force all the catcaches to finish initializing and thereby open the
4118  * catalogs and indexes they use. This will preload the relcache with
4119  * entries for all the most important system catalogs and indexes, so
4120  * that the init files will be most useful for future backends.
4121  */
4123 
4124  /* now write the files */
4126  write_relcache_init_file(false);
4127  }
4128 }
#define AttributeRelidNumIndexId
Definition: indexing.h:96
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5591
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define IndexRelidIndexId
Definition: indexing.h:168
#define RewriteRelRulenameIndexId
Definition: indexing.h:217
void RelationBuildRowSecurity(Relation relation)
Definition: policy.c:192
void RelationInitTableAccessMethod(Relation relation)
Definition: relcache.c:1743
Relation reldesc
Definition: relcache.c:127
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
bool criticalSharedRelcachesBuilt
Definition: relcache.c:142
#define AuthIdOidIndexId
Definition: indexing.h:101
static HTAB * RelationIdCache
Definition: relcache.c:130
Form_pg_class rd_rel
Definition: rel.h:109
#define TriggerRelidNameIndexId
Definition: indexing.h:253
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2081
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
int32 tdtypmod
Definition: tupdesc.h:83
#define FATAL
Definition: elog.h:52
static void write_relcache_init_file(bool shared)
Definition: relcache.c:6007
TriggerDesc * trigdesc
Definition: rel.h:115
static void RelationParseRelOptions(Relation relation, HeapTuple tuple)
Definition: relcache.c:439
static void load_critical_index(Oid indexoid, Oid heapoid)
Definition: relcache.c:4137
static const FormData_pg_attribute Desc_pg_proc[Natts_pg_proc]
Definition: relcache.c:109
#define RelationGetRelationName(relation)
Definition: rel.h:490
#define DatabaseOidIndexId
Definition: indexing.h:146
#define ClassOidIndexId
Definition: indexing.h:114
struct RowSecurityDesc * rd_rsdesc
Definition: rel.h:117
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
#define AccessMethodProcedureIndexId
Definition: indexing.h:84
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2068
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
const struct TableAmRoutine * rd_tableam
Definition: rel.h:171
TupleDesc rd_att
Definition: rel.h:110
#define OpclassOidIndexId
Definition: indexing.h:197
#define InvalidOid
Definition: postgres_ext.h:36
#define CLASS_TUPLE_SIZE
Definition: pg_class.h:145
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:738
#define AuthMemMemRoleIndexId
Definition: indexing.h:106
RuleLock * rd_rules
Definition: rel.h:113
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1390
#define DatabaseNameIndexId
Definition: indexing.h:144
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1380
#define SharedSecLabelObjectIndexId
Definition: indexing.h:320
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:392
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
Oid tdtypeid
Definition: tupdesc.h:82
void RelationBuildTriggers(Relation relation)
Definition: trigger.c:1592
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1807
static const FormData_pg_attribute Desc_pg_class[Natts_pg_class]
Definition: relcache.c:107
#define elog(elevel,...)
Definition: elog.h:214
void RelationMapInitializePhase3(void)
Definition: relmapper.c:625
static void RelationBuildRuleLock(Relation relation)
Definition: relcache.c:733
bool criticalRelcachesBuilt
Definition: relcache.c:136
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
#define AuthIdRolnameIndexId
Definition: indexing.h:99
void InitCatalogCachePhase2(void)
Definition: syscache.c:1075
#define RelationGetRelid(relation)
Definition: rel.h:456
static const FormData_pg_attribute Desc_pg_type[Natts_pg_type]
Definition: relcache.c:110
bytea * rd_options
Definition: rel.h:157
void hash_seq_term(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1466
static const FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute]
Definition: relcache.c:108
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInvalidate()

void RelationCacheInvalidate ( void  )

Definition at line 2822 of file relcache.c.

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

Referenced by InvalidateSystemCaches(), and LocalExecuteInvalidationMessage().

2823 {
2825  RelIdCacheEnt *idhentry;
2826  Relation relation;
2827  List *rebuildFirstList = NIL;
2828  List *rebuildList = NIL;
2829  ListCell *l;
2830 
2831  /*
2832  * Reload relation mapping data before starting to reconstruct cache.
2833  */
2835 
2836  /* Phase 1 */
2837  hash_seq_init(&status, RelationIdCache);
2838 
2839  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2840  {
2841  relation = idhentry->reldesc;
2842 
2843  /* Must close all smgr references to avoid leaving dangling ptrs */
2844  RelationCloseSmgr(relation);
2845 
2846  /*
2847  * Ignore new relations; no other backend will manipulate them before
2848  * we commit. Likewise, before replacing a relation's relfilenode, we
2849  * shall have acquired AccessExclusiveLock and drained any applicable
2850  * pending invalidations.
2851  */
2852  if (relation->rd_createSubid != InvalidSubTransactionId ||
2854  continue;
2855 
2857 
2858  if (RelationHasReferenceCountZero(relation))
2859  {
2860  /* Delete this entry immediately */
2861  Assert(!relation->rd_isnailed);
2862  RelationClearRelation(relation, false);
2863  }
2864  else
2865  {
2866  /*
2867  * If it's a mapped relation, immediately update its rd_node in
2868  * case its relfilenode changed. We must do this during phase 1
2869  * in case the relation is consulted during rebuild of other
2870  * relcache entries in phase 2. It's safe since consulting the
2871  * map doesn't involve any access to relcache entries.
2872  */
2873  if (RelationIsMapped(relation))
2874  RelationInitPhysicalAddr(relation);
2875 
2876  /*
2877  * Add this entry to list of stuff to rebuild in second pass.
2878  * pg_class goes to the front of rebuildFirstList while
2879  * pg_class_oid_index goes to the back of rebuildFirstList, so
2880  * they are done first and second respectively. Other nailed
2881  * relations go to the front of rebuildList, so they'll be done
2882  * next in no particular order; and everything else goes to the
2883  * back of rebuildList.
2884  */
2885  if (RelationGetRelid(relation) == RelationRelationId)
2886  rebuildFirstList = lcons(relation, rebuildFirstList);
2887  else if (RelationGetRelid(relation) == ClassOidIndexId)
2888  rebuildFirstList = lappend(rebuildFirstList, relation);
2889  else if (relation->rd_isnailed)
2890  rebuildList = lcons(relation, rebuildList);
2891  else
2892  rebuildList = lappend(rebuildList, relation);
2893  }
2894  }
2895 
2896  /*
2897  * Now zap any remaining smgr cache entries. This must happen before we
2898  * start to rebuild entries, since that may involve catalog fetches which
2899  * will re-open catalog files.
2900  */
2901  smgrcloseall();
2902 
2903  /* Phase 2: rebuild the items found to need rebuild in phase 1 */
2904  foreach(l, rebuildFirstList)
2905  {
2906  relation = (Relation) lfirst(l);
2907  RelationClearRelation(relation, true);
2908  }
2909  list_free(rebuildFirstList);
2910  foreach(l, rebuildList)
2911  {
2912  relation = (Relation) lfirst(l);
2913  RelationClearRelation(relation, true);
2914  }
2915  list_free(rebuildList);
2916 }
#define NIL
Definition: pg_list.h:65
static long relcacheInvalsReceived
Definition: relcache.c:150
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2422
bool rd_isnailed
Definition: rel.h:61
Relation reldesc
Definition: relcache.c:127
#define RelationCloseSmgr(relation)
Definition: rel.h:525
static HTAB * RelationIdCache
Definition: relcache.c:130
void smgrcloseall(void)
Definition: smgr.c:286
struct RelationData * Relation
Definition: relcache.h:27
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1272
#define ClassOidIndexId
Definition: indexing.h:114
List * lappend(List *list, void *datum)
Definition: list.c:322
#define RelationIsMapped(relation)
Definition: rel.h:505
SubTransactionId rd_createSubid
Definition: rel.h:102
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
List * lcons(void *datum, List *list)
Definition: list.c:454
#define Assert(condition)
Definition: c.h:738
#define lfirst(lc)
Definition: pg_list.h:190
#define InvalidSubTransactionId
Definition: c.h:519
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1390
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1380
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:440
void list_free(List *list)
Definition: list.c:1377
void RelationMapInvalidateAll(void)
Definition: relmapper.c:425
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:456

◆ RelationCacheInvalidateEntry()

void RelationCacheInvalidateEntry ( Oid  relationId)

Definition at line 2779 of file relcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

2780 {
2781  Relation relation;
2782 
2783  RelationIdCacheLookup(relationId, relation);
2784 
2785  if (PointerIsValid(relation))
2786  {
2788  RelationFlushRelation(relation);
2789  }
2790 }
static long relcacheInvalsReceived
Definition: relcache.c:150
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:209
static void RelationFlushRelation(Relation relation)
Definition: relcache.c:2702
#define PointerIsValid(pointer)
Definition: c.h:632

◆ RelationClearRelation()

static void RelationClearRelation ( Relation  relation,
bool  rebuild 
)
static

Definition at line 2422 of file relcache.c.

References Assert, CLASS_TUPLE_SIZE, elog, equalRSDesc(), equalRuleLocks(), equalTupleDescs(), ERROR, HistoricSnapshotActive(), InvalidSubTransactionId, IsTransactionState(), MemoryContextSetParent(), pfree(), RelationData::rd_amcache, RelationData::rd_att, RelationData::rd_droppedSubid, RelationData::rd_indexcxt, RelationData::rd_isnailed, RelationData::rd_isvalid, RelationData::rd_partdesc, RelationData::rd_partkey, RelationData::rd_pdcxt, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_rsdesc, RelationData::rd_rules, RelationBuildDesc(), RelationCacheDelete, RelationCloseSmgr, RelationDestroyRelation(), RelationGetRelid, RelationHasReferenceCountZero, RelationReloadIndexInfo(), RelationReloadNailed(), and SWAPFIELD.

Referenced by AtEOSubXact_cleanup(), AtEOXact_cleanup(), RelationCacheInvalidate(), RelationClose(), RelationFlushRelation(), RelationForgetRelation(), and RelationIdGetRelation().

2423 {
2424  /*
2425  * As per notes above, a rel to be rebuilt MUST have refcnt > 0; while of
2426  * course it would be an equally bad idea to blow away one with nonzero
2427  * refcnt, since that would leave someone somewhere with a dangling
2428  * pointer. All callers are expected to have verified that this holds.
2429  */
2430  Assert(rebuild ?
2431  !RelationHasReferenceCountZero(relation) :
2432  RelationHasReferenceCountZero(relation));
2433 
2434  /*
2435  * Make sure smgr and lower levels close the relation's files, if they
2436  * weren't closed already. If the relation is not getting deleted, the
2437  * next smgr access should reopen the files automatically. This ensures
2438  * that the low-level file access state is updated after, say, a vacuum
2439  * truncation.
2440  */
2441  RelationCloseSmgr(relation);
2442 
2443  /* Free AM cached data, if any */
2444  if (relation->rd_amcache)
2445  pfree(relation->rd_amcache);
2446  relation->rd_amcache = NULL;
2447 
2448  /*
2449  * Treat nailed-in system relations separately, they always need to be
2450  * accessible, so we can't blow them away.
2451  */
2452  if (relation->rd_isnailed)
2453  {
2454  RelationReloadNailed(relation);
2455  return;
2456  }
2457 
2458  /* Mark it invalid until we've finished rebuild */
2459  relation->rd_isvalid = false;
2460 
2461  /* See RelationForgetRelation(). */
2462  if (relation->rd_droppedSubid != InvalidSubTransactionId)
2463  return;
2464 
2465  /*
2466  * Even non-system indexes should not be blown away if they are open and
2467  * have valid index support information. This avoids problems with active
2468  * use of the index support information. As with nailed indexes, we
2469  * re-read the pg_class row to handle possible physical relocation of the
2470  * index, and we check for pg_index updates too.
2471  */
2472  if ((relation->rd_rel->relkind == RELKIND_INDEX ||
2473  relation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX) &&
2474  relation->rd_refcnt > 0 &&
2475  relation->rd_indexcxt != NULL)
2476  {
2477  if (IsTransactionState())
2478  RelationReloadIndexInfo(relation);
2479  return;
2480  }
2481 
2482  /*
2483  * If we're really done with the relcache entry, blow it away. But if
2484  * someone is still using it, reconstruct the whole deal without moving
2485  * the physical RelationData record (so that the someone's pointer is
2486  * still valid).
2487  */
2488  if (!rebuild)
2489  {
2490  /* Remove it from the hash table */
2491  RelationCacheDelete(relation);
2492 
2493  /* And release storage */
2494  RelationDestroyRelation(relation, false);
2495  }
2496  else if (!IsTransactionState())
2497  {
2498  /*
2499  * If we're not inside a valid transaction, we can't do any catalog
2500  * access so it's not possible to rebuild yet. Just exit, leaving
2501  * rd_isvalid = false so that the rebuild will occur when the entry is
2502  * next opened.
2503  *
2504  * Note: it's possible that we come here during subtransaction abort,
2505  * and the reason for wanting to rebuild is that the rel is open in
2506  * the outer transaction. In that case it might seem unsafe to not
2507  * rebuild immediately, since whatever code has the rel already open
2508  * will keep on using the relcache entry as-is. However, in such a
2509  * case the outer transaction should be holding a lock that's
2510  * sufficient to prevent any significant change in the rel's schema,
2511  * so the existing entry contents should be good enough for its
2512  * purposes; at worst we might be behind on statistics updates or the
2513  * like. (See also CheckTableNotInUse() and its callers.) These same
2514  * remarks also apply to the cases above where we exit without having
2515  * done RelationReloadIndexInfo() yet.
2516  */
2517  return;
2518  }
2519  else
2520  {
2521  /*
2522  * Our strategy for rebuilding an open relcache entry is to build a
2523  * new entry from scratch, swap its contents with the old entry, and
2524  * finally delete the new entry (along with any infrastructure swapped
2525  * over from the old entry). This is to avoid trouble in case an
2526  * error causes us to lose control partway through. The old entry
2527  * will still be marked !rd_isvalid, so we'll try to rebuild it again
2528  * on next access. Meanwhile it's not any less valid than it was
2529  * before, so any code that might expect to continue accessing it
2530  * isn't hurt by the rebuild failure. (Consider for example a
2531  * subtransaction that ALTERs a table and then gets canceled partway
2532  * through the cache entry rebuild. The outer transaction should
2533  * still see the not-modified cache entry as valid.) The worst
2534  * consequence of an error is leaking the necessarily-unreferenced new
2535  * entry, and this shouldn't happen often enough for that to be a big
2536  * problem.
2537  *
2538  * When rebuilding an open relcache entry, we must preserve ref count,
2539  * rd_*Subid, and rd_toastoid state. Also attempt to preserve the
2540  * pg_class entry (rd_rel), tupledesc, rewrite-rule, partition key,
2541  * and partition descriptor substructures in place, because various
2542  * places assume that these structures won't move while they are
2543  * working with an open relcache entry. (Note: the refcount
2544  * mechanism for tupledescs might someday allow us to remove this hack
2545  * for the tupledesc.)
2546  *
2547  * Note that this process does not touch CurrentResourceOwner; which
2548  * is good because whatever ref counts the entry may have do not
2549  * necessarily belong to that resource owner.
2550  */
2551  Relation newrel;
2552  Oid save_relid = RelationGetRelid(relation);
2553  bool keep_tupdesc;
2554  bool keep_rules;
2555  bool keep_policies;
2556  bool keep_partkey;
2557 
2558  /* Build temporary entry, but don't link it into hashtable */
2559  newrel = RelationBuildDesc(save_relid, false);
2560  if (newrel == NULL)
2561  {
2562  /*
2563  * We can validly get here, if we're using a historic snapshot in
2564  * which a relation, accessed from outside logical decoding, is
2565  * still invisible. In that case it's fine to just mark the
2566  * relation as invalid and return - it'll fully get reloaded by
2567  * the cache reset at the end of logical decoding (or at the next
2568  * access). During normal processing we don't want to ignore this
2569  * case as it shouldn't happen there, as explained below.
2570  */
2571  if (HistoricSnapshotActive())
2572  return;
2573 
2574  /*
2575  * This shouldn't happen as dropping a relation is intended to be
2576  * impossible if still referenced (cf. CheckTableNotInUse()). But
2577  * if we get here anyway, we can't just delete the relcache entry,
2578  * as it possibly could get accessed later (as e.g. the error
2579  * might get trapped and handled via a subtransaction rollback).
2580  */
2581  elog(ERROR, "relation %u deleted while still in use", save_relid);
2582  }
2583 
2584  keep_tupdesc = equalTupleDescs(relation->rd_att, newrel->