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:437
#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:401
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:365
#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:437
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:401
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:1353
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1343
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c: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:437
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:401
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:365
int rd_refcnt
Definition: rel.h:88
void list_free(List *list)
Definition: list.c:1133
#define elog
Definition: elog.h:219
void AtEOXact_RelationCache ( bool  isCommit)

Definition at line 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:1353
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1343
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 4008 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().

4009 {
4010  AttrDefault *attrdef = relation->rd_att->constr->defval;
4011  int ndef = relation->rd_att->constr->num_defval;
4012  Relation adrel;
4013  SysScanDesc adscan;
4014  ScanKeyData skey;
4015  HeapTuple htup;
4016  Datum val;
4017  bool isnull;
4018  int found;
4019  int i;
4020 
4021  ScanKeyInit(&skey,
4023  BTEqualStrategyNumber, F_OIDEQ,
4024  ObjectIdGetDatum(RelationGetRelid(relation)));
4025 
4027  adscan = systable_beginscan(adrel, AttrDefaultIndexId, true,
4028  NULL, 1, &skey);
4029  found = 0;
4030 
4031  while (HeapTupleIsValid(htup = systable_getnext(adscan)))
4032  {
4033  Form_pg_attrdef adform = (Form_pg_attrdef) GETSTRUCT(htup);
4034 
4035  for (i = 0; i < ndef; i++)
4036  {
4037  if (adform->adnum != attrdef[i].adnum)
4038  continue;
4039  if (attrdef[i].adbin != NULL)
4040  elog(WARNING, "multiple attrdef records found for attr %s of rel %s",
4041  NameStr(relation->rd_att->attrs[adform->adnum - 1]->attname),
4042  RelationGetRelationName(relation));
4043  else
4044  found++;
4045 
4046  val = fastgetattr(htup,
4048  adrel->rd_att, &isnull);
4049  if (isnull)
4050  elog(WARNING, "null adbin for attr %s of rel %s",
4051  NameStr(relation->rd_att->attrs[adform->adnum - 1]->attname),
4052  RelationGetRelationName(relation));
4053  else
4054  {
4055  /* detoast and convert to cstring in caller's context */
4056  char *s = TextDatumGetCString(val);
4057 
4059  pfree(s);
4060  }
4061  break;
4062  }
4063 
4064  if (i >= ndef)
4065  elog(WARNING, "unexpected attrdef record found for attr %d of rel %s",
4066  adform->adnum, RelationGetRelationName(relation));
4067  }
4068 
4069  systable_endscan(adscan);
4070  heap_close(adrel, AccessShareLock);
4071 
4072  if (found != ndef)
4073  elog(WARNING, "%d attrdef record(s) missing for rel %s",
4074  ndef - found, RelationGetRelationName(relation));
4075 }
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:437
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:417
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 3946 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().

