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/index.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/partition.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:164
static int eoxact_list_len
Definition: relcache.c:166

Definition at line 169 of file relcache.c.

Referenced by RelationAssumeNewRelfilenode(), and RelationBuildLocalRelation().

◆ INITRELCACHESIZE

#define INITRELCACHESIZE   400

Definition at line 3774 of file relcache.c.

Referenced by RelationCacheInitialize().

◆ MAX_EOXACT_LIST

#define MAX_EOXACT_LIST   32

Definition at line 164 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.

Referenced by RelationBuildDesc().

◆ 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:954
static HTAB * RelationIdCache
Definition: relcache.c:132
#define WARNING
Definition: elog.h:40

Definition at line 223 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:954
static HTAB * RelationIdCache
Definition: relcache.c:132
#define RelationGetRelationName(relation)
Definition: rel.h:491
#define WARNING
Definition: elog.h:40
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:441
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:394

Definition at line 189 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:954
static HTAB * RelationIdCache
Definition: relcache.c:132

Definition at line 211 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 91 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 386 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().

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

3276 {
3277  /*
3278  * Is it a relation created in the current subtransaction?
3279  *
3280  * During subcommit, mark it as belonging to the parent, instead, as long
3281  * as it has not been dropped. Otherwise simply delete the relcache entry.
3282  * --- it isn't interesting any longer.
3283  */
3284  if (relation->rd_createSubid == mySubid)
3285  {
3286  /*
3287  * Valid rd_droppedSubid means the corresponding relation is dropped
3288  * but the relcache entry is preserved for at-commit pending sync. We
3289  * need to drop it explicitly here not to make the entry orphan.
3290  */
3291  Assert(relation->rd_droppedSubid == mySubid ||
3293  if (isCommit && relation->rd_droppedSubid == InvalidSubTransactionId)
3294  relation->rd_createSubid = parentSubid;
3295  else if (RelationHasReferenceCountZero(relation))
3296  {
3297  /* allow the entry to be removed */
3302  RelationClearRelation(relation, false);
3303  return;
3304  }
3305  else
3306  {
3307  /*
3308  * Hmm, somewhere there's a (leaked?) reference to the relation.
3309  * We daren't remove the entry for fear of dereferencing a
3310  * dangling pointer later. Bleat, and transfer it to the parent
3311  * subtransaction so we can try again later. This must be just a
3312  * WARNING to avoid error-during-error-recovery loops.
3313  */
3314  relation->rd_createSubid = parentSubid;
3315  elog(WARNING, "cannot remove relcache entry for \"%s\" because it has nonzero refcount",
3316  RelationGetRelationName(relation));
3317  }
3318  }
3319 
3320  /*
3321  * Likewise, update or drop any new-relfilenode-in-subtransaction record
3322  * or drop record.
3323  */
3324  if (relation->rd_newRelfilenodeSubid == mySubid)
3325  {
3326  if (isCommit)
3327  relation->rd_newRelfilenodeSubid = parentSubid;
3328  else
3330  }
3331 
3332  if (relation->rd_firstRelfilenodeSubid == mySubid)
3333  {
3334  if (isCommit)
3335  relation->rd_firstRelfilenodeSubid = parentSubid;
3336  else
3338  }
3339 
3340  if (relation->rd_droppedSubid == mySubid)
3341  {
3342  if (isCommit)
3343  relation->rd_droppedSubid = parentSubid;
3344  else
3346  }
3347 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2444
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:104
#define RelationGetRelationName(relation)
Definition: rel.h:491
#define WARNING
Definition: elog.h:40
SubTransactionId rd_createSubid
Definition: rel.h:103
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:106
#define Assert(condition)
Definition: c.h:792
#define InvalidSubTransactionId
Definition: c.h:581
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:441
#define elog(elevel,...)
Definition: elog.h:228
SubTransactionId rd_droppedSubid
Definition: rel.h:108

◆ AtEOSubXact_RelationCache()

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

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

3229 {
3231  RelIdCacheEnt *idhentry;
3232  int i;
3233 
3234  /*
3235  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3236  * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3237  * logic as in AtEOXact_RelationCache.
3238  */
3240  {
3241  hash_seq_init(&status, RelationIdCache);
3242  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3243  {
3244  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3245  mySubid, parentSubid);
3246  }
3247  }
3248  else
3249  {
3250  for (i = 0; i < eoxact_list_len; i++)
3251  {
3252  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3253  (void *) &eoxact_list[i],
3254  HASH_FIND,
3255  NULL);
3256  if (idhentry != NULL)
3257  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3258  mySubid, parentSubid);
3259  }
3260  }
3261 
3262  /* Don't reset the list; we still need more cleanup later */
3263 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:165
static void AtEOSubXact_cleanup(Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
Definition: relcache.c:3274
Relation reldesc
Definition: relcache.c:129
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
static HTAB * RelationIdCache
Definition: relcache.c:132
static bool eoxact_list_overflowed
Definition: relcache.c:167
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1436
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1426
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
static int eoxact_list_len
Definition: relcache.c:166

◆ AtEOXact_cleanup()

static void AtEOXact_cleanup ( Relation  relation,
bool  isCommit 
)
static

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

3146 {
3147  bool clear_relcache = false;
3148 
3149  /*
3150  * The relcache entry's ref count should be back to its normal
3151  * not-in-a-transaction state: 0 unless it's nailed in cache.
3152  *
3153  * In bootstrap mode, this is NOT true, so don't check it --- the
3154  * bootstrap code expects relations to stay open across start/commit
3155  * transaction calls. (That seems bogus, but it's not worth fixing.)
3156  *
3157  * Note: ideally this check would be applied to every relcache entry, not
3158  * just those that have eoxact work to do. But it's not worth forcing a
3159  * scan of the whole relcache just for this. (Moreover, doing so would
3160  * mean that assert-enabled testing never tests the hash_search code path
3161  * above, which seems a bad idea.)
3162  */
3163 #ifdef USE_ASSERT_CHECKING
3165  {
3166  int expected_refcnt;
3167 
3168  expected_refcnt = relation->rd_isnailed ? 1 : 0;
3169  Assert(relation->rd_refcnt == expected_refcnt);
3170  }
3171 #endif
3172 
3173  /*
3174  * Is the relation live after this transaction ends?
3175  *
3176  * During commit, clear the relcache entry if it is preserved after
3177  * relation drop, in order not to orphan the entry. During rollback,
3178  * clear the relcache entry if the relation is created in the current
3179  * transaction since it isn't interesting any longer once we are out of
3180  * the transaction.
3181  */
3182  clear_relcache =
3183  (isCommit ?
3186 
3187  /*
3188  * Since we are now out of the transaction, reset the subids to zero. That
3189  * also lets RelationClearRelation() drop the relcache entry.
3190  */
3195 
3196  if (clear_relcache)
3197  {
3198  if (RelationHasReferenceCountZero(relation))
3199  {
3200  RelationClearRelation(relation, false);
3201  return;
3202  }
3203  else
3204  {
3205  /*
3206  * Hmm, somewhere there's a (leaked?) reference to the relation.
3207  * We daren't remove the entry for fear of dereferencing a
3208  * dangling pointer later. Bleat, and mark it as not belonging to
3209  * the current transaction. Hopefully it'll get cleaned up
3210  * eventually. This must be just a WARNING to avoid
3211  * error-during-error-recovery loops.
3212  */
3213  elog(WARNING, "cannot remove relcache entry for \"%s\" because it has nonzero refcount",
3214  RelationGetRelationName(relation));
3215  }
3216  }
3217 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2444
bool rd_isnailed
Definition: rel.h:61
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:104
#define RelationGetRelationName(relation)
Definition: rel.h:491
#define WARNING
Definition: elog.h:40
SubTransactionId rd_createSubid
Definition: rel.h:103
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:106
#define Assert(condition)
Definition: c.h:792
#define InvalidSubTransactionId
Definition: c.h:581
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:441
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:394
int rd_refcnt
Definition: rel.h:58
#define elog(elevel,...)
Definition: elog.h:228
SubTransactionId rd_droppedSubid
Definition: rel.h:108

◆ AtEOXact_RelationCache()

void AtEOXact_RelationCache ( bool  isCommit)

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

3083 {
3085  RelIdCacheEnt *idhentry;
3086  int i;
3087 
3088  /*
3089  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3090  * listed in it. Otherwise fall back on a hash_seq_search scan.
3091  *
3092  * For simplicity, eoxact_list[] entries are not deleted till end of
3093  * top-level transaction, even though we could remove them at
3094  * subtransaction end in some cases, or remove relations from the list if
3095  * they are cleared for other reasons. Therefore we should expect the
3096  * case that list entries are not found in the hashtable; if not, there's
3097  * nothing to do for them.
3098  */
3100  {
3101  hash_seq_init(&status, RelationIdCache);
3102  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3103  {
3104  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3105  }
3106  }
3107  else
3108  {
3109  for (i = 0; i < eoxact_list_len; i++)
3110  {
3111  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3112  (void *) &eoxact_list[i],
3113  HASH_FIND,
3114  NULL);
3115  if (idhentry != NULL)
3116  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3117  }
3118  }
3119 
3120  if (EOXactTupleDescArrayLen > 0)
3121  {
3122  Assert(EOXactTupleDescArray != NULL);
3123  for (i = 0; i < NextEOXactTupleDescNum; i++)
3126  EOXactTupleDescArray = NULL;
3127  }
3128 
3129  /* Now we're out of the transaction and can clear the lists */
3130  eoxact_list_len = 0;
3131  eoxact_list_overflowed = false;
3132  NextEOXactTupleDescNum = 0;
3134 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:165
static int EOXactTupleDescArrayLen
Definition: relcache.c:184
Relation reldesc
Definition: relcache.c:129
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
static HTAB * RelationIdCache
Definition: relcache.c:132
static void AtEOXact_cleanup(Relation relation, bool isCommit)
Definition: relcache.c:3145
static bool eoxact_list_overflowed
Definition: relcache.c:167
static int NextEOXactTupleDescNum
Definition: relcache.c:183
void pfree(void *pointer)
Definition: mcxt.c:1057
#define Assert(condition)
Definition: c.h:792
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1436
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1426
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:313
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
static int eoxact_list_len
Definition: relcache.c:166
static TupleDesc * EOXactTupleDescArray
Definition: relcache.c:182

◆ AttrDefaultFetch()

static void AttrDefaultFetch ( Relation  relation)
static

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

4254 {
4255  AttrDefault *attrdef = relation->rd_att->constr->defval;
4256  int ndef = relation->rd_att->constr->num_defval;
4257  Relation adrel;
4258  SysScanDesc adscan;
4259  ScanKeyData skey;
4260  HeapTuple htup;
4261  Datum val;
4262  bool isnull;
4263  int found;
4264  int i;
4265 
4266  ScanKeyInit(&skey,
4267  Anum_pg_attrdef_adrelid,
4268  BTEqualStrategyNumber, F_OIDEQ,
4269  ObjectIdGetDatum(RelationGetRelid(relation)));
4270 
4271  adrel = table_open(AttrDefaultRelationId, AccessShareLock);
4272  adscan = systable_beginscan(adrel, AttrDefaultIndexId, true,
4273  NULL, 1, &skey);
4274  found = 0;
4275 
4276  while (HeapTupleIsValid(htup = systable_getnext(adscan)))
4277  {
4278  Form_pg_attrdef adform = (Form_pg_attrdef) GETSTRUCT(htup);
4279  Form_pg_attribute attr = TupleDescAttr(relation->rd_att, adform->adnum - 1);
4280 
4281  for (i = 0; i < ndef; i++)
4282  {
4283  if (adform->adnum != attrdef[i].adnum)
4284  continue;
4285  if (attrdef[i].adbin != NULL)
4286  elog(WARNING, "multiple attrdef records found for attr %s of rel %s",
4287  NameStr(attr->attname),
4288  RelationGetRelationName(relation));
4289  else
4290  found++;
4291 
4292  val = fastgetattr(htup,
4293  Anum_pg_attrdef_adbin,
4294  adrel->rd_att, &isnull);
4295  if (isnull)
4296  elog(WARNING, "null adbin for attr %s of rel %s",
4297  NameStr(attr->attname),
4298  RelationGetRelationName(relation));
4299  else
4300  {
4301  /* detoast and convert to cstring in caller's context */
4302  char *s = TextDatumGetCString(val);
4303 
4305  pfree(s);
4306  }
4307  break;
4308  }
4309 
4310  if (i >= ndef)
4311  elog(WARNING, "unexpected attrdef record found for attr %d of rel %s",
4312  adform->adnum, RelationGetRelationName(relation));
4313  }
4314 
4315  systable_endscan(adscan);
4316  table_close(adrel, AccessShareLock);
4317 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:593
#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 AttrDefaultIndexId
Definition: pg_attrdef.h:52
#define AccessShareLock
Definition: lockdefs.h:36
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:381
AttrDefault * defval
Definition: tupdesc.h:39
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:500
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
TupleConstr * constr
Definition: tupdesc.h:85
#define RelationGetRelationName(relation)
Definition: rel.h:491
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:83
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:111
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
uint16 num_defval
Definition: tupdesc.h:42
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1174
#define elog(elevel,...)
Definition: elog.h:228
int i
AttrNumber adnum
Definition: tupdesc.h:24
char * adbin
Definition: tupdesc.h:25
#define NameStr(name)
Definition: c.h:669
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:457
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 4194 of file relcache.c.

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

Referenced by GetPgClassDescriptor(), and GetPgIndexDescriptor().

4195 {
4196  TupleDesc result;
4197  MemoryContext oldcxt;
4198  int i;
4199 
4201 
4202  result = CreateTemplateTupleDesc(natts);
4203  result->tdtypeid = RECORDOID; /* not right, but we don't care */
4204  result->tdtypmod = -1;
4205 
4206  for (i = 0; i < natts; i++)
4207  {
4208  memcpy(TupleDescAttr(result, i), &attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
4209  /* make sure attcacheoff is valid */
4210  TupleDescAttr(result, i)->attcacheoff = -1;
4211  }
4212 
4213  /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
4214  TupleDescAttr(result, 0)->attcacheoff = 0;
4215 
4216  /* Note: we don't bother to set up a TupleConstr entry */
4217 
4218  MemoryContextSwitchTo(oldcxt);
4219 
4220  return result;
4221 }
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 4394 of file relcache.c.

References ConstrCheck::ccname.

Referenced by CheckConstraintFetch().

4395 {
4396  const ConstrCheck *ca = (const ConstrCheck *) a;
4397  const ConstrCheck *cb = (const ConstrCheck *) b;
4398 
4399  return strcmp(ca->ccname, cb->ccname);
4400 }
char * ccname
Definition: tupdesc.h:30

◆ CheckConstraintFetch()

static void CheckConstraintFetch ( Relation  relation)
static

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

4324 {
4325  ConstrCheck *check = relation->rd_att->constr->check;
4326  int ncheck = relation->rd_att->constr->num_check;
4327  Relation conrel;
4328  SysScanDesc conscan;
4329  ScanKeyData skey[1];
4330  HeapTuple htup;
4331  int found = 0;
4332 
4333  ScanKeyInit(&skey[0],
4334  Anum_pg_constraint_conrelid,
4335  BTEqualStrategyNumber, F_OIDEQ,
4336  ObjectIdGetDatum(RelationGetRelid(relation)));
4337 
4338  conrel = table_open(ConstraintRelationId, AccessShareLock);
4339  conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
4340  NULL, 1, skey);
4341 
4342  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4343  {
4345  Datum val;
4346  bool isnull;
4347  char *s;
4348 
4349  /* We want check constraints only */
4350  if (conform->contype != CONSTRAINT_CHECK)
4351  continue;
4352 
4353  if (found >= ncheck)
4354  elog(ERROR, "unexpected constraint record found for rel %s",
4355  RelationGetRelationName(relation));
4356 
4357  check[found].ccvalid = conform->convalidated;
4358  check[found].ccnoinherit = conform->connoinherit;
4360  NameStr(conform->conname));
4361 
4362  /* Grab and test conbin is actually set */
4363  val = fastgetattr(htup,
4364  Anum_pg_constraint_conbin,
4365  conrel->rd_att, &isnull);
4366  if (isnull)
4367  elog(ERROR, "null conbin for rel %s",
4368  RelationGetRelationName(relation));
4369 
4370  /* detoast and convert to cstring in caller's context */
4371  s = TextDatumGetCString(val);
4372  check[found].ccbin = MemoryContextStrdup(CacheMemoryContext, s);
4373  pfree(s);
4374 
4375  found++;
4376  }
4377 
4378  systable_endscan(conscan);
4379  table_close(conrel, AccessShareLock);
4380 
4381  if (found != ncheck)
4382  elog(ERROR, "%d constraint record(s) missing for rel %s",
4383  ncheck - found, RelationGetRelationName(relation));
4384 
4385  /* Sort the records so that CHECKs are applied in a deterministic order */
4386  if (ncheck > 1)
4387  qsort(check, ncheck, sizeof(ConstrCheck), CheckConstraintCmp);
4388 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:593
#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:4394
#define AccessShareLock
Definition: lockdefs.h:36
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:381
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:500
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
#define ConstraintRelidTypidNameIndexId
TupleConstr * constr
Definition: tupdesc.h:85
char * ccname
Definition: tupdesc.h:30
#define RelationGetRelationName(relation)
Definition: rel.h:491
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:367
TupleDesc rd_att
Definition: rel.h:111
uint16 num_check
Definition: tupdesc.h:43
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1174
#define elog(elevel,...)
Definition: elog.h:228
#define NameStr(name)
Definition: c.h:669
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:503
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
char * ccbin
Definition: tupdesc.h:31
#define RelationGetRelid(relation)
Definition: rel.h:457
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 5428 of file relcache.c.

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

Referenced by RelationGetIndexAttOptions().

5429 {
5430  bytea **opts = palloc(sizeof(*opts) * natts);
5431 
5432  for (int i = 0; i < natts; i++)
5433  {
5434  bytea *opt = srcopts[i];
5435 
5436  opts[i] = !opt ? NULL : (bytea *)
5437  DatumGetPointer(datumCopy(PointerGetDatum(opt), false, -1));
5438  }
5439 
5440  return opts;
5441 }
#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:950
int i
Definition: c.h:609

◆ equalPolicy()

static bool equalPolicy ( RowSecurityPolicy policy1,
RowSecurityPolicy policy2 
)
static

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

943 {
944  int i;
945  Oid *r1,
946  *r2;
947 
948  if (policy1 != NULL)
949  {
950  if (policy2 == NULL)
951  return false;
952 
953  if (policy1->polcmd != policy2->polcmd)
954  return false;
955  if (policy1->hassublinks != policy2->hassublinks)
956  return false;
957  if (strcmp(policy1->policy_name, policy2->policy_name) != 0)
958  return false;
959  if (ARR_DIMS(policy1->roles)[0] != ARR_DIMS(policy2->roles)[0])
960  return false;
961 
962  r1 = (Oid *) ARR_DATA_PTR(policy1->roles);
963  r2 = (Oid *) ARR_DATA_PTR(policy2->roles);
964 
965  for (i = 0; i < ARR_DIMS(policy1->roles)[0]; i++)
966  {
967  if (r1[i] != r2[i])
968  return false;
969  }
970 
971  if (!equal(policy1->qual, policy2->qual))
972  return false;
973  if (!equal(policy1->with_check_qual, policy2->with_check_qual))
974  return false;
975  }
976  else if (policy2 != NULL)
977  return false;
978 
979  return true;
980 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3042
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_DATA_PTR(a)
Definition: array.h:315
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 988 of file relcache.c.

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

Referenced by RelationClearRelation().

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

◆ equalRuleLocks()

static bool equalRuleLocks ( RuleLock rlock1,
RuleLock rlock2 
)
static

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

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

5510 {
5514 
5515  return 0; /* return value does not matter */
5516 }
#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:3289
#define RelationGetRelationName(relation)
Definition: rel.h:491
int err_generic_string(int field, const char *str)
Definition: elog.c:1356
#define RelationGetNamespace(relation)
Definition: rel.h:498

◆ errtablecol()

int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5526 of file relcache.c.

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

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

5527 {
5528  TupleDesc reldesc = RelationGetDescr(rel);
5529  const char *colname;
5530 
5531  /* Use reldesc if it's a user attribute, else consult the catalogs */
5532  if (attnum > 0 && attnum <= reldesc->natts)
5533  colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
5534  else
5535  colname = get_attname(RelationGetRelid(rel), attnum, false);
5536 
5537  return errtablecolname(rel, colname);
5538 }
#define RelationGetDescr(relation)
Definition: rel.h:483
#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:669
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:825
#define RelationGetRelid(relation)
Definition: rel.h:457
int errtablecolname(Relation rel, const char *colname)
Definition: relcache.c:5550

◆ errtablecolname()

int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5550 of file relcache.c.

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

Referenced by errtablecol().

5551 {
5552  errtable(rel);
5554 
5555  return 0; /* return value does not matter */
5556 }
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:67
int err_generic_string(int field, const char *str)
Definition: elog.c:1356
int errtable(Relation rel)
Definition: relcache.c:5509

◆ errtableconstraint()

int errtableconstraint ( Relation  rel,
const char *  conname 
)

Definition at line 5563 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(), and ri_ReportViolation().

5564 {
5565  errtable(rel);
5567 
5568  return 0; /* return value does not matter */
5569 }
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:69
int err_generic_string(int field, const char *str)
Definition: elog.c:1356
int errtable(Relation rel)
Definition: relcache.c:5509

◆ formrdesc()

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

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

1832 {
1833  Relation relation;
1834  int i;
1835  bool has_not_null;
1836 
1837  /*
1838  * allocate new relation desc, clear all fields of reldesc
1839  */
1840  relation = (Relation) palloc0(sizeof(RelationData));
1841 
1842  /* make sure relation is marked as having no open file yet */
1843  relation->rd_smgr = NULL;
1844 
1845  /*
1846  * initialize reference count: 1 because it is nailed in cache
1847  */
1848  relation->rd_refcnt = 1;
1849 
1850  /*
1851  * all entries built with this routine are nailed-in-cache; none are for
1852  * new or temp relations.
1853  */
1854  relation->rd_isnailed = true;
1859  relation->rd_backend = InvalidBackendId;
1860  relation->rd_islocaltemp = false;
1861 
1862  /*
1863  * initialize relation tuple form
1864  *
1865  * The data we insert here is pretty incomplete/bogus, but it'll serve to
1866  * get us launched. RelationCacheInitializePhase3() will read the real
1867  * data from pg_class and replace what we've done here. Note in
1868  * particular that relowner is left as zero; this cues
1869  * RelationCacheInitializePhase3 that the real data isn't there yet.
1870  */
1872 
1873  namestrcpy(&relation->rd_rel->relname, relationName);
1874  relation->rd_rel->relnamespace = PG_CATALOG_NAMESPACE;
1875  relation->rd_rel->reltype = relationReltype;
1876 
1877  /*
1878  * It's important to distinguish between shared and non-shared relations,
1879  * even at bootstrap time, to make sure we know where they are stored.
1880  */
1881  relation->rd_rel->relisshared = isshared;
1882  if (isshared)
1883  relation->rd_rel->reltablespace = GLOBALTABLESPACE_OID;
1884 
1885  /* formrdesc is used only for permanent relations */
1886  relation->rd_rel->relpersistence = RELPERSISTENCE_PERMANENT;
1887 
1888  /* ... and they're always populated, too */
1889  relation->rd_rel->relispopulated = true;
1890 
1891  relation->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
1892  relation->rd_rel->relpages = 0;
1893  relation->rd_rel->reltuples = -1;
1894  relation->rd_rel->relallvisible = 0;
1895  relation->rd_rel->relkind = RELKIND_RELATION;
1896  relation->rd_rel->relnatts = (int16) natts;
1897  relation->rd_rel->relam = HEAP_TABLE_AM_OID;
1898 
1899  /*
1900  * initialize attribute tuple form
1901  *
1902  * Unlike the case with the relation tuple, this data had better be right
1903  * because it will never be replaced. The data comes from
1904  * src/include/catalog/ headers via genbki.pl.
1905  */
1906  relation->rd_att = CreateTemplateTupleDesc(natts);
1907  relation->rd_att->tdrefcount = 1; /* mark as refcounted */
1908 
1909  relation->rd_att->tdtypeid = relationReltype;
1910  relation->rd_att->tdtypmod = -1; /* just to be sure */
1911 
1912  /*
1913  * initialize tuple desc info
1914  */
1915  has_not_null = false;
1916  for (i = 0; i < natts; i++)
1917  {
1918  memcpy(TupleDescAttr(relation->rd_att, i),
1919  &attrs[i],
1921  has_not_null |= attrs[i].attnotnull;
1922  /* make sure attcacheoff is valid */
1923  TupleDescAttr(relation->rd_att, i)->attcacheoff = -1;
1924  }
1925 
1926  /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
1927  TupleDescAttr(relation->rd_att, 0)->attcacheoff = 0;
1928 
1929  /* mark not-null status */
1930  if (has_not_null)
1931  {
1932  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
1933 
1934  constr->has_not_null = true;
1935  relation->rd_att->constr = constr;
1936  }
1937 
1938  /*
1939  * initialize relation id from info in att array (my, this is ugly)
1940  */
1941  RelationGetRelid(relation) = TupleDescAttr(relation->rd_att, 0)->attrelid;
1942 
1943  /*
1944  * All relations made with formrdesc are mapped. This is necessarily so
1945  * because there is no other way to know what filenode they currently
1946  * have. In bootstrap mode, add them to the initial relation mapper data,
1947  * specifying that the initial filenode is the same as the OID.
1948  */
1949  relation->rd_rel->relfilenode = InvalidOid;
1952  RelationGetRelid(relation),
1953  isshared, true);
1954 
1955  /*
1956  * initialize the relation lock manager information
1957  */
1958  RelationInitLockInfo(relation); /* see lmgr.c */
1959 
1960  /*
1961  * initialize physical addressing information for the relation
1962  */
1963  RelationInitPhysicalAddr(relation);
1964 
1965  /*
1966  * initialize the table am handler
1967  */
1968  relation->rd_rel->relam = HEAP_TABLE_AM_OID;
1969  relation->rd_tableam = GetHeapamTableAmRoutine();
1970 
1971  /*
1972  * initialize the rel-has-index flag, using hardwired knowledge
1973  */
1975  {
1976  /* In bootstrap mode, we have no indexes */
1977  relation->rd_rel->relhasindex = false;
1978  }
1979  else
1980  {
1981  /* Otherwise, all the rels formrdesc is used for have indexes */
1982  relation->rd_rel->relhasindex = true;
1983  }
1984 
1985  /*
1986  * add new reldesc to relcache
1987  */
1988  RelationCacheInsert(relation, false);
1989 
1990  /* It's fully valid */
1991  relation->rd_isvalid = true;
1992 }
signed short int16
Definition: c.h:416
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:44
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#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:104
Form_pg_class rd_rel
Definition: rel.h:110
struct RelationData * Relation
Definition: relcache.h:27
int32 tdtypmod
Definition: tupdesc.h:83
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1279
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:103
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:106
#define InvalidBackendId
Definition: backendid.h:23
void * palloc0(Size size)
Definition: mcxt.c:981
const struct TableAmRoutine * rd_tableam
Definition: rel.h:172
TupleDesc rd_att
Definition: rel.h:111
#define InvalidOid
Definition: postgres_ext.h:36
#define RelationCacheInsert(RELATION, replace_allowed)
Definition: relcache.c:189
#define CLASS_TUPLE_SIZE
Definition: pg_class.h:145
BackendId rd_backend
Definition: rel.h:59
#define InvalidSubTransactionId
Definition: c.h:581
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:394
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:457
SubTransactionId rd_droppedSubid
Definition: rel.h:108
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 4224 of file relcache.c.

References BuildHardcodedDescriptor(), and Desc_pg_class.

Referenced by RelationParseRelOptions().

4225 {
4226  static TupleDesc pgclassdesc = NULL;
4227 
4228  /* Already done? */
4229  if (pgclassdesc == NULL)
4230  pgclassdesc = BuildHardcodedDescriptor(Natts_pg_class,
4231  Desc_pg_class);
4232 
4233  return pgclassdesc;
4234 }
static TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:4194
static const FormData_pg_attribute Desc_pg_class[Natts_pg_class]
Definition: relcache.c:109

◆ GetPgIndexDescriptor()

static TupleDesc GetPgIndexDescriptor ( void  )
static

Definition at line 4237 of file relcache.c.

References BuildHardcodedDescriptor(), and Desc_pg_index.

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

4238 {
4239  static TupleDesc pgindexdesc = NULL;
4240 
4241  /* Already done? */
4242  if (pgindexdesc == NULL)
4243  pgindexdesc = BuildHardcodedDescriptor(Natts_pg_index,
4244  Desc_pg_index);
4245 
4246  return pgindexdesc;
4247 }
static const FormData_pg_attribute Desc_pg_index[Natts_pg_index]
Definition: relcache.c:116
static TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:4194

◆ GetRelationPublicationActions()

struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

Definition at line 5318 of file relcache.c.

References CacheMemoryContext, elog, ERROR, get_partition_ancestors(), 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, RelationData::rd_rel, RelationGetRelid, ReleaseSysCache(), and SearchSysCache1().

Referenced by CheckCmdReplicaIdentity().

5319 {
5320  List *puboids;
5321  ListCell *lc;
5322  MemoryContext oldcxt;
5323  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5324 
5325  /*
5326  * If not publishable, it publishes no actions. (pgoutput_change() will
5327  * ignore it.)
5328  */
5329  if (!is_publishable_relation(relation))
5330  return pubactions;
5331 
5332  if (relation->rd_pubactions)
5333  return memcpy(pubactions, relation->rd_pubactions,
5334  sizeof(PublicationActions));
5335 
5336  /* Fetch the publication membership info. */
5337  puboids = GetRelationPublications(RelationGetRelid(relation));
5338  if (relation->rd_rel->relispartition)
5339  {
5340  /* Add publications that the ancestors are in too. */
5341  List *ancestors = get_partition_ancestors(RelationGetRelid(relation));
5342  ListCell *lc;
5343 
5344  foreach(lc, ancestors)
5345  {
5346  Oid ancestor = lfirst_oid(lc);
5347 
5348  puboids = list_concat_unique_oid(puboids,
5349  GetRelationPublications(ancestor));
5350  }
5351  }
5352  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5353 
5354  foreach(lc, puboids)
5355  {
5356  Oid pubid = lfirst_oid(lc);
5357  HeapTuple tup;
5358  Form_pg_publication pubform;
5359 
5361 
5362  if (!HeapTupleIsValid(tup))
5363  elog(ERROR, "cache lookup failed for publication %u", pubid);
5364 
5365  pubform = (Form_pg_publication) GETSTRUCT(tup);
5366 
5367  pubactions->pubinsert |= pubform->pubinsert;
5368  pubactions->pubupdate |= pubform->pubupdate;
5369  pubactions->pubdelete |= pubform->pubdelete;
5370  pubactions->pubtruncate |= pubform->pubtruncate;
5371 
5372  ReleaseSysCache(tup);
5373 
5374  /*
5375  * If we know everything is replicated, there is no point to check for
5376  * other publications.
5377  */
5378  if (pubactions->pubinsert && pubactions->pubupdate &&
5379  pubactions->pubdelete && pubactions->pubtruncate)
5380  break;
5381  }
5382 
5383  if (relation->rd_pubactions)
5384  {
5385  pfree(relation->rd_pubactions);
5386  relation->rd_pubactions = NULL;
5387  }
5388 
5389  /* Now save copy of the actions in the relcache entry. */
5391  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5392  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5393  MemoryContextSwitchTo(oldcxt);
5394 
5395  return pubactions;
5396 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
PublicationActions * rd_pubactions
Definition: rel.h:151
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Form_pg_class rd_rel
Definition: rel.h:110
unsigned int Oid
Definition: postgres_ext.h:31
List * GetRelationPublications(Oid relid)
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
List * list_concat_unique_oid(List *list1, const List *list2)
Definition: list.c:1316
bool is_publishable_relation(Relation rel)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void * palloc0(Size size)
Definition: mcxt.c:981
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
List * GetAllTablesPublications(void)
void * palloc(Size size)
Definition: mcxt.c:950
#define elog(elevel,...)
Definition: elog.h:228
FormData_pg_publication * Form_pg_publication
Definition: pg_list.h:50
List * get_partition_ancestors(Oid relid)
Definition: partition.c:115
#define RelationGetRelid(relation)
Definition: rel.h:457
#define lfirst_oid(lc)
Definition: pg_list.h:171
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 1555 of file relcache.c.

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

Referenced by RelationInitIndexAccessInfo().

1561 {
1562  int attIndex;
1563 
1564  for (attIndex = 0; attIndex < maxAttributeNumber; attIndex++)
1565  {
1566  OpClassCacheEnt *opcentry;
1567 
1568  if (!OidIsValid(indclass->values[attIndex]))
1569  elog(ERROR, "bogus pg_index tuple");
1570 
1571  /* look up the info for this opclass, using a cache */
1572  opcentry = LookupOpclassInfo(indclass->values[attIndex],
1573  maxSupportNumber);
1574 
1575  /* copy cached data into relcache entry */
1576  opFamily[attIndex] = opcentry->opcfamily;
1577  opcInType[attIndex] = opcentry->opcintype;
1578  if (maxSupportNumber > 0)
1579  memcpy(&indexSupport[attIndex * maxSupportNumber],
1580  opcentry->supportProcs,
1581  maxSupportNumber * sizeof(RegProcedure));
1582  }
1583 }
regproc RegProcedure
Definition: c.h:573
#define OidIsValid(objectId)
Definition: c.h:698
#define ERROR
Definition: elog.h:45
RegProcedure * supportProcs
Definition: relcache.c:248
static OpClassCacheEnt * LookupOpclassInfo(Oid operatorClassOid, StrategyNumber numSupport)
Definition: relcache.c:1606
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:656
#define elog(elevel,...)
Definition: elog.h:228

◆ InitIndexAmRoutine()

static void InitIndexAmRoutine ( Relation  relation)
static

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

1362 {
1363  IndexAmRoutine *cached,
1364  *tmp;
1365 
1366  /*
1367  * Call the amhandler in current, short-lived memory context, just in case
1368  * it leaks anything (it probably won't, but let's be paranoid).
1369  */
1370  tmp = GetIndexAmRoutine(relation->rd_amhandler);
1371 
1372  /* OK, now transfer the data into relation's rd_indexcxt. */
1373  cached = (IndexAmRoutine *) MemoryContextAlloc(relation->rd_indexcxt,
1374  sizeof(IndexAmRoutine));
1375  memcpy(cached, tmp, sizeof(IndexAmRoutine));
1376  relation->rd_indam = cached;
1377 
1378  pfree(tmp);
1379 }
struct IndexAmRoutine * rd_indam
Definition: rel.h:189
void pfree(void *pointer)
Definition: mcxt.c:1057
Oid rd_amhandler
Definition: rel.h:167
IndexAmRoutine * GetIndexAmRoutine(Oid amhandler)
Definition: amapi.c:33
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:797
MemoryContext rd_indexcxt
Definition: rel.h:187

◆ InitTableAmRoutine()

static void InitTableAmRoutine ( Relation  relation)
static

Definition at line 1756 of file relcache.c.

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

Referenced by RelationInitTableAccessMethod().

1757 {
1758  relation->rd_tableam = GetTableAmRoutine(relation->rd_amhandler);
1759 }
Oid rd_amhandler
Definition: rel.h:167
const TableAmRoutine * GetTableAmRoutine(Oid amhandler)
Definition: tableamapi.c:34
const struct TableAmRoutine * rd_tableam
Definition: rel.h:172

◆ load_critical_index()

static void load_critical_index ( Oid  indexoid,
Oid  heapoid 
)
static

Definition at line 4158 of file relcache.c.

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

Referenced by RelationCacheInitializePhase3().

4159 {
4160  Relation ird;
4161 
4162  /*
4163  * We must lock the underlying catalog before locking the index to avoid
4164  * deadlock, since RelationBuildDesc might well need to read the catalog,
4165  * and if anyone else is exclusive-locking this catalog and index they'll
4166  * be doing it in that order.
4167  */
4168  LockRelationOid(heapoid, AccessShareLock);
4169  LockRelationOid(indexoid, AccessShareLock);
4170  ird = RelationBuildDesc(indexoid, true);
4171  if (ird == NULL)
4172  elog(PANIC, "could not open critical system index %u", indexoid);
4173  ird->rd_isnailed = true;
4174  ird->rd_refcnt = 1;
4177 
4178  (void) RelationGetIndexAttOptions(ird, false);
4179 }
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:55
static Relation RelationBuildDesc(Oid targetRelId, bool insertIt)
Definition: relcache.c:1029
int rd_refcnt
Definition: rel.h:58
#define elog(elevel,...)
Definition: elog.h:228
bytea ** RelationGetIndexAttOptions(Relation relation, bool copy)
Definition: relcache.c:5448
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 5627 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, RelationData::rd_version_checked, 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().

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

◆ LookupOpclassInfo()

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

Definition at line 1606 of file relcache.c.

References AccessMethodProcedureIndexId, AccessShareLock, Assert, BTEqualStrategyNumber, CacheMemoryContext, CreateCacheMemoryContext(), criticalRelcachesBuilt, debug_invalidate_system_caches_always, elog, HASHCTL::entrysize, ERROR, GETSTRUCT, HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), HeapTupleIsValid, HASHCTL::keysize, MemoryContextAllocZero(), 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().

1608 {
1609  OpClassCacheEnt *opcentry;
1610  bool found;
1611  Relation rel;
1612  SysScanDesc scan;
1613  ScanKeyData skey[3];
1614  HeapTuple htup;
1615  bool indexOK;
1616 
1617  if (OpClassCache == NULL)
1618  {
1619  /* First time through: initialize the opclass cache */
1620  HASHCTL ctl;
1621 
1622  ctl.keysize = sizeof(Oid);
1623  ctl.entrysize = sizeof(OpClassCacheEnt);
1624  OpClassCache = hash_create("Operator class cache", 64,
1625  &ctl, HASH_ELEM | HASH_BLOBS);
1626 
1627  /* Also make sure CacheMemoryContext exists */
1628  if (!CacheMemoryContext)
1630  }
1631 
1632  opcentry = (OpClassCacheEnt *) hash_search(OpClassCache,
1633  (void *) &operatorClassOid,
1634  HASH_ENTER, &found);
1635 
1636  if (!found)
1637  {
1638  /* Need to allocate memory for new entry */
1639  opcentry->valid = false; /* until known OK */
1640  opcentry->numSupport = numSupport;
1641 
1642  if (numSupport > 0)
1643  opcentry->supportProcs = (RegProcedure *)
1645  (numSupport + 1) * sizeof(RegProcedure));
1646  else
1647  opcentry->supportProcs = NULL;
1648  }
1649  else
1650  {
1651  Assert(numSupport == opcentry->numSupport);
1652  }
1653 
1654  /*
1655  * When testing for cache-flush hazards, we intentionally disable the
1656  * operator class cache and force reloading of the info on each call. This
1657  * is helpful because we want to test the case where a cache flush occurs
1658  * while we are loading the info, and it's very hard to provoke that if
1659  * this happens only once per opclass per backend.
1660  */
1661 #ifdef CLOBBER_CACHE_ENABLED
1663  opcentry->valid = false;
1664 #endif
1665 
1666  if (opcentry->valid)
1667  return opcentry;
1668 
1669  /*
1670  * Need to fill in new entry.
1671  *
1672  * To avoid infinite recursion during startup, force heap scans if we're
1673  * looking up info for the opclasses used by the indexes we would like to
1674  * reference here.
1675  */
1676  indexOK = criticalRelcachesBuilt ||
1677  (operatorClassOid != OID_BTREE_OPS_OID &&
1678  operatorClassOid != INT2_BTREE_OPS_OID);
1679 
1680  /*
1681  * We have to fetch the pg_opclass row to determine its opfamily and
1682  * opcintype, which are needed to look up related operators and functions.
1683  * It'd be convenient to use the syscache here, but that probably doesn't
1684  * work while bootstrapping.
1685  */
1686  ScanKeyInit(&skey[0],
1687  Anum_pg_opclass_oid,
1688  BTEqualStrategyNumber, F_OIDEQ,
1689  ObjectIdGetDatum(operatorClassOid));
1690  rel = table_open(OperatorClassRelationId, AccessShareLock);
1691  scan = systable_beginscan(rel, OpclassOidIndexId, indexOK,
1692  NULL, 1, skey);
1693 
1694  if (HeapTupleIsValid(htup = systable_getnext(scan)))
1695  {
1696  Form_pg_opclass opclassform = (Form_pg_opclass) GETSTRUCT(htup);
1697 
1698  opcentry->opcfamily = opclassform->opcfamily;
1699  opcentry->opcintype = opclassform->opcintype;
1700  }
1701  else
1702  elog(ERROR, "could not find tuple for opclass %u", operatorClassOid);
1703 
1704  systable_endscan(scan);
1706 
1707  /*
1708  * Scan pg_amproc to obtain support procs for the opclass. We only fetch
1709  * the default ones (those with lefttype = righttype = opcintype).
1710  */
1711  if (numSupport > 0)
1712  {
1713  ScanKeyInit(&skey[0],
1714  Anum_pg_amproc_amprocfamily,
1715  BTEqualStrategyNumber, F_OIDEQ,
1716  ObjectIdGetDatum(opcentry->opcfamily));
1717  ScanKeyInit(&skey[1],
1718  Anum_pg_amproc_amproclefttype,
1719  BTEqualStrategyNumber, F_OIDEQ,
1720  ObjectIdGetDatum(opcentry->opcintype));
1721  ScanKeyInit(&skey[2],
1722  Anum_pg_amproc_amprocrighttype,
1723  BTEqualStrategyNumber, F_OIDEQ,
1724  ObjectIdGetDatum(opcentry->opcintype));
1725  rel = table_open(AccessMethodProcedureRelationId, AccessShareLock);
1726  scan = systable_beginscan(rel, AccessMethodProcedureIndexId, indexOK,
1727  NULL, 3, skey);
1728 
1729  while (HeapTupleIsValid(htup = systable_getnext(scan)))
1730  {
1731  Form_pg_amproc amprocform = (Form_pg_amproc) GETSTRUCT(htup);
1732 
1733  if (amprocform->amprocnum <= 0 ||
1734  (StrategyNumber) amprocform->amprocnum > numSupport)
1735  elog(ERROR, "invalid amproc number %d for opclass %u",
1736  amprocform->amprocnum, operatorClassOid);
1737 
1738  opcentry->supportProcs[amprocform->amprocnum - 1] =
1739  amprocform->amproc;
1740  }
1741 
1742  systable_endscan(scan);
1744  }
1745 
1746  opcentry->valid = true;
1747  return opcentry;
1748 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
struct opclasscacheent OpClassCacheEnt
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:593
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define HASH_ELEM
Definition: hsearch.h:95
FormData_pg_amproc * Form_pg_amproc
Definition: pg_amproc.h:68
regproc RegProcedure
Definition: c.h:573
#define AccessShareLock
Definition: lockdefs.h:36
Size entrysize
Definition: hsearch.h:76
uint16 StrategyNumber
Definition: stratnum.h:22
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
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:381
StrategyNumber numSupport
Definition: relcache.c:245
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:500
int debug_invalidate_system_caches_always
Definition: inval.c:184
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
RegProcedure * supportProcs
Definition: relcache.c:248
static HTAB * OpClassCache
Definition: relcache.c:251
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
#define OpclassOidIndexId
Definition: pg_opclass.h:88
#define HASH_BLOBS
Definition: hsearch.h:97
#define AccessMethodProcedureIndexId
Definition: pg_amproc.h:71
Size keysize
Definition: hsearch.h:75
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:840
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:792
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
#define elog(elevel,...)
Definition: elog.h:228
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
bool criticalRelcachesBuilt
Definition: relcache.c:138
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 3751 of file relcache.c.

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

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

3752 {
3755  relation->rd_firstRelfilenodeSubid = relation->rd_newRelfilenodeSubid;
3756 
3757  /* Flag relation as needing eoxact cleanup (to clear these fields) */
3758  EOXactListAdd(relation);
3759 }
#define EOXactListAdd(rel)
Definition: relcache.c:169
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:104
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:106
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:723
#define InvalidSubTransactionId
Definition: c.h:581

◆ RelationBuildDesc()

static Relation RelationBuildDesc ( Oid  targetRelId,
bool  insertIt 
)
static

Definition at line 1029 of file relcache.c.

References AllocateRelationDesc(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, BackendIdForTempRelations, CurrentMemoryContext, debug_invalidate_system_caches_always, elog, ERROR, GETSTRUCT, GetTempNamespaceBackendId(), heap_freetuple(), HeapTupleIsValid, InvalidBackendId, InvalidOid, InvalidSubTransactionId, 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_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, RECOVER_RELATION_BUILD_MEMORY, RelationBuildRowSecurity(), RelationBuildRuleLock(), RelationBuildTriggers(), RelationBuildTupleDesc(), RelationCacheInsert, RelationGetRelid, RelationInitIndexAccessInfo(), RelationInitLockInfo(), RelationInitPhysicalAddr(), RelationInitTableAccessMethod(), RelationParseRelOptions(), ScanPgRelation(), and RelationData::trigdesc.

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

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

◆ 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 3356 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().

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

737 {
738  MemoryContext rulescxt;
739  MemoryContext oldcxt;
740  HeapTuple rewrite_tuple;
741  Relation rewrite_desc;
742  TupleDesc rewrite_tupdesc;
743  SysScanDesc rewrite_scan;
745  RuleLock *rulelock;
746  int numlocks;
747  RewriteRule **rules;
748  int maxlocks;
749 
750  /*
751  * Make the private context. Assume it'll not contain much data.
752  */
754  "relation rules",
756  relation->rd_rulescxt = rulescxt;
758  RelationGetRelationName(relation));
759 
760  /*
761  * allocate an array to hold the rewrite rules (the array is extended if
762  * necessary)
763  */
764  maxlocks = 4;
765  rules = (RewriteRule **)
766  MemoryContextAlloc(rulescxt, sizeof(RewriteRule *) * maxlocks);
767  numlocks = 0;
768 
769  /*
770  * form a scan key
771  */
772  ScanKeyInit(&key,
773  Anum_pg_rewrite_ev_class,
774  BTEqualStrategyNumber, F_OIDEQ,
776 
777  /*
778  * open pg_rewrite and begin a scan
779  *
780  * Note: since we scan the rules using RewriteRelRulenameIndexId, we will
781  * be reading the rules in name order, except possibly during
782  * emergency-recovery operations (ie, IgnoreSystemIndexes). This in turn
783  * ensures that rules will be fired in name order.
784  */
785  rewrite_desc = table_open(RewriteRelationId, AccessShareLock);
786  rewrite_tupdesc = RelationGetDescr(rewrite_desc);
787  rewrite_scan = systable_beginscan(rewrite_desc,
789  true, NULL,
790  1, &key);
791 
792  while (HeapTupleIsValid(rewrite_tuple = systable_getnext(rewrite_scan)))
793  {
794  Form_pg_rewrite rewrite_form = (Form_pg_rewrite) GETSTRUCT(rewrite_tuple);
795  bool isnull;
796  Datum rule_datum;
797  char *rule_str;
798  RewriteRule *rule;
799 
800  rule = (RewriteRule *) MemoryContextAlloc(rulescxt,
801  sizeof(RewriteRule));
802 
803  rule->ruleId = rewrite_form->oid;
804 
805  rule->event = rewrite_form->ev_type - '0';
806  rule->enabled = rewrite_form->ev_enabled;
807  rule->isInstead = rewrite_form->is_instead;
808 
809  /*
810  * Must use heap_getattr to fetch ev_action and ev_qual. Also, the
811  * rule strings are often large enough to be toasted. To avoid
812  * leaking memory in the caller's context, do the detoasting here so
813  * we can free the detoasted version.
814  */
815  rule_datum = heap_getattr(rewrite_tuple,
816  Anum_pg_rewrite_ev_action,
817  rewrite_tupdesc,
818  &isnull);
819  Assert(!isnull);
820  rule_str = TextDatumGetCString(rule_datum);
821  oldcxt = MemoryContextSwitchTo(rulescxt);
822  rule->actions = (List *) stringToNode(rule_str);
823  MemoryContextSwitchTo(oldcxt);
824  pfree(rule_str);
825 
826  rule_datum = heap_getattr(rewrite_tuple,
827  Anum_pg_rewrite_ev_qual,
828  rewrite_tupdesc,
829  &isnull);
830  Assert(!isnull);
831  rule_str = TextDatumGetCString(rule_datum);
832  oldcxt = MemoryContextSwitchTo(rulescxt);
833  rule->qual = (Node *) stringToNode(rule_str);
834  MemoryContextSwitchTo(oldcxt);
835  pfree(rule_str);
836 
837  /*
838  * We want the rule's table references to be checked as though by the
839  * table owner, not the user referencing the rule. Therefore, scan
840  * through the rule's actions and set the checkAsUser field on all
841  * rtable entries. We have to look at the qual as well, in case it
842  * contains sublinks.
843  *
844  * The reason for doing this when the rule is loaded, rather than when
845  * it is stored, is that otherwise ALTER TABLE OWNER would have to
846  * grovel through stored rules to update checkAsUser fields. Scanning
847  * the rule tree during load is relatively cheap (compared to
848  * constructing it in the first place), so we do it here.
849  */
850  setRuleCheckAsUser((Node *) rule->actions, relation->rd_rel->relowner);
851  setRuleCheckAsUser(rule->qual, relation->rd_rel->relowner);
852 
853  if (numlocks >= maxlocks)
854  {
855  maxlocks *= 2;
856  rules = (RewriteRule **)
857  repalloc(rules, sizeof(RewriteRule *) * maxlocks);
858  }
859  rules[numlocks++] = rule;
860  }
861 
862  /*
863  * end the scan and close the attribute relation
864  */
865  systable_endscan(rewrite_scan);
866  table_close(rewrite_desc, AccessShareLock);
867 
868  /*
869  * there might not be any rules (if relhasrules is out-of-date)
870  */
871  if (numlocks == 0)
872  {
873  relation->rd_rules = NULL;
874  relation->rd_rulescxt = NULL;
875  MemoryContextDelete(rulescxt);
876  return;
877  }
878 
879  /*
880  * form a RuleLock and insert into relation
881  */
882  rulelock = (RuleLock *) MemoryContextAlloc(rulescxt, sizeof(RuleLock));
883  rulelock->numLocks = numlocks;
884  rulelock->rules = rules;
885 
886  relation->rd_rules = rulelock;
887 }
Node * qual
Definition: prs2lock.h:28
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:212
#define AllocSetContextCreate
Definition: memutils.h:170
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:593
#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:483
#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:528
void * stringToNode(const char *str)
Definition: read.c:89
MemoryContext rd_rulescxt
Definition: rel.h:115
Form_pg_class rd_rel
Definition: rel.h:110
bool isInstead
Definition: prs2lock.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:381
Definition: localtime.c:72
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:500
void pfree(void *pointer)
Definition: mcxt.c:1057
#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:281
#define RelationGetRelationName(relation)
Definition: rel.h:491
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:83
uintptr_t Datum
Definition: postgres.h:367
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:792
#define RewriteRelRulenameIndexId
Definition: pg_rewrite.h:59
RuleLock * rd_rules
Definition: rel.h:114
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1070
FormData_pg_rewrite * Form_pg_rewrite
Definition: pg_rewrite.h:52
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:797
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:457
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 498 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().

499 {
500  HeapTuple pg_attribute_tuple;
501  Relation pg_attribute_desc;
502  SysScanDesc pg_attribute_scan;
503  ScanKeyData skey[2];
504  int need;
505  TupleConstr *constr;
506  AttrDefault *attrdef = NULL;
507  AttrMissing *attrmiss = NULL;
508  int ndef = 0;
509 
510  /* fill rd_att's type ID fields (compare heap.c's AddNewRelationTuple) */
511  relation->rd_att->tdtypeid =
512  relation->rd_rel->reltype ? relation->rd_rel->reltype : RECORDOID;
513  relation->rd_att->tdtypmod = -1; /* just to be sure */
514 
516  sizeof(TupleConstr));
517  constr->has_not_null = false;
518  constr->has_generated_stored = false;
519 
520  /*
521  * Form a scan key that selects only user attributes (attnum > 0).
522  * (Eliminating system attribute rows at the index level is lots faster
523  * than fetching them.)
524  */
525  ScanKeyInit(&skey[0],
526  Anum_pg_attribute_attrelid,
527  BTEqualStrategyNumber, F_OIDEQ,
529  ScanKeyInit(&skey[1],
530  Anum_pg_attribute_attnum,
531  BTGreaterStrategyNumber, F_INT2GT,
532  Int16GetDatum(0));
533 
534  /*
535  * Open pg_attribute and begin a scan. Force heap scan if we haven't yet
536  * built the critical relcache entries (this includes initdb and startup
537  * without a pg_internal.init file).
538  */
539  pg_attribute_desc = table_open(AttributeRelationId, AccessShareLock);
540  pg_attribute_scan = systable_beginscan(pg_attribute_desc,
543  NULL,
544  2, skey);
545 
546  /*
547  * add attribute data to relation->rd_att
548  */
549  need = RelationGetNumberOfAttributes(relation);
550 
551  while (HeapTupleIsValid(pg_attribute_tuple = systable_getnext(pg_attribute_scan)))
552  {
553  Form_pg_attribute attp;
554  int attnum;
555 
556  attp = (Form_pg_attribute) GETSTRUCT(pg_attribute_tuple);
557 
558  attnum = attp->attnum;
559  if (attnum <= 0 || attnum > RelationGetNumberOfAttributes(relation))
560  elog(ERROR, "invalid attribute number %d for %s",
561  attp->attnum, RelationGetRelationName(relation));
562 
563 
564  memcpy(TupleDescAttr(relation->rd_att, attnum - 1),
565  attp,
567 
568  /* Update constraint/default info */
569  if (attp->attnotnull)
570  constr->has_not_null = true;
571  if (attp->attgenerated == ATTRIBUTE_GENERATED_STORED)
572  constr->has_generated_stored = true;
573 
574  /* If the column has a default, fill it into the attrdef array */
575  if (attp->atthasdef)
576  {
577  if (attrdef == NULL)
578  attrdef = (AttrDefault *)
581  sizeof(AttrDefault));
582  attrdef[ndef].adnum = attnum;
583  attrdef[ndef].adbin = NULL;
584 
585  ndef++;
586  }
587 
588  /* Likewise for a missing value */
589  if (attp->atthasmissing)
590  {
591  Datum missingval;
592  bool missingNull;
593 
594  /* Do we have a missing value? */
595  missingval = heap_getattr(pg_attribute_tuple,
596  Anum_pg_attribute_attmissingval,
597  pg_attribute_desc->rd_att,
598  &missingNull);
599  if (!missingNull)
600  {
601  /* Yes, fetch from the array */
602  MemoryContext oldcxt;
603  bool is_null;
604  int one = 1;
605  Datum missval;
606 
607  if (attrmiss == NULL)
608  attrmiss = (AttrMissing *)
610  relation->rd_rel->relnatts *
611  sizeof(AttrMissing));
612 
613  missval = array_get_element(missingval,
614  1,
615  &one,
616  -1,
617  attp->attlen,
618  attp->attbyval,
619  attp->attalign,
620  &is_null);
621  Assert(!is_null);
622  if (attp->attbyval)
623  {
624  /* for copy by val just copy the datum direct */
625  attrmiss[attnum - 1].am_value = missval;
626  }
627  else
628  {
629  /* otherwise copy in the correct context */
631  attrmiss[attnum - 1].am_value = datumCopy(missval,
632  attp->attbyval,
633  attp->attlen);
634  MemoryContextSwitchTo(oldcxt);
635  }
636  attrmiss[attnum - 1].am_present = true;
637  }
638  }
639  need--;
640  if (need == 0)
641  break;
642  }
643 
644  /*
645  * end the scan and close the attribute relation
646  */
647  systable_endscan(pg_attribute_scan);
648  table_close(pg_attribute_desc, AccessShareLock);
649 
650  if (need != 0)
651  elog(ERROR, "catalog is missing %d attribute(s) for relid %u",
652  need, RelationGetRelid(relation));
653 
654  /*
655  * The attcacheoff values we read from pg_attribute should all be -1
656  * ("unknown"). Verify this if assert checking is on. They will be
657  * computed when and if needed during tuple access.
658  */
659 #ifdef USE_ASSERT_CHECKING
660  {
661  int i;
662 
663  for (i = 0; i < RelationGetNumberOfAttributes(relation); i++)
664  Assert(TupleDescAttr(relation->rd_att, i)->attcacheoff == -1);
665  }
666 #endif
667 
668  /*
669  * However, we can easily set the attcacheoff value for the first
670  * attribute: it must be zero. This eliminates the need for special cases
671  * for attnum=1 that used to exist in fastgetattr() and index_getattr().
672  */
673  if (RelationGetNumberOfAttributes(relation) > 0)
674  TupleDescAttr(relation->rd_att, 0)->attcacheoff = 0;
675 
676  /*
677  * Set up constraint/default info
678  */
679  if (constr->has_not_null ||
680  constr->has_generated_stored ||
681  ndef > 0 ||
682  attrmiss ||
683  relation->rd_rel->relchecks)
684  {
685  relation->rd_att->constr = constr;
686 
687  if (ndef > 0) /* DEFAULTs */
688  {
689  if (ndef < RelationGetNumberOfAttributes(relation))
690  constr->defval = (AttrDefault *)
691  repalloc(attrdef, ndef * sizeof(AttrDefault));
692  else
693  constr->defval = attrdef;
694  constr->num_defval = ndef;
695  AttrDefaultFetch(relation);
696  }
697  else
698  constr->num_defval = 0;
699 
700  constr->missing = attrmiss;
701 
702  if (relation->rd_rel->relchecks > 0) /* CHECKs */
703  {
704  constr->num_check = relation->rd_rel->relchecks;
705  constr->check = (ConstrCheck *)
707  constr->num_check * sizeof(ConstrCheck));
708  CheckConstraintFetch(relation);
709  }
710  else
711  constr->num_check = 0;
712  }
713  else
714  {
715  pfree(constr);
716  relation->rd_att->constr = NULL;
717  }
718 }
static void AttrDefaultFetch(Relation relation)
Definition: relcache.c:4253
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:593
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:463
#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:110
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:381
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:500
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
int32 tdtypmod
Definition: tupdesc.h:83
#define AttributeRelidNumIndexId
Definition: pg_attribute.h:198
TupleConstr * constr
Definition: tupdesc.h:85
#define RelationGetRelationName(relation)
Definition: rel.h:491
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:111
uint16 num_check
Definition: tupdesc.h:43
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:840
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:1841
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:792
static void CheckConstraintFetch(Relation relation)
Definition: relcache.c:4323
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1070
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:797
#define elog(elevel,...)
Definition: elog.h:228
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:138
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:457
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInitFilePostInvalidate()

void RelationCacheInitFilePostInvalidate ( void  )

Definition at line 6336 of file relcache.c.

References LWLockRelease().

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

6337 {
6338  LWLockRelease(RelCacheInitLock);
6339 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )

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

6312 {
6313  char localinitfname[MAXPGPATH];
6314  char sharedinitfname[MAXPGPATH];
6315 
6316  if (DatabasePath)
6317  snprintf(localinitfname, sizeof(localinitfname), "%s/%s",
6319  snprintf(sharedinitfname, sizeof(sharedinitfname), "global/%s",
6321 
6322  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6323 
6324  /*
6325  * The files might not be there if no backend has been started since the
6326  * last removal. But complain about failures other than ENOENT with
6327  * ERROR. Fortunately, it's not too late to abort the transaction if we
6328  * can't get rid of the would-be-obsolete init file.
6329  */
6330  if (DatabasePath)
6331  unlink_initfile(localinitfname, ERROR);
6332  unlink_initfile(sharedinitfname, ERROR);
6333 }
#define ERROR
Definition: elog.h:45
#define MAXPGPATH
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25
char * DatabasePath
Definition: globals.c:94
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6408
#define snprintf
Definition: port.h:215

◆ RelationCacheInitFileRemove()

void RelationCacheInitFileRemove ( void  )

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

6352 {
6353  const char *tblspcdir = "pg_tblspc";
6354  DIR *dir;
6355  struct dirent *de;
6356  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6357 
6358  snprintf(path, sizeof(path), "global/%s",
6360  unlink_initfile(path, LOG);
6361 
6362  /* Scan everything in the default tablespace */
6364 
6365  /* Scan the tablespace link directory to find non-default tablespaces */
6366  dir = AllocateDir(tblspcdir);
6367 
6368  while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6369  {
6370  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6371  {
6372  /* Scan the tablespace dir for per-database dirs */
6373  snprintf(path, sizeof(path), "%s/%s/%s",
6374  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6376  }
6377  }
6378 
6379  FreeDir(dir);
6380 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6384
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2696
#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:2615
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6408
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:215
int FreeDir(DIR *dir)
Definition: fd.c:2733

◆ RelationCacheInitFileRemoveInDir()

static void RelationCacheInitFileRemoveInDir ( const char *  tblspcpath)
static

Definition at line 6384 of file relcache.c.

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

Referenced by RelationCacheInitFileRemove().

6385 {
6386  DIR *dir;
6387  struct dirent *de;
6388  char initfilename[MAXPGPATH * 2];
6389 
6390  /* Scan the tablespace directory to find per-database directories */
6391  dir = AllocateDir(tblspcpath);
6392 
6393  while ((de = ReadDirExtended(dir, tblspcpath, LOG)) != NULL)
6394  {
6395  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6396  {
6397  /* Try to remove the init file in each database */
6398  snprintf(initfilename, sizeof(initfilename), "%s/%s/%s",
6399  tblspcpath, de->d_name, RELCACHE_INIT_FILENAME);
6400  unlink_initfile(initfilename, LOG);
6401  }
6402  }
6403 
6404  FreeDir(dir);
6405 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2696
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2615
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6408
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:215
int FreeDir(DIR *dir)
Definition: fd.c:2733

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 3777 of file relcache.c.

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

Referenced by InitPostgres().

3778 {
3779  HASHCTL ctl;
3780 
3781  /*
3782  * make sure cache memory context exists
3783  */
3784  if (!CacheMemoryContext)
3786 
3787  /*
3788  * create hashtable that indexes the relcache
3789  */
3790  ctl.keysize = sizeof(Oid);
3791  ctl.entrysize = sizeof(RelIdCacheEnt);
3792  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3793  &ctl, HASH_ELEM | HASH_BLOBS);
3794 
3795  /*
3796  * relation mapper needs to be initialized too
3797  */
3799 }
void RelationMapInitialize(void)
Definition: relmapper.c:584
#define HASH_ELEM
Definition: hsearch.h:95
struct relidcacheent RelIdCacheEnt
Size entrysize
Definition: hsearch.h:76
static HTAB * RelationIdCache
Definition: relcache.c:132
unsigned int Oid
Definition: postgres_ext.h:31
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
#define HASH_BLOBS
Definition: hsearch.h:97
Size keysize
Definition: hsearch.h:75
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
#define INITRELCACHESIZE
Definition: relcache.c:3774
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInitializePhase2()

void RelationCacheInitializePhase2 ( void  )

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

3814 {
3815  MemoryContext oldcxt;
3816 
3817  /*
3818  * relation mapper needs initialized too
3819  */
3821 
3822  /*
3823  * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3824  * nothing.
3825  */
3827  return;
3828 
3829  /*
3830  * switch to cache memory context
3831  */
3833 
3834  /*
3835  * Try to load the shared relcache cache file. If unsuccessful, bootstrap
3836  * the cache with pre-made descriptors for the critical shared catalogs.
3837  */
3838  if (!load_relcache_init_file(true))
3839  {
3840  formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
3841  Natts_pg_database, Desc_pg_database);
3842  formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
3843  Natts_pg_authid, Desc_pg_authid);
3844  formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
3845  Natts_pg_auth_members, Desc_pg_auth_members);
3846  formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
3847  Natts_pg_shseclabel, Desc_pg_shseclabel);
3848  formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
3849  Natts_pg_subscription, Desc_pg_subscription);
3850 
3851 #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
3852  }
3853 
3854  MemoryContextSwitchTo(oldcxt);
3855 }
static const FormData_pg_attribute Desc_pg_auth_members[Natts_pg_auth_members]
Definition: relcache.c:115
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5627
void RelationMapInitializePhase2(void)
Definition: relmapper.c:604
static const FormData_pg_attribute Desc_pg_authid[Natts_pg_authid]
Definition: relcache.c:114
static const FormData_pg_attribute Desc_pg_subscription[Natts_pg_subscription]
Definition: relcache.c:118
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static const FormData_pg_attribute Desc_pg_database[Natts_pg_database]
Definition: relcache.c:113
static const FormData_pg_attribute Desc_pg_shseclabel[Natts_pg_shseclabel]
Definition: relcache.c:117
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:394
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1829
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInitializePhase3()

void RelationCacheInitializePhase3 ( void  )

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

3873 {
3875  RelIdCacheEnt *idhentry;
3876  MemoryContext oldcxt;
3877  bool needNewCacheFile = !criticalSharedRelcachesBuilt;
3878 
3879  /*
3880  * relation mapper needs initialized too
3881  */
3883 
3884  /*
3885  * switch to cache memory context
3886  */
3888 
3889  /*
3890  * Try to load the local relcache cache file. If unsuccessful, bootstrap
3891  * the cache with pre-made descriptors for the critical "nailed-in" system
3892  * catalogs.
3893  */
3894  if (IsBootstrapProcessingMode() ||
3895  !load_relcache_init_file(false))
3896  {
3897  needNewCacheFile = true;
3898 
3899  formrdesc("pg_class", RelationRelation_Rowtype_Id, false,
3900  Natts_pg_class, Desc_pg_class);
3901  formrdesc("pg_attribute", AttributeRelation_Rowtype_Id, false,
3902  Natts_pg_attribute, Desc_pg_attribute);
3903  formrdesc("pg_proc", ProcedureRelation_Rowtype_Id, false,
3904  Natts_pg_proc, Desc_pg_proc);
3905  formrdesc("pg_type", TypeRelation_Rowtype_Id, false,
3906  Natts_pg_type, Desc_pg_type);
3907 
3908 #define NUM_CRITICAL_LOCAL_RELS 4 /* fix if you change list above */
3909  }
3910 
3911  MemoryContextSwitchTo(oldcxt);
3912 
3913  /* In bootstrap mode, the faked-up formrdesc info is all we'll have */
3915  return;
3916 
3917  /*
3918  * If we didn't get the critical system indexes loaded into relcache, do
3919  * so now. These are critical because the catcache and/or opclass cache
3920  * depend on them for fetches done during relcache load. Thus, we have an
3921  * infinite-recursion problem. We can break the recursion by doing
3922  * heapscans instead of indexscans at certain key spots. To avoid hobbling
3923  * performance, we only want to do that until we have the critical indexes
3924  * loaded into relcache. Thus, the flag criticalRelcachesBuilt is used to
3925  * decide whether to do heapscan or indexscan at the key spots, and we set
3926  * it true after we've loaded the critical indexes.
3927  *
3928  * The critical indexes are marked as "nailed in cache", partly to make it
3929  * easy for load_relcache_init_file to count them, but mainly because we
3930  * cannot flush and rebuild them once we've set criticalRelcachesBuilt to
3931  * true. (NOTE: perhaps it would be possible to reload them by
3932  * temporarily setting criticalRelcachesBuilt to false again. For now,
3933  * though, we just nail 'em in.)
3934  *
3935  * RewriteRelRulenameIndexId and TriggerRelidNameIndexId are not critical
3936  * in the same way as the others, because the critical catalogs don't
3937  * (currently) have any rules or triggers, and so these indexes can be
3938  * rebuilt without inducing recursion. However they are used during
3939  * relcache load when a rel does have rules or triggers, so we choose to
3940  * nail them for performance reasons.
3941  */
3943  {
3945  RelationRelationId);
3947  AttributeRelationId);
3949  IndexRelationId);
3951  OperatorClassRelationId);
3953  AccessMethodProcedureRelationId);
3955  RewriteRelationId);
3957  TriggerRelationId);
3958 
3959 #define NUM_CRITICAL_LOCAL_INDEXES 7 /* fix if you change list above */
3960 
3961  criticalRelcachesBuilt = true;
3962  }
3963 
3964  /*
3965  * Process critical shared indexes too.
3966  *
3967  * DatabaseNameIndexId isn't critical for relcache loading, but rather for
3968  * initial lookup of MyDatabaseId, without which we'll never find any
3969  * non-shared catalogs at all. Autovacuum calls InitPostgres with a
3970  * database OID, so it instead depends on DatabaseOidIndexId. We also
3971  * need to nail up some indexes on pg_authid and pg_auth_members for use
3972  * during client authentication. SharedSecLabelObjectIndexId isn't
3973  * critical for the core system, but authentication hooks might be
3974  * interested in it.
3975  */
3977  {
3979  DatabaseRelationId);
3981  DatabaseRelationId);
3983  AuthIdRelationId);
3985  AuthIdRelationId);
3987  AuthMemRelationId);
3989  SharedSecLabelRelationId);
3990 
3991 #define NUM_CRITICAL_SHARED_INDEXES 6 /* fix if you change list above */
3992 
3994  }
3995 
3996  /*
3997  * Now, scan all the relcache entries and update anything that might be
3998  * wrong in the results from formrdesc or the relcache cache file. If we
3999  * faked up relcache entries using formrdesc, then read the real pg_class
4000  * rows and replace the fake entries with them. Also, if any of the
4001  * relcache entries have rules, triggers, or security policies, load that
4002  * info the hard way since it isn't recorded in the cache file.
4003  *
4004  * Whenever we access the catalogs to read data, there is a possibility of
4005  * a shared-inval cache flush causing relcache entries to be removed.
4006  * Since hash_seq_search only guarantees to still work after the *current*
4007  * entry is removed, it's unsafe to continue the hashtable scan afterward.
4008  * We handle this by restarting the scan from scratch after each access.
4009  * This is theoretically O(N^2), but the number of entries that actually
4010  * need to be fixed is small enough that it doesn't matter.
4011  */
4012  hash_seq_init(&status, RelationIdCache);
4013 
4014  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
4015  {
4016  Relation relation = idhentry->reldesc;
4017  bool restart = false;
4018 
4019  /*
4020  * Make sure *this* entry doesn't get flushed while we work with it.
4021  */
4023 
4024  /*
4025  * If it's a faked-up entry, read the real pg_class tuple.
4026  */
4027  if (relation->rd_rel->relowner == InvalidOid)
4028  {
4029  HeapTuple htup;
4030  Form_pg_class relp;
4031 
4032  htup = SearchSysCache1(RELOID,
4033  ObjectIdGetDatum(RelationGetRelid(relation)));
4034  if (!HeapTupleIsValid(htup))
4035  elog(FATAL, "cache lookup failed for relation %u",
4036  RelationGetRelid(relation));
4037  relp = (Form_pg_class) GETSTRUCT(htup);
4038 
4039  /*
4040  * Copy tuple to relation->rd_rel. (See notes in
4041  * AllocateRelationDesc())
4042  */
4043  memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
4044 
4045  /* Update rd_options while we have the tuple */
4046  if (relation->rd_options)
4047  pfree(relation->rd_options);
4048  RelationParseRelOptions(relation, htup);
4049 
4050  /*
4051  * Check the values in rd_att were set up correctly. (We cannot
4052  * just copy them over now: formrdesc must have set up the rd_att
4053  * data correctly to start with, because it may already have been
4054  * copied into one or more catcache entries.)
4055  */
4056  Assert(relation->rd_att->tdtypeid == relp->reltype);
4057  Assert(relation->rd_att->tdtypmod == -1);
4058 
4059  ReleaseSysCache(htup);
4060 
4061  /* relowner had better be OK now, else we'll loop forever */
4062  if (relation->rd_rel->relowner == InvalidOid)
4063  elog(ERROR, "invalid relowner in pg_class entry for \"%s\"",
4064  RelationGetRelationName(relation));
4065 
4066  restart = true;
4067  }
4068 
4069  /*
4070  * Fix data that isn't saved in relcache cache file.
4071  *
4072  * relhasrules or relhastriggers could possibly be wrong or out of
4073  * date. If we don't actually find any rules or triggers, clear the
4074  * local copy of the flag so that we don't get into an infinite loop
4075  * here. We don't make any attempt to fix the pg_class entry, though.
4076  */
4077  if (relation->rd_rel->relhasrules && relation->rd_rules == NULL)
4078  {
4079  RelationBuildRuleLock(relation);
4080  if (relation->rd_rules == NULL)
4081  relation->rd_rel->relhasrules = false;
4082  restart = true;
4083  }
4084  if (relation->rd_rel->relhastriggers && relation->trigdesc == NULL)
4085  {
4086  RelationBuildTriggers(relation);
4087  if (relation->trigdesc == NULL)
4088  relation->rd_rel->relhastriggers = false;
4089  restart = true;
4090  }
4091 
4092  /*
4093  * Re-load the row security policies if the relation has them, since
4094  * they are not preserved in the cache. Note that we can never NOT
4095  * have a policy while relrowsecurity is true,
4096  * RelationBuildRowSecurity will create a single default-deny policy
4097  * if there is no policy defined in pg_policy.
4098  */
4099  if (relation->rd_rel->relrowsecurity && relation->rd_rsdesc == NULL)
4100  {
4101  RelationBuildRowSecurity(relation);
4102 
4103  Assert(relation->rd_rsdesc != NULL);
4104  restart = true;
4105  }
4106 
4107  /* Reload tableam data if needed */
4108  if (relation->rd_tableam == NULL &&
4109  (relation->rd_rel->relkind == RELKIND_RELATION ||
4110  relation->rd_rel->relkind == RELKIND_SEQUENCE ||
4111  relation->rd_rel->relkind == RELKIND_TOASTVALUE ||
4112  relation->rd_rel->relkind == RELKIND_MATVIEW))
4113  {
4115  Assert(relation->rd_tableam != NULL);
4116 
4117  restart = true;
4118  }
4119 
4120  /* Release hold on the relation */
4122 
4123  /* Now, restart the hashtable scan if needed */
4124  if (restart)
4125  {
4126  hash_seq_term(&status);
4127  hash_seq_init(&status, RelationIdCache);
4128  }
4129  }
4130 
4131  /*
4132  * Lastly, write out new relcache cache files if needed. We don't bother
4133  * to distinguish cases where only one of the two needs an update.
4134  */
4135  if (needNewCacheFile)
4136  {
4137  /*
4138  * Force all the catcaches to finish initializing and thereby open the
4139  * catalogs and indexes they use. This will preload the relcache with
4140  * entries for all the most important system catalogs and indexes, so
4141  * that the init files will be most useful for future backends.
4142  */
4144 
4145  /* now write the files */
4147  write_relcache_init_file(false);
4148  }
4149 }
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5627
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define TriggerRelidNameIndexId
Definition: pg_trigger.h:80
void RelationBuildRowSecurity(Relation relation)
Definition: policy.c:195
void RelationInitTableAccessMethod(Relation relation)
Definition: relcache.c:1765
#define IndexRelidIndexId
Definition: pg_index.h:73
Relation reldesc
Definition: relcache.c:129
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define DatabaseNameIndexId
Definition: pg_database.h:88
bool criticalSharedRelcachesBuilt
Definition: relcache.c:144
static HTAB * RelationIdCache
Definition: relcache.c:132
Form_pg_class rd_rel
Definition: rel.h:110
#define ClassOidIndexId
Definition: pg_class.h:156
#define SharedSecLabelObjectIndexId
Definition: pg_shseclabel.h:46
#define AuthMemMemRoleIndexId
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2103
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
int32 tdtypmod
Definition: tupdesc.h:83
#define FATAL
Definition: elog.h:54
static void write_relcache_init_file(bool shared)
Definition: relcache.c:6044
TriggerDesc * trigdesc
Definition: rel.h:116
static void RelationParseRelOptions(Relation relation, HeapTuple tuple)
Definition: relcache.c:441
#define AttributeRelidNumIndexId
Definition: pg_attribute.h:198
static void load_critical_index(Oid indexoid, Oid heapoid)
Definition: relcache.c:4158
static const FormData_pg_attribute Desc_pg_proc[Natts_pg_proc]
Definition: relcache.c:111
#define RelationGetRelationName(relation)
Definition: rel.h:491
#define OpclassOidIndexId
Definition: pg_opclass.h:88
struct RowSecurityDesc * rd_rsdesc
Definition: rel.h:118
#define DatabaseOidIndexId
Definition: pg_database.h:90
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2090
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define AccessMethodProcedureIndexId
Definition: pg_amproc.h:71
const struct TableAmRoutine * rd_tableam
Definition: rel.h:172
TupleDesc rd_att
Definition: rel.h:111
#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:792
#define RewriteRelRulenameIndexId
Definition: pg_rewrite.h:59
RuleLock * rd_rules
Definition: rel.h:114
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1436
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1426
#define AuthIdOidIndexId
Definition: pg_authid.h:65
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:394
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
Oid tdtypeid
Definition: tupdesc.h:82
void RelationBuildTriggers(Relation relation)
Definition: trigger.c:1644
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1829
static const FormData_pg_attribute Desc_pg_class[Natts_pg_class]
Definition: relcache.c:109
#define elog(elevel,...)
Definition: elog.h:228
void RelationMapInitializePhase3(void)
Definition: relmapper.c:625
static void RelationBuildRuleLock(Relation relation)
Definition: relcache.c:736
bool criticalRelcachesBuilt
Definition: relcache.c:138
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
void InitCatalogCachePhase2(void)
Definition: syscache.c:1086
#define AuthIdRolnameIndexId
Definition: pg_authid.h:63
#define RelationGetRelid(relation)
Definition: rel.h:457
static const FormData_pg_attribute Desc_pg_type[Natts_pg_type]
Definition: relcache.c:112
bytea * rd_options
Definition: rel.h:158
void hash_seq_term(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1512
static const FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute]
Definition: relcache.c:110
MemoryContext CacheMemoryContext
Definition: mcxt.c:47

