PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
relcache.c File Reference
#include "postgres.h"
#include <sys/file.h>
#include <fcntl.h>
#include <unistd.h>
#include "access/htup_details.h"
#include "access/multixact.h"
#include "access/nbtree.h"
#include "access/reloptions.h"
#include "access/sysattr.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "catalog/catalog.h"
#include "catalog/index.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/partition.h"
#include "catalog/pg_am.h"
#include "catalog/pg_amproc.h"
#include "catalog/pg_attrdef.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_auth_members.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_database.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_partitioned_table.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_publication.h"
#include "catalog/pg_rewrite.h"
#include "catalog/pg_shseclabel.h"
#include "catalog/pg_statistic_ext.h"
#include "catalog/pg_subscription.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
#include "catalog/schemapg.h"
#include "catalog/storage.h"
#include "commands/policy.h"
#include "commands/trigger.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/prep.h"
#include "optimizer/var.h"
#include "rewrite/rewriteDefine.h"
#include "rewrite/rowsecurity.h"
#include "storage/lmgr.h"
#include "storage/smgr.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/relmapper.h"
#include "utils/resowner_private.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "utils/tqual.h"
Include dependency graph for relcache.c:

Go to the source code of this file.

Data Structures

struct  relidcacheent
 
struct  opclasscacheent
 

Macros

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

Typedefs

typedef struct relidcacheent RelIdCacheEnt
 
typedef struct opclasscacheent OpClassCacheEnt
 

Functions

static void RelationDestroyRelation (Relation relation, bool remember_tupdesc)
 
static void RelationClearRelation (Relation relation, bool rebuild)
 
static void RelationReloadIndexInfo (Relation relation)
 
static void RelationFlushRelation (Relation relation)
 
static void RememberToFreeTupleDescAtEOX (TupleDesc td)
 
static void AtEOXact_cleanup (Relation relation, bool isCommit)
 
