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  inprogressent
 
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 inprogressent InProgressEnt
 
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 (bool debug_discard)
 
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 InProgressEntin_progress_list
 
static int in_progress_list_len
 
static int in_progress_list_maxlen
 
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:181
static int eoxact_list_len
Definition: relcache.c:183

Definition at line 186 of file relcache.c.

Referenced by RelationAssumeNewRelfilenode(), and RelationBuildLocalRelation().

◆ INITRELCACHESIZE

#define INITRELCACHESIZE   400

Definition at line 3865 of file relcache.c.

Referenced by RelationCacheInitialize().

◆ MAX_EOXACT_LIST

#define MAX_EOXACT_LIST   32

Definition at line 181 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 240 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 206 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 228 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

◆ InProgressEnt

typedef struct inprogressent InProgressEnt

◆ OpClassCacheEnt

◆ RelIdCacheEnt

typedef struct relidcacheent RelIdCacheEnt

Function Documentation

◆ AllocateRelationDesc()

static Relation AllocateRelationDesc ( Form_pg_class  relp)
static

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

405 {
406  Relation relation;
407  MemoryContext oldcxt;
408  Form_pg_class relationForm;
409 
410  /* Relcache entries must live in CacheMemoryContext */
412 
413  /*
414  * allocate and zero space for new relation descriptor
415  */
416  relation = (Relation) palloc0(sizeof(RelationData));
417 
418  /* make sure relation is marked as having no open file yet */
419  relation->rd_smgr = NULL;
420 
421  /*
422  * Copy the relation tuple form
423  *
424  * We only allocate space for the fixed fields, ie, CLASS_TUPLE_SIZE. The
425  * variable-length fields (relacl, reloptions) are NOT stored in the
426  * relcache --- there'd be little point in it, since we don't copy the
427  * tuple's nulls bitmap and hence wouldn't know if the values are valid.
428  * Bottom line is that relacl *cannot* be retrieved from the relcache. Get
429  * it from the syscache if you need it. The same goes for the original
430  * form of reloptions (however, we do store the parsed form of reloptions
431  * in rd_options).
432  */
433  relationForm = (Form_pg_class) palloc(CLASS_TUPLE_SIZE);
434 
435  memcpy(relationForm, relp, CLASS_TUPLE_SIZE);
436 
437  /* initialize relation tuple form */
438  relation->rd_rel = relationForm;
439 
440  /* and allocate attribute tuple form storage */
441  relation->rd_att = CreateTemplateTupleDesc(relationForm->relnatts);
442  /* which we mark as a reference-counted tupdesc */
443  relation->rd_att->tdrefcount = 1;
444 
445  MemoryContextSwitchTo(oldcxt);
446 
447  return relation;
448 }
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:26
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 3363 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().

3365 {
3366  /*
3367  * Is it a relation created in the current subtransaction?
3368  *
3369  * During subcommit, mark it as belonging to the parent, instead, as long
3370  * as it has not been dropped. Otherwise simply delete the relcache entry.
3371  * --- it isn't interesting any longer.
3372  */
3373  if (relation->rd_createSubid == mySubid)
3374  {
3375  /*
3376  * Valid rd_droppedSubid means the corresponding relation is dropped
3377  * but the relcache entry is preserved for at-commit pending sync. We
3378  * need to drop it explicitly here not to make the entry orphan.
3379  */
3380  Assert(relation->rd_droppedSubid == mySubid ||
3382  if (isCommit && relation->rd_droppedSubid == InvalidSubTransactionId)
3383  relation->rd_createSubid = parentSubid;
3384  else if (RelationHasReferenceCountZero(relation))
3385  {
3386  /* allow the entry to be removed */
3391  RelationClearRelation(relation, false);
3392  return;
3393  }
3394  else
3395  {
3396  /*
3397  * Hmm, somewhere there's a (leaked?) reference to the relation.
3398  * We daren't remove the entry for fear of dereferencing a
3399  * dangling pointer later. Bleat, and transfer it to the parent
3400  * subtransaction so we can try again later. This must be just a
3401  * WARNING to avoid error-during-error-recovery loops.
3402  */
3403  relation->rd_createSubid = parentSubid;
3404  elog(WARNING, "cannot remove relcache entry for \"%s\" because it has nonzero refcount",
3405  RelationGetRelationName(relation));
3406  }
3407  }
3408 
3409  /*
3410  * Likewise, update or drop any new-relfilenode-in-subtransaction record
3411  * or drop record.
3412  */
3413  if (relation->rd_newRelfilenodeSubid == mySubid)
3414  {
3415  if (isCommit)
3416  relation->rd_newRelfilenodeSubid = parentSubid;
3417  else
3419  }
3420 
3421  if (relation->rd_firstRelfilenodeSubid == mySubid)
3422  {
3423  if (isCommit)
3424  relation->rd_firstRelfilenodeSubid = parentSubid;
3425  else
3427  }
3428 
3429  if (relation->rd_droppedSubid == mySubid)
3430  {
3431  if (isCommit)
3432  relation->rd_droppedSubid = parentSubid;
3433  else
3435  }
3436 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2482
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 3308 of file relcache.c.

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

3310 {
3312  RelIdCacheEnt *idhentry;
3313  int i;
3314 
3315  /*
3316  * Forget in_progress_list. This is relevant when we're aborting due to
3317  * an error during RelationBuildDesc(). We don't commit subtransactions
3318  * during RelationBuildDesc().
3319  */
3320  Assert(in_progress_list_len == 0 || !isCommit);
3322 
3323  /*
3324  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3325  * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3326  * logic as in AtEOXact_RelationCache.
3327  */
3329  {
3330  hash_seq_init(&status, RelationIdCache);
3331  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3332  {
3333  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3334  mySubid, parentSubid);
3335  }
3336  }
3337  else
3338  {
3339  for (i = 0; i < eoxact_list_len; i++)
3340  {
3341  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3342  (void *) &eoxact_list[i],
3343  HASH_FIND,
3344  NULL);
3345  if (idhentry != NULL)
3346  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3347  mySubid, parentSubid);
3348  }
3349  }
3350 
3351  /* Don't reset the list; we still need more cleanup later */
3352 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:182
static void AtEOSubXact_cleanup(Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
Definition: relcache.c:3363
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:184
static int in_progress_list_len
Definition: relcache.c:168
#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
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:229
static int eoxact_list_len
Definition: relcache.c:183

◆ AtEOXact_cleanup()

static void AtEOXact_cleanup ( Relation  relation,
bool  isCommit 
)
static

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

3227 {
3228  bool clear_relcache = false;
3229 
3230  /*
3231  * The relcache entry's ref count should be back to its normal
3232  * not-in-a-transaction state: 0 unless it's nailed in cache.
3233  *
3234  * In bootstrap mode, this is NOT true, so don't check it --- the
3235  * bootstrap code expects relations to stay open across start/commit
3236  * transaction calls. (That seems bogus, but it's not worth fixing.)
3237  *
3238  * Note: ideally this check would be applied to every relcache entry, not
3239  * just those that have eoxact work to do. But it's not worth forcing a
3240  * scan of the whole relcache just for this. (Moreover, doing so would
3241  * mean that assert-enabled testing never tests the hash_search code path
3242  * above, which seems a bad idea.)
3243  */
3244 #ifdef USE_ASSERT_CHECKING
3246  {
3247  int expected_refcnt;
3248 
3249  expected_refcnt = relation->rd_isnailed ? 1 : 0;
3250  Assert(relation->rd_refcnt == expected_refcnt);
3251  }
3252 #endif
3253 
3254  /*
3255  * Is the relation live after this transaction ends?
3256  *
3257  * During commit, clear the relcache entry if it is preserved after
3258  * relation drop, in order not to orphan the entry. During rollback,
3259  * clear the relcache entry if the relation is created in the current
3260  * transaction since it isn't interesting any longer once we are out of
3261  * the transaction.
3262  */
3263  clear_relcache =
3264  (isCommit ?
3267 
3268  /*
3269  * Since we are now out of the transaction, reset the subids to zero. That
3270  * also lets RelationClearRelation() drop the relcache entry.
3271  */
3276 
3277  if (clear_relcache)
3278  {
3279  if (RelationHasReferenceCountZero(relation))
3280  {
3281  RelationClearRelation(relation, false);
3282  return;
3283  }
3284  else
3285  {
3286  /*
3287  * Hmm, somewhere there's a (leaked?) reference to the relation.
3288  * We daren't remove the entry for fear of dereferencing a
3289  * dangling pointer later. Bleat, and mark it as not belonging to
3290  * the current transaction. Hopefully it'll get cleaned up
3291  * eventually. This must be just a WARNING to avoid
3292  * error-during-error-recovery loops.
3293  */
3294  elog(WARNING, "cannot remove relcache entry for \"%s\" because it has nonzero refcount",
3295  RelationGetRelationName(relation));
3296  }
3297  }
3298 }
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2482
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 3156 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, in_progress_list_len, NextEOXactTupleDescNum, pfree(), relidcacheent::reldesc, and status().

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

3157 {
3159  RelIdCacheEnt *idhentry;
3160  int i;
3161 
3162  /*
3163  * Forget in_progress_list. This is relevant when we're aborting due to
3164  * an error during RelationBuildDesc().
3165  */
3166  Assert(in_progress_list_len == 0 || !isCommit);
3168 
3169  /*
3170  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3171  * listed in it. Otherwise fall back on a hash_seq_search scan.
3172  *
3173  * For simplicity, eoxact_list[] entries are not deleted till end of
3174  * top-level transaction, even though we could remove them at
3175  * subtransaction end in some cases, or remove relations from the list if
3176  * they are cleared for other reasons. Therefore we should expect the
3177  * case that list entries are not found in the hashtable; if not, there's
3178  * nothing to do for them.
3179  */
3181  {
3182  hash_seq_init(&status, RelationIdCache);
3183  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3184  {
3185  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3186  }
3187  }
3188  else
3189  {
3190  for (i = 0; i < eoxact_list_len; i++)
3191  {
3192  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3193  (void *) &eoxact_list[i],
3194  HASH_FIND,
3195  NULL);
3196  if (idhentry != NULL)
3197  AtEOXact_cleanup(idhentry->reldesc, isCommit);
3198  }
3199  }
3200 
3201  if (EOXactTupleDescArrayLen > 0)
3202  {
3203  Assert(EOXactTupleDescArray != NULL);
3204  for (i = 0; i < NextEOXactTupleDescNum; i++)
3207  EOXactTupleDescArray = NULL;
3208  }
3209 
3210  /* Now we're out of the transaction and can clear the lists */
3211  eoxact_list_len = 0;
3212  eoxact_list_overflowed = false;
3213  NextEOXactTupleDescNum = 0;
3215 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:182
static int EOXactTupleDescArrayLen
Definition: relcache.c:201
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:3226
static bool eoxact_list_overflowed
Definition: relcache.c:184
static int NextEOXactTupleDescNum
Definition: relcache.c:200
void pfree(void *pointer)
Definition: mcxt.c:1169
static int in_progress_list_len
Definition: relcache.c:168
#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:229
static int eoxact_list_len
Definition: relcache.c:183
static TupleDesc * EOXactTupleDescArray
Definition: relcache.c:199

◆ AttrDefaultCmp()

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

Definition at line 4440 of file relcache.c.

References AttrDefault::adnum.

Referenced by AttrDefaultFetch().

4441 {
4442  const AttrDefault *ada = (const AttrDefault *) a;
4443  const AttrDefault *adb = (const AttrDefault *) b;
4444 
4445  return ada->adnum - adb->adnum;
4446 }
AttrNumber adnum
Definition: tupdesc.h:24

◆ AttrDefaultFetch()

static void AttrDefaultFetch ( Relation  relation,
int  ndef 
)
static

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

4361 {
4362  AttrDefault *attrdef;
4363  Relation adrel;
4364  SysScanDesc adscan;
4365  ScanKeyData skey;
4366  HeapTuple htup;
4367  int found = 0;
4368 
4369  /* Allocate array with room for as many entries as expected */
4370  attrdef = (AttrDefault *)
4372  ndef * sizeof(AttrDefault));
4373 
4374  /* Search pg_attrdef for relevant entries */
4375  ScanKeyInit(&skey,
4376  Anum_pg_attrdef_adrelid,
4377  BTEqualStrategyNumber, F_OIDEQ,
4378  ObjectIdGetDatum(RelationGetRelid(relation)));
4379 
4380  adrel = table_open(AttrDefaultRelationId, AccessShareLock);
4381  adscan = systable_beginscan(adrel, AttrDefaultIndexId, true,
4382  NULL, 1, &skey);
4383 
4384  while (HeapTupleIsValid(htup = systable_getnext(adscan)))
4385  {
4386  Form_pg_attrdef adform = (Form_pg_attrdef) GETSTRUCT(htup);
4387  Datum val;
4388  bool isnull;
4389 
4390  /* protect limited size of array */
4391  if (found >= ndef)
4392  {
4393  elog(WARNING, "unexpected pg_attrdef record found for attribute %d of relation \"%s\"",
4394  adform->adnum, RelationGetRelationName(relation));
4395  break;
4396  }
4397 
4398  val = fastgetattr(htup,
4399  Anum_pg_attrdef_adbin,
4400  adrel->rd_att, &isnull);
4401  if (isnull)
4402  elog(WARNING, "null adbin for attribute %d of relation \"%s\"",
4403  adform->adnum, RelationGetRelationName(relation));
4404  else
4405  {
4406  /* detoast and convert to cstring in caller's context */
4407  char *s = TextDatumGetCString(val);
4408 
4409  attrdef[found].adnum = adform->adnum;
4410  attrdef[found].adbin = MemoryContextStrdup(CacheMemoryContext, s);
4411  pfree(s);
4412  found++;
4413  }
4414  }
4415 
4416  systable_endscan(adscan);
4417  table_close(adrel, AccessShareLock);
4418 
4419  if (found != ndef)
4420  elog(WARNING, "%d pg_attrdef record(s) missing for relation \"%s\"",
4421  ndef - found, RelationGetRelationName(relation));
4422 
4423  /*
4424  * Sort the AttrDefault entries by adnum, for the convenience of
4425  * equalTupleDescs(). (Usually, they already will be in order, but this
4426  * might not be so if systable_getnext isn't using an index.)
4427  */
4428  if (found > 1)
4429  qsort(attrdef, found, sizeof(AttrDefault), AttrDefaultCmp);
4430 
4431  /* Install array only after it's fully valid */
4432  relation->rd_att->constr->defval = attrdef;
4433  relation->rd_att->constr->num_defval = found;
4434 }
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:87
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:4440
#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:505
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 4295 of file relcache.c.

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

Referenced by GetPgClassDescriptor(), and GetPgIndexDescriptor().

4296 {
4297  TupleDesc result;
4298  MemoryContext oldcxt;
4299  int i;
4300 
4302 
4303  result = CreateTemplateTupleDesc(natts);
4304  result->tdtypeid = RECORDOID; /* not right, but we don't care */
4305  result->tdtypmod = -1;
4306 
4307  for (i = 0; i < natts; i++)
4308  {
4309  memcpy(TupleDescAttr(result, i), &attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
4310  /* make sure attcacheoff is valid */
4311  TupleDescAttr(result, i)->attcacheoff = -1;
4312  }
4313 
4314  /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
4315  TupleDescAttr(result, 0)->attcacheoff = 0;
4316 
4317  /* Note: we don't bother to set up a TupleConstr entry */
4318 
4319  MemoryContextSwitchTo(oldcxt);
4320 
4321  return result;
4322 }
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 4544 of file relcache.c.

References ConstrCheck::ccname.

Referenced by CheckConstraintFetch().

4545 {
4546  const ConstrCheck *ca = (const ConstrCheck *) a;
4547  const ConstrCheck *cb = (const ConstrCheck *) b;
4548 
4549  return strcmp(ca->ccname, cb->ccname);
4550 }
char * ccname
Definition: tupdesc.h:30

◆ CheckConstraintFetch()

static void CheckConstraintFetch ( Relation  relation)
static

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

4456 {
4457  ConstrCheck *check;
4458  int ncheck = relation->rd_rel->relchecks;
4459  Relation conrel;
4460  SysScanDesc conscan;
4461  ScanKeyData skey[1];
4462  HeapTuple htup;
4463  int found = 0;
4464 
4465  /* Allocate array with room for as many entries as expected */
4466  check = (ConstrCheck *)
4468  ncheck * sizeof(ConstrCheck));
4469 
4470  /* Search pg_constraint for relevant entries */
4471  ScanKeyInit(&skey[0],
4472  Anum_pg_constraint_conrelid,
4473  BTEqualStrategyNumber, F_OIDEQ,
4474  ObjectIdGetDatum(RelationGetRelid(relation)));
4475 
4476  conrel = table_open(ConstraintRelationId, AccessShareLock);
4477  conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,
4478  NULL, 1, skey);
4479 
4480  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4481  {
4483  Datum val;
4484  bool isnull;
4485 
4486  /* We want check constraints only */
4487  if (conform->contype != CONSTRAINT_CHECK)
4488  continue;
4489 
4490  /* protect limited size of array */
4491  if (found >= ncheck)
4492  {
4493  elog(WARNING, "unexpected pg_constraint record found for relation \"%s\"",
4494  RelationGetRelationName(relation));
4495  break;
4496  }
4497 
4498  check[found].ccvalid = conform->convalidated;
4499  check[found].ccnoinherit = conform->connoinherit;
4501  NameStr(conform->conname));
4502 
4503  /* Grab and test conbin is actually set */
4504  val = fastgetattr(htup,
4505  Anum_pg_constraint_conbin,
4506  conrel->rd_att, &isnull);
4507  if (isnull)
4508  elog(WARNING, "null conbin for relation \"%s\"",
4509  RelationGetRelationName(relation));
4510  else
4511  {
4512  /* detoast and convert to cstring in caller's context */
4513  char *s = TextDatumGetCString(val);
4514 
4515  check[found].ccbin = MemoryContextStrdup(CacheMemoryContext, s);
4516  pfree(s);
4517  found++;
4518  }
4519  }
4520 
4521  systable_endscan(conscan);
4522  table_close(conrel, AccessShareLock);
4523 
4524  if (found != ncheck)
4525  elog(WARNING, "%d pg_constraint record(s) missing for relation \"%s\"",
4526  ncheck - found, RelationGetRelationName(relation));
4527 
4528  /*
4529  * Sort the records by name. This ensures that CHECKs are applied in a
4530  * deterministic order, and it also makes equalTupleDescs() faster.
4531  */
4532  if (found > 1)
4533  qsort(check, found, sizeof(ConstrCheck), CheckConstraintCmp);
4534 
4535  /* Install array only after it's fully valid */
4536  relation->rd_att->constr->check = check;
4537  relation->rd_att->constr->num_check = found;
4538 }
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:4544
#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:87
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:505
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 5658 of file relcache.c.

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

Referenced by RelationGetIndexAttOptions().

5659 {
5660  bytea **opts = palloc(sizeof(*opts) * natts);
5661 
5662  for (int i = 0; i < natts; i++)
5663  {
5664  bytea *opt = srcopts[i];
5665 
5666  opts[i] = !opt ? NULL : (bytea *)
5667  DatumGetPointer(datumCopy(PointerGetDatum(opt), false, -1));
5668  }
5669 
5670  return opts;
5671 }
#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:110
#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 932 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().

933 {
934  int i;
935  Oid *r1,
936  *r2;
937 
938  if (policy1 != NULL)
939  {
940  if (policy2 == NULL)
941  return false;
942 
943  if (policy1->polcmd != policy2->polcmd)
944  return false;
945  if (policy1->hassublinks != policy2->hassublinks)
946  return false;
947  if (strcmp(policy1->policy_name, policy2->policy_name) != 0)
948  return false;
949  if (ARR_DIMS(policy1->roles)[0] != ARR_DIMS(policy2->roles)[0])
950  return false;
951 
952  r1 = (Oid *) ARR_DATA_PTR(policy1->roles);
953  r2 = (Oid *) ARR_DATA_PTR(policy2->roles);
954 
955  for (i = 0; i < ARR_DIMS(policy1->roles)[0]; i++)
956  {
957  if (r1[i] != r2[i])
958  return false;
959  }
960 
961  if (!equal(policy1->qual, policy2->qual))
962  return false;
963  if (!equal(policy1->with_check_qual, policy2->with_check_qual))
964  return false;
965  }
966  else if (policy2 != NULL)
967  return false;
968 
969  return true;
970 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3149
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 978 of file relcache.c.

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

Referenced by RelationClearRelation().

979 {
980  ListCell *lc,
981  *rc;
982 
983  if (rsdesc1 == NULL && rsdesc2 == NULL)
984  return true;
985 
986  if ((rsdesc1 != NULL && rsdesc2 == NULL) ||
987  (rsdesc1 == NULL && rsdesc2 != NULL))
988  return false;
989 
990  if (list_length(rsdesc1->policies) != list_length(rsdesc2->policies))
991  return false;
992 
993  /* RelationBuildRowSecurity should build policies in order */
994  forboth(lc, rsdesc1->policies, rc, rsdesc2->policies)
995  {
998 
999  if (!equalPolicy(l, r))
1000  return false;
1001  }
1002 
1003  return true;
1004 }
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:446
static bool equalPolicy(RowSecurityPolicy *policy1, RowSecurityPolicy *policy2)
Definition: relcache.c:932
#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 887 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().

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

5740 {
5744 
5745  return 0; /* return value does not matter */
5746 }
#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 5756 of file relcache.c.

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

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

5757 {
5758  TupleDesc reldesc = RelationGetDescr(rel);
5759  const char *colname;
5760 
5761  /* Use reldesc if it's a user attribute, else consult the catalogs */
5762  if (attnum > 0 && attnum <= reldesc->natts)
5763  colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
5764  else
5765  colname = get_attname(RelationGetRelid(rel), attnum, false);
5766 
5767  return errtablecolname(rel, colname);
5768 }
#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:5780

◆ errtablecolname()

int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5780 of file relcache.c.

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

Referenced by errtablecol().

5781 {
5782  errtable(rel);
5784 
5785  return 0; /* return value does not matter */
5786 }
#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:5739

◆ errtableconstraint()

int errtableconstraint ( Relation  rel,
const char *  conname 
)

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

5794 {
5795  errtable(rel);
5797 
5798  return 0; /* return value does not matter */
5799 }
#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:5739

◆ formrdesc()

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

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

1861 {
1862  Relation relation;
1863  int i;
1864  bool has_not_null;
1865 
1866  /*
1867  * allocate new relation desc, clear all fields of reldesc
1868  */
1869  relation = (Relation) palloc0(sizeof(RelationData));
1870 
1871  /* make sure relation is marked as having no open file yet */
1872  relation->rd_smgr = NULL;
1873 
1874  /*
1875  * initialize reference count: 1 because it is nailed in cache
1876  */
1877  relation->rd_refcnt = 1;
1878 
1879  /*
1880  * all entries built with this routine are nailed-in-cache; none are for
1881  * new or temp relations.
1882  */
1883  relation->rd_isnailed = true;
1888  relation->rd_backend = InvalidBackendId;
1889  relation->rd_islocaltemp = false;
1890 
1891  /*
1892  * initialize relation tuple form
1893  *
1894  * The data we insert here is pretty incomplete/bogus, but it'll serve to
1895  * get us launched. RelationCacheInitializePhase3() will read the real
1896  * data from pg_class and replace what we've done here. Note in
1897  * particular that relowner is left as zero; this cues
1898  * RelationCacheInitializePhase3 that the real data isn't there yet.
1899  */
1901 
1902  namestrcpy(&relation->rd_rel->relname, relationName);
1903  relation->rd_rel->relnamespace = PG_CATALOG_NAMESPACE;
1904  relation->rd_rel->reltype = relationReltype;
1905 
1906  /*
1907  * It's important to distinguish between shared and non-shared relations,
1908  * even at bootstrap time, to make sure we know where they are stored.
1909  */
1910  relation->rd_rel->relisshared = isshared;
1911  if (isshared)
1912  relation->rd_rel->reltablespace = GLOBALTABLESPACE_OID;
1913 
1914  /* formrdesc is used only for permanent relations */
1915  relation->rd_rel->relpersistence = RELPERSISTENCE_PERMANENT;
1916 
1917  /* ... and they're always populated, too */
1918  relation->rd_rel->relispopulated = true;
1919 
1920  relation->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
1921  relation->rd_rel->relpages = 0;
1922  relation->rd_rel->reltuples = -1;
1923  relation->rd_rel->relallvisible = 0;
1924  relation->rd_rel->relkind = RELKIND_RELATION;
1925  relation->rd_rel->relnatts = (int16) natts;
1926  relation->rd_rel->relam = HEAP_TABLE_AM_OID;
1927 
1928  /*
1929  * initialize attribute tuple form
1930  *
1931  * Unlike the case with the relation tuple, this data had better be right
1932  * because it will never be replaced. The data comes from
1933  * src/include/catalog/ headers via genbki.pl.
1934  */
1935  relation->rd_att = CreateTemplateTupleDesc(natts);
1936  relation->rd_att->tdrefcount = 1; /* mark as refcounted */
1937 
1938  relation->rd_att->tdtypeid = relationReltype;
1939  relation->rd_att->tdtypmod = -1; /* just to be sure */
1940 
1941  /*
1942  * initialize tuple desc info
1943  */
1944  has_not_null = false;
1945  for (i = 0; i < natts; i++)
1946  {
1947  memcpy(TupleDescAttr(relation->rd_att, i),
1948  &attrs[i],
1950  has_not_null |= attrs[i].attnotnull;
1951  /* make sure attcacheoff is valid */
1952  TupleDescAttr(relation->rd_att, i)->attcacheoff = -1;
1953  }
1954 
1955  /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
1956  TupleDescAttr(relation->rd_att, 0)->attcacheoff = 0;
1957 
1958  /* mark not-null status */
1959  if (has_not_null)
1960  {
1961  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
1962 
1963  constr->has_not_null = true;
1964  relation->rd_att->constr = constr;
1965  }
1966 
1967  /*
1968  * initialize relation id from info in att array (my, this is ugly)
1969  */
1970  RelationGetRelid(relation) = TupleDescAttr(relation->rd_att, 0)->attrelid;
1971 
1972  /*
1973  * All relations made with formrdesc are mapped. This is necessarily so
1974  * because there is no other way to know what filenode they currently
1975  * have. In bootstrap mode, add them to the initial relation mapper data,
1976  * specifying that the initial filenode is the same as the OID.
1977  */
1978  relation->rd_rel->relfilenode = InvalidOid;
1981  RelationGetRelid(relation),
1982  isshared, true);
1983 
1984  /*
1985  * initialize the relation lock manager information
1986  */
1987  RelationInitLockInfo(relation); /* see lmgr.c */
1988 
1989  /*
1990  * initialize physical addressing information for the relation
1991  */
1992  RelationInitPhysicalAddr(relation);
1993 
1994  /*
1995  * initialize the table am handler
1996  */
1997  relation->rd_rel->relam = HEAP_TABLE_AM_OID;
1998  relation->rd_tableam = GetHeapamTableAmRoutine();
1999 
2000  /*
2001  * initialize the rel-has-index flag, using hardwired knowledge
2002  */
2004  {
2005  /* In bootstrap mode, we have no indexes */
2006  relation->rd_rel->relhasindex = false;
2007  }
2008  else
2009  {
2010  /* Otherwise, all the rels formrdesc is used for have indexes */
2011  relation->rd_rel->relhasindex = true;
2012  }
2013 
2014  /*
2015  * add new reldesc to relcache
2016  */
2017  RelationCacheInsert(relation, false);
2018 
2019  /* It's fully valid */
2020  relation->rd_isvalid = true;
2021 }
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:26
int32 tdtypmod
Definition: tupdesc.h:83
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1305
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:206
#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 4325 of file relcache.c.

References BuildHardcodedDescriptor(), and Desc_pg_class.

Referenced by RelationParseRelOptions().

4326 {
4327  static TupleDesc pgclassdesc = NULL;
4328 
4329  /* Already done? */
4330  if (pgclassdesc == NULL)
4331  pgclassdesc = BuildHardcodedDescriptor(Natts_pg_class,
4332  Desc_pg_class);
4333 
4334  return pgclassdesc;
4335 }
static TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:4295
static const FormData_pg_attribute Desc_pg_class[Natts_pg_class]
Definition: relcache.c:108

◆ GetPgIndexDescriptor()

static TupleDesc GetPgIndexDescriptor ( void  )
static

Definition at line 4338 of file relcache.c.

References BuildHardcodedDescriptor(), and Desc_pg_index.

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

4339 {
4340  static TupleDesc pgindexdesc = NULL;
4341 
4342  /* Already done? */
4343  if (pgindexdesc == NULL)
4344  pgindexdesc = BuildHardcodedDescriptor(Natts_pg_index,
4345  Desc_pg_index);
4346 
4347  return pgindexdesc;
4348 }
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:4295

◆ GetRelationPublicationActions()

struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

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

5549 {
5550  List *puboids;
5551  ListCell *lc;
5552  MemoryContext oldcxt;
5553  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5554 
5555  /*
5556  * If not publishable, it publishes no actions. (pgoutput_change() will
5557  * ignore it.)
5558  */
5559  if (!is_publishable_relation(relation))
5560  return pubactions;
5561 
5562  if (relation->rd_pubactions)
5563  return memcpy(pubactions, relation->rd_pubactions,
5564  sizeof(PublicationActions));
5565 
5566  /* Fetch the publication membership info. */
5567  puboids = GetRelationPublications(RelationGetRelid(relation));
5568  if (relation->rd_rel->relispartition)
5569  {
5570  /* Add publications that the ancestors are in too. */
5571  List *ancestors = get_partition_ancestors(RelationGetRelid(relation));
5572  ListCell *lc;
5573 
5574  foreach(lc, ancestors)
5575  {
5576  Oid ancestor = lfirst_oid(lc);
5577 
5578  puboids = list_concat_unique_oid(puboids,
5579  GetRelationPublications(ancestor));
5580  }
5581  }
5582  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5583 
5584  foreach(lc, puboids)
5585  {
5586  Oid pubid = lfirst_oid(lc);
5587  HeapTuple tup;
5588  Form_pg_publication pubform;
5589 
5591 
5592  if (!HeapTupleIsValid(tup))
5593  elog(ERROR, "cache lookup failed for publication %u", pubid);
5594 
5595  pubform = (Form_pg_publication) GETSTRUCT(tup);
5596 
5597  pubactions->pubinsert |= pubform->pubinsert;
5598  pubactions->pubupdate |= pubform->pubupdate;
5599  pubactions->pubdelete |= pubform->pubdelete;
5600  pubactions->pubtruncate |= pubform->pubtruncate;
5601 
5602  ReleaseSysCache(tup);
5603 
5604  /*
5605  * If we know everything is replicated, there is no point to check for
5606  * other publications.
5607  */
5608  if (pubactions->pubinsert && pubactions->pubupdate &&
5609  pubactions->pubdelete && pubactions->pubtruncate)
5610  break;
5611  }
5612 
5613  if (relation->rd_pubactions)
5614  {
5615  pfree(relation->rd_pubactions);
5616  relation->rd_pubactions = NULL;
5617  }
5618 
5619  /* Now save copy of the actions in the relcache entry. */
5621  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5622  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5623  MemoryContextSwitchTo(oldcxt);
5624 
5625  return pubactions;
5626 }
#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 1581 of file relcache.c.

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

Referenced by RelationInitIndexAccessInfo().

1587 {
1588  int attIndex;
1589 
1590  for (attIndex = 0; attIndex < maxAttributeNumber; attIndex++)
1591  {
1592  OpClassCacheEnt *opcentry;
1593 
1594  if (!OidIsValid(indclass->values[attIndex]))
1595  elog(ERROR, "bogus pg_index tuple");
1596 
1597  /* look up the info for this opclass, using a cache */
1598  opcentry = LookupOpclassInfo(indclass->values[attIndex],
1599  maxSupportNumber);
1600 
1601  /* copy cached data into relcache entry */
1602  opFamily[attIndex] = opcentry->opcfamily;
1603  opcInType[attIndex] = opcentry->opcintype;
1604  if (maxSupportNumber > 0)
1605  memcpy(&indexSupport[attIndex * maxSupportNumber],
1606  opcentry->supportProcs,
1607  maxSupportNumber * sizeof(RegProcedure));
1608  }
1609 }
regproc RegProcedure
Definition: c.h:585
#define OidIsValid(objectId)
Definition: c.h:710
#define ERROR
Definition: elog.h:46
RegProcedure * supportProcs
Definition: relcache.c:265
static OpClassCacheEnt * LookupOpclassInfo(Oid operatorClassOid, StrategyNumber numSupport)
Definition: relcache.c:1632
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 1387 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().

1388 {
1389  IndexAmRoutine *cached,
1390  *tmp;
1391 
1392  /*
1393  * Call the amhandler in current, short-lived memory context, just in case
1394  * it leaks anything (it probably won't, but let's be paranoid).
1395  */
1396  tmp = GetIndexAmRoutine(relation->rd_amhandler);
1397 
1398  /* OK, now transfer the data into relation's rd_indexcxt. */
1399  cached = (IndexAmRoutine *) MemoryContextAlloc(relation->rd_indexcxt,
1400  sizeof(IndexAmRoutine));
1401  memcpy(cached, tmp, sizeof(IndexAmRoutine));
1402  relation->rd_indam = cached;
1403 
1404  pfree(tmp);
1405 }
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 1785 of file relcache.c.

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

Referenced by RelationInitTableAccessMethod().

1786 {
1787  relation->rd_tableam = GetTableAmRoutine(relation->rd_amhandler);
1788 }
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 4259 of file relcache.c.

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

Referenced by RelationCacheInitializePhase3().

4260 {
4261  Relation ird;
4262 
4263  /*
4264  * We must lock the underlying catalog before locking the index to avoid
4265  * deadlock, since RelationBuildDesc might well need to read the catalog,
4266  * and if anyone else is exclusive-locking this catalog and index they'll
4267  * be doing it in that order.
4268  */
4269  LockRelationOid(heapoid, AccessShareLock);
4270  LockRelationOid(indexoid, AccessShareLock);
4271  ird = RelationBuildDesc(indexoid, true);
4272  if (ird == NULL)
4273  elog(PANIC, "could not open critical system index %u", indexoid);
4274  ird->rd_isnailed = true;
4275  ird->rd_refcnt = 1;
4278 
4279  (void) RelationGetIndexAttOptions(ird, false);
4280 }
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:1019
int rd_refcnt
Definition: rel.h:58
#define elog(elevel,...)
Definition: elog.h:232
bytea ** RelationGetIndexAttOptions(Relation relation, bool copy)
Definition: relcache.c:5678
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 5857 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().

5858 {
5859  FILE *fp;
5860  char initfilename[MAXPGPATH];
5861  Relation *rels;
5862  int relno,
5863  num_rels,
5864  max_rels,
5865  nailed_rels,
5866  nailed_indexes,
5867  magic;
5868  int i;
5869 
5870  if (shared)
5871  snprintf(initfilename, sizeof(initfilename), "global/%s",
5873  else
5874  snprintf(initfilename, sizeof(initfilename), "%s/%s",
5876 
5877  fp = AllocateFile(initfilename, PG_BINARY_R);
5878  if (fp == NULL)
5879  return false;
5880 
5881  /*
5882  * Read the index relcache entries from the file. Note we will not enter
5883  * any of them into the cache if the read fails partway through; this
5884  * helps to guard against broken init files.
5885  */
5886  max_rels = 100;
5887  rels = (Relation *) palloc(max_rels * sizeof(Relation));
5888  num_rels = 0;
5889  nailed_rels = nailed_indexes = 0;
5890 
5891  /* check for correct magic number (compatible version) */
5892  if (fread(&magic, 1, sizeof(magic), fp) != sizeof(magic))
5893  goto read_failed;
5894  if (magic != RELCACHE_INIT_FILEMAGIC)
5895  goto read_failed;
5896 
5897  for (relno = 0;; relno++)
5898  {
5899  Size len;
5900  size_t nread;
5901  Relation rel;
5902  Form_pg_class relform;
5903  bool has_not_null;
5904 
5905  /* first read the relation descriptor length */
5906  nread = fread(&len, 1, sizeof(len), fp);
5907  if (nread != sizeof(len))
5908  {
5909  if (nread == 0)
5910  break; /* end of file */
5911  goto read_failed;
5912  }
5913 
5914  /* safety check for incompatible relcache layout */
5915  if (len != sizeof(RelationData))
5916  goto read_failed;
5917 
5918  /* allocate another relcache header */
5919  if (num_rels >= max_rels)
5920  {
5921  max_rels *= 2;
5922  rels = (Relation *) repalloc(rels, max_rels * sizeof(Relation));
5923  }
5924 
5925  rel = rels[num_rels++] = (Relation) palloc(len);
5926 
5927  /* then, read the Relation structure */
5928  if (fread(rel, 1, len, fp) != len)
5929  goto read_failed;
5930 
5931  /* next read the relation tuple form */
5932  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5933  goto read_failed;
5934 
5935  relform = (Form_pg_class) palloc(len);
5936  if (fread(relform, 1, len, fp) != len)
5937  goto read_failed;
5938 
5939  rel->rd_rel = relform;
5940 
5941  /* initialize attribute tuple forms */
5942  rel->rd_att = CreateTemplateTupleDesc(relform->relnatts);
5943  rel->rd_att->tdrefcount = 1; /* mark as refcounted */
5944 
5945  rel->rd_att->tdtypeid = relform->reltype ? relform->reltype : RECORDOID;
5946  rel->rd_att->tdtypmod = -1; /* just to be sure */
5947 
5948  /* next read all the attribute tuple form data entries */
5949  has_not_null = false;
5950  for (i = 0; i < relform->relnatts; i++)
5951  {
5952  Form_pg_attribute attr = TupleDescAttr(rel->rd_att, i);
5953 
5954  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5955  goto read_failed;
5956  if (len != ATTRIBUTE_FIXED_PART_SIZE)
5957  goto read_failed;
5958  if (fread(attr, 1, len, fp) != len)
5959  goto read_failed;
5960 
5961  has_not_null |= attr->attnotnull;
5962  }
5963 
5964  /* next read the access method specific field */
5965  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5966  goto read_failed;
5967  if (len > 0)
5968  {
5969  rel->rd_options = palloc(len);
5970  if (fread(rel->rd_options, 1, len, fp) != len)
5971  goto read_failed;
5972  if (len != VARSIZE(rel->rd_options))
5973  goto read_failed; /* sanity check */
5974  }
5975  else
5976  {
5977  rel->rd_options = NULL;
5978  }
5979 
5980  /* mark not-null status */
5981  if (has_not_null)
5982  {
5983  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
5984 
5985  constr->has_not_null = true;
5986  rel->rd_att->constr = constr;
5987  }
5988 
5989  /*
5990  * If it's an index, there's more to do. Note we explicitly ignore
5991  * partitioned indexes here.
5992  */
5993  if (rel->rd_rel->relkind == RELKIND_INDEX)
5994  {
5995  MemoryContext indexcxt;
5996  Oid *opfamily;
5997  Oid *opcintype;
5998  RegProcedure *support;
5999  int nsupport;
6000  int16 *indoption;
6001  Oid *indcollation;
6002 
6003  /* Count nailed indexes to ensure we have 'em all */
6004  if (rel->rd_isnailed)
6005  nailed_indexes++;
6006 
6007  /* next, read the pg_index tuple */
6008  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6009  goto read_failed;
6010 
6011  rel->rd_indextuple = (HeapTuple) palloc(len);
6012  if (fread(rel->rd_indextuple, 1, len, fp) != len)
6013  goto read_failed;
6014 
6015  /* Fix up internal pointers in the tuple -- see heap_copytuple */
6016  rel->rd_indextuple->t_data = (HeapTupleHeader) ((char *) rel->rd_indextuple + HEAPTUPLESIZE);
6018 
6019  /*
6020  * prepare index info context --- parameters should match
6021  * RelationInitIndexAccessInfo
6022  */
6024  "index info",
6026  rel->rd_indexcxt = indexcxt;
6029 
6030  /*
6031  * Now we can fetch the index AM's API struct. (We can't store
6032  * that in the init file, since it contains function pointers that
6033  * might vary across server executions. Fortunately, it should be
6034  * safe to call the amhandler even while bootstrapping indexes.)
6035  */
6036  InitIndexAmRoutine(rel);
6037 
6038  /* next, read the vector of opfamily OIDs */
6039  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6040  goto read_failed;
6041 
6042  opfamily = (Oid *) MemoryContextAlloc(indexcxt, len);
6043  if (fread(opfamily, 1, len, fp) != len)
6044  goto read_failed;
6045 
6046  rel->rd_opfamily = opfamily;
6047 
6048  /* next, read the vector of opcintype OIDs */
6049  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6050  goto read_failed;
6051 
6052  opcintype = (Oid *) MemoryContextAlloc(indexcxt, len);
6053  if (fread(opcintype, 1, len, fp) != len)
6054  goto read_failed;
6055 
6056  rel->rd_opcintype = opcintype;
6057 
6058  /* next, read the vector of support procedure OIDs */
6059  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6060  goto read_failed;
6061  support = (RegProcedure *) MemoryContextAlloc(indexcxt, len);
6062  if (fread(support, 1, len, fp) != len)
6063  goto read_failed;
6064 
6065  rel->rd_support = support;
6066 
6067  /* next, read the vector of collation OIDs */
6068  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6069  goto read_failed;
6070 
6071  indcollation = (Oid *) MemoryContextAlloc(indexcxt, len);
6072  if (fread(indcollation, 1, len, fp) != len)
6073  goto read_failed;
6074 
6075  rel->rd_indcollation = indcollation;
6076 
6077  /* finally, read the vector of indoption values */
6078  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6079  goto read_failed;
6080 
6081  indoption = (int16 *) MemoryContextAlloc(indexcxt, len);
6082  if (fread(indoption, 1, len, fp) != len)
6083  goto read_failed;
6084 
6085  rel->rd_indoption = indoption;
6086 
6087  /* finally, read the vector of opcoptions values */
6088  rel->rd_opcoptions = (bytea **)
6089  MemoryContextAllocZero(indexcxt, sizeof(*rel->rd_opcoptions) * relform->relnatts);
6090 
6091  for (i = 0; i < relform->relnatts; i++)
6092  {
6093  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6094  goto read_failed;
6095 
6096  if (len > 0)
6097  {
6098  rel->rd_opcoptions[i] = (bytea *) MemoryContextAlloc(indexcxt, len);
6099  if (fread(rel->rd_opcoptions[i], 1, len, fp) != len)
6100  goto read_failed;
6101  }
6102  }
6103 
6104  /* set up zeroed fmgr-info vector */
6105  nsupport = relform->relnatts * rel->rd_indam->amsupport;
6106  rel->rd_supportinfo = (FmgrInfo *)
6107  MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
6108  }
6109  else
6110  {
6111  /* Count nailed rels to ensure we have 'em all */
6112  if (rel->rd_isnailed)
6113  nailed_rels++;
6114 
6115  /* Load table AM data */
6116  if (rel->rd_rel->relkind == RELKIND_RELATION ||
6117  rel->rd_rel->relkind == RELKIND_SEQUENCE ||
6118  rel->rd_rel->relkind == RELKIND_TOASTVALUE ||
6119  rel->rd_rel->relkind == RELKIND_MATVIEW)
6121 
6122  Assert(rel->rd_index == NULL);
6123  Assert(rel->rd_indextuple == NULL);
6124  Assert(rel->rd_indexcxt == NULL);
6125  Assert(rel->rd_indam == NULL);
6126  Assert(rel->rd_opfamily == NULL);
6127  Assert(rel->rd_opcintype == NULL);
6128  Assert(rel->rd_support == NULL);
6129  Assert(rel->rd_supportinfo == NULL);
6130  Assert(rel->rd_indoption == NULL);
6131  Assert(rel->rd_indcollation == NULL);
6132  Assert(rel->rd_opcoptions == NULL);
6133  }
6134 
6135  /*
6136  * Rules and triggers are not saved (mainly because the internal
6137  * format is complex and subject to change). They must be rebuilt if
6138  * needed by RelationCacheInitializePhase3. This is not expected to
6139  * be a big performance hit since few system catalogs have such. Ditto
6140  * for RLS policy data, partition info, index expressions, predicates,
6141  * exclusion info, and FDW info.
6142  */
6143  rel->rd_rules = NULL;
6144  rel->rd_rulescxt = NULL;
6145  rel->trigdesc = NULL;
6146  rel->rd_rsdesc = NULL;
6147  rel->rd_partkey = NULL;
6148  rel->rd_partkeycxt = NULL;
6149  rel->rd_partdesc = NULL;
6150  rel->rd_partdesc_nodetached = NULL;
6152  rel->rd_pdcxt = NULL;
6153  rel->rd_pddcxt = NULL;
6154  rel->rd_partcheck = NIL;
6155  rel->rd_partcheckvalid = false;
6156  rel->rd_partcheckcxt = NULL;
6157  rel->rd_indexprs = NIL;
6158  rel->rd_indpred = NIL;
6159  rel->rd_exclops = NULL;
6160  rel->rd_exclprocs = NULL;
6161  rel->rd_exclstrats = NULL;
6162  rel->rd_fdwroutine = NULL;
6163 
6164  /*
6165  * Reset transient-state fields in the relcache entry
6166  */
6167  rel->rd_smgr = NULL;
6168  if (rel->rd_isnailed)
6169  rel->rd_refcnt = 1;
6170  else
6171  rel->rd_refcnt = 0;
6172  rel->rd_indexvalid = false;
6173  rel->rd_indexlist = NIL;
6174  rel->rd_pkindex = InvalidOid;
6175  rel->rd_replidindex = InvalidOid;
6176  rel->rd_indexattr = NULL;
6177  rel->rd_keyattr = NULL;
6178  rel->rd_pkattr = NULL;
6179  rel->rd_idattr = NULL;
6180  rel->rd_pubactions = NULL;
6181  rel->rd_statvalid = false;
6182  rel->rd_statlist = NIL;
6183  rel->rd_fkeyvalid = false;
6184  rel->rd_fkeylist = NIL;
6189  rel->rd_amcache = NULL;
6190  MemSet(&rel->pgstat_info, 0, sizeof(rel->pgstat_info));
6191 
6192  /*
6193  * Recompute lock and physical addressing info. This is needed in
6194  * case the pg_internal.init file was copied from some other database
6195  * by CREATE DATABASE.
6196  */
6197  RelationInitLockInfo(rel);
6199  }
6200 
6201  /*
6202  * We reached the end of the init file without apparent problem. Did we
6203  * get the right number of nailed items? This is a useful crosscheck in
6204  * case the set of critical rels or indexes changes. However, that should
6205  * not happen in a normally-running system, so let's bleat if it does.
6206  *
6207  * For the shared init file, we're called before client authentication is
6208  * done, which means that elog(WARNING) will go only to the postmaster
6209  * log, where it's easily missed. To ensure that developers notice bad
6210  * values of NUM_CRITICAL_SHARED_RELS/NUM_CRITICAL_SHARED_INDEXES, we put
6211  * an Assert(false) there.
6212  */
6213  if (shared)
6214  {
6215  if (nailed_rels != NUM_CRITICAL_SHARED_RELS ||
6216  nailed_indexes != NUM_CRITICAL_SHARED_INDEXES)
6217  {
6218  elog(WARNING, "found %d nailed shared rels and %d nailed shared indexes in init file, but expected %d and %d respectively",
6219  nailed_rels, nailed_indexes,
6221  /* Make sure we get developers' attention about this */
6222  Assert(false);
6223  /* In production builds, recover by bootstrapping the relcache */
6224  goto read_failed;
6225  }
6226  }
6227  else
6228  {
6229  if (nailed_rels != NUM_CRITICAL_LOCAL_RELS ||
6230  nailed_indexes != NUM_CRITICAL_LOCAL_INDEXES)
6231  {
6232  elog(WARNING, "found %d nailed rels and %d nailed indexes in init file, but expected %d and %d respectively",
6233  nailed_rels, nailed_indexes,
6235  /* We don't need an Assert() in this case */
6236  goto read_failed;
6237  }
6238  }
6239 
6240  /*
6241  * OK, all appears well.
6242  *
6243  * Now insert all the new relcache entries into the cache.
6244  */
6245  for (relno = 0; relno < num_rels; relno++)
6246  {
6247  RelationCacheInsert(rels[relno], false);
6248  }
6249 
6250  pfree(rels);
6251  FreeFile(fp);
6252 
6253  if (shared)
6255  else
6256  criticalRelcachesBuilt = true;
6257  return true;
6258 
6259  /*
6260  * init file is broken, so do it the hard way. We don't bother trying to
6261  * free the clutter we just allocated; it's not in the relcache so it
6262  * won't hurt.
6263  */
6264 read_failed:
6265  pfree(rels);
6266  FreeFile(fp);
6267 
6268  return false;
6269 }
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:1794
#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:1387
struct HeapTupleData * rd_indextuple
Definition: rel.h:189
HeapTupleHeader t_data
Definition: htup.h:68
struct RelationData * Relation
Definition: relcache.h:26
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:1305
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:2460
#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:24
Bitmapset * rd_idattr
Definition: rel.h:161
#define RelationCacheInsert(RELATION, replace_allowed)
Definition: relcache.c:206
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:2659
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:217
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 1632 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().

1634 {
1635  OpClassCacheEnt *opcentry;
1636  bool found;
1637  Relation rel;
1638  SysScanDesc scan;
1639  ScanKeyData skey[3];
1640  HeapTuple htup;
1641  bool indexOK;
1642 
1643  if (OpClassCache == NULL)
1644  {
1645  /* First time through: initialize the opclass cache */
1646  HASHCTL ctl;
1647 
1648  /* Also make sure CacheMemoryContext exists */
1649  if (!CacheMemoryContext)
1651 
1652  ctl.keysize = sizeof(Oid);
1653  ctl.entrysize = sizeof(OpClassCacheEnt);
1654  OpClassCache = hash_create("Operator class cache", 64,
1655  &ctl, HASH_ELEM | HASH_BLOBS);
1656  }
1657 
1658  opcentry = (OpClassCacheEnt *) hash_search(OpClassCache,
1659  (void *) &operatorClassOid,
1660  HASH_ENTER, &found);
1661 
1662  if (!found)
1663  {
1664  /* Initialize new entry */
1665  opcentry->valid = false; /* until known OK */
1666  opcentry->numSupport = numSupport;
1667  opcentry->supportProcs = NULL; /* filled below */
1668  }
1669  else
1670  {
1671  Assert(numSupport == opcentry->numSupport);
1672  }
1673 
1674  /*
1675  * When aggressively testing cache-flush hazards, we disable the operator
1676  * class cache and force reloading of the info on each call. This models
1677  * no real-world behavior, since the cache entries are never invalidated
1678  * otherwise. However it can be helpful for detecting bugs in the cache
1679  * loading logic itself, such as reliance on a non-nailed index. Given
1680  * the limited use-case and the fact that this adds a great deal of
1681  * expense, we enable it only for high values of debug_discard_caches.
1682  */
1683 #ifdef DISCARD_CACHES_ENABLED
1684  if (debug_discard_caches > 2)
1685  opcentry->valid = false;
1686 #endif
1687 
1688  if (opcentry->valid)
1689  return opcentry;
1690 
1691  /*
1692  * Need to fill in new entry. First allocate space, unless we already did
1693  * so in some previous attempt.
1694  */
1695  if (opcentry->supportProcs == NULL && numSupport > 0)
1696  opcentry->supportProcs = (RegProcedure *)
1698  numSupport * sizeof(RegProcedure));
1699 
1700  /*
1701  * To avoid infinite recursion during startup, force heap scans if we're
1702  * looking up info for the opclasses used by the indexes we would like to
1703  * reference here.
1704  */
1705  indexOK = criticalRelcachesBuilt ||
1706  (operatorClassOid != OID_BTREE_OPS_OID &&
1707  operatorClassOid != INT2_BTREE_OPS_OID);
1708 
1709  /*
1710  * We have to fetch the pg_opclass row to determine its opfamily and
1711  * opcintype, which are needed to look up related operators and functions.
1712  * It'd be convenient to use the syscache here, but that probably doesn't
1713  * work while bootstrapping.
1714  */
1715  ScanKeyInit(&skey[0],
1716  Anum_pg_opclass_oid,
1717  BTEqualStrategyNumber, F_OIDEQ,
1718  ObjectIdGetDatum(operatorClassOid));
1719  rel = table_open(OperatorClassRelationId, AccessShareLock);
1720  scan = systable_beginscan(rel, OpclassOidIndexId, indexOK,
1721  NULL, 1, skey);
1722 
1723  if (HeapTupleIsValid(htup = systable_getnext(scan)))
1724  {
1725  Form_pg_opclass opclassform = (Form_pg_opclass) GETSTRUCT(htup);
1726 
1727  opcentry->opcfamily = opclassform->opcfamily;
1728  opcentry->opcintype = opclassform->opcintype;
1729  }
1730  else
1731  elog(ERROR, "could not find tuple for opclass %u", operatorClassOid);
1732 
1733  systable_endscan(scan);
1735 
1736  /*
1737  * Scan pg_amproc to obtain support procs for the opclass. We only fetch
1738  * the default ones (those with lefttype = righttype = opcintype).
1739  */
1740  if (numSupport > 0)
1741  {
1742  ScanKeyInit(&skey[0],
1743  Anum_pg_amproc_amprocfamily,
1744  BTEqualStrategyNumber, F_OIDEQ,
1745  ObjectIdGetDatum(opcentry->opcfamily));
1746  ScanKeyInit(&skey[1],
1747  Anum_pg_amproc_amproclefttype,
1748  BTEqualStrategyNumber, F_OIDEQ,
1749  ObjectIdGetDatum(opcentry->opcintype));
1750  ScanKeyInit(&skey[2],
1751  Anum_pg_amproc_amprocrighttype,
1752  BTEqualStrategyNumber, F_OIDEQ,
1753  ObjectIdGetDatum(opcentry->opcintype));
1754  rel = table_open(AccessMethodProcedureRelationId, AccessShareLock);
1755  scan = systable_beginscan(rel, AccessMethodProcedureIndexId, indexOK,
1756  NULL, 3, skey);
1757 
1758  while (HeapTupleIsValid(htup = systable_getnext(scan)))
1759  {
1760  Form_pg_amproc amprocform = (Form_pg_amproc) GETSTRUCT(htup);
1761 
1762  if (amprocform->amprocnum <= 0 ||
1763  (StrategyNumber) amprocform->amprocnum > numSupport)
1764  elog(ERROR, "invalid amproc number %d for opclass %u",
1765  amprocform->amprocnum, operatorClassOid);
1766 
1767  opcentry->supportProcs[amprocform->amprocnum - 1] =
1768  amprocform->amproc;
1769  }
1770 
1771  systable_endscan(scan);
1773  }
1774 
1775  opcentry->valid = true;
1776  return opcentry;
1777 }
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:240
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
StrategyNumber numSupport
Definition: relcache.c:262
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:265
static HTAB * OpClassCache
Definition: relcache.c:268
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 3842 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().

3843 {
3846  relation->rd_firstRelfilenodeSubid = relation->rd_newRelfilenodeSubid;
3847 
3848  /* Flag relation as needing eoxact cleanup (to clear these fields) */
3849  EOXactListAdd(relation);
3850 }
#define EOXactListAdd(rel)
Definition: relcache.c:186
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:103
SubTransactionId rd_firstRelfilenodeSubid
Definition: rel.h:105
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:724
#define InvalidSubTransactionId
Definition: c.h:593

◆ RelationBuildDesc()

static Relation RelationBuildDesc ( Oid  targetRelId,
bool  insertIt 
)
static

Definition at line 1019 of file relcache.c.

References AllocateRelationDesc(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, BackendIdForTempRelations, CurrentMemoryContext, debug_discard_caches, elog, ERROR, GETSTRUCT, GetTempNamespaceBackendId(), heap_freetuple(), HeapTupleIsValid, in_progress_list_len, in_progress_list_maxlen, inprogressent::invalidated, 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, RelationDestroyRelation(), RelationGetRelid, RelationInitIndexAccessInfo(), RelationInitLockInfo(), RelationInitPhysicalAddr(), RelationInitTableAccessMethod(), RelationParseRelOptions(), inprogressent::reloid, repalloc(), ScanPgRelation(), and RelationData::trigdesc.

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

1020 {
1021  int in_progress_offset;
1022  Relation relation;
1023  Oid relid;
1024  HeapTuple pg_class_tuple;
1025  Form_pg_class relp;
1026 
1027  /*
1028  * This function and its subroutines can allocate a good deal of transient
1029  * data in CurrentMemoryContext. Traditionally we've just leaked that
1030  * data, reasoning that the caller's context is at worst of transaction
1031  * scope, and relcache loads shouldn't happen so often that it's essential
1032  * to recover transient data before end of statement/transaction. However
1033  * that's definitely not true when debug_discard_caches is active, and
1034  * perhaps it's not true in other cases.
1035  *
1036  * When debug_discard_caches is active or when forced to by
1037  * RECOVER_RELATION_BUILD_MEMORY=1, arrange to allocate the junk in a
1038  * temporary context that we'll free before returning. Make it a child of
1039  * caller's context so that it will get cleaned up appropriately if we
1040  * error out partway through.
1041  */
1042 #ifdef MAYBE_RECOVER_RELATION_BUILD_MEMORY
1043  MemoryContext tmpcxt = NULL;
1044  MemoryContext oldcxt = NULL;
1045 
1047  {
1049  "RelationBuildDesc workspace",
1051  oldcxt = MemoryContextSwitchTo(tmpcxt);
1052  }
1053 #endif
1054 
1055  /* Register to catch invalidation messages */
1057  {
1058  int allocsize;
1059 
1060  allocsize = in_progress_list_maxlen * 2;
1062  allocsize * sizeof(*in_progress_list));
1063  in_progress_list_maxlen = allocsize;
1064  }
1065  in_progress_offset = in_progress_list_len++;
1066  in_progress_list[in_progress_offset].reloid = targetRelId;
1067 retry:
1068  in_progress_list[in_progress_offset].invalidated = false;
1069 
1070  /*
1071  * find the tuple in pg_class corresponding to the given relation id
1072  */
1073  pg_class_tuple = ScanPgRelation(targetRelId, true, false);
1074 
1075  /*
1076  * if no such tuple exists, return NULL
1077  */
1078  if (!HeapTupleIsValid(pg_class_tuple))
1079  {
1080 #ifdef MAYBE_RECOVER_RELATION_BUILD_MEMORY
1081  if (tmpcxt)
1082  {
1083  /* Return to caller's context, and blow away the temporary context */
1084  MemoryContextSwitchTo(oldcxt);
1085  MemoryContextDelete(tmpcxt);
1086  }
1087 #endif
1088  Assert(in_progress_offset + 1 == in_progress_list_len);
1090  return NULL;
1091  }
1092 
1093  /*
1094  * get information from the pg_class_tuple
1095  */
1096  relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);
1097  relid = relp->oid;
1098  Assert(relid == targetRelId);
1099 
1100  /*
1101  * allocate storage for the relation descriptor, and copy pg_class_tuple
1102  * to relation->rd_rel.
1103  */
1104  relation = AllocateRelationDesc(relp);
1105 
1106  /*
1107  * initialize the relation's relation id (relation->rd_id)
1108  */
1109  RelationGetRelid(relation) = relid;
1110 
1111  /*
1112  * Normal relations are not nailed into the cache. Since we don't flush
1113  * new relations, it won't be new. It could be temp though.
1114  */
1115  relation->rd_refcnt = 0;
1116  relation->rd_isnailed = false;
1121  switch (relation->rd_rel->relpersistence)
1122  {
1123  case RELPERSISTENCE_UNLOGGED:
1124  case RELPERSISTENCE_PERMANENT:
1125  relation->rd_backend = InvalidBackendId;
1126  relation->rd_islocaltemp = false;
1127  break;
1128  case RELPERSISTENCE_TEMP:
1129  if (isTempOrTempToastNamespace(relation->rd_rel->relnamespace))
1130  {
1131  relation->rd_backend = BackendIdForTempRelations();
1132  relation->rd_islocaltemp = true;
1133  }
1134  else
1135  {
1136  /*
1137  * If it's a temp table, but not one of ours, we have to use
1138  * the slow, grotty method to figure out the owning backend.
1139  *
1140  * Note: it's possible that rd_backend gets set to MyBackendId
1141  * here, in case we are looking at a pg_class entry left over
1142  * from a crashed backend that coincidentally had the same
1143  * BackendId we're using. We should *not* consider such a
1144  * table to be "ours"; this is why we need the separate
1145  * rd_islocaltemp flag. The pg_class entry will get flushed
1146  * if/when we clean out the corresponding temp table namespace
1147  * in preparation for using it.
1148  */
1149  relation->rd_backend =
1150  GetTempNamespaceBackendId(relation->rd_rel->relnamespace);
1151  Assert(relation->rd_backend != InvalidBackendId);
1152  relation->rd_islocaltemp = false;
1153  }
1154  break;
1155  default:
1156  elog(ERROR, "invalid relpersistence: %c",
1157  relation->rd_rel->relpersistence);
1158  break;
1159  }
1160 
1161  /*
1162  * initialize the tuple descriptor (relation->rd_att).
1163  */
1164  RelationBuildTupleDesc(relation);
1165 
1166  /*
1167  * Fetch rules and triggers that affect this relation
1168  */
1169  if (relation->rd_rel->relhasrules)
1170  RelationBuildRuleLock(relation);
1171  else
1172  {
1173  relation->rd_rules = NULL;
1174  relation->rd_rulescxt = NULL;
1175  }
1176 
1177  if (relation->rd_rel->relhastriggers)
1178  RelationBuildTriggers(relation);
1179  else
1180  relation->trigdesc = NULL;
1181 
1182  if (relation->rd_rel->relrowsecurity)
1183  RelationBuildRowSecurity(relation);
1184  else
1185  relation->rd_rsdesc = NULL;
1186 
1187  /* foreign key data is not loaded till asked for */
1188  relation->rd_fkeylist = NIL;
1189  relation->rd_fkeyvalid = false;
1190 
1191  /* partitioning data is not loaded till asked for */
1192  relation->rd_partkey = NULL;
1193  relation->rd_partkeycxt = NULL;
1194  relation->rd_partdesc = NULL;
1195  relation->rd_partdesc_nodetached = NULL;
1197  relation->rd_pdcxt = NULL;
1198  relation->rd_pddcxt = NULL;
1199  relation->rd_partcheck = NIL;
1200  relation->rd_partcheckvalid = false;
1201  relation->rd_partcheckcxt = NULL;
1202 
1203  /*
1204  * initialize access method information
1205  */
1206  switch (relation->rd_rel->relkind)
1207  {
1208  case RELKIND_INDEX:
1209  case RELKIND_PARTITIONED_INDEX:
1210  Assert(relation->rd_rel->relam != InvalidOid);
1211  RelationInitIndexAccessInfo(relation);
1212  break;
1213  case RELKIND_RELATION:
1214  case RELKIND_TOASTVALUE:
1215  case RELKIND_MATVIEW:
1216  Assert(relation->rd_rel->relam != InvalidOid);
1218  break;
1219  case RELKIND_SEQUENCE:
1220  Assert(relation->rd_rel->relam == InvalidOid);
1222  break;
1223  case RELKIND_VIEW:
1224  case RELKIND_COMPOSITE_TYPE:
1225  case RELKIND_FOREIGN_TABLE:
1226  case RELKIND_PARTITIONED_TABLE:
1227  Assert(relation->rd_rel->relam == InvalidOid);
1228  break;
1229  }
1230 
1231  /* extract reloptions if any */
1232  RelationParseRelOptions(relation, pg_class_tuple);
1233 
1234  /*
1235  * initialize the relation lock manager information
1236  */
1237  RelationInitLockInfo(relation); /* see lmgr.c */
1238 
1239  /*
1240  * initialize physical addressing information for the relation
1241  */
1242  RelationInitPhysicalAddr(relation);
1243 
1244  /* make sure relation is marked as having no open file yet */
1245  relation->rd_smgr = NULL;
1246 
1247  /*
1248  * now we can free the memory allocated for pg_class_tuple
1249  */
1250  heap_freetuple(pg_class_tuple);
1251 
1252  /*
1253  * If an invalidation arrived mid-build, start over. Between here and the
1254  * end of this function, don't add code that does or reasonably could read
1255  * system catalogs. That range must be free from invalidation processing
1256  * for the !insertIt case. For the insertIt case, RelationCacheInsert()
1257  * will enroll this relation in ordinary relcache invalidation processing,
1258  */
1259  if (in_progress_list[in_progress_offset].invalidated)
1260  {
1261  RelationDestroyRelation(relation, false);
1262  goto retry;
1263  }
1264  Assert(in_progress_offset + 1 == in_progress_list_len);
1266 
1267  /*
1268  * Insert newly created relation into relcache hash table, if requested.
1269  *
1270  * There is one scenario in which we might find a hashtable entry already
1271  * present, even though our caller failed to find it: if the relation is a
1272  * system catalog or index that's used during relcache load, we might have
1273  * recursively created the same relcache entry during the preceding steps.
1274  * So allow RelationCacheInsert to delete any already-present relcache
1275  * entry for the same OID. The already-present entry should have refcount
1276  * zero (else somebody forgot to close it); in the event that it doesn't,
1277  * we'll elog a WARNING and leak the already-present entry.
1278  */
1279  if (insertIt)
1280  RelationCacheInsert(relation, true);
1281 
1282  /* It's fully valid */
1283  relation->rd_isvalid = true;
1284 
1285 #ifdef MAYBE_RECOVER_RELATION_BUILD_MEMORY
1286  if (tmpcxt)
1287  {
1288  /* Return to caller's context, and blow away the temporary context */
1289  MemoryContextSwitchTo(oldcxt);
1290  MemoryContextDelete(tmpcxt);
1291  }
1292 #endif
1293 
1294  return relation;
1295 }
#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
bool invalidated
Definition: relcache.c:164
void RelationBuildRowSecurity(Relation relation)
Definition: policy.c:196
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3226
void RelationInitTableAccessMethod(Relation relation)
Definition: relcache.c:1794
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:240
static Relation AllocateRelationDesc(Form_pg_class relp)
Definition: relcache.c:404
#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:1305
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
void RelationInitLockInfo(Relation relation)
Definition: lmgr.c:72
static int in_progress_list_len
Definition: relcache.c:168
#define BackendIdForTempRelations()
Definition: backendid.h:34
static void RelationParseRelOptions(Relation relation, HeapTuple tuple)
Definition: relcache.c:459
static int in_progress_list_maxlen
Definition: relcache.c:169
static void RelationBuildTupleDesc(Relation relation)
Definition: relcache.c:516
#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
static void RelationDestroyRelation(Relation relation, bool remember_tupdesc)
Definition: relcache.c:2393
PartitionDesc rd_partdesc_nodetached
Definition: rel.h:132
#define InvalidOid
Definition: postgres_ext.h:36
static InProgressEnt * in_progress_list
Definition: relcache.c:167
#define RelationCacheInsert(RELATION, replace_allowed)
Definition: relcache.c:206
#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 * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
void RelationInitIndexAccessInfo(Relation relation)
Definition: relcache.c:1411
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:334
#define elog(elevel,...)
Definition: elog.h:232
static void RelationBuildRuleLock(Relation relation)
Definition: relcache.c:726
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 3445 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().

3456 {
3457  Relation rel;
3458  MemoryContext oldcxt;
3459  int natts = tupDesc->natts;
3460  int i;
3461  bool has_not_null;
3462  bool nailit;
3463 
3464  AssertArg(natts >= 0);
3465 
3466  /*
3467  * check for creation of a rel that must be nailed in cache.
3468  *
3469  * XXX this list had better match the relations specially handled in
3470  * RelationCacheInitializePhase2/3.
3471  */
3472  switch (relid)
3473  {
3474  case DatabaseRelationId:
3475  case AuthIdRelationId:
3476  case AuthMemRelationId:
3477  case RelationRelationId:
3478  case AttributeRelationId:
3479  case ProcedureRelationId:
3480  case TypeRelationId:
3481  nailit = true;
3482  break;
3483  default:
3484  nailit = false;
3485  break;
3486  }
3487 
3488  /*
3489  * check that hardwired list of shared rels matches what's in the
3490  * bootstrap .bki file. If you get a failure here during initdb, you
3491  * probably need to fix IsSharedRelation() to match whatever you've done
3492  * to the set of shared relations.
3493  */
3494  if (shared_relation != IsSharedRelation(relid))
3495  elog(ERROR, "shared_relation flag for \"%s\" does not match IsSharedRelation(%u)",
3496  relname, relid);
3497 
3498  /* Shared relations had better be mapped, too */
3499  Assert(mapped_relation || !shared_relation);
3500 
3501  /*
3502  * switch to the cache context to create the relcache entry.
3503  */
3504  if (!CacheMemoryContext)
3506 
3508 
3509  /*
3510  * allocate a new relation descriptor and fill in basic state fields.
3511  */
3512  rel = (Relation) palloc0(sizeof(RelationData));
3513 
3514  /* make sure relation is marked as having no open file yet */
3515  rel->rd_smgr = NULL;
3516 
3517  /* mark it nailed if appropriate */
3518  rel->rd_isnailed = nailit;
3519 
3520  rel->rd_refcnt = nailit ? 1 : 0;
3521 
3522  /* it's being created in this transaction */
3527 
3528  /*
3529  * create a new tuple descriptor from the one passed in. We do this
3530  * partly to copy it into the cache context, and partly because the new
3531  * relation can't have any defaults or constraints yet; they have to be
3532  * added in later steps, because they require additions to multiple system
3533  * catalogs. We can copy attnotnull constraints here, however.
3534  */
3535  rel->rd_att = CreateTupleDescCopy(tupDesc);
3536  rel->rd_att->tdrefcount = 1; /* mark as refcounted */
3537  has_not_null = false;
3538  for (i = 0; i < natts; i++)
3539  {
3540  Form_pg_attribute satt = TupleDescAttr(tupDesc, i);
3541  Form_pg_attribute datt = TupleDescAttr(rel->rd_att, i);
3542 
3543  datt->attidentity = satt->attidentity;
3544  datt->attgenerated = satt->attgenerated;
3545  datt->attnotnull = satt->attnotnull;
3546  has_not_null |= satt->attnotnull;
3547  }
3548 
3549  if (has_not_null)
3550  {
3551  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
3552 
3553  constr->has_not_null = true;
3554  rel->rd_att->constr = constr;
3555  }
3556 
3557  /*
3558  * initialize relation tuple form (caller may add/override data later)
3559  */
3561 
3562  namestrcpy(&rel->rd_rel->relname, relname);
3563  rel->rd_rel->relnamespace = relnamespace;
3564 
3565  rel->rd_rel->relkind = relkind;
3566  rel->rd_rel->relnatts = natts;
3567  rel->rd_rel->reltype = InvalidOid;
3568  /* needed when bootstrapping: */
3569  rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;
3570 
3571  /* set up persistence and relcache fields dependent on it */
3572  rel->rd_rel->relpersistence = relpersistence;
3573  switch (relpersistence)
3574  {
3575  case RELPERSISTENCE_UNLOGGED:
3576  case RELPERSISTENCE_PERMANENT:
3578  rel->rd_islocaltemp = false;
3579  break;
3580  case RELPERSISTENCE_TEMP:
3581  Assert(isTempOrTempToastNamespace(relnamespace));
3583  rel->rd_islocaltemp = true;
3584  break;
3585  default:
3586  elog(ERROR, "invalid relpersistence: %c", relpersistence);
3587  break;
3588  }
3589 
3590  /* if it's a materialized view, it's not populated initially */
3591  if (relkind == RELKIND_MATVIEW)
3592  rel->rd_rel->relispopulated = false;
3593  else
3594  rel->rd_rel->relispopulated = true;
3595 
3596  /* set replica identity -- system catalogs and non-tables don't have one */
3597  if (!IsCatalogNamespace(relnamespace) &&
3598  (relkind == RELKIND_RELATION ||
3599  relkind == RELKIND_MATVIEW ||
3600  relkind == RELKIND_PARTITIONED_TABLE))
3601  rel->rd_rel->relreplident = REPLICA_IDENTITY_DEFAULT;
3602  else
3603  rel->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
3604 
3605  /*
3606  * Insert relation physical and logical identifiers (OIDs) into the right
3607  * places. For a mapped relation, we set relfilenode to zero and rely on
3608  * RelationInitPhysicalAddr to consult the map.
3609  */
3610  rel->rd_rel->relisshared = shared_relation;
3611 
3612  RelationGetRelid(rel) = relid;
3613 
3614  for (i = 0; i < natts; i++)
3615  TupleDescAttr(rel->rd_att, i)->attrelid = relid;
3616 
3617  rel->rd_rel->reltablespace = reltablespace;
3618 
3619  if (mapped_relation)
3620  {
3621  rel->rd_rel->relfilenode = InvalidOid;
3622  /* Add it to the active mapping information */
3623  RelationMapUpdateMap(relid, relfilenode, shared_relation, true);
3624  }
3625  else
3626  rel->rd_rel->relfilenode = relfilenode;
3627 
3628  RelationInitLockInfo(rel); /* see lmgr.c */
3629 
3631 
3632  rel->rd_rel->relam = accessmtd;
3633 
3634  /*
3635  * RelationInitTableAccessMethod will do syscache lookups, so we mustn't
3636  * run it in CacheMemoryContext. Fortunately, the remaining steps don't
3637  * require a long-lived current context.
3638  */
3639  MemoryContextSwitchTo(oldcxt);
3640 
3641  if (relkind == RELKIND_RELATION ||
3642  relkind == RELKIND_SEQUENCE ||
3643  relkind == RELKIND_TOASTVALUE ||
3644  relkind == RELKIND_MATVIEW)
3646 
3647  /*
3648  * Okay to insert into the relcache hash table.
3649  *
3650  * Ordinarily, there should certainly not be an existing hash entry for
3651  * the same OID; but during bootstrap, when we create a "real" relcache
3652  * entry for one of the bootstrap relations, we'll be overwriting the
3653  * phony one created with formrdesc. So allow that to happen for nailed
3654  * rels.
3655  */
3656  RelationCacheInsert(rel, nailit);
3657 
3658  /*
3659  * Flag relation as needing eoxact cleanup (to clear rd_createSubid). We
3660  * can't do this before storing relid in it.
3661  */
3662  EOXactListAdd(rel);
3663 
3664  /* It's fully valid */
3665  rel->rd_isvalid = true;
3666 
3667  /*
3668  * Caller expects us to pin the returned entry.
3669  */
3671 
3672  return rel;
3673 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
#define EOXactListAdd(rel)
Definition: relcache.c:186
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:1794
#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:26
#define ERROR
Definition: elog.h:46
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1305
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:2119
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:206
#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:724
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 726 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().

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

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

References LWLockRelease().

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

6569 {
6570  LWLockRelease(RelCacheInitLock);
6571 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )

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

6544 {
6545  char localinitfname[MAXPGPATH];
6546  char sharedinitfname[MAXPGPATH];
6547 
6548  if (DatabasePath)
6549  snprintf(localinitfname, sizeof(localinitfname), "%s/%s",
6551  snprintf(sharedinitfname, sizeof(sharedinitfname), "global/%s",
6553 
6554  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6555 
6556  /*
6557  * The files might not be there if no backend has been started since the
6558  * last removal. But complain about failures other than ENOENT with
6559  * ERROR. Fortunately, it's not too late to abort the transaction if we
6560  * can't get rid of the would-be-obsolete init file.
6561  */
6562  if (DatabasePath)
6563  unlink_initfile(localinitfname, ERROR);
6564  unlink_initfile(sharedinitfname, ERROR);
6565 }
#define ERROR
Definition: elog.h:46
#define MAXPGPATH
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:24
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:6640
#define snprintf
Definition: port.h:217

◆ RelationCacheInitFileRemove()

void RelationCacheInitFileRemove ( void  )

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

6584 {
6585  const char *tblspcdir = "pg_tblspc";
6586  DIR *dir;
6587  struct dirent *de;
6588  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6589 
6590  snprintf(path, sizeof(path), "global/%s",
6592  unlink_initfile(path, LOG);
6593 
6594  /* Scan everything in the default tablespace */
6596 
6597  /* Scan the tablespace link directory to find non-default tablespaces */
6598  dir = AllocateDir(tblspcdir);
6599 
6600  while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6601  {
6602  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6603  {
6604  /* Scan the tablespace dir for per-database dirs */
6605  snprintf(path, sizeof(path), "%s/%s/%s",
6606  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6608  }
6609  }
6610 
6611  FreeDir(dir);
6612 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6616
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2802
#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:2721
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:24
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6640
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:217
int FreeDir(DIR *dir)
Definition: fd.c:2839

◆ RelationCacheInitFileRemoveInDir()

static void RelationCacheInitFileRemoveInDir ( const char *  tblspcpath)
static

Definition at line 6616 of file relcache.c.

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

Referenced by RelationCacheInitFileRemove().

6617 {
6618  DIR *dir;
6619  struct dirent *de;
6620  char initfilename[MAXPGPATH * 2];
6621 
6622  /* Scan the tablespace directory to find per-database directories */
6623  dir = AllocateDir(tblspcpath);
6624 
6625  while ((de = ReadDirExtended(dir, tblspcpath, LOG)) != NULL)
6626  {
6627  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6628  {
6629  /* Try to remove the init file in each database */
6630  snprintf(initfilename, sizeof(initfilename), "%s/%s/%s",
6631  tblspcpath, de->d_name, RELCACHE_INIT_FILENAME);
6632  unlink_initfile(initfilename, LOG);
6633  }
6634  }
6635 
6636  FreeDir(dir);
6637 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2802
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2721
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:24
static void unlink_initfile(const char *initfilename, int elevel)
Definition: relcache.c:6640
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:217
int FreeDir(DIR *dir)
Definition: fd.c:2839

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 3868 of file relcache.c.

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

Referenced by InitPostgres().

3869 {
3870  HASHCTL ctl;
3871  int allocsize;
3872 
3873  /*
3874  * make sure cache memory context exists
3875  */
3876  if (!CacheMemoryContext)
3878 
3879  /*
3880  * create hashtable that indexes the relcache
3881  */
3882  ctl.keysize = sizeof(Oid);
3883  ctl.entrysize = sizeof(RelIdCacheEnt);
3884  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3885  &ctl, HASH_ELEM | HASH_BLOBS);
3886 
3887  /*
3888  * reserve enough in_progress_list slots for many cases
3889  */
3890  allocsize = 4;
3893  allocsize * sizeof(*in_progress_list));
3894  in_progress_list_maxlen = allocsize;
3895 
3896  /*
3897  * relation mapper needs to be initialized too
3898  */
3900 }
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
static int in_progress_list_maxlen
Definition: relcache.c:169
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
static InProgressEnt * in_progress_list
Definition: relcache.c:167
void CreateCacheMemoryContext(void)
Definition: catcache.c:620
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
#define INITRELCACHESIZE
Definition: relcache.c:3865
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ RelationCacheInitializePhase2()

void RelationCacheInitializePhase2 ( void  )

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

3915 {
3916  MemoryContext oldcxt;
3917 
3918  /*
3919  * relation mapper needs initialized too
3920  */
3922 
3923  /*
3924  * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3925  * nothing.
3926  */
3928  return;
3929 
3930  /*
3931  * switch to cache memory context
3932  */
3934 
3935  /*
3936  * Try to load the shared relcache cache file. If unsuccessful, bootstrap
3937  * the cache with pre-made descriptors for the critical shared catalogs.
3938  */
3939  if (!load_relcache_init_file(true))
3940  {
3941  formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
3942  Natts_pg_database, Desc_pg_database);
3943  formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
3944  Natts_pg_authid, Desc_pg_authid);
3945  formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
3946  Natts_pg_auth_members, Desc_pg_auth_members);
3947  formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
3948  Natts_pg_shseclabel, Desc_pg_shseclabel);
3949  formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
3950  Natts_pg_subscription, Desc_pg_subscription);
3951 
3952 #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
3953  }
3954 
3955  MemoryContextSwitchTo(oldcxt);
3956 }
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:5857
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:1858
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ RelationCacheInitializePhase3()

void RelationCacheInitializePhase3 ( void  )

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

3974 {
3976  RelIdCacheEnt *idhentry;
3977  MemoryContext oldcxt;
3978  bool needNewCacheFile = !criticalSharedRelcachesBuilt;
3979 
3980  /*
3981  * relation mapper needs initialized too
3982  */
3984 
3985  /*
3986  * switch to cache memory context
3987  */
3989 
3990  /*
3991  * Try to load the local relcache cache file. If unsuccessful, bootstrap
3992  * the cache with pre-made descriptors for the critical "nailed-in" system
3993  * catalogs.
3994  */
3995  if (IsBootstrapProcessingMode() ||
3996  !load_relcache_init_file(false))
3997  {
3998  needNewCacheFile = true;
3999 
4000  formrdesc("pg_class", RelationRelation_Rowtype_Id, false,
4001  Natts_pg_class, Desc_pg_class);
4002  formrdesc("pg_attribute", AttributeRelation_Rowtype_Id, false,
4003  Natts_pg_attribute, Desc_pg_attribute);
4004  formrdesc("pg_proc", ProcedureRelation_Rowtype_Id, false,
4005  Natts_pg_proc, Desc_pg_proc);
4006  formrdesc("pg_type", TypeRelation_Rowtype_Id, false,
4007  Natts_pg_type, Desc_pg_type);
4008 
4009 #define NUM_CRITICAL_LOCAL_RELS 4 /* fix if you change list above */
4010  }
4011 
4012  MemoryContextSwitchTo(oldcxt);
4013 
4014  /* In bootstrap mode, the faked-up formrdesc info is all we'll have */
4016  return;
4017 
4018  /*
4019  * If we didn't get the critical system indexes loaded into relcache, do
4020  * so now. These are critical because the catcache and/or opclass cache
4021  * depend on them for fetches done during relcache load. Thus, we have an
4022  * infinite-recursion problem. We can break the recursion by doing
4023  * heapscans instead of indexscans at certain key spots. To avoid hobbling
4024  * performance, we only want to do that until we have the critical indexes
4025  * loaded into relcache. Thus, the flag criticalRelcachesBuilt is used to
4026  * decide whether to do heapscan or indexscan at the key spots, and we set
4027  * it true after we've loaded the critical indexes.
4028  *
4029  * The critical indexes are marked as "nailed in cache", partly to make it
4030  * easy for load_relcache_init_file to count them, but mainly because we
4031  * cannot flush and rebuild them once we've set criticalRelcachesBuilt to
4032  * true. (NOTE: perhaps it would be possible to reload them by
4033  * temporarily setting criticalRelcachesBuilt to false again. For now,
4034  * though, we just nail 'em in.)
4035  *
4036  * RewriteRelRulenameIndexId and TriggerRelidNameIndexId are not critical
4037  * in the same way as the others, because the critical catalogs don't
4038  * (currently) have any rules or triggers, and so these indexes can be
4039  * rebuilt without inducing recursion. However they are used during
4040  * relcache load when a rel does have rules or triggers, so we choose to
4041  * nail them for performance reasons.
4042  */
4044  {
4045  load_critical_index(ClassOidIndexId,
4046  RelationRelationId);
4047  load_critical_index(AttributeRelidNumIndexId,
4048  AttributeRelationId);
4049  load_critical_index(IndexRelidIndexId,
4050  IndexRelationId);
4051  load_critical_index(OpclassOidIndexId,
4052  OperatorClassRelationId);
4053  load_critical_index(AccessMethodProcedureIndexId,
4054  AccessMethodProcedureRelationId);
4055  load_critical_index(RewriteRelRulenameIndexId,
4056  RewriteRelationId);
4057  load_critical_index(TriggerRelidNameIndexId,
4058  TriggerRelationId);
4059 
4060 #define NUM_CRITICAL_LOCAL_INDEXES 7 /* fix if you change list above */
4061 
4062  criticalRelcachesBuilt = true;
4063  }
4064 
4065  /*
4066  * Process critical shared indexes too.
4067  *
4068  * DatabaseNameIndexId isn't critical for relcache loading, but rather for
4069  * initial lookup of MyDatabaseId, without which we'll never find any
4070  * non-shared catalogs at all. Autovacuum calls InitPostgres with a
4071  * database OID, so it instead depends on DatabaseOidIndexId. We also
4072  * need to nail up some indexes on pg_authid and pg_auth_members for use
4073  * during client authentication. SharedSecLabelObjectIndexId isn't
4074  * critical for the core system, but authentication hooks might be
4075  * interested in it.
4076  */
4078  {
4079  load_critical_index(DatabaseNameIndexId,
4080  DatabaseRelationId);
4081  load_critical_index(DatabaseOidIndexId,
4082  DatabaseRelationId);
4083  load_critical_index(AuthIdRolnameIndexId,
4084  AuthIdRelationId);
4085  load_critical_index(AuthIdOidIndexId,
4086  AuthIdRelationId);
4087  load_critical_index(AuthMemMemRoleIndexId,
4088  AuthMemRelationId);
4089  load_critical_index(SharedSecLabelObjectIndexId,
4090  SharedSecLabelRelationId);
4091 
4092 #define NUM_CRITICAL_SHARED_INDEXES 6 /* fix if you change list above */
4093 
4095  }
4096 
4097  /*
4098  * Now, scan all the relcache entries and update anything that might be
4099  * wrong in the results from formrdesc or the relcache cache file. If we
4100  * faked up relcache entries using formrdesc, then read the real pg_class
4101  * rows and replace the fake entries with them. Also, if any of the
4102  * relcache entries have rules, triggers, or security policies, load that
4103  * info the hard way since it isn't recorded in the cache file.
4104  *
4105  * Whenever we access the catalogs to read data, there is a possibility of
4106  * a shared-inval cache flush causing relcache entries to be removed.
4107  * Since hash_seq_search only guarantees to still work after the *current*
4108  * entry is removed, it's unsafe to continue the hashtable scan afterward.
4109  * We handle this by restarting the scan from scratch after each access.
4110  * This is theoretically O(N^2), but the number of entries that actually
4111  * need to be fixed is small enough that it doesn't matter.
4112  */
4113  hash_seq_init(&status, RelationIdCache);
4114 
4115  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
4116  {
4117  Relation relation = idhentry->reldesc;
4118  bool restart = false;
4119 
4120  /*
4121  * Make sure *this* entry doesn't get flushed while we work with it.
4122  */
4124 
4125  /*
4126  * If it's a faked-up entry, read the real pg_class tuple.
4127  */
4128  if (relation->rd_rel->relowner == InvalidOid)
4129  {
4130  HeapTuple htup;
4131  Form_pg_class relp;
4132 
4133  htup = SearchSysCache1(RELOID,
4134  ObjectIdGetDatum(RelationGetRelid(relation)));
4135  if (!HeapTupleIsValid(htup))
4136  elog(FATAL, "cache lookup failed for relation %u",
4137  RelationGetRelid(relation));
4138  relp = (Form_pg_class) GETSTRUCT(htup);
4139 
4140  /*
4141  * Copy tuple to relation->rd_rel. (See notes in
4142  * AllocateRelationDesc())
4143  */
4144  memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
4145 
4146  /* Update rd_options while we have the tuple */
4147  if (relation->rd_options)
4148  pfree(relation->rd_options);
4149  RelationParseRelOptions(relation, htup);
4150 
4151  /*
4152  * Check the values in rd_att were set up correctly. (We cannot
4153  * just copy them over now: formrdesc must have set up the rd_att
4154  * data correctly to start with, because it may already have been
4155  * copied into one or more catcache entries.)
4156  */
4157  Assert(relation->rd_att->tdtypeid == relp->reltype);
4158  Assert(relation->rd_att->tdtypmod == -1);
4159 
4160  ReleaseSysCache(htup);
4161 
4162  /* relowner had better be OK now, else we'll loop forever */
4163  if (relation->rd_rel->relowner == InvalidOid)
4164  elog(ERROR, "invalid relowner in pg_class entry for \"%s\"",
4165  RelationGetRelationName(relation));
4166 
4167  restart = true;
4168  }
4169 
4170  /*
4171  * Fix data that isn't saved in relcache cache file.
4172  *
4173  * relhasrules or relhastriggers could possibly be wrong or out of
4174  * date. If we don't actually find any rules or triggers, clear the
4175  * local copy of the flag so that we don't get into an infinite loop
4176  * here. We don't make any attempt to fix the pg_class entry, though.
4177  */
4178  if (relation->rd_rel->relhasrules && relation->rd_rules == NULL)
4179  {
4180  RelationBuildRuleLock(relation);
4181  if (relation->rd_rules == NULL)
4182  relation->rd_rel->relhasrules = false;
4183  restart = true;
4184  }
4185  if (relation->rd_rel->relhastriggers && relation->trigdesc == NULL)
4186  {
4187  RelationBuildTriggers(relation);
4188  if (relation->trigdesc == NULL)
4189  relation->rd_rel->relhastriggers = false;
4190  restart = true;
4191  }
4192 
4193  /*
4194  * Re-load the row security policies if the relation has them, since
4195  * they are not preserved in the cache. Note that we can never NOT
4196  * have a policy while relrowsecurity is true,
4197  * RelationBuildRowSecurity will create a single default-deny policy
4198  * if there is no policy defined in pg_policy.
4199  */
4200  if (relation->rd_rel->relrowsecurity && relation->rd_rsdesc == NULL)
4201  {
4202  RelationBuildRowSecurity(relation);
4203 
4204  Assert(relation->rd_rsdesc != NULL);
4205  restart = true;
4206  }
4207 
4208  /* Reload tableam data if needed */
4209  if (relation->rd_tableam == NULL &&
4210  (relation->rd_rel->relkind == RELKIND_RELATION ||
4211  relation->rd_rel->relkind == RELKIND_SEQUENCE ||
4212  relation->rd_rel->relkind == RELKIND_TOASTVALUE ||
4213  relation->rd_rel->relkind == RELKIND_MATVIEW))
4214  {
4216  Assert(relation->rd_tableam != NULL);
4217 
4218  restart = true;
4219  }
4220 
4221  /* Release hold on the relation */
4223 
4224  /* Now, restart the hashtable scan if needed */
4225  if (restart)
4226  {
4227  hash_seq_term(&status);
4228  hash_seq_init(&status, RelationIdCache);
4229  }
4230  }
4231 
4232  /*
4233  * Lastly, write out new relcache cache files if needed. We don't bother
4234  * to distinguish cases where only one of the two needs an update.
4235  */
4236  if (needNewCacheFile)
4237  {
4238  /*
4239  * Force all the catcaches to finish initializing and thereby open the
4240  * catalogs and indexes they use. This will preload the relcache with
4241  * entries for all the most important system catalogs and indexes, so
4242  * that the init files will be most useful for future backends.
4243  */
4245 
4246  /* now write the files */
4248  write_relcache_init_file(false);
4249  }
4250 }
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5857
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
void RelationBuildRowSecurity(Relation relation)
Definition: policy.c:196
void RelationInitTableAccessMethod(Relation relation)
Definition: relcache.c:1794
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:2132
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:6276
TriggerDesc * trigdesc
Definition: rel.h:115
static void RelationParseRelOptions(Relation relation, HeapTuple tuple)
Definition: relcache.c:459
static void load_critical_index(Oid indexoid, Oid heapoid)
Definition: relcache.c:4259
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:2119
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:1858
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:726
bool criticalRelcachesBuilt
Definition: relcache.c:137
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:229
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 ( bool  debug_discard)

Definition at line 2912 of file relcache.c.

References Assert, hash_seq_init(), hash_seq_search(), i, in_progress_list_len, 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 InvalidateSystemCachesExtended(), and LocalExecuteInvalidationMessage().

2913 {
2915  RelIdCacheEnt *idhentry;
2916  Relation relation;
2917  List *rebuildFirstList = NIL;
2918  List *rebuildList = NIL;
2919  ListCell *l;
2920  int i;
2921 
2922  /*
2923  * Reload relation mapping data before starting to reconstruct cache.
2924  */
2926 
2927  /* Phase 1 */
2928  hash_seq_init(&status, RelationIdCache);
2929 
2930  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2931  {
2932  relation = idhentry->reldesc;
2933 
2934  /* Must close all smgr references to avoid leaving dangling ptrs */
2935  RelationCloseSmgr(relation);
2936 
2937  /*
2938  * Ignore new relations; no other backend will manipulate them before
2939  * we commit. Likewise, before replacing a relation's relfilenode, we
2940  * shall have acquired AccessExclusiveLock and drained any applicable
2941  * pending invalidations.
2942  */
2943  if (relation->rd_createSubid != InvalidSubTransactionId ||
2945  continue;
2946 
2948 
2949  if (RelationHasReferenceCountZero(relation))
2950  {
2951  /* Delete this entry immediately */
2952  Assert(!relation->rd_isnailed);
2953  RelationClearRelation(relation, false);
2954  }
2955  else
2956  {
2957  /*
2958  * If it's a mapped relation, immediately update its rd_node in
2959  * case its relfilenode changed. We must do this during phase 1
2960  * in case the relation is consulted during rebuild of other
2961  * relcache entries in phase 2. It's safe since consulting the
2962  * map doesn't involve any access to relcache entries.
2963  */
2964  if (RelationIsMapped(relation))
2965  RelationInitPhysicalAddr(relation);
2966 
2967  /*
2968  * Add this entry to list of stuff to rebuild in second pass.
2969  * pg_class goes to the front of rebuildFirstList while
2970  * pg_class_oid_index goes to the back of rebuildFirstList, so
2971  * they are done first and second respectively. Other nailed
2972  * relations go to the front of rebuildList, so they'll be done
2973  * next in no particular order; and everything else goes to the
2974  * back of rebuildList.
2975  */
2976  if (RelationGetRelid(relation) == RelationRelationId)
2977  rebuildFirstList = lcons(relation, rebuildFirstList);
2978  else if (RelationGetRelid(relation) == ClassOidIndexId)
2979  rebuildFirstList = lappend(rebuildFirstList, relation);
2980  else if (relation->rd_isnailed)
2981  rebuildList = lcons(relation, rebuildList);
2982  else
2983  rebuildList = lappend(rebuildList, relation);
2984  }
2985  }
2986 
2987  /*
2988  * Now zap any remaining smgr cache entries. This must happen before we
2989  * start to rebuild entries, since that may involve catalog fetches which
2990  * will re-open catalog files.
2991  */
2992  smgrcloseall();
2993 
2994  /* Phase 2: rebuild the items found to need rebuild in phase 1 */
2995  foreach(l, rebuildFirstList)
2996  {
2997  relation = (Relation) lfirst(l);
2998  RelationClearRelation(relation, true);
2999  }
3000  list_free(rebuildFirstList);
3001  foreach(l, rebuildList)
3002  {
3003  relation = (Relation) lfirst(l);
3004  RelationClearRelation(relation, true);
3005  }
3006  list_free(rebuildList);
3007 
3008  if (!debug_discard)
3009  /* Any RelationBuildDesc() on the stack must start over. */
3010  for (i = 0; i < in_progress_list_len; i++)
3011  in_progress_list[i].invalidated = true;
3012 }
#define NIL
Definition: pg_list.h:65
static long relcacheInvalsReceived
Definition: relcache.c:151
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2482
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:26
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1305
static int in_progress_list_len
Definition: relcache.c:168
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
static InProgressEnt * in_progress_list
Definition: relcache.c:167
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
int i
void RelationMapInvalidateAll(void)
Definition: relmapper.c:425
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:229
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:477

◆ RelationCacheInvalidateEntry()

void RelationCacheInvalidateEntry ( Oid  relationId)

Definition at line 2856 of file relcache.c.

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

Referenced by LocalExecuteInvalidationMessage().

2857 {
2858  Relation relation;
2859 
2860  RelationIdCacheLookup(relationId, relation);
2861 
2862  if (PointerIsValid(relation))
2863  {
2865  RelationFlushRelation(relation);
2866  }
2867  else
2868  {
2869  int i;
2870 
2871  for (i = 0; i < in_progress_list_len; i++)
2872  if (in_progress_list[i].reloid == relationId)
2873  in_progress_list[i].invalidated = true;
2874  }
2875 }
static long relcacheInvalsReceived
Definition: relcache.c:151
bool invalidated
Definition: relcache.c:164
#define RelationIdCacheLookup(ID, RELATION)
Definition: relcache.c:228
static int in_progress_list_len
Definition: relcache.c:168
static void RelationFlushRelation(Relation relation)
Definition: relcache.c:2779
static InProgressEnt * in_progress_list
Definition: relcache.c:167
int i
#define PointerIsValid(pointer)
Definition: c.h:698

◆ RelationClearRelation()

static void RelationClearRelation ( Relation  relation,
bool  rebuild 
)
static

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

2483 {
2484  /*
2485  * As per notes above, a rel to be rebuilt MUST have refcnt > 0; while of
2486  * course it would be an equally bad idea to blow away one with nonzero
2487  * refcnt, since that would leave someone somewhere with a dangling
2488  * pointer. All callers are expected to have verified that this holds.
2489  */
2490  Assert(rebuild ?
2491  !RelationHasReferenceCountZero(relation) :
2492  RelationHasReferenceCountZero(relation));
2493 
2494  /*
2495  * Make sure smgr and lower levels close the relation's files, if they
2496  * weren't closed already. If the relation is not getting deleted, the
2497  * next smgr access should reopen the files automatically. This ensures
2498  * that the low-level file access state is updated after, say, a vacuum
2499  * truncation.
2500  */
2501  RelationCloseSmgr(relation);
2502 
2503  /* Free AM cached data, if any */
2504  if (relation->rd_amcache)
2505  pfree(relation->rd_amcache);
2506  relation->rd_amcache = NUL