◆ RelationCacheInvalidate()

void RelationCacheInvalidate ( void  )

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

2845 {
2847  RelIdCacheEnt *idhentry;
2848  Relation relation;
2849  List *rebuildFirstList = NIL;
2850  List *rebuildList = NIL;
2851  ListCell *l;
2852 
2853  /*
2854  * Reload relation mapping data before starting to reconstruct cache.
2855  */
2857 
2858  /* Phase 1 */
2859  hash_seq_init(&status, RelationIdCache);
2860 
2861  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2862  {
2863  relation = idhentry->reldesc;
2864 
2865  /* Must close all smgr references to avoid leaving dangling ptrs */
2866  RelationCloseSmgr(relation);
2867 
2868  /*
2869  * Ignore new relations; no other backend will manipulate them before
2870  * we commit. Likewise, before replacing a relation's relfilenode, we
2871  * shall have acquired AccessExclusiveLock and drained any applicable
2872  * pending invalidations.
2873  */
2874  if (relation->rd_createSubid != InvalidSubTransactionId ||
2876  continue;
2877 
2879 
2880  if (RelationHasReferenceCountZero(relation))
2881  {
2882  /* Delete this entry immediately */
2883  Assert(!relation->rd_isnailed);
2884  RelationClearRelation(relation, false);
2885  }
2886  else
2887  {
2888  /*
2889  * If it's a mapped relation, immediately update its rd_node in
2890  * case its relfilenode changed. We must do this during phase 1
2891  * in case the relation is consulted during rebuild of other
2892  * relcache entries in phase 2. It's safe since consulting the
2893  * map doesn't involve any access to relcache entries.
2894  */
2895  if (RelationIsMapped(relation))
2896  RelationInitPhysicalAddr(relation);
2897 
2898  /*
2899  * Add this entry to list of stuff to rebuild in second pass.
2900  * pg_class goes to the front of rebuildFirstList while
2901  * pg_class_oid_index goes to the back of rebuildFirstList, so
2902  * they are done first and second respectively. Other nailed
2903  * relations go to the front of rebuildList, so they'll be done
2904  * next in no particular order; and everything else goes to the
2905  * back of rebuildList.
2906  */
2907  if (RelationGetRelid(relation) == RelationRelationId)
2908  rebuildFirstList = lcons(relation, rebuildFirstList);
2909  else if (RelationGetRelid(relation) == ClassOidIndexId)
2910  rebuildFirstList = lappend(rebuildFirstList, relation);
2911  else if (relation->rd_isnailed)
2912  rebuildList = lcons(relation, rebuildList);
2913  else
2914  rebuildList = lappend(rebuildList, relation);
2915  }
2916  }
2917 
2918  /*
2919  * Now zap any remaining smgr cache entries. This must happen before we
2920  * start to rebuild entries, since that may involve catalog fetches which
2921  * will re-open catalog files.
2922  */
2923  smgrcloseall();
2924 
2925  /* Phase 2: rebuild the items found to need rebuild in phase 1 */
2926  foreach(l, rebuildFirstList)
2927  {
2928  relation = (Relation) lfirst(l);
2929  RelationClearRelation(relation, true);
2930  }
2931  list_free(rebuildFirstList);
2932  foreach(l, rebuildList)
2933  {
2934  relation = (Relation) lfirst(l);
2935  RelationClearRelation(relation, true);
2936  }
2937  list_free(rebuildList);
2938 }
#define NIL
Definition: pg_list.h:65
static long relcacheInvalsReceived
Definition: relcache.c:152
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2444
bool rd_isnailed
Definition: rel.h:61
Relation reldesc
Definition: relcache.c:129
#define RelationCloseSmgr(relation)
Definition: rel.h:526
static HTAB * RelationIdCache
Definition: relcache.c:132
#define ClassOidIndexId
Definition: pg_class.h:156
void smgrcloseall(void)
Definition: smgr.c:286
struct RelationData * Relation
Definition: relcache.h:27
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1279
List * lappend(List *list, void *datum)
Definition: list.c:336
#define RelationIsMapped(relation)
Definition: rel.h:506
SubTransactionId rd_createSubid
Definition: rel.h:103
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:106
List * lcons(void *datum, List *list)
Definition: list.c:468
#define Assert(condition)
Definition: c.h:792
#define lfirst(lc)
Definition: pg_list.h:169
#define InvalidSubTransactionId
Definition: c.h:581
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1436
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1426
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:441
void list_free(List *list)
Definition: list.c:1391
void RelationMapInvalidateAll(void)
Definition: relmapper.c:425
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:457

◆ RelationCacheInvalidateEntry()

void RelationCacheInvalidateEntry ( Oid  relationId)

Definition at line 2801 of file relcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

2802 {
2803  Relation relation;
2804 
2805  RelationIdCacheLookup(relationId, relation);
2806 
2807  if (PointerIsValid(relation))
2808  {
2810  RelationFlushRelation(relation);
2811  }
2812 }
static long relcacheInvalsReceived
Definition: relcache.c:152
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:211
static void RelationFlushRelation(Relation relation)
Definition: relcache.c:2724
#define PointerIsValid(pointer)
Definition: c.h:686

◆ RelationClearRelation()

static void RelationClearRelation ( Relation  relation,
bool  rebuild 
)
static

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

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