PostgreSQL Source Code  git master
relcache.c File Reference
#include "postgres.h"
#include <sys/file.h>
#include <fcntl.h>
#include <unistd.h>
#include "access/htup_details.h"
#include "access/multixact.h"
#include "access/nbtree.h"
#include "access/parallel.h"
#include "access/reloptions.h"
#include "access/sysattr.h"
#include "access/table.h"
#include "access/tableam.h"
#include "access/tupdesc_details.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "catalog/catalog.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/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)
 
BitmapsetRelationGetIdentityKeyBitmap (Relation relation)
 
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:163
static int eoxact_list_len
Definition: relcache.c:165

Definition at line 168 of file relcache.c.

Referenced by RelationAssumeNewRelfilenode(), and RelationBuildLocalRelation().

◆ INITRELCACHESIZE

#define INITRELCACHESIZE   400

Definition at line 3772 of file relcache.c.

Referenced by RelationCacheInitialize().

◆ MAX_EOXACT_LIST

#define MAX_EOXACT_LIST   32

Definition at line 163 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 99 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:131
#define WARNING
Definition: elog.h:40

Definition at line 222 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:131
#define RelationGetRelationName(relation)
Definition: rel.h:511
#define WARNING
Definition: elog.h:40
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:461
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:406

Definition at line 188 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:131

Definition at line 210 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 90 of file relcache.c.

Referenced by load_relcache_init_file(), and write_relcache_init_file().

◆ SWAPFIELD

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

Referenced by RelationClearRelation().

Typedef Documentation

◆ OpClassCacheEnt

◆ RelIdCacheEnt

typedef struct relidcacheent RelIdCacheEnt

Function Documentation

◆ AllocateRelationDesc()

static Relation AllocateRelationDesc ( Form_pg_class  relp)
static

Definition at line 386 of file relcache.c.

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

Referenced by RelationBuildDesc().

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

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

◆ AtEOSubXact_RelationCache()

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

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

3225 {
3227  RelIdCacheEnt *idhentry;
3228  int i;
3229 
3230  /*
3231  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3232  * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3233  * logic as in AtEOXact_RelationCache.
3234  */
3236  {
3237  hash_seq_init(&status, RelationIdCache);
3238  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3239  {
3240  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3241  mySubid, parentSubid);
3242  }
3243  }
3244  else
3245  {
3246  for (i = 0; i < eoxact_list_len; i++)
3247  {
3248  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3249  (void *) &eoxact_list[i],
3250  HASH_FIND,
3251  NULL);
3252  if (idhentry != NULL)
3253  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3254  mySubid, parentSubid);
3255  }
3256  }
3257 
3258  /* Don't reset the list; we still need more cleanup later */
3259 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:164
static void AtEOSubXact_cleanup(Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
Definition: relcache.c:3270
Relation reldesc
Definition: relcache.c:128
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
static HTAB * RelationIdCache
Definition: relcache.c:131
static bool eoxact_list_overflowed
Definition: relcache.c:166
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:165

◆ AtEOXact_cleanup()

static void AtEOXact_cleanup ( Relation  relation,
bool  isCommit 
)
static

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

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

◆ AtEOXact_RelationCache()

void AtEOXact_RelationCache ( bool  isCommit)

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

3079 {
3081  RelIdCacheEnt *idhentry;
3082  int i;
3083 
3084  /*
3085  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3086  * listed in it. Otherwise fall back on a hash_seq_search scan.
3087  *
3088  * For simplicity, eoxact_list[] entries are not deleted till end of
3089  * top-level transaction, even though we could remove them at
3090  * subtransaction end in some cases, or remove relations from the list if
3091  * they are cleared for other reasons. Therefore we should expect the
3092  * case that list entries are not found in the hashtable; if not, there's
3093  * nothing to do for them.
3094  */
3096  {
3097  hash_seq_init(&status, RelationIdCache);
3098  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3099  {
3100  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3101  }
3102  }
3103  else
3104  {
3105  for (i = 0; i < eoxact_list_len; i++)
3106  {
3107  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3108  (void *) &eoxact_list[i],
3109  HASH_FIND,
3110  NULL);
3111  if (idhentry != NULL)
3112  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3113  }
3114  }
3115 
3116  if (EOXactTupleDescArrayLen > 0)
3117  {
3118  Assert(EOXactTupleDescArray != NULL);
3119  for (i = 0; i < NextEOXactTupleDescNum; i++)
3122  EOXactTupleDescArray = NULL;
3123  }
3124 
3125  /* Now we're out of the transaction and can clear the lists */
3126  eoxact_list_len = 0;
3127  eoxact_list_overflowed = false;
3128  NextEOXactTupleDescNum = 0;
3130 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:164
static int EOXactTupleDescArrayLen
Definition: relcache.c:183
Relation reldesc
Definition: relcache.c:128
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
static HTAB * RelationIdCache
Definition: relcache.c:131
static void AtEOXact_cleanup(Relation relation, bool isCommit)
Definition: relcache.c:3141
static bool eoxact_list_overflowed
Definition: relcache.c:166
static int NextEOXactTupleDescNum
Definition: relcache.c:182
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:165
static TupleDesc * EOXactTupleDescArray
Definition: relcache.c:181

◆ AttrDefaultCmp()

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

Definition at line 4337 of file relcache.c.

References AttrDefault::adnum.

Referenced by AttrDefaultFetch().

4338 {
4339  const AttrDefault *ada = (const AttrDefault *) a;
4340  const AttrDefault *adb = (const AttrDefault *) b;
4341 
4342  return ada->adnum - adb->adnum;
4343 }
AttrNumber adnum
Definition: tupdesc.h:24

◆ AttrDefaultFetch()

static void AttrDefaultFetch ( Relation  relation,
int  ndef 
)
static

Definition at line 4257 of file relcache.c.

References AccessShareLock, AttrDefault::adbin, AttrDefault::adnum, AttrDefaultCmp(), 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().

4258 {
4259  AttrDefault *attrdef;
4260  Relation adrel;
4261  SysScanDesc adscan;
4262  ScanKeyData skey;
4263  HeapTuple htup;
4264  int found = 0;
4265 
4266  /* Allocate array with room for as many entries as expected */
4267  attrdef = (AttrDefault *)
4269  ndef * sizeof(AttrDefault));
4270 
4271  /* Search pg_attrdef for relevant entries */
4272  ScanKeyInit(&skey,
4273  Anum_pg_attrdef_adrelid,
4274  BTEqualStrategyNumber, F_OIDEQ,
4275  ObjectIdGetDatum(RelationGetRelid(relation)));
4276 
4277  adrel = table_open(AttrDefaultRelationId, AccessShareLock);
4278  adscan = systable_beginscan(adrel, AttrDefaultIndexId, true,
4279  NULL, 1, &skey);
4280 
4281  while (HeapTupleIsValid(htup = systable_getnext(adscan)))
4282  {
4283  Form_pg_attrdef adform = (Form_pg_attrdef) GETSTRUCT(htup);
4284  Datum val;
4285  bool isnull;
4286 
4287  /* protect limited size of array */
4288  if (found >= ndef)
4289  {
4290  elog(WARNING, "unexpected pg_attrdef record found for attribute %d of relation \"%s\"",
4291  adform->adnum, RelationGetRelationName(relation));
4292  break;
4293  }
4294 
4295  val = fastgetattr(htup,
4296  Anum_pg_attrdef_adbin,
4297  adrel->rd_att, &isnull);
4298  if (isnull)
4299  elog(WARNING, "null adbin for attribute %d of relation \"%s\"",
4300  adform->adnum, RelationGetRelationName(relation));
4301  else
4302  {
4303  /* detoast and convert to cstring in caller's context */
4304  char *s = TextDatumGetCString(val);
4305 
4306  attrdef[found].adnum = adform->adnum;
4307  attrdef[found].adbin = MemoryContextStrdup(CacheMemoryContext, s);
4308  pfree(s);
4309  found++;
4310  }
4311  }
4312 
4313  systable_endscan(adscan);
4314  table_close(adrel, AccessShareLock);
4315 
4316  if (found != ndef)
4317  elog(WARNING, "%d pg_attrdef record(s) missing for relation \"%s\"",
4318  ndef - found, RelationGetRelationName(relation));
4319 
4320  /*
4321  * Sort the AttrDefault entries by adnum, for the convenience of
4322  * equalTupleDescs(). (Usually, they already will be in order, but this
4323  * might not be so if systable_getnext isn't using an index.)
4324  */
4325  if (found > 1)
4326  qsort(attrdef, found, sizeof(AttrDefault), AttrDefaultCmp);
4327 
4328  /* Install array only after it's fully valid */
4329  relation->rd_att->constr->defval = attrdef;
4330  relation->rd_att->constr->num_defval = found;
4331 }
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 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:511
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:110
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:4337
#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:477
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 4192 of file relcache.c.

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