static void AtEOSubXact_cleanup (Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
 
static bool load_relcache_init_file (bool shared)
 
static void write_relcache_init_file (bool shared)
 
static void write_item (const void *data, Size len, FILE *fp)
 
static void formrdesc (const char *relationName, Oid relationReltype, bool isshared, bool hasoids, int natts, const FormData_pg_attribute *attrs)
 
static HeapTuple ScanPgRelation (Oid targetRelId, bool indexOK, bool force_non_historic)
 
static Relation AllocateRelationDesc (Form_pg_class relp)
 
static void RelationParseRelOptions (Relation relation, HeapTuple tuple)
 
static void RelationBuildTupleDesc (Relation relation)
 
static void RelationBuildPartitionKey (Relation relation)
 
static PartitionKey copy_partition_key (PartitionKey fromkey)
 
static Relation RelationBuildDesc (Oid targetRelId, bool insertIt)
 
static void RelationInitPhysicalAddr (Relation relation)
 
static void load_critical_index (Oid indexoid, Oid heapoid)
 
static TupleDesc GetPgClassDescriptor (void)
 
static TupleDesc GetPgIndexDescriptor (void)
 
static void AttrDefaultFetch (Relation relation)
 
static void CheckConstraintFetch (Relation relation)
 
static int CheckConstraintCmp (const void *a, const void *b)
 
static Listinsert_ordered_oid (List *list, Oid datum)
 
static void InitIndexAmRoutine (Relation relation)
 
static void IndexSupportInitialize (oidvector *indclass, RegProcedure *indexSupport, Oid *opFamily, Oid *opcInType, StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber)
 
static OpClassCacheEntLookupOpclassInfo (Oid operatorClassOid, StrategyNumber numSupport)
 
static void RelationCacheInitFileRemoveInDir (const char *tblspcpath)
 
static void unlink_initfile (const char *initfilename)
 
static bool equalPartitionDescs (PartitionKey key, PartitionDesc partdesc1, PartitionDesc partdesc2)
 
static void RelationBuildRuleLock (Relation relation)
 
static bool equalRuleLocks (RuleLock *rlock1, RuleLock *rlock2)
 
static bool equalPolicy (RowSecurityPolicy *policy1, RowSecurityPolicy *policy2)
 
static bool equalRSDesc (RowSecurityDesc *rsdesc1, RowSecurityDesc *rsdesc2)
 
void RelationInitIndexAccessInfo (Relation relation)
 
Relation RelationIdGetRelation (Oid relationId)
 
void RelationIncrementReferenceCount (Relation rel)
 
void RelationDecrementReferenceCount (Relation rel)
 
void RelationClose (Relation relation)
 
void RelationForgetRelation (Oid rid)
 
void RelationCacheInvalidateEntry (Oid relationId)
 
void RelationCacheInvalidate (void)
 
void RelationCloseSmgrByOid (Oid relationId)
 
void AtEOXact_RelationCache (bool isCommit)
 
void AtEOSubXact_RelationCache (bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
 
Relation RelationBuildLocalRelation (const char *relname, Oid relnamespace, TupleDesc tupDesc, Oid relid, Oid relfilenode, Oid reltablespace, bool shared_relation, bool mapped_relation, char relpersistence, char relkind)
 
void RelationSetNewRelfilenode (Relation relation, char persistence, TransactionId freezeXid, MultiXactId minmulti)
 
void RelationCacheInitialize (void)
 
void RelationCacheInitializePhase2 (void)
 
void RelationCacheInitializePhase3 (void)
 
static TupleDesc BuildHardcodedDescriptor (int natts, const FormData_pg_attribute *attrs, bool hasoids)
 
ListRelationGetFKeyList (Relation relation)
 
ListRelationGetIndexList (Relation relation)
 
ListRelationGetStatExtList (Relation relation)
 
void RelationSetIndexList (Relation relation, List *indexIds, Oid oidIndex)
 
Oid RelationGetOidIndex (Relation relation)
 
Oid RelationGetPrimaryKeyIndex (Relation relation)
 
Oid RelationGetReplicaIndex (Relation relation)
 
ListRelationGetIndexExpressions (Relation relation)
 
ListRelationGetIndexPredicate (Relation relation)
 
BitmapsetRelationGetIndexAttrBitmap (Relation relation, IndexAttrBitmapKind attrKind)
 
void RelationGetExclusionInfo (Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
 
struct PublicationActionsGetRelationPublicationActions (Relation relation)
 
int errtable (Relation rel)
 
int errtablecol (Relation rel, int attnum)
 
int errtablecolname (Relation rel, const char *colname)
 
int errtableconstraint (Relation rel, const char *conname)
 
bool RelationIdIsInInitFile (Oid relationId)
 
bool RelationHasUnloggedIndex (Relation rel)
 
void RelationCacheInitFilePreInvalidate (void)
 
void RelationCacheInitFilePostInvalidate (void)
 
void RelationCacheInitFileRemove (void)
 

Variables

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

Macro Definition Documentation

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

Definition at line 160 of file relcache.c.

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

#define INITRELCACHESIZE   400

Definition at line 3525 of file relcache.c.

Referenced by RelationCacheInitialize().

#define MAX_EOXACT_LIST   32

Definition at line 155 of file relcache.c.

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

Referenced by load_relcache_init_file().

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

Referenced by load_relcache_init_file().

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

Referenced by load_relcache_init_file().

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

Referenced by load_relcache_init_file().

#define RelationCacheDelete (   RELATION)
Value:
do { \
RelIdCacheEnt *hentry; \
(void *) &((RELATION)->rd_id), \
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:123
#define WARNING
Definition: elog.h:40
#define NULL
Definition: c.h:229
#define elog
Definition: elog.h:219

Definition at line 214 of file relcache.c.

Referenced by RelationClearRelation().

#define RelationCacheInsert (   RELATION,
  replace_allowed 
)
Value:
do { \
RelIdCacheEnt *hentry; bool found; \
(void *) &((RELATION)->rd_id), \
HASH_ENTER, &found); \
if (found) \
{ \
/* see comments in RelationBuildDesc and RelationBuildLocalRelation */ \
Relation _old_rel = hentry->reldesc; \
Assert(replace_allowed); \
hentry->reldesc = (RELATION); \
RelationDestroyRelation(_old_rel, false); \
elog(WARNING, "leaking still-referenced relcache entry for \"%s\"", \
} \
else \
hentry->reldesc = (RELATION); \
} while(0)
struct relidcacheent RelIdCacheEnt
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
static HTAB * RelationIdCache
Definition: relcache.c:123
struct RelationData * Relation
Definition: relcache.h:21
#define RelationGetRelationName(relation)
Definition: rel.h:436
#define WARNING
Definition: elog.h:40
static void RelationDestroyRelation(Relation relation, bool remember_tupdesc)
Definition: relcache.c:2304
#define Assert(condition)
Definition: c.h:675
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:400
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:370
#define elog
Definition: elog.h:219

Definition at line 180 of file relcache.c.

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

#define RelationIdCacheLookup (   ID,
  RELATION 
)
Value:
do { \
RelIdCacheEnt *hentry; \
(void *) &(ID), \
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:123
#define NULL
Definition: c.h:229

Definition at line 202 of file relcache.c.

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

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

Definition at line 95 of file relcache.c.

Referenced by load_relcache_init_file(), and write_relcache_init_file().

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

Referenced by RelationClearRelation().

Typedef Documentation

Function Documentation

static Relation AllocateRelationDesc ( Form_pg_class  relp)
static

Definition at line 379 of file relcache.c.

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

Referenced by RelationBuildDesc().

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

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

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

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

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

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

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

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

4016 {
4017  AttrDefault *attrdef = relation->rd_att->constr->defval;
4018  int ndef = relation->rd_att->constr->num_defval;
4019  Relation adrel;
4020  SysScanDesc adscan;
4021  ScanKeyData skey;
4022  HeapTuple htup;
4023  Datum val;
4024  bool isnull;
4025  int found;
4026  int i;
4027 
4028  ScanKeyInit(&skey,
4030  BTEqualStrategyNumber, F_OIDEQ,
4031  ObjectIdGetDatum(RelationGetRelid(relation)));
4032 
4034  adscan = systable_beginscan(adrel, AttrDefaultIndexId, true,
4035  NULL, 1, &skey);
4036  found = 0;
4037 
4038  while (HeapTupleIsValid(htup = systable_getnext(adscan)))
4039  {
4040  Form_pg_attrdef adform = (Form_pg_attrdef) GETSTRUCT(htup);
4041 
4042  for (i = 0; i < ndef; i++)
4043  {
4044  if (adform->adnum != attrdef[i].adnum)
4045  continue;
4046  if (attrdef[i].adbin != NULL)
4047  elog(WARNING, "multiple attrdef records found for attr %s of rel %s",
4048  NameStr(relation->rd_att->attrs[adform->adnum - 1]->attname),
4049  RelationGetRelationName(relation));
4050  else
4051  found++;
4052 
4053  val = fastgetattr(htup,
4055  adrel->rd_att, &isnull);
4056  if (isnull)
4057  elog(WARNING, "null adbin for attr %s of rel %s",
4058  NameStr(relation->rd_att->attrs[adform->adnum - 1]->attname),
4059  RelationGetRelationName(relation));
4060  else
4061  {
4062  /* detoast and convert to cstring in caller's context */
4063  char *s = TextDatumGetCString(val);
4064 
4066  pfree(s);
4067  }
4068  break;
4069  }
4070 
4071  if (i >= ndef)
4072  elog(WARNING, "unexpected attrdef record found for attr %d of rel %s",
4073  adform->adnum, RelationGetRelationName(relation));
4074  }
4075 
4076  systable_endscan(adscan);
4077  heap_close(adrel, AccessShareLock);
4078 
4079  if (found != ndef)
4080  elog(WARNING, "%d attrdef record(s) missing for rel %s",
4081  ndef - found, RelationGetRelationName(relation));
4082 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:719
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:328
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
void pfree(void *pointer)
Definition: mcxt.c:950
AttrDefault * defval
Definition: tupdesc.h:39
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define AttrDefaultIndexId
Definition: indexing.h:87
AttrNumber adnum
Definition: tupdesc.h:24
#define RelationGetRelationName(relation)
Definition: rel.h:436
char * adbin
Definition: tupdesc.h:25
FormData_pg_attrdef * Form_pg_attrdef
Definition: pg_attrdef.h:47
#define WARNING
Definition: elog.h:40
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
TupleDesc rd_att
Definition: rel.h:115
#define Anum_pg_attrdef_adrelid
Definition: pg_attrdef.h:54
uint16 num_defval
Definition: tupdesc.h:41
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
TupleConstr * constr
Definition: tupdesc.h:76
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1064
int i
#define NameStr(name)
Definition: c.h:499
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
#define AttrDefaultRelationId
Definition: pg_attrdef.h:29
#define RelationGetRelid(relation)
Definition: rel.h:416
long val
Definition: informix.c:689
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static TupleDesc BuildHardcodedDescriptor ( int  natts,
const FormData_pg_attribute attrs,
bool  hasoids 
)
static

Definition at line 3953 of file relcache.c.

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

Referenced by GetPgClassDescriptor(), and GetPgIndexDescriptor().

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

Definition at line 4159 of file relcache.c.

References constrCheck::ccname.

Referenced by CheckConstraintFetch().

4160 {
4161  const ConstrCheck *ca = (const ConstrCheck *) a;
4162  const ConstrCheck *cb = (const ConstrCheck *) b;
4163 
4164  return strcmp(ca->ccname, cb->ccname);
4165 }
char * ccname
Definition: tupdesc.h:30
static void CheckConstraintFetch ( Relation  relation)
static

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

4089 {
4090  ConstrCheck *check = relation->rd_att->constr->check;
4091  int ncheck = relation->rd_att->constr->num_check;
4092  Relation conrel;
4093  SysScanDesc conscan;
4094  ScanKeyData skey[1];
4095  HeapTuple htup;
4096  int found = 0;
4097 
4098  ScanKeyInit(&skey[0],
4100  BTEqualStrategyNumber, F_OIDEQ,
4101  ObjectIdGetDatum(RelationGetRelid(relation)));
4102 
4104  conscan = systable_beginscan(conrel, ConstraintRelidIndexId, true,
4105  NULL, 1, skey);
4106 
4107  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4108  {
4110  Datum val;
4111  bool isnull;
4112  char *s;
4113 
4114  /* We want check constraints only */
4115  if (conform->contype != CONSTRAINT_CHECK)
4116  continue;
4117 
4118  if (found >= ncheck)
4119  elog(ERROR, "unexpected constraint record found for rel %s",
4120  RelationGetRelationName(relation));
4121 
4122  check[found].ccvalid = conform->convalidated;
4123  check[found].ccnoinherit = conform->connoinherit;
4125  NameStr(conform->conname));
4126 
4127  /* Grab and test conbin is actually set */
4128  val = fastgetattr(htup,
4130  conrel->rd_att, &isnull);
4131  if (isnull)
4132  elog(ERROR, "null conbin for rel %s",
4133  RelationGetRelationName(relation));
4134 
4135  /* detoast and convert to cstring in caller's context */
4136  s = TextDatumGetCString(val);
4137  check[found].ccbin = MemoryContextStrdup(CacheMemoryContext, s);
4138  pfree(s);
4139 
4140  found++;
4141  }
4142 
4143  systable_endscan(conscan);
4144  heap_close(conrel, AccessShareLock);
4145 
4146  if (found != ncheck)
4147  elog(ERROR, "%d constraint record(s) missing for rel %s",
4148  ncheck - found, RelationGetRelationName(relation));
4149 
4150  /* Sort the records so that CHECKs are applied in a deterministic order */
4151  if (ncheck > 1)
4152  qsort(check, ncheck, sizeof(ConstrCheck), CheckConstraintCmp);
4153 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:719
char * ccname
Definition: tupdesc.h:30
bool ccnoinherit
Definition: tupdesc.h:33
ConstrCheck * check
Definition: tupdesc.h:40
char * ccbin
Definition: tupdesc.h:31
static int CheckConstraintCmp(const void *a, const void *b)
Definition: relcache.c:4159
#define AccessShareLock
Definition: lockdefs.h:36
#define heap_close(r, l)
Definition: heapam.h:97
#define Anum_pg_constraint_conbin
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
#define CONSTRAINT_CHECK
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
void pfree(void *pointer)
Definition: mcxt.c:950
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:436
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:372
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
TupleDesc rd_att
Definition: rel.h:115
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
TupleConstr * constr
Definition: tupdesc.h:76
bool ccvalid
Definition: tupdesc.h:32
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1064
#define NameStr(name)
Definition: c.h:499
#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:416
long val
Definition: informix.c:689
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define ConstraintRelidIndexId
Definition: indexing.h:126
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static PartitionKey copy_partition_key ( PartitionKey  fromkey)
static

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

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

Definition at line 1173 of file relcache.c.

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

Referenced by RelationClearRelation().

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

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

1095 {
1096  int i;
1097  Oid *r1,
1098  *r2;
1099 
1100  if (policy1 != NULL)
1101  {
1102  if (policy2 == NULL)
1103  return false;
1104 
1105  if (policy1->polcmd != policy2->polcmd)
1106  return false;
1107  if (policy1->hassublinks != policy2->hassublinks)
1108  return false;
1109  if (strcmp(policy1->policy_name, policy2->policy_name) != 0)
1110  return false;
1111  if (ARR_DIMS(policy1->roles)[0] != ARR_DIMS(policy2->roles)[0])
1112  return false;
1113 
1114  r1 = (Oid *) ARR_DATA_PTR(policy1->roles);
1115  r2 = (Oid *) ARR_DATA_PTR(policy2->roles);
1116 
1117  for (i = 0; i < ARR_DIMS(policy1->roles)[0]; i++)
1118  {
1119  if (r1[i] != r2[i])
1120  return false;
1121  }
1122 
1123  if (!equal(policy1->qual, policy2->qual))
1124  return false;
1125  if (!equal(policy1->with_check_qual, policy2->with_check_qual))
1126  return false;
1127  }
1128  else if (policy2 != NULL)
1129  return false;
1130 
1131  return true;
1132 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2962
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:229
int i
static bool equalRSDesc ( RowSecurityDesc rsdesc1,
RowSecurityDesc rsdesc2 
)
static

Definition at line 1140 of file relcache.c.

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

Referenced by RelationClearRelation().

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

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

Definition at line 5243 of file relcache.c.

References err_generic_string(), get_namespace_name(), PG_DIAG_SCHEMA_NAME, PG_DIAG_TABLE_NAME, RelationGetNamespace, and RelationGetRelationName.

Referenced by ATPrepChangePersistence(), BuildRelationExtStatistics(), errtablecolname(), and errtableconstraint().

5244 {
5248 
5249  return 0; /* return value does not matter */
5250 }
#define PG_DIAG_SCHEMA_NAME
Definition: postgres_ext.h:65
#define PG_DIAG_TABLE_NAME
Definition: postgres_ext.h:66
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
#define RelationGetRelationName(relation)
Definition: rel.h:436
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
#define RelationGetNamespace(relation)
Definition: rel.h:443
int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5260 of file relcache.c.

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

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

5261 {
5262  TupleDesc reldesc = RelationGetDescr(rel);
5263  const char *colname;
5264 
5265  /* Use reldesc if it's a user attribute, else consult the catalogs */
5266  if (attnum > 0 && attnum <= reldesc->natts)
5267  colname = NameStr(reldesc->attrs[attnum - 1]->attname);
5268  else
5269  colname = get_relid_attribute_name(RelationGetRelid(rel), attnum);
5270 
5271  return errtablecolname(rel, colname);
5272 }
#define RelationGetDescr(relation)
Definition: rel.h:428
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:499
#define RelationGetRelid(relation)
Definition: rel.h:416
int errtablecolname(Relation rel, const char *colname)
Definition: relcache.c:5284
int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5284 of file relcache.c.

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

Referenced by errtablecol().

5285 {
5286  errtable(rel);
5288 
5289  return 0; /* return value does not matter */
5290 }
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:67
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
int errtable(Relation rel)
Definition: relcache.c:5243
int errtableconstraint ( Relation  rel,
const char *  conname 
)

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

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

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

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

Definition at line 3984 of file relcache.c.

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

Referenced by RelationParseRelOptions().

3985 {
3986  static TupleDesc pgclassdesc = NULL;
3987 
3988  /* Already done? */
3989  if (pgclassdesc == NULL)
3991  Desc_pg_class,
3992  true);
3993 
3994  return pgclassdesc;
3995 }
#define Natts_pg_class
Definition: pg_class.h:102
static TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs, bool hasoids)
Definition: relcache.c:3953
#define NULL
Definition: c.h:229
static const FormData_pg_attribute Desc_pg_class[Natts_pg_class]
Definition: relcache.c:100
static TupleDesc GetPgIndexDescriptor ( void  )
static

Definition at line 3998 of file relcache.c.

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

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

3999 {
4000  static TupleDesc pgindexdesc = NULL;
4001 
4002  /* Already done? */
4003  if (pgindexdesc == NULL)
4005  Desc_pg_index,
4006  false);
4007 
4008  return pgindexdesc;
4009 }
static TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs, bool hasoids)
Definition: relcache.c:3953
static const FormData_pg_attribute Desc_pg_index[Natts_pg_index]
Definition: relcache.c:107
#define Natts_pg_index
Definition: pg_index.h:73
#define NULL
Definition: c.h:229
struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

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

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

Definition at line 1668 of file relcache.c.

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

Referenced by RelationInitIndexAccessInfo().

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

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

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

Definition at line 4551 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(), and RelationGetStatExtList().

4552 {
4553  ListCell *prev;
4554 
4555  /* Does the datum belong at the front? */
4556  if (list == NIL || datum < linitial_oid(list))
4557  return lcons_oid(datum, list);
4558  /* No, so find the entry it belongs after */
4559  prev = list_head(list);
4560  for (;;)
4561  {
4562  ListCell *curr = lnext(prev);
4563 
4564  if (curr == NULL || datum < lfirst_oid(curr))
4565  break; /* it belongs after 'prev', before 'curr' */
4566 
4567  prev = curr;
4568  }
4569  /* Insert datum into list after 'prev' */
4570  lappend_cell_oid(list, prev, datum);
4571  return list;
4572 }
#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:229
#define linitial_oid(l)
Definition: pg_list.h:113
tuple list
Definition: sort-test.py:11
#define lfirst_oid(lc)
Definition: pg_list.h:108
static void load_critical_index ( Oid  indexoid,
Oid  heapoid 
)
static

Definition at line 3919 of file relcache.c.

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

Referenced by RelationCacheInitializePhase3().

3920 {
3921  Relation ird;
3922 
3923  /*
3924  * We must lock the underlying catalog before locking the index to avoid
3925  * deadlock, since RelationBuildDesc might well need to read the catalog,
3926  * and if anyone else is exclusive-locking this catalog and index they'll
3927  * be doing it in that order.
3928  */
3929  LockRelationOid(heapoid, AccessShareLock);
3930  LockRelationOid(indexoid, AccessShareLock);
3931  ird = RelationBuildDesc(indexoid, true);
3932  if (ird == NULL)
3933  elog(PANIC, "could not open critical system index %u", indexoid);
3934  ird->rd_isnailed = true;
3935  ird->rd_refcnt = 1;
3938 }
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:229
static Relation RelationBuildDesc(Oid targetRelId, bool insertIt)
Definition: relcache.c:1233
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 5361 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_pdcxt, RelationData::rd_pkattr, RelationData::rd_pkindex, RelationData::rd_pubactions, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_replidindex, RelationData::rd_rsdesc, RelationData::rd_rules, RelationData::rd_rulescxt, RelationData::rd_smgr, RelationData::rd_statlist, RelationData::rd_statvalid, RelationData::rd_support, RelationData::rd_supportinfo, RelationCacheInsert, RelationGetRelationName, RelationInitLockInfo(), RelationInitPhysicalAddr(), RELCACHE_INIT_FILEMAGIC, RELCACHE_INIT_FILENAME, RELKIND_INDEX, repalloc(), snprintf(), HeapTupleData::t_data, tupleDesc::tdrefcount, tupleDesc::tdtypeid, tupleDesc::tdtypmod, RelationData::trigdesc, VARSIZE, and WARNING.

Referenced by RelationCacheInitializePhase2(), and RelationCacheInitializePhase3().

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

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

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

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

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

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

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

Definition at line 827 of file relcache.c.

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate(), Anum_pg_partitioned_table_partclass, Anum_pg_partitioned_table_partcollation, Anum_pg_partitioned_table_partexprs, Assert, 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().

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

Definition at line 659 of file relcache.c.

References AccessShareLock, RewriteRule::actions, ALLOCSET_SMALL_SIZES, AllocSetContextCreate(), Anum_pg_rewrite_ev_action, Anum_pg_rewrite_ev_class, Anum_pg_rewrite_ev_qual, Assert, BTEqualStrategyNumber, CacheMemoryContext, RewriteRule::enabled, RewriteRule::event, GETSTRUCT, heap_close, heap_getattr, heap_open(), HeapTupleGetOid, HeapTupleIsValid, RewriteRule::isInstead, MemoryContextAlloc(), MemoryContextDelete(), MemoryContextSwitchTo(), 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().

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

Definition at line 487 of file relcache.c.

References AccessShareLock, attrDefault::adbin, attrDefault::adnum, Anum_pg_attribute_attnum, Anum_pg_attribute_attrelid, Assert, AttrDefaultFetch(), ATTRIBUTE_FIXED_PART_SIZE, AttributeRelationId, AttributeRelidNumIndexId, 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().

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

Definition at line 6069 of file relcache.c.

References LWLockRelease().

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

6070 {
6071  LWLockRelease(RelCacheInitLock);
6072 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
void RelationCacheInitFilePreInvalidate ( void  )

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

6044 {
6045  char initfilename[MAXPGPATH];
6046 
6047  snprintf(initfilename, sizeof(initfilename), "%s/%s",
6049 
6050  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6051 
6052  if (unlink(initfilename) < 0)
6053  {
6054  /*
6055  * The file might not be there if no backend has been started since
6056  * the last removal. But complain about failures other than ENOENT.
6057  * Fortunately, it's not too late to abort the transaction if we can't
6058  * get rid of the would-be-obsolete init file.
6059  */
6060  if (errno != ENOENT)
6061  ereport(ERROR,
6063  errmsg("could not remove cache file \"%s\": %m",
6064  initfilename)));
6065  }
6066 }
#define RELCACHE_INIT_FILENAME
Definition: relcache.c:93
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define ERROR
Definition: elog.h:43
#define MAXPGPATH
int errcode_for_file_access(void)
Definition: elog.c:598
int unlink(const char *filename)
#define ereport(elevel, rest)
Definition: elog.h:122
char * DatabasePath
Definition: globals.c:85
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
int errmsg(const char *fmt,...)
Definition: elog.c:797
void RelationCacheInitFileRemove ( void  )

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

6085 {
6086  const char *tblspcdir = "pg_tblspc";
6087  DIR *dir;
6088  struct dirent *de;
6089  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6090 
6091  /*
6092  * We zap the shared cache file too. In theory it can't get out of sync
6093  * enough to be a problem, but in data-corruption cases, who knows ...
6094  */
6095  snprintf(path, sizeof(path), "global/%s",
6097  unlink_initfile(path);
6098 
6099  /* Scan everything in the default tablespace */
6101 
6102  /* Scan the tablespace link directory to find non-default tablespaces */
6103  dir = AllocateDir(tblspcdir);
6104  if (dir == NULL)
6105  {
6106  elog(LOG, "could not open tablespace link directory \"%s\": %m",
6107  tblspcdir);
6108  return;
6109  }
6110 
6111  while ((de = ReadDir(dir, tblspcdir)) != NULL)
6112  {
6113  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6114  {
6115  /* Scan the tablespace dir for per-database dirs */
6116  snprintf(path, sizeof(path), "%s/%s/%s",
6117  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6119  }
6120  }
6121 
6122  FreeDir(dir);
6123 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6127
#define RELCACHE_INIT_FILENAME
Definition: relcache.c:93
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2335
static void unlink_initfile(const char *initfilename)
Definition: relcache.c:6157
#define NULL
Definition: c.h:229
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2401
#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:2444
static void RelationCacheInitFileRemoveInDir ( const char *  tblspcpath)
static

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

6128 {
6129  DIR *dir;
6130  struct dirent *de;
6131  char initfilename[MAXPGPATH * 2];
6132 
6133  /* Scan the tablespace directory to find per-database directories */
6134  dir = AllocateDir(tblspcpath);
6135  if (dir == NULL)
6136  {
6137  elog(LOG, "could not open tablespace directory \"%s\": %m",
6138  tblspcpath);
6139  return;
6140  }
6141 
6142  while ((de = ReadDir(dir, tblspcpath)) != NULL)
6143  {
6144  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6145  {
6146  /* Try to remove the init file in each database */
6147  snprintf(initfilename, sizeof(initfilename), "%s/%s/%s",
6148  tblspcpath, de->d_name, RELCACHE_INIT_FILENAME);
6149  unlink_initfile(initfilename);
6150  }
6151  }
6152 
6153  FreeDir(dir);
6154 }
#define RELCACHE_INIT_FILENAME
Definition: relcache.c:93
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2335
static void unlink_initfile(const char *initfilename)
Definition: relcache.c:6157
#define NULL
Definition: c.h:229
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2401
char d_name[MAX_PATH]
Definition: dirent.h:14
#define elog
Definition: elog.h:219
int FreeDir(DIR *dir)
Definition: fd.c:2444
void RelationCacheInitialize ( void  )

Definition at line 3528 of file relcache.c.

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

Referenced by InitPostgres().

3529 {
3530  HASHCTL ctl;
3531 
3532  /*
3533  * make sure cache memory context exists
3534  */
3535  if (!CacheMemoryContext)
3537 
3538  /*
3539  * create hashtable that indexes the relcache
3540  */
3541  MemSet(&ctl, 0, sizeof(ctl));
3542  ctl.keysize = sizeof(Oid);
3543  ctl.entrysize = sizeof(RelIdCacheEnt);
3544  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3545  &ctl, HASH_ELEM | HASH_BLOBS);
3546 
3547  /*
3548  * relation mapper needs to be initialized too
3549  */
3551 }
void RelationMapInitialize(void)
Definition: relmapper.c:562
#define HASH_ELEM
Definition: hsearch.h:87
struct relidcacheent RelIdCacheEnt
Size entrysize
Definition: hsearch.h:73
#define MemSet(start, val, len)
Definition: c.h:857
static HTAB * RelationIdCache
Definition: relcache.c:123
unsigned int Oid
Definition: postgres_ext.h:31
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
Size keysize
Definition: hsearch.h:72
void CreateCacheMemoryContext(void)
Definition: catcache.c:511
#define INITRELCACHESIZE
Definition: relcache.c:3525
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void RelationCacheInitializePhase2 ( void  )

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

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

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