3948 {
3949  TupleDesc result;
3950  MemoryContext oldcxt;
3951  int i;
3952 
3954 
3955  result = CreateTemplateTupleDesc(natts, hasoids);
3956  result->tdtypeid = RECORDOID; /* not right, but we don't care */
3957  result->tdtypmod = -1;
3958 
3959  for (i = 0; i < natts; i++)
3960  {
3961  memcpy(result->attrs[i], &attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
3962  /* make sure attcacheoff is valid */
3963  result->attrs[i]->attcacheoff = -1;
3964  }
3965 
3966  /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
3967  result->attrs[0]->attcacheoff = 0;
3968 
3969  /* Note: we don't bother to set up a TupleConstr entry */
3970 
3971  MemoryContextSwitchTo(oldcxt);
3972 
3973  return result;
3974 }
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:1618
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 4152 of file relcache.c.

References constrCheck::ccname.

Referenced by CheckConstraintFetch().

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

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

4082 {
4083  ConstrCheck *check = relation->rd_att->constr->check;
4084  int ncheck = relation->rd_att->constr->num_check;
4085  Relation conrel;
4086  SysScanDesc conscan;
4087  ScanKeyData skey[1];
4088  HeapTuple htup;
4089  int found = 0;
4090 
4091  ScanKeyInit(&skey[0],
4093  BTEqualStrategyNumber, F_OIDEQ,
4094  ObjectIdGetDatum(RelationGetRelid(relation)));
4095 
4097  conscan = systable_beginscan(conrel, ConstraintRelidIndexId, true,
4098  NULL, 1, skey);
4099 
4100  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4101  {
4103  Datum val;
4104  bool isnull;
4105  char *s;
4106 
4107  /* We want check constraints only */
4108  if (conform->contype != CONSTRAINT_CHECK)
4109  continue;
4110 
4111  if (found >= ncheck)
4112  elog(ERROR, "unexpected constraint record found for rel %s",
4113  RelationGetRelationName(relation));
4114 
4115  check[found].ccvalid = conform->convalidated;
4116  check[found].ccnoinherit = conform->connoinherit;
4118  NameStr(conform->conname));
4119 
4120  /* Grab and test conbin is actually set */
4121  val = fastgetattr(htup,
4123  conrel->rd_att, &isnull);
4124  if (isnull)
4125  elog(ERROR, "null conbin for rel %s",
4126  RelationGetRelationName(relation));
4127 
4128  /* detoast and convert to cstring in caller's context */
4129  s = TextDatumGetCString(val);
4130  check[found].ccbin = MemoryContextStrdup(CacheMemoryContext, s);
4131  pfree(s);
4132 
4133  found++;
4134  }
4135 
4136  systable_endscan(conscan);
4137  heap_close(conrel, AccessShareLock);
4138 
4139  if (found != ncheck)
4140  elog(ERROR, "%d constraint record(s) missing for rel %s",
4141  ncheck - found, RelationGetRelationName(relation));
4142 
4143  /* Sort the records so that CHECKs are applied in a deterministic order */
4144  if (ncheck > 1)
4145  qsort(check, ncheck, sizeof(ConstrCheck), CheckConstraintCmp);
4146 }
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:4152
#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:437
#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:417
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:621
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:595
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:2961
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:2961
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 5232 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().

5233 {
5237 
5238  return 0; /* return value does not matter */
5239 }
#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:3038
#define RelationGetRelationName(relation)
Definition: rel.h:437
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
#define RelationGetNamespace(relation)
Definition: rel.h:444
int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5249 of file relcache.c.

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

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

5250 {
5251  TupleDesc reldesc = RelationGetDescr(rel);
5252  const char *colname;
5253 
5254  /* Use reldesc if it's a user attribute, else consult the catalogs */
5255  if (attnum > 0 && attnum <= reldesc->natts)
5256  colname = NameStr(reldesc->attrs[attnum - 1]->attname);
5257  else
5258  colname = get_relid_attribute_name(RelationGetRelid(rel), attnum);
5259 
5260  return errtablecolname(rel, colname);
5261 }
#define RelationGetDescr(relation)
Definition: rel.h:429
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:417
int errtablecolname(Relation rel, const char *colname)
Definition: relcache.c:5273
int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5273 of file relcache.c.

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

Referenced by errtablecol().

5274 {
5275  errtable(rel);
5277 
5278  return 0; /* return value does not matter */
5279 }
#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:5232
int errtableconstraint ( Relation  rel,
const char *  conname 
)

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

5287 {
5288  errtable(rel);
5290 
5291  return 0; /* return value does not matter */
5292 }
#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:5232
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:217
int32 tdtypmod
Definition: tupdesc.h:78
#define RELPERSISTENCE_PERMANENT
Definition: pg_class.h:170
struct RelationData * Relation
Definition: relcache.h:21
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c: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:365
FormData_pg_class * Form_pg_class
Definition: pg_class.h:95
int rd_refcnt
Definition: rel.h:88
int tdrefcount
Definition: tupdesc.h:80
int i
#define RELKIND_RELATION
Definition: pg_class.h:160
#define RelationGetRelid(relation)
Definition: rel.h:417
void RelationMapUpdateMap(Oid relationId, Oid fileNode, bool shared, bool immediate)
Definition: relmapper.c:248
static TupleDesc GetPgClassDescriptor ( void  )
static

