PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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/reloptions.h"
#include "access/sysattr.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "catalog/catalog.h"
#include "catalog/index.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/partition.h"
#include "catalog/pg_am.h"
#include "catalog/pg_amproc.h"
#include "catalog/pg_attrdef.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_auth_members.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_database.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_partitioned_table.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/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/prep.h"
#include "optimizer/var.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/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 "utils/tqual.h"
Include dependency graph for relcache.c:

Go to the source code of this file.

Data Structures

struct  relidcacheent
 
struct  opclasscacheent
 

Macros

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

Typedefs

typedef struct relidcacheent RelIdCacheEnt
 
typedef struct opclasscacheent OpClassCacheEnt
 

Functions

static void RelationDestroyRelation (Relation relation, bool remember_tupdesc)
 
static void RelationClearRelation (Relation relation, bool rebuild)
 
static void RelationReloadIndexInfo (Relation relation)
 
static void 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, bool hasoids, 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 void RelationBuildPartitionKey (Relation relation)
 
static PartitionKey copy_partition_key (PartitionKey fromkey)
 
static Relation RelationBuildDesc (Oid targetRelId, bool insertIt)
 
static void RelationInitPhysicalAddr (Relation relation)
 
static void load_critical_index (Oid indexoid, Oid heapoid)
 
static TupleDesc GetPgClassDescriptor (void)
 
static TupleDesc GetPgIndexDescriptor (void)
 
static void AttrDefaultFetch (Relation relation)
 
static void CheckConstraintFetch (Relation relation)
 
static int CheckConstraintCmp (const void *a, const void *b)
 
static Listinsert_ordered_oid (List *list, Oid datum)
 
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)
 
static bool equalPartitionDescs (PartitionKey key, PartitionDesc partdesc1, PartitionDesc partdesc2)
 
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)
 
Relation RelationIdGetRelation (Oid relationId)
 
void RelationIncrementReferenceCount (Relation rel)
 
void RelationDecrementReferenceCount (Relation rel)
 
void RelationClose (Relation relation)
 
void RelationForgetRelation (Oid rid)
 
void RelationCacheInvalidateEntry (Oid relationId)
 
void RelationCacheInvalidate (void)
 
void RelationCloseSmgrByOid (Oid relationId)
 
void AtEOXact_RelationCache (bool isCommit)
 
void AtEOSubXact_RelationCache (bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
 
Relation RelationBuildLocalRelation (const char *relname, Oid relnamespace, TupleDesc tupDesc, Oid relid, Oid relfilenode, Oid reltablespace, bool shared_relation, bool mapped_relation, char relpersistence, char relkind)
 
void RelationSetNewRelfilenode (Relation relation, char persistence, TransactionId freezeXid, MultiXactId minmulti)
 
void RelationCacheInitialize (void)
 
void RelationCacheInitializePhase2 (void)
 
void RelationCacheInitializePhase3 (void)
 
static TupleDesc BuildHardcodedDescriptor (int natts, const FormData_pg_attribute *attrs, bool hasoids)
 
ListRelationGetFKeyList (Relation relation)
 
ListRelationGetIndexList (Relation relation)
 
ListRelationGetStatExtList (Relation relation)
 
void RelationSetIndexList (Relation relation, List *indexIds, Oid oidIndex)
 
Oid RelationGetOidIndex (Relation relation)
 
Oid RelationGetPrimaryKeyIndex (Relation relation)
 
Oid RelationGetReplicaIndex (Relation relation)
 
ListRelationGetIndexExpressions (Relation relation)
 
ListRelationGetIndexPredicate (Relation relation)
 
BitmapsetRelationGetIndexAttrBitmap (Relation relation, IndexAttrBitmapKind attrKind)
 
void RelationGetExclusionInfo (Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
 
struct PublicationActionsGetRelationPublicationActions (Relation relation)
 
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)
 
bool RelationHasUnloggedIndex (Relation rel)
 
void RelationCacheInitFilePreInvalidate (void)
 
void RelationCacheInitFilePostInvalidate (void)
 
void RelationCacheInitFileRemove (void)
 

Variables

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

Macro Definition Documentation

#define EOXactListAdd (   rel)
Value:
do { \
eoxact_list[eoxact_list_len++] = (rel)->rd_id; \
} while (0)
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:156
#define MAX_EOXACT_LIST
Definition: relcache.c:155
static bool eoxact_list_overflowed
Definition: relcache.c:158
static int eoxact_list_len
Definition: relcache.c:157

Definition at line 160 of file relcache.c.

Referenced by RelationBuildLocalRelation(), RelationSetIndexList(), and RelationSetNewRelfilenode().

#define INITRELCACHESIZE   400

Definition at line 3536 of file relcache.c.

Referenced by RelationCacheInitialize().

#define MAX_EOXACT_LIST   32

Definition at line 155 of file relcache.c.

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

Referenced by load_relcache_init_file().

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

Referenced by load_relcache_init_file().

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

Referenced by load_relcache_init_file().

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

Referenced by load_relcache_init_file().

#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)
struct relidcacheent RelIdCacheEnt
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
static HTAB * RelationIdCache
Definition: relcache.c:123
#define WARNING
Definition: elog.h:40
#define elog
Definition: elog.h:219

Definition at line 214 of file relcache.c.

Referenced by RelationClearRelation().

#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)
struct relidcacheent RelIdCacheEnt
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
static HTAB * RelationIdCache
Definition: relcache.c:123
struct RelationData * Relation
Definition: relcache.h:21
#define RelationGetRelationName(relation)
Definition: rel.h:436
#define WARNING
Definition: elog.h:40
static void RelationDestroyRelation(Relation relation, bool remember_tupdesc)
Definition: relcache.c:2312
#define Assert(condition)
Definition: c.h:681
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:400
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:367
#define elog
Definition: elog.h:219

Definition at line 180 of file relcache.c.

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

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

Definition at line 202 of file relcache.c.

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

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

Definition at line 95 of file relcache.c.

Referenced by load_relcache_init_file(), and write_relcache_init_file().

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

Referenced by RelationClearRelation().

Typedef Documentation

Function Documentation

static Relation AllocateRelationDesc ( Form_pg_class  relp)
static

Definition at line 379 of file relcache.c.

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

Referenced by RelationBuildDesc().

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

Definition at line 3122 of file relcache.c.

References elog, InvalidOid, InvalidSubTransactionId, list_free(), NIL, RelationData::rd_createSubid, RelationData::rd_indexlist, RelationData::rd_indexvalid, RelationData::rd_newRelfilenodeSubid, RelationData::rd_oidindex, RelationData::rd_pkindex, RelationData::rd_replidindex, RelationClearRelation(), RelationGetRelationName, RelationHasReferenceCountZero, and WARNING.

Referenced by AtEOSubXact_RelationCache().

3124 {
3125  /*
3126  * Is it a relation created in the current subtransaction?
3127  *
3128  * During subcommit, mark it as belonging to the parent, instead. During
3129  * subabort, simply delete the relcache entry.
3130  */
3131  if (relation->rd_createSubid == mySubid)
3132  {
3133  if (isCommit)
3134  relation->rd_createSubid = parentSubid;
3135  else if (RelationHasReferenceCountZero(relation))
3136  {
3137  RelationClearRelation(relation, false);
3138  return;
3139  }
3140  else
3141  {
3142  /*
3143  * Hmm, somewhere there's a (leaked?) reference to the relation.
3144  * We daren't remove the entry for fear of dereferencing a
3145  * dangling pointer later. Bleat, and transfer it to the parent
3146  * subtransaction so we can try again later. This must be just a
3147  * WARNING to avoid error-during-error-recovery loops.
3148  */
3149  relation->rd_createSubid = parentSubid;
3150  elog(WARNING, "cannot remove relcache entry for \"%s\" because it has nonzero refcount",
3151  RelationGetRelationName(relation));
3152  }
3153  }
3154 
3155  /*
3156  * Likewise, update or drop any new-relfilenode-in-subtransaction hint.
3157  */
3158  if (relation->rd_newRelfilenodeSubid == mySubid)
3159  {
3160  if (isCommit)
3161  relation->rd_newRelfilenodeSubid = parentSubid;
3162  else
3164  }
3165 
3166  /*
3167  * Flush any temporary index list.
3168  */
3169  if (relation->rd_indexvalid == 2)
3170  {
3171  list_free(relation->rd_indexlist);
3172  relation->rd_indexlist = NIL;
3173  relation->rd_oidindex = InvalidOid;
3174  relation->rd_pkindex = InvalidOid;
3175  relation->rd_replidindex = InvalidOid;
3176  relation->rd_indexvalid = 0;
3177  }
3178 }
#define NIL
Definition: pg_list.h:69
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2396
Oid rd_replidindex
Definition: rel.h:138
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:111
Oid rd_pkindex
Definition: rel.h:137
char rd_indexvalid
Definition: rel.h:93
#define RelationGetRelationName(relation)
Definition: rel.h:436
Oid rd_oidindex
Definition: rel.h:136
List * rd_indexlist
Definition: rel.h:135
#define WARNING
Definition: elog.h:40
SubTransactionId rd_createSubid
Definition: rel.h:110
#define InvalidOid
Definition: postgres_ext.h:36
#define InvalidSubTransactionId
Definition: c.h:397
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:400
void list_free(List *list)
Definition: list.c:1133
#define elog
Definition: elog.h:219
void AtEOSubXact_RelationCache ( bool  isCommit,
SubTransactionId  mySubid,
SubTransactionId  parentSubid 
)

Definition at line 3075 of file relcache.c.

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

3077 {
3079  RelIdCacheEnt *idhentry;
3080  int i;
3081 
3082  /*
3083  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3084  * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3085  * logic as in AtEOXact_RelationCache.
3086  */
3088  {
3089  hash_seq_init(&status, RelationIdCache);
3090  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3091  {
3092  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3093  mySubid, parentSubid);
3094  }
3095  }
3096  else
3097  {
3098  for (i = 0; i < eoxact_list_len; i++)
3099  {
3100  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3101  (void *) &eoxact_list[i],
3102  HASH_FIND,
3103  NULL);
3104  if (idhentry != NULL)
3105  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3106  mySubid, parentSubid);
3107  }
3108  }
3109 
3110  /* Don't reset the list; we still need more cleanup later */
3111 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:156
static void AtEOSubXact_cleanup(Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
Definition: relcache.c:3122
Relation reldesc
Definition: relcache.c:120
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
static HTAB * RelationIdCache
Definition: relcache.c:123
static bool eoxact_list_overflowed
Definition: relcache.c:158
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1385
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1375
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
static int eoxact_list_len
Definition: relcache.c:157
static void AtEOXact_cleanup ( Relation  relation,
bool  isCommit 
)
static

Definition at line 2987 of file relcache.c.

References Assert, elog, InvalidOid, InvalidSubTransactionId, IsBootstrapProcessingMode, list_free(), NIL, RelationData::rd_createSubid, RelationData::rd_indexlist, RelationData::rd_indexvalid, RelationData::rd_isnailed, RelationData::rd_newRelfilenodeSubid, RelationData::rd_oidindex, RelationData::rd_pkindex, RelationData::rd_refcnt, RelationData::rd_replidindex, RelationClearRelation(), RelationGetRelationName, RelationHasReferenceCountZero, and WARNING.

Referenced by AtEOXact_RelationCache().

2988 {
2989  /*
2990  * The relcache entry's ref count should be back to its normal
2991  * not-in-a-transaction state: 0 unless it's nailed in cache.
2992  *
2993  * In bootstrap mode, this is NOT true, so don't check it --- the
2994  * bootstrap code expects relations to stay open across start/commit
2995  * transaction calls. (That seems bogus, but it's not worth fixing.)
2996  *
2997  * Note: ideally this check would be applied to every relcache entry, not
2998  * just those that have eoxact work to do. But it's not worth forcing a
2999  * scan of the whole relcache just for this. (Moreover, doing so would
3000  * mean that assert-enabled testing never tests the hash_search code path
3001  * above, which seems a bad idea.)
3002  */
3003 #ifdef USE_ASSERT_CHECKING
3005  {
3006  int expected_refcnt;
3007 
3008  expected_refcnt = relation->rd_isnailed ? 1 : 0;
3009  Assert(relation->rd_refcnt == expected_refcnt);
3010  }
3011 #endif
3012 
3013  /*
3014  * Is it a relation created in the current transaction?
3015  *
3016  * During commit, reset the flag to zero, since we are now out of the
3017  * creating transaction. During abort, simply delete the relcache entry
3018  * --- it isn't interesting any longer. (NOTE: if we have forgotten the
3019  * new-ness of a new relation due to a forced cache flush, the entry will
3020  * get deleted anyway by shared-cache-inval processing of the aborted
3021  * pg_class insertion.)
3022  */
3023  if (relation->rd_createSubid != InvalidSubTransactionId)
3024  {
3025  if (isCommit)
3027  else if (RelationHasReferenceCountZero(relation))
3028  {
3029  RelationClearRelation(relation, false);
3030  return;
3031  }
3032  else
3033  {
3034  /*
3035  * Hmm, somewhere there's a (leaked?) reference to the relation.
3036  * We daren't remove the entry for fear of dereferencing a
3037  * dangling pointer later. Bleat, and mark it as not belonging to
3038  * the current transaction. Hopefully it'll get cleaned up
3039  * eventually. This must be just a WARNING to avoid
3040  * error-during-error-recovery loops.
3041  */
3043  elog(WARNING, "cannot remove relcache entry for \"%s\" because it has nonzero refcount",
3044  RelationGetRelationName(relation));
3045  }
3046  }
3047 
3048  /*
3049  * Likewise, reset the hint about the relfilenode being new.
3050  */
3052 
3053  /*
3054  * Flush any temporary index list.
3055  */
3056  if (relation->rd_indexvalid == 2)
3057  {
3058  list_free(relation->rd_indexlist);
3059  relation->rd_indexlist = NIL;
3060  relation->rd_oidindex = InvalidOid;
3061  relation->rd_pkindex = InvalidOid;
3062  relation->rd_replidindex = InvalidOid;
3063  relation->rd_indexvalid = 0;
3064  }
3065 }
#define NIL
Definition: pg_list.h:69
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2396
Oid rd_replidindex
Definition: rel.h:138
bool rd_isnailed
Definition: rel.h:91
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:111
Oid rd_pkindex
Definition: rel.h:137
char rd_indexvalid
Definition: rel.h:93
#define RelationGetRelationName(relation)
Definition: rel.h:436
Oid rd_oidindex
Definition: rel.h:136
List * rd_indexlist
Definition: rel.h:135
#define WARNING
Definition: elog.h:40
SubTransactionId rd_createSubid
Definition: rel.h:110
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:681
#define InvalidSubTransactionId
Definition: c.h:397
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:400
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:367
int rd_refcnt
Definition: rel.h:88
void list_free(List *list)
Definition: list.c:1133
#define elog
Definition: elog.h:219
void AtEOXact_RelationCache ( bool  isCommit)

Definition at line 2924 of file relcache.c.

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

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

2925 {
2927  RelIdCacheEnt *idhentry;
2928  int i;
2929 
2930  /*
2931  * Unless the eoxact_list[] overflowed, we only need to examine the rels
2932  * listed in it. Otherwise fall back on a hash_seq_search scan.
2933  *
2934  * For simplicity, eoxact_list[] entries are not deleted till end of
2935  * top-level transaction, even though we could remove them at
2936  * subtransaction end in some cases, or remove relations from the list if
2937  * they are cleared for other reasons. Therefore we should expect the
2938  * case that list entries are not found in the hashtable; if not, there's
2939  * nothing to do for them.
2940  */
2942  {
2943  hash_seq_init(&status, RelationIdCache);
2944  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2945  {
2946  AtEOXact_cleanup(idhentry->reldesc, isCommit);
2947  }
2948  }
2949  else
2950  {
2951  for (i = 0; i < eoxact_list_len; i++)
2952  {
2953  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
2954  (void *) &eoxact_list[i],
2955  HASH_FIND,
2956  NULL);
2957  if (idhentry != NULL)
2958  AtEOXact_cleanup(idhentry->reldesc, isCommit);
2959  }
2960  }
2961 
2962  if (EOXactTupleDescArrayLen > 0)
2963  {
2964  Assert(EOXactTupleDescArray != NULL);
2965  for (i = 0; i < NextEOXactTupleDescNum; i++)
2968  EOXactTupleDescArray = NULL;
2969  }
2970 
2971  /* Now we're out of the transaction and can clear the lists */
2972  eoxact_list_len = 0;
2973  eoxact_list_overflowed = false;
2974  NextEOXactTupleDescNum = 0;
2976 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:156
static int EOXactTupleDescArrayLen
Definition: relcache.c:175
Relation reldesc
Definition: relcache.c:120
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
static HTAB * RelationIdCache
Definition: relcache.c:123
static void AtEOXact_cleanup(Relation relation, bool isCommit)
Definition: relcache.c:2987
static bool eoxact_list_overflowed
Definition: relcache.c:158
static int NextEOXactTupleDescNum
Definition: relcache.c:174
void pfree(void *pointer)
Definition: mcxt.c:949
#define Assert(condition)
Definition: c.h:681
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1385
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1375
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:251
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
static int eoxact_list_len
Definition: relcache.c:157
static TupleDesc * EOXactTupleDescArray
Definition: relcache.c:173
static void AttrDefaultFetch ( Relation  relation)
static

Definition at line 4026 of file relcache.c.

References AccessShareLock, attrDefault::adbin, attrDefault::adnum, Anum_pg_attrdef_adbin, Anum_pg_attrdef_adrelid, AttrDefaultIndexId, AttrDefaultRelationId, BTEqualStrategyNumber, CacheMemoryContext, tupleDesc::constr, tupleConstr::defval, elog, fastgetattr, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, i, MemoryContextStrdup(), NameStr, tupleConstr::num_defval, ObjectIdGetDatum, pfree(), RelationData::rd_att, RelationGetRelationName, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), TextDatumGetCString, TupleDescAttr, val, and WARNING.

Referenced by RelationBuildTupleDesc().

4027 {
4028  AttrDefault *attrdef = relation->rd_att->constr->defval;
4029  int ndef = relation->rd_att->constr->num_defval;
4030  Relation adrel;
4031  SysScanDesc adscan;
4032  ScanKeyData skey;
4033  HeapTuple htup;
4034  Datum val;
4035  bool isnull;
4036  int found;
4037  int i;
4038 
4039  ScanKeyInit(&skey,
4041  BTEqualStrategyNumber, F_OIDEQ,
4042  ObjectIdGetDatum(RelationGetRelid(relation)));
4043 
4045  adscan = systable_beginscan(adrel, AttrDefaultIndexId, true,
4046  NULL, 1, &skey);
4047  found = 0;
4048 
4049  while (HeapTupleIsValid(htup = systable_getnext(adscan)))
4050  {
4051  Form_pg_attrdef adform = (Form_pg_attrdef) GETSTRUCT(htup);
4052  Form_pg_attribute attr = TupleDescAttr(relation->rd_att, adform->adnum - 1);
4053 
4054  for (i = 0; i < ndef; i++)
4055  {
4056  if (adform->adnum != attrdef[i].adnum)
4057  continue;
4058  if (attrdef[i].adbin != NULL)
4059  elog(WARNING, "multiple attrdef records found for attr %s of rel %s",
4060  NameStr(attr->attname),
4061  RelationGetRelationName(relation));
4062  else
4063  found++;
4064 
4065  val = fastgetattr(htup,
4067  adrel->rd_att, &isnull);
4068  if (isnull)
4069  elog(WARNING, "null adbin for attr %s of rel %s",
4070  NameStr(attr->attname),
4071  RelationGetRelationName(relation));
4072  else
4073  {
4074  /* detoast and convert to cstring in caller's context */
4075  char *s = TextDatumGetCString(val);
4076 
4078  pfree(s);
4079  }
4080  break;
4081  }
4082 
4083  if (i >= ndef)
4084  elog(WARNING, "unexpected attrdef record found for attr %d of rel %s",
4085  adform->adnum, RelationGetRelationName(relation));
4086  }
4087 
4088  systable_endscan(adscan);
4089  heap_close(adrel, AccessShareLock);
4090 
4091  if (found != ndef)
4092  elog(WARNING, "%d attrdef record(s) missing for rel %s",
4093  ndef - found, RelationGetRelationName(relation));
4094 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:719
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
#define AccessShareLock
Definition: lockdefs.h:36
#define Anum_pg_attrdef_adbin
Definition: pg_attrdef.h:56
#define heap_close(r, l)
Definition: heapam.h:97
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
void pfree(void *pointer)
Definition: mcxt.c:949
AttrDefault * defval
Definition: tupdesc.h:39
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define AttrDefaultIndexId
Definition: indexing.h:87
AttrNumber adnum
Definition: tupdesc.h:24
#define RelationGetRelationName(relation)
Definition: rel.h:436
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
char * adbin
Definition: tupdesc.h:25
FormData_pg_attrdef * Form_pg_attrdef
Definition: pg_attrdef.h:47
#define WARNING
Definition: elog.h:40
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
TupleDesc rd_att
Definition: rel.h:115
#define Anum_pg_attrdef_adrelid
Definition: pg_attrdef.h:54
uint16 num_defval
Definition: tupdesc.h:41
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
TupleConstr * constr
Definition: tupdesc.h:78
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1063
int i
#define NameStr(name)
Definition: c.h:493
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
#define AttrDefaultRelationId
Definition: pg_attrdef.h:29
#define RelationGetRelid(relation)
Definition: rel.h:416
long val
Definition: informix.c:689
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static TupleDesc BuildHardcodedDescriptor ( int  natts,
const FormData_pg_attribute attrs,
bool  hasoids 
)
static

Definition at line 3964 of file relcache.c.

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

Referenced by GetPgClassDescriptor(), and GetPgIndexDescriptor().

3966 {
3967  TupleDesc result;
3968  MemoryContext oldcxt;
3969  int i;
3970 
3972 
3973  result = CreateTemplateTupleDesc(natts, hasoids);
3974  result->tdtypeid = RECORDOID; /* not right, but we don't care */
3975  result->tdtypmod = -1;
3976 
3977  for (i = 0; i < natts; i++)
3978  {
3979  memcpy(TupleDescAttr(result, i), &attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
3980  /* make sure attcacheoff is valid */
3981  TupleDescAttr(result, i)->attcacheoff = -1;
3982  }
3983 
3984  /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
3985  TupleDescAttr(result, 0)->attcacheoff = 0;
3986 
3987  /* Note: we don't bother to set up a TupleConstr entry */
3988 
3989  MemoryContextSwitchTo(oldcxt);
3990 
3991  return result;
3992 }
Oid tdtypeid
Definition: tupdesc.h:74
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int32 tdtypmod
Definition: tupdesc.h:75
#define RECORDOID
Definition: pg_type.h:680
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:179
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:43
int i
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static int CheckConstraintCmp ( const void *  a,
const void *  b 
)
static

Definition at line 4171 of file relcache.c.

References constrCheck::ccname.

Referenced by CheckConstraintFetch().

4172 {
4173  const ConstrCheck *ca = (const ConstrCheck *) a;
4174  const ConstrCheck *cb = (const ConstrCheck *) b;
4175 
4176  return strcmp(ca->ccname, cb->ccname);
4177 }
char * ccname
Definition: tupdesc.h:30
static void CheckConstraintFetch ( Relation  relation)
static

Definition at line 4100 of file relcache.c.

References AccessShareLock, Anum_pg_constraint_conbin, Anum_pg_constraint_conrelid, BTEqualStrategyNumber, CacheMemoryContext, constrCheck::ccbin, constrCheck::ccname, constrCheck::ccnoinherit, constrCheck::ccvalid, tupleConstr::check, CheckConstraintCmp(), tupleDesc::constr, CONSTRAINT_CHECK, ConstraintRelationId, ConstraintRelidIndexId, elog, ERROR, fastgetattr, GETSTRUCT, heap_close, heap_open(), HeapTupleIsValid, MemoryContextStrdup(), NameStr, tupleConstr::num_check, ObjectIdGetDatum, pfree(), qsort, RelationData::rd_att, RelationGetRelationName, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), TextDatumGetCString, and val.

Referenced by RelationBuildTupleDesc().

4101 {
4102  ConstrCheck *check = relation->rd_att->constr->check;
4103  int ncheck = relation->rd_att->constr->num_check;
4104  Relation conrel;
4105  SysScanDesc conscan;
4106  ScanKeyData skey[1];
4107  HeapTuple htup;
4108  int found = 0;
4109 
4110  ScanKeyInit(&skey[0],
4112  BTEqualStrategyNumber, F_OIDEQ,
4113  ObjectIdGetDatum(RelationGetRelid(relation)));
4114 
4116  conscan = systable_beginscan(conrel, ConstraintRelidIndexId, true,
4117  NULL, 1, skey);
4118 
4119  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4120  {
4122  Datum val;
4123  bool isnull;
4124  char *s;
4125 
4126  /* We want check constraints only */
4127  if (conform->contype != CONSTRAINT_CHECK)
4128  continue;
4129 
4130  if (found >= ncheck)
4131  elog(ERROR, "unexpected constraint record found for rel %s",
4132  RelationGetRelationName(relation));
4133 
4134  check[found].ccvalid = conform->convalidated;
4135  check[found].ccnoinherit = conform->connoinherit;
4137  NameStr(conform->conname));
4138 
4139  /* Grab and test conbin is actually set */
4140  val = fastgetattr(htup,
4142  conrel->rd_att, &isnull);
4143  if (isnull)
4144  elog(ERROR, "null conbin for rel %s",
4145  RelationGetRelationName(relation));
4146 
4147  /* detoast and convert to cstring in caller's context */
4148  s = TextDatumGetCString(val);
4149  check[found].ccbin = MemoryContextStrdup(CacheMemoryContext, s);
4150  pfree(s);
4151 
4152  found++;
4153  }
4154 
4155  systable_endscan(conscan);
4156  heap_close(conrel, AccessShareLock);
4157 
4158  if (found != ncheck)
4159  elog(ERROR, "%d constraint record(s) missing for rel %s",
4160  ncheck - found, RelationGetRelationName(relation));
4161 
4162  /* Sort the records so that CHECKs are applied in a deterministic order */
4163  if (ncheck > 1)
4164  qsort(check, ncheck, sizeof(ConstrCheck), CheckConstraintCmp);
4165 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:719
char * ccname
Definition: tupdesc.h:30
bool ccnoinherit
Definition: tupdesc.h:33
ConstrCheck * check
Definition: tupdesc.h:40
char * ccbin
Definition: tupdesc.h:31
static int CheckConstraintCmp(const void *a, const void *b)
Definition: relcache.c:4171
#define AccessShareLock
Definition: lockdefs.h:36
#define heap_close(r, l)
Definition: heapam.h:97
#define Anum_pg_constraint_conbin
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
#define CONSTRAINT_CHECK
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
void pfree(void *pointer)
Definition: mcxt.c:949
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:436
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
TupleDesc rd_att
Definition: rel.h:115
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
TupleConstr * constr
Definition: tupdesc.h:78
bool ccvalid
Definition: tupdesc.h:32
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1063
#define NameStr(name)
Definition: c.h:493
#define Anum_pg_constraint_conrelid
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
uint16 num_check
Definition: tupdesc.h:42
#define ConstraintRelationId
Definition: pg_constraint.h:29
#define elog
Definition: elog.h:219
#define qsort(a, b, c, d)
Definition: port.h:447
#define RelationGetRelid(relation)
Definition: rel.h:416
long val
Definition: informix.c:689
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define ConstraintRelidIndexId
Definition: indexing.h:126
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static PartitionKey copy_partition_key ( PartitionKey  fromkey)
static

Definition at line 999 of file relcache.c.

References copyObject, palloc(), PartitionKeyData::partattrs, PartitionKeyData::partcollation, PartitionKeyData::partexprs, PartitionKeyData::partnatts, PartitionKeyData::partopcintype, PartitionKeyData::partopfamily, PartitionKeyData::partsupfunc, PartitionKeyData::parttypalign, PartitionKeyData::parttypbyval, PartitionKeyData::parttypcoll, PartitionKeyData::parttypid, PartitionKeyData::parttyplen, PartitionKeyData::parttypmod, and PartitionKeyData::strategy.

Referenced by RelationBuildPartitionKey().

1000 {
1001  PartitionKey newkey;
1002  int n;
1003 
1004  newkey = (PartitionKey) palloc(sizeof(PartitionKeyData));
1005 
1006  newkey->strategy = fromkey->strategy;
1007  newkey->partnatts = n = fromkey->partnatts;
1008 
1009  newkey->partattrs = (AttrNumber *) palloc(n * sizeof(AttrNumber));
1010  memcpy(newkey->partattrs, fromkey->partattrs, n * sizeof(AttrNumber));
1011 
1012  newkey->partexprs = copyObject(fromkey->partexprs);
1013 
1014  newkey->partopfamily = (Oid *) palloc(n * sizeof(Oid));
1015  memcpy(newkey->partopfamily, fromkey->partopfamily, n * sizeof(Oid));
1016 
1017  newkey->partopcintype = (Oid *) palloc(n * sizeof(Oid));
1018  memcpy(newkey->partopcintype, fromkey->partopcintype, n * sizeof(Oid));
1019 
1020  newkey->partsupfunc = (FmgrInfo *) palloc(n * sizeof(FmgrInfo));
1021  memcpy(newkey->partsupfunc, fromkey->partsupfunc, n * sizeof(FmgrInfo));
1022 
1023  newkey->partcollation = (Oid *) palloc(n * sizeof(Oid));
1024  memcpy(newkey->partcollation, fromkey->partcollation, n * sizeof(Oid));
1025 
1026  newkey->parttypid = (Oid *) palloc(n * sizeof(Oid));
1027  memcpy(newkey->parttypid, fromkey->parttypid, n * sizeof(Oid));
1028 
1029  newkey->parttypmod = (int32 *) palloc(n * sizeof(int32));
1030  memcpy(newkey->parttypmod, fromkey->parttypmod, n * sizeof(int32));
1031 
1032  newkey->parttyplen = (int16 *) palloc(n * sizeof(int16));
1033  memcpy(newkey->parttyplen, fromkey->parttyplen, n * sizeof(int16));
1034 
1035  newkey->parttypbyval = (bool *) palloc(n * sizeof(bool));
1036  memcpy(newkey->parttypbyval, fromkey->parttypbyval, n * sizeof(bool));
1037 
1038  newkey->parttypalign = (char *) palloc(n * sizeof(bool));
1039  memcpy(newkey->parttypalign, fromkey->parttypalign, n * sizeof(char));
1040 
1041  newkey->parttypcoll = (Oid *) palloc(n * sizeof(Oid));
1042  memcpy(newkey->parttypcoll, fromkey->parttypcoll, n * sizeof(Oid));
1043 
1044  return newkey;
1045 }
signed short int16
Definition: c.h:245
Definition: fmgr.h:56
Oid * partopfamily
Definition: rel.h:61
FmgrInfo * partsupfunc
Definition: rel.h:63
List * partexprs
Definition: rel.h:58
char strategy
Definition: rel.h:54
unsigned int Oid
Definition: postgres_ext.h:31
signed int int32
Definition: c.h:246
Oid * parttypcoll
Definition: rel.h:74
Oid * parttypid
Definition: rel.h:69
Oid * partcollation
Definition: rel.h:66
AttrNumber * partattrs
Definition: rel.h:56
int16 partnatts
Definition: rel.h:55
char * parttypalign
Definition: rel.h:73
int32 * parttypmod
Definition: rel.h:70
bool * parttypbyval
Definition: rel.h:72
int16 * parttyplen
Definition: rel.h:71
void * palloc(Size size)
Definition: mcxt.c:848
struct PartitionKeyData * PartitionKey
Definition: rel.h:77
Oid * partopcintype
Definition: rel.h:62
#define copyObject(obj)
Definition: nodes.h:623
int16 AttrNumber
Definition: attnum.h:21
static bool equalPartitionDescs ( PartitionKey  key,
PartitionDesc  partdesc1,
PartitionDesc  partdesc2 
)
static

Definition at line 1179 of file relcache.c.

References Assert, PartitionDescData::boundinfo, i, PartitionDescData::nparts, PartitionDescData::oids, partition_bounds_equal(), PartitionKeyData::partnatts, PartitionKeyData::parttypbyval, and PartitionKeyData::parttyplen.

Referenced by RelationClearRelation().

1181 {
1182  int i;
1183 
1184  if (partdesc1 != NULL)
1185  {
1186  if (partdesc2 == NULL)
1187  return false;
1188  if (partdesc1->nparts != partdesc2->nparts)
1189  return false;
1190 
1191  Assert(key != NULL || partdesc1->nparts == 0);
1192 
1193  /*
1194  * Same oids? If the partitioning structure did not change, that is,
1195  * no partitions were added or removed to the relation, the oids array
1196  * should still match element-by-element.
1197  */
1198  for (i = 0; i < partdesc1->nparts; i++)
1199  {
1200  if (partdesc1->oids[i] != partdesc2->oids[i])
1201  return false;
1202  }
1203 
1204  /*
1205  * Now compare partition bound collections. The logic to iterate over
1206  * the collections is private to partition.c.
1207  */
1208  if (partdesc1->boundinfo != NULL)
1209  {
1210  if (partdesc2->boundinfo == NULL)
1211  return false;
1212 
1214  key->parttypbyval,
1215  partdesc1->boundinfo,
1216  partdesc2->boundinfo))
1217  return false;
1218  }
1219  else if (partdesc2->boundinfo != NULL)
1220  return false;
1221  }
1222  else if (partdesc2 != NULL)
1223  return false;
1224 
1225  return true;
1226 }
bool partition_bounds_equal(int partnatts, int16 *parttyplen, bool *parttypbyval, PartitionBoundInfo b1, PartitionBoundInfo b2)
Definition: partition.c:641
PartitionBoundInfo boundinfo
Definition: partition.h:37
int16 partnatts
Definition: rel.h:55
bool * parttypbyval
Definition: rel.h:72
#define Assert(condition)
Definition: c.h:681
int16 * parttyplen
Definition: rel.h:71
int i
static bool equalPolicy ( RowSecurityPolicy policy1,
RowSecurityPolicy policy2 
)
static

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

1101 {
1102  int i;
1103  Oid *r1,
1104  *r2;
1105 
1106  if (policy1 != NULL)
1107  {
1108  if (policy2 == NULL)
1109  return false;
1110 
1111  if (policy1->polcmd != policy2->polcmd)
1112  return false;
1113  if (policy1->hassublinks != policy2->hassublinks)
1114  return false;
1115  if (strcmp(policy1->policy_name, policy2->policy_name) != 0)
1116  return false;
1117  if (ARR_DIMS(policy1->roles)[0] != ARR_DIMS(policy2->roles)[0])
1118  return false;
1119 
1120  r1 = (Oid *) ARR_DATA_PTR(policy1->roles);
1121  r2 = (Oid *) ARR_DATA_PTR(policy2->roles);
1122 
1123  for (i = 0; i < ARR_DIMS(policy1->roles)[0]; i++)
1124  {
1125  if (r1[i] != r2[i])
1126  return false;
1127  }
1128 
1129  if (!equal(policy1->qual, policy2->qual))
1130  return false;
1131  if (!equal(policy1->with_check_qual, policy2->with_check_qual))
1132  return false;
1133  }
1134  else if (policy2 != NULL)
1135  return false;
1136 
1137  return true;
1138 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2972
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_DIMS(a)
Definition: array.h:279
#define ARR_DATA_PTR(a)
Definition: array.h:307
Expr * with_check_qual
Definition: rowsecurity.h:27
ArrayType * roles
Definition: rowsecurity.h:24
int i
static bool equalRSDesc ( RowSecurityDesc rsdesc1,
RowSecurityDesc rsdesc2 
)
static

Definition at line 1146 of file relcache.c.

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

Referenced by RelationClearRelation().

1147 {
1148  ListCell *lc,
1149  *rc;
1150 
1151  if (rsdesc1 == NULL && rsdesc2 == NULL)
1152  return true;
1153 
1154  if ((rsdesc1 != NULL && rsdesc2 == NULL) ||
1155  (rsdesc1 == NULL && rsdesc2 != NULL))
1156  return false;
1157 
1158  if (list_length(rsdesc1->policies) != list_length(rsdesc2->policies))
1159  return false;
1160 
1161  /* RelationBuildRowSecurity should build policies in order */
1162  forboth(lc, rsdesc1->policies, rc, rsdesc2->policies)
1163  {
1166 
1167  if (!equalPolicy(l, r))
1168  return false;
1169  }
1170 
1171  return true;
1172 }
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:180
static bool equalPolicy(RowSecurityPolicy *policy1, RowSecurityPolicy *policy2)
Definition: relcache.c:1100
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
static bool equalRuleLocks ( RuleLock rlock1,
RuleLock rlock2 
)
static

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

1056 {
1057  int i;
1058 
1059  /*
1060  * As of 7.3 we assume the rule ordering is repeatable, because
1061  * RelationBuildRuleLock should read 'em in a consistent order. So just
1062  * compare corresponding slots.
1063  */
1064  if (rlock1 != NULL)
1065  {
1066  if (rlock2 == NULL)
1067  return false;
1068  if (rlock1->numLocks != rlock2->numLocks)
1069  return false;
1070  for (i = 0; i < rlock1->numLocks; i++)
1071  {
1072  RewriteRule *rule1 = rlock1->rules[i];
1073  RewriteRule *rule2 = rlock2->rules[i];
1074 
1075  if (rule1->ruleId != rule2->ruleId)
1076  return false;
1077  if (rule1->event != rule2->event)
1078  return false;
1079  if (rule1->enabled != rule2->enabled)
1080  return false;
1081  if (rule1->isInstead != rule2->isInstead)
1082  return false;
1083  if (!equal(rule1->qual, rule2->qual))
1084  return false;
1085  if (!equal(rule1->actions, rule2->actions))
1086  return false;
1087  }
1088  }
1089  else if (rlock2 != NULL)
1090  return false;
1091  return true;
1092 }
Node * qual
Definition: prs2lock.h:28
int numLocks
Definition: prs2lock.h:42
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2972
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
int errtable ( Relation  rel)

Definition at line 5255 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(), BuildRelationExtStatistics(), errtablecolname(), and errtableconstraint().

5256 {
5260 
5261  return 0; /* return value does not matter */
5262 }
#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:3033
#define RelationGetRelationName(relation)
Definition: rel.h:436
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
#define RelationGetNamespace(relation)
Definition: rel.h:443
int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5272 of file relcache.c.

References errtablecolname(), get_relid_attribute_name(), NameStr, RelationGetDescr, RelationGetRelid, and TupleDescAttr.

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

5273 {
5274  TupleDesc reldesc = RelationGetDescr(rel);
5275  const char *colname;
5276 
5277  /* Use reldesc if it's a user attribute, else consult the catalogs */
5278  if (attnum > 0 && attnum <= reldesc->natts)
5279  colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
5280  else
5281  colname = get_relid_attribute_name(RelationGetRelid(rel), attnum);
5282 
5283  return errtablecolname(rel, colname);
5284 }
#define RelationGetDescr(relation)
Definition: rel.h:428
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
char * get_relid_attribute_name(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:801
#define NameStr(name)
Definition: c.h:493
#define RelationGetRelid(relation)
Definition: rel.h:416
int errtablecolname(Relation rel, const char *colname)
Definition: relcache.c:5296
int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5296 of file relcache.c.

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

Referenced by errtablecol().

5297 {
5298  errtable(rel);
5300 
5301  return 0; /* return value does not matter */
5302 }
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:67
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
int errtable(Relation rel)
Definition: relcache.c:5255
int errtableconstraint ( Relation  rel,
const char *  conname 
)

Definition at line 5309 of file relcache.c.

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

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

5310 {
5311  errtable(rel);
5313 
5314  return 0; /* return value does not matter */
5315 }
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:69
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
int errtable(Relation rel)
Definition: relcache.c:5255
static void formrdesc ( const char *  relationName,
Oid  relationReltype,
bool  isshared,
bool  hasoids,
int  natts,
const FormData_pg_attribute attrs 
)
static

Definition at line 1895 of file relcache.c.

References ATTRIBUTE_FIXED_PART_SIZE, CLASS_TUPLE_SIZE, tupleDesc::constr, CreateTemplateTupleDesc(), GLOBALTABLESPACE_OID, tupleConstr::has_not_null, i, InvalidBackendId, InvalidOid, InvalidSubTransactionId, IsBootstrapProcessingMode, namestrcpy(), palloc0(), PG_CATALOG_NAMESPACE, RelationData::rd_att, RelationData::rd_backend, RelationData::rd_createSubid, RelationData::rd_islocaltemp, RelationData::rd_isnailed, RelationData::rd_isvalid, RelationData::rd_newRelfilenodeSubid, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_smgr, RelationCacheInsert, RelationGetRelid, RelationInitLockInfo(), RelationInitPhysicalAddr(), RelationMapUpdateMap(), RELKIND_RELATION, RELPERSISTENCE_PERMANENT, REPLICA_IDENTITY_NOTHING, tupleDesc::tdrefcount, tupleDesc::tdtypeid, tupleDesc::tdtypmod, and TupleDescAttr.

Referenced by RelationCacheInitializePhase2(), and RelationCacheInitializePhase3().

1898 {
1899  Relation relation;
1900  int i;
1901  bool has_not_null;
1902 
1903  /*
1904  * allocate new relation desc, clear all fields of reldesc
1905  */
1906  relation = (Relation) palloc0(sizeof(RelationData));
1907 
1908  /* make sure relation is marked as having no open file yet */
1909  relation->rd_smgr = NULL;
1910 
1911  /*
1912  * initialize reference count: 1 because it is nailed in cache
1913  */
1914  relation->rd_refcnt = 1;
1915 
1916  /*
1917  * all entries built with this routine are nailed-in-cache; none are for
1918  * new or temp relations.
1919  */
1920  relation->rd_isnailed = true;
1923  relation->rd_backend = InvalidBackendId;
1924  relation->rd_islocaltemp = false;
1925 
1926  /*
1927  * initialize relation tuple form
1928  *
1929  * The data we insert here is pretty incomplete/bogus, but it'll serve to
1930  * get us launched. RelationCacheInitializePhase3() will read the real
1931  * data from pg_class and replace what we've done here. Note in
1932  * particular that relowner is left as zero; this cues
1933  * RelationCacheInitializePhase3 that the real data isn't there yet.
1934  */
1936 
1937  namestrcpy(&relation->rd_rel->relname, relationName);
1938  relation->rd_rel->relnamespace = PG_CATALOG_NAMESPACE;
1939  relation->rd_rel->reltype = relationReltype;
1940 
1941  /*
1942  * It's important to distinguish between shared and non-shared relations,
1943  * even at bootstrap time, to make sure we know where they are stored.
1944  */
1945  relation->rd_rel->relisshared = isshared;
1946  if (isshared)
1947  relation->rd_rel->reltablespace = GLOBALTABLESPACE_OID;
1948 
1949  /* formrdesc is used only for permanent relations */
1950  relation->rd_rel->relpersistence = RELPERSISTENCE_PERMANENT;
1951 
1952  /* ... and they're always populated, too */
1953  relation->rd_rel->relispopulated = true;
1954 
1955  relation->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
1956  relation->rd_rel->relpages = 0;
1957  relation->rd_rel->reltuples = 0;
1958  relation->rd_rel->relallvisible = 0;
1959  relation->rd_rel->relkind = RELKIND_RELATION;
1960  relation->rd_rel->relhasoids = hasoids;
1961  relation->rd_rel->relnatts = (int16) natts;
1962 
1963  /*
1964  * initialize attribute tuple form
1965  *
1966  * Unlike the case with the relation tuple, this data had better be right
1967  * because it will never be replaced. The data comes from
1968  * src/include/catalog/ headers via genbki.pl.
1969  */
1970  relation->rd_att = CreateTemplateTupleDesc(natts, hasoids);
1971  relation->rd_att->tdrefcount = 1; /* mark as refcounted */
1972 
1973  relation->rd_att->tdtypeid = relationReltype;
1974  relation->rd_att->tdtypmod = -1; /* unnecessary, but... */
1975 
1976  /*
1977  * initialize tuple desc info
1978  */
1979  has_not_null = false;
1980  for (i = 0; i < natts; i++)
1981  {
1982  memcpy(TupleDescAttr(relation->rd_att, i),
1983  &attrs[i],
1985  has_not_null |= attrs[i].attnotnull;
1986  /* make sure attcacheoff is valid */
1987  TupleDescAttr(relation->rd_att, i)->attcacheoff = -1;
1988  }
1989 
1990  /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
1991  TupleDescAttr(relation->rd_att, 0)->attcacheoff = 0;
1992 
1993  /* mark not-null status */
1994  if (has_not_null)
1995  {
1996  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
1997 
1998  constr->has_not_null = true;
1999  relation->rd_att->constr = constr;
2000  }
2001 
2002  /*
2003  * initialize relation id from info in att array (my, this is ugly)
2004  */
2005  RelationGetRelid(relation) = TupleDescAttr(relation->rd_att, 0)->attrelid;
2006 
2007  /*
2008  * All relations made with formrdesc are mapped. This is necessarily so
2009  * because there is no other way to know what filenode they currently
2010  * have. In bootstrap mode, add them to the initial relation mapper data,
2011  * specifying that the initial filenode is the same as the OID.
2012  */
2013  relation->rd_rel->relfilenode = InvalidOid;
2016  RelationGetRelid(relation),
2017  isshared, true);
2018 
2019  /*
2020  * initialize the relation lock manager information
2021  */
2022  RelationInitLockInfo(relation); /* see lmgr.c */
2023 
2024  /*
2025  * initialize physical addressing information for the relation
2026  */
2027  RelationInitPhysicalAddr(relation);
2028 
2029  /*
2030  * initialize the rel-has-index flag, using hardwired knowledge
2031  */
2033  {
2034  /* In bootstrap mode, we have no indexes */
2035  relation->rd_rel->relhasindex = false;
2036  }
2037  else
2038  {
2039  /* Otherwise, all the rels formrdesc is used for have indexes */
2040  relation->rd_rel->relhasindex = true;
2041  }
2042 
2043  /*
2044  * add new reldesc to relcache
2045  */
2046  RelationCacheInsert(relation, false);
2047 
2048  /* It's fully valid */
2049  relation->rd_isvalid = true;
2050 }
signed short int16
Definition: c.h:245
Oid tdtypeid
Definition: tupdesc.h:74
#define REPLICA_IDENTITY_NOTHING
Definition: pg_class.h:177
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
bool rd_isnailed
Definition: rel.h:91
bool rd_islocaltemp
Definition: rel.h:90
#define GLOBALTABLESPACE_OID
Definition: pg_tablespace.h:64
bool rd_isvalid
Definition: rel.h:92
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:111
Form_pg_class rd_rel
Definition: rel.h:114
int namestrcpy(Name name, const char *str)
Definition: name.c:216
int32 tdtypmod
Definition: tupdesc.h:75
#define RELPERSISTENCE_PERMANENT
Definition: pg_class.h:170
struct RelationData * Relation
Definition: relcache.h:21
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1426
void RelationInitLockInfo(Relation relation)
Definition: lmgr.c:68
#define PG_CATALOG_NAMESPACE
Definition: pg_namespace.h:71
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:179
bool has_not_null
Definition: tupdesc.h:43
SubTransactionId rd_createSubid
Definition: rel.h:110
#define InvalidBackendId
Definition: backendid.h:23
void * palloc0(Size size)
Definition: mcxt.c:877
TupleDesc rd_att
Definition: rel.h:115
#define InvalidOid
Definition: postgres_ext.h:36
#define RelationCacheInsert(RELATION, replace_allowed)
Definition: relcache.c:180
#define CLASS_TUPLE_SIZE
Definition: pg_class.h:87
BackendId rd_backend
Definition: rel.h:89
TupleConstr * constr
Definition: tupdesc.h:78
#define InvalidSubTransactionId
Definition: c.h:397
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:43
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:367
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
int rd_refcnt
Definition: rel.h:88
int tdrefcount
Definition: tupdesc.h:77
int i
#define RELKIND_RELATION
Definition: pg_class.h:160
#define RelationGetRelid(relation)
Definition: rel.h:416
void RelationMapUpdateMap(Oid relationId, Oid fileNode, bool shared, bool immediate)
Definition: relmapper.c:248
static TupleDesc GetPgClassDescriptor ( void  )
static

Definition at line 3995 of file relcache.c.

References BuildHardcodedDescriptor(), Desc_pg_class, and Natts_pg_class.

Referenced by RelationParseRelOptions().

3996 {
3997  static TupleDesc pgclassdesc = NULL;
3998 
3999  /* Already done? */
4000  if (pgclassdesc == NULL)
4002  Desc_pg_class,
4003  true);
4004 
4005  return pgclassdesc;
4006 }
#define Natts_pg_class
Definition: pg_class.h:102
static TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs, bool hasoids)
Definition: relcache.c:3964
static const FormData_pg_attribute Desc_pg_class[Natts_pg_class]
Definition: relcache.c:100
static TupleDesc GetPgIndexDescriptor ( void  )
static

Definition at line 4009 of file relcache.c.

References BuildHardcodedDescriptor(), Desc_pg_index, and Natts_pg_index.

Referenced by RelationGetIndexExpressions(), RelationGetIndexList(), RelationGetIndexPredicate(), and RelationInitIndexAccessInfo().

4010 {
4011  static TupleDesc pgindexdesc = NULL;
4012 
4013  /* Already done? */
4014  if (pgindexdesc == NULL)
4016  Desc_pg_index,
4017  false);
4018 
4019  return pgindexdesc;
4020 }
static TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs, bool hasoids)
Definition: relcache.c:3964
static const FormData_pg_attribute Desc_pg_index[Natts_pg_index]
Definition: relcache.c:107
#define Natts_pg_index
Definition: pg_index.h:73
struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

Definition at line 5184 of file relcache.c.

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

Referenced by CheckCmdReplicaIdentity().

5185 {
5186  List *puboids;
5187  ListCell *lc;
5188  MemoryContext oldcxt;
5189  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5190 
5191  if (relation->rd_pubactions)
5192  return memcpy(pubactions, relation->rd_pubactions,
5193  sizeof(PublicationActions));
5194 
5195  /* Fetch the publication membership info. */
5196  puboids = GetRelationPublications(RelationGetRelid(relation));
5197  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5198 
5199  foreach(lc, puboids)
5200  {
5201  Oid pubid = lfirst_oid(lc);
5202  HeapTuple tup;
5203  Form_pg_publication pubform;
5204 
5206 
5207  if (!HeapTupleIsValid(tup))
5208  elog(ERROR, "cache lookup failed for publication %u", pubid);
5209 
5210  pubform = (Form_pg_publication) GETSTRUCT(tup);
5211 
5212  pubactions->pubinsert |= pubform->pubinsert;
5213  pubactions->pubupdate |= pubform->pubupdate;
5214  pubactions->pubdelete |= pubform->pubdelete;
5215 
5216  ReleaseSysCache(tup);
5217 
5218  /*
5219  * If we know everything is replicated, there is no point to check for
5220  * other publications.
5221  */
5222  if (pubactions->pubinsert && pubactions->pubupdate &&
5223  pubactions->pubdelete)
5224  break;
5225  }
5226 
5227  if (relation->rd_pubactions)
5228  {
5229  pfree(relation->rd_pubactions);
5230  relation->rd_pubactions = NULL;
5231  }
5232 
5233  /* Now save copy of the actions in the relcache entry. */
5235  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5236  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5237  MemoryContextSwitchTo(oldcxt);
5238 
5239  return pubactions;
5240 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
PublicationActions * rd_pubactions
Definition: rel.h:149
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned int Oid
Definition: postgres_ext.h:31
List * list_concat_unique_oid(List *list1, List *list2)
Definition: list.c:1082
List * GetRelationPublications(Oid relid)
void pfree(void *pointer)
Definition: mcxt.c:949
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void * palloc0(Size size)
Definition: mcxt.c:877
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
List * GetAllTablesPublications(void)
void * palloc(Size size)
Definition: mcxt.c:848
#define elog
Definition: elog.h:219
FormData_pg_publication * Form_pg_publication
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:416
#define lfirst_oid(lc)
Definition: pg_list.h:108
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static void IndexSupportInitialize ( oidvector indclass,
RegProcedure indexSupport,
Oid opFamily,
Oid opcInType,
StrategyNumber  maxSupportNumber,
AttrNumber  maxAttributeNumber 
)
static

Definition at line 1676 of file relcache.c.

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

Referenced by RelationInitIndexAccessInfo().

1682 {
1683  int attIndex;
1684 
1685  for (attIndex = 0; attIndex < maxAttributeNumber; attIndex++)
1686  {
1687  OpClassCacheEnt *opcentry;
1688 
1689  if (!OidIsValid(indclass->values[attIndex]))
1690  elog(ERROR, "bogus pg_index tuple");
1691 
1692  /* look up the info for this opclass, using a cache */
1693  opcentry = LookupOpclassInfo(indclass->values[attIndex],
1694  maxSupportNumber);
1695 
1696  /* copy cached data into relcache entry */
1697  opFamily[attIndex] = opcentry->opcfamily;
1698  opcInType[attIndex] = opcentry->opcintype;
1699  if (maxSupportNumber > 0)
1700  memcpy(&indexSupport[attIndex * maxSupportNumber],
1701  opcentry->supportProcs,
1702  maxSupportNumber * sizeof(RegProcedure));
1703  }
1704 }
regproc RegProcedure
Definition: c.h:389
#define OidIsValid(objectId)
Definition: c.h:532
#define ERROR
Definition: elog.h:43
RegProcedure * supportProcs
Definition: relcache.c:239
static OpClassCacheEnt * LookupOpclassInfo(Oid operatorClassOid, StrategyNumber numSupport)
Definition: relcache.c:1727
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:480
#define elog
Definition: elog.h:219
static void InitIndexAmRoutine ( Relation  relation)
static

Definition at line 1489 of file relcache.c.

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

Referenced by load_relcache_init_file(), and RelationInitIndexAccessInfo().

1490 {
1491  IndexAmRoutine *cached,
1492  *tmp;
1493 
1494  /*
1495  * Call the amhandler in current, short-lived memory context, just in case
1496  * it leaks anything (it probably won't, but let's be paranoid).
1497  */
1498  tmp = GetIndexAmRoutine(relation->rd_amhandler);
1499 
1500  /* OK, now transfer the data into relation's rd_indexcxt. */
1501  cached = (IndexAmRoutine *) MemoryContextAlloc(relation->rd_indexcxt,
1502  sizeof(IndexAmRoutine));
1503  memcpy(cached, tmp, sizeof(IndexAmRoutine));
1504  relation->rd_amroutine = cached;
1505 
1506  pfree(tmp);
1507 }
struct IndexAmRoutine * rd_amroutine
Definition: rel.h:181
void pfree(void *pointer)
Definition: mcxt.c:949
Oid rd_amhandler
Definition: rel.h:178
IndexAmRoutine * GetIndexAmRoutine(Oid amhandler)
Definition: amapi.c:33
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:706
MemoryContext rd_indexcxt
Definition: rel.h:179
static List * insert_ordered_oid ( List list,
Oid  datum 
)
static

Definition at line 4563 of file relcache.c.

References lappend_cell_oid(), lcons_oid(), lfirst_oid, linitial_oid, sort-test::list, list_head(), lnext, and NIL.

Referenced by RelationGetIndexList(), and RelationGetStatExtList().

4564 {
4565  ListCell *prev;
4566 
4567  /* Does the datum belong at the front? */
4568  if (list == NIL || datum < linitial_oid(list))
4569  return lcons_oid(datum, list);
4570  /* No, so find the entry it belongs after */
4571  prev = list_head(list);
4572  for (;;)
4573  {
4574  ListCell *curr = lnext(prev);
4575 
4576  if (curr == NULL || datum < lfirst_oid(curr))
4577  break; /* it belongs after 'prev', before 'curr' */
4578 
4579  prev = curr;
4580  }
4581  /* Insert datum into list after 'prev' */
4582  lappend_cell_oid(list, prev, datum);
4583  return list;
4584 }
#define NIL
Definition: pg_list.h:69
List * lcons_oid(Oid datum, List *list)
Definition: list.c:295
ListCell * lappend_cell_oid(List *list, ListCell *prev, Oid datum)
Definition: list.c:235
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
#define linitial_oid(l)
Definition: pg_list.h:113
tuple list
Definition: sort-test.py:11
#define lfirst_oid(lc)
Definition: pg_list.h:108
static void load_critical_index ( Oid  indexoid,
Oid  heapoid 
)
static

Definition at line 3930 of file relcache.c.

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

Referenced by RelationCacheInitializePhase3().

3931 {
3932  Relation ird;
3933 
3934  /*
3935  * We must lock the underlying catalog before locking the index to avoid
3936  * deadlock, since RelationBuildDesc might well need to read the catalog,
3937  * and if anyone else is exclusive-locking this catalog and index they'll
3938  * be doing it in that order.
3939  */
3940  LockRelationOid(heapoid, AccessShareLock);
3941  LockRelationOid(indexoid, AccessShareLock);
3942  ird = RelationBuildDesc(indexoid, true);
3943  if (ird == NULL)
3944  elog(PANIC, "could not open critical system index %u", indexoid);
3945  ird->rd_isnailed = true;
3946  ird->rd_refcnt = 1;
3949 }
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:182
bool rd_isnailed
Definition: rel.h:91
#define AccessShareLock
Definition: lockdefs.h:36
#define PANIC
Definition: elog.h:53
static Relation RelationBuildDesc(Oid targetRelId, bool insertIt)
Definition: relcache.c:1241
int rd_refcnt
Definition: rel.h:88
#define elog
Definition: elog.h:219
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105
static bool load_relcache_init_file ( bool  shared)
static

Definition at line 5373 of file relcache.c.

References AllocateFile(), ALLOCSET_SMALL_SIZES, AllocSetContextCreate(), IndexAmRoutine::amsupport, Assert, ATTRIBUTE_FIXED_PART_SIZE, CacheMemoryContext, tupleDesc::constr, CreateTemplateTupleDesc(), criticalRelcachesBuilt, criticalSharedRelcachesBuilt, DatabasePath, elog, FreeFile(), GETSTRUCT, tupleConstr::has_not_null, HEAPTUPLESIZE, i, InitIndexAmRoutine(), InvalidOid, InvalidSubTransactionId, MAXPGPATH, MemoryContextAlloc(), MemoryContextAllocZero(), 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_amroutine, RelationData::rd_att, RelationData::rd_createSubid, RelationData::rd_exclops, RelationData::rd_exclprocs, RelationData::rd_exclstrats, RelationData::rd_fdwroutine, RelationData::rd_fkeylist, RelationData::rd_fkeyvalid, RelationData::rd_idattr, 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_oidindex, RelationData::rd_opcintype, RelationData::rd_opfamily, RelationData::rd_options, RelationData::rd_partcheck, RelationData::rd_partdesc, RelationData::rd_partkey, RelationData::rd_partkeycxt, RelationData::rd_pdcxt, RelationData::rd_pkattr, RelationData::rd_pkindex, RelationData::rd_pubactions, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_replidindex, RelationData::rd_rsdesc, RelationData::rd_rules, RelationData::rd_rulescxt, RelationData::rd_smgr, RelationData::rd_statlist, RelationData::rd_statvalid, RelationData::rd_support, RelationData::rd_supportinfo, RelationCacheInsert, RelationGetRelationName, RelationInitLockInfo(), RelationInitPhysicalAddr(), RELCACHE_INIT_FILEMAGIC, RELCACHE_INIT_FILENAME, RELKIND_INDEX, repalloc(), snprintf(), HeapTupleData::t_data, tupleDesc::tdrefcount, tupleDesc::tdtypeid, tupleDesc::tdtypmod, RelationData::trigdesc, TupleDescAttr, VARSIZE, and WARNING.

Referenced by RelationCacheInitializePhase2(), and RelationCacheInitializePhase3().

5374 {
5375  FILE *fp;
5376  char initfilename[MAXPGPATH];
5377  Relation *rels;
5378  int relno,
5379  num_rels,
5380  max_rels,
5381  nailed_rels,
5382  nailed_indexes,
5383  magic;
5384  int i;
5385 
5386  if (shared)
5387  snprintf(initfilename, sizeof(initfilename), "global/%s",
5389  else
5390  snprintf(initfilename, sizeof(initfilename), "%s/%s",
5392 
5393  fp = AllocateFile(initfilename, PG_BINARY_R);
5394  if (fp == NULL)
5395  return false;
5396 
5397  /*
5398  * Read the index relcache entries from the file. Note we will not enter
5399  * any of them into the cache if the read fails partway through; this
5400  * helps to guard against broken init files.
5401  */
5402  max_rels = 100;
5403  rels = (Relation *) palloc(max_rels * sizeof(Relation));
5404  num_rels = 0;
5405  nailed_rels = nailed_indexes = 0;
5406 
5407  /* check for correct magic number (compatible version) */
5408  if (fread(&magic, 1, sizeof(magic), fp) != sizeof(magic))
5409  goto read_failed;
5410  if (magic != RELCACHE_INIT_FILEMAGIC)
5411  goto read_failed;
5412 
5413  for (relno = 0;; relno++)
5414  {
5415  Size len;
5416  size_t nread;
5417  Relation rel;
5418  Form_pg_class relform;
5419  bool has_not_null;
5420 
5421  /* first read the relation descriptor length */
5422  nread = fread(&len, 1, sizeof(len), fp);
5423  if (nread != sizeof(len))
5424  {
5425  if (nread == 0)
5426  break; /* end of file */
5427  goto read_failed;
5428  }
5429 
5430  /* safety check for incompatible relcache layout */
5431  if (len != sizeof(RelationData))
5432  goto read_failed;
5433 
5434  /* allocate another relcache header */
5435  if (num_rels >= max_rels)
5436  {
5437  max_rels *= 2;
5438  rels = (Relation *) repalloc(rels, max_rels * sizeof(Relation));
5439  }
5440 
5441  rel = rels[num_rels++] = (Relation) palloc(len);
5442 
5443  /* then, read the Relation structure */
5444  if (fread(rel, 1, len, fp) != len)
5445  goto read_failed;
5446 
5447  /* next read the relation tuple form */
5448  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5449  goto read_failed;
5450 
5451  relform = (Form_pg_class) palloc(len);
5452  if (fread(relform, 1, len, fp) != len)
5453  goto read_failed;
5454 
5455  rel->rd_rel = relform;
5456 
5457  /* initialize attribute tuple forms */
5458  rel->rd_att = CreateTemplateTupleDesc(relform->relnatts,
5459  relform->relhasoids);
5460  rel->rd_att->tdrefcount = 1; /* mark as refcounted */
5461 
5462  rel->rd_att->tdtypeid = relform->reltype;
5463  rel->rd_att->tdtypmod = -1; /* unnecessary, but... */
5464 
5465  /* next read all the attribute tuple form data entries */
5466  has_not_null = false;
5467  for (i = 0; i < relform->relnatts; i++)
5468  {
5469  Form_pg_attribute attr = TupleDescAttr(rel->rd_att, i);
5470 
5471  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5472  goto read_failed;
5473  if (len != ATTRIBUTE_FIXED_PART_SIZE)
5474  goto read_failed;
5475  if (fread(attr, 1, len, fp) != len)
5476  goto read_failed;
5477 
5478  has_not_null |= attr->attnotnull;
5479  }
5480 
5481  /* next read the access method specific field */
5482  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5483  goto read_failed;
5484  if (len > 0)
5485  {
5486  rel->rd_options = palloc(len);
5487  if (fread(rel->rd_options, 1, len, fp) != len)
5488  goto read_failed;
5489  if (len != VARSIZE(rel->rd_options))
5490  goto read_failed; /* sanity check */
5491  }
5492  else
5493  {
5494  rel->rd_options = NULL;
5495  }
5496 
5497  /* mark not-null status */
5498  if (has_not_null)
5499  {
5500  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
5501 
5502  constr->has_not_null = true;
5503  rel->rd_att->constr = constr;
5504  }
5505 
5506  /* If it's an index, there's more to do */
5507  if (rel->rd_rel->relkind == RELKIND_INDEX)
5508  {
5509  MemoryContext indexcxt;
5510  Oid *opfamily;
5511  Oid *opcintype;
5512  RegProcedure *support;
5513  int nsupport;
5514  int16 *indoption;
5515  Oid *indcollation;
5516 
5517  /* Count nailed indexes to ensure we have 'em all */
5518  if (rel->rd_isnailed)
5519  nailed_indexes++;
5520 
5521  /* next, read the pg_index tuple */
5522  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5523  goto read_failed;
5524 
5525  rel->rd_indextuple = (HeapTuple) palloc(len);
5526  if (fread(rel->rd_indextuple, 1, len, fp) != len)
5527  goto read_failed;
5528 
5529  /* Fix up internal pointers in the tuple -- see heap_copytuple */
5530  rel->rd_indextuple->t_data = (HeapTupleHeader) ((char *) rel->rd_indextuple + HEAPTUPLESIZE);
5532 
5533  /*
5534  * prepare index info context --- parameters should match
5535  * RelationInitIndexAccessInfo
5536  */
5540  rel->rd_indexcxt = indexcxt;
5541 
5542  /*
5543  * Now we can fetch the index AM's API struct. (We can't store
5544  * that in the init file, since it contains function pointers that
5545  * might vary across server executions. Fortunately, it should be
5546  * safe to call the amhandler even while bootstrapping indexes.)
5547  */
5548  InitIndexAmRoutine(rel);
5549 
5550  /* next, read the vector of opfamily OIDs */
5551  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5552  goto read_failed;
5553 
5554  opfamily = (Oid *) MemoryContextAlloc(indexcxt, len);
5555  if (fread(opfamily, 1, len, fp) != len)
5556  goto read_failed;
5557 
5558  rel->rd_opfamily = opfamily;
5559 
5560  /* next, read the vector of opcintype OIDs */
5561  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5562  goto read_failed;
5563 
5564  opcintype = (Oid *) MemoryContextAlloc(indexcxt, len);
5565  if (fread(opcintype, 1, len, fp) != len)
5566  goto read_failed;
5567 
5568  rel->rd_opcintype = opcintype;
5569 
5570  /* next, read the vector of support procedure OIDs */
5571  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5572  goto read_failed;
5573  support = (RegProcedure *) MemoryContextAlloc(indexcxt, len);
5574  if (fread(support, 1, len, fp) != len)
5575  goto read_failed;
5576 
5577  rel->rd_support = support;
5578 
5579  /* next, read the vector of collation OIDs */
5580  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5581  goto read_failed;
5582 
5583  indcollation = (Oid *) MemoryContextAlloc(indexcxt, len);
5584  if (fread(indcollation, 1, len, fp) != len)
5585  goto read_failed;
5586 
5587  rel->rd_indcollation = indcollation;
5588 
5589  /* finally, read the vector of indoption values */
5590  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5591  goto read_failed;
5592 
5593  indoption = (int16 *) MemoryContextAlloc(indexcxt, len);
5594  if (fread(indoption, 1, len, fp) != len)
5595  goto read_failed;
5596 
5597  rel->rd_indoption = indoption;
5598 
5599  /* set up zeroed fmgr-info vector */
5600  nsupport = relform->relnatts * rel->rd_amroutine->amsupport;
5601  rel->rd_supportinfo = (FmgrInfo *)
5602  MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
5603  }
5604  else
5605  {
5606  /* Count nailed rels to ensure we have 'em all */
5607  if (rel->rd_isnailed)
5608  nailed_rels++;
5609 
5610  Assert(rel->rd_index == NULL);
5611  Assert(rel->rd_indextuple == NULL);
5612  Assert(rel->rd_indexcxt == NULL);
5613  Assert(rel->rd_amroutine == NULL);
5614  Assert(rel->rd_opfamily == NULL);
5615  Assert(rel->rd_opcintype == NULL);
5616  Assert(rel->rd_support == NULL);
5617  Assert(rel->rd_supportinfo == NULL);
5618  Assert(rel->rd_indoption == NULL);
5619  Assert(rel->rd_indcollation == NULL);
5620  }
5621 
5622  /*
5623  * Rules and triggers are not saved (mainly because the internal
5624  * format is complex and subject to change). They must be rebuilt if
5625  * needed by RelationCacheInitializePhase3. This is not expected to
5626  * be a big performance hit since few system catalogs have such. Ditto
5627  * for RLS policy data, index expressions, predicates, exclusion info,
5628  * and FDW info.
5629  */
5630  rel->rd_rules = NULL;
5631  rel->rd_rulescxt = NULL;
5632  rel->trigdesc = NULL;
5633  rel->rd_rsdesc = NULL;
5634  rel->rd_partkeycxt = NULL;
5635  rel->rd_partkey = NULL;
5636  rel->rd_pdcxt = NULL;
5637  rel->rd_partdesc = NULL;
5638  rel->rd_partcheck = NIL;
5639  rel->rd_indexprs = NIL;
5640  rel->rd_indpred = NIL;
5641  rel->rd_exclops = NULL;
5642  rel->rd_exclprocs = NULL;
5643  rel->rd_exclstrats = NULL;
5644  rel->rd_fdwroutine = NULL;
5645 
5646  /*
5647  * Reset transient-state fields in the relcache entry
5648  */
5649  rel->rd_smgr = NULL;
5650  if (rel->rd_isnailed)
5651  rel->rd_refcnt = 1;
5652  else
5653  rel->rd_refcnt = 0;
5654  rel->rd_indexvalid = 0;
5655  rel->rd_fkeylist = NIL;
5656  rel->rd_fkeyvalid = false;
5657  rel->rd_indexlist = NIL;
5658  rel->rd_oidindex = InvalidOid;
5659  rel->rd_pkindex = InvalidOid;
5660  rel->rd_replidindex = InvalidOid;
5661  rel->rd_indexattr = NULL;
5662  rel->rd_keyattr = NULL;
5663  rel->rd_pkattr = NULL;
5664  rel->rd_idattr = NULL;
5665  rel->rd_pubactions = NULL;
5666  rel->rd_statvalid = false;
5667  rel->rd_statlist = NIL;
5670  rel->rd_amcache = NULL;
5671  MemSet(&rel->pgstat_info, 0, sizeof(rel->pgstat_info));
5672 
5673  /*
5674  * Recompute lock and physical addressing info. This is needed in
5675  * case the pg_internal.init file was copied from some other database
5676  * by CREATE DATABASE.
5677  */
5678  RelationInitLockInfo(rel);
5680  }
5681 
5682  /*
5683  * We reached the end of the init file without apparent problem. Did we
5684  * get the right number of nailed items? This is a useful crosscheck in
5685  * case the set of critical rels or indexes changes. However, that should
5686  * not happen in a normally-running system, so let's bleat if it does.
5687  *
5688  * For the shared init file, we're called before client authentication is
5689  * done, which means that elog(WARNING) will go only to the postmaster
5690  * log, where it's easily missed. To ensure that developers notice bad
5691  * values of NUM_CRITICAL_SHARED_RELS/NUM_CRITICAL_SHARED_INDEXES, we put
5692  * an Assert(false) there.
5693  */
5694  if (shared)
5695  {
5696  if (nailed_rels != NUM_CRITICAL_SHARED_RELS ||
5697  nailed_indexes != NUM_CRITICAL_SHARED_INDEXES)
5698  {
5699  elog(WARNING, "found %d nailed shared rels and %d nailed shared indexes in init file, but expected %d and %d respectively",
5700  nailed_rels, nailed_indexes,
5702  /* Make sure we get developers' attention about this */
5703  Assert(false);
5704  /* In production builds, recover by bootstrapping the relcache */
5705  goto read_failed;
5706  }
5707  }
5708  else
5709  {
5710  if (nailed_rels != NUM_CRITICAL_LOCAL_RELS ||
5711  nailed_indexes != NUM_CRITICAL_LOCAL_INDEXES)
5712  {
5713  elog(WARNING, "found %d nailed rels and %d nailed indexes in init file, but expected %d and %d respectively",
5714  nailed_rels, nailed_indexes,
5716  /* We don't need an Assert() in this case */
5717  goto read_failed;
5718  }
5719  }
5720 
5721  /*
5722  * OK, all appears well.
5723  *
5724  * Now insert all the new relcache entries into the cache.
5725  */
5726  for (relno = 0; relno < num_rels; relno++)
5727  {
5728  RelationCacheInsert(rels[relno], false);
5729  }
5730 
5731  pfree(rels);
5732  FreeFile(fp);
5733 
5734  if (shared)
5736  else
5737  criticalRelcachesBuilt = true;
5738  return true;
5739 
5740  /*
5741  * init file is broken, so do it the hard way. We don't bother trying to
5742  * free the clutter we just allocated; it's not in the relcache so it
5743  * won't hurt.
5744  */
5745 read_failed:
5746  pfree(rels);
5747  FreeFile(fp);
5748 
5749  return false;
5750 }
struct FdwRoutine * rd_fdwroutine
Definition: rel.h:204
signed short int16
Definition: c.h:245
#define NIL
Definition: pg_list.h:69
Definition: fmgr.h:56
struct PartitionDescData * rd_partdesc
Definition: rel.h:131
uint16 amsupport
Definition: amapi.h:169
HeapTupleData * HeapTuple
Definition: htup.h:70
Oid tdtypeid
Definition: tupdesc.h:74
int16 * rd_indoption
Definition: rel.h:186
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
PublicationActions * rd_pubactions
Definition: rel.h:149
FmgrInfo * rd_supportinfo
Definition: rel.h:185
Bitmapset * rd_keyattr
Definition: rel.h:145
#define VARSIZE(PTR)
Definition: postgres.h:304
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
Oid rd_replidindex
Definition: rel.h:138
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:175
bool rd_isnailed
Definition: rel.h:91
regproc RegProcedure
Definition: c.h:389
uint16 * rd_exclstrats
Definition: rel.h:191
#define NUM_CRITICAL_LOCAL_INDEXES
List * rd_indexprs
Definition: rel.h:187
List * rd_fkeylist
Definition: rel.h:125
#define RELCACHE_INIT_FILENAME
Definition: relcache.c:93
#define MemSet(start, val, len)
Definition: c.h:863
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:111
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
MemoryContext rd_rulescxt
Definition: rel.h:119
bool criticalSharedRelcachesBuilt
Definition: relcache.c:135
Oid * rd_exclprocs
Definition: rel.h:190
Form_pg_class rd_rel
Definition: rel.h:114
unsigned int Oid
Definition: postgres_ext.h:31
#define NUM_CRITICAL_SHARED_INDEXES
#define PG_BINARY_R
Definition: c.h:1046
#define NUM_CRITICAL_SHARED_RELS
struct IndexAmRoutine * rd_amroutine
Definition: rel.h:181
static void InitIndexAmRoutine(Relation relation)
Definition: relcache.c:1489
int32 tdtypmod
Definition: tupdesc.h:75
struct HeapTupleData * rd_indextuple
Definition: rel.h:161
HeapTupleHeader t_data
Definition: htup.h:67
struct RelationData * Relation
Definition: relcache.h:21
Form_pg_index rd_index
Definition: rel.h:159
void pfree(void *pointer)
Definition: mcxt.c:949
#define NUM_CRITICAL_LOCAL_RELS
Oid * rd_indcollation
Definition: rel.h:193
Oid rd_pkindex
Definition: rel.h:137
struct PartitionKeyData * rd_partkey
Definition: rel.h:129
#define MAXPGPATH
TriggerDesc * trigdesc
Definition: rel.h:120
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1426
void RelationInitLockInfo(Relation relation)
Definition: lmgr.c:68
char rd_indexvalid
Definition: rel.h:93
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2117
#define RELCACHE_INIT_FILEMAGIC
Definition: relcache.c:95
#define RelationGetRelationName(relation)
Definition: rel.h:436
List * rd_indpred
Definition: rel.h:188
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
Oid rd_oidindex
Definition: rel.h:136
Oid * rd_opfamily
Definition: rel.h:182
Oid * rd_exclops
Definition: rel.h:189
List * rd_indexlist
Definition: rel.h:135
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:179
struct RowSecurityDesc * rd_rsdesc
Definition: rel.h:122
RegProcedure * rd_support
Definition: rel.h:184
bool has_not_null
Definition: tupdesc.h:43
#define WARNING
Definition: elog.h:40
FormData_pg_index * Form_pg_index
Definition: pg_index.h:67
SubTransactionId rd_createSubid
Definition: rel.h:110
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
void * palloc0(Size size)
Definition: mcxt.c:877
TupleDesc rd_att
Definition: rel.h:115
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:741
#define InvalidOid
Definition: postgres_ext.h:36
Bitmapset * rd_idattr
Definition: rel.h:147
#define RelationCacheInsert(RELATION, replace_allowed)
Definition: relcache.c:180
char * DatabasePath
Definition: globals.c:85
MemoryContext rd_pdcxt
Definition: rel.h:130
#define Assert(condition)
Definition: c.h:681
MemoryContext rd_partkeycxt
Definition: rel.h:128
RuleLock * rd_rules
Definition: rel.h:118
TupleConstr * constr
Definition: tupdesc.h:78
size_t Size
Definition: c.h:350
struct PgStat_TableStatus * pgstat_info
Definition: rel.h:218
#define InvalidSubTransactionId
Definition: c.h:397
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:43
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:962
int FreeFile(FILE *file)
Definition: fd.c:2309
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
Bitmapset * rd_pkattr
Definition: rel.h:146
bool rd_statvalid
Definition: rel.h:95
void * palloc(Size size)
Definition: mcxt.c:848
int rd_refcnt
Definition: rel.h:88
#define HEAPTUPLESIZE
Definition: htup.h:72
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:706
int tdrefcount
Definition: tupdesc.h:77
MemoryContext rd_indexcxt
Definition: rel.h:179
int i
#define RELKIND_INDEX
Definition: pg_class.h:161
#define elog
Definition: elog.h:219
bool criticalRelcachesBuilt
Definition: relcache.c:129
void * rd_amcache
Definition: rel.h:192
Oid * rd_opcintype
Definition: rel.h:183
List * rd_statlist
Definition: rel.h:141
bool rd_fkeyvalid
Definition: rel.h:126
List * rd_partcheck
Definition: rel.h:132
Bitmapset * rd_indexattr
Definition: rel.h:144
bytea * rd_options
Definition: rel.h:156
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static OpClassCacheEnt * LookupOpclassInfo ( Oid  operatorClassOid,
StrategyNumber  numSupport 
)
static

Definition at line 1727 of file relcache.c.

References AccessMethodProcedureIndexId, AccessMethodProcedureRelationId, AccessShareLock, Anum_pg_amproc_amprocfamily, Anum_pg_amproc_amproclefttype, Anum_pg_amproc_amprocrighttype, Assert, BTEqualStrategyNumber, CacheMemoryContext, CreateCacheMemoryContext(), criticalRelcachesBuilt, elog, HASHCTL::entrysize, ERROR, GETSTRUCT, HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), heap_close, heap_open(), HeapTupleIsValid, INT2_BTREE_OPS_OID, HASHCTL::keysize, MemoryContextAllocZero(), MemSet, opclasscacheent::numSupport, ObjectIdAttributeNumber, ObjectIdGetDatum, OID_BTREE_OPS_OID, opclasscacheent::opcfamily, opclasscacheent::opcintype, OpclassOidIndexId, OperatorClassRelationId, ScanKeyInit(), opclasscacheent::supportProcs, systable_beginscan(), systable_endscan(), systable_getnext(), and opclasscacheent::valid.

Referenced by IndexSupportInitialize().

1729 {
1730  OpClassCacheEnt *opcentry;
1731  bool found;
1732  Relation rel;
1733  SysScanDesc scan;
1734  ScanKeyData skey[3];
1735  HeapTuple htup;
1736  bool indexOK;
1737 
1738  if (OpClassCache == NULL)
1739  {
1740  /* First time through: initialize the opclass cache */
1741  HASHCTL ctl;
1742 
1743  MemSet(&ctl, 0, sizeof(ctl));
1744  ctl.keysize = sizeof(Oid);
1745  ctl.entrysize = sizeof(OpClassCacheEnt);
1746  OpClassCache = hash_create("Operator class cache", 64,
1747  &ctl, HASH_ELEM | HASH_BLOBS);
1748 
1749  /* Also make sure CacheMemoryContext exists */
1750  if (!CacheMemoryContext)
1752  }
1753 
1754  opcentry = (OpClassCacheEnt *) hash_search(OpClassCache,
1755  (void *) &operatorClassOid,
1756  HASH_ENTER, &found);
1757 
1758  if (!found)
1759  {
1760  /* Need to allocate memory for new entry */
1761  opcentry->valid = false; /* until known OK */
1762  opcentry->numSupport = numSupport;
1763 
1764  if (numSupport > 0)
1765  opcentry->supportProcs = (RegProcedure *)
1767  numSupport * sizeof(RegProcedure));
1768  else
1769  opcentry->supportProcs = NULL;
1770  }
1771  else
1772  {
1773  Assert(numSupport == opcentry->numSupport);
1774  }
1775 
1776  /*
1777  * When testing for cache-flush hazards, we intentionally disable the
1778  * operator class cache and force reloading of the info on each call. This
1779  * is helpful because we want to test the case where a cache flush occurs
1780  * while we are loading the info, and it's very hard to provoke that if
1781  * this happens only once per opclass per backend.
1782  */
1783 #if defined(CLOBBER_CACHE_ALWAYS)
1784  opcentry->valid = false;
1785 #endif
1786 
1787  if (opcentry->valid)
1788  return opcentry;
1789 
1790  /*
1791  * Need to fill in new entry.
1792  *
1793  * To avoid infinite recursion during startup, force heap scans if we're
1794  * looking up info for the opclasses used by the indexes we would like to
1795  * reference here.
1796  */
1797  indexOK = criticalRelcachesBuilt ||
1798  (operatorClassOid != OID_BTREE_OPS_OID &&
1799  operatorClassOid != INT2_BTREE_OPS_OID);
1800 
1801  /*
1802  * We have to fetch the pg_opclass row to determine its opfamily and
1803  * opcintype, which are needed to look up related operators and functions.
1804  * It'd be convenient to use the syscache here, but that probably doesn't
1805  * work while bootstrapping.
1806  */
1807  ScanKeyInit(&skey[0],
1809  BTEqualStrategyNumber, F_OIDEQ,
1810  ObjectIdGetDatum(operatorClassOid));
1812  scan = systable_beginscan(rel, OpclassOidIndexId, indexOK,
1813  NULL, 1, skey);
1814 
1815  if (HeapTupleIsValid(htup = systable_getnext(scan)))
1816  {
1817  Form_pg_opclass opclassform = (Form_pg_opclass) GETSTRUCT(htup);
1818 
1819  opcentry->opcfamily = opclassform->opcfamily;
1820  opcentry->opcintype = opclassform->opcintype;
1821  }
1822  else
1823  elog(ERROR, "could not find tuple for opclass %u", operatorClassOid);
1824 
1825  systable_endscan(scan);
1827 
1828  /*
1829  * Scan pg_amproc to obtain support procs for the opclass. We only fetch
1830  * the default ones (those with lefttype = righttype = opcintype).
1831  */
1832  if (numSupport > 0)
1833  {
1834  ScanKeyInit(&skey[0],
1836  BTEqualStrategyNumber, F_OIDEQ,
1837  ObjectIdGetDatum(opcentry->opcfamily));
1838  ScanKeyInit(&skey[1],
1840  BTEqualStrategyNumber, F_OIDEQ,
1841  ObjectIdGetDatum(opcentry->opcintype));
1842  ScanKeyInit(&skey[2],
1844  BTEqualStrategyNumber, F_OIDEQ,
1845  ObjectIdGetDatum(opcentry->opcintype));
1847  scan = systable_beginscan(rel, AccessMethodProcedureIndexId, indexOK,
1848  NULL, 3, skey);
1849 
1850  while (HeapTupleIsValid(htup = systable_getnext(scan)))
1851  {
1852  Form_pg_amproc amprocform = (Form_pg_amproc) GETSTRUCT(htup);
1853 
1854  if (amprocform->amprocnum <= 0 ||
1855  (StrategyNumber) amprocform->amprocnum > numSupport)
1856  elog(ERROR, "invalid amproc number %d for opclass %u",
1857  amprocform->amprocnum, operatorClassOid);
1858 
1859  opcentry->supportProcs[amprocform->amprocnum - 1] =
1860  amprocform->amproc;
1861  }
1862 
1863  systable_endscan(scan);
1865  }
1866 
1867  opcentry->valid = true;
1868  return opcentry;
1869 }
struct opclasscacheent OpClassCacheEnt
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define INT2_BTREE_OPS_OID
Definition: pg_opclass.h:118
#define HASH_ELEM
Definition: hsearch.h:87
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
FormData_pg_amproc * Form_pg_amproc
Definition: pg_amproc.h:59
regproc RegProcedure
Definition: c.h:389
#define AccessShareLock
Definition: lockdefs.h:36
#define OperatorClassRelationId
Definition: pg_opclass.h:49
Size entrysize
Definition: hsearch.h:73
uint16 StrategyNumber
Definition: stratnum.h:22
#define MemSet(start, val, len)
Definition: c.h:863
#define OID_BTREE_OPS_OID
Definition: pg_opclass.h:145
#define heap_close(r, l)
Definition: heapam.h:97
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
unsigned int Oid
Definition: postgres_ext.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
StrategyNumber numSupport
Definition: relcache.c:236
#define Anum_pg_amproc_amproclefttype
Definition: pg_amproc.h:67
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
RegProcedure * supportProcs
Definition: relcache.c:239
#define Anum_pg_amproc_amprocfamily
Definition: pg_amproc.h:66
static HTAB * OpClassCache
Definition: relcache.c:242
#define Anum_pg_amproc_amprocrighttype
Definition: pg_amproc.h:68
#define HASH_BLOBS
Definition: hsearch.h:88
#define AccessMethodProcedureIndexId
Definition: indexing.h:82
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
Size keysize
Definition: hsearch.h:72
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:741
#define OpclassOidIndexId
Definition: indexing.h:200
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:681
void CreateCacheMemoryContext(void)
Definition: catcache.c:636
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
bool criticalRelcachesBuilt
Definition: relcache.c:129
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:68
#define AccessMethodProcedureRelationId
Definition: pg_amproc.h:43
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static Relation RelationBuildDesc ( Oid  targetRelId,
bool  insertIt 
)
static

Definition at line 1241 of file relcache.c.

References AllocateRelationDesc(), Assert, BackendIdForTempRelations, elog, ERROR, GETSTRUCT, GetTempNamespaceBackendId(), heap_freetuple(), HeapTupleGetOid, HeapTupleIsValid, InvalidBackendId, InvalidSubTransactionId, isTempOrTempToastNamespace(), NIL, OidIsValid, RelationData::rd_backend, RelationData::rd_createSubid, RelationData::rd_fkeylist, RelationData::rd_fkeyvalid, RelationData::rd_islocaltemp, RelationData::rd_isnailed, RelationData::rd_isvalid, RelationData::rd_newRelfilenodeSubid, RelationData::rd_partdesc, RelationData::rd_partkey, RelationData::rd_partkeycxt, RelationData::rd_pdcxt, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_rsdesc, RelationData::rd_rules, RelationData::rd_rulescxt, RelationData::rd_smgr, RelationBuildPartitionDesc(), RelationBuildPartitionKey(), RelationBuildRowSecurity(), RelationBuildRuleLock(), RelationBuildTriggers(), RelationBuildTupleDesc(), RelationCacheInsert, RelationGetRelid, RelationInitIndexAccessInfo(), RelationInitLockInfo(), RelationInitPhysicalAddr(), RelationParseRelOptions(), RELKIND_PARTITIONED_TABLE, RELPERSISTENCE_PERMANENT, RELPERSISTENCE_TEMP, RELPERSISTENCE_UNLOGGED, ScanPgRelation(), and RelationData::trigdesc.

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

1242 {
1243  Relation relation;
1244  Oid relid;
1245  HeapTuple pg_class_tuple;
1246  Form_pg_class relp;
1247 
1248  /*
1249  * find the tuple in pg_class corresponding to the given relation id
1250  */
1251  pg_class_tuple = ScanPgRelation(targetRelId, true, false);
1252 
1253  /*
1254  * if no such tuple exists, return NULL
1255  */
1256  if (!HeapTupleIsValid(pg_class_tuple))
1257  return NULL;
1258 
1259  /*
1260  * get information from the pg_class_tuple
1261  */
1262  relid = HeapTupleGetOid(pg_class_tuple);
1263  relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);
1264  Assert(relid == targetRelId);
1265 
1266  /*
1267  * allocate storage for the relation descriptor, and copy pg_class_tuple
1268  * to relation->rd_rel.
1269  */
1270  relation = AllocateRelationDesc(relp);
1271 
1272  /*
1273  * initialize the relation's relation id (relation->rd_id)
1274  */
1275  RelationGetRelid(relation) = relid;
1276 
1277  /*
1278  * normal relations are not nailed into the cache; nor can a pre-existing
1279  * relation be new. It could be temp though. (Actually, it could be new
1280  * too, but it's okay to forget that fact if forced to flush the entry.)
1281  */
1282  relation->rd_refcnt = 0;
1283  relation->rd_isnailed = false;
1286  switch (relation->rd_rel->relpersistence)
1287  {
1290  relation->rd_backend = InvalidBackendId;
1291  relation->rd_islocaltemp = false;
1292  break;
1293  case RELPERSISTENCE_TEMP:
1294  if (isTempOrTempToastNamespace(relation->rd_rel->relnamespace))
1295  {
1296  relation->rd_backend = BackendIdForTempRelations();
1297  relation->rd_islocaltemp = true;
1298  }
1299  else
1300  {
1301  /*
1302  * If it's a temp table, but not one of ours, we have to use
1303  * the slow, grotty method to figure out the owning backend.
1304  *
1305  * Note: it's possible that rd_backend gets set to MyBackendId
1306  * here, in case we are looking at a pg_class entry left over
1307  * from a crashed backend that coincidentally had the same
1308  * BackendId we're using. We should *not* consider such a
1309  * table to be "ours"; this is why we need the separate
1310  * rd_islocaltemp flag. The pg_class entry will get flushed
1311  * if/when we clean out the corresponding temp table namespace
1312  * in preparation for using it.
1313  */
1314  relation->rd_backend =
1315  GetTempNamespaceBackendId(relation->rd_rel->relnamespace);
1316  Assert(relation->rd_backend != InvalidBackendId);
1317  relation->rd_islocaltemp = false;
1318  }
1319  break;
1320  default:
1321  elog(ERROR, "invalid relpersistence: %c",
1322  relation->rd_rel->relpersistence);
1323  break;
1324  }
1325 
1326  /*
1327  * initialize the tuple descriptor (relation->rd_att).
1328  */
1329  RelationBuildTupleDesc(relation);
1330 
1331  /*
1332  * Fetch rules and triggers that affect this relation
1333  */
1334  if (relation->rd_rel->relhasrules)
1335  RelationBuildRuleLock(relation);
1336  else
1337  {
1338  relation->rd_rules = NULL;
1339  relation->rd_rulescxt = NULL;
1340  }
1341 
1342  if (relation->rd_rel->relhastriggers)
1343  RelationBuildTriggers(relation);
1344  else
1345  relation->trigdesc = NULL;
1346 
1347  if (relation->rd_rel->relrowsecurity)
1348  RelationBuildRowSecurity(relation);
1349  else
1350  relation->rd_rsdesc = NULL;
1351 
1352  /* foreign key data is not loaded till asked for */
1353  relation->rd_fkeylist = NIL;
1354  relation->rd_fkeyvalid = false;
1355 
1356  /* if a partitioned table, initialize key and partition descriptor info */
1357  if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1358  {
1359  RelationBuildPartitionKey(relation);
1360  RelationBuildPartitionDesc(relation);
1361  }
1362  else
1363  {
1364  relation->rd_partkeycxt = NULL;
1365  relation->rd_partkey = NULL;
1366  relation->rd_partdesc = NULL;
1367  relation->rd_pdcxt = NULL;
1368  }
1369 
1370  /*
1371  * if it's an index, initialize index-related information
1372  */
1373  if (OidIsValid(relation->rd_rel->relam))
1374  RelationInitIndexAccessInfo(relation);
1375 
1376  /* extract reloptions if any */
1377  RelationParseRelOptions(relation, pg_class_tuple);
1378 
1379  /*
1380  * initialize the relation lock manager information
1381  */
1382  RelationInitLockInfo(relation); /* see lmgr.c */
1383 
1384  /*
1385  * initialize physical addressing information for the relation
1386  */
1387  RelationInitPhysicalAddr(relation);
1388 
1389  /* make sure relation is marked as having no open file yet */
1390  relation->rd_smgr = NULL;
1391 
1392  /*
1393  * now we can free the memory allocated for pg_class_tuple
1394  */
1395  heap_freetuple(pg_class_tuple);
1396 
1397  /*
1398  * Insert newly created relation into relcache hash table, if requested.
1399  *
1400  * There is one scenario in which we might find a hashtable entry already
1401  * present, even though our caller failed to find it: if the relation is a
1402  * system catalog or index that's used during relcache load, we might have
1403  * recursively created the same relcache entry during the preceding steps.
1404  * So allow RelationCacheInsert to delete any already-present relcache
1405  * entry for the same OID. The already-present entry should have refcount
1406  * zero (else somebody forgot to close it); in the event that it doesn't,
1407  * we'll elog a WARNING and leak the already-present entry.
1408  */
1409  if (insertIt)
1410  RelationCacheInsert(relation, true);
1411 
1412  /* It's fully valid */
1413  relation->rd_isvalid = true;
1414 
1415  return relation;
1416 }
#define NIL
Definition: pg_list.h:69
struct PartitionDescData * rd_partdesc
Definition: rel.h:131
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define RELPERSISTENCE_UNLOGGED
Definition: pg_class.h:171
void RelationBuildRowSecurity(Relation relation)
Definition: policy.c:191
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3142
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
bool rd_isnailed
Definition: rel.h:91
bool rd_islocaltemp
Definition: rel.h:90
List * rd_fkeylist
Definition: rel.h:125
bool rd_isvalid
Definition: rel.h:92
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:111
int GetTempNamespaceBackendId(Oid namespaceId)
Definition: namespace.c:3195
MemoryContext rd_rulescxt
Definition: rel.h:119
Form_pg_class rd_rel
Definition: rel.h:114
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
unsigned int Oid
Definition: postgres_ext.h:31
static Relation AllocateRelationDesc(Form_pg_class relp)
Definition: relcache.c:379
#define OidIsValid(objectId)
Definition: c.h:532
static void RelationBuildPartitionKey(Relation relation)
Definition: relcache.c:827
void RelationBuildPartitionDesc(Relation rel)
Definition: partition.c:161
#define RELPERSISTENCE_PERMANENT
Definition: pg_class.h:170
#define ERROR
Definition: elog.h:43
struct PartitionKeyData * rd_partkey
Definition: rel.h:129
TriggerDesc * trigdesc
Definition: rel.h:120
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1426
void RelationInitLockInfo(Relation relation)
Definition: lmgr.c:68
#define BackendIdForTempRelations()
Definition: backendid.h:34
static void RelationParseRelOptions(Relation relation, HeapTuple tuple)
Definition: relcache.c:435
static void RelationBuildTupleDesc(Relation relation)
Definition: relcache.c:487
struct RowSecurityDesc * rd_rsdesc
Definition: rel.h:122
SubTransactionId rd_createSubid
Definition: rel.h:110
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
#define InvalidBackendId
Definition: backendid.h:23
#define RelationCacheInsert(RELATION, replace_allowed)
Definition: relcache.c:180
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
MemoryContext rd_pdcxt
Definition: rel.h:130
BackendId rd_backend
Definition: rel.h:89
#define Assert(condition)
Definition: c.h:681
MemoryContext rd_partkeycxt
Definition: rel.h:128
RuleLock * rd_rules
Definition: rel.h:118
#define InvalidSubTransactionId
Definition: c.h:397
void RelationInitIndexAccessInfo(Relation relation)
Definition: relcache.c:1513
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
void RelationBuildTriggers(Relation relation)
Definition: trigger.c:1683
int rd_refcnt
Definition: rel.h:88
static HeapTuple ScanPgRelation(Oid targetRelId, bool indexOK, bool force_non_historic)
Definition: relcache.c:309
static void RelationBuildRuleLock(Relation relation)
Definition: relcache.c:659
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
#define RELPERSISTENCE_TEMP
Definition: pg_class.h:172
bool rd_fkeyvalid
Definition: rel.h:126
#define RelationGetRelid(relation)
Definition: rel.h:416
Relation RelationBuildLocalRelation ( const char *  relname,
Oid  relnamespace,
TupleDesc  tupDesc,
Oid  relid,
Oid  relfilenode,
Oid  reltablespace,
bool  shared_relation,
bool  mapped_relation,
char  relpersistence,
char  relkind 
)

Definition at line 3187 of file relcache.c.

References Assert, AssertArg, AttributeRelationId, AuthIdRelationId, AuthMemRelationId, BackendIdForTempRelations, BOOTSTRAP_SUPERUSERID, CacheMemoryContext, CLASS_TUPLE_SIZE, tupleDesc::constr, CreateCacheMemoryContext(), CreateTupleDescCopy(), DatabaseRelationId, elog, EOXactListAdd, ERROR, GetCurrentSubTransactionId(), tupleConstr::has_not_null, i, InvalidBackendId, InvalidOid, InvalidSubTransactionId, IsSharedRelation(), IsSystemNamespace(), isTempOrTempToastNamespace(), MemoryContextSwitchTo(), namestrcpy(), tupleDesc::natts, palloc0(), ProcedureRelationId, RelationData::rd_att, RelationData::rd_backend, RelationData::rd_createSubid, 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(), RelationMapUpdateMap(), RelationRelationId, RELKIND_MATVIEW, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, RELPERSISTENCE_PERMANENT, RELPERSISTENCE_TEMP, RELPERSISTENCE_UNLOGGED, REPLICA_IDENTITY_DEFAULT, REPLICA_IDENTITY_NOTHING, tupleDesc::tdhasoid, tupleDesc::tdrefcount, TupleDescAttr, and TypeRelationId.

Referenced by heap_create().

3197 {
3198  Relation rel;
3199  MemoryContext oldcxt;
3200  int natts = tupDesc->natts;
3201  int i;
3202  bool has_not_null;
3203  bool nailit;
3204 
3205  AssertArg(natts >= 0);
3206 
3207  /*
3208  * check for creation of a rel that must be nailed in cache.
3209  *
3210  * XXX this list had better match the relations specially handled in
3211  * RelationCacheInitializePhase2/3.
3212  */
3213  switch (relid)
3214  {
3215  case DatabaseRelationId:
3216  case AuthIdRelationId:
3217  case AuthMemRelationId:
3218  case RelationRelationId:
3219  case AttributeRelationId:
3220  case ProcedureRelationId:
3221  case TypeRelationId:
3222  nailit = true;
3223  break;
3224  default:
3225  nailit = false;
3226  break;
3227  }
3228 
3229  /*
3230  * check that hardwired list of shared rels matches what's in the
3231  * bootstrap .bki file. If you get a failure here during initdb, you
3232  * probably need to fix IsSharedRelation() to match whatever you've done
3233  * to the set of shared relations.
3234  */
3235  if (shared_relation != IsSharedRelation(relid))
3236  elog(ERROR, "shared_relation flag for \"%s\" does not match IsSharedRelation(%u)",
3237  relname, relid);
3238 
3239  /* Shared relations had better be mapped, too */
3240  Assert(mapped_relation || !shared_relation);
3241 
3242  /*
3243  * switch to the cache context to create the relcache entry.
3244  */
3245  if (!CacheMemoryContext)
3247 
3249 
3250  /*
3251  * allocate a new relation descriptor and fill in basic state fields.
3252  */
3253  rel = (Relation) palloc0(sizeof(RelationData));
3254 
3255  /* make sure relation is marked as having no open file yet */
3256  rel->rd_smgr = NULL;
3257 
3258  /* mark it nailed if appropriate */
3259  rel->rd_isnailed = nailit;
3260 
3261  rel->rd_refcnt = nailit ? 1 : 0;
3262 
3263  /* it's being created in this transaction */
3266 
3267  /*
3268  * create a new tuple descriptor from the one passed in. We do this
3269  * partly to copy it into the cache context, and partly because the new
3270  * relation can't have any defaults or constraints yet; they have to be
3271  * added in later steps, because they require additions to multiple system
3272  * catalogs. We can copy attnotnull constraints here, however.
3273  */
3274  rel->rd_att = CreateTupleDescCopy(tupDesc);
3275  rel->rd_att->tdrefcount = 1; /* mark as refcounted */
3276  has_not_null = false;
3277  for (i = 0; i < natts; i++)
3278  {
3279  Form_pg_attribute satt = TupleDescAttr(tupDesc, i);
3280  Form_pg_attribute datt = TupleDescAttr(rel->rd_att, i);
3281 
3282  datt->attidentity = satt->attidentity;
3283  datt->attnotnull = satt->attnotnull;
3284  has_not_null |= satt->attnotnull;
3285  }
3286 
3287  if (has_not_null)
3288  {
3289  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
3290 
3291  constr->has_not_null = true;
3292  rel->rd_att->constr = constr;
3293  }
3294 
3295  /*
3296  * initialize relation tuple form (caller may add/override data later)
3297  */
3299 
3300  namestrcpy(&rel->rd_rel->relname, relname);
3301  rel->rd_rel->relnamespace = relnamespace;
3302 
3303  rel->rd_rel->relkind = relkind;
3304  rel->rd_rel->relhasoids = rel->rd_att->tdhasoid;
3305  rel->rd_rel->relnatts = natts;
3306  rel->rd_rel->reltype = InvalidOid;
3307  /* needed when bootstrapping: */
3308  rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;
3309 
3310  /* set up persistence and relcache fields dependent on it */
3311  rel->rd_rel->relpersistence = relpersistence;
3312  switch (relpersistence)
3313  {
3317  rel->rd_islocaltemp = false;
3318  break;
3319  case RELPERSISTENCE_TEMP:
3320  Assert(isTempOrTempToastNamespace(relnamespace));
3322  rel->rd_islocaltemp = true;
3323  break;
3324  default:
3325  elog(ERROR, "invalid relpersistence: %c", relpersistence);
3326  break;
3327  }
3328 
3329  /* if it's a materialized view, it's not populated initially */
3330  if (relkind == RELKIND_MATVIEW)
3331  rel->rd_rel->relispopulated = false;
3332  else
3333  rel->rd_rel->relispopulated = true;
3334 
3335  /* system relations and non-table objects don't have one */
3336  if (!IsSystemNamespace(relnamespace) &&
3337  (relkind == RELKIND_RELATION ||
3338  relkind == RELKIND_MATVIEW ||
3339  relkind == RELKIND_PARTITIONED_TABLE))
3340  rel->rd_rel->relreplident = REPLICA_IDENTITY_DEFAULT;
3341  else
3342  rel->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
3343 
3344  /*
3345  * Insert relation physical and logical identifiers (OIDs) into the right
3346  * places. For a mapped relation, we set relfilenode to zero and rely on
3347  * RelationInitPhysicalAddr to consult the map.
3348  */
3349  rel->rd_rel->relisshared = shared_relation;
3350 
3351  RelationGetRelid(rel) = relid;
3352 
3353  for (i = 0; i < natts; i++)
3354  TupleDescAttr(rel->rd_att, i)->attrelid = relid;
3355 
3356  rel->rd_rel->reltablespace = reltablespace;
3357 
3358  if (mapped_relation)
3359  {
3360  rel->rd_rel->relfilenode = InvalidOid;
3361  /* Add it to the active mapping information */
3362  RelationMapUpdateMap(relid, relfilenode, shared_relation, true);
3363  }
3364  else
3365  rel->rd_rel->relfilenode = relfilenode;
3366 
3367  RelationInitLockInfo(rel); /* see lmgr.c */
3368 
3370 
3371  /*
3372  * Okay to insert into the relcache hash table.
3373  *
3374  * Ordinarily, there should certainly not be an existing hash entry for
3375  * the same OID; but during bootstrap, when we create a "real" relcache
3376  * entry for one of the bootstrap relations, we'll be overwriting the
3377  * phony one created with formrdesc. So allow that to happen for nailed
3378  * rels.
3379  */
3380  RelationCacheInsert(rel, nailit);
3381 
3382  /*
3383  * Flag relation as needing eoxact cleanup (to clear rd_createSubid). We
3384  * can't do this before storing relid in it.
3385  */
3386  EOXactListAdd(rel);
3387 
3388  /*
3389  * done building relcache entry.
3390  */
3391  MemoryContextSwitchTo(oldcxt);
3392 
3393  /* It's fully valid */
3394  rel->rd_isvalid = true;
3395 
3396  /*
3397  * Caller expects us to pin the returned entry.
3398  */
3400 
3401  return rel;
3402 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:102
#define EOXactListAdd(rel)
Definition: relcache.c:160
bool tdhasoid
Definition: tupdesc.h:76
#define RELPERSISTENCE_UNLOGGED
Definition: pg_class.h:171
#define REPLICA_IDENTITY_NOTHING
Definition: pg_class.h:177
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3142
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
#define ProcedureRelationId
Definition: pg_proc.h:33
#define AuthMemRelationId
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
#define DatabaseRelationId
Definition: pg_database.h:29
#define RelationRelationId
Definition: pg_class.h:29
bool rd_isnailed
Definition: rel.h:91
bool rd_islocaltemp
Definition: rel.h:90
#define RELKIND_MATVIEW
Definition: pg_class.h:165
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define REPLICA_IDENTITY_DEFAULT
Definition: pg_class.h:175
#define AttributeRelationId
Definition: pg_attribute.h:33
bool rd_isvalid
Definition: rel.h:92
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:111
Form_pg_class rd_rel
Definition: rel.h:114
#define TypeRelationId
Definition: pg_type.h:34
int namestrcpy(Name name, const char *str)
Definition: name.c:216
int natts
Definition: tupdesc.h:73
#define AuthIdRelationId
Definition: pg_authid.h:42
#define RELPERSISTENCE_PERMANENT
Definition: pg_class.h:170
struct RelationData * Relation
Definition: relcache.h:21
#define ERROR
Definition: elog.h:43
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1426
void RelationInitLockInfo(Relation relation)
Definition: lmgr.c:68
#define BackendIdForTempRelations()
Definition: backendid.h:34
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define AssertArg(condition)
Definition: c.h:683
bool has_not_null
Definition: tupdesc.h:43
SubTransactionId rd_createSubid
Definition: rel.h:110
#define RELKIND_PARTITIONED_TABLE
Definition: pg_class.h:168
#define InvalidBackendId
Definition: backendid.h:23
void * palloc0(Size size)
Definition: mcxt.c:877
void RelationIncrementReferenceCount(Relation rel)
Definition: relcache.c:2131
bool IsSharedRelation(Oid relationId)
Definition: catalog.c:220
TupleDesc rd_att
Definition: rel.h:115
bool IsSystemNamespace(Oid namespaceId)
Definition: catalog.c:163
#define InvalidOid
Definition: postgres_ext.h:36
#define RelationCacheInsert(RELATION, replace_allowed)
Definition: relcache.c:180
#define CLASS_TUPLE_SIZE
Definition: pg_class.h:87
BackendId rd_backend
Definition: rel.h:89
#define Assert(condition)
Definition: c.h:681
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:642
TupleConstr * constr
Definition: tupdesc.h:78
void CreateCacheMemoryContext(void)
Definition: catcache.c:636
#define BOOTSTRAP_SUPERUSERID
Definition: pg_authid.h:102
#define InvalidSubTransactionId
Definition: c.h:397
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
int rd_refcnt
Definition: rel.h:88
int tdrefcount
Definition: tupdesc.h:77
int i
#define elog
Definition: elog.h:219
#define RELPERSISTENCE_TEMP
Definition: pg_class.h:172
#define RELKIND_RELATION
Definition: pg_class.h:160
#define RelationGetRelid(relation)
Definition: rel.h:416
void RelationMapUpdateMap(Oid relationId, Oid fileNode, bool shared, bool immediate)
Definition: relmapper.c:248
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static void RelationBuildPartitionKey ( Relation  relation)
static

Definition at line 827 of file relcache.c.

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate(), Anum_pg_partitioned_table_partclass, Anum_pg_partitioned_table_partcollation, Anum_pg_partitioned_table_partexprs, Assert, BTORDER_PROC, CacheMemoryContext, CLAOID, copy_partition_key(), DatumGetPointer, elog, ERROR, eval_const_expressions(), exprCollation(), exprType(), exprTypmod(), fix_opfuncids(), fmgr_info(), get_opfamily_proc(), get_typlenbyvalalign(), GETSTRUCT, HeapTupleIsValid, i, lfirst, list_head(), MemoryContextSwitchTo(), ObjectIdGetDatum, OidIsValid, palloc0(), PartitionKeyData::partattrs, PartitionKeyData::partcollation, PartitionKeyData::partexprs, PartitionKeyData::partnatts, PartitionKeyData::partopcintype, PartitionKeyData::partopfamily, PARTRELID, PartitionKeyData::partsupfunc, PartitionKeyData::parttypalign, PartitionKeyData::parttypbyval, PartitionKeyData::parttypcoll, PartitionKeyData::parttypid, PartitionKeyData::parttyplen, PartitionKeyData::parttypmod, pfree(), RelationData::rd_att, RelationData::rd_partkey, RelationData::rd_partkeycxt, RelationGetRelationName, RelationGetRelid, ReleaseSysCache(), SearchSysCache1(), PartitionKeyData::strategy, stringToNode(), SysCacheGetAttr(), TextDatumGetCString, TupleDescAttr, and oidvector::values.

Referenced by RelationBuildDesc(), and RelationCacheInitializePhase3().

828 {
830  HeapTuple tuple;
831  bool isnull;
832  int i;
833  PartitionKey key;
834  AttrNumber *attrs;
835  oidvector *opclass;
836  oidvector *collation;
837  ListCell *partexprs_item;
838  Datum datum;
839  MemoryContext partkeycxt,
840  oldcxt;
841 
842  tuple = SearchSysCache1(PARTRELID,
844 
845  /*
846  * The following happens when we have created our pg_class entry but not
847  * the pg_partitioned_table entry yet.
848  */
849  if (!HeapTupleIsValid(tuple))
850  return;
851 
852  key = (PartitionKey) palloc0(sizeof(PartitionKeyData));
853 
854  /* Fixed-length attributes */
855  form = (Form_pg_partitioned_table) GETSTRUCT(tuple);
856  key->strategy = form->partstrat;
857  key->partnatts = form->partnatts;
858 
859  /*
860  * We can rely on the first variable-length attribute being mapped to the
861  * relevant field of the catalog's C struct, because all previous
862  * attributes are non-nullable and fixed-length.
863  */
864  attrs = form->partattrs.values;
865 
866  /* But use the hard way to retrieve further variable-length attributes */
867  /* Operator class */
868  datum = SysCacheGetAttr(PARTRELID, tuple,
870  Assert(!isnull);
871  opclass = (oidvector *) DatumGetPointer(datum);
872 
873  /* Collation */
874  datum = SysCacheGetAttr(PARTRELID, tuple,
876  Assert(!isnull);
877  collation = (oidvector *) DatumGetPointer(datum);
878 
879  /* Expressions */
880  datum = SysCacheGetAttr(PARTRELID, tuple,
882  if (!isnull)
883  {
884  char *exprString;
885  Node *expr;
886 
887  exprString = TextDatumGetCString(datum);
888  expr = stringToNode(exprString);
889  pfree(exprString);
890 
891  /*
892  * Run the expressions through const-simplification since the planner
893  * will be comparing them to similarly-processed qual clause operands,
894  * and may fail to detect valid matches without this step. We don't
895  * need to bother with canonicalize_qual() though, because partition
896  * expressions are not full-fledged qualification clauses.
897  */
898  expr = eval_const_expressions(NULL, (Node *) expr);
899 
900  /* May as well fix opfuncids too */
901  fix_opfuncids((Node *) expr);
902  key->partexprs = (List *) expr;
903  }
904 
905  key->partattrs = (AttrNumber *) palloc0(key->partnatts * sizeof(AttrNumber));
906  key->partopfamily = (Oid *) palloc0(key->partnatts * sizeof(Oid));
907  key->partopcintype = (Oid *) palloc0(key->partnatts * sizeof(Oid));
908  key->partsupfunc = (FmgrInfo *) palloc0(key->partnatts * sizeof(FmgrInfo));
909 
910  key->partcollation = (Oid *) palloc0(key->partnatts * sizeof(Oid));
911 
912  /* Gather type and collation info as well */
913  key->parttypid = (Oid *) palloc0(key->partnatts * sizeof(Oid));
914  key->parttypmod = (int32 *) palloc0(key->partnatts * sizeof(int32));
915  key->parttyplen = (int16 *) palloc0(key->partnatts * sizeof(int16));
916  key->parttypbyval = (bool *) palloc0(key->partnatts * sizeof(bool));
917  key->parttypalign = (char *) palloc0(key->partnatts * sizeof(char));
918  key->parttypcoll = (Oid *) palloc0(key->partnatts * sizeof(Oid));
919 
920  /* Copy partattrs and fill other per-attribute info */
921  memcpy(key->partattrs, attrs, key->partnatts * sizeof(int16));
922  partexprs_item = list_head(key->partexprs);
923  for (i = 0; i < key->partnatts; i++)
924  {
925  AttrNumber attno = key->partattrs[i];
926  HeapTuple opclasstup;
927  Form_pg_opclass opclassform;
928  Oid funcid;
929 
930  /* Collect opfamily information */
931  opclasstup = SearchSysCache1(CLAOID,
932  ObjectIdGetDatum(opclass->values[i]));
933  if (!HeapTupleIsValid(opclasstup))
934  elog(ERROR, "cache lookup failed for opclass %u", opclass->values[i]);
935 
936  opclassform = (Form_pg_opclass) GETSTRUCT(opclasstup);
937  key->partopfamily[i] = opclassform->opcfamily;
938  key->partopcintype[i] = opclassform->opcintype;
939 
940  /*
941  * A btree support function covers the cases of list and range methods
942  * currently supported.
943  */
944  funcid = get_opfamily_proc(opclassform->opcfamily,
945  opclassform->opcintype,
946  opclassform->opcintype,
947  BTORDER_PROC);
948  if (!OidIsValid(funcid)) /* should not happen */
949  elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
950  BTORDER_PROC, opclassform->opcintype, opclassform->opcintype,
951  opclassform->opcfamily);
952 
953  fmgr_info(funcid, &key->partsupfunc[i]);
954 
955  /* Collation */
956  key->partcollation[i] = collation->values[i];
957 
958  /* Collect type information */
959  if (attno != 0)
960  {
961  Form_pg_attribute att = TupleDescAttr(relation->rd_att, attno - 1);
962 
963  key->parttypid[i] = att->atttypid;
964  key->parttypmod[i] = att->atttypmod;
965  key->parttypcoll[i] = att->attcollation;
966  }
967  else
968  {
969  key->parttypid[i] = exprType(lfirst(partexprs_item));
970  key->parttypmod[i] = exprTypmod(lfirst(partexprs_item));
971  key->parttypcoll[i] = exprCollation(lfirst(partexprs_item));
972  }
974  &key->parttyplen[i],
975  &key->parttypbyval[i],
976  &key->parttypalign[i]);
977 
978  ReleaseSysCache(opclasstup);
979  }
980 
981  ReleaseSysCache(tuple);
982 
983  /* Success --- now copy to the cache memory */
985  RelationGetRelationName(relation),
987  relation->rd_partkeycxt = partkeycxt;
988  oldcxt = MemoryContextSwitchTo(relation->rd_partkeycxt);
989  relation->rd_partkey = copy_partition_key(key);
990  MemoryContextSwitchTo(oldcxt);
991 }
signed short int16
Definition: c.h:245
Definition: c.h:472
Definition: fmgr.h:56
void * stringToNode(char *str)
Definition: read.c:38
#define BTORDER_PROC
Definition: nbtree.h:229
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid * partopfamily
Definition: rel.h:61
FmgrInfo * partsupfunc
Definition: rel.h:63
#define Anum_pg_partitioned_table_partexprs
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:276
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2021
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1582
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:175
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:510
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2429
List * partexprs
Definition: rel.h:58
char strategy
Definition: rel.h:54
unsigned int Oid
Definition: postgres_ext.h:31
FormData_pg_partitioned_table * Form_pg_partitioned_table
#define OidIsValid(objectId)
Definition: c.h:532
signed int int32
Definition: c.h:246
void pfree(void *pointer)
Definition: mcxt.c:949
Oid * parttypcoll
Definition: rel.h:74
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:122
struct PartitionKeyData * rd_partkey
Definition: rel.h:129
#define Anum_pg_partitioned_table_partcollation
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:480
#define RelationGetRelationName(relation)
Definition: rel.h:436
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
Oid * parttypid
Definition: rel.h:69
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
Oid * partcollation
Definition: rel.h:66
#define TextDatumGetCString(d)
Definition: builtins.h:92
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
void * palloc0(Size size)
Definition: mcxt.c:877
AttrNumber * partattrs
Definition: rel.h:56
uintptr_t Datum
Definition: postgres.h:372
int16 partnatts
Definition: rel.h:55
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
char * parttypalign
Definition: rel.h:73
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
TupleDesc rd_att
Definition: rel.h:115
int32 * parttypmod
Definition: rel.h:70
bool * parttypbyval
Definition: rel.h:72
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:681
#define lfirst(lc)
Definition: pg_list.h:106
int16 * parttyplen
Definition: rel.h:71
MemoryContext rd_partkeycxt
Definition: rel.h:128
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:744
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:720
#define DatumGetPointer(X)
Definition: postgres.h:555
struct PartitionKeyData * PartitionKey
Definition: rel.h:77
static PartitionKey copy_partition_key(PartitionKey fromkey)
Definition: relcache.c:999
Oid * partopcintype
Definition: rel.h:62
int i
#define elog
Definition: elog.h:219
#define Anum_pg_partitioned_table_partclass
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:68
Definition: pg_list.h:45
int16 AttrNumber
Definition: attnum.h:21
#define RelationGetRelid(relation)
Definition: rel.h:416
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static void RelationBuildRuleLock ( Relation  relation)
static

Definition at line 659 of file relcache.c.

References AccessShareLock, RewriteRule::actions, ALLOCSET_SMALL_SIZES, AllocSetContextCreate(), Anum_pg_rewrite_ev_action, Anum_pg_rewrite_ev_class, Anum_pg_rewrite_ev_qual, Assert, BTEqualStrategyNumber, CacheMemoryContext, RewriteRule::enabled, RewriteRule::event, GETSTRUCT, heap_close, heap_getattr, heap_open(), HeapTupleGetOid, HeapTupleIsValid, RewriteRule::isInstead, MemoryContextAlloc(), MemoryContextDelete(), MemoryContextSwitchTo(), RuleLock::numLocks, ObjectIdGetDatum, pfree(), RewriteRule::qual, RelationData::rd_rel, RelationData::rd_rules, RelationData::rd_rulescxt, RelationGetDescr, RelationGetRelationName, RelationGetRelid, repalloc(), RewriteRelationId, RewriteRelRulenameIndexId, RewriteRule::ruleId, RuleLock::rules, rules, ScanKeyInit(), setRuleCheckAsUser(), stringToNode(), systable_beginscan(), systable_endscan(), systable_getnext(), and TextDatumGetCString.

Referenced by RelationBuildDesc(), and RelationCacheInitializePhase3().

660 {
661  MemoryContext rulescxt;
662  MemoryContext oldcxt;
663  HeapTuple rewrite_tuple;
664  Relation rewrite_desc;
665  TupleDesc rewrite_tupdesc;
666  SysScanDesc rewrite_scan;
667  ScanKeyData key;
668  RuleLock *rulelock;
669  int numlocks;
670  RewriteRule **rules;
671  int maxlocks;
672 
673  /*
674  * Make the private context. Assume it'll not contain much data.
675  */
677  RelationGetRelationName(relation),
679  relation->rd_rulescxt = rulescxt;
680 
681  /*
682  * allocate an array to hold the rewrite rules (the array is extended if
683  * necessary)
684  */
685  maxlocks = 4;
686  rules = (RewriteRule **)
687  MemoryContextAlloc(rulescxt, sizeof(RewriteRule *) * maxlocks);
688  numlocks = 0;
689 
690  /*
691  * form a scan key
692  */
693  ScanKeyInit(&key,
695  BTEqualStrategyNumber, F_OIDEQ,
697 
698  /*
699  * open pg_rewrite and begin a scan
700  *
701  * Note: since we scan the rules using RewriteRelRulenameIndexId, we will
702  * be reading the rules in name order, except possibly during
703  * emergency-recovery operations (ie, IgnoreSystemIndexes). This in turn
704  * ensures that rules will be fired in name order.
705  */
707  rewrite_tupdesc = RelationGetDescr(rewrite_desc);
708  rewrite_scan = systable_beginscan(rewrite_desc,
710  true, NULL,
711  1, &key);
712 
713  while (HeapTupleIsValid(rewrite_tuple = systable_getnext(rewrite_scan)))
714  {
715  Form_pg_rewrite rewrite_form = (Form_pg_rewrite) GETSTRUCT(rewrite_tuple);
716  bool isnull;
717  Datum rule_datum;
718  char *rule_str;
719  RewriteRule *rule;
720 
721  rule = (RewriteRule *) MemoryContextAlloc(rulescxt,
722  sizeof(RewriteRule));
723 
724  rule->ruleId = HeapTupleGetOid(rewrite_tuple);
725 
726  rule->event = rewrite_form->ev_type - '0';
727  rule->enabled = rewrite_form->ev_enabled;
728  rule->isInstead = rewrite_form->is_instead;
729 
730  /*
731  * Must use heap_getattr to fetch ev_action and ev_qual. Also, the
732  * rule strings are often large enough to be toasted. To avoid
733  * leaking memory in the caller's context, do the detoasting here so
734  * we can free the detoasted version.
735  */
736  rule_datum = heap_getattr(rewrite_tuple,
738  rewrite_tupdesc,
739  &isnull);
740  Assert(!isnull);
741  rule_str = TextDatumGetCString(rule_datum);
742  oldcxt = MemoryContextSwitchTo(rulescxt);
743  rule->actions = (List *) stringToNode(rule_str);
744  MemoryContextSwitchTo(oldcxt);
745  pfree(rule_str);
746 
747  rule_datum = heap_getattr(rewrite_tuple,
749  rewrite_tupdesc,
750  &isnull);
751  Assert(!isnull);
752  rule_str = TextDatumGetCString(rule_datum);
753  oldcxt = MemoryContextSwitchTo(rulescxt);
754  rule->qual = (Node *) stringToNode(rule_str);
755  MemoryContextSwitchTo(oldcxt);
756  pfree(rule_str);
757 
758  /*
759  * We want the rule's table references to be checked as though by the
760  * table owner, not the user referencing the rule. Therefore, scan
761  * through the rule's actions and set the checkAsUser field on all
762  * rtable entries. We have to look at the qual as well, in case it
763  * contains sublinks.
764  *
765  * The reason for doing this when the rule is loaded, rather than when
766  * it is stored, is that otherwise ALTER TABLE OWNER would have to
767  * grovel through stored rules to update checkAsUser fields. Scanning
768  * the rule tree during load is relatively cheap (compared to
769  * constructing it in the first place), so we do it here.
770  */
771  setRuleCheckAsUser((Node *) rule->actions, relation->rd_rel->relowner);
772  setRuleCheckAsUser(rule->qual, relation->rd_rel->relowner);
773 
774  if (numlocks >= maxlocks)
775  {
776  maxlocks *= 2;
777  rules = (RewriteRule **)
778  repalloc(rules, sizeof(RewriteRule *) * maxlocks);
779  }
780  rules[numlocks++] = rule;
781  }
782 
783  /*
784  * end the scan and close the attribute relation
785  */
786  systable_endscan(rewrite_scan);
787  heap_close(rewrite_desc, AccessShareLock);
788 
789  /*
790  * there might not be any rules (if relhasrules is out-of-date)
791  */
792  if (numlocks == 0)
793  {
794  relation->rd_rules = NULL;
795  relation->rd_rulescxt = NULL;
796  MemoryContextDelete(rulescxt);
797  return;
798  }
799 
800  /*
801  * form a RuleLock and insert into relation
802  */
803  rulelock = (RuleLock *) MemoryContextAlloc(rulescxt, sizeof(RuleLock));
804  rulelock->numLocks = numlocks;
805  rulelock->rules = rules;
806 
807  relation->rd_rules = rulelock;
808 }
void * stringToNode(char *str)
Definition: read.c:38
Node * qual
Definition: prs2lock.h:28
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
int numLocks
Definition: prs2lock.h:42
void setRuleCheckAsUser(Node *node, Oid userid)
#define Anum_pg_rewrite_ev_action
Definition: pg_rewrite.h:66
#define RelationGetDescr(relation)
Definition: rel.h:428
#define RewriteRelRulenameIndexId
Definition: indexing.h:223
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:175
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:510
#define Anum_pg_rewrite_ev_class
Definition: pg_rewrite.h:61
MemoryContext rd_rulescxt
Definition: rel.h:119
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:114
bool isInstead
Definition: prs2lock.h:31
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
Definition: localtime.c:78
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
void pfree(void *pointer)
Definition: mcxt.c:949
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
CmdType event
Definition: prs2lock.h:27
static struct rule * rules
Definition: zic.c:269
#define RelationGetRelationName(relation)
Definition: rel.h:436
RewriteRule ** rules
Definition: prs2lock.h:43
List * actions
Definition: prs2lock.h:29
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:769
#define TextDatumGetCString(d)
Definition: builtins.h:92
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
#define RewriteRelationId
Definition: pg_rewrite.h:32
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:681
RuleLock * rd_rules
Definition: rel.h:118
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:962
FormData_pg_rewrite * Form_pg_rewrite
Definition: pg_rewrite.h:53
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:706
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:416
Oid ruleId
Definition: prs2lock.h:26
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define Anum_pg_rewrite_ev_qual
Definition: pg_rewrite.h:65
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
char enabled
Definition: prs2lock.h:30
static void RelationBuildTupleDesc ( Relation  relation)
static

Definition at line 487 of file relcache.c.

References AccessShareLock, attrDefault::adbin, attrDefault::adnum, Anum_pg_attribute_attnum, Anum_pg_attribute_attrelid, Assert, AttrDefaultFetch(), ATTRIBUTE_FIXED_PART_SIZE, AttributeRelationId, AttributeRelidNumIndexId, BTEqualStrategyNumber, BTGreaterStrategyNumber, CacheMemoryContext, tupleConstr::check, CheckConstraintFetch(), tupleDesc::constr, criticalRelcachesBuilt, tupleConstr::defval, elog, ERROR, GETSTRUCT, tupleConstr::has_not_null, heap_close, heap_open(), HeapTupleIsValid, i, Int16GetDatum, MemoryContextAlloc(), MemoryContextAllocZero(), tupleConstr::num_check, tupleConstr::num_defval, ObjectIdGetDatum, pfree(), RelationData::rd_att, RelationData::rd_rel, RelationGetRelationName, RelationGetRelid, repalloc(), ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), tupleDesc::tdhasoid, tupleDesc::tdtypeid, tupleDesc::tdtypmod, and TupleDescAttr.

Referenced by RelationBuildDesc().

488 {
489  HeapTuple pg_attribute_tuple;
490  Relation pg_attribute_desc;
491  SysScanDesc pg_attribute_scan;
492  ScanKeyData skey[2];
493  int need;
494  TupleConstr *constr;
495  AttrDefault *attrdef = NULL;
496  int ndef = 0;
497 
498  /* copy some fields from pg_class row to rd_att */
499  relation->rd_att->tdtypeid = relation->rd_rel->reltype;
500  relation->rd_att->tdtypmod = -1; /* unnecessary, but... */
501  relation->rd_att->tdhasoid = relation->rd_rel->relhasoids;
502 
504  sizeof(TupleConstr));
505  constr->has_not_null = false;
506 
507  /*
508  * Form a scan key that selects only user attributes (attnum > 0).
509  * (Eliminating system attribute rows at the index level is lots faster
510  * than fetching them.)
511  */
512  ScanKeyInit(&skey[0],
514  BTEqualStrategyNumber, F_OIDEQ,
516  ScanKeyInit(&skey[1],
518  BTGreaterStrategyNumber, F_INT2GT,
519  Int16GetDatum(0));
520 
521  /*
522  * Open pg_attribute and begin a scan. Force heap scan if we haven't yet
523  * built the critical relcache entries (this includes initdb and startup
524  * without a pg_internal.init file).
525  */
526  pg_attribute_desc = heap_open(AttributeRelationId, AccessShareLock);
527  pg_attribute_scan = systable_beginscan(pg_attribute_desc,
530  NULL,
531  2, skey);
532 
533  /*
534  * add attribute data to relation->rd_att
535  */
536  need = relation->rd_rel->relnatts;
537 
538  while (HeapTupleIsValid(pg_attribute_tuple = systable_getnext(pg_attribute_scan)))
539  {
540  Form_pg_attribute attp;
541 
542  attp = (Form_pg_attribute) GETSTRUCT(pg_attribute_tuple);
543 
544  if (attp->attnum <= 0 ||
545  attp->attnum > relation->rd_rel->relnatts)
546  elog(ERROR, "invalid attribute number %d for %s",
547  attp->attnum, RelationGetRelationName(relation));
548 
549  memcpy(TupleDescAttr(relation->rd_att, attp->attnum - 1),
550  attp,
552 
553  /* Update constraint/default info */
554  if (attp->attnotnull)
555  constr->has_not_null = true;
556 
557  if (attp->atthasdef)
558  {
559  if (attrdef == NULL)
560  attrdef = (AttrDefault *)
562  relation->rd_rel->relnatts *
563  sizeof(AttrDefault));
564  attrdef[ndef].adnum = attp->attnum;
565  attrdef[ndef].adbin = NULL;
566  ndef++;
567  }
568  need--;
569  if (need == 0)
570  break;
571  }
572 
573  /*
574  * end the scan and close the attribute relation
575  */
576  systable_endscan(pg_attribute_scan);
577  heap_close(pg_attribute_desc, AccessShareLock);
578 
579  if (need != 0)
580  elog(ERROR, "catalog is missing %d attribute(s) for relid %u",
581  need, RelationGetRelid(relation));
582 
583  /*
584  * The attcacheoff values we read from pg_attribute should all be -1
585  * ("unknown"). Verify this if assert checking is on. They will be
586  * computed when and if needed during tuple access.
587  */
588 #ifdef USE_ASSERT_CHECKING
589  {
590  int i;
591 
592  for (i = 0; i < relation->rd_rel->relnatts; i++)
593  Assert(TupleDescAttr(relation->rd_att, i)->attcacheoff == -1);
594  }
595 #endif
596 
597  /*
598  * However, we can easily set the attcacheoff value for the first
599  * attribute: it must be zero. This eliminates the need for special cases
600  * for attnum=1 that used to exist in fastgetattr() and index_getattr().
601  */
602  if (relation->rd_rel->relnatts > 0)
603  TupleDescAttr(relation->rd_att, 0)->attcacheoff = 0;
604 
605  /*
606  * Set up constraint/default info
607  */
608  if (constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks)
609  {
610  relation->rd_att->constr = constr;
611 
612  if (ndef > 0) /* DEFAULTs */
613  {
614  if (ndef < relation->rd_rel->relnatts)
615  constr->defval = (AttrDefault *)
616  repalloc(attrdef, ndef * sizeof(AttrDefault));
617  else
618  constr->defval = attrdef;
619  constr->num_defval = ndef;
620  AttrDefaultFetch(relation);
621  }
622  else
623  constr->num_defval = 0;
624 
625  if (relation->rd_rel->relchecks > 0) /* CHECKs */
626  {
627  constr->num_check = relation->rd_rel->relchecks;
628  constr->check = (ConstrCheck *)
630  constr->num_check * sizeof(ConstrCheck));
631  CheckConstraintFetch(relation);
632  }
633  else
634  constr->num_check = 0;
635  }
636  else
637  {
638  pfree(constr);
639  relation->rd_att->constr = NULL;
640  }
641 }
#define AttributeRelidNumIndexId
Definition: indexing.h:94
static void AttrDefaultFetch(Relation relation)
Definition: relcache.c:4026
#define Anum_pg_attribute_attrelid
Definition: pg_attribute.h:195
Oid tdtypeid
Definition: tupdesc.h:74
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
bool tdhasoid
Definition: tupdesc.h:76
#define Anum_pg_attribute_attnum
Definition: pg_attribute.h:200
ConstrCheck * check
Definition: tupdesc.h:40
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
#define Int16GetDatum(X)
Definition: postgres.h:457
#define AccessShareLock
Definition: lockdefs.h:36
#define AttributeRelationId
Definition: pg_attribute.h:33
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:114
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
int32 tdtypmod
Definition: tupdesc.h:75
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
void pfree(void *pointer)
Definition: mcxt.c:949
AttrDefault * defval
Definition: tupdesc.h:39
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
AttrNumber adnum
Definition: tupdesc.h:24
#define RelationGetRelationName(relation)
Definition: rel.h:436
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
char * adbin
Definition: tupdesc.h:25
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:179
bool has_not_null
Definition: tupdesc.h:43
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
TupleDesc rd_att
Definition: rel.h:115
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:741
uint16 num_defval
Definition: tupdesc.h:41
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:681
static void CheckConstraintFetch(Relation relation)
Definition: relcache.c:4100
TupleConstr * constr
Definition: tupdesc.h:78
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:962
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:706
int i
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
uint16 num_check
Definition: tupdesc.h:42
#define elog
Definition: elog.h:219
bool criticalRelcachesBuilt
Definition: relcache.c:129
#define RelationGetRelid(relation)
Definition: rel.h:416
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void RelationCacheInitFilePostInvalidate ( void  )

Definition at line 6084 of file relcache.c.

References LWLockRelease().

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

6085 {
6086  LWLockRelease(RelCacheInitLock);
6087 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
void RelationCacheInitFilePreInvalidate ( void  )

Definition at line 6058 of file relcache.c.

References DatabasePath, ereport, errcode_for_file_access(), errmsg(), ERROR, LW_EXCLUSIVE, LWLockAcquire(), MAXPGPATH, RELCACHE_INIT_FILENAME, and snprintf().

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

6059 {
6060  char initfilename[MAXPGPATH];
6061 
6062  snprintf(initfilename, sizeof(initfilename), "%s/%s",
6064 
6065  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6066 
6067  if (unlink(initfilename) < 0)
6068  {
6069  /*
6070  * The file might not be there if no backend has been started since
6071  * the last removal. But complain about failures other than ENOENT.
6072  * Fortunately, it's not too late to abort the transaction if we can't
6073  * get rid of the would-be-obsolete init file.
6074  */
6075  if (errno != ENOENT)
6076  ereport(ERROR,
6078  errmsg("could not remove cache file \"%s\": %m",
6079  initfilename)));
6080  }
6081 }
#define RELCACHE_INIT_FILENAME
Definition: relcache.c:93
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define ERROR
Definition: elog.h:43
#define MAXPGPATH
int errcode_for_file_access(void)
Definition: elog.c:598
#define ereport(elevel, rest)
Definition: elog.h:122
char * DatabasePath
Definition: globals.c:85
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
int errmsg(const char *fmt,...)
Definition: elog.c:797
void RelationCacheInitFileRemove ( void  )

Definition at line 6099 of file relcache.c.

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

Referenced by StartupXLOG().

6100 {
6101  const char *tblspcdir = "pg_tblspc";
6102  DIR *dir;
6103  struct dirent *de;
6104  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6105 
6106  /*
6107  * We zap the shared cache file too. In theory it can't get out of sync
6108  * enough to be a problem, but in data-corruption cases, who knows ...
6109  */
6110  snprintf(path, sizeof(path), "global/%s",
6112  unlink_initfile(path);
6113 
6114  /* Scan everything in the default tablespace */
6116 
6117  /* Scan the tablespace link directory to find non-default tablespaces */
6118  dir = AllocateDir(tblspcdir);
6119  if (dir == NULL)
6120  {
6121  elog(LOG, "could not open tablespace link directory \"%s\": %m",
6122  tblspcdir);
6123  return;
6124  }
6125 
6126  while ((de = ReadDir(dir, tblspcdir)) != NULL)
6127  {
6128  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6129  {
6130  /* Scan the tablespace dir for per-database dirs */
6131  snprintf(path, sizeof(path), "%s/%s/%s",
6132  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6134  }
6135  }
6136 
6137  FreeDir(dir);
6138 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6142
#define RELCACHE_INIT_FILENAME
Definition: relcache.c:93
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2367
static void unlink_initfile(const char *initfilename)
Definition: relcache.c:6172
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2433
#define TABLESPACE_VERSION_DIRECTORY
Definition: catalog.h:26
char d_name[MAX_PATH]
Definition: dirent.h:14
#define elog
Definition: elog.h:219
int FreeDir(DIR *dir)
Definition: fd.c:2476
static void RelationCacheInitFileRemoveInDir ( const char *  tblspcpath)
static

Definition at line 6142 of file relcache.c.

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

Referenced by RelationCacheInitFileRemove().

6143 {
6144  DIR *dir;
6145  struct dirent *de;
6146  char initfilename[MAXPGPATH * 2];
6147 
6148  /* Scan the tablespace directory to find per-database directories */
6149  dir = AllocateDir(tblspcpath);
6150  if (dir == NULL)
6151  {
6152  elog(LOG, "could not open tablespace directory \"%s\": %m",
6153  tblspcpath);
6154  return;
6155  }
6156 
6157  while ((de = ReadDir(dir, tblspcpath)) != NULL)
6158  {
6159  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6160  {
6161  /* Try to remove the init file in each database */
6162  snprintf(initfilename, sizeof(initfilename), "%s/%s/%s",
6163  tblspcpath, de->d_name, RELCACHE_INIT_FILENAME);
6164  unlink_initfile(initfilename);
6165  }
6166  }
6167 
6168  FreeDir(dir);
6169 }
#define RELCACHE_INIT_FILENAME
Definition: relcache.c:93
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2367
static void unlink_initfile(const char *initfilename)
Definition: relcache.c:6172
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2433
char d_name[MAX_PATH]
Definition: dirent.h:14
#define elog
Definition: elog.h:219
int FreeDir(DIR *dir)
Definition: fd.c:2476
void RelationCacheInitialize ( void  )

Definition at line 3539 of file relcache.c.

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

Referenced by InitPostgres().

3540 {
3541  HASHCTL ctl;
3542 
3543  /*
3544  * make sure cache memory context exists
3545  */
3546  if (!CacheMemoryContext)
3548 
3549  /*
3550  * create hashtable that indexes the relcache
3551  */
3552  MemSet(&ctl, 0, sizeof(ctl));
3553  ctl.keysize = sizeof(Oid);
3554  ctl.entrysize = sizeof(RelIdCacheEnt);
3555  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3556  &ctl, HASH_ELEM | HASH_BLOBS);
3557 
3558  /*
3559  * relation mapper needs to be initialized too
3560  */
3562 }
void RelationMapInitialize(void)
Definition: relmapper.c:562
#define HASH_ELEM
Definition: hsearch.h:87
struct relidcacheent RelIdCacheEnt
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:863
static HTAB * RelationIdCache
Definition: relcache.c:123
unsigned int Oid
Definition: postgres_ext.h:31
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Size keysize
Definition: hsearch.h:72
void CreateCacheMemoryContext(void)
Definition: catcache.c:636
#define INITRELCACHESIZE
Definition: relcache.c:3536
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void RelationCacheInitializePhase2 ( void  )

Definition at line 3576 of file relcache.c.

References AuthIdRelation_Rowtype_Id, AuthMemRelation_Rowtype_Id, CacheMemoryContext, DatabaseRelation_Rowtype_Id, Desc_pg_auth_members, Desc_pg_authid, Desc_pg_database, Desc_pg_shseclabel, Desc_pg_subscription, formrdesc(), IsBootstrapProcessingMode, load_relcache_init_file(), MemoryContextSwitchTo(), Natts_pg_auth_members, Natts_pg_authid, Natts_pg_database, Natts_pg_shseclabel, Natts_pg_subscription, RelationMapInitializePhase2(), SharedSecLabelRelation_Rowtype_Id, and SubscriptionRelation_Rowtype_Id.

Referenced by InitPostgres().

3577 {
3578  MemoryContext oldcxt;
3579 
3580  /*
3581  * relation mapper needs initialized too
3582  */
3584 
3585  /*
3586  * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3587  * nothing.
3588  */
3590  return;
3591 
3592  /*
3593  * switch to cache memory context
3594  */
3596 
3597  /*
3598  * Try to load the shared relcache cache file. If unsuccessful, bootstrap
3599  * the cache with pre-made descriptors for the critical shared catalogs.
3600  */
3601  if (!load_relcache_init_file(true))
3602  {
3603  formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
3605  formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
3607  formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
3609  formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
3611  formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
3613 
3614 #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
3615  }
3616 
3617  MemoryContextSwitchTo(oldcxt);
3618 }
static const FormData_pg_attribute Desc_pg_auth_members[Natts_pg_auth_members]
Definition: relcache.c:106
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5373
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, bool hasoids, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1895
#define SubscriptionRelation_Rowtype_Id
void RelationMapInitializePhase2(void)
Definition: relmapper.c:582
#define Natts_pg_database
Definition: pg_database.h:63
static const FormData_pg_attribute Desc_pg_authid[Natts_pg_authid]
Definition: relcache.c:105
static const FormData_pg_attribute Desc_pg_subscription[Natts_pg_subscription]
Definition: relcache.c:109
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define Natts_pg_auth_members
#define SharedSecLabelRelation_Rowtype_Id
Definition: pg_shseclabel.h:22
#define Natts_pg_subscription
#define AuthIdRelation_Rowtype_Id
Definition: pg_authid.h:43
#define AuthMemRelation_Rowtype_Id
static const FormData_pg_attribute Desc_pg_database[Natts_pg_database]
Definition: relcache.c:104
#define Natts_pg_shseclabel
Definition: pg_shseclabel.h:41
static const FormData_pg_attribute Desc_pg_shseclabel[Natts_pg_shseclabel]
Definition: relcache.c:108
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:367
#define DatabaseRelation_Rowtype_Id
Definition: pg_database.h:30
#define Natts_pg_authid
Definition: pg_authid.h:78
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void RelationCacheInitializePhase3 ( void  )

Definition at line 3635 of file relcache.c.

References AccessMethodProcedureIndexId, AccessMethodProcedureRelationId, Assert, AttributeRelation_Rowtype_Id, AttributeRelationId, AttributeRelidNumIndexId, AuthIdOidIndexId, AuthIdRelationId, AuthIdRolnameIndexId, AuthMemMemRoleIndexId, AuthMemRelationId, CacheMemoryContext, CLASS_TUPLE_SIZE, ClassOidIndexId, criticalRelcachesBuilt, criticalSharedRelcachesBuilt, DatabaseNameIndexId, DatabaseOidIndexId, DatabaseRelationId, 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, IndexRelationId, IndexRelidIndexId, InitCatalogCachePhase2(), InvalidOid, IsBootstrapProcessingMode, load_critical_index(), load_relcache_init_file(), MemoryContextSwitchTo(), Natts_pg_attribute, Natts_pg_class, Natts_pg_proc, Natts_pg_type, ObjectIdGetDatum, OpclassOidIndexId, OperatorClassRelationId, pfree(), ProcedureRelation_Rowtype_Id, RelationData::rd_att, RelationData::rd_options, RelationData::rd_partdesc, RelationData::rd_partkey, RelationData::rd_rel, RelationData::rd_rsdesc, RelationData::rd_rules, RelationBuildPartitionDesc(), RelationBuildPartitionKey(), RelationBuildRowSecurity(), RelationBuildRuleLock(), RelationBuildTriggers(), RelationDecrementReferenceCount(), RelationGetRelationName, RelationGetRelid, RelationIncrementReferenceCount(), RelationMapInitializePhase3(), RelationParseRelOptions(), RelationRelation_Rowtype_Id, RelationRelationId, relidcacheent::reldesc, ReleaseSysCache(), RELKIND_PARTITIONED_TABLE, RELOID, RewriteRelationId, RewriteRelRulenameIndexId, SearchSysCache1(), SharedSecLabelObjectIndexId, SharedSecLabelRelationId, status(), tupleDesc::tdhasoid, tupleDesc::tdtypeid, tupleDesc::tdtypmod, RelationData::trigdesc, TriggerRelationId, TriggerRelidNameIndexId, TypeRelation_Rowtype_Id, and write_relcache_init_file().

Referenced by InitPostgres().

3636 {
3638  RelIdCacheEnt *idhentry;
3639  MemoryContext oldcxt;
3640  bool needNewCacheFile = !criticalSharedRelcachesBuilt;
3641 
3642  /*
3643  * relation mapper needs initialized too
3644  */
3646 
3647  /*
3648  * switch to cache memory context
3649  */
3651 
3652  /*
3653  * Try to load the local relcache cache file. If unsuccessful, bootstrap
3654  * the cache with pre-made descriptors for the critical "nailed-in" system
3655  * catalogs.
3656  */
3657  if (IsBootstrapProcessingMode() ||
3658  !load_relcache_init_file(false))
3659  {
3660  needNewCacheFile = true;
3661 
3662  formrdesc("pg_class", RelationRelation_Rowtype_Id, false,
3663  true, Natts_pg_class, Desc_pg_class);
3664  formrdesc("pg_attribute", AttributeRelation_Rowtype_Id, false,
3666  formrdesc("pg_proc", ProcedureRelation_Rowtype_Id, false,
3667  true, Natts_pg_proc, Desc_pg_proc);
3668  formrdesc("pg_type", TypeRelation_Rowtype_Id, false,
3669  true, Natts_pg_type, Desc_pg_type);
3670 
3671 #define NUM_CRITICAL_LOCAL_RELS 4 /* fix if you change list above */
3672  }
3673 
3674  MemoryContextSwitchTo(oldcxt);
3675 
3676  /* In bootstrap mode, the faked-up formrdesc info is all we'll have */
3678  return;
3679 
3680  /*
3681  * If we didn't get the critical system indexes loaded into relcache, do
3682  * so now. These are critical because the catcache and/or opclass cache
3683  * depend on them for fetches done during relcache load. Thus, we have an
3684  * infinite-recursion problem. We can break the recursion by doing
3685  * heapscans instead of indexscans at certain key spots. To avoid hobbling
3686  * performance, we only want to do that until we have the critical indexes
3687  * loaded into relcache. Thus, the flag criticalRelcachesBuilt is used to
3688  * decide whether to do heapscan or indexscan at the key spots, and we set
3689  * it true after we've loaded the critical indexes.
3690  *
3691  * The critical indexes are marked as "nailed in cache", partly to make it
3692  * easy for load_relcache_init_file to count them, but mainly because we
3693  * cannot flush and rebuild them once we've set criticalRelcachesBuilt to
3694  * true. (NOTE: perhaps it would be possible to reload them by
3695  * temporarily setting criticalRelcachesBuilt to false again. For now,
3696  * though, we just nail 'em in.)
3697  *
3698  * RewriteRelRulenameIndexId and TriggerRelidNameIndexId are not critical
3699  * in the same way as the others, because the critical catalogs don't
3700  * (currently) have any rules or triggers, and so these indexes can be
3701  * rebuilt without inducing recursion. However they are used during
3702  * relcache load when a rel does have rules or triggers, so we choose to
3703  * nail them for performance reasons.
3704  */
3706  {
3712  IndexRelationId);
3721 
3722 #define NUM_CRITICAL_LOCAL_INDEXES 7 /* fix if you change list above */
3723 
3724  criticalRelcachesBuilt = true;
3725  }
3726 
3727  /*
3728  * Process critical shared indexes too.
3729  *
3730  * DatabaseNameIndexId isn't critical for relcache loading, but rather for
3731  * initial lookup of MyDatabaseId, without which we'll never find any
3732  * non-shared catalogs at all. Autovacuum calls InitPostgres with a
3733  * database OID, so it instead depends on DatabaseOidIndexId. We also
3734  * need to nail up some indexes on pg_authid and pg_auth_members for use
3735  * during client authentication. SharedSecLabelObjectIndexId isn't
3736  * critical for the core system, but authentication hooks might be
3737  * interested in it.
3738  */
3740  {
3753 
3754 #define NUM_CRITICAL_SHARED_INDEXES 6 /* fix if you change list above */
3755 
3757  }
3758 
3759  /*
3760  * Now, scan all the relcache entries and update anything that might be
3761  * wrong in the results from formrdesc or the relcache cache file. If we
3762  * faked up relcache entries using formrdesc, then read the real pg_class
3763  * rows and replace the fake entries with them. Also, if any of the
3764  * relcache entries have rules, triggers, or security policies, load that
3765  * info the hard way since it isn't recorded in the cache file.
3766  *
3767  * Whenever we access the catalogs to read data, there is a possibility of
3768  * a shared-inval cache flush causing relcache entries to be removed.
3769  * Since hash_seq_search only guarantees to still work after the *current*
3770  * entry is removed, it's unsafe to continue the hashtable scan afterward.
3771  * We handle this by restarting the scan from scratch after each access.
3772  * This is theoretically O(N^2), but the number of entries that actually
3773  * need to be fixed is small enough that it doesn't matter.
3774  */
3775  hash_seq_init(&status, RelationIdCache);
3776 
3777  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3778  {
3779  Relation relation = idhentry->reldesc;
3780  bool restart = false;
3781 
3782  /*
3783  * Make sure *this* entry doesn't get flushed while we work with it.
3784  */
3786 
3787  /*
3788  * If it's a faked-up entry, read the real pg_class tuple.
3789  */
3790  if (relation->rd_rel->relowner == InvalidOid)
3791  {
3792  HeapTuple htup;
3793  Form_pg_class relp;
3794 
3795  htup = SearchSysCache1(RELOID,
3796  ObjectIdGetDatum(RelationGetRelid(relation)));
3797  if (!HeapTupleIsValid(htup))
3798  elog(FATAL, "cache lookup failed for relation %u",
3799  RelationGetRelid(relation));
3800  relp = (Form_pg_class) GETSTRUCT(htup);
3801 
3802  /*
3803  * Copy tuple to relation->rd_rel. (See notes in
3804  * AllocateRelationDesc())
3805  */
3806  memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
3807 
3808  /* Update rd_options while we have the tuple */
3809  if (relation->rd_options)
3810  pfree(relation->rd_options);
3811  RelationParseRelOptions(relation, htup);
3812 
3813  /*
3814  * Check the values in rd_att were set up correctly. (We cannot
3815  * just copy them over now: formrdesc must have set up the rd_att
3816  * data correctly to start with, because it may already have been
3817  * copied into one or more catcache entries.)
3818  */
3819  Assert(relation->rd_att->tdtypeid == relp->reltype);
3820  Assert(relation->rd_att->tdtypmod == -1);
3821  Assert(relation->rd_att->tdhasoid == relp->relhasoids);
3822 
3823  ReleaseSysCache(htup);
3824 
3825  /* relowner had better be OK now, else we'll loop forever */
3826  if (relation->rd_rel->relowner == InvalidOid)
3827  elog(ERROR, "invalid relowner in pg_class entry for \"%s\"",
3828  RelationGetRelationName(relation));
3829 
3830  restart = true;
3831  }
3832 
3833  /*
3834  * Fix data that isn't saved in relcache cache file.
3835  *
3836  * relhasrules or relhastriggers could possibly be wrong or out of
3837  * date. If we don't actually find any rules or triggers, clear the
3838  * local copy of the flag so that we don't get into an infinite loop
3839  * here. We don't make any attempt to fix the pg_class entry, though.
3840  */
3841  if (relation->rd_rel->relhasrules && relation->rd_rules == NULL)
3842  {
3843  RelationBuildRuleLock(relation);
3844  if (relation->rd_rules == NULL)
3845  relation->rd_rel->relhasrules = false;
3846  restart = true;
3847  }
3848  if (relation->rd_rel->relhastriggers && relation->trigdesc == NULL)
3849  {
3850  RelationBuildTriggers(relation);
3851  if (relation->trigdesc == NULL)
3852  relation->rd_rel->relhastriggers = false;
3853  restart = true;
3854  }
3855 
3856  /*
3857  * Re-load the row security policies if the relation has them, since
3858  * they are not preserved in the cache. Note that we can never NOT
3859  * have a policy while relrowsecurity is true,
3860  * RelationBuildRowSecurity will create a single default-deny policy
3861  * if there is no policy defined in pg_policy.
3862  */
3863  if (relation->rd_rel->relrowsecurity && relation->rd_rsdesc == NULL)
3864  {
3865  RelationBuildRowSecurity(relation);
3866 
3867  Assert(relation->rd_rsdesc != NULL);
3868  restart = true;
3869  }
3870 
3871  /*
3872  * Reload the partition key and descriptor for a partitioned table.
3873  */
3874  if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
3875  relation->rd_partkey == NULL)
3876  {
3877  RelationBuildPartitionKey(relation);
3878  Assert(relation->rd_partkey != NULL);
3879 
3880  restart = true;
3881  }
3882 
3883  if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
3884  relation->rd_partdesc == NULL)
3885  {
3886  RelationBuildPartitionDesc(relation);
3887  Assert(relation->rd_partdesc != NULL);
3888 
3889  restart = true;
3890  }
3891 
3892  /* Release hold on the relation */
3894 
3895  /* Now, restart the hashtable scan if needed */
3896  if (restart)
3897  {
3898  hash_seq_term(&status);
3899  hash_seq_init(&status, RelationIdCache);
3900  }
3901  }
3902 
3903  /*
3904  * Lastly, write out new relcache cache files if needed. We don't bother
3905  * to distinguish cases where only one of the two needs an update.
3906  */
3907  if (needNewCacheFile)
3908  {
3909  /*
3910  * Force all the catcaches to finish initializing and thereby open the