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, int ndef)
 
static int AttrDefaultCmp (const void *a, const void *b)
 
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 3750 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 387 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().

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

◆ AtEOSubXact_cleanup()

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

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

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

◆ AtEOSubXact_RelationCache()

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

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

3203 {
3205  RelIdCacheEnt *idhentry;
3206  int i;
3207 
3208  /*
3209  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3210  * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3211  * logic as in AtEOXact_RelationCache.
3212  */
3214  {
3215  hash_seq_init(&status, RelationIdCache);
3216  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3217  {
3218  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3219  mySubid, parentSubid);
3220  }
3221  }
3222  else
3223  {
3224  for (i = 0; i < eoxact_list_len; i++)
3225  {
3226  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3227  (void *) &eoxact_list[i],
3228  HASH_FIND,
3229  NULL);
3230  if (idhentry != NULL)
3231  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3232  mySubid, parentSubid);
3233  }
3234  }
3235 
3236  /* Don't reset the list; we still need more cleanup later */
3237 }
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:3248
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 3119 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().

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

◆ AtEOXact_RelationCache()

void AtEOXact_RelationCache ( bool  isCommit)

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

3057 {
3059  RelIdCacheEnt *idhentry;
3060  int i;
3061 
3062  /*
3063  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3064  * listed in it. Otherwise fall back on a hash_seq_search scan.
3065  *
3066  * For simplicity, eoxact_list[] entries are not deleted till end of
3067  * top-level transaction, even though we could remove them at
3068  * subtransaction end in some cases, or remove relations from the list if
3069  * they are cleared for other reasons. Therefore we should expect the
3070  * case that list entries are not found in the hashtable; if not, there's
3071  * nothing to do for them.
3072  */
3074  {
3075  hash_seq_init(&status, RelationIdCache);
3076  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3077  {
3078  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3079  }
3080  }
3081  else
3082  {
3083  for (i = 0; i < eoxact_list_len; i++)
3084  {
3085  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3086  (void *) &eoxact_list[i],
3087  HASH_FIND,
3088  NULL);
3089  if (idhentry != NULL)
3090  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3091  }
3092  }
3093 
3094  if (EOXactTupleDescArrayLen > 0)
3095  {
3096  Assert(EOXactTupleDescArray != NULL);
3097  for (i = 0; i < NextEOXactTupleDescNum; i++)
3100  EOXactTupleDescArray = NULL;
3101  }
3102 
3103  /* Now we're out of the transaction and can clear the lists */
3104  eoxact_list_len = 0;
3105  eoxact_list_overflowed = false;
3106  NextEOXactTupleDescNum = 0;
3108 }
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:3119
static bool eoxact_list_overflowed
Definition: relcache.c:167
static int NextEOXactTupleDescNum
Definition: relcache.c:183
void pfree(void *pointer)
Definition: mcxt.c:1169
#define Assert(condition)
Definition: c.h:804
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:309
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

◆ AttrDefaultCmp()

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

Definition at line 4315 of file relcache.c.

References AttrDefault::adnum.

Referenced by AttrDefaultFetch().

4316 {
4317  const AttrDefault *ada = (const AttrDefault *) a;
4318  const AttrDefault *adb = (const AttrDefault *) b;
4319 
4320  return ada->adnum - adb->adnum;
4321 }
AttrNumber adnum
Definition: tupdesc.h:24

◆ AttrDefaultFetch()

static void AttrDefaultFetch ( Relation  relation,
int  ndef 
)
static

Definition at line 4235 of file relcache.c.

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

Referenced by RelationBuildTupleDesc().

4236 {
4237  AttrDefault *attrdef;
4238  Relation adrel;
4239  SysScanDesc adscan;
4240  ScanKeyData skey;
4241  HeapTuple htup;
4242  int found = 0;
4243 
4244  /* Allocate array with room for as many entries as expected */
4245  attrdef = (AttrDefault *)
4247  ndef * sizeof(AttrDefault));
4248 
4249  /* Search pg_attrdef for relevant entries */
4250  ScanKeyInit(&skey,
4251  Anum_pg_attrdef_adrelid,
4252  BTEqualStrategyNumber, F_OIDEQ,
4253  ObjectIdGetDatum(RelationGetRelid(relation)));
4254 
4255  adrel = table_open(AttrDefaultRelationId, AccessShareLock);
4256  adscan = systable_beginscan(adrel, AttrDefaultIndexId, true,
4257  NULL, 1, &skey);
4258 
4259  while (HeapTupleIsValid(htup = systable_getnext(adscan)))
4260  {
4261  Form_pg_attrdef adform = (Form_pg_attrdef) GETSTRUCT(htup);
4262  Datum val;
4263  bool isnull;
4264 
4265  /* protect limited size of array */
4266  if (found >= ndef)
4267  {
4268  elog(WARNING, "unexpected pg_attrdef record found for attribute %d of relation \"%s\"",
4269  adform->adnum, RelationGetRelationName(relation));
4270  break;
4271  }
4272 
4273  val = fastgetattr(htup,
4274  Anum_pg_attrdef_adbin,
4275  adrel->rd_att, &isnull);
4276  if (isnull)
4277  elog(WARNING, "null adbin for attribute %d of relation \"%s\"",
4278  adform->adnum, RelationGetRelationName(relation));
4279  else
4280  {
4281  /* detoast and convert to cstring in caller's context */
4282  char *s = TextDatumGetCString(val);
4283 
4284  attrdef[found].adnum = adform->adnum;
4285  attrdef[found].adbin = MemoryContextStrdup(CacheMemoryContext, s);
4286  pfree(s);
4287  found++;
4288  }
4289  }
4290 
4291  systable_endscan(adscan);
4292  table_close(adrel, AccessShareLock);
4293 
4294  if (found != ndef)
4295  elog(WARNING, "%d pg_attrdef record(s) missing for relation \"%s\"",
4296  ndef - found, RelationGetRelationName(relation));
4297 
4298  /*
4299  * Sort the AttrDefault entries by adnum, for the convenience of
4300  * equalTupleDescs(). (Usually, they already will be in order, but this
4301  * might not be so if systable_getnext isn't using an index.)
4302  */
4303  if (found > 1)
4304  qsort(attrdef, found, sizeof(AttrDefault), AttrDefaultCmp);
4305 
4306  /* Install array only after it's fully valid */
4307  relation->rd_att->constr->defval = attrdef;
4308  relation->rd_att->constr->num_defval = found;
4309 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:711
#define AttrDefaultIndexId
Definition: pg_attrdef.h:53
#define AccessShareLock
Definition: lockdefs.h:36
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
AttrDefault * defval
Definition: tupdesc.h:39
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
TupleConstr * constr
Definition: tupdesc.h:85
#define RelationGetRelationName(relation)
Definition: rel.h:491
FormData_pg_attrdef * Form_pg_attrdef
Definition: pg_attrdef.h:48
#define WARNING
Definition: elog.h:40
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:411
TupleDesc rd_att
Definition: rel.h:111
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:906
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
uint16 num_defval
Definition: tupdesc.h:42
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1286
static int AttrDefaultCmp(const void *a, const void *b)
Definition: relcache.c:4315
#define elog(elevel,...)
Definition: elog.h:232
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
#define qsort(a, b, c, d)
Definition: port.h:504
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:51

◆ BuildHardcodedDescriptor()

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

Definition at line 4170 of file relcache.c.

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

Referenced by GetPgClassDescriptor(), and GetPgIndexDescriptor().

4171 {
4172  TupleDesc result;
4173  MemoryContext oldcxt;
4174  int i;
4175 
4177 
4178  result = CreateTemplateTupleDesc(natts);
4179  result->tdtypeid = RECORDOID; /* not right, but we don't care */
4180  result->tdtypmod = -1;
4181 
4182  for (i = 0; i < natts; i++)
4183  {
4184  memcpy(TupleDescAttr(result, i), &attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
4185  /* make sure attcacheoff is valid */
4186  TupleDescAttr(result, i)->attcacheoff = -1;
4187  }
4188 
4189  /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
4190  TupleDescAttr(result, 0)->attcacheoff = 0;
4191 
4192  /* Note: we don't bother to set up a TupleConstr entry */
4193 
4194  MemoryContextSwitchTo(oldcxt);
4195 
4196  return result;
4197 }
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:45
#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:195
Oid tdtypeid
Definition: tupdesc.h:82
int i
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ CheckConstraintCmp()

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

Definition at line 4419 of file relcache.c.

References ConstrCheck::ccname.

Referenced by CheckConstraintFetch().

4420 {
4421  const ConstrCheck *ca = (const ConstrCheck *) a;
4422  const ConstrCheck *cb = (const ConstrCheck *) b;
4423 
4424  return strcmp(ca->ccname, cb->ccname);
4425 }
char * ccname
Definition: tupdesc.h:30

◆ CheckConstraintFetch()

static void CheckConstraintFetch ( Relation  relation)
static

Definition at line 4330 of file relcache.c.

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

Referenced by RelationBuildTupleDesc().

4331 {
4332  ConstrCheck *check;
4333  int ncheck = relation->rd_rel->relchecks;
4334  Relation conrel;
4335  SysScanDesc conscan;
4336  ScanKeyData skey[1];
4337  HeapTuple htup;
4338  int found = 0;
4339 
4340  /* Allocate array with room for as many entries as expected */
4341  check = (ConstrCheck *)
4343  ncheck * sizeof(ConstrCheck));
4344 
4345  /* Search pg_constraint for relevant entries */
4346  ScanKeyInit(&skey[0],
4347  Anum_pg_constraint_conrelid,
4348  BTEqualStrategyNumber, F_OIDEQ,
4349  ObjectIdGetDatum(RelationGetRelid(relation)));
4350 
4351  conrel = table_open(ConstraintRelationId, AccessShareLock);
4352  conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
4353  NULL, 1, skey);
4354 
4355  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4356  {
4358  Datum val;
4359  bool isnull;
4360 
4361  /* We want check constraints only */
4362  if (conform->contype != CONSTRAINT_CHECK)
4363  continue;
4364 
4365  /* protect limited size of array */
4366  if (found >= ncheck)
4367  {
4368  elog(WARNING, "unexpected pg_constraint record found for relation \"%s\"",
4369  RelationGetRelationName(relation));
4370  break;
4371  }
4372 
4373  check[found].ccvalid = conform->convalidated;
4374  check[found].ccnoinherit = conform->connoinherit;
4376  NameStr(conform->conname));
4377 
4378  /* Grab and test conbin is actually set */
4379  val = fastgetattr(htup,
4380  Anum_pg_constraint_conbin,
4381  conrel->rd_att, &isnull);
4382  if (isnull)
4383  elog(WARNING, "null conbin for relation \"%s\"",
4384  RelationGetRelationName(relation));
4385  else
4386  {
4387  /* detoast and convert to cstring in caller's context */
4388  char *s = TextDatumGetCString(val);
4389 
4390  check[found].ccbin = MemoryContextStrdup(CacheMemoryContext, s);
4391  pfree(s);
4392  found++;
4393  }
4394  }
4395 
4396  systable_endscan(conscan);
4397  table_close(conrel, AccessShareLock);
4398 
4399  if (found != ncheck)
4400  elog(WARNING, "%d pg_constraint record(s) missing for relation \"%s\"",
4401  ncheck - found, RelationGetRelationName(relation));
4402 
4403  /*
4404  * Sort the records by name. This ensures that CHECKs are applied in a
4405  * deterministic order, and it also makes equalTupleDescs() faster.
4406  */
4407  if (found > 1)
4408  qsort(check, found, sizeof(ConstrCheck), CheckConstraintCmp);
4409 
4410  /* Install array only after it's fully valid */
4411  relation->rd_att->constr->check = check;
4412  relation->rd_att->constr->num_check = found;
4413 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:711
static int CheckConstraintCmp(const void *a, const void *b)
Definition: relcache.c:4419
#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:383
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ConstraintRelidTypidNameIndexId
TupleConstr * constr
Definition: tupdesc.h:85
char * ccname
Definition: tupdesc.h:30
#define RelationGetRelationName(relation)
Definition: rel.h:491
#define WARNING
Definition: elog.h:40
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:411
TupleDesc rd_att
Definition: rel.h:111
uint16 num_check
Definition: tupdesc.h:43
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:906
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1286
#define elog(elevel,...)
Definition: elog.h:232
#define NameStr(name)
Definition: c.h:681
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:504
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:51