Definition at line 3977 of file relcache.c.

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

Referenced by RelationParseRelOptions().

3978 {
3979  static TupleDesc pgclassdesc = NULL;
3980 
3981  /* Already done? */
3982  if (pgclassdesc == NULL)
3984  Desc_pg_class,
3985  true);
3986 
3987  return pgclassdesc;
3988 }
#define Natts_pg_class
Definition: pg_class.h:102
static TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs, bool hasoids)
Definition: relcache.c:3946
#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 3991 of file relcache.c.

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

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

3992 {
3993  static TupleDesc pgindexdesc = NULL;
3994 
3995  /* Already done? */
3996  if (pgindexdesc == NULL)
3998  Desc_pg_index,
3999  false);
4000 
4001  return pgindexdesc;
4002 }
static TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs, bool hasoids)
Definition: relcache.c:3946
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 5161 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().

5162 {
5163  List *puboids;
5164  ListCell *lc;
5165  MemoryContext oldcxt;
5166  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5167 
5168  if (relation->rd_pubactions)
5169  return memcpy(pubactions, relation->rd_pubactions,
5170  sizeof(PublicationActions));
5171 
5172  /* Fetch the publication membership info. */
5173  puboids = GetRelationPublications(RelationGetRelid(relation));
5174  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5175 
5176  foreach(lc, puboids)
5177  {
5178  Oid pubid = lfirst_oid(lc);
5179  HeapTuple tup;
5180  Form_pg_publication pubform;
5181 
5183 
5184  if (!HeapTupleIsValid(tup))
5185  elog(ERROR, "cache lookup failed for publication %u", pubid);
5186 
5187  pubform = (Form_pg_publication) GETSTRUCT(tup);
5188 
5189  pubactions->pubinsert |= pubform->pubinsert;
5190  pubactions->pubupdate |= pubform->pubupdate;
5191  pubactions->pubdelete |= pubform->pubdelete;
5192 
5193  ReleaseSysCache(tup);
5194 
5195  /*
5196  * If we know everything is replicated, there is no point to check
5197  * for other publications.
5198  */
5199  if (pubactions->pubinsert && pubactions->pubupdate &&
5200  pubactions->pubdelete)
5201  break;
5202  }
5203 
5204  if (relation->rd_pubactions)
5205  {
5206  pfree(relation->rd_pubactions);
5207  relation->rd_pubactions = NULL;
5208  }
5209 
5210  /* Now save copy of the actions in the relcache entry. */
5212  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5213  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5214  MemoryContextSwitchTo(oldcxt);
5215 
5216  return pubactions;
5217 }
#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:152
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:1116
#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:417
#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 4541 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().

4542 {
4543  ListCell *prev;
4544 
4545  /* Does the datum belong at the front? */
4546  if (list == NIL || datum < linitial_oid(list))
4547  return lcons_oid(datum, list);
4548  /* No, so find the entry it belongs after */
4549  prev = list_head(list);
4550  for (;;)
4551  {
4552  ListCell *curr = lnext(prev);
4553 
4554  if (curr == NULL || datum < lfirst_oid(curr))
4555  break; /* it belongs after 'prev', before 'curr' */
4556 
4557  prev = curr;
4558  }
4559  /* Insert datum into list after 'prev' */
4560  lappend_cell_oid(list, prev, datum);
4561  return list;
4562 }
#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 3912 of file relcache.c.

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

Referenced by RelationCacheInitializePhase3().

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