Referenced by GetPgClassDescriptor(), and GetPgIndexDescriptor().

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

References ConstrCheck::ccname.

Referenced by CheckConstraintFetch().

4442 {
4443  const ConstrCheck *ca = (const ConstrCheck *) a;
4444  const ConstrCheck *cb = (const ConstrCheck *) b;
4445 
4446  return strcmp(ca->ccname, cb->ccname);
4447 }
char * ccname
Definition: tupdesc.h:30

◆ CheckConstraintFetch()

static void CheckConstraintFetch ( Relation  relation)
static

Definition at line 4352 of file relcache.c.

References AccessShareLock, BTEqualStrategyNumber, CacheMemoryContext, ConstrCheck::ccbin, ConstrCheck::ccname, ConstrCheck::ccnoinherit, ConstrCheck::ccvalid, TupleConstr::check, CheckConstraintCmp(), TupleDescData::constr, 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().

4353 {
4354  ConstrCheck *check;
4355  int ncheck = relation->rd_rel->relchecks;
4356  Relation conrel;
4357  SysScanDesc conscan;
4358  ScanKeyData skey[1];
4359  HeapTuple htup;
4360  int found = 0;
4361 
4362  /* Allocate array with room for as many entries as expected */
4363  check = (ConstrCheck *)
4365  ncheck * sizeof(ConstrCheck));
4366 
4367  /* Search pg_constraint for relevant entries */
4368  ScanKeyInit(&skey[0],
4369  Anum_pg_constraint_conrelid,
4370  BTEqualStrategyNumber, F_OIDEQ,
4371  ObjectIdGetDatum(RelationGetRelid(relation)));
4372 
4373  conrel = table_open(ConstraintRelationId, AccessShareLock);
4374  conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
4375  NULL, 1, skey);
4376 
4377  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4378  {
4380  Datum val;
4381  bool isnull;
4382 
4383  /* We want check constraints only */
4384  if (conform->contype != CONSTRAINT_CHECK)
4385  continue;
4386 
4387  /* protect limited size of array */
4388  if (found >= ncheck)
4389  {
4390  elog(WARNING, "unexpected pg_constraint record found for relation \"%s\"",
4391  RelationGetRelationName(relation));
4392  break;
4393  }
4394 
4395  check[found].ccvalid = conform->convalidated;
4396  check[found].ccnoinherit = conform->connoinherit;
4398  NameStr(conform->conname));
4399 
4400  /* Grab and test conbin is actually set */
4401  val = fastgetattr(htup,
4402  Anum_pg_constraint_conbin,
4403  conrel->rd_att, &isnull);
4404  if (isnull)
4405  elog(WARNING, "null conbin for relation \"%s\"",
4406  RelationGetRelationName(relation));
4407  else
4408  {
4409  /* detoast and convert to cstring in caller's context */
4410  char *s = TextDatumGetCString(val);
4411 
4412  check[found].ccbin = MemoryContextStrdup(CacheMemoryContext, s);
4413  pfree(s);
4414  found++;
4415  }
4416  }
4417 
4418  systable_endscan(conscan);
4419  table_close(conrel, AccessShareLock);
4420 
4421  if (found != ncheck)
4422  elog(WARNING, "%d pg_constraint record(s) missing for relation \"%s\"",
4423  ncheck - found, RelationGetRelationName(relation));
4424 
4425  /*
4426  * Sort the records by name. This ensures that CHECKs are applied in a
4427  * deterministic order, and it also makes equalTupleDescs() faster.
4428  */
4429  if (found > 1)
4430  qsort(check, found, sizeof(ConstrCheck), CheckConstraintCmp);
4431 
4432  /* Install array only after it's fully valid */
4433  relation->rd_att->constr->check = check;
4434  relation->rd_att->constr->num_check = found;
4435 }
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:4441
#define AccessShareLock
Definition: lockdefs.h:36
Form_pg_class rd_rel
Definition: rel.h:109
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c: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
TupleConstr * constr
Definition: tupdesc.h:85
char * ccname
Definition: tupdesc.h:30
#define RelationGetRelationName(relation)
Definition: rel.h:511
#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:110
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:477
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 5555 of file relcache.c.

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

Referenced by RelationGetIndexAttOptions().

5556 {
5557  bytea **opts = palloc(sizeof(*opts) * natts);
5558 
5559  for (int i = 0; i < natts; i++)
5560  {
5561  bytea *opt = srcopts[i];
5562 
5563  opts[i] = !opt ? NULL : (bytea *)
5564  DatumGetPointer(datumCopy(PointerGetDatum(opt), false, -1));
5565  }
5566 
5567  return opts;
5568 }
#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:111
#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 914 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().

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

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

Referenced by RelationClearRelation().

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

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

5637 {
5641 
5642  return 0; /* return value does not matter */
5643 }
#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:511
int err_generic_string(int field, const char *str)
Definition: elog.c:1351
#define RelationGetNamespace(relation)
Definition: rel.h:518

◆ errtablecol()

int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5653 of file relcache.c.

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

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

5654 {
5655  TupleDesc reldesc = RelationGetDescr(rel);
5656  const char *colname;
5657 
5658  /* Use reldesc if it's a user attribute, else consult the catalogs */
5659  if (attnum > 0 && attnum <= reldesc->natts)
5660  colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
5661  else
5662  colname = get_attname(RelationGetRelid(rel), attnum, false);
5663 
5664  return errtablecolname(rel, colname);
5665 }
#define RelationGetDescr(relation)
Definition: rel.h:503
#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:477
int errtablecolname(Relation rel, const char *colname)
Definition: relcache.c:5677

◆ errtablecolname()

int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5677 of file relcache.c.

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

Referenced by errtablecol().

5678 {
5679  errtable(rel);
5681 
5682  return 0; /* return value does not matter */
5683 }
#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:5636

◆ errtableconstraint()

int errtableconstraint ( Relation  rel,
const char *  conname 
)

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

5691 {
5692  errtable(rel);
5694 
5695  return 0; /* return value does not matter */
5696 }
#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:5636

◆ formrdesc()

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

Definition at line 1807 of file relcache.c.

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

Referenced by RelationCacheInitializePhase2(), and RelationCacheInitializePhase3().

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

◆ GetPgClassDescriptor()

static TupleDesc GetPgClassDescriptor ( void  )
static