◆ CopyIndexAttOptions()

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

Definition at line 5453 of file relcache.c.

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

Referenced by RelationGetIndexAttOptions().

5454 {
5455  bytea **opts = palloc(sizeof(*opts) * natts);
5456 
5457  for (int i = 0; i < natts; i++)
5458  {
5459  bytea *opt = srcopts[i];
5460 
5461  opts[i] = !opt ? NULL : (bytea *)
5462  DatumGetPointer(datumCopy(PointerGetDatum(opt), false, -1));
5463  }
5464 
5465  return opts;
5466 }
#define PointerGetDatum(X)
Definition: postgres.h:600
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:131
static AmcheckOptions opts
Definition: pg_amcheck.c:103
#define DatumGetPointer(X)
Definition: postgres.h:593
void * palloc(Size size)
Definition: mcxt.c:1062
int i
Definition: c.h:621

◆ equalPolicy()

static bool equalPolicy ( RowSecurityPolicy policy1,
RowSecurityPolicy policy2 
)
static

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

916 {
917  int i;
918  Oid *r1,
919  *r2;
920 
921  if (policy1 != NULL)
922  {
923  if (policy2 == NULL)
924  return false;
925 
926  if (policy1->polcmd != policy2->polcmd)
927  return false;
928  if (policy1->hassublinks != policy2->hassublinks)
929  return false;
930  if (strcmp(policy1->policy_name, policy2->policy_name) != 0)
931  return false;
932  if (ARR_DIMS(policy1->roles)[0] != ARR_DIMS(policy2->roles)[0])
933  return false;
934 
935  r1 = (Oid *) ARR_DATA_PTR(policy1->roles);
936  r2 = (Oid *) ARR_DATA_PTR(policy2->roles);
937 
938  for (i = 0; i < ARR_DIMS(policy1->roles)[0]; i++)
939  {
940  if (r1[i] != r2[i])
941  return false;
942  }
943 
944  if (!equal(policy1->qual, policy2->qual))
945  return false;
946  if (!equal(policy1->with_check_qual, policy2->with_check_qual))
947  return false;
948  }
949  else if (policy2 != NULL)
950  return false;
951 
952  return true;
953 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3105
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 961 of file relcache.c.

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

Referenced by RelationClearRelation().

962 {
963  ListCell *lc,
964  *rc;
965 
966  if (rsdesc1 == NULL && rsdesc2 == NULL)
967  return true;
968 
969  if ((rsdesc1 != NULL && rsdesc2 == NULL) ||
970  (rsdesc1 == NULL && rsdesc2 != NULL))
971  return false;
972 
973  if (list_length(rsdesc1->policies) != list_length(rsdesc2->policies))
974  return false;
975 
976  /* RelationBuildRowSecurity should build policies in order */
977  forboth(lc, rsdesc1->policies, rc, rsdesc2->policies)
978  {
981 
982  if (!equalPolicy(l, r))
983  return false;
984  }
985 
986  return true;
987 }
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:446
static bool equalPolicy(RowSecurityPolicy *policy1, RowSecurityPolicy *policy2)
Definition: relcache.c:915
#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 870 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().

871 {
872  int i;
873 
874  /*
875  * As of 7.3 we assume the rule ordering is repeatable, because
876  * RelationBuildRuleLock should read 'em in a consistent order. So just
877  * compare corresponding slots.
878  */
879  if (rlock1 != NULL)
880  {
881  if (rlock2 == NULL)
882  return false;
883  if (rlock1->numLocks != rlock2->numLocks)
884  return false;
885  for (i = 0; i < rlock1->numLocks; i++)
886  {
887  RewriteRule *rule1 = rlock1->rules[i];
888  RewriteRule *rule2 = rlock2->rules[i];
889 
890  if (rule1->ruleId != rule2->ruleId)
891  return false;
892  if (rule1->event != rule2->event)
893  return false;
894  if (rule1->enabled != rule2->enabled)
895  return false;
896  if (rule1->isInstead != rule2->isInstead)
897  return false;
898  if (!equal(rule1->qual, rule2->qual))
899  return false;
900  if (!equal(rule1->actions, rule2->actions))
901  return false;
902  }
903  }
904  else if (rlock2 != NULL)
905  return false;
906  return true;
907 }
Node * qual
Definition: prs2lock.h:28
int numLocks
Definition: prs2lock.h:42
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3105
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 5534 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().

5535 {
5539 
5540  return 0; /* return value does not matter */
5541 }
#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:3316
#define RelationGetRelationName(relation)
Definition: rel.h:491
int err_generic_string(int field, const char *str)
Definition: elog.c:1351
#define RelationGetNamespace(relation)
Definition: rel.h:498

◆ errtablecol()

int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5551 of file relcache.c.

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

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

5552 {
5553  TupleDesc reldesc = RelationGetDescr(rel);
5554  const char *colname;
5555 
5556  /* Use reldesc if it's a user attribute, else consult the catalogs */
5557  if (attnum > 0 && attnum <= reldesc->natts)
5558  colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
5559  else
5560  colname = get_attname(RelationGetRelid(rel), attnum, false);
5561 
5562  return errtablecolname(rel, colname);
5563 }
#define RelationGetDescr(relation)
Definition: rel.h:483
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
NameData attname
Definition: pg_attribute.h:41
int16 attnum
Definition: pg_attribute.h:83
#define NameStr(name)
Definition: c.h:681
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:5575

◆ errtablecolname()

int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5575 of file relcache.c.

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

Referenced by errtablecol().

5576 {
5577  errtable(rel);
5579 
5580  return 0; /* return value does not matter */
5581 }
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:67
int err_generic_string(int field, const char *str)
Definition: elog.c:1351
int errtable(Relation rel)
Definition: relcache.c:5534

◆ errtableconstraint()

int errtableconstraint ( Relation  rel,
const char *  conname 
)

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

5589 {
5590  errtable(rel);
5592 
5593  return 0; /* return value does not matter */
5594 }
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:69
int err_generic_string(int field, const char *str)
Definition: elog.c:1351
int errtable(Relation rel)
Definition: relcache.c:5534

◆ formrdesc()

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

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

1805 {
1806  Relation relation;
1807  int i;
1808  bool has_not_null;
1809 
1810  /*
1811  * allocate new relation desc, clear all fields of reldesc
1812  */
1813  relation = (Relation) palloc0(sizeof(RelationData));
1814 
1815  /* make sure relation is marked as having no open file yet */
1816  relation->rd_smgr = NULL;
1817 
1818  /*
1819  * initialize reference count: 1 because it is nailed in cache
1820  */
1821  relation->rd_refcnt = 1;
1822 
1823  /*
1824  * all entries built with this routine are nailed-in-cache; none are for
1825  * new or temp relations.
1826  */
1827  relation->rd_isnailed = true;
1832  relation->rd_backend = InvalidBackendId;
1833  relation->rd_islocaltemp = false;
1834 
1835  /*
1836  * initialize relation tuple form
1837  *
1838  * The data we insert here is pretty incomplete/bogus, but it'll serve to
1839  * get us launched. RelationCacheInitializePhase3() will read the real
1840  * data from pg_class and replace what we've done here. Note in
1841  * particular that relowner is left as zero; this cues
1842  * RelationCacheInitializePhase3 that the real data isn't there yet.
1843  */
1845 
1846  namestrcpy(&relation->rd_rel->relname, relationName);
1847  relation->rd_rel->relnamespace = PG_CATALOG_NAMESPACE;
1848  relation->rd_rel->reltype = relationReltype;
1849 
1850  /*
1851  * It's important to distinguish between shared and non-shared relations,
1852  * even at bootstrap time, to make sure we know where they are stored.
1853  */
1854  relation->rd_rel->relisshared = isshared;
1855  if (isshared)
1856  relation->rd_rel->reltablespace = GLOBALTABLESPACE_OID;
1857 
1858  /* formrdesc is used only for permanent relations */
1859  relation->rd_rel->relpersistence = RELPERSISTENCE_PERMANENT;
1860 
1861  /* ... and they're always populated, too */
1862  relation->rd_rel->relispopulated = true;
1863 
1864  relation->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
1865  relation->rd_rel->relpages = 0;
1866  relation->rd_rel->reltuples = -1;
1867  relation->rd_rel->relallvisible = 0;
1868  relation->rd_rel->relkind = RELKIND_RELATION;
1869  relation->rd_rel->relnatts = (int16) natts;
1870  relation->rd_rel->relam = HEAP_TABLE_AM_OID;
1871 
1872  /*
1873  * initialize attribute tuple form
1874  *
1875  * Unlike the case with the relation tuple, this data had better be right
1876  * because it will never be replaced. The data comes from
1877  * src/include/catalog/ headers via genbki.pl.
1878  */
1879  relation->rd_att = CreateTemplateTupleDesc(natts);
1880  relation->rd_att->tdrefcount = 1; /* mark as refcounted */
1881 
1882  relation->rd_att->tdtypeid = relationReltype;
1883  relation->rd_att->tdtypmod = -1; /* just to be sure */
1884 
1885  /*
1886  * initialize tuple desc info
1887  */
1888  has_not_null = false;
1889  for (i = 0; i < natts; i++)
1890  {
1891  memcpy(TupleDescAttr(relation->rd_att, i),
1892  &attrs[i],
1894  has_not_null |= attrs[i].attnotnull;
1895  /* make sure attcacheoff is valid */
1896  TupleDescAttr(relation->rd_att, i)->attcacheoff = -1;
1897  }
1898 
1899  /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
1900  TupleDescAttr(relation->rd_att, 0)->attcacheoff = 0;
1901 
1902  /* mark not-null status */
1903  if (has_not_null)
1904  {
1905  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
1906 
1907  constr->has_not_null = true;
1908  relation->rd_att->constr = constr;
1909  }
1910 
1911  /*
1912  * initialize relation id from info in att array (my, this is ugly)
1913  */
1914  RelationGetRelid(relation) = TupleDescAttr(relation->rd_att, 0)->attrelid;
1915 
1916  /*
1917  * All relations made with formrdesc are mapped. This is necessarily so
1918  * because there is no other way to know what filenode they currently
1919  * have. In bootstrap mode, add them to the initial relation mapper data,
1920  * specifying that the initial filenode is the same as the OID.
1921  */
1922  relation->rd_rel->relfilenode = InvalidOid;
1925  RelationGetRelid(relation),
1926  isshared, true);
1927 
1928  /*
1929  * initialize the relation lock manager information
1930  */
1931  RelationInitLockInfo(relation); /* see lmgr.c */
1932 
1933  /*
1934  * initialize physical addressing information for the relation
1935  */
1936  RelationInitPhysicalAddr(relation);
1937 
1938  /*
1939  * initialize the table am handler
1940  */
1941  relation->rd_rel->relam = HEAP_TABLE_AM_OID;
1942  relation->rd_tableam = GetHeapamTableAmRoutine();
1943 
1944  /*
1945  * initialize the rel-has-index flag, using hardwired knowledge
1946  */
1948  {
1949  /* In bootstrap mode, we have no indexes */
1950  relation->rd_rel->relhasindex = false;
1951  }
1952  else
1953  {
1954  /* Otherwise, all the rels formrdesc is used for have indexes */
1955  relation->rd_rel->relhasindex = true;
1956  }
1957 
1958  /*
1959  * add new reldesc to relcache
1960  */
1961  RelationCacheInsert(relation, false);
1962 
1963  /* It's fully valid */
1964  relation->rd_isvalid = true;
1965 }
signed short int16
Definition: c.h:428
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:45
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:1252
void RelationInitLockInfo(Relation relation)
Definition: lmgr.c:72
TupleConstr * constr
Definition: tupdesc.h:85
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:195
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:1093
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:593
#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 4200 of file relcache.c.

References BuildHardcodedDescriptor(), and Desc_pg_class.

Referenced by RelationParseRelOptions().

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

◆ GetPgIndexDescriptor()

static TupleDesc GetPgIndexDescriptor ( void  )
static

Definition at line 4213 of file relcache.c.

References BuildHardcodedDescriptor(), and Desc_pg_index.

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

4214 {
4215  static TupleDesc pgindexdesc = NULL;
4216 
4217  /* Already done? */
4218  if (pgindexdesc == NULL)
4219  pgindexdesc = BuildHardcodedDescriptor(Natts_pg_index,
4220  Desc_pg_index);
4221 
4222  return pgindexdesc;
4223 }
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:4170

◆ GetRelationPublicationActions()

struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

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

5344 {
5345  List *puboids;
5346  ListCell *lc;
5347  MemoryContext oldcxt;
5348  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5349 
5350  /*
5351  * If not publishable, it publishes no actions. (pgoutput_change() will
5352  * ignore it.)
5353  */
5354  if (!is_publishable_relation(relation))
5355  return pubactions;
5356 
5357  if (relation->rd_pubactions)
5358  return memcpy(pubactions, relation->rd_pubactions,
5359  sizeof(PublicationActions));
5360 
5361  /* Fetch the publication membership info. */
5362  puboids = GetRelationPublications(RelationGetRelid(relation));
5363  if (relation->rd_rel->relispartition)
5364  {
5365  /* Add publications that the ancestors are in too. */
5366  List *ancestors = get_partition_ancestors(RelationGetRelid(relation));
5367  ListCell *lc;
5368 
5369  foreach(lc, ancestors)
5370  {
5371  Oid ancestor = lfirst_oid(lc);
5372 
5373  puboids = list_concat_unique_oid(puboids,
5374  GetRelationPublications(ancestor));
5375  }
5376  }
5377  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5378 
5379  foreach(lc, puboids)
5380  {
5381  Oid pubid = lfirst_oid(lc);
5382  HeapTuple tup;
5383  Form_pg_publication pubform;
5384 
5386 
5387  if (!HeapTupleIsValid(tup))
5388  elog(ERROR, "cache lookup failed for publication %u", pubid);
5389 
5390  pubform = (Form_pg_publication) GETSTRUCT(tup);
5391 
5392  pubactions->pubinsert |= pubform->pubinsert;
5393  pubactions->pubupdate |= pubform->pubupdate;
5394  pubactions->pubdelete |= pubform->pubdelete;
5395  pubactions->pubtruncate |= pubform->pubtruncate;
5396 
5397  ReleaseSysCache(tup);
5398 
5399  /*
5400  * If we know everything is replicated, there is no point to check for
5401  * other publications.
5402  */
5403  if (pubactions->pubinsert && pubactions->pubupdate &&
5404  pubactions->pubdelete && pubactions->pubtruncate)
5405  break;
5406  }
5407 
5408  if (relation->rd_pubactions)
5409  {
5410  pfree(relation->rd_pubactions);
5411  relation->rd_pubactions = NULL;
5412  }
5413 
5414  /* Now save copy of the actions in the relcache entry. */
5416  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5417  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5418  MemoryContextSwitchTo(oldcxt);
5419 
5420  return pubactions;
5421 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
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:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
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:1093
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:1062
#define elog(elevel,...)
Definition: elog.h:232
FormData_pg_publication * Form_pg_publication
Definition: pg_list.h:50
List * get_partition_ancestors(Oid relid)
Definition: partition.c:133
#define RelationGetRelid(relation)
Definition: rel.h:457
#define lfirst_oid(lc)
Definition: pg_list.h:171
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ IndexSupportInitialize()

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

Definition at line 1528 of file relcache.c.

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

Referenced by RelationInitIndexAccessInfo().

1534 {
1535  int attIndex;
1536 
1537  for (attIndex = 0; attIndex < maxAttributeNumber; attIndex++)
1538  {
1539  OpClassCacheEnt *opcentry;
1540 
1541  if (!OidIsValid(indclass->values[attIndex]))
1542  elog(ERROR, "bogus pg_index tuple");
1543 
1544  /* look up the info for this opclass, using a cache */
1545  opcentry = LookupOpclassInfo(indclass->values[attIndex],
1546  maxSupportNumber);
1547 
1548  /* copy cached data into relcache entry */
1549  opFamily[attIndex] = opcentry->opcfamily;
1550  opcInType[attIndex] = opcentry->opcintype;
1551  if (maxSupportNumber > 0)
1552  memcpy(&indexSupport[attIndex * maxSupportNumber],
1553  opcentry->supportProcs,
1554  maxSupportNumber * sizeof(RegProcedure));
1555  }
1556 }
regproc RegProcedure
Definition: c.h:585
#define OidIsValid(objectId)
Definition: c.h:710
#define ERROR
Definition: elog.h:46
RegProcedure * supportProcs
Definition: relcache.c:248
static OpClassCacheEnt * LookupOpclassInfo(Oid operatorClassOid, StrategyNumber numSupport)
Definition: relcache.c:1579
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:668
#define elog(elevel,...)
Definition: elog.h:232

◆ InitIndexAmRoutine()

static void InitIndexAmRoutine ( Relation  relation)
static

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

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

◆ InitTableAmRoutine()

static void InitTableAmRoutine ( Relation  relation)
static

Definition at line 1729 of file relcache.c.

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

Referenced by RelationInitTableAccessMethod().

1730 {
1731  relation->rd_tableam = GetTableAmRoutine(relation->rd_amhandler);
1732 }
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 4134 of file relcache.c.

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

Referenced by RelationCacheInitializePhase3().

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

◆ load_relcache_init_file()

static bool load_relcache_init_file ( bool  shared)
static

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

5653 {
5654  FILE *fp;
5655  char initfilename[MAXPGPATH];
5656  Relation *rels;
5657  int relno,
5658  num_rels,
5659  max_rels,
5660  nailed_rels,
5661  nailed_indexes,
5662  magic;
5663  int i;
5664 
5665  if (shared)
5666  snprintf(initfilename, sizeof(initfilename), "global/%s",
5668  else
5669  snprintf(initfilename, sizeof(initfilename), "%s/%s",
5671 
5672  fp = AllocateFile(initfilename, PG_BINARY_R);
5673  if (fp == NULL)
5674  return false;
5675 
5676  /*
5677  * Read the index relcache entries from the file. Note we will not enter
5678  * any of them into the cache if the read fails partway through; this
5679  * helps to guard against broken init files.
5680  */
5681  max_rels = 100;
5682  rels = (Relation *) palloc(max_rels * sizeof(Relation));
5683  num_rels = 0;
5684  nailed_rels = nailed_indexes = 0;
5685 
5686  /* check for correct magic number (compatible version) */
5687  if (fread(&magic, 1, sizeof(magic), fp) != sizeof(magic))
5688  goto read_failed;
5689  if (magic != RELCACHE_INIT_FILEMAGIC)
5690  goto read_failed;
5691 
5692  for (relno = 0;; relno++)
5693  {
5694  Size len;
5695  size_t nread;
5696  Relation rel;
5697  Form_pg_class relform;
5698  bool has_not_null;
5699 
5700  /* first read the relation descriptor length */
5701  nread = fread(&len, 1, sizeof(len), fp);
5702  if (nread != sizeof(len))
5703  {
5704  if (nread == 0)
5705  break; /* end of file */
5706  goto read_failed;
5707  }
5708 
5709  /* safety check for incompatible relcache layout */
5710  if (len != sizeof(RelationData))
5711  goto read_failed;
5712 
5713  /* allocate another relcache header */
5714  if (num_rels >= max_rels)
5715  {
5716  max_rels *= 2;
5717  rels = (Relation *) repalloc(rels, max_rels * sizeof(Relation));
5718  }
5719 
5720  rel = rels[num_rels++] = (Relation) palloc(len);
5721 
5722  /* then, read the Relation structure */
5723  if (fread(rel, 1, len, fp) != len)
5724  goto read_failed;
5725 
5726  /* next read the relation tuple form */
5727  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5728  goto read_failed;
5729 
5730  relform = (Form_pg_class) palloc(len);
5731  if (fread(relform, 1, len, fp) != len)
5732  goto read_failed;
5733 
5734  rel->rd_rel = relform;
5735 
5736  /* initialize attribute tuple forms */
5737  rel->rd_att = CreateTemplateTupleDesc(relform->relnatts);
5738  rel->rd_att->tdrefcount = 1; /* mark as refcounted */
5739 
5740  rel->rd_att->tdtypeid = relform->reltype ? relform->reltype : RECORDOID;
5741  rel->rd_att->tdtypmod = -1; /* just to be sure */
5742 
5743  /* next read all the attribute tuple form data entries */
5744  has_not_null = false;
5745  for (i = 0; i < relform->relnatts; i++)
5746  {
5747  Form_pg_attribute attr = TupleDescAttr(rel->rd_att, i);
5748 
5749  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5750  goto read_failed;
5751  if (len != ATTRIBUTE_FIXED_PART_SIZE)
5752  goto read_failed;
5753  if (fread(attr, 1, len, fp) != len)
5754  goto read_failed;
5755 
5756  has_not_null |= attr->attnotnull;
5757  }
5758 
5759  /* next read the access method specific field */
5760  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5761  goto read_failed;
5762  if (len > 0)
5763  {
5764  rel->rd_options = palloc(len);
5765  if (fread(rel->rd_options, 1, len, fp) != len)
5766  goto read_failed;
5767  if (len != VARSIZE(rel->rd_options))
5768  goto read_failed; /* sanity check */
5769  }
5770  else
5771  {
5772  rel->rd_options = NULL;
5773  }
5774 
5775  /* mark not-null status */
5776  if (has_not_null)
5777  {
5778  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
5779 
5780  constr->has_not_null = true;
5781  rel->rd_att->constr = constr;
5782  }
5783 
5784  /*
5785  * If it's an index, there's more to do. Note we explicitly ignore
5786  * partitioned indexes here.
5787  */
5788  if (rel->rd_rel->relkind == RELKIND_INDEX)
5789  {
5790  MemoryContext indexcxt;
5791  Oid *opfamily;
5792  Oid *opcintype;
5793  RegProcedure *support;
5794  int nsupport;
5795  int16 *indoption;
5796  Oid *indcollation;
5797 
5798  /* Count nailed indexes to ensure we have 'em all */
5799  if (rel->rd_isnailed)
5800  nailed_indexes++;
5801 
5802  /* next, read the pg_index tuple */
5803  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5804  goto read_failed;
5805 
5806  rel->rd_indextuple = (HeapTuple) palloc(len);
5807  if (fread(rel->rd_indextuple, 1, len, fp) != len)
5808  goto read_failed;
5809 
5810  /* Fix up internal pointers in the tuple -- see heap_copytuple */
5811  rel->rd_indextuple->t_data = (HeapTupleHeader) ((char *) rel->rd_indextuple + HEAPTUPLESIZE);
5813 
5814  /*
5815  * prepare index info context --- parameters should match
5816  * RelationInitIndexAccessInfo
5817  */
5819  "index info",
5821  rel->rd_indexcxt = indexcxt;
5824 
5825  /*
5826  * Now we can fetch the index AM's API struct. (We can't store
5827  * that in the init file, since it contains function pointers that
5828  * might vary across server executions. Fortunately, it should be
5829  * safe to call the amhandler even while bootstrapping indexes.)
5830  */
5831  InitIndexAmRoutine(rel);
5832 
5833  /* next, read the vector of opfamily OIDs */
5834  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5835  goto read_failed;
5836 
5837  opfamily = (Oid *) MemoryContextAlloc(indexcxt, len);
5838  if (fread(opfamily, 1, len, fp) != len)
5839  goto read_failed;
5840 
5841  rel->rd_opfamily = opfamily;
5842 
5843  /* next, read the vector of opcintype OIDs */
5844  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5845  goto read_failed;
5846 
5847  opcintype = (Oid *) MemoryContextAlloc(indexcxt, len);
5848  if (fread(opcintype, 1, len, fp) != len)
5849  goto read_failed;
5850 
5851  rel->rd_opcintype = opcintype;
5852 
5853  /* next, read the vector of support procedure OIDs */
5854  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5855  goto read_failed;
5856  support = (RegProcedure *) MemoryContextAlloc(indexcxt, len);
5857  if (fread(support, 1, len, fp) != len)
5858  goto read_failed;
5859 
5860  rel->rd_support = support;
5861 
5862  /* next, read the vector of collation OIDs */
5863  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5864  goto read_failed;
5865 
5866  indcollation = (Oid *) MemoryContextAlloc(indexcxt, len);
5867  if (fread(indcollation, 1, len, fp) != len)
5868  goto read_failed;
5869 
5870  rel->rd_indcollation = indcollation;
5871 
5872  /* finally, read the vector of indoption values */
5873  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5874  goto read_failed;
5875 
5876  indoption = (int16 *) MemoryContextAlloc(indexcxt, len);
5877  if (fread(indoption, 1, len, fp) != len)
5878  goto read_failed;
5879 
5880  rel->rd_indoption = indoption;
5881 
5882  /* finally, read the vector of opcoptions values */
5883  rel->rd_opcoptions = (bytea **)
5884  MemoryContextAllocZero(indexcxt, sizeof(*rel->rd_opcoptions) * relform->relnatts);
5885 
5886  for (i = 0; i < relform->relnatts; i++)
5887  {
5888  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5889  goto read_failed;
5890 
5891  if (len > 0)
5892  {
5893  rel->rd_opcoptions[i] = (bytea *) MemoryContextAlloc(indexcxt, len);
5894  if (fread(rel->rd_opcoptions[i], 1, len, fp) != len)
5895  goto read_failed;
5896  }
5897  }
5898 
5899  /* set up zeroed fmgr-info vector */
5900  nsupport = relform->relnatts * rel->rd_indam->amsupport;
5901  rel->rd_supportinfo = (FmgrInfo *)
5902  MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
5903  }
5904  else
5905  {
5906  /* Count nailed rels to ensure we have 'em all */
5907  if (rel->rd_isnailed)
5908  nailed_rels++;
5909 
5910  /* Load table AM data */
5911  if (rel->rd_rel->relkind == RELKIND_RELATION ||
5912  rel->rd_rel->relkind == RELKIND_SEQUENCE ||
5913  rel->rd_rel->relkind == RELKIND_TOASTVALUE ||
5914  rel->rd_rel->relkind == RELKIND_MATVIEW)
5916 
5917  Assert(rel->rd_index == NULL);
5918  Assert(rel->rd_indextuple == NULL);
5919  Assert(rel->rd_indexcxt == NULL);
5920  Assert(rel->rd_indam == NULL);
5921  Assert(rel->rd_opfamily == NULL);
5922  Assert(rel->rd_opcintype == NULL);
5923  Assert(rel->rd_support == NULL);
5924  Assert(rel->rd_supportinfo == NULL);
5925  Assert(rel->rd_indoption == NULL);
5926  Assert(rel->rd_indcollation == NULL);
5927  Assert(rel->rd_opcoptions == NULL);
5928  }
5929 
5930  /*
5931  * Rules and triggers are not saved (mainly because the internal
5932  * format is complex and subject to change). They must be rebuilt if
5933  * needed by RelationCacheInitializePhase3. This is not expected to
5934  * be a big performance hit since few system catalogs have such. Ditto
5935  * for RLS policy data, partition info, index expressions, predicates,
5936  * exclusion info, and FDW info.
5937  */
5938  rel->rd_rules = NULL;
5939  rel->rd_rulescxt = NULL;
5940  rel->trigdesc = NULL;
5941  rel->rd_rsdesc = NULL;
5942  rel->rd_partkey = NULL;
5943  rel->rd_partkeycxt = NULL;
5944  rel->rd_partdesc = NULL;
5945  rel->rd_pdcxt = NULL;
5946  rel->rd_partcheck = NIL;
5947  rel->rd_partcheckvalid = false;
5948  rel->rd_partcheckcxt = NULL;
5949  rel->rd_indexprs = NIL;
5950  rel->rd_indpred = NIL;
5951  rel->rd_exclops = NULL;
5952  rel->rd_exclprocs = NULL;
5953  rel->rd_exclstrats = NULL;
5954  rel->rd_fdwroutine = NULL;
5955 
5956  /*
5957  * Reset transient-state fields in the relcache entry
5958  */
5959  rel->rd_smgr = NULL;
5960  if (rel->rd_isnailed)
5961  rel->rd_refcnt = 1;
5962  else
5963  rel->rd_refcnt = 0;
5964  rel->rd_indexvalid = false;
5965  rel->rd_indexlist = NIL;
5966  rel->rd_pkindex = InvalidOid;
5967  rel->rd_replidindex = InvalidOid;
5968  rel->rd_indexattr = NULL;
5969  rel->rd_keyattr = NULL;
5970  rel->rd_pkattr = NULL;
5971  rel->rd_idattr = NULL;
5972  rel->rd_pubactions = NULL;
5973  rel->rd_statvalid = false;
5974  rel->rd_version_checked = false;
5975  rel->rd_statlist = NIL;
5976  rel->rd_fkeyvalid = false;
5977  rel->rd_fkeylist = NIL;
5982  rel->rd_amcache = NULL;
5983  MemSet(&rel->pgstat_info, 0, sizeof(rel->pgstat_info));
5984 
5985  /*
5986  * Recompute lock and physical addressing info. This is needed in
5987  * case the pg_internal.init file was copied from some other database
5988  * by CREATE DATABASE.
5989  */
5990  RelationInitLockInfo(rel);
5992  }
5993 
5994  /*
5995  * We reached the end of the init file without apparent problem. Did we
5996  * get the right number of nailed items? This is a useful crosscheck in
5997  * case the set of critical rels or indexes changes. However, that should
5998  * not happen in a normally-running system, so let's bleat if it does.
5999  *
6000  * For the shared init file, we're called before client authentication is
6001  * done, which means that elog(WARNING) will go only to the postmaster
6002  * log, where it's easily missed. To ensure that developers notice bad
6003  * values of NUM_CRITICAL_SHARED_RELS/NUM_CRITICAL_SHARED_INDEXES, we put
6004  * an Assert(false) there.
6005  */
6006  if (shared)
6007  {
6008  if (nailed_rels != NUM_CRITICAL_SHARED_RELS ||
6009  nailed_indexes != NUM_CRITICAL_SHARED_INDEXES)
6010  {
6011  elog(WARNING, "found %d nailed shared rels and %d nailed shared indexes in init file, but expected %d and %d respectively",
6012  nailed_rels, nailed_indexes,
6014  /* Make sure we get developers' attention about this */
6015  Assert(false);
6016  /* In production builds, recover by bootstrapping the relcache */
6017  goto read_failed;
6018  }
6019  }
6020  else
6021  {
6022  if (nailed_rels != NUM_CRITICAL_LOCAL_RELS ||
6023  nailed_indexes != NUM_CRITICAL_LOCAL_INDEXES)
6024  {
6025  elog(WARNING, "found %d nailed rels and %d nailed indexes in init file, but expected %d and %d respectively",
6026  nailed_rels, nailed_indexes,
6028  /* We don't need an Assert() in this case */
6029  goto read_failed;
6030  }
6031  }
6032 
6033  /*
6034  * OK, all appears well.
6035  *
6036  * Now insert all the new relcache entries into the cache.
6037  */
6038  for (relno = 0; relno < num_rels; relno++)
6039  {
6040  RelationCacheInsert(rels[relno], false);
6041  }
6042 
6043  pfree(rels);
6044  FreeFile(fp);
6045 
6046  if (shared)
6048  else
6049  criticalRelcachesBuilt = true;
6050  return true;
6051 
6052  /*
6053  * init file is broken, so do it the hard way. We don't bother trying to
6054  * free the clutter we just allocated; it's not in the relcache so it
6055  * won't hurt.
6056  */
6057 read_failed:
6058  pfree(rels);
6059  FreeFile(fp);
6060 
6061  return false;
6062 }
struct FdwRoutine * rd_fdwroutine
Definition: rel.h:223
signed short int16
Definition: c.h:428
#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:173
HeapTupleData * HeapTuple
Definition: htup.h:71
int16 * rd_indoption
Definition: rel.h:194
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
PublicationActions * rd_pubactions
Definition: rel.h:151
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:45
struct FmgrInfo * rd_supportinfo
Definition: rel.h:193
Bitmapset * rd_keyattr
Definition: rel.h:147
#define VARSIZE(PTR)
Definition: postgres.h:316
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
void RelationInitTableAccessMethod(Relation relation)
Definition: relcache.c:1738
#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:205
bool rd_isnailed
Definition: rel.h:61
regproc RegProcedure
Definition: c.h:585
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:1008
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:1273
#define NUM_CRITICAL_SHARED_RELS
static void InitIndexAmRoutine(Relation relation)
Definition: relcache.c:1334
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:1169
#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:1252
void RelationInitLockInfo(Relation relation)
Definition: lmgr.c:72
#define MemoryContextCopyAndSetIdentifier(cxt, id)
Definition: memutils.h:98
TupleConstr * constr
Definition: tupdesc.h:85
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2373
#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:203
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:195
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:69
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:1093
TupleDesc rd_att
Definition: rel.h:111
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:906
#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:96
MemoryContext rd_pdcxt
Definition: rel.h:130
#define Assert(condition)
Definition: c.h:804
MemoryContext rd_partkeycxt
Definition: rel.h:126
RuleLock * rd_rules
Definition: rel.h:114
size_t Size
Definition: c.h:540
struct PgStat_TableStatus * pgstat_info
Definition: rel.h:237
#define InvalidSubTransactionId
Definition: c.h:593
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
int FreeFile(FILE *file)
Definition: fd.c:2572
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:1062
int rd_refcnt
Definition: rel.h:58
#define HEAPTUPLESIZE
Definition: htup.h:73
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
#define elog(elevel,...)
Definition: elog.h:232
MemoryContext rd_indexcxt
Definition: rel.h:187
int i
int tdrefcount
Definition: tupdesc.h:84
Definition: c.h:621
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:216
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:51

◆ LookupOpclassInfo()

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

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

1581 {
1582  OpClassCacheEnt *opcentry;
1583  bool found;
1584  Relation rel;
1585  SysScanDesc scan;
1586  ScanKeyData skey[3];
1587  HeapTuple htup;
1588  bool indexOK;
1589 
1590  if (OpClassCache == NULL)
1591  {
1592  /* First time through: initialize the opclass cache */
1593  HASHCTL ctl;
1594 
1595  ctl.keysize = sizeof(Oid);
1596  ctl.entrysize = sizeof(OpClassCacheEnt);
1597  OpClassCache = hash_create("Operator class cache", 64,
1598  &ctl, HASH_ELEM | HASH_BLOBS);
1599 
1600  /* Also make sure CacheMemoryContext exists */
1601  if (!CacheMemoryContext)
1603  }
1604 
1605  opcentry = (OpClassCacheEnt *) hash_search(OpClassCache,
1606  (void *) &operatorClassOid,
1607  HASH_ENTER, &found);
1608 
1609  if (!found)
1610  {
1611  /* Need to allocate memory for new entry */
1612  opcentry->valid = false; /* until known OK */
1613  opcentry->numSupport = numSupport;
1614 
1615  if (numSupport > 0)
1616  opcentry->supportProcs = (RegProcedure *)
1618  (numSupport + 1) * sizeof(RegProcedure));
1619  else
1620  opcentry->supportProcs = NULL;
1621  }
1622  else
1623  {
1624  Assert(numSupport == opcentry->numSupport);
1625  }
1626 
1627  /*
1628  * When testing for cache-flush hazards, we intentionally disable the
1629  * operator class cache and force reloading of the info on each call. This
1630  * is helpful because we want to test the case where a cache flush occurs
1631  * while we are loading the info, and it's very hard to provoke that if
1632  * this happens only once per opclass per backend.
1633  */
1634 #ifdef CLOBBER_CACHE_ENABLED
1636  opcentry->valid = false;
1637 #endif
1638 
1639  if (opcentry->valid)
1640  return opcentry;
1641 
1642  /*
1643  * Need to fill in new entry.
1644  *
1645  * To avoid infinite recursion during startup, force heap scans if we're
1646  * looking up info for the opclasses used by the indexes we would like to
1647  * reference here.
1648  */
1649  indexOK = criticalRelcachesBuilt ||
1650  (operatorClassOid != OID_BTREE_OPS_OID &&
1651  operatorClassOid != INT2_BTREE_OPS_OID);
1652 
1653  /*
1654  * We have to fetch the pg_opclass row to determine its opfamily and
1655  * opcintype, which are needed to look up related operators and functions.
1656  * It'd be convenient to use the syscache here, but that probably doesn't
1657  * work while bootstrapping.
1658  */
1659  ScanKeyInit(&skey[0],
1660  Anum_pg_opclass_oid,
1661  BTEqualStrategyNumber, F_OIDEQ,
1662  ObjectIdGetDatum(operatorClassOid));
1663  rel = table_open(OperatorClassRelationId, AccessShareLock);
1664  scan = systable_beginscan(rel, OpclassOidIndexId, indexOK,
1665  NULL, 1, skey);
1666 
1667  if (HeapTupleIsValid(htup = systable_getnext(scan)))
1668  {
1669  Form_pg_opclass opclassform = (Form_pg_opclass) GETSTRUCT(htup);
1670 
1671  opcentry->opcfamily = opclassform->opcfamily;
1672  opcentry->opcintype = opclassform->opcintype;
1673  }
1674  else
1675  elog(ERROR, "could not find tuple for opclass %u", operatorClassOid);
1676 
1677  systable_endscan(scan);
1679 
1680  /*
1681  * Scan pg_amproc to obtain support procs for the opclass. We only fetch
1682  * the default ones (those with lefttype = righttype = opcintype).
1683  */
1684  if (numSupport > 0)
1685  {
1686  ScanKeyInit(&skey[0],
1687  Anum_pg_amproc_amprocfamily,
1688  BTEqualStrategyNumber, F_OIDEQ,
1689  ObjectIdGetDatum(opcentry->opcfamily));
1690  ScanKeyInit(&skey[1],
1691  Anum_pg_amproc_amproclefttype,
1692  BTEqualStrategyNumber, F_OIDEQ,
1693  ObjectIdGetDatum(opcentry->opcintype));
1694  ScanKeyInit(&skey[2],
1695  Anum_pg_amproc_amprocrighttype,
1696  BTEqualStrategyNumber, F_OIDEQ,
1697  ObjectIdGetDatum(opcentry->opcintype));
1698  rel = table_open(AccessMethodProcedureRelationId, AccessShareLock);
1699  scan = systable_beginscan(rel, AccessMethodProcedureIndexId, indexOK,
1700  NULL, 3, skey);
1701 
1702  while (HeapTupleIsValid(htup = systable_getnext(scan)))
1703  {
1704  Form_pg_amproc amprocform = (Form_pg_amproc) GETSTRUCT(htup);
1705 
1706  if (amprocform->amprocnum <= 0 ||
1707  (StrategyNumber) amprocform->amprocnum > numSupport)
1708  elog(ERROR, "invalid amproc number %d for opclass %u",
1709  amprocform->amprocnum, operatorClassOid);
1710 
1711  opcentry->supportProcs[amprocform->amprocnum - 1] =
1712  amprocform->amproc;
1713  }
1714 
1715  systable_endscan(scan);
1717  }
1718 
1719  opcentry->valid = true;
1720  return opcentry;
1721 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
struct opclasscacheent OpClassCacheEnt
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define HASH_ELEM
Definition: hsearch.h:95
FormData_pg_amproc * Form_pg_amproc
Definition: pg_amproc.h:68
regproc RegProcedure
Definition: c.h:585
#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:383
StrategyNumber numSupport
Definition: relcache.c:245
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
int debug_invalidate_system_caches_always
Definition: inval.c:184
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
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:906
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
#define elog(elevel,...)
Definition: elog.h:232
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:51

◆ RelationAssumeNewRelfilenode()

void RelationAssumeNewRelfilenode ( Relation  relation)

Definition at line 3727 of file relcache.c.

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

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

3728 {
3731  relation->rd_firstRelfilenodeSubid = relation->rd_newRelfilenodeSubid;
3732 
3733  /* Flag relation as needing eoxact cleanup (to clear these fields) */
3734  EOXactListAdd(relation);
3735 }
#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:593

◆ RelationBuildDesc()

static Relation RelationBuildDesc ( Oid  targetRelId,
bool  insertIt 
)
static

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

1003 {
1004  Relation relation;
1005  Oid relid;
1006  HeapTuple pg_class_tuple;
1007  Form_pg_class relp;
1008 
1009  /*
1010  * This function and its subroutines can allocate a good deal of transient
1011  * data in CurrentMemoryContext. Traditionally we've just leaked that
1012  * data, reasoning that the caller's context is at worst of transaction
1013  * scope, and relcache loads shouldn't happen so often that it's essential
1014  * to recover transient data before end of statement/transaction. However
1015  * that's definitely not true in clobber-cache test builds, and perhaps
1016  * it's not true in other cases.
1017  *
1018  * When cache clobbering is enabled or when forced to by
1019  * RECOVER_RELATION_BUILD_MEMORY=1, arrange to allocate the junk in a
1020  * temporary context that we'll free before returning. Make it a child
1021  * of caller's context so that it will get cleaned up appropriately if
1022  * we error out partway through.
1023  */
1024 #ifdef MAYBE_RECOVER_RELATION_BUILD_MEMORY
1025  MemoryContext tmpcxt = NULL;
1026  MemoryContext oldcxt = NULL;
1027 
1029  {
1031  "RelationBuildDesc workspace",
1033  oldcxt = MemoryContextSwitchTo(tmpcxt);
1034  }
1035 #endif
1036 
1037  /*
1038  * find the tuple in pg_class corresponding to the given relation id
1039  */
1040  pg_class_tuple = ScanPgRelation(targetRelId, true, false);
1041 
1042  /*
1043  * if no such tuple exists, return NULL
1044  */
1045  if (!HeapTupleIsValid(pg_class_tuple))
1046  {
1047 #ifdef MAYBE_RECOVER_RELATION_BUILD_MEMORY
1048  if (tmpcxt)
1049  {
1050  /* Return to caller's context, and blow away the temporary context */
1051  MemoryContextSwitchTo(oldcxt);
1052  MemoryContextDelete(tmpcxt);
1053  }
1054 #endif
1055  return NULL;
1056  }
1057 
1058  /*
1059  * get information from the pg_class_tuple
1060  */
1061  relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);
1062  relid = relp->oid;
1063  Assert(relid == targetRelId);
1064 
1065  /*
1066  * allocate storage for the relation descriptor, and copy pg_class_tuple
1067  * to relation->rd_rel.
1068  */
1069  relation = AllocateRelationDesc(relp);
1070 
1071  /*
1072  * initialize the relation's relation id (relation->rd_id)
1073  */
1074  RelationGetRelid(relation) = relid;
1075 
1076  /*
1077  * Normal relations are not nailed into the cache. Since we don't flush
1078  * new relations, it won't be new. It could be temp though.
1079  */
1080  relation->rd_refcnt = 0;
1081  relation->rd_isnailed = false;
1086  switch (relation->rd_rel->relpersistence)
1087  {
1088  case RELPERSISTENCE_UNLOGGED:
1089  case RELPERSISTENCE_PERMANENT:
1090  relation->rd_backend = InvalidBackendId;
1091  relation->rd_islocaltemp = false;
1092  break;
1093  case RELPERSISTENCE_TEMP:
1094  if (isTempOrTempToastNamespace(relation->rd_rel->relnamespace))
1095  {
1096  relation->rd_backend = BackendIdForTempRelations();
1097  relation->rd_islocaltemp = true;
1098  }
1099  else
1100  {
1101  /*
1102  * If it's a temp table, but not one of ours, we have to use
1103  * the slow, grotty method to figure out the owning backend.
1104  *
1105  * Note: it's possible that rd_backend gets set to MyBackendId
1106  * here, in case we are looking at a pg_class entry left over
1107  * from a crashed backend that coincidentally had the same
1108  * BackendId we're using. We should *not* consider such a
1109  * table to be "ours"; this is why we need the separate
1110  * rd_islocaltemp flag. The pg_class entry will get flushed
1111  * if/when we clean out the corresponding temp table namespace
1112  * in preparation for using it.
1113  */
1114  relation->rd_backend =
1115  GetTempNamespaceBackendId(relation->rd_rel->relnamespace);
1116  Assert(relation->rd_backend != InvalidBackendId);
1117  relation->rd_islocaltemp = false;
1118  }
1119  break;
1120  default:
1121  elog(ERROR, "invalid relpersistence: %c",
1122  relation->rd_rel->relpersistence);
1123  break;
1124  }
1125 
1126  /*
1127  * initialize the tuple descriptor (relation->rd_att).
1128  */
1129  RelationBuildTupleDesc(relation);
1130 
1131  /*
1132  * Fetch rules and triggers that affect this relation
1133  */
1134  if (relation->rd_rel->relhasrules)
1135  RelationBuildRuleLock(relation);
1136  else
1137  {
1138  relation->rd_rules = NULL;
1139  relation->rd_rulescxt = NULL;
1140  }
1141 
1142  if (relation->rd_rel->relhastriggers)
1143  RelationBuildTriggers(relation);
1144  else
1145  relation->trigdesc = NULL;
1146 
1147  if (relation->rd_rel->relrowsecurity)
1148  RelationBuildRowSecurity(relation);
1149  else
1150  relation->rd_rsdesc = NULL;
1151 
1152  /* foreign key data is not loaded till asked for */
1153  relation->rd_fkeylist = NIL;
1154  relation->rd_fkeyvalid = false;
1155 
1156  /* partitioning data is not loaded till asked for */
1157  relation->rd_partkey = NULL;
1158  relation->rd_partkeycxt = NULL;
1159  relation->rd_partdesc = NULL;
1160  relation->rd_pdcxt = NULL;
1161  relation->rd_partcheck = NIL;
1162  relation->rd_partcheckvalid = false;
1163  relation->rd_partcheckcxt = NULL;
1164 
1165  /*
1166  * initialize access method information
1167  */
1168  switch (relation->rd_rel->relkind)
1169  {
1170  case RELKIND_INDEX:
1171  case RELKIND_PARTITIONED_INDEX:
1172  Assert(relation->rd_rel->relam != InvalidOid);
1173  RelationInitIndexAccessInfo(relation);
1174  break;
1175  case RELKIND_RELATION:
1176  case RELKIND_TOASTVALUE:
1177  case RELKIND_MATVIEW:
1178  Assert(relation->rd_rel->relam != InvalidOid);
1180  break;
1181  case RELKIND_SEQUENCE:
1182  Assert(relation->rd_rel->relam == InvalidOid);
1184  break;
1185  case RELKIND_VIEW:
1186  case RELKIND_COMPOSITE_TYPE:
1187  case RELKIND_FOREIGN_TABLE:
1188  case RELKIND_PARTITIONED_TABLE:
1189  Assert(relation->rd_rel->relam == InvalidOid);
1190  break;
1191  }
1192 
1193  /* extract reloptions if any */
1194  RelationParseRelOptions(relation, pg_class_tuple);
1195 
1196  /*
1197  * initialize the relation lock manager information
1198  */
1199  RelationInitLockInfo(relation); /* see lmgr.c */
1200 
1201  /*
1202  * initialize physical addressing information for the relation
1203  */
1204  RelationInitPhysicalAddr(relation);
1205 
1206  /* make sure relation is marked as having no open file yet */
1207  relation->rd_smgr = NULL;
1208 
1209  /*
1210  * now we can free the memory allocated for pg_class_tuple
1211  */
1212  heap_freetuple(pg_class_tuple);
1213 
1214  /*
1215  * Insert newly created relation into relcache hash table, if requested.
1216  *
1217  * There is one scenario in which we might find a hashtable entry already
1218  * present, even though our caller failed to find it: if the relation is a
1219  * system catalog or index that's used during relcache load, we might have
1220  * recursively created the same relcache entry during the preceding steps.
1221  * So allow RelationCacheInsert to delete any already-present relcache
1222  * entry for the same OID. The already-present entry should have refcount
1223  * zero (else somebody forgot to close it); in the event that it doesn't,
1224  * we'll elog a WARNING and leak the already-present entry.
1225  */
1226  if (insertIt)
1227  RelationCacheInsert(relation, true);
1228 
1229  /* It's fully valid */
1230  relation->rd_isvalid = true;
1231 
1232 #ifdef MAYBE_RECOVER_RELATION_BUILD_MEMORY
1233  if (tmpcxt)
1234  {
1235  /* Return to caller's context, and blow away the temporary context */
1236  MemoryContextSwitchTo(oldcxt);
1237  MemoryContextDelete(tmpcxt);
1238  }
1239 #endif
1240 
1241  return relation;
1242 }
#define NIL
Definition: pg_list.h:65
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
#define AllocSetContextCreate
Definition: memutils.h:173
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
void RelationBuildRowSecurity(Relation relation)
Definition: policy.c:195
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3180
void RelationInitTableAccessMethod(Relation relation)
Definition: relcache.c:1738
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:387
#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:46
TriggerDesc * trigdesc
Definition: rel.h:116
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1252
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
void RelationInitLockInfo(Relation relation)
Definition: lmgr.c:72
#define BackendIdForTempRelations()
Definition: backendid.h:34
static void RelationParseRelOptions(Relation relation, HeapTuple tuple)
Definition: relcache.c:442
static void RelationBuildTupleDesc(Relation relation)
Definition: relcache.c:499
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
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:804
MemoryContext rd_partkeycxt
Definition: rel.h:126
RuleLock * rd_rules
Definition: rel.h:114
#define InvalidSubTransactionId
Definition: c.h:593
void RelationInitIndexAccessInfo(Relation relation)
Definition: relcache.c:1358
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
void RelationBuildTriggers(Relation relation)
Definition: trigger.c:1637
int rd_refcnt
Definition: rel.h:58
static HeapTuple ScanPgRelation(Oid targetRelId, bool indexOK, bool force_non_historic)
Definition: relcache.c:317
#define elog(elevel,...)
Definition: elog.h:232
static void RelationBuildRuleLock(Relation relation)
Definition: relcache.c:709
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 3330 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().

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

◆ RelationBuildRuleLock()

static void RelationBuildRuleLock ( Relation  relation)
static

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

710 {
711  MemoryContext rulescxt;
712  MemoryContext oldcxt;
713  HeapTuple rewrite_tuple;
714  Relation rewrite_desc;
715  TupleDesc rewrite_tupdesc;
716  SysScanDesc rewrite_scan;
718  RuleLock *rulelock;
719  int numlocks;
720  RewriteRule **rules;
721  int maxlocks;
722 
723  /*
724  * Make the private context. Assume it'll not contain much data.
725  */
727  "relation rules",
729  relation->rd_rulescxt = rulescxt;
731  RelationGetRelationName(relation));
732 
733  /*
734  * allocate an array to hold the rewrite rules (the array is extended if
735  * necessary)
736  */
737  maxlocks = 4;
738  rules = (RewriteRule **)
739  MemoryContextAlloc(rulescxt, sizeof(RewriteRule *) * maxlocks);
740  numlocks = 0;
741 
742  /*
743  * form a scan key
744  */
745  ScanKeyInit(&key,
746  Anum_pg_rewrite_ev_class,
747  BTEqualStrategyNumber, F_OIDEQ,
749 
750  /*
751  * open pg_rewrite and begin a scan
752  *
753  * Note: since we scan the rules using RewriteRelRulenameIndexId, we will
754  * be reading the rules in name order, except possibly during
755  * emergency-recovery operations (ie, IgnoreSystemIndexes). This in turn
756  * ensures that rules will be fired in name order.
757  */
758  rewrite_desc = table_open(RewriteRelationId, AccessShareLock);
759  rewrite_tupdesc = RelationGetDescr(rewrite_desc);
760  rewrite_scan = systable_beginscan(rewrite_desc,
762  true, NULL,
763  1, &key);
764 
765  while (HeapTupleIsValid(rewrite_tuple = systable_getnext(rewrite_scan)))
766  {
767  Form_pg_rewrite rewrite_form = (Form_pg_rewrite) GETSTRUCT(rewrite_tuple);
768  bool isnull;
769  Datum rule_datum;
770  char *rule_str;
771  RewriteRule *rule;
772 
773  rule = (RewriteRule *) MemoryContextAlloc(rulescxt,
774  sizeof(RewriteRule));
775 
776  rule->ruleId = rewrite_form->oid;
777 
778  rule->event = rewrite_form->ev_type - '0';
779  rule->enabled = rewrite_form->ev_enabled;
780  rule->isInstead = rewrite_form->is_instead;
781 
782  /*
783  * Must use heap_getattr to fetch ev_action and ev_qual. Also, the
784  * rule strings are often large enough to be toasted. To avoid
785  * leaking memory in the caller's context, do the detoasting here so
786  * we can free the detoasted version.
787  */
788  rule_datum = heap_getattr(rewrite_tuple,
789  Anum_pg_rewrite_ev_action,
790  rewrite_tupdesc,
791  &isnull);
792  Assert(!isnull);
793  rule_str = TextDatumGetCString(rule_datum);
794  oldcxt = MemoryContextSwitchTo(rulescxt);
795  rule->actions = (List *) stringToNode(rule_str);
796  MemoryContextSwitchTo(oldcxt);
797  pfree(rule_str);
798 
799  rule_datum = heap_getattr(rewrite_tuple,
800  Anum_pg_rewrite_ev_qual,
801  rewrite_tupdesc,
802  &isnull);
803  Assert(!isnull);
804  rule_str = TextDatumGetCString(rule_datum);
805  oldcxt = MemoryContextSwitchTo(rulescxt);
806  rule->qual = (Node *) stringToNode(rule_str);
807  MemoryContextSwitchTo(oldcxt);
808  pfree(rule_str);
809 
810  /*
811  * We want the rule's table references to be checked as though by the
812  * table owner, not the user referencing the rule. Therefore, scan
813  * through the rule's actions and set the checkAsUser field on all
814  * rtable entries. We have to look at the qual as well, in case it
815  * contains sublinks.
816  *
817  * The reason for doing this when the rule is loaded, rather than when
818  * it is stored, is that otherwise ALTER TABLE OWNER would have to
819  * grovel through stored rules to update checkAsUser fields. Scanning
820  * the rule tree during load is relatively cheap (compared to
821  * constructing it in the first place), so we do it here.
822  */
823  setRuleCheckAsUser((Node *) rule->actions, relation->rd_rel->relowner);
824  setRuleCheckAsUser(rule->qual, relation->rd_rel->relowner);
825 
826  if (numlocks >= maxlocks)
827  {
828  maxlocks *= 2;
829  rules = (RewriteRule **)
830  repalloc(rules, sizeof(RewriteRule *) * maxlocks);
831  }
832  rules[numlocks++] = rule;
833  }
834 
835  /*
836  * end the scan and close the attribute relation
837  */
838  systable_endscan(rewrite_scan);
839  table_close(rewrite_desc, AccessShareLock);
840 
841  /*
842  * there might not be any rules (if relhasrules is out-of-date)
843  */
844  if (numlocks == 0)
845  {
846  relation->rd_rules = NULL;
847  relation->rd_rulescxt = NULL;
848  MemoryContextDelete(rulescxt);
849  return;
850  }
851 
852  /*
853  * form a RuleLock and insert into relation
854  */
855  rulelock = (RuleLock *) MemoryContextAlloc(rulescxt, sizeof(RuleLock));
856  rulelock->numLocks = numlocks;
857  rulelock->rules = rules;
858 
859  relation->rd_rules = rulelock;
860 }
Node * qual
Definition: prs2lock.h:28
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
#define AllocSetContextCreate
Definition: memutils.h:173
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
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:205
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:539
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:383
Definition: localtime.c:72
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define MemoryContextCopyAndSetIdentifier(cxt, id)
Definition: memutils.h:98
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:761
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:411
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
#define RewriteRelRulenameIndexId
Definition: pg_rewrite.h:59
RuleLock * rd_rules
Definition: rel.h:114
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
FormData_pg_rewrite * Form_pg_rewrite
Definition: pg_rewrite.h:52
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
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:51
char enabled
Definition: prs2lock.h:30

◆ RelationBuildTupleDesc()

static void RelationBuildTupleDesc ( Relation  relation)
static

Definition at line 499 of file relcache.c.

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

Referenced by RelationBuildDesc().

500 {
501  HeapTuple pg_attribute_tuple;
502  Relation pg_attribute_desc;
503  SysScanDesc pg_attribute_scan;
504  ScanKeyData skey[2];
505  int need;
506  TupleConstr *constr;
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 relation \"%s\"",
561  attp->attnum, RelationGetRelationName(relation));
562 
563  memcpy(TupleDescAttr(relation->rd_att, attnum - 1),
564  attp,
566 
567  /* Update constraint/default info */
568  if (attp->attnotnull)
569  constr->has_not_null = true;
570  if (attp->attgenerated == ATTRIBUTE_GENERATED_STORED)
571  constr->has_generated_stored = true;
572  if (attp->atthasdef)
573  ndef++;
574 
575  /* If the column has a "missing" value, put it in the attrmiss array */
576  if (attp->atthasmissing)
577  {
578  Datum missingval;
579  bool missingNull;
580 
581  /* Do we have a missing value? */
582  missingval = heap_getattr(pg_attribute_tuple,
583  Anum_pg_attribute_attmissingval,
584  pg_attribute_desc->rd_att,
585  &missingNull);
586  if (!missingNull)
587  {
588  /* Yes, fetch from the array */
589  MemoryContext oldcxt;
590  bool is_null;
591  int one = 1;
592  Datum missval;
593 
594  if (attrmiss == NULL)
595  attrmiss = (AttrMissing *)
597  relation->rd_rel->relnatts *
598  sizeof(AttrMissing));
599 
600  missval = array_get_element(missingval,
601  1,
602  &one,
603  -1,
604  attp->attlen,
605  attp->attbyval,
606  attp->attalign,
607  &is_null);
608  Assert(!is_null);
609  if (attp->attbyval)
610  {
611  /* for copy by val just copy the datum direct */
612  attrmiss[attnum - 1].am_value = missval;
613  }
614  else
615  {
616  /* otherwise copy in the correct context */
618  attrmiss[attnum - 1].am_value = datumCopy(missval,
619  attp->attbyval,
620  attp->attlen);
621  MemoryContextSwitchTo(oldcxt);
622  }
623  attrmiss[attnum - 1].am_present = true;
624  }
625  }
626  need--;
627  if (need == 0)
628  break;
629  }
630 
631  /*
632  * end the scan and close the attribute relation
633  */
634  systable_endscan(pg_attribute_scan);
635  table_close(pg_attribute_desc, AccessShareLock);
636 
637  if (need != 0)
638  elog(ERROR, "pg_attribute catalog is missing %d attribute(s) for relation OID %u",
639  need, RelationGetRelid(relation));
640 
641  /*
642  * The attcacheoff values we read from pg_attribute should all be -1
643  * ("unknown"). Verify this if assert checking is on. They will be
644  * computed when and if needed during tuple access.
645  */
646 #ifdef USE_ASSERT_CHECKING
647  {
648  int i;
649 
650  for (i = 0; i < RelationGetNumberOfAttributes(relation); i++)
651  Assert(TupleDescAttr(relation->rd_att, i)->attcacheoff == -1);
652  }
653 #endif
654 
655  /*
656  * However, we can easily set the attcacheoff value for the first
657  * attribute: it must be zero. This eliminates the need for special cases
658  * for attnum=1 that used to exist in fastgetattr() and index_getattr().
659  */
660  if (RelationGetNumberOfAttributes(relation) > 0)
661  TupleDescAttr(relation->rd_att, 0)->attcacheoff = 0;
662 
663  /*
664  * Set up constraint/default info
665  */
666  if (constr->has_not_null ||
667  constr->has_generated_stored ||
668  ndef > 0 ||
669  attrmiss ||
670  relation->rd_rel->relchecks > 0)
671  {
672  relation->rd_att->constr = constr;
673 
674  if (ndef > 0) /* DEFAULTs */
675  AttrDefaultFetch(relation, ndef);
676  else
677  constr->num_defval = 0;
678 
679  constr->missing = attrmiss;
680 
681  if (relation->rd_rel->relchecks > 0) /* CHECKs */
682  CheckConstraintFetch(relation);
683  else
684  constr->num_check = 0;
685  }
686  else
687  {
688  pfree(constr);
689  relation->rd_att->constr = NULL;
690  }
691 }
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:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:463
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
static void AttrDefaultFetch(Relation relation, int ndef)
Definition: relcache.c:4235
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define Int16GetDatum(X)
Definition: postgres.h:495
#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:383
bool has_generated_stored
Definition: tupdesc.h:45
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
int32 tdtypmod
Definition: tupdesc.h:83
#define AttributeRelidNumIndexId
Definition: pg_attribute.h:208
TupleConstr * constr
Definition: tupdesc.h:85
#define RelationGetRelationName(relation)
Definition: rel.h:491
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:195
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:131
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:761
uintptr_t Datum
Definition: postgres.h:411
TupleDesc rd_att
Definition: rel.h:111
uint16 num_check
Definition: tupdesc.h:43
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:906
int16 attnum
Definition: pg_attribute.h:83
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:804
static void CheckConstraintFetch(Relation relation)
Definition: relcache.c:4330
struct AttrMissing * missing
Definition: tupdesc.h:41
uint16 num_defval
Definition: tupdesc.h:42
Oid tdtypeid
Definition: tupdesc.h:82
#define elog(elevel,...)
Definition: elog.h:232
int i
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
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:51

◆ RelationCacheInitFilePostInvalidate()

void RelationCacheInitFilePostInvalidate ( void  )

Definition at line 6361 of file relcache.c.

References LWLockRelease().

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

6362 {
6363  LWLockRelease(RelCacheInitLock);
6364 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )

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

6337 {
6338  char localinitfname[MAXPGPATH];
6339  char sharedinitfname[MAXPGPATH];
6340 
6341  if (DatabasePath)
6342  snprintf(localinitfname, sizeof(localinitfname), "%s/%s",
6344  snprintf(sharedinitfname, sizeof(sharedinitfname), "global/%s",
6346 
6347  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6348 
6349  /*
6350  * The files might not be there if no backend has been started since the
6351  * last removal. But complain about failures other than ENOENT with
6352  * ERROR. Fortunately, it's not too late to abort the transaction if we
6353  * can't get rid of the would-be-obsolete init file.
6354  */
6355  if (DatabasePath)
6356  unlink_initfile(localinitfname, ERROR);
6357  unlink_initfile(sharedinitfname, ERROR);
6358 }
#define ERROR
Definition: elog.h:46
#define MAXPGPATH
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25
char * DatabasePath
Definition: globals.c:96
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6433
#define snprintf
Definition: port.h:216

◆ RelationCacheInitFileRemove()

void RelationCacheInitFileRemove ( void  )

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

6377 {
6378  const char *tblspcdir = "pg_tblspc";
6379  DIR *dir;
6380  struct dirent *de;
6381  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6382 
6383  snprintf(path, sizeof(path), "global/%s",
6385  unlink_initfile(path, LOG);
6386 
6387  /* Scan everything in the default tablespace */
6389 
6390  /* Scan the tablespace link directory to find non-default tablespaces */
6391  dir = AllocateDir(tblspcdir);
6392 
6393  while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6394  {
6395  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6396  {
6397  /* Scan the tablespace dir for per-database dirs */
6398  snprintf(path, sizeof(path), "%s/%s/%s",
6399  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6401  }
6402  }
6403 
6404  FreeDir(dir);
6405 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6409
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2715
#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:2634
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6433
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:216
int FreeDir(DIR *dir)
Definition: fd.c:2752

◆ RelationCacheInitFileRemoveInDir()

static void RelationCacheInitFileRemoveInDir ( const char *  tblspcpath)
static

Definition at line 6409 of file relcache.c.

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

Referenced by RelationCacheInitFileRemove().

6410 {
6411  DIR *dir;
6412  struct dirent *de;
6413  char initfilename[MAXPGPATH * 2];
6414 
6415  /* Scan the tablespace directory to find per-database directories */
6416  dir = AllocateDir(tblspcpath);
6417 
6418  while ((de = ReadDirExtended(dir, tblspcpath, LOG)) != NULL)
6419  {
6420  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6421  {
6422  /* Try to remove the init file in each database */
6423  snprintf(initfilename, sizeof(initfilename), "%s/%s/%s",
6424  tblspcpath, de->d_name, RELCACHE_INIT_FILENAME);
6425  unlink_initfile(initfilename, LOG);
6426  }
6427  }
6428 
6429  FreeDir(dir);
6430 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2715
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2634
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6433
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:216
int FreeDir(DIR *dir)
Definition: fd.c:2752

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 3753 of file relcache.c.

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

Referenced by InitPostgres().

3754 {
3755  HASHCTL ctl;
3756 
3757  /*
3758  * make sure cache memory context exists
3759  */
3760  if (!CacheMemoryContext)
3762 
3763  /*
3764  * create hashtable that indexes the relcache
3765  */
3766  ctl.keysize = sizeof(Oid);
3767  ctl.entrysize = sizeof(RelIdCacheEnt);
3768  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3769  &ctl, HASH_ELEM | HASH_BLOBS);
3770 
3771  /*
3772  * relation mapper needs to be initialized too
3773  */
3775 }
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:3750
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ RelationCacheInitializePhase2()

void RelationCacheInitializePhase2 ( void  )

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

3790 {
3791  MemoryContext oldcxt;
3792 
3793  /*
3794  * relation mapper needs initialized too
3795  */
3797 
3798  /*
3799  * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3800  * nothing.
3801  */
3803  return;
3804 
3805  /*
3806  * switch to cache memory context
3807  */
3809 
3810  /*
3811  * Try to load the shared relcache cache file. If unsuccessful, bootstrap
3812  * the cache with pre-made descriptors for the critical shared catalogs.
3813  */
3814  if (!load_relcache_init_file(true))
3815  {
3816  formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
3817  Natts_pg_database, Desc_pg_database);
3818  formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
3819  Natts_pg_authid, Desc_pg_authid);
3820  formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
3821  Natts_pg_auth_members, Desc_pg_auth_members);
3822  formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
3823  Natts_pg_shseclabel, Desc_pg_shseclabel);
3824  formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
3825  Natts_pg_subscription, Desc_pg_subscription);
3826 
3827 #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
3828  }
3829 
3830  MemoryContextSwitchTo(oldcxt);
3831 }
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:5652
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:1802
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ RelationCacheInitializePhase3()

void RelationCacheInitializePhase3 ( void  )

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

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

◆ RelationCacheInvalidate()

void RelationCacheInvalidate ( void  )

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

2819 {
2821  RelIdCacheEnt *idhentry;
2822  Relation relation;
2823  List *rebuildFirstList = NIL;
2824  List *rebuildList = NIL;
2825  ListCell *l;
2826 
2827  /*
2828  * Reload relation mapping data before starting to reconstruct cache.
2829  */
2831 
2832  /* Phase 1 */
2833  hash_seq_init(&status, RelationIdCache);
2834 
2835  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2836  {
2837  relation = idhentry->reldesc;
2838 
2839  /* Must close all smgr references to avoid leaving dangling ptrs */
2840  RelationCloseSmgr(relation);
2841 
2842  /*
2843  * Ignore new relations; no other backend will manipulate them before
2844  * we commit. Likewise, before replacing a relation's relfilenode, we
2845  * shall have acquired AccessExclusiveLock and drained any applicable
2846  * pending invalidations.
2847  */
2848  if (relation->rd_createSubid != InvalidSubTransactionId ||
2850  continue;
2851 
2853 
2854  if (RelationHasReferenceCountZero(relation))
2855  {
2856  /* Delete this entry immediately */
2857  Assert(!relation->rd_isnailed);
2858  RelationClearRelation(relation, false);
2859  }
2860  else
2861  {
2862  /*
2863  * If it's a mapped relation, immediately update its rd_node in
2864  * case its relfilenode changed. We must do this during phase 1
2865  * in case the relation is consulted during rebuild of other
2866  * relcache entries in phase 2. It's safe since consulting the
2867  * map doesn't involve any access to relcache entries.
2868  */
2869  if (RelationIsMapped(relation))
2870  RelationInitPhysicalAddr(relation);
2871 
2872  /*
2873  * Add this entry to list of stuff to rebuild in second pass.
2874  * pg_class goes to the front of rebuildFirstList while
2875  * pg_class_oid_index goes to the back of rebuildFirstList, so
2876  * they are done first and second respectively. Other nailed
2877  * relations go to the front of rebuildList, so they'll be done
2878  * next in no particular order; and everything else goes to the
2879  * back of rebuildList.
2880  */
2881  if (RelationGetRelid(relation) == RelationRelationId)
2882  rebuildFirstList = lcons(relation, rebuildFirstList);
2883  else if (RelationGetRelid(relation) == ClassOidIndexId)
2884  rebuildFirstList = lappend(rebuildFirstList, relation);
2885  else if (relation->rd_isnailed)
2886  rebuildList = lcons(relation, rebuildList);
2887  else
2888  rebuildList = lappend(rebuildList, relation);
2889  }
2890  }
2891 
2892  /*
2893  * Now zap any remaining smgr cache entries. This must happen before we
2894  * start to rebuild entries, since that may involve catalog fetches which
2895  * will re-open catalog files.
2896  */
2897  smgrcloseall();
2898 
2899  /* Phase 2: rebuild the items found to need rebuild in phase 1 */
2900  foreach(l, rebuildFirstList)
2901  {
2902  relation = (Relation) lfirst(l);
2903  RelationClearRelation(relation, true);
2904  }
2905  list_free(rebuildFirstList);
2906  foreach(l, rebuildList)
2907  {
2908  relation = (Relation) lfirst(l);
2909  RelationClearRelation(relation, true);
2910  }
2911  list_free(rebuildList);
2912 }
#define NIL
Definition: pg_list.h:65
static long relcacheInvalsReceived
Definition: relcache.c:152
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2418
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:1252
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:804
#define lfirst(lc)
Definition: pg_list.h:169
#define InvalidSubTransactionId
Definition: c.h:593
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 2775 of file relcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

2776 {
2777  Relation relation;
2778 
2779  RelationIdCacheLookup(relationId, relation);
2780 
2781  if (PointerIsValid(relation))
2782  {
2784  RelationFlushRelation(relation);
2785  }
2786 }
static long relcacheInvalsReceived
Definition: relcache.c:152
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:211
static void RelationFlushRelation(Relation relation)
Definition: relcache.c:2698
#define PointerIsValid(pointer)
Definition: c.h:698

◆ RelationClearRelation()

static void RelationClearRelation ( Relation  relation,
bool  rebuild 
)
static

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

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