References AllocateFile(), ALLOCSET_SMALL_SIZES, AllocSetContextCreate(), IndexAmRoutine::amsupport, Assert, ATTRIBUTE_FIXED_PART_SIZE, tupleDesc::attrs, CacheMemoryContext, tupleDesc::constr, CreateTemplateTupleDesc(), criticalRelcachesBuilt, criticalSharedRelcachesBuilt, DatabasePath, elog, FreeFile(), GETSTRUCT, tupleConstr::has_not_null, HEAPTUPLESIZE, i, InitIndexAmRoutine(), InvalidOid, InvalidSubTransactionId, MAXPGPATH, MemoryContextAlloc(), MemoryContextAllocZero(), MemSet, NIL, NULL, NUM_CRITICAL_LOCAL_INDEXES, NUM_CRITICAL_LOCAL_RELS, NUM_CRITICAL_SHARED_INDEXES, NUM_CRITICAL_SHARED_RELS, palloc(), palloc0(), pfree(), PG_BINARY_R, RelationData::pgstat_info, RelationData::rd_amcache, RelationData::rd_amroutine, RelationData::rd_att, RelationData::rd_createSubid, RelationData::rd_exclops, RelationData::rd_exclprocs, RelationData::rd_exclstrats, RelationData::rd_fdwroutine, RelationData::rd_fkeylist, RelationData::rd_fkeyvalid, RelationData::rd_idattr, RelationData::rd_indcollation, RelationData::rd_index, RelationData::rd_indexattr, RelationData::rd_indexcxt, RelationData::rd_indexlist, RelationData::rd_indexprs, RelationData::rd_indextuple, RelationData::rd_indexvalid, RelationData::rd_indoption, RelationData::rd_indpred, RelationData::rd_isnailed, RelationData::rd_keyattr, RelationData::rd_newRelfilenodeSubid, RelationData::rd_oidindex, RelationData::rd_opcintype, RelationData::rd_opfamily, RelationData::rd_options, RelationData::rd_partcheck, RelationData::rd_partdesc, RelationData::rd_partkey, RelationData::rd_partkeycxt, RelationData::rd_pkattr, RelationData::rd_pkindex, RelationData::rd_pubactions, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_replidindex, RelationData::rd_rsdesc, RelationData::rd_rules, RelationData::rd_rulescxt, RelationData::rd_smgr, RelationData::rd_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().

5351 {
5352  FILE *fp;
5353  char initfilename[MAXPGPATH];
5354  Relation *rels;
5355  int relno,
5356  num_rels,
5357  max_rels,
5358  nailed_rels,
5359  nailed_indexes,
5360  magic;
5361  int i;
5362 
5363  if (shared)
5364  snprintf(initfilename, sizeof(initfilename), "global/%s",
5366  else
5367  snprintf(initfilename, sizeof(initfilename), "%s/%s",
5369 
5370  fp = AllocateFile(initfilename, PG_BINARY_R);
5371  if (fp == NULL)
5372  return false;
5373 
5374  /*
5375  * Read the index relcache entries from the file. Note we will not enter
5376  * any of them into the cache if the read fails partway through; this
5377  * helps to guard against broken init files.
5378  */
5379  max_rels = 100;
5380  rels = (Relation *) palloc(max_rels * sizeof(Relation));
5381  num_rels = 0;
5382  nailed_rels = nailed_indexes = 0;
5383 
5384  /* check for correct magic number (compatible version) */
5385  if (fread(&magic, 1, sizeof(magic), fp) != sizeof(magic))
5386  goto read_failed;
5387  if (magic != RELCACHE_INIT_FILEMAGIC)
5388  goto read_failed;
5389 
5390  for (relno = 0;; relno++)
5391  {
5392  Size len;
5393  size_t nread;
5394  Relation rel;
5395  Form_pg_class relform;
5396  bool has_not_null;
5397 
5398  /* first read the relation descriptor length */
5399  nread = fread(&len, 1, sizeof(len), fp);
5400  if (nread != sizeof(len))
5401  {
5402  if (nread == 0)
5403  break; /* end of file */
5404  goto read_failed;
5405  }
5406 
5407  /* safety check for incompatible relcache layout */
5408  if (len != sizeof(RelationData))
5409  goto read_failed;
5410 
5411  /* allocate another relcache header */
5412  if (num_rels >= max_rels)
5413  {
5414  max_rels *= 2;
5415  rels = (Relation *) repalloc(rels, max_rels * sizeof(Relation));
5416  }
5417 
5418  rel = rels[num_rels++] = (Relation) palloc(len);
5419 
5420  /* then, read the Relation structure */
5421  if (fread(rel, 1, len, fp) != len)
5422  goto read_failed;
5423 
5424  /* next read the relation tuple form */
5425  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5426  goto read_failed;
5427 
5428  relform = (Form_pg_class) palloc(len);
5429  if (fread(relform, 1, len, fp) != len)
5430  goto read_failed;
5431 
5432  rel->rd_rel = relform;
5433 
5434  /* initialize attribute tuple forms */
5435  rel->rd_att = CreateTemplateTupleDesc(relform->relnatts,
5436  relform->relhasoids);
5437  rel->rd_att->tdrefcount = 1; /* mark as refcounted */
5438 
5439  rel->rd_att->tdtypeid = relform->reltype;
5440  rel->rd_att->tdtypmod = -1; /* unnecessary, but... */
5441 
5442  /* next read all the attribute tuple form data entries */
5443  has_not_null = false;
5444  for (i = 0; i < relform->relnatts; i++)
5445  {
5446  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5447  goto read_failed;
5448  if (len != ATTRIBUTE_FIXED_PART_SIZE)
5449  goto read_failed;
5450  if (fread(rel->rd_att->attrs[i], 1, len, fp) != len)
5451  goto read_failed;
5452 
5453  has_not_null |= rel->rd_att->attrs[i]->attnotnull;
5454  }
5455 
5456  /* next read the access method specific field */
5457  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5458  goto read_failed;
5459  if (len > 0)
5460  {
5461  rel->rd_options = palloc(len);
5462  if (fread(rel->rd_options, 1, len, fp) != len)
5463  goto read_failed;
5464  if (len != VARSIZE(rel->rd_options))
5465  goto read_failed; /* sanity check */
5466  }
5467  else
5468  {
5469  rel->rd_options = NULL;
5470  }
5471 
5472  /* mark not-null status */
5473  if (has_not_null)
5474  {
5475  TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
5476 
5477  constr->has_not_null = true;
5478  rel->rd_att->constr = constr;
5479  }
5480 
5481  /* If it's an index, there's more to do */
5482  if (rel->rd_rel->relkind == RELKIND_INDEX)
5483  {
5484  MemoryContext indexcxt;
5485  Oid *opfamily;
5486  Oid *opcintype;
5487  RegProcedure *support;
5488  int nsupport;
5489  int16 *indoption;
5490  Oid *indcollation;
5491 
5492  /* Count nailed indexes to ensure we have 'em all */
5493  if (rel->rd_isnailed)
5494  nailed_indexes++;
5495 
5496  /* next, read the pg_index tuple */
5497  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5498  goto read_failed;
5499 
5500  rel->rd_indextuple = (HeapTuple) palloc(len);
5501  if (fread(rel->rd_indextuple, 1, len, fp) != len)
5502  goto read_failed;
5503 
5504  /* Fix up internal pointers in the tuple -- see heap_copytuple */
5505  rel->rd_indextuple->t_data = (HeapTupleHeader) ((char *) rel->rd_indextuple + HEAPTUPLESIZE);
5507 
5508  /*
5509  * prepare index info context --- parameters should match
5510  * RelationInitIndexAccessInfo
5511  */
5515  rel->rd_indexcxt = indexcxt;
5516 
5517  /*
5518  * Now we can fetch the index AM's API struct. (We can't store
5519  * that in the init file, since it contains function pointers that
5520  * might vary across server executions. Fortunately, it should be
5521  * safe to call the amhandler even while bootstrapping indexes.)
5522  */
5523  InitIndexAmRoutine(rel);
5524 
5525  /* next, read the vector of opfamily OIDs */
5526  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5527  goto read_failed;
5528 
5529  opfamily = (Oid *) MemoryContextAlloc(indexcxt, len);
5530  if (fread(opfamily, 1, len, fp) != len)
5531  goto read_failed;
5532 
5533  rel->rd_opfamily = opfamily;
5534 
5535  /* next, read the vector of opcintype OIDs */
5536  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5537  goto read_failed;
5538 
5539  opcintype = (Oid *) MemoryContextAlloc(indexcxt, len);
5540  if (fread(opcintype, 1, len, fp) != len)
5541  goto read_failed;
5542 
5543  rel->rd_opcintype = opcintype;
5544 
5545  /* next, read the vector of support procedure OIDs */
5546  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5547  goto read_failed;
5548  support = (RegProcedure *) MemoryContextAlloc(indexcxt, len);
5549  if (fread(support, 1, len, fp) != len)
5550  goto read_failed;
5551 
5552  rel->rd_support = support;
5553 
5554  /* next, read the vector of collation OIDs */
5555  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5556  goto read_failed;
5557 
5558  indcollation = (Oid *) MemoryContextAlloc(indexcxt, len);
5559  if (fread(indcollation, 1, len, fp) != len)
5560  goto read_failed;
5561 
5562  rel->rd_indcollation = indcollation;
5563 
5564  /* finally, read the vector of indoption values */
5565  if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
5566  goto read_failed;
5567 
5568  indoption = (int16 *) MemoryContextAlloc(indexcxt, len);
5569  if (fread(indoption, 1, len, fp) != len)
5570  goto read_failed;
5571 
5572  rel->rd_indoption = indoption;
5573 
5574  /* set up zeroed fmgr-info vector */
5575  nsupport = relform->relnatts * rel->rd_amroutine->amsupport;
5576  rel->rd_supportinfo = (FmgrInfo *)
5577  MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
5578  }
5579  else
5580  {
5581  /* Count nailed rels to ensure we have 'em all */
5582  if (rel->rd_isnailed)
5583  nailed_rels++;
5584 
5585  Assert(rel->rd_index == NULL);
5586  Assert(rel->rd_indextuple == NULL);
5587  Assert(rel->rd_indexcxt == NULL);
5588  Assert(rel->rd_amroutine == NULL);
5589  Assert(rel->rd_opfamily == NULL);
5590  Assert(rel->rd_opcintype == NULL);
5591  Assert(rel->rd_support == NULL);
5592  Assert(rel->rd_supportinfo == NULL);
5593  Assert(rel->rd_indoption == NULL);
5594  Assert(rel->rd_indcollation == NULL);
5595  }
5596 
5597  /*
5598  * Rules and triggers are not saved (mainly because the internal
5599  * format is complex and subject to change). They must be rebuilt if
5600  * needed by RelationCacheInitializePhase3. This is not expected to
5601  * be a big performance hit since few system catalogs have such. Ditto
5602  * for RLS policy data, index expressions, predicates, exclusion info,
5603  * and FDW info.
5604  */
5605  rel->rd_rules = NULL;
5606  rel->rd_rulescxt = NULL;
5607  rel->trigdesc = NULL;
5608  rel->rd_rsdesc = NULL;
5609  rel->rd_partkeycxt = NULL;
5610  rel->rd_partkey = NULL;
5611  rel->rd_partdesc = NULL;
5612  rel->rd_partcheck = NIL;
5613  rel->rd_indexprs = NIL;
5614  rel->rd_indpred = NIL;
5615  rel->rd_exclops = NULL;
5616  rel->rd_exclprocs = NULL;
5617  rel->rd_exclstrats = NULL;
5618  rel->rd_fdwroutine = NULL;
5619 
5620  /*
5621  * Reset transient-state fields in the relcache entry
5622  */
5623  rel->rd_smgr = NULL;
5624  if (rel->rd_isnailed)
5625  rel->rd_refcnt = 1;
5626  else
5627  rel->rd_refcnt = 0;
5628  rel->rd_indexvalid = 0;
5629  rel->rd_fkeylist = NIL;
5630  rel->rd_fkeyvalid = false;
5631  rel->rd_indexlist = NIL;
5632  rel->rd_oidindex = InvalidOid;
5633  rel->rd_pkindex = InvalidOid;
5634  rel->rd_replidindex = InvalidOid;
5635  rel->rd_indexattr = NULL;
5636  rel->rd_keyattr = NULL;
5637  rel->rd_pkattr = NULL;
5638  rel->rd_idattr = NULL;
5639  rel->rd_pubactions = NULL;
5640  rel->rd_statvalid = false;
5641  rel->rd_statlist = NIL;
5644  rel->rd_amcache = NULL;
5645  MemSet(&rel->pgstat_info, 0, sizeof(rel->pgstat_info));
5646 
5647  /*
5648  * Recompute lock and physical addressing info. This is needed in
5649  * case the pg_internal.init file was copied from some other database
5650  * by CREATE DATABASE.
5651  */
5652  RelationInitLockInfo(rel);
5654  }
5655 
5656  /*
5657  * We reached the end of the init file without apparent problem. Did we
5658  * get the right number of nailed items? This is a useful crosscheck in
5659  * case the set of critical rels or indexes changes. However, that should
5660  * not happen in a normally-running system, so let's bleat if it does.
5661  *
5662  * For the shared init file, we're called before client authentication is
5663  * done, which means that elog(WARNING) will go only to the postmaster
5664  * log, where it's easily missed. To ensure that developers notice bad
5665  * values of NUM_CRITICAL_SHARED_RELS/NUM_CRITICAL_SHARED_INDEXES, we put
5666  * an Assert(false) there.
5667  */
5668  if (shared)
5669  {
5670  if (nailed_rels != NUM_CRITICAL_SHARED_RELS ||
5671  nailed_indexes != NUM_CRITICAL_SHARED_INDEXES)
5672  {
5673  elog(WARNING, "found %d nailed shared rels and %d nailed shared indexes in init file, but expected %d and %d respectively",
5674  nailed_rels, nailed_indexes,
5676  /* Make sure we get developers' attention about this */
5677  Assert(false);
5678  /* In production builds, recover by bootstrapping the relcache */
5679  goto read_failed;
5680  }
5681  }
5682  else
5683  {
5684  if (nailed_rels != NUM_CRITICAL_LOCAL_RELS ||
5685  nailed_indexes != NUM_CRITICAL_LOCAL_INDEXES)
5686  {
5687  elog(WARNING, "found %d nailed rels and %d nailed indexes in init file, but expected %d and %d respectively",
5688  nailed_rels, nailed_indexes,
5690  /* We don't need an Assert() in this case */
5691  goto read_failed;
5692  }
5693  }
5694 
5695  /*
5696  * OK, all appears well.
5697  *
5698  * Now insert all the new relcache entries into the cache.
5699  */
5700  for (relno = 0; relno < num_rels; relno++)
5701  {
5702  RelationCacheInsert(rels[relno], false);
5703  }
5704 
5705  pfree(rels);
5706  FreeFile(fp);
5707 
5708  if (shared)
5710  else
5711  criticalRelcachesBuilt = true;
5712  return true;
5713 
5714  /*
5715  * init file is broken, so do it the hard way. We don't bother trying to
5716  * free the clutter we just allocated; it's not in the relcache so it
5717  * won't hurt.
5718  */
5719 read_failed:
5720  pfree(rels);
5721  FreeFile(fp);
5722 
5723  return false;
5724 }
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:437
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:84
#define NULL
Definition: c.h:229
#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:525
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
bool criticalRelcachesBuilt
Definition: relcache.c: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:3032
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:3085
MemoryContext rd_rulescxt
Definition: rel.h:119
Form_pg_class rd_rel
Definition: rel.h:114
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
unsigned int Oid
Definition: postgres_ext.h:31
static Relation AllocateRelationDesc(Form_pg_class relp)
Definition: relcache.c:379
#define OidIsValid(objectId)
Definition: c.h:538
static void RelationBuildPartitionKey(Relation relation)
Definition: relcache.c:827
void RelationBuildPartitionDesc(Relation rel)
Definition: partition.c:151
#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:1605
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:417
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:3032
#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:217
int natts
Definition: tupdesc.h:73
#define AuthIdRelationId
Definition: pg_authid.h:42
#define RELPERSISTENCE_PERMANENT
Definition: pg_class.h:170
struct RelationData * Relation
Definition: relcache.h:21
#define ERROR
Definition: elog.h:43
static void RelationInitPhysicalAddr(Relation relation)
Definition: relcache.c: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:219
TupleDesc rd_att
Definition: rel.h:115
bool IsSystemNamespace(Oid namespaceId)
Definition: catalog.c:162
#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:525
#define BOOTSTRAP_SUPERUSERID
Definition: pg_authid.h:108
#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:417
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:1603
#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:152
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:437
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:1116
char * parttypalign
Definition: rel.h:73
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1278
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:748
#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:417
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:429
#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:74
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:437
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:417
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:4008
#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:437
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:4081
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:417
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void RelationCacheInitFilePostInvalidate ( void  )

Definition at line 6057 of file relcache.c.

References LWLockRelease().

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

6058 {
6059  LWLockRelease(RelCacheInitLock);
6060 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
void RelationCacheInitFilePreInvalidate ( void  )

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

6032 {
6033  char initfilename[MAXPGPATH];
6034 
6035  snprintf(initfilename, sizeof(initfilename), "%s/%s",
6037 
6038  LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
6039 
6040  if (unlink(initfilename) < 0)
6041  {
6042  /*
6043  * The file might not be there if no backend has been started since
6044  * the last removal. But complain about failures other than ENOENT.
6045  * Fortunately, it's not too late to abort the transaction if we can't
6046  * get rid of the would-be-obsolete init file.
6047  */
6048  if (errno != ENOENT)
6049  ereport(ERROR,
6051  errmsg("could not remove cache file \"%s\": %m",
6052  initfilename)));
6053  }
6054 }
#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:84
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 6072 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().

6073 {
6074  const char *tblspcdir = "pg_tblspc";
6075  DIR *dir;
6076  struct dirent *de;
6077  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6078 
6079  /*
6080  * We zap the shared cache file too. In theory it can't get out of sync
6081  * enough to be a problem, but in data-corruption cases, who knows ...
6082  */
6083  snprintf(path, sizeof(path), "global/%s",
6085  unlink_initfile(path);
6086 
6087  /* Scan everything in the default tablespace */
6089 
6090  /* Scan the tablespace link directory to find non-default tablespaces */
6091  dir = AllocateDir(tblspcdir);
6092  if (dir == NULL)
6093  {
6094  elog(LOG, "could not open tablespace link directory \"%s\": %m",
6095  tblspcdir);
6096  return;
6097  }
6098 
6099  while ((de = ReadDir(dir, tblspcdir)) != NULL)
6100  {
6101  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6102  {
6103  /* Scan the tablespace dir for per-database dirs */
6104  snprintf(path, sizeof(path), "%s/%s/%s",
6105  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6107  }
6108  }
6109 
6110  FreeDir(dir);
6111 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6115
#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:6145
#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 6115 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().

6116 {
6117  DIR *dir;
6118  struct dirent *de;
6119  char initfilename[MAXPGPATH * 2];
6120 
6121  /* Scan the tablespace directory to find per-database directories */
6122  dir = AllocateDir(tblspcpath);
6123  if (dir == NULL)
6124  {
6125  elog(LOG, "could not open tablespace directory \"%s\": %m",
6126  tblspcpath);
6127  return;
6128  }
6129 
6130  while ((de = ReadDir(dir, tblspcpath)) != NULL)
6131  {
6132  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6133  {
6134  /* Try to remove the init file in each database */
6135  snprintf(initfilename, sizeof(initfilename), "%s/%s/%s",
6136  tblspcpath, de->d_name, RELCACHE_INIT_FILENAME);
6137  unlink_initfile(initfilename);
6138  }
6139  }
6140 
6141  FreeDir(dir);
6142 }
#define RELCACHE_INIT_FILENAME
Definition: relcache.c:93
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2335
static void unlink_initfile(const char *initfilename)
Definition: relcache.c:6145
#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:525
#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:5350
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:365
#define DatabaseRelation_Rowtype_Id
Definition: pg_database.h:30
#define Natts_pg_authid
Definition: pg_authid.h:78
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void RelationCacheInitializePhase3 ( void  )

Definition at line 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  * Fix data that isn't saved in relcache cache file.
3824  *
3825  * relhasrules or relhastriggers could possibly be wrong or out of
3826  * date. If we don't actually find any rules or triggers, clear the
3827