Definition at line 4222 of file relcache.c.

References BuildHardcodedDescriptor(), and Desc_pg_class.

Referenced by RelationParseRelOptions().

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

◆ GetPgIndexDescriptor()

static TupleDesc GetPgIndexDescriptor ( void  )
static

Definition at line 4235 of file relcache.c.

References BuildHardcodedDescriptor(), and Desc_pg_index.

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

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

◆ GetRelationPublicationActions()

struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

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

5446 {
5447  List *puboids;
5448  ListCell *lc;
5449  MemoryContext oldcxt;
5450  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5451 
5452  /*
5453  * If not publishable, it publishes no actions. (pgoutput_change() will
5454  * ignore it.)
5455  */
5456  if (!is_publishable_relation(relation))
5457  return pubactions;
5458 
5459  if (relation->rd_pubactions)
5460  return memcpy(pubactions, relation->rd_pubactions,
5461  sizeof(PublicationActions));
5462 
5463  /* Fetch the publication membership info. */
5464  puboids = GetRelationPublications(RelationGetRelid(relation));
5465  if (relation->rd_rel->relispartition)
5466  {
5467  /* Add publications that the ancestors are in too. */
5468  List *ancestors = get_partition_ancestors(RelationGetRelid(relation));
5469  ListCell *lc;
5470 
5471  foreach(lc, ancestors)
5472  {
5473  Oid ancestor = lfirst_oid(lc);
5474 
5475  puboids = list_concat_unique_oid(puboids,
5476  GetRelationPublications(ancestor));
5477  }
5478  }
5479  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5480 
5481  foreach(lc, puboids)
5482  {
5483  Oid pubid = lfirst_oid(lc);
5484  HeapTuple tup;
5485  Form_pg_publication pubform;
5486 
5488 
5489  if (!HeapTupleIsValid(tup))
5490  elog(ERROR, "cache lookup failed for publication %u", pubid);
5491 
5492  pubform = (Form_pg_publication) GETSTRUCT(tup);
5493 
5494  pubactions->pubinsert |= pubform->pubinsert;
5495  pubactions->pubupdate |= pubform->pubupdate;
5496  pubactions->pubdelete |= pubform->pubdelete;
5497  pubactions->pubtruncate |= pubform->pubtruncate;
5498 
5499  ReleaseSysCache(tup);
5500 
5501  /*
5502  * If we know everything is replicated, there is no point to check for
5503  * other publications.
5504  */
5505  if (pubactions->pubinsert && pubactions->pubupdate &&
5506  pubactions->pubdelete && pubactions->pubtruncate)
5507  break;
5508  }
5509 
5510  if (relation->rd_pubactions)
5511  {
5512  pfree(relation->rd_pubactions);
5513  relation->rd_pubactions = NULL;
5514  }
5515 
5516  /* Now save copy of the actions in the relcache entry. */
5518  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5519  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5520  MemoryContextSwitchTo(oldcxt);
5521 
5522  return pubactions;
5523 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
PublicationActions * rd_pubactions
Definition: rel.h:163
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Form_pg_class rd_rel
Definition: rel.h:109
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:477
#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 1530 of file relcache.c.

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

Referenced by RelationInitIndexAccessInfo().

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

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

◆ InitTableAmRoutine()

static void InitTableAmRoutine ( Relation  relation)
static

Definition at line 1734 of file relcache.c.

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

Referenced by RelationInitTableAccessMethod().

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

◆ load_critical_index()

static void load_critical_index ( Oid  indexoid,
Oid  heapoid 
)
static

Definition at line 4156 of file relcache.c.

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

Referenced by RelationCacheInitializePhase3().

4157 {
4158  Relation ird;
4159 
4160  /*
4161  * We must lock the underlying catalog before locking the index to avoid
4162  * deadlock, since RelationBuildDesc might well need to read the catalog,
4163  * and if anyone else is exclusive-locking this catalog and index they'll
4164  * be doing it in that order.
4165  */
4166  LockRelationOid(heapoid, AccessShareLock);
4167  LockRelationOid(indexoid, AccessShareLock);
4168  ird = RelationBuildDesc(indexoid, true);
4169  if (ird == NULL)
4170  elog(PANIC, "could not open critical system index %u", indexoid);
4171  ird->rd_isnailed = true;
4172  ird->rd_refcnt = 1;
4175 
4176  (void) RelationGetIndexAttOptions(ird, false);
4177 }
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:1001
int rd_refcnt
Definition: rel.h:58
#define elog(elevel,...)
Definition: elog.h:232
bytea ** RelationGetIndexAttOptions(Relation relation, bool copy)
Definition: relcache.c:5575
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 5754 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, InvalidTransactionId, 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_partdesc_nodetached, RelationData::rd_partdesc_nodetached_xmin, RelationData::rd_partkey, RelationData::rd_partkeycxt, RelationData::rd_pdcxt, RelationData::rd_pddcxt, RelationData::rd_pkattr, RelationData::rd_pkindex, RelationData::rd_pubactions, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_replidindex, RelationData::rd_rsdesc, RelationData::rd_rules, RelationData::rd_rulescxt, RelationData::rd_smgr, RelationData::rd_statlist, RelationData::rd_statvalid, RelationData::rd_support, RelationData::rd_supportinfo, RelationCacheInsert, RelationGetRelationName, RelationInitLockInfo(), RelationInitPhysicalAddr(), RelationInitTableAccessMethod(), RELCACHE_INIT_FILEMAGIC, RELCACHE_INIT_FILENAME, repalloc(), snprintf, HeapTupleData::t_data, TupleDescData::tdrefcount, TupleDescData::tdtypeid, TupleDescData::tdtypmod, RelationData::trigdesc, TupleDescAttr, VARSIZE, and WARNING.

Referenced by RelationCacheInitializePhase2(), and RelationCacheInitializePhase3().

5755 {
5756  FILE *fp;
5757  char initfilename[MAXPGPATH];
5758  Relation *rels;
5759  int relno,
5760  num_rels,
5761  max_rels,
5762  nailed_rels,
5763  nailed_indexes,
5764  magic;
5765  int i;
5766 
5767  if (shared)
5768  snprintf(initfilename, sizeof(initfilename), "global/%s",
5770  else
5771  snprintf(initfilename, sizeof(initfilename), "%s/%s",
5773 
5774  fp = AllocateFile(initfilename, PG_BINARY_R);
5775  if (fp == NULL)
5776  return false;
5777 
5778  /*
5779  * Read the index relcache entries from the file. Note we will not enter
5780  * any of them into the cache if the read fails partway through; this
5781  * helps to guard against broken init files.
5782  */
5783  max_rels = 100;
5784  rels = (Relation *) palloc(max_rels * sizeof(Relation));
5785  num_rels = 0;
5786  nailed_rels = nailed_indexes = 0;
5787 
5788  /* check for correct magic number (compatible version) */
5789  if (fread(&magic, 1, sizeof(magic), fp) != sizeof(magic))
5790  goto read_failed;
5791  if (magic != RELCACHE_INIT_FILEMAGIC)
5792  goto read_failed;
5793 
5794  for (relno = 0;; relno++)
5795  {
5796  Size len;
5797  size_t nread;
5798  Relation rel;
5799  Form_pg_class relform;
5800  bool has_not_null;
5801 
5802  /* first read the relation descriptor length */
5803  nread = fread(&len, 1, sizeof(len), fp);
5804  if (nread != sizeof(len))
5805  {
5806  if (nread == 0)
5807  break; /* end of file */
5808  goto read_failed;
5809  }
5810 
5811  /* safety check for incompatible relcache layout */
5812  if (len != sizeof(RelationData))
5813  goto read_failed;
5814 
5815  /* allocate another relcache header */
5816  if (num_rels >= max_rels)
5817  {
5818  max_rels *= 2;
5819  rels = (Relation *) repalloc(rels, max_rels * sizeof(Relation));
5820  }
5821 
5822  rel = rels[num_rels++] = (Relation) palloc(len);
5823 
5824  /* then, read the Relation structure */
5825  if (fread(rel, 1, len, fp) != len)
5826  goto read_failed;
5827 
5828  /* next read the relation tuple form */
5829  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5830  goto read_failed;
5831 
5832  relform = (Form_pg_class) palloc(len);
5833  if (fread(relform, 1, len, fp) != len)
5834  goto read_failed;
5835 
5836  rel->rd_rel = relform;
5837 
5838  /* initialize attribute tuple forms */
5839  rel->rd_att = CreateTemplateTupleDesc(relform->relnatts);
5840  rel->rd_att->tdrefcount = 1; /* mark as refcounted */
5841 
5842  rel->rd_att->tdtypeid = relform->reltype ? relform->reltype : RECORDOID;
5843  rel->rd_att->tdtypmod = -1; /* just to be sure */
5844 
5845  /* next read all the attribute tuple form data entries */
5846  has_not_null = false;
5847  for (i = 0; i < relform->relnatts; i++)
5848  {
5849  Form_pg_attribute attr = TupleDescAttr(rel->rd_att, i);
5850 
5851  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5852  goto read_failed;
5853  if (len != ATTRIBUTE_FIXED_PART_SIZE)
5854  goto read_failed;
5855  if (fread(attr, 1, len, fp) != len)
5856  goto read_failed;
5857 
5858  has_not_null |= attr->attnotnull;
5859  }
5860 
5861  /* next read the access method specific field */
5862  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5863  goto read_failed;
5864  if (len > 0)
5865  {
5866  rel->rd_options = palloc(len);
5867  if (fread(rel->rd_options, 1, len, fp) != len)
5868  goto read_failed;
5869  if (len != VARSIZE(rel->rd_options))
5870  goto read_failed; /* sanity check */
5871  }
5872  else
5873  {
5874  rel->rd_options = NULL;
5875  }
5876 
5877  /* mark not-null status */
5878  if (has_not_null)
5879  {
5880  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
5881 
5882  constr->has_not_null = true;
5883  rel->rd_att->constr = constr;
5884  }
5885 
5886  /*
5887  * If it's an index, there's more to do. Note we explicitly ignore
5888  * partitioned indexes here.
5889  */
5890  if (rel->rd_rel->relkind == RELKIND_INDEX)
5891  {
5892  MemoryContext indexcxt;
5893  Oid *opfamily;
5894  Oid *opcintype;
5895  RegProcedure *support;
5896  int nsupport;
5897  int16 *indoption;
5898  Oid *indcollation;
5899 
5900  /* Count nailed indexes to ensure we have 'em all */
5901  if (rel->rd_isnailed)
5902  nailed_indexes++;
5903 
5904  /* next, read the pg_index tuple */
5905  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5906  goto read_failed;
5907 
5908  rel->rd_indextuple = (HeapTuple) palloc(len);
5909  if (fread(rel->rd_indextuple, 1, len, fp) != len)
5910  goto read_failed;
5911 
5912  /* Fix up internal pointers in the tuple -- see heap_copytuple */
5913  rel->rd_indextuple->t_data = (HeapTupleHeader) ((char *) rel->rd_indextuple + HEAPTUPLESIZE);
5915 
5916  /*
5917  * prepare index info context --- parameters should match
5918  * RelationInitIndexAccessInfo
5919  */
5921  "index info",
5923  rel->rd_indexcxt = indexcxt;
5926 
5927  /*
5928  * Now we can fetch the index AM's API struct. (We can't store
5929  * that in the init file, since it contains function pointers that
5930  * might vary across server executions. Fortunately, it should be
5931  * safe to call the amhandler even while bootstrapping indexes.)
5932  */
5933  InitIndexAmRoutine(rel);
5934 
5935  /* next, read the vector of opfamily OIDs */
5936  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5937  goto read_failed;
5938 
5939  opfamily = (Oid *) MemoryContextAlloc(indexcxt, len);
5940  if (fread(opfamily, 1, len, fp) != len)
5941  goto read_failed;
5942 
5943  rel->rd_opfamily = opfamily;
5944 
5945  /* next, read the vector of opcintype OIDs */
5946  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5947  goto read_failed;
5948 
5949  opcintype = (Oid *) MemoryContextAlloc(indexcxt, len);
5950  if (fread(opcintype, 1, len, fp) != len)
5951  goto read_failed;
5952 
5953  rel->rd_opcintype = opcintype;
5954 
5955  /* next, read the vector of support procedure OIDs */
5956  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5957  goto read_failed;
5958  support = (RegProcedure *) MemoryContextAlloc(indexcxt, len);
5959  if (fread(support, 1, len, fp) != len)
5960  goto read_failed;
5961 
5962  rel->rd_support = support;
5963 
5964  /* next, read the vector of collation OIDs */
5965  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5966  goto read_failed;
5967 
5968  indcollation = (Oid *) MemoryContextAlloc(indexcxt, len);
5969  if (fread(indcollation, 1, len, fp) != len)
5970  goto read_failed;
5971 
5972  rel->rd_indcollation = indcollation;
5973 
5974  /* finally, read the vector of indoption values */
5975  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5976  goto read_failed;
5977 
5978  indoption = (int16 *) MemoryContextAlloc(indexcxt, len);
5979  if (fread(indoption, 1, len, fp) != len)
5980  goto read_failed;
5981 
5982  rel->rd_indoption = indoption;
5983 
5984  /* finally, read the vector of opcoptions values */
5985  rel->rd_opcoptions = (bytea **)
5986  MemoryContextAllocZero(indexcxt, sizeof(*rel->rd_opcoptions) * relform->relnatts);
5987 
5988  for (i = 0; i < relform->relnatts; i++)
5989  {
5990  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5991  goto read_failed;
5992 
5993  if (len > 0)
5994  {
5995  rel->rd_opcoptions[i] = (bytea *) MemoryContextAlloc(indexcxt, len);
5996  if (fread(rel->rd_opcoptions[i], 1, len, fp) != len)
5997  goto read_failed;
5998  }
5999  }
6000 
6001  /* set up zeroed fmgr-info vector */
6002  nsupport = relform->relnatts * rel->rd_indam->amsupport;
6003  rel->rd_supportinfo = (FmgrInfo *)
6004  MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
6005  }
6006  else
6007  {
6008  /* Count nailed rels to ensure we have 'em all */
6009  if (rel->rd_isnailed)
6010  nailed_rels++;
6011 
6012  /* Load table AM data */
6013  if (rel->rd_rel->relkind == RELKIND_RELATION ||
6014  rel->rd_rel->relkind == RELKIND_SEQUENCE ||
6015  rel->rd_rel->relkind == RELKIND_TOASTVALUE ||
6016  rel->rd_rel->relkind == RELKIND_MATVIEW)
6018 
6019  Assert(rel->rd_index == NULL);
6020  Assert(rel->rd_indextuple == NULL);
6021  Assert(rel->rd_indexcxt == NULL);
6022  Assert(rel->rd_indam == NULL);
6023  Assert(rel->rd_opfamily == NULL);
6024  Assert(rel->rd_opcintype == NULL);
6025  Assert(rel->rd_support == NULL);
6026  Assert(rel->rd_supportinfo == NULL);
6027  Assert(rel->rd_indoption == NULL);
6028  Assert(rel->rd_indcollation == NULL);
6029  Assert(rel->rd_opcoptions == NULL);
6030  }
6031 
6032  /*
6033  * Rules and triggers are not saved (mainly because the internal
6034  * format is complex and subject to change). They must be rebuilt if
6035  * needed by RelationCacheInitializePhase3. This is not expected to
6036  * be a big performance hit since few system catalogs have such. Ditto
6037  * for RLS policy data, partition info, index expressions, predicates,
6038  * exclusion info, and FDW info.
6039  */
6040  rel->rd_rules = NULL;
6041  rel->rd_rulescxt = NULL;
6042  rel->trigdesc = NULL;
6043  rel->rd_rsdesc = NULL;
6044  rel->rd_partkey = NULL;
6045  rel->rd_partkeycxt = NULL;
6046  rel->rd_partdesc = NULL;
6047  rel->rd_partdesc_nodetached = NULL;
6049  rel->rd_pdcxt = NULL;
6050  rel->rd_pddcxt = NULL;
6051  rel->rd_partcheck = NIL;
6052  rel->rd_partcheckvalid = false;
6053  rel->rd_partcheckcxt = NULL;
6054  rel->rd_indexprs = NIL;
6055  rel->rd_indpred = NIL;
6056  rel->rd_exclops = NULL;
6057  rel->rd_exclprocs = NULL;
6058  rel->rd_exclstrats = NULL;
6059  rel->rd_fdwroutine = NULL;
6060 
6061  /*
6062  * Reset transient-state fields in the relcache entry
6063  */
6064  rel->rd_smgr = NULL;
6065  if (rel->rd_isnailed)
6066  rel->rd_refcnt = 1;
6067  else
6068  rel->rd_refcnt = 0;
6069  rel->rd_indexvalid = false;
6070  rel->rd_indexlist = NIL;
6071  rel->rd_pkindex = InvalidOid;
6072  rel->rd_replidindex = InvalidOid;
6073  rel->rd_indexattr = NULL;
6074  rel->rd_keyattr = NULL;
6075  rel->rd_pkattr = NULL;
6076  rel->rd_idattr = NULL;
6077  rel->rd_pubactions = NULL;
6078  rel->rd_statvalid = false;
6079  rel->rd_statlist = NIL;
6080  rel->rd_fkeyvalid = false;
6081  rel->rd_fkeylist = NIL;
6086  rel->rd_amcache = NULL;
6087  MemSet(&rel->pgstat_info, 0, sizeof(rel->pgstat_info));
6088 
6089  /*
6090  * Recompute lock and physical addressing info. This is needed in
6091  * case the pg_internal.init file was copied from some other database
6092  * by CREATE DATABASE.
6093  */
6094  RelationInitLockInfo(rel);
6096  }
6097 
6098  /*
6099  * We reached the end of the init file without apparent problem. Did we
6100  * get the right number of nailed items? This is a useful crosscheck in
6101  * case the set of critical rels or indexes changes. However, that should
6102  * not happen in a normally-running system, so let's bleat if it does.
6103  *
6104  * For the shared init file, we're called before client authentication is
6105  * done, which means that elog(WARNING) will go only to the postmaster
6106  * log, where it's easily missed. To ensure that developers notice bad
6107  * values of NUM_CRITICAL_SHARED_RELS/NUM_CRITICAL_SHARED_INDEXES, we put
6108  * an Assert(false) there.
6109  */
6110  if (shared)
6111  {
6112  if (nailed_rels != NUM_CRITICAL_SHARED_RELS ||
6113  nailed_indexes != NUM_CRITICAL_SHARED_INDEXES)
6114  {
6115  elog(WARNING, "found %d nailed shared rels and %d nailed shared indexes in init file, but expected %d and %d respectively",
6116  nailed_rels, nailed_indexes,
6118  /* Make sure we get developers' attention about this */
6119  Assert(false);
6120  /* In production builds, recover by bootstrapping the relcache */
6121  goto read_failed;
6122  }
6123  }
6124  else
6125  {
6126  if (nailed_rels != NUM_CRITICAL_LOCAL_RELS ||
6127  nailed_indexes != NUM_CRITICAL_LOCAL_INDEXES)
6128  {
6129  elog(WARNING, "found %d nailed rels and %d nailed indexes in init file, but expected %d and %d respectively",
6130  nailed_rels, nailed_indexes,
6132  /* We don't need an Assert() in this case */
6133  goto read_failed;
6134  }
6135  }
6136 
6137  /*
6138  * OK, all appears well.
6139  *
6140  * Now insert all the new relcache entries into the cache.
6141  */
6142  for (relno = 0; relno < num_rels; relno++)
6143  {
6144  RelationCacheInsert(rels[relno], false);
6145  }
6146 
6147  pfree(rels);
6148  FreeFile(fp);
6149 
6150  if (shared)
6152  else
6153  criticalRelcachesBuilt = true;
6154  return true;
6155 
6156  /*
6157  * init file is broken, so do it the hard way. We don't bother trying to
6158  * free the clutter we just allocated; it's not in the relcache so it
6159  * won't hurt.
6160  */
6161 read_failed:
6162  pfree(rels);
6163  FreeFile(fp);
6164 
6165  return false;
6166 }
struct FdwRoutine * rd_fdwroutine
Definition: rel.h:235
signed short int16
Definition: c.h:428
#define NIL
Definition: pg_list.h:65
struct IndexAmRoutine * rd_indam
Definition: rel.h:201
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:206
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
PublicationActions * rd_pubactions
Definition: rel.h:163
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:45
struct FmgrInfo * rd_supportinfo
Definition: rel.h:205
Bitmapset * rd_keyattr
Definition: rel.h:159
#define VARSIZE(PTR)
Definition: postgres.h:316
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
void RelationInitTableAccessMethod(Relation relation)
Definition: relcache.c:1743
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
Oid rd_replidindex
Definition: rel.h:152
#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:211
#define NUM_CRITICAL_LOCAL_INDEXES
List * rd_indexprs
Definition: rel.h:207
bytea ** rd_opcoptions
Definition: rel.h:213
List * rd_fkeylist
Definition: rel.h:120
bool rd_partcheckvalid
Definition: rel.h:146
#define MemSet(start, val, len)
Definition: c.h:1008
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:103
MemoryContext rd_rulescxt
Definition: rel.h:114
bool criticalSharedRelcachesBuilt
Definition: relcache.c:143
Oid * rd_exclprocs
Definition: rel.h:210
Form_pg_class rd_rel
Definition: rel.h:109
unsigned int Oid
Definition: postgres_ext.h:31
#define NUM_CRITICAL_SHARED_INDEXES
#define PG_BINARY_R
Definition: c.h:1273
#define NUM_CRITICAL_SHARED_RELS
static void InitIndexAmRoutine(Relation relation)
Definition: relcache.c:1336
struct HeapTupleData * rd_indextuple
Definition: rel.h:189
HeapTupleHeader t_data
Definition: htup.h:68
struct RelationData * Relation
Definition: relcache.h:27
Form_pg_index rd_index
Definition: rel.h:187
PartitionKey rd_partkey
Definition: rel.h:124
void pfree(void *pointer)
Definition: mcxt.c:1169
#define NUM_CRITICAL_LOCAL_RELS
Oid * rd_indcollation
Definition: rel.h:212
int32 tdtypmod
Definition: tupdesc.h:83
Oid rd_pkindex
Definition: rel.h:151
#define MAXPGPATH
TriggerDesc * trigdesc
Definition: rel.h:115
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1254
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:2417
#define InvalidTransactionId
Definition: transam.h:31
#define RELCACHE_INIT_FILEMAGIC
Definition: relcache.c:90
#define RelationGetRelationName(relation)
Definition: rel.h:511
MemoryContext rd_pddcxt
Definition: rel.h:133
List * rd_indpred
Definition: rel.h:208
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
Oid * rd_opfamily
Definition: rel.h:202
Oid * rd_exclops
Definition: rel.h:209
PartitionDesc rd_partdesc
Definition: rel.h:128
TransactionId rd_partdesc_nodetached_xmin
Definition: rel.h:142
List * rd_indexlist
Definition: rel.h:150
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:199
struct RowSecurityDesc * rd_rsdesc
Definition: rel.h:117
RegProcedure * rd_support
Definition: rel.h:204
#define WARNING
Definition: elog.h:40
FormData_pg_index * Form_pg_index
Definition: pg_index.h:69
SubTransactionId rd_createSubid
Definition: rel.h:102
bool rd_indexvalid
Definition: rel.h:63
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
void * palloc0(Size size)
Definition: mcxt.c:1093
PartitionDesc rd_partdesc_nodetached
Definition: rel.h:132
TupleDesc rd_att
Definition: rel.h:110
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:161
#define RelationCacheInsert(RELATION, replace_allowed)
Definition: relcache.c:188
char * DatabasePath
Definition: globals.c:96
MemoryContext rd_pdcxt
Definition: rel.h:129
#define Assert(condition)
Definition: c.h:804
MemoryContext rd_partkeycxt
Definition: rel.h:125
SMgrRelation rd_smgr
Definition: rel.h:57
RuleLock * rd_rules
Definition: rel.h:113
size_t Size
Definition: c.h:540
struct PgStat_TableStatus * pgstat_info
Definition: rel.h:249
#define InvalidSubTransactionId
Definition: c.h:593
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
int FreeFile(FILE *file)
Definition: fd.c:2616
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
Bitmapset * rd_pkattr
Definition: rel.h:160
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:199
int i
int tdrefcount
Definition: tupdesc.h:84
Definition: c.h:621
MemoryContext rd_partcheckcxt
Definition: rel.h:147
bool criticalRelcachesBuilt
Definition: relcache.c:137
void * rd_amcache
Definition: rel.h:224
Oid * rd_opcintype
Definition: rel.h:203
bool has_not_null
Definition: tupdesc.h:44
List * rd_statlist
Definition: rel.h:155
#define snprintf
Definition: port.h:216
bool rd_fkeyvalid
Definition: rel.h:121
List * rd_partcheck
Definition: rel.h:145
Bitmapset * rd_indexattr
Definition: rel.h:158
bytea * rd_options
Definition: rel.h:170
SubTransactionId rd_droppedSubid
Definition: rel.h:107
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ LookupOpclassInfo()

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

Definition at line 1581 of file relcache.c.

References AccessShareLock, Assert, BTEqualStrategyNumber, CacheMemoryContext, CreateCacheMemoryContext(), criticalRelcachesBuilt, debug_discard_caches, 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, ScanKeyInit(), opclasscacheent::supportProcs, systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), and opclasscacheent::valid.

Referenced by IndexSupportInitialize().

1583 {
1584  OpClassCacheEnt *opcentry;
1585  bool found;
1586  Relation rel;
1587  SysScanDesc scan;
1588  ScanKeyData skey[3];
1589  HeapTuple htup;
1590  bool indexOK;
1591 
1592  if (OpClassCache == NULL)
1593  {
1594  /* First time through: initialize the opclass cache */
1595  HASHCTL ctl;
1596 
1597  /* Also make sure CacheMemoryContext exists */
1598  if (!CacheMemoryContext)
1600 
1601  ctl.keysize = sizeof(Oid);
1602  ctl.entrysize = sizeof(OpClassCacheEnt);
1603  OpClassCache = hash_create("Operator class cache", 64,
1604  &ctl, HASH_ELEM | HASH_BLOBS);
1605  }
1606 
1607  opcentry = (OpClassCacheEnt *) hash_search(OpClassCache,
1608  (void *) &operatorClassOid,
1609  HASH_ENTER, &found);
1610 
1611  if (!found)
1612  {
1613  /* Initialize new entry */
1614  opcentry->valid = false; /* until known OK */
1615  opcentry->numSupport = numSupport;
1616  opcentry->supportProcs = NULL; /* filled below */
1617  }
1618  else
1619  {
1620  Assert(numSupport == opcentry->numSupport);
1621  }
1622 
1623  /*
1624  * When aggressively testing cache-flush hazards, we disable the operator
1625  * class cache and force reloading of the info on each call. This models
1626  * no real-world behavior, since the cache entries are never invalidated
1627  * otherwise. However it can be helpful for detecting bugs in the cache
1628  * loading logic itself, such as reliance on a non-nailed index. Given
1629  * the limited use-case and the fact that this adds a great deal of
1630  * expense, we enable it only for high values of debug_discard_caches.
1631  */
1632 #ifdef DISCARD_CACHES_ENABLED
1633  if (debug_discard_caches > 2)
1634  opcentry->valid = false;
1635 #endif
1636 
1637  if (opcentry->valid)
1638  return opcentry;
1639 
1640  /*
1641  * Need to fill in new entry. First allocate space, unless we already did
1642  * so in some previous attempt.
1643  */
1644  if (opcentry->supportProcs == NULL && numSupport > 0)
1645  opcentry->supportProcs = (RegProcedure *)
1647  numSupport * sizeof(RegProcedure));
1648 
1649  /*
1650  * To avoid infinite recursion during startup, force heap scans if we're
1651  * looking up info for the opclasses used by the indexes we would like to
1652  * reference here.
1653  */
1654  indexOK = criticalRelcachesBuilt ||
1655  (operatorClassOid != OID_BTREE_OPS_OID &&
1656  operatorClassOid != INT2_BTREE_OPS_OID);
1657 
1658  /*
1659  * We have to fetch the pg_opclass row to determine its opfamily and
1660  * opcintype, which are needed to look up related operators and functions.
1661  * It'd be convenient to use the syscache here, but that probably doesn't
1662  * work while bootstrapping.
1663  */
1664  ScanKeyInit(&skey[0],
1665  Anum_pg_opclass_oid,
1666  BTEqualStrategyNumber, F_OIDEQ,
1667  ObjectIdGetDatum(operatorClassOid));
1668  rel = table_open(OperatorClassRelationId, AccessShareLock);
1669  scan = systable_beginscan(rel, OpclassOidIndexId, indexOK,
1670  NULL, 1, skey);
1671 
1672  if (HeapTupleIsValid(htup = systable_getnext(scan)))
1673  {
1674  Form_pg_opclass opclassform = (Form_pg_opclass) GETSTRUCT(htup);
1675 
1676  opcentry->opcfamily = opclassform->opcfamily;
1677  opcentry->opcintype = opclassform->opcintype;
1678  }
1679  else
1680  elog(ERROR, "could not find tuple for opclass %u", operatorClassOid);
1681 
1682  systable_endscan(scan);
1684 
1685  /*
1686  * Scan pg_amproc to obtain support procs for the opclass. We only fetch
1687  * the default ones (those with lefttype = righttype = opcintype).
1688  */
1689  if (numSupport > 0)
1690  {
1691  ScanKeyInit(&skey[0],
1692  Anum_pg_amproc_amprocfamily,
1693  BTEqualStrategyNumber, F_OIDEQ,
1694  ObjectIdGetDatum(opcentry->opcfamily));
1695  ScanKeyInit(&skey[1],
1696  Anum_pg_amproc_amproclefttype,
1697  BTEqualStrategyNumber, F_OIDEQ,
1698  ObjectIdGetDatum(opcentry->opcintype));
1699  ScanKeyInit(&skey[2],
1700  Anum_pg_amproc_amprocrighttype,
1701  BTEqualStrategyNumber, F_OIDEQ,
1702  ObjectIdGetDatum(opcentry->opcintype));
1703  rel = table_open(AccessMethodProcedureRelationId, AccessShareLock);
1704  scan = systable_beginscan(rel, AccessMethodProcedureIndexId, indexOK,
1705  NULL, 3, skey);
1706 
1707  while (HeapTupleIsValid(htup = systable_getnext(scan)))
1708  {
1709  Form_pg_amproc amprocform = (Form_pg_amproc) GETSTRUCT(htup);
1710 
1711  if (amprocform->amprocnum <= 0 ||
1712  (StrategyNumber) amprocform->amprocnum > numSupport)
1713  elog(ERROR, "invalid amproc number %d for opclass %u",
1714  amprocform->amprocnum, operatorClassOid);
1715 
1716  opcentry->supportProcs[amprocform->amprocnum - 1] =
1717  amprocform->amproc;
1718  }
1719 
1720  systable_endscan(scan);
1722  }
1723 
1724  opcentry->valid = true;
1725  return opcentry;
1726 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c: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
int debug_discard_caches
Definition: inval.c:185
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
StrategyNumber numSupport
Definition: relcache.c:244
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
RegProcedure * supportProcs
Definition: relcache.c:247
static HTAB * OpClassCache
Definition: relcache.c:250
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 * 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:137
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 3749 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().

3750 {
3753  relation->rd_firstRelfilenodeSubid = relation->rd_newRelfilenodeSubid;
3754 
3755  /* Flag relation as needing eoxact cleanup (to clear these fields) */
3756  EOXactListAdd(relation);
3757 }
#define EOXactListAdd(rel)
Definition: relcache.c:168
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:103
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
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 1001 of file relcache.c.

References AllocateRelationDesc(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, BackendIdForTempRelations, CurrentMemoryContext, debug_discard_caches, elog, ERROR, GETSTRUCT, GetTempNamespaceBackendId(), heap_freetuple(), HeapTupleIsValid, InvalidBackendId, InvalidOid, InvalidSubTransactionId, InvalidTransactionId, 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_partdesc_nodetached, RelationData::rd_partdesc_nodetached_xmin, RelationData::rd_partkey, RelationData::rd_partkeycxt, RelationData::rd_pdcxt, RelationData::rd_pddcxt, 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().

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

◆ RelationBuildLocalRelation()

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

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

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

◆ RelationBuildRuleLock()

static void RelationBuildRuleLock ( Relation  relation)
static

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

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

References AccessShareLock, AttrMissing::am_present, AttrMissing::am_value, array_get_element(), Assert, attnum, AttrDefaultFetch(), ATTRIBUTE_FIXED_PART_SIZE, 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().

499 {
500  HeapTuple pg_attribute_tuple;
501  Relation pg_attribute_desc;
502  SysScanDesc pg_attribute_scan;
503  ScanKeyData skey[2];
504  int need;
505  TupleConstr *constr;
506  AttrMissing *attrmiss = NULL;
507  int ndef = 0;
508 
509  /* fill rd_att's type ID fields (compare heap.c's AddNewRelationTuple) */
510  relation->rd_att->tdtypeid =
511  relation->rd_rel->reltype ? relation->rd_rel->reltype : RECORDOID;
512  relation->rd_att->tdtypmod = -1; /* just to be sure */
513 
515  sizeof(TupleConstr));
516  constr->has_not_null = false;
517  constr->has_generated_stored = false;
518 
519  /*
520  * Form a scan key that selects only user attributes (attnum > 0).
521  * (Eliminating system attribute rows at the index level is lots faster
522  * than fetching them.)
523  */
524  ScanKeyInit(&skey[0],
525  Anum_pg_attribute_attrelid,
526  BTEqualStrategyNumber, F_OIDEQ,
528  ScanKeyInit(&skey[1],
529  Anum_pg_attribute_attnum,
530  BTGreaterStrategyNumber, F_INT2GT,
531  Int16GetDatum(0));
532 
533  /*
534  * Open pg_attribute and begin a scan. Force heap scan if we haven't yet
535  * built the critical relcache entries (this includes initdb and startup
536  * without a pg_internal.init file).
537  */
538  pg_attribute_desc = table_open(AttributeRelationId, AccessShareLock);
539  pg_attribute_scan = systable_beginscan(pg_attribute_desc,
540  AttributeRelidNumIndexId,
542  NULL,
543  2, skey);
544 
545  /*
546  * add attribute data to relation->rd_att
547  */
548  need = RelationGetNumberOfAttributes(relation);
549 
550  while (HeapTupleIsValid(pg_attribute_tuple = systable_getnext(pg_attribute_scan)))
551  {
552  Form_pg_attribute attp;
553  int attnum;
554 
555  attp = (Form_pg_attribute) GETSTRUCT(pg_attribute_tuple);
556 
557  attnum = attp->attnum;
558  if (attnum <= 0 || attnum > RelationGetNumberOfAttributes(relation))
559  elog(ERROR, "invalid attribute number %d for relation \"%s\"",
560  attp->attnum, RelationGetRelationName(relation));
561 
562  memcpy(TupleDescAttr(relation->rd_att, attnum - 1),
563  attp,
565 
566  /* Update constraint/default info */
567  if (attp->attnotnull)
568  constr->has_not_null = true;
569  if (attp->attgenerated == ATTRIBUTE_GENERATED_STORED)
570  constr->has_generated_stored = true;
571  if (attp->atthasdef)
572  ndef++;
573 
574  /* If the column has a "missing" value, put it in the attrmiss array */
575  if (attp->atthasmissing)
576  {
577  Datum missingval;
578  bool missingNull;
579 
580  /* Do we have a missing value? */
581  missingval = heap_getattr(pg_attribute_tuple,
582  Anum_pg_attribute_attmissingval,
583  pg_attribute_desc->rd_att,
584  &missingNull);
585  if (!missingNull)
586  {
587  /* Yes, fetch from the array */
588  MemoryContext oldcxt;
589  bool is_null;
590  int one = 1;
591  Datum missval;
592 
593  if (attrmiss == NULL)
594  attrmiss = (AttrMissing *)
596  relation->rd_rel->relnatts *
597  sizeof(AttrMissing));
598 
599  missval = array_get_element(missingval,
600  1,
601  &one,
602  -1,
603  attp->attlen,
604  attp->attbyval,
605  attp->attalign,
606  &is_null);
607  Assert(!is_null);
608  if (attp->attbyval)
609  {
610  /* for copy by val just copy the datum direct */
611  attrmiss[attnum - 1].am_value = missval;
612  }
613  else
614  {
615  /* otherwise copy in the correct context */
617  attrmiss[attnum - 1].am_value = datumCopy(missval,
618  attp->attbyval,
619  attp->attlen);
620  MemoryContextSwitchTo(oldcxt);
621  }
622  attrmiss[attnum - 1].am_present = true;
623  }
624  }
625  need--;
626  if (need == 0)
627  break;
628  }
629 
630  /*
631  * end the scan and close the attribute relation
632  */
633  systable_endscan(pg_attribute_scan);
634  table_close(pg_attribute_desc, AccessShareLock);
635 
636  if (need != 0)
637  elog(ERROR, "pg_attribute catalog is missing %d attribute(s) for relation OID %u",
638  need, RelationGetRelid(relation));
639 
640  /*
641  * The attcacheoff values we read from pg_attribute should all be -1
642  * ("unknown"). Verify this if assert checking is on. They will be
643  * computed when and if needed during tuple access.
644  */
645 #ifdef USE_ASSERT_CHECKING
646  {
647  int i;
648 
649  for (i = 0; i < RelationGetNumberOfAttributes(relation); i++)
650  Assert(TupleDescAttr(relation->rd_att, i)->attcacheoff == -1);
651  }
652 #endif
653 
654  /*
655  * However, we can easily set the attcacheoff value for the first
656  * attribute: it must be zero. This eliminates the need for special cases
657  * for attnum=1 that used to exist in fastgetattr() and index_getattr().
658  */
659  if (RelationGetNumberOfAttributes(relation) > 0)
660  TupleDescAttr(relation->rd_att, 0)->attcacheoff = 0;
661 
662  /*
663  * Set up constraint/default info
664  */
665  if (constr->has_not_null ||
666  constr->has_generated_stored ||
667  ndef > 0 ||
668  attrmiss ||
669  relation->rd_rel->relchecks > 0)
670  {
671  relation->rd_att->constr = constr;
672 
673  if (ndef > 0) /* DEFAULTs */
674  AttrDefaultFetch(relation, ndef);
675  else
676  constr->num_defval = 0;
677 
678  constr->missing = attrmiss;
679 
680  if (relation->rd_rel->relchecks > 0) /* CHECKs */
681  CheckConstraintFetch(relation);
682  else
683  constr->num_check = 0;
684  }
685  else
686  {
687  pfree(constr);
688  relation->rd_att->constr = NULL;
689  }
690 }
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:483
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
static void AttrDefaultFetch(Relation relation, int ndef)
Definition: relcache.c:4257
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:109
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
TupleConstr * constr
Definition: tupdesc.h:85
#define RelationGetRelationName(relation)
Definition: rel.h:511
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:199
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:110
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:1830
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
static void CheckConstraintFetch(Relation relation)
Definition: relcache.c:4352
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:137
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:477
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ RelationCacheInitFilePostInvalidate()

void RelationCacheInitFilePostInvalidate ( void  )

Definition at line 6465 of file relcache.c.

References LWLockRelease().

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

6466 {
6467  LWLockRelease(RelCacheInitLock);
6468 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )

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

6441 {
6442  char localinitfname[MAXPGPATH];
6443  char sharedinitfname[MAXPGPATH];
6444 
6445  if (DatabasePath)
6446  snprintf(localinitfname, sizeof(localinitfname), "%s/%s",
6448  snprintf(sharedinitfname, sizeof(sharedinitfname), "global/%s",
6450 
6451  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6452 
6453  /*
6454  * The files might not be there if no backend has been started since the
6455  * last removal. But complain about failures other than ENOENT with
6456  * ERROR. Fortunately, it's not too late to abort the transaction if we
6457  * can't get rid of the would-be-obsolete init file.
6458  */
6459  if (DatabasePath)
6460  unlink_initfile(localinitfname, ERROR);
6461  unlink_initfile(sharedinitfname, ERROR);
6462 }
#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:1199
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6537
#define snprintf
Definition: port.h:216

◆ RelationCacheInitFileRemove()

void RelationCacheInitFileRemove ( void  )

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

6481 {
6482  const char *tblspcdir = "pg_tblspc";
6483  DIR *dir;
6484  struct dirent *de;
6485  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6486 
6487  snprintf(path, sizeof(path), "global/%s",
6489  unlink_initfile(path, LOG);
6490 
6491  /* Scan everything in the default tablespace */
6493 
6494  /* Scan the tablespace link directory to find non-default tablespaces */
6495  dir = AllocateDir(tblspcdir);
6496 
6497  while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6498  {
6499  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6500  {
6501  /* Scan the tablespace dir for per-database dirs */
6502  snprintf(path, sizeof(path), "%s/%s/%s",
6503  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6505  }
6506  }
6507 
6508  FreeDir(dir);
6509 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6513
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2759
#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:2678
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6537
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:216
int FreeDir(DIR *dir)
Definition: fd.c:2796

◆ RelationCacheInitFileRemoveInDir()

static void RelationCacheInitFileRemoveInDir ( const char *  tblspcpath)
static

Definition at line 6513 of file relcache.c.

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

Referenced by RelationCacheInitFileRemove().

6514 {
6515  DIR *dir;
6516  struct dirent *de;
6517  char initfilename[MAXPGPATH * 2];
6518 
6519  /* Scan the tablespace directory to find per-database directories */
6520  dir = AllocateDir(tblspcpath);
6521 
6522  while ((de = ReadDirExtended(dir, tblspcpath, LOG)) != NULL)
6523  {
6524  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6525  {
6526  /* Try to remove the init file in each database */
6527  snprintf(initfilename, sizeof(initfilename), "%s/%s/%s",
6528  tblspcpath, de->d_name, RELCACHE_INIT_FILENAME);
6529  unlink_initfile(initfilename, LOG);
6530  }
6531  }
6532 
6533  FreeDir(dir);
6534 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2759
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2678
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:25
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6537
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:216
int FreeDir(DIR *dir)
Definition: fd.c:2796

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 3775 of file relcache.c.

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

Referenced by InitPostgres().

3776 {
3777  HASHCTL ctl;
3778 
3779  /*
3780  * make sure cache memory context exists
3781  */
3782  if (!CacheMemoryContext)
3784 
3785  /*
3786  * create hashtable that indexes the relcache
3787  */
3788  ctl.keysize = sizeof(Oid);
3789  ctl.entrysize = sizeof(RelIdCacheEnt);
3790  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3791  &ctl, HASH_ELEM | HASH_BLOBS);
3792 
3793  /*
3794  * relation mapper needs to be initialized too
3795  */
3797 }
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:131
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:3772
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ RelationCacheInitializePhase2()

void RelationCacheInitializePhase2 ( void  )

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

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

◆ RelationCacheInitializePhase3()

void RelationCacheInitializePhase3 ( void  )

Definition at line 3870 of file relcache.c.

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

Referenced by InitPostgres().

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

◆ RelationCacheInvalidate()

void RelationCacheInvalidate ( void  )

Definition at line 2840 of file relcache.c.

References Assert, 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().

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

◆ RelationCacheInvalidateEntry()

void RelationCacheInvalidateEntry ( Oid  relationId)

Definition at line 2797 of file relcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

2798 {
2799  Relation relation;
2800 
2801  RelationIdCacheLookup(relationId, relation);
2802 
2803  if (PointerIsValid(relation))
2804  {
2806  RelationFlushRelation(relation);
2807  }
2808 }
static long relcacheInvalsReceived
Definition: relcache.c:151
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:210
static void RelationFlushRelation(Relation relation)
Definition: relcache.c:2720
#define PointerIsValid(pointer)
Definition: c.h:698

◆ RelationClearRelation()

static void RelationClearRelation ( Relation  relation,
bool  rebuild 
)
static

Definition at line 2431 of file relcache.c.

References Assert, CLASS_TUPLE_SIZE, elog, equalRSDesc(), equalRuleLocks(), equalTupleDescs(), ERROR, HistoricSnapshotActive(), InvalidSubTransactionId, InvalidTransactionId, 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_partdesc_nodetached, RelationData::rd_partdesc_nodetached_xmin, RelationData::rd_partkey, RelationData::rd_pdcxt, RelationData::rd_pddcxt, 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().

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