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_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)
 
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:155
#define MAX_EOXACT_LIST
Definition: relcache.c:154
static bool eoxact_list_overflowed
Definition: relcache.c:157
static int eoxact_list_len
Definition: relcache.c:156

Definition at line 159 of file relcache.c.

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

#define INITRELCACHESIZE   400

Definition at line 3523 of file relcache.c.

Referenced by RelationCacheInitialize().

#define MAX_EOXACT_LIST   32

Definition at line 154 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), \
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:885
static HTAB * RelationIdCache
Definition: relcache.c:122
#define WARNING
Definition: elog.h:40
#define NULL
Definition: c.h:226
#define elog
Definition: elog.h:219

Definition at line 213 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:885
static HTAB * RelationIdCache
Definition: relcache.c:122
struct RelationData * Relation
Definition: relcache.h:21
#define RelationGetRelationName(relation)
Definition: rel.h:433
#define WARNING
Definition: elog.h:40
static void RelationDestroyRelation(Relation relation, bool remember_tupdesc)
Definition: relcache.c:2303
#define Assert(condition)
Definition: c.h:671
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:397
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:365
#define elog
Definition: elog.h:219

Definition at line 179 of file relcache.c.

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

#define RelationIdCacheLookup (   ID,
  RELATION 
)
Value:
do { \
RelIdCacheEnt *hentry; \
(void *) &(ID), \
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:885
static HTAB * RelationIdCache
Definition: relcache.c:122
#define NULL
Definition: c.h:226

Definition at line 201 of file relcache.c.

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

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

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

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

Referenced by RelationBuildDesc().

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

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

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

3068 {
3070  RelIdCacheEnt *idhentry;
3071  int i;
3072 
3073  /*
3074  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3075  * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3076  * logic as in AtEOXact_RelationCache.
3077  */
3079  {
3080  hash_seq_init(&status, RelationIdCache);
3081  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3082  {
3083  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3084  mySubid, parentSubid);
3085  }
3086  }
3087  else
3088  {
3089  for (i = 0; i < eoxact_list_len; i++)
3090  {
3091  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3092  (void *) &eoxact_list[i],
3093  HASH_FIND,
3094  NULL);
3095  if (idhentry != NULL)
3096  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3097  mySubid, parentSubid);
3098  }
3099  }
3100 
3101  /* Don't reset the list; we still need more cleanup later */
3102 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:155
static void AtEOSubXact_cleanup(Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
Definition: relcache.c:3113
Relation reldesc
Definition: relcache.c:119
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
static HTAB * RelationIdCache
Definition: relcache.c:122
static bool eoxact_list_overflowed
Definition: relcache.c:157
#define NULL
Definition: c.h:226
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1353
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1343
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:222
static int eoxact_list_len
Definition: relcache.c:156
static void AtEOXact_cleanup ( Relation  relation,
bool  isCommit 
)
static

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

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

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

2916 {
2918  RelIdCacheEnt *idhentry;
2919  int i;
2920 
2921  /*
2922  * Unless the eoxact_list[] overflowed, we only need to examine the rels
2923  * listed in it. Otherwise fall back on a hash_seq_search scan.
2924  *
2925  * For simplicity, eoxact_list[] entries are not deleted till end of
2926  * top-level transaction, even though we could remove them at
2927  * subtransaction end in some cases, or remove relations from the list if
2928  * they are cleared for other reasons. Therefore we should expect the
2929  * case that list entries are not found in the hashtable; if not, there's
2930  * nothing to do for them.
2931  */
2933  {
2934  hash_seq_init(&status, RelationIdCache);
2935  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2936  {
2937  AtEOXact_cleanup(idhentry->reldesc, isCommit);
2938  }
2939  }
2940  else
2941  {
2942  for (i = 0; i < eoxact_list_len; i++)
2943  {
2944  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
2945  (void *) &eoxact_list[i],
2946  HASH_FIND,
2947  NULL);
2948  if (idhentry != NULL)
2949  AtEOXact_cleanup(idhentry->reldesc, isCommit);
2950  }
2951  }
2952 
2953  if (EOXactTupleDescArrayLen > 0)
2954  {
2956  for (i = 0; i < NextEOXactTupleDescNum; i++)
2960  }
2961 
2962  /* Now we're out of the transaction and can clear the lists */
2963  eoxact_list_len = 0;
2964  eoxact_list_overflowed = false;
2965  NextEOXactTupleDescNum = 0;
2967 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:155
static int EOXactTupleDescArrayLen
Definition: relcache.c:174
Relation reldesc
Definition: relcache.c:119
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
static HTAB * RelationIdCache
Definition: relcache.c:122
static void AtEOXact_cleanup(Relation relation, bool isCommit)
Definition: relcache.c:2978
static bool eoxact_list_overflowed
Definition: relcache.c:157
static int NextEOXactTupleDescNum
Definition: relcache.c:173
void pfree(void *pointer)
Definition: mcxt.c:992
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1353
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1343
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:266
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:222
static int eoxact_list_len
Definition: relcache.c:156
static TupleDesc * EOXactTupleDescArray
Definition: relcache.c:172
static void AttrDefaultFetch ( Relation  relation)
static

Definition at line 4006 of file relcache.c.

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

Referenced by RelationBuildTupleDesc().

4007 {
4008  AttrDefault *attrdef = relation->rd_att->constr->defval;
4009  int ndef = relation->rd_att->constr->num_defval;
4010  Relation adrel;
4011  SysScanDesc adscan;
4012  ScanKeyData skey;
4013  HeapTuple htup;
4014  Datum val;
4015  bool isnull;
4016  int found;
4017  int i;
4018 
4019  ScanKeyInit(&skey,
4021  BTEqualStrategyNumber, F_OIDEQ,
4022  ObjectIdGetDatum(RelationGetRelid(relation)));
4023 
4025  adscan = systable_beginscan(adrel, AttrDefaultIndexId, true,
4026  NULL, 1, &skey);
4027  found = 0;
4028 
4029  while (HeapTupleIsValid(htup = systable_getnext(adscan)))
4030  {
4031  Form_pg_attrdef adform = (Form_pg_attrdef) GETSTRUCT(htup);
4032 
4033  for (i = 0; i < ndef; i++)
4034  {
4035  if (adform->adnum != attrdef[i].adnum)
4036  continue;
4037  if (attrdef[i].adbin != NULL)
4038  elog(WARNING, "multiple attrdef records found for attr %s of rel %s",
4039  NameStr(relation->rd_att->attrs[adform->adnum - 1]->attname),
4040  RelationGetRelationName(relation));
4041  else
4042  found++;
4043 
4044  val = fastgetattr(htup,
4046  adrel->rd_att, &isnull);
4047  if (isnull)
4048  elog(WARNING, "null adbin for attr %s of rel %s",
4049  NameStr(relation->rd_att->attrs[adform->adnum - 1]->attname),
4050  RelationGetRelationName(relation));
4051  else
4052  {
4053  /* detoast and convert to cstring in caller's context */
4054  char *s = TextDatumGetCString(val);
4055 
4057  pfree(s);
4058  }
4059  break;
4060  }
4061 
4062  if (i >= ndef)
4063  elog(WARNING, "unexpected attrdef record found for attr %d of rel %s",
4064  adform->adnum, RelationGetRelationName(relation));
4065  }
4066 
4067  systable_endscan(adscan);
4068  heap_close(adrel, AccessShareLock);
4069 
4070  if (found != ndef)
4071  elog(WARNING, "%d attrdef record(s) missing for rel %s",
4072  ndef - found, RelationGetRelationName(relation));
4073 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:719
Form_pg_attribute * attrs
Definition: tupdesc.h:74
#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:322
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
void pfree(void *pointer)
Definition: mcxt.c:992
AttrDefault * defval
Definition: tupdesc.h:39
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define AttrDefaultIndexId
Definition: indexing.h:87
AttrNumber adnum
Definition: tupdesc.h:24
#define RelationGetRelationName(relation)
Definition: rel.h:433
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:91
uintptr_t Datum
Definition: postgres.h:374
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
TupleDesc rd_att
Definition: rel.h:114
#define Anum_pg_attrdef_adrelid
Definition: pg_attrdef.h:54
uint16 num_defval
Definition: tupdesc.h:41
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
TupleConstr * constr
Definition: tupdesc.h:76
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1152
int i
#define NameStr(name)
Definition: c.h:495
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:413
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 3944 of file relcache.c.

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

Referenced by GetPgClassDescriptor(), and GetPgIndexDescriptor().

3946 {
3947  TupleDesc result;
3948  MemoryContext oldcxt;
3949  int i;
3950 
3952 
3953  result = CreateTemplateTupleDesc(natts, hasoids);
3954  result->tdtypeid = RECORDOID; /* not right, but we don't care */
3955  result->tdtypmod = -1;
3956 
3957  for (i = 0; i < natts; i++)
3958  {
3959  memcpy(result->attrs[i], &attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
3960  /* make sure attcacheoff is valid */
3961  result->attrs[i]->attcacheoff = -1;
3962  }
3963 
3964  /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
3965  result->attrs[0]->attcacheoff = 0;
3966 
3967  /* Note: we don't bother to set up a TupleConstr entry */
3968 
3969  MemoryContextSwitchTo(oldcxt);
3970 
3971  return result;
3972 }
Oid tdtypeid
Definition: tupdesc.h:77
Form_pg_attribute * attrs
Definition: tupdesc.h:74
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int32 tdtypmod
Definition: tupdesc.h:78
#define RECORDOID
Definition: pg_type.h:668
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:176
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:41
int i
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static int CheckConstraintCmp ( const void *  a,
const void *  b 
)
static

Definition at line 4150 of file relcache.c.

References constrCheck::ccname.

Referenced by CheckConstraintFetch().

4151 {
4152  const ConstrCheck *ca = (const ConstrCheck *) a;
4153  const ConstrCheck *cb = (const ConstrCheck *) b;
4154 
4155  return strcmp(ca->ccname, cb->ccname);
4156 }
char * ccname
Definition: tupdesc.h:30
static void CheckConstraintFetch ( Relation  relation)
static

Definition at line 4079 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, NULL, tupleConstr::num_check, ObjectIdGetDatum, pfree(), qsort, RelationData::rd_att, RelationGetRelationName, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), TextDatumGetCString, and val.

Referenced by RelationBuildTupleDesc().

4080 {
4081  ConstrCheck *check = relation->rd_att->constr->check;
4082  int ncheck = relation->rd_att->constr->num_check;
4083  Relation conrel;
4084  SysScanDesc conscan;
4085  ScanKeyData skey[1];
4086  HeapTuple htup;
4087  int found = 0;
4088 
4089  ScanKeyInit(&skey[0],
4091  BTEqualStrategyNumber, F_OIDEQ,
4092  ObjectIdGetDatum(RelationGetRelid(relation)));
4093 
4095  conscan = systable_beginscan(conrel, ConstraintRelidIndexId, true,
4096  NULL, 1, skey);
4097 
4098  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4099  {
4101  Datum val;
4102  bool isnull;
4103  char *s;
4104 
4105  /* We want check constraints only */
4106  if (conform->contype != CONSTRAINT_CHECK)
4107  continue;
4108 
4109  if (found >= ncheck)
4110  elog(ERROR, "unexpected constraint record found for rel %s",
4111  RelationGetRelationName(relation));
4112 
4113  check[found].ccvalid = conform->convalidated;
4114  check[found].ccnoinherit = conform->connoinherit;
4116  NameStr(conform->conname));
4117 
4118  /* Grab and test conbin is actually set */
4119  val = fastgetattr(htup,
4121  conrel->rd_att, &isnull);
4122  if (isnull)
4123  elog(ERROR, "null conbin for rel %s",
4124  RelationGetRelationName(relation));
4125 
4126  /* detoast and convert to cstring in caller's context */
4127  s = TextDatumGetCString(val);
4128  check[found].ccbin = MemoryContextStrdup(CacheMemoryContext, s);
4129  pfree(s);
4130 
4131  found++;
4132  }
4133 
4134  systable_endscan(conscan);
4135  heap_close(conrel, AccessShareLock);
4136 
4137  if (found != ncheck)
4138  elog(ERROR, "%d constraint record(s) missing for rel %s",
4139  ncheck - found, RelationGetRelationName(relation));
4140 
4141  /* Sort the records so that CHECKs are applied in a deterministic order */
4142  if (ncheck > 1)
4143  qsort(check, ncheck, sizeof(ConstrCheck), CheckConstraintCmp);
4144 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#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:4150
#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:322
#define CONSTRAINT_CHECK
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
void pfree(void *pointer)
Definition: mcxt.c:992
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:433
#define TextDatumGetCString(d)
Definition: builtins.h:91
uintptr_t Datum
Definition: postgres.h:374
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
TupleDesc rd_att
Definition: rel.h:114
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
TupleConstr * constr
Definition: tupdesc.h:76
bool ccvalid
Definition: tupdesc.h:32
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1152
#define NameStr(name)
Definition: c.h:495
#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:440
#define RelationGetRelid(relation)
Definition: rel.h:413
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 992 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().

993 {
994  PartitionKey newkey;
995  int n;
996 
997  newkey = (PartitionKey) palloc(sizeof(PartitionKeyData));
998 
999  newkey->strategy = fromkey->strategy;
1000  newkey->partnatts = n = fromkey->partnatts;
1001 
1002  newkey->partattrs = (AttrNumber *) palloc(n * sizeof(AttrNumber));
1003  memcpy(newkey->partattrs, fromkey->partattrs, n * sizeof(AttrNumber));
1004 
1005  newkey->partexprs = copyObject(fromkey->partexprs);
1006 
1007  newkey->partopfamily = (Oid *) palloc(n * sizeof(Oid));
1008  memcpy(newkey->partopfamily, fromkey->partopfamily, n * sizeof(Oid));
1009 
1010  newkey->partopcintype = (Oid *) palloc(n * sizeof(Oid));
1011  memcpy(newkey->partopcintype, fromkey->partopcintype, n * sizeof(Oid));
1012 
1013  newkey->partsupfunc = (FmgrInfo *) palloc(n * sizeof(FmgrInfo));
1014  memcpy(newkey->partsupfunc, fromkey->partsupfunc, n * sizeof(FmgrInfo));
1015 
1016  newkey->partcollation = (Oid *) palloc(n * sizeof(Oid));
1017  memcpy(newkey->partcollation, fromkey->partcollation, n * sizeof(Oid));
1018 
1019  newkey->parttypid = (Oid *) palloc(n * sizeof(Oid));
1020  memcpy(newkey->parttypid, fromkey->parttypid, n * sizeof(Oid));
1021 
1022  newkey->parttypmod = (int32 *) palloc(n * sizeof(int32));
1023  memcpy(newkey->parttypmod, fromkey->parttypmod, n * sizeof(int32));
1024 
1025  newkey->parttyplen = (int16 *) palloc(n * sizeof(int16));
1026  memcpy(newkey->parttyplen, fromkey->parttyplen, n * sizeof(int16));
1027 
1028  newkey->parttypbyval = (bool *) palloc(n * sizeof(bool));
1029  memcpy(newkey->parttypbyval, fromkey->parttypbyval, n * sizeof(bool));
1030 
1031  newkey->parttypalign = (char *) palloc(n * sizeof(bool));
1032  memcpy(newkey->parttypalign, fromkey->parttypalign, n * sizeof(char));
1033 
1034  newkey->parttypcoll = (Oid *) palloc(n * sizeof(Oid));
1035  memcpy(newkey->parttypcoll, fromkey->parttypcoll, n * sizeof(Oid));
1036 
1037  return newkey;
1038 }
signed short int16
Definition: c.h:252
Definition: fmgr.h:53
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:253
void * copyObject(const void *from)
Definition: copyfuncs.c:4475
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:891
struct PartitionKeyData * PartitionKey
Definition: rel.h:77
Oid * partopcintype
Definition: rel.h:62
int16 AttrNumber
Definition: attnum.h:21
static bool equalPartitionDescs ( PartitionKey  key,
PartitionDesc  partdesc1,
PartitionDesc  partdesc2 
)
static

Definition at line 1172 of file relcache.c.

References Assert, PartitionDescData::boundinfo, i, PartitionDescData::nparts, NULL, PartitionDescData::oids, and partition_bounds_equal().

Referenced by RelationClearRelation().

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

Definition at line 1093 of file relcache.c.

References ARR_DATA_PTR, ARR_DIMS, equal(), RowSecurityPolicy::hassublinks, i, NULL, RowSecurityPolicy::polcmd, RowSecurityPolicy::policy_name, RowSecurityPolicy::qual, RowSecurityPolicy::roles, and RowSecurityPolicy::with_check_qual.

Referenced by equalRSDesc().

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

Definition at line 1139 of file relcache.c.

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

Referenced by RelationClearRelation().

1140 {
1141  ListCell *lc,
1142  *rc;
1143 
1144  if (rsdesc1 == NULL && rsdesc2 == NULL)
1145  return true;
1146 
1147  if ((rsdesc1 != NULL && rsdesc2 == NULL) ||
1148  (rsdesc1 == NULL && rsdesc2 != NULL))
1149  return false;
1150 
1151  if (list_length(rsdesc1->policies) != list_length(rsdesc2->policies))
1152  return false;
1153 
1154  /* RelationBuildRowSecurity should build policies in order */
1155  forboth(lc, rsdesc1->policies, rc, rsdesc2->policies)
1156  {
1159 
1160  if (!equalPolicy(l, r))
1161  return false;
1162  }
1163 
1164  return true;
1165 }
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:174
static bool equalPolicy(RowSecurityPolicy *policy1, RowSecurityPolicy *policy2)
Definition: relcache.c:1093
#define NULL
Definition: c.h:226
#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 1048 of file relcache.c.

References RewriteRule::actions, RewriteRule::enabled, equal(), RewriteRule::event, i, RewriteRule::isInstead, NULL, RuleLock::numLocks, RewriteRule::qual, RewriteRule::ruleId, and RuleLock::rules.

Referenced by RelationClearRelation().

1049 {
1050  int i;
1051 
1052  /*
1053  * As of 7.3 we assume the rule ordering is repeatable, because
1054  * RelationBuildRuleLock should read 'em in a consistent order. So just
1055  * compare corresponding slots.
1056  */
1057  if (rlock1 != NULL)
1058  {
1059  if (rlock2 == NULL)
1060  return false;
1061  if (rlock1->numLocks != rlock2->numLocks)
1062  return false;
1063  for (i = 0; i < rlock1->numLocks; i++)
1064  {
1065  RewriteRule *rule1 = rlock1->rules[i];
1066  RewriteRule *rule2 = rlock2->rules[i];
1067 
1068  if (rule1->ruleId != rule2->ruleId)
1069  return false;
1070  if (rule1->event != rule2->event)
1071  return false;
1072  if (rule1->enabled != rule2->enabled)
1073  return false;
1074  if (rule1->isInstead != rule2->isInstead)
1075  return false;
1076  if (!equal(rule1->qual, rule2->qual))
1077  return false;
1078  if (!equal(rule1->actions, rule2->actions))
1079  return false;
1080  }
1081  }
1082  else if (rlock2 != NULL)
1083  return false;
1084  return true;
1085 }
Node * qual
Definition: prs2lock.h:28
int numLocks
Definition: prs2lock.h:42
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2870
bool isInstead
Definition: prs2lock.h:31
CmdType event
Definition: prs2lock.h:27
RewriteRule ** rules
Definition: prs2lock.h:43
List * actions
Definition: prs2lock.h:29
#define NULL
Definition: c.h:226
int i
Oid ruleId
Definition: prs2lock.h:26
char enabled
Definition: prs2lock.h:30
int errtable ( Relation  rel)

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

5156 {
5160 
5161  return 0; /* return value does not matter */
5162 }
#define PG_DIAG_SCHEMA_NAME
Definition: postgres_ext.h:61
#define PG_DIAG_TABLE_NAME
Definition: postgres_ext.h:62
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
#define RelationGetRelationName(relation)
Definition: rel.h:433
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
#define RelationGetNamespace(relation)
Definition: rel.h:440
int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5172 of file relcache.c.

References tupleDesc::attrs, errtablecolname(), get_relid_attribute_name(), NameStr, RelationGetDescr, and RelationGetRelid.

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

5173 {
5174  TupleDesc reldesc = RelationGetDescr(rel);
5175  const char *colname;
5176 
5177  /* Use reldesc if it's a user attribute, else consult the catalogs */
5178  if (attnum > 0 && attnum <= reldesc->natts)
5179  colname = NameStr(reldesc->attrs[attnum - 1]->attname);
5180  else
5181  colname = get_relid_attribute_name(RelationGetRelid(rel), attnum);
5182 
5183  return errtablecolname(rel, colname);
5184 }
#define RelationGetDescr(relation)
Definition: rel.h:425
Form_pg_attribute * attrs
Definition: tupdesc.h:74
char * get_relid_attribute_name(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:801
#define NameStr(name)
Definition: c.h:495
#define RelationGetRelid(relation)
Definition: rel.h:413
int errtablecolname(Relation rel, const char *colname)
Definition: relcache.c:5196
int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5196 of file relcache.c.

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

Referenced by errtablecol().

5197 {
5198  errtable(rel);
5200 
5201  return 0; /* return value does not matter */
5202 }
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:63
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
int errtable(Relation rel)
Definition: relcache.c:5155
int errtableconstraint ( Relation  rel,
const char *  conname 
)

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

5210 {
5211  errtable(rel);
5213 
5214  return 0; /* return value does not matter */
5215 }
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:65
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
int errtable(Relation rel)
Definition: relcache.c:5155
static void formrdesc ( const char *  relationName,
Oid  relationReltype,
bool  isshared,
bool  hasoids,
int  natts,
const FormData_pg_attribute attrs 
)
static

Definition at line 1886 of file relcache.c.

References ATTRIBUTE_FIXED_PART_SIZE, tupleDesc::attrs, CLASS_TUPLE_SIZE, tupleDesc::constr, CreateTemplateTupleDesc(), GLOBALTABLESPACE_OID, tupleConstr::has_not_null, i, InvalidBackendId, InvalidOid, InvalidSubTransactionId, IsBootstrapProcessingMode, namestrcpy(), NULL, 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, and tupleDesc::tdtypmod.

Referenced by RelationCacheInitializePhase2(), and RelationCacheInitializePhase3().

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

Definition at line 3975 of file relcache.c.

References BuildHardcodedDescriptor(), Desc_pg_class, Natts_pg_class, and NULL.

Referenced by RelationParseRelOptions().

3976 {
3977  static TupleDesc pgclassdesc = NULL;
3978 
3979  /* Already done? */
3980  if (pgclassdesc == NULL)
3982  Desc_pg_class,
3983  true);
3984 
3985  return pgclassdesc;
3986 }
#define Natts_pg_class
Definition: pg_class.h:102
static TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs, bool hasoids)
Definition: relcache.c:3944
#define NULL
Definition: c.h:226
static const FormData_pg_attribute Desc_pg_class[Natts_pg_class]
Definition: relcache.c:99
static TupleDesc GetPgIndexDescriptor ( void  )
static

Definition at line 3989 of file relcache.c.

References BuildHardcodedDescriptor(), Desc_pg_index, Natts_pg_index, and NULL.

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

3990 {
3991  static TupleDesc pgindexdesc = NULL;
3992 
3993  /* Already done? */
3994  if (pgindexdesc == NULL)
3996  Desc_pg_index,
3997  false);
3998 
3999  return pgindexdesc;
4000 }
static TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs, bool hasoids)
Definition: relcache.c:3944
static const FormData_pg_attribute Desc_pg_index[Natts_pg_index]
Definition: relcache.c:106
#define Natts_pg_index
Definition: pg_index.h:73
#define NULL
Definition: c.h:226
struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

Definition at line 5084 of file relcache.c.

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

Referenced by CheckCmdReplicaIdentity().

5085 {
5086  List *puboids;
5087  ListCell *lc;
5088  MemoryContext oldcxt;
5089  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5090 
5091  if (relation->rd_pubactions)
5092  return memcpy(pubactions, relation->rd_pubactions,
5093  sizeof(PublicationActions));
5094 
5095  /* Fetch the publication membership info. */
5096  puboids = GetRelationPublications(RelationGetRelid(relation));
5097  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5098 
5099  foreach(lc, puboids)
5100  {
5101  Oid pubid = lfirst_oid(lc);
5102  HeapTuple tup;
5103  Form_pg_publication pubform;
5104 
5106 
5107  if (!HeapTupleIsValid(tup))
5108  elog(ERROR, "cache lookup failed for publication %u", pubid);
5109 
5110  pubform = (Form_pg_publication) GETSTRUCT(tup);
5111 
5112  pubactions->pubinsert |= pubform->pubinsert;
5113  pubactions->pubupdate |= pubform->pubupdate;
5114  pubactions->pubdelete |= pubform->pubdelete;
5115 
5116  ReleaseSysCache(tup);
5117 
5118  /*
5119  * If we know everything is replicated, there is no point to check
5120  * for other publications.
5121  */
5122  if (pubactions->pubinsert && pubactions->pubupdate &&
5123  pubactions->pubdelete)
5124  break;
5125  }
5126 
5127  if (relation->rd_pubactions)
5128  {
5129  pfree(relation->rd_pubactions);
5130  relation->rd_pubactions = NULL;
5131  }
5132 
5133  /* Now save copy of the actions in the relcache entry. */
5135  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5136  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5137  MemoryContextSwitchTo(oldcxt);
5138 
5139  return pubactions;
5140 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
PublicationActions * rd_pubactions
Definition: rel.h:145
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
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
List * GetRelationPublications(Oid relid)
void pfree(void *pointer)
Definition: mcxt.c:992
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
void * palloc0(Size size)
Definition: mcxt.c:920
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
List * GetAllTablesPublications(void)
void * palloc(Size size)
Definition: mcxt.c:891
#define elog
Definition: elog.h:219
FormData_pg_publication * Form_pg_publication
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:413
#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 1667 of file relcache.c.

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

Referenced by RelationInitIndexAccessInfo().

1673 {
1674  int attIndex;
1675 
1676  for (attIndex = 0; attIndex < maxAttributeNumber; attIndex++)
1677  {
1678  OpClassCacheEnt *opcentry;
1679 
1680  if (!OidIsValid(indclass->values[attIndex]))
1681  elog(ERROR, "bogus pg_index tuple");
1682 
1683  /* look up the info for this opclass, using a cache */
1684  opcentry = LookupOpclassInfo(indclass->values[attIndex],
1685  maxSupportNumber);
1686 
1687  /* copy cached data into relcache entry */
1688  opFamily[attIndex] = opcentry->opcfamily;
1689  opcInType[attIndex] = opcentry->opcintype;
1690  if (maxSupportNumber > 0)
1691  memcpy(&indexSupport[attIndex * maxSupportNumber],
1692  opcentry->supportProcs,
1693  maxSupportNumber * sizeof(RegProcedure));
1694  }
1695 }
regproc RegProcedure
Definition: c.h:392
#define OidIsValid(objectId)
Definition: c.h:534
#define ERROR
Definition: elog.h:43
RegProcedure * supportProcs
Definition: relcache.c:238
static OpClassCacheEnt * LookupOpclassInfo(Oid operatorClassOid, StrategyNumber numSupport)
Definition: relcache.c:1718
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:482
#define elog
Definition: elog.h:219
static void InitIndexAmRoutine ( Relation  relation)
static

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

1481 {
1482  IndexAmRoutine *cached,
1483  *tmp;
1484 
1485  /*
1486  * Call the amhandler in current, short-lived memory context, just in case
1487  * it leaks anything (it probably won't, but let's be paranoid).
1488  */
1489  tmp = GetIndexAmRoutine(relation->rd_amhandler);
1490 
1491  /* OK, now transfer the data into relation's rd_indexcxt. */
1492  cached = (IndexAmRoutine *) MemoryContextAlloc(relation->rd_indexcxt,
1493  sizeof(IndexAmRoutine));
1494  memcpy(cached, tmp, sizeof(IndexAmRoutine));
1495  relation->rd_amroutine = cached;
1496 
1497  pfree(tmp);
1498 }
struct IndexAmRoutine * rd_amroutine
Definition: rel.h:177
void pfree(void *pointer)
Definition: mcxt.c:992
Oid rd_amhandler
Definition: rel.h:174
IndexAmRoutine * GetIndexAmRoutine(Oid amhandler)
Definition: amapi.c:33
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
MemoryContext rd_indexcxt
Definition: rel.h:175
static List * insert_ordered_oid ( List list,
Oid  datum 
)
static

Definition at line 4464 of file relcache.c.

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

Referenced by RelationGetIndexList().

4465 {
4466  ListCell *prev;
4467 
4468  /* Does the datum belong at the front? */
4469  if (list == NIL || datum < linitial_oid(list))
4470  return lcons_oid(datum, list);
4471  /* No, so find the entry it belongs after */
4472  prev = list_head(list);
4473  for (;;)
4474  {
4475  ListCell *curr = lnext(prev);
4476 
4477  if (curr == NULL || datum < lfirst_oid(curr))
4478  break; /* it belongs after 'prev', before 'curr' */
4479 
4480  prev = curr;
4481  }
4482  /* Insert datum into list after 'prev' */
4483  lappend_cell_oid(list, prev, datum);
4484  return list;
4485 }
#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 NULL
Definition: c.h:226
#define linitial_oid(l)
Definition: pg_list.h:112
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 3910 of file relcache.c.

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

Referenced by RelationCacheInitializePhase3().

3911 {
3912  Relation ird;
3913 
3914  /*
3915  * We must lock the underlying catalog before locking the index to avoid
3916  * deadlock, since RelationBuildDesc might well need to read the catalog,
3917  * and if anyone else is exclusive-locking this catalog and index they'll
3918  * be doing it in that order.
3919  */
3920  LockRelationOid(heapoid, AccessShareLock);
3921  LockRelationOid(indexoid, AccessShareLock);
3922  ird = RelationBuildDesc(indexoid, true);
3923  if (ird == NULL)
3924  elog(PANIC, "could not open critical system index %u", indexoid);
3925  ird->rd_isnailed = true;
3926  ird->rd_refcnt = 1;
3929 }
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
#define NULL
Definition: c.h:226
static Relation RelationBuildDesc(Oid targetRelId, bool insertIt)
Definition: relcache.c:1232
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 5273 of file relcache.c.

References AllocateFile(), ALLOCSET_SMALL_SIZES, AllocSetContextCreate(), IndexAmRoutine::amsupport, Assert, ATTRIBUTE_FIXED_PART_SIZE, tupleDesc::attrs, CacheMemoryContext, tupleDesc::constr, CreateTemplateTupleDesc(), criticalRelcachesBuilt, criticalSharedRelcachesBuilt, DatabasePath, elog, FreeFile(), GETSTRUCT, tupleConstr::has_not_null, HEAPTUPLESIZE, i, InitIndexAmRoutine(), InvalidOid, InvalidSubTransactionId, MAXPGPATH, MemoryContextAlloc(), MemoryContextAllocZero(), MemSet, NIL, NULL, 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_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_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, VARSIZE, and WARNING.

Referenced by RelationCacheInitializePhase2(), and RelationCacheInitializePhase3().

5274 {
5275  FILE *fp;
5276  char initfilename[MAXPGPATH];
5277  Relation *rels;
5278  int relno,
5279  num_rels,
5280  max_rels,
5281  nailed_rels,
5282  nailed_indexes,
5283  magic;
5284  int i;
5285 
5286  if (shared)
5287  snprintf(initfilename, sizeof(initfilename), "global/%s",
5289  else
5290  snprintf(initfilename, sizeof(initfilename), "%s/%s",
5292 
5293  fp = AllocateFile(initfilename, PG_BINARY_R);
5294  if (fp == NULL)
5295  return false;
5296 
5297  /*
5298  * Read the index relcache entries from the file. Note we will not enter
5299  * any of them into the cache if the read fails partway through; this
5300  * helps to guard against broken init files.
5301  */
5302  max_rels = 100;
5303  rels = (Relation *) palloc(max_rels * sizeof(Relation));
5304  num_rels = 0;
5305  nailed_rels = nailed_indexes = 0;
5306 
5307  /* check for correct magic number (compatible version) */
5308  if (fread(&magic, 1, sizeof(magic), fp) != sizeof(magic))
5309  goto read_failed;
5310  if (magic != RELCACHE_INIT_FILEMAGIC)
5311  goto read_failed;
5312 
5313  for (relno = 0;; relno++)
5314  {
5315  Size len;
5316  size_t nread;
5317  Relation rel;
5318  Form_pg_class relform;
5319  bool has_not_null;
5320 
5321  /* first read the relation descriptor length */
5322  nread = fread(&len, 1, sizeof(len), fp);
5323  if (nread != sizeof(len))
5324  {
5325  if (nread == 0)
5326  break; /* end of file */
5327  goto read_failed;
5328  }
5329 
5330  /* safety check for incompatible relcache layout */
5331  if (len != sizeof(RelationData))
5332  goto read_failed;
5333 
5334  /* allocate another relcache header */
5335  if (num_rels >= max_rels)
5336  {
5337  max_rels *= 2;
5338  rels = (Relation *) repalloc(rels, max_rels * sizeof(Relation));
5339  }
5340 
5341  rel = rels[num_rels++] = (Relation) palloc(len);
5342 
5343  /* then, read the Relation structure */
5344  if (fread(rel, 1, len, fp) != len)
5345  goto read_failed;
5346 
5347  /* next read the relation tuple form */
5348  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5349  goto read_failed;
5350 
5351  relform = (Form_pg_class) palloc(len);
5352  if (fread(relform, 1, len, fp) != len)
5353  goto read_failed;
5354 
5355  rel->rd_rel = relform;
5356 
5357  /* initialize attribute tuple forms */
5358  rel->rd_att = CreateTemplateTupleDesc(relform->relnatts,
5359  relform->relhasoids);
5360  rel->rd_att->tdrefcount = 1; /* mark as refcounted */
5361 
5362  rel->rd_att->tdtypeid = relform->reltype;
5363  rel->rd_att->tdtypmod = -1; /* unnecessary, but... */
5364 
5365  /* next read all the attribute tuple form data entries */
5366  has_not_null = false;
5367  for (i = 0; i < relform->relnatts; i++)
5368  {
5369  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5370  goto read_failed;
5371  if (len != ATTRIBUTE_FIXED_PART_SIZE)
5372  goto read_failed;
5373  if (fread(rel->rd_att->attrs[i], 1, len, fp) != len)
5374  goto read_failed;
5375 
5376  has_not_null |= rel->rd_att->attrs[i]->attnotnull;
5377  }
5378 
5379  /* next read the access method specific field */
5380  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5381  goto read_failed;
5382  if (len > 0)
5383  {
5384  rel->rd_options = palloc(len);
5385  if (fread(rel->rd_options, 1, len, fp) != len)
5386  goto read_failed;
5387  if (len != VARSIZE(rel->rd_options))
5388  goto read_failed; /* sanity check */
5389  }
5390  else
5391  {
5392  rel->rd_options = NULL;
5393  }
5394 
5395  /* mark not-null status */
5396  if (has_not_null)
5397  {
5398  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
5399 
5400  constr->has_not_null = true;
5401  rel->rd_att->constr = constr;
5402  }
5403 
5404  /* If it's an index, there's more to do */
5405  if (rel->rd_rel->relkind == RELKIND_INDEX)
5406  {
5407  MemoryContext indexcxt;
5408  Oid *opfamily;
5409  Oid *opcintype;
5410  RegProcedure *support;
5411  int nsupport;
5412  int16 *indoption;
5413  Oid *indcollation;
5414 
5415  /* Count nailed indexes to ensure we have 'em all */
5416  if (rel->rd_isnailed)
5417  nailed_indexes++;
5418 
5419  /* next, read the pg_index tuple */
5420  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5421  goto read_failed;
5422 
5423  rel->rd_indextuple = (HeapTuple) palloc(len);
5424  if (fread(rel->rd_indextuple, 1, len, fp) != len)
5425  goto read_failed;
5426 
5427  /* Fix up internal pointers in the tuple -- see heap_copytuple */
5428  rel->rd_indextuple->t_data = (HeapTupleHeader) ((char *) rel->rd_indextuple + HEAPTUPLESIZE);
5430 
5431  /*
5432  * prepare index info context --- parameters should match
5433  * RelationInitIndexAccessInfo
5434  */
5438  rel->rd_indexcxt = indexcxt;
5439 
5440  /*
5441  * Now we can fetch the index AM's API struct. (We can't store
5442  * that in the init file, since it contains function pointers that
5443  * might vary across server executions. Fortunately, it should be
5444  * safe to call the amhandler even while bootstrapping indexes.)
5445  */
5446  InitIndexAmRoutine(rel);
5447 
5448  /* next, read the vector of opfamily OIDs */
5449  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5450  goto read_failed;
5451 
5452  opfamily = (Oid *) MemoryContextAlloc(indexcxt, len);
5453  if (fread(opfamily, 1, len, fp) != len)
5454  goto read_failed;
5455 
5456  rel->rd_opfamily = opfamily;
5457 
5458  /* next, read the vector of opcintype OIDs */
5459  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5460  goto read_failed;
5461 
5462  opcintype = (Oid *) MemoryContextAlloc(indexcxt, len);
5463  if (fread(opcintype, 1, len, fp) != len)
5464  goto read_failed;
5465 
5466  rel->rd_opcintype = opcintype;
5467 
5468  /* next, read the vector of support procedure OIDs */
5469  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5470  goto read_failed;
5471  support = (RegProcedure *) MemoryContextAlloc(indexcxt, len);
5472  if (fread(support, 1, len, fp) != len)
5473  goto read_failed;
5474 
5475  rel->rd_support = support;
5476 
5477  /* next, read the vector of collation OIDs */
5478  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5479  goto read_failed;
5480 
5481  indcollation = (Oid *) MemoryContextAlloc(indexcxt, len);
5482  if (fread(indcollation, 1, len, fp) != len)
5483  goto read_failed;
5484 
5485  rel->rd_indcollation = indcollation;
5486 
5487  /* finally, read the vector of indoption values */
5488  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5489  goto read_failed;
5490 
5491  indoption = (int16 *) MemoryContextAlloc(indexcxt, len);
5492  if (fread(indoption, 1, len, fp) != len)
5493  goto read_failed;
5494 
5495  rel->rd_indoption = indoption;
5496 
5497  /* set up zeroed fmgr-info vector */
5498  nsupport = relform->relnatts * rel->rd_amroutine->amsupport;
5499  rel->rd_supportinfo = (FmgrInfo *)
5500  MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
5501  }
5502  else
5503  {
5504  /* Count nailed rels to ensure we have 'em all */
5505  if (rel->rd_isnailed)
5506  nailed_rels++;
5507 
5508  Assert(rel->rd_index == NULL);
5509  Assert(rel->rd_indextuple == NULL);
5510  Assert(rel->rd_indexcxt == NULL);
5511  Assert(rel->rd_amroutine == NULL);
5512  Assert(rel->rd_opfamily == NULL);
5513  Assert(rel->rd_opcintype == NULL);
5514  Assert(rel->rd_support == NULL);
5515  Assert(rel->rd_supportinfo == NULL);
5516  Assert(rel->rd_indoption == NULL);
5517  Assert(rel->rd_indcollation == NULL);
5518  }
5519 
5520  /*
5521  * Rules and triggers are not saved (mainly because the internal
5522  * format is complex and subject to change). They must be rebuilt if
5523  * needed by RelationCacheInitializePhase3. This is not expected to
5524  * be a big performance hit since few system catalogs have such. Ditto
5525  * for RLS policy data, index expressions, predicates, exclusion info,
5526  * and FDW info.
5527  */
5528  rel->rd_rules = NULL;
5529  rel->rd_rulescxt = NULL;
5530  rel->trigdesc = NULL;
5531  rel->rd_rsdesc = NULL;
5532  rel->rd_partkeycxt = NULL;
5533  rel->rd_partkey = NULL;
5534  rel->rd_partdesc = NULL;
5535  rel->rd_partcheck = NIL;
5536  rel->rd_indexprs = NIL;
5537  rel->rd_indpred = NIL;
5538  rel->rd_exclops = NULL;
5539  rel->rd_exclprocs = NULL;
5540  rel->rd_exclstrats = NULL;
5541  rel->rd_fdwroutine = NULL;
5542 
5543  /*
5544  * Reset transient-state fields in the relcache entry
5545  */
5546  rel->rd_smgr = NULL;
5547  if (rel->rd_isnailed)
5548  rel->rd_refcnt = 1;
5549  else
5550  rel->rd_refcnt = 0;
5551  rel->rd_indexvalid = 0;
5552  rel->rd_fkeylist = NIL;
5553  rel->rd_fkeyvalid = false;
5554  rel->rd_indexlist = NIL;
5555  rel->rd_oidindex = InvalidOid;
5556  rel->rd_pkindex = InvalidOid;
5557  rel->rd_replidindex = InvalidOid;
5558  rel->rd_indexattr = NULL;
5559  rel->rd_keyattr = NULL;
5560  rel->rd_pkattr = NULL;
5561  rel->rd_idattr = NULL;
5562  rel->rd_pubactions = NULL;
5565  rel->rd_amcache = NULL;
5566  MemSet(&rel->pgstat_info, 0, sizeof(rel->pgstat_info));
5567 
5568  /*
5569  * Recompute lock and physical addressing info. This is needed in
5570  * case the pg_internal.init file was copied from some other database
5571  * by CREATE DATABASE.
5572  */
5573  RelationInitLockInfo(rel);
5575  }
5576 
5577  /*
5578  * We reached the end of the init file without apparent problem. Did we
5579  * get the right number of nailed items? This is a useful crosscheck in
5580  * case the set of critical rels or indexes changes. However, that should
5581  * not happen in a normally-running system, so let's bleat if it does.
5582  *
5583  * For the shared init file, we're called before client authentication is
5584  * done, which means that elog(WARNING) will go only to the postmaster
5585  * log, where it's easily missed. To ensure that developers notice bad
5586  * values of NUM_CRITICAL_SHARED_RELS/NUM_CRITICAL_SHARED_INDEXES, we put
5587  * an Assert(false) there.
5588  */
5589  if (shared)
5590  {
5591  if (nailed_rels != NUM_CRITICAL_SHARED_RELS ||
5592  nailed_indexes != NUM_CRITICAL_SHARED_INDEXES)
5593  {
5594  elog(WARNING, "found %d nailed shared rels and %d nailed shared indexes in init file, but expected %d and %d respectively",
5595  nailed_rels, nailed_indexes,
5597  /* Make sure we get developers' attention about this */
5598  Assert(false);
5599  /* In production builds, recover by bootstrapping the relcache */
5600  goto read_failed;
5601  }
5602  }
5603  else
5604  {
5605  if (nailed_rels != NUM_CRITICAL_LOCAL_RELS ||
5606  nailed_indexes != NUM_CRITICAL_LOCAL_INDEXES)
5607  {
5608  elog(WARNING, "found %d nailed rels and %d nailed indexes in init file, but expected %d and %d respectively",
5609  nailed_rels, nailed_indexes,
5611  /* We don't need an Assert() in this case */
5612  goto read_failed;
5613  }
5614  }
5615 
5616  /*
5617  * OK, all appears well.
5618  *
5619  * Now insert all the new relcache entries into the cache.
5620  */
5621  for (relno = 0; relno < num_rels; relno++)
5622  {
5623  RelationCacheInsert(rels[relno], false);
5624  }
5625 
5626  pfree(rels);
5627  FreeFile(fp);
5628 
5629  if (shared)
5631  else
5632  criticalRelcachesBuilt = true;
5633  return true;
5634 
5635  /*
5636  * init file is broken, so do it the hard way. We don't bother trying to
5637  * free the clutter we just allocated; it's not in the relcache so it
5638  * won't hurt.
5639  */
5640 read_failed:
5641  pfree(rels);
5642  FreeFile(fp);
5643 
5644  return false;
5645 }
struct FdwRoutine * rd_fdwroutine
Definition: rel.h:200
signed short int16
Definition: c.h:252
#define NIL
Definition: pg_list.h:69
Definition: fmgr.h:53
struct PartitionDescData * rd_partdesc
Definition: rel.h:130
uint16 amsupport
Definition: amapi.h:169
HeapTupleData * HeapTuple
Definition: htup.h:70
Oid tdtypeid
Definition: tupdesc.h:77
int16 * rd_indoption
Definition: rel.h:182
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
PublicationActions * rd_pubactions
Definition: rel.h:145
FmgrInfo * rd_supportinfo
Definition: rel.h:181
Bitmapset * rd_keyattr
Definition: rel.h:141
#define VARSIZE(PTR)
Definition: postgres.h:306
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
Oid rd_replidindex
Definition: rel.h:137
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:155
bool rd_isnailed
Definition: rel.h:91
regproc RegProcedure
Definition: c.h:392
Form_pg_attribute * attrs
Definition: tupdesc.h:74
uint16 * rd_exclstrats
Definition: rel.h:187
#define NUM_CRITICAL_LOCAL_INDEXES
List * rd_indexprs
Definition: rel.h:183
List * rd_fkeylist
Definition: rel.h:124
#define RELCACHE_INIT_FILENAME
Definition: relcache.c:92
#define MemSet(start, val, len)
Definition: c.h:853
SubTransactionId rd_newRelfilenodeSubid
Definition: rel.h:110
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
MemoryContext rd_rulescxt
Definition: rel.h:118
bool criticalSharedRelcachesBuilt
Definition: relcache.c:134
Oid * rd_exclprocs
Definition: rel.h:186
Form_pg_class rd_rel
Definition: rel.h:113
unsigned int Oid
Definition: postgres_ext.h:31
#define NUM_CRITICAL_SHARED_INDEXES
#define PG_BINARY_R
Definition: c.h:1040
#define NUM_CRITICAL_SHARED_RELS
struct IndexAmRoutine * rd_amroutine
Definition: rel.h:177
static void InitIndexAmRoutine(Relation relation)
Definition: relcache.c:1480
int32 tdtypmod
Definition: tupdesc.h:78
struct HeapTupleData * rd_indextuple
Definition: rel.h:157
HeapTupleHeader t_data
Definition: htup.h:67
struct RelationData * Relation
Definition: relcache.h:21
Form_pg_index rd_index
Definition: rel.h:155
void pfree(void *pointer)
Definition: mcxt.c:992
#define NUM_CRITICAL_LOCAL_RELS
Oid * rd_indcollation
Definition: rel.h:189
Oid rd_pkindex
Definition: rel.h:136
struct PartitionKeyData * rd_partkey
Definition: rel.h:128
#define MAXPGPATH
TriggerDesc * trigdesc
Definition: rel.h:119
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c:1417
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:2043
#define RELCACHE_INIT_FILEMAGIC
Definition: relcache.c:94
#define RelationGetRelationName(relation)
Definition: rel.h:433
List * rd_indpred
Definition: rel.h:184
Oid rd_oidindex
Definition: rel.h:135
Oid * rd_opfamily
Definition: rel.h:178
Oid * rd_exclops
Definition: rel.h:185
List * rd_indexlist
Definition: rel.h:134
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:176
struct RowSecurityDesc * rd_rsdesc
Definition: rel.h:121
RegProcedure * rd_support
Definition: rel.h:180
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:109
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:440
void * palloc0(Size size)
Definition: mcxt.c:920
TupleDesc rd_att
Definition: rel.h:114
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:784
#define InvalidOid
Definition: postgres_ext.h:36
Bitmapset * rd_idattr
Definition: rel.h:143
#define RelationCacheInsert(RELATION, replace_allowed)
Definition: relcache.c:179
char * DatabasePath
Definition: globals.c:84
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
MemoryContext rd_partkeycxt
Definition: rel.h:127
RuleLock * rd_rules
Definition: rel.h:117
TupleConstr * constr
Definition: tupdesc.h:76
size_t Size
Definition: c.h:353
struct PgStat_TableStatus * pgstat_info
Definition: rel.h:214
#define InvalidSubTransactionId
Definition: c.h:400
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:41
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1021
int FreeFile(FILE *file)
Definition: fd.c:2226
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
Bitmapset * rd_pkattr
Definition: rel.h:142
void * palloc(Size size)
Definition: mcxt.c:891
int rd_refcnt
Definition: rel.h:88
#define HEAPTUPLESIZE
Definition: htup.h:72
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
int tdrefcount
Definition: tupdesc.h:80
MemoryContext rd_indexcxt
Definition: rel.h:175
int i
#define RELKIND_INDEX
Definition: pg_class.h:161
#define elog
Definition: elog.h:219
bool criticalRelcachesBuilt
Definition: relcache.c:128
void * rd_amcache
Definition: rel.h:188
Oid * rd_opcintype
Definition: rel.h:179
bool rd_fkeyvalid
Definition: rel.h:125
List * rd_partcheck
Definition: rel.h:131
Bitmapset * rd_indexattr
Definition: rel.h:140
bytea * rd_options
Definition: rel.h:152
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static OpClassCacheEnt * LookupOpclassInfo ( Oid  operatorClassOid,
StrategyNumber  numSupport 
)
static

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

1720 {
1721  OpClassCacheEnt *opcentry;
1722  bool found;
1723  Relation rel;
1724  SysScanDesc scan;
1725  ScanKeyData skey[3];
1726  HeapTuple htup;
1727  bool indexOK;
1728 
1729  if (OpClassCache == NULL)
1730  {
1731  /* First time through: initialize the opclass cache */
1732  HASHCTL ctl;
1733 
1734  MemSet(&ctl, 0, sizeof(ctl));
1735  ctl.keysize = sizeof(Oid);
1736  ctl.entrysize = sizeof(OpClassCacheEnt);
1737  OpClassCache = hash_create("Operator class cache", 64,
1738  &ctl, HASH_ELEM | HASH_BLOBS);
1739 
1740  /* Also make sure CacheMemoryContext exists */
1741  if (!CacheMemoryContext)
1743  }
1744 
1745  opcentry = (OpClassCacheEnt *) hash_search(OpClassCache,
1746  (void *) &operatorClassOid,
1747  HASH_ENTER, &found);
1748 
1749  if (!found)
1750  {
1751  /* Need to allocate memory for new entry */
1752  opcentry->valid = false; /* until known OK */
1753  opcentry->numSupport = numSupport;
1754 
1755  if (numSupport > 0)
1756  opcentry->supportProcs = (RegProcedure *)
1758  numSupport * sizeof(RegProcedure));
1759  else
1760  opcentry->supportProcs = NULL;
1761  }
1762  else
1763  {
1764  Assert(numSupport == opcentry->numSupport);
1765  }
1766 
1767  /*
1768  * When testing for cache-flush hazards, we intentionally disable the
1769  * operator class cache and force reloading of the info on each call. This
1770  * is helpful because we want to test the case where a cache flush occurs
1771  * while we are loading the info, and it's very hard to provoke that if
1772  * this happens only once per opclass per backend.
1773  */
1774 #if defined(CLOBBER_CACHE_ALWAYS)
1775  opcentry->valid = false;
1776 #endif
1777 
1778  if (opcentry->valid)
1779  return opcentry;
1780 
1781  /*
1782  * Need to fill in new entry.
1783  *
1784  * To avoid infinite recursion during startup, force heap scans if we're
1785  * looking up info for the opclasses used by the indexes we would like to
1786  * reference here.
1787  */
1788  indexOK = criticalRelcachesBuilt ||
1789  (operatorClassOid != OID_BTREE_OPS_OID &&
1790  operatorClassOid != INT2_BTREE_OPS_OID);
1791 
1792  /*
1793  * We have to fetch the pg_opclass row to determine its opfamily and
1794  * opcintype, which are needed to look up related operators and functions.
1795  * It'd be convenient to use the syscache here, but that probably doesn't
1796  * work while bootstrapping.
1797  */
1798  ScanKeyInit(&skey[0],
1800  BTEqualStrategyNumber, F_OIDEQ,
1801  ObjectIdGetDatum(operatorClassOid));
1803  scan = systable_beginscan(rel, OpclassOidIndexId, indexOK,
1804  NULL, 1, skey);
1805 
1806  if (HeapTupleIsValid(htup = systable_getnext(scan)))
1807  {
1808  Form_pg_opclass opclassform = (Form_pg_opclass) GETSTRUCT(htup);
1809 
1810  opcentry->opcfamily = opclassform->opcfamily;
1811  opcentry->opcintype = opclassform->opcintype;
1812  }
1813  else
1814  elog(ERROR, "could not find tuple for opclass %u", operatorClassOid);
1815 
1816  systable_endscan(scan);
1818 
1819  /*
1820  * Scan pg_amproc to obtain support procs for the opclass. We only fetch
1821  * the default ones (those with lefttype = righttype = opcintype).
1822  */
1823  if (numSupport > 0)
1824  {
1825  ScanKeyInit(&skey[0],
1827  BTEqualStrategyNumber, F_OIDEQ,
1828  ObjectIdGetDatum(opcentry->opcfamily));
1829  ScanKeyInit(&skey[1],
1831  BTEqualStrategyNumber, F_OIDEQ,
1832  ObjectIdGetDatum(opcentry->opcintype));
1833  ScanKeyInit(&skey[2],
1835  BTEqualStrategyNumber, F_OIDEQ,
1836  ObjectIdGetDatum(opcentry->opcintype));
1838  scan = systable_beginscan(rel, AccessMethodProcedureIndexId, indexOK,
1839  NULL, 3, skey);
1840 
1841  while (HeapTupleIsValid(htup = systable_getnext(scan)))
1842  {
1843  Form_pg_amproc amprocform = (Form_pg_amproc) GETSTRUCT(htup);
1844 
1845  if (amprocform->amprocnum <= 0 ||
1846  (StrategyNumber) amprocform->amprocnum > numSupport)
1847  elog(ERROR, "invalid amproc number %d for opclass %u",
1848  amprocform->amprocnum, operatorClassOid);
1849 
1850  opcentry->supportProcs[amprocform->amprocnum - 1] =
1851  amprocform->amproc;
1852  }
1853 
1854  systable_endscan(scan);
1856  }
1857 
1858  opcentry->valid = true;
1859  return opcentry;
1860 }
struct opclasscacheent OpClassCacheEnt
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:493
#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:392
#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:853
#define OID_BTREE_OPS_OID
Definition: pg_opclass.h:143
#define heap_close(r, l)
Definition: heapam.h:97
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
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:322
StrategyNumber numSupport
Definition: relcache.c:235
#define Anum_pg_amproc_amproclefttype
Definition: pg_amproc.h:67
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:410
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
RegProcedure * supportProcs
Definition: relcache.c:238
#define Anum_pg_amproc_amprocfamily
Definition: pg_amproc.h:66
static HTAB * OpClassCache
Definition: relcache.c:241
#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:301
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1287
Size keysize
Definition: hsearch.h:72
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:784
#define OpclassOidIndexId
Definition: indexing.h:193
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
void CreateCacheMemoryContext(void)
Definition: catcache.c:525
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:128
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 1232 of file relcache.c.

References AllocateRelationDesc(), Assert, BackendIdForTempRelations, elog, ERROR, GETSTRUCT, GetTempNamespaceBackendId(), heap_freetuple(), HeapTupleGetOid, HeapTupleIsValid, InvalidBackendId, InvalidSubTransactionId, isTempOrTempToastNamespace(), NIL, NULL, 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().

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

References Assert, AssertArg, AttributeRelationId, tupleDesc::attrs, 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, NULL, 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, and TypeRelationId.

Referenced by heap_create().

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

Definition at line 826 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, tupleDesc::attrs, 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(), NULL, ObjectIdGetDatum, 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, and oidvector::values.

Referenced by RelationBuildDesc(), and RelationCacheInitializePhase3().

827 {
829  HeapTuple tuple;
830  bool isnull;
831  int i;
832  PartitionKey key;
833  AttrNumber *attrs;
834  oidvector *opclass;
835  oidvector *collation;
836  ListCell *partexprs_item;
837  Datum datum;
838  MemoryContext partkeycxt,
839  oldcxt;
840 
841  tuple = SearchSysCache1(PARTRELID,
843 
844  /*
845  * The following happens when we have created our pg_class entry but not
846  * the pg_partitioned_table entry yet.
847  */
848  if (!HeapTupleIsValid(tuple))
849  return;
850 
851  key = (PartitionKey) palloc0(sizeof(PartitionKeyData));
852 
853  /* Fixed-length attributes */
854  form = (Form_pg_partitioned_table) GETSTRUCT(tuple);
855  key->strategy = form->partstrat;
856  key->partnatts = form->partnatts;
857 
858  /*
859  * We can rely on the first variable-length attribute being mapped to the
860  * relevant field of the catalog's C struct, because all previous
861  * attributes are non-nullable and fixed-length.
862  */
863  attrs = form->partattrs.values;
864 
865  /* But use the hard way to retrieve further variable-length attributes */
866  /* Operator class */
867  datum = SysCacheGetAttr(PARTRELID, tuple,
869  Assert(!isnull);
870  opclass = (oidvector *) DatumGetPointer(datum);
871 
872  /* Collation */
873  datum = SysCacheGetAttr(PARTRELID, tuple,
875  Assert(!isnull);
876  collation = (oidvector *) DatumGetPointer(datum);
877 
878  /* Expressions */
879  datum = SysCacheGetAttr(PARTRELID, tuple,
881  if (!isnull)
882  {
883  char *exprString;
884  Node *expr;
885 
886  exprString = TextDatumGetCString(datum);
887  expr = stringToNode(exprString);
888  pfree(exprString);
889 
890  /*
891  * Run the expressions through const-simplification since the planner
892  * will be comparing them to similarly-processed qual clause operands,
893  * and may fail to detect valid matches without this step. We don't
894  * need to bother with canonicalize_qual() though, because partition
895  * expressions are not full-fledged qualification clauses.
896  */
897  expr = eval_const_expressions(NULL, (Node *) expr);
898 
899  /* May as well fix opfuncids too */
900  fix_opfuncids((Node *) expr);
901  key->partexprs = (List *) expr;
902  }
903 
904  key->partattrs = (AttrNumber *) palloc0(key->partnatts * sizeof(AttrNumber));
905  key->partopfamily = (Oid *) palloc0(key->partnatts * sizeof(Oid));
906  key->partopcintype = (Oid *) palloc0(key->partnatts * sizeof(Oid));
907  key->partsupfunc = (FmgrInfo *) palloc0(key->partnatts * sizeof(FmgrInfo));
908 
909  key->partcollation = (Oid *) palloc0(key->partnatts * sizeof(Oid));
910 
911  /* Gather type and collation info as well */
912  key->parttypid = (Oid *) palloc0(key->partnatts * sizeof(Oid));
913  key->parttypmod = (int32 *) palloc0(key->partnatts * sizeof(int32));
914  key->parttyplen = (int16 *) palloc0(key->partnatts * sizeof(int16));
915  key->parttypbyval = (bool *) palloc0(key->partnatts * sizeof(bool));
916  key->parttypalign = (char *) palloc0(key->partnatts * sizeof(char));
917  key->parttypcoll = (Oid *) palloc0(key->partnatts * sizeof(Oid));
918 
919  /* Copy partattrs and fill other per-attribute info */
920  memcpy(key->partattrs, attrs, key->partnatts * sizeof(int16));
921  partexprs_item = list_head(key->partexprs);
922  for (i = 0; i < key->partnatts; i++)
923  {
924  AttrNumber attno = key->partattrs[i];
925  HeapTuple opclasstup;
926  Form_pg_opclass opclassform;
927  Oid funcid;
928 
929  /* Collect opfamily information */
930  opclasstup = SearchSysCache1(CLAOID,
931  ObjectIdGetDatum(opclass->values[i]));
932  if (!HeapTupleIsValid(opclasstup))
933  elog(ERROR, "cache lookup failed for opclass %u", opclass->values[i]);
934 
935  opclassform = (Form_pg_opclass) GETSTRUCT(opclasstup);
936  key->partopfamily[i] = opclassform->opcfamily;
937  key->partopcintype[i] = opclassform->opcintype;
938 
939  /*
940  * A btree support function covers the cases of list and range methods
941  * currently supported.
942  */
943  funcid = get_opfamily_proc(opclassform->opcfamily,
944  opclassform->opcintype,
945  opclassform->opcintype,
946  BTORDER_PROC);
947 
948  fmgr_info(funcid, &key->partsupfunc[i]);
949 
950  /* Collation */
951  key->partcollation[i] = collation->values[i];
952 
953  /* Collect type information */
954  if (attno != 0)
955  {
956  key->parttypid[i] = relation->rd_att->attrs[attno - 1]->atttypid;
957  key->parttypmod[i] = relation->rd_att->attrs[attno - 1]->atttypmod;
958  key->parttypcoll[i] = relation->rd_att->attrs[attno - 1]->attcollation;
959  }
960  else
961  {
962  key->parttypid[i] = exprType(lfirst(partexprs_item));
963  key->parttypmod[i] = exprTypmod(lfirst(partexprs_item));
964  key->parttypcoll[i] = exprCollation(lfirst(partexprs_item));
965  }
967  &key->parttyplen[i],
968  &key->parttypbyval[i],
969  &key->parttypalign[i]);
970 
971  ReleaseSysCache(opclasstup);
972  }
973 
974  ReleaseSysCache(tuple);
975 
976  /* Success --- now copy to the cache memory */
978  RelationGetRelationName(relation),
980  relation->rd_partkeycxt = partkeycxt;
981  oldcxt = MemoryContextSwitchTo(relation->rd_partkeycxt);
982  relation->rd_partkey = copy_partition_key(key);
983  MemoryContextSwitchTo(oldcxt);
984 }
signed short int16
Definition: c.h:252
Definition: c.h:474
Definition: fmgr.h:53
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:273
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:1989
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1591
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:155
Form_pg_attribute * attrs
Definition: tupdesc.h:74
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:508
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2366
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 SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
signed int int32
Definition: c.h:253
void pfree(void *pointer)
Definition: mcxt.c:992
Oid * parttypcoll
Definition: rel.h:74
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:159
struct PartitionKeyData * rd_partkey
Definition: rel.h:128
#define Anum_pg_partitioned_table_partcollation
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:482
#define RelationGetRelationName(relation)
Definition: rel.h:433
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
Oid * parttypid
Definition: rel.h:69
Oid * partcollation
Definition: rel.h:66
#define TextDatumGetCString(d)
Definition: builtins.h:91
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:440
void * palloc0(Size size)
Definition: mcxt.c:920
AttrNumber * partattrs
Definition: rel.h:56
uintptr_t Datum
Definition: postgres.h:374
int16 partnatts
Definition: rel.h:55
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
char * parttypalign
Definition: rel.h:73
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1245
TupleDesc rd_att
Definition: rel.h:114
int32 * parttypmod
Definition: rel.h:70
bool * parttypbyval
Definition: rel.h:72
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
int16 * parttyplen
Definition: rel.h:71
MemoryContext rd_partkeycxt
Definition: rel.h:127
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:745
#define DatumGetPointer(X)
Definition: postgres.h:557
struct PartitionKeyData * PartitionKey
Definition: rel.h:77
static PartitionKey copy_partition_key(PartitionKey fromkey)
Definition: relcache.c:992
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:413
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static void RelationBuildRuleLock ( Relation  relation)
static

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

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

Referenced by RelationBuildDesc().

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

Definition at line 5982 of file relcache.c.

References LWLockRelease().

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

5983 {
5984  LWLockRelease(RelCacheInitLock);
5985 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
void RelationCacheInitFilePreInvalidate ( void  )

Definition at line 5956 of file relcache.c.

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

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

5957 {
5958  char initfilename[MAXPGPATH];
5959 
5960  snprintf(initfilename, sizeof(initfilename), "%s/%s",
5962 
5963  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
5964 
5965  if (unlink(initfilename) < 0)
5966  {
5967  /*
5968  * The file might not be there if no backend has been started since
5969  * the last removal. But complain about failures other than ENOENT.
5970  * Fortunately, it's not too late to abort the transaction if we can't
5971  * get rid of the would-be-obsolete init file.
5972  */
5973  if (errno != ENOENT)
5974  ereport(ERROR,
5976  errmsg("could not remove cache file \"%s\": %m",
5977  initfilename)));
5978  }
5979 }
#define RELCACHE_INIT_FILENAME
Definition: relcache.c:92
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
int unlink(const char *filename)
#define ereport(elevel, rest)
Definition: elog.h:122
char * DatabasePath
Definition: globals.c:84
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
int errmsg(const char *fmt,...)
Definition: elog.c:797
void RelationCacheInitFileRemove ( void  )

Definition at line 5997 of file relcache.c.

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

Referenced by StartupXLOG().

5998 {
5999  const char *tblspcdir = "pg_tblspc";
6000  DIR *dir;
6001  struct dirent *de;
6002  char path[MAXPGPATH];
6003 
6004  /*
6005  * We zap the shared cache file too. In theory it can't get out of sync
6006  * enough to be a problem, but in data-corruption cases, who knows ...
6007  */
6008  snprintf(path, sizeof(path), "global/%s",
6010  unlink_initfile(path);
6011 
6012  /* Scan everything in the default tablespace */
6014 
6015  /* Scan the tablespace link directory to find non-default tablespaces */
6016  dir = AllocateDir(tblspcdir);
6017  if (dir == NULL)
6018  {
6019  elog(LOG, "could not open tablespace link directory \"%s\": %m",
6020  tblspcdir);
6021  return;
6022  }
6023 
6024  while ((de = ReadDir(dir, tblspcdir)) != NULL)
6025  {
6026  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6027  {
6028  /* Scan the tablespace dir for per-database dirs */
6029  snprintf(path, sizeof(path), "%s/%s/%s",
6030  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6032  }
6033  }
6034 
6035  FreeDir(dir);
6036 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6040
#define RELCACHE_INIT_FILENAME
Definition: relcache.c:92
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:2284
static void unlink_initfile(const char *initfilename)
Definition: relcache.c:6070
#define NULL
Definition: c.h:226
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2350
#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:2393
static void RelationCacheInitFileRemoveInDir ( const char *  tblspcpath)
static

Definition at line 6040 of file relcache.c.

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

Referenced by RelationCacheInitFileRemove().

6041 {
6042  DIR *dir;
6043  struct dirent *de;
6044  char initfilename[MAXPGPATH];
6045 
6046  /* Scan the tablespace directory to find per-database directories */
6047  dir = AllocateDir(tblspcpath);
6048  if (dir == NULL)
6049  {
6050  elog(LOG, "could not open tablespace directory \"%s\": %m",
6051  tblspcpath);
6052  return;
6053  }
6054 
6055  while ((de = ReadDir(dir, tblspcpath)) != NULL)
6056  {
6057  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6058  {
6059  /* Try to remove the init file in each database */
6060  snprintf(initfilename, sizeof(initfilename), "%s/%s/%s",
6061  tblspcpath, de->d_name, RELCACHE_INIT_FILENAME);
6062  unlink_initfile(initfilename);
6063  }
6064  }
6065 
6066  FreeDir(dir);
6067 }
#define RELCACHE_INIT_FILENAME
Definition: relcache.c:92
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:2284
static void unlink_initfile(const char *initfilename)
Definition: relcache.c:6070
#define NULL
Definition: c.h:226
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2350
char d_name[MAX_PATH]
Definition: dirent.h:14
#define elog
Definition: elog.h:219
int FreeDir(DIR *dir)
Definition: fd.c:2393
void RelationCacheInitialize ( void  )

Definition at line 3526 of file relcache.c.

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

Referenced by InitPostgres().

3527 {
3528  HASHCTL ctl;
3529 
3530  /*
3531  * make sure cache memory context exists
3532  */
3533  if (!CacheMemoryContext)
3535 
3536  /*
3537  * create hashtable that indexes the relcache
3538  */
3539  MemSet(&ctl, 0, sizeof(ctl));
3540  ctl.keysize = sizeof(Oid);
3541  ctl.entrysize = sizeof(RelIdCacheEnt);
3542  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3543  &ctl, HASH_ELEM | HASH_BLOBS);
3544 
3545  /*
3546  * relation mapper needs to be initialized too
3547  */
3549 }
void RelationMapInitialize(void)
Definition: relmapper.c:561
#define HASH_ELEM
Definition: hsearch.h:87
struct relidcacheent RelIdCacheEnt
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:853
static HTAB * RelationIdCache
Definition: relcache.c:122
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:301
Size keysize
Definition: hsearch.h:72
void CreateCacheMemoryContext(void)
Definition: catcache.c:525
#define INITRELCACHESIZE
Definition: relcache.c:3523
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void RelationCacheInitializePhase2 ( void  )

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

3564 {
3565  MemoryContext oldcxt;
3566 
3567  /*
3568  * relation mapper needs initialized too
3569  */
3571 
3572  /*
3573  * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3574  * nothing.
3575  */
3577  return;
3578 
3579  /*
3580  * switch to cache memory context
3581  */
3583 
3584  /*
3585  * Try to load the shared relcache cache file. If unsuccessful, bootstrap
3586  * the cache with pre-made descriptors for the critical shared catalogs.
3587  */
3588  if (!load_relcache_init_file(true))
3589  {
3590  formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
3592  formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
3594  formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
3596  formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
3598  formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
3600 
3601 #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
3602  }
3603 
3604  MemoryContextSwitchTo(oldcxt);
3605 }
static const FormData_pg_attribute Desc_pg_auth_members[Natts_pg_auth_members]
Definition: relcache.c:105
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5273
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, bool hasoids, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1886
#define SubscriptionRelation_Rowtype_Id
void RelationMapInitializePhase2(void)
Definition: relmapper.c:581
#define Natts_pg_database
Definition: pg_database.h:63
static const FormData_pg_attribute Desc_pg_authid[Natts_pg_authid]
Definition: relcache.c:104
static const FormData_pg_attribute Desc_pg_subscription[Natts_pg_subscription]
Definition: relcache.c:108
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:103
#define Natts_pg_shseclabel
Definition: pg_shseclabel.h:41
static const FormData_pg_attribute Desc_pg_shseclabel[Natts_pg_shseclabel]
Definition: relcache.c:107
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:365
#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 3622 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, NULL, 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().

3623 {
3625  RelIdCacheEnt *idhentry;
3626  MemoryContext oldcxt;
3627  bool needNewCacheFile = !criticalSharedRelcachesBuilt;
3628 
3629  /*
3630  * relation mapper needs initialized too
3631  */
3633 
3634  /*
3635  * switch to cache memory context
3636  */
3638 
3639  /*
3640  * Try to load the local relcache cache file. If unsuccessful, bootstrap
3641  * the cache with pre-made descriptors for the critical "nailed-in" system
3642  * catalogs.
3643  */
3644  if (IsBootstrapProcessingMode() ||
3645  !load_relcache_init_file(false))
3646  {
3647  needNewCacheFile = true;
3648 
3649  formrdesc("pg_class", RelationRelation_Rowtype_Id, false,
3650  true, Natts_pg_class, Desc_pg_class);
3651  formrdesc("pg_attribute", AttributeRelation_Rowtype_Id, false,
3653  formrdesc("pg_proc", ProcedureRelation_Rowtype_Id, false,
3654  true, Natts_pg_proc, Desc_pg_proc);
3655  formrdesc("pg_type", TypeRelation_Rowtype_Id, false,
3656  true, Natts_pg_type, Desc_pg_type);
3657 
3658 #define NUM_CRITICAL_LOCAL_RELS 4 /* fix if you change list above */
3659  }
3660 
3661  MemoryContextSwitchTo(oldcxt);
3662 
3663  /* In bootstrap mode, the faked-up formrdesc info is all we'll have */
3665  return;
3666 
3667  /*
3668  * If we didn't get the critical system indexes loaded into relcache, do
3669  * so now. These are critical because the catcache and/or opclass cache
3670  * depend on them for fetches done during relcache load. Thus, we have an
3671  * infinite-recursion problem. We can break the recursion by doing
3672  * heapscans instead of indexscans at certain key spots. To avoid hobbling
3673  * performance, we only want to do that until we have the critical indexes
3674  * loaded into relcache. Thus, the flag criticalRelcachesBuilt is used to
3675  * decide whether to do heapscan or indexscan at the key spots, and we set
3676  * it true after we've loaded the critical indexes.
3677  *
3678  * The critical indexes are marked as "nailed in cache", partly to make it
3679  * easy for load_relcache_init_file to count them, but mainly because we
3680  * cannot flush and rebuild them once we've set criticalRelcachesBuilt to
3681  * true. (NOTE: perhaps it would be possible to reload them by
3682  * temporarily setting criticalRelcachesBuilt to false again. For now,
3683  * though, we just nail 'em in.)
3684  *
3685  * RewriteRelRulenameIndexId and TriggerRelidNameIndexId are not critical
3686  * in the same way as the others, because the critical catalogs don't
3687  * (currently) have any rules or triggers, and so these indexes can be
3688  * rebuilt without inducing recursion. However they are used during
3689  * relcache load when a rel does have rules or triggers, so we choose to
3690  * nail them for performance reasons.
3691  */
3693  {
3699  IndexRelationId);
3708 
3709 #define NUM_CRITICAL_LOCAL_INDEXES 7 /* fix if you change list above */
3710 
3711  criticalRelcachesBuilt = true;
3712  }
3713 
3714  /*
3715  * Process critical shared indexes too.
3716  *
3717  * DatabaseNameIndexId isn't critical for relcache loading, but rather for
3718  * initial lookup of MyDatabaseId, without which we'll never find any
3719  * non-shared catalogs at all. Autovacuum calls InitPostgres with a
3720  * database OID, so it instead depends on DatabaseOidIndexId. We also
3721  * need to nail up some indexes on pg_authid and pg_auth_members for use
3722  * during client authentication. SharedSecLabelObjectIndexId isn't
3723  * critical for the core system, but authentication hooks might be
3724  * interested in it.
3725  */
3727  {
3740 
3741 #define NUM_CRITICAL_SHARED_INDEXES 6 /* fix if you change list above */
3742 
3744  }
3745 
3746  /*
3747  * Now, scan all the relcache entries and update anything that might be
3748  * wrong in the results from formrdesc or the relcache cache file. If we
3749  * faked up relcache entries using formrdesc, then read the real pg_class
3750  * rows and replace the fake entries with them. Also, if any of the
3751  * relcache entries have rules, triggers, or security policies, load that
3752  * info the hard way since it isn't recorded in the cache file.
3753  *
3754  * Whenever we access the catalogs to read data, there is a possibility of
3755  * a shared-inval cache flush causing relcache entries to be removed.
3756  * Since hash_seq_search only guarantees to still work after the *current*
3757  * entry is removed, it's unsafe to continue the hashtable scan afterward.
3758  * We handle this by restarting the scan from scratch after each access.
3759  * This is theoretically O(N^2), but the number of entries that actually
3760  * need to be fixed is small enough that it doesn't matter.
3761  */
3762  hash_seq_init(&status, RelationIdCache);
3763 
3764  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3765  {
3766  Relation relation = idhentry->reldesc;
3767  bool restart = false;
3768 
3769  /*
3770  * Make sure *this* entry doesn't get flushed while we work with it.
3771  */
3773 
3774  /*
3775  * If it's a faked-up entry, read the real pg_class tuple.
3776  */
3777  if (relation->rd_rel->relowner == InvalidOid)
3778  {
3779  HeapTuple htup;
3780  Form_pg_class relp;
3781 
3782  htup = SearchSysCache1(RELOID,
3783  ObjectIdGetDatum(RelationGetRelid(relation)));
3784  if (!HeapTupleIsValid(htup))
3785  elog(FATAL, "cache lookup failed for relation %u",
3786  RelationGetRelid(relation));
3787  relp = (Form_pg_class) GETSTRUCT(htup);
3788 
3789  /*
3790  * Copy tuple to relation->rd_rel. (See notes in
3791  * AllocateRelationDesc())
3792  */
3793  memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
3794 
3795  /* Update rd_options while we have the tuple */
3796  if (relation->rd_options)
3797  pfree(relation->rd_options);
3798  RelationParseRelOptions(relation, htup);
3799 
3800  /*
3801  * Check the values in rd_att were set up correctly. (We cannot
3802  * just copy them over now: formrdesc must have set up the rd_att
3803  * data correctly to start with, because it may already have been
3804  * copied into one or more catcache entries.)
3805  */
3806  Assert(relation->rd_att->tdtypeid == relp->reltype);
3807  Assert(relation->rd_att->tdtypmod == -1);
3808  Assert(relation->rd_att->tdhasoid == relp->relhasoids);
3809 
3810  ReleaseSysCache(htup);
3811 
3812  /* relowner had better be OK now, else we'll loop forever */
3813  if (relation->rd_rel->relowner == InvalidOid)
3814  elog(ERROR, "invalid relowner in pg_class entry for \"%s\"",
3815  RelationGetRelationName(relation));
3816 
3817  restart = true;
3818  }
3819 
3820  /*
3821  * Fix data that isn't saved in relcache cache file.
3822  *
3823  * relhasrules or relhastriggers could possibly be wrong or out of
3824  * date. If we don't actually find any rules or triggers, clear the
3825  * local copy of the flag so that we don't get into an infinite loop
3826  * here. We don't make any attempt to fix the pg_class entry, though.
3827  */
3828  if (relation->rd_rel->relhasrules && relation->rd_rules == NULL)
3829  {
3830  RelationBuildRuleLock(relation);
3831  if (relation->rd_rules == NULL)
3832  relation->rd_rel->relhasrules = false;
3833  restart = true;
3834  }
3835  if (relation->rd_rel->relhastriggers && relation->trigdesc == NULL)
3836  {
3837  RelationBuildTriggers(relation);
3838  if (relation->trigdesc == NULL)
3839  relation->rd_rel->relhastriggers = false;
3840  restart = true;
3841  }
3842 
3843  /*
3844