PostgreSQL Source Code  git master
relcache.c File Reference
#include "postgres.h"
#include <sys/file.h>
#include <fcntl.h>
#include <unistd.h>
#include "access/hash.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_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 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

◆ EOXactListAdd

#define EOXactListAdd (   rel)
Value:
do { \
eoxact_list[eoxact_list_len++] = (rel)->rd_id; \
else \
eoxact_list_overflowed = true; \
} while (0)
#define MAX_EOXACT_LIST
Definition: relcache.c:151
static int eoxact_list_len
Definition: relcache.c:153

Definition at line 156 of file relcache.c.

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

◆ INITRELCACHESIZE

#define INITRELCACHESIZE   400

Definition at line 3508 of file relcache.c.

Referenced by RelationCacheInitialize().

◆ MAX_EOXACT_LIST

#define MAX_EOXACT_LIST   32

Definition at line 151 of file relcache.c.

◆ NUM_CRITICAL_LOCAL_INDEXES

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

Referenced by load_relcache_init_file().

◆ NUM_CRITICAL_LOCAL_RELS

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

Referenced by load_relcache_init_file().

◆ NUM_CRITICAL_SHARED_INDEXES

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

Referenced by load_relcache_init_file().

◆ NUM_CRITICAL_SHARED_RELS

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

Referenced by load_relcache_init_file().

◆ RelationCacheDelete

#define RelationCacheDelete (   RELATION)
Value:
do { \
RelIdCacheEnt *hentry; \
(void *) &((RELATION)->rd_id), \
HASH_REMOVE, NULL); \
if (hentry == NULL) \
elog(WARNING, "failed to delete relcache entry for OID %u", \
(RELATION)->rd_id); \
} while(0)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:904
static HTAB * RelationIdCache
Definition: relcache.c:119
#define WARNING
Definition: elog.h:40

Definition at line 210 of file relcache.c.

Referenced by RelationClearRelation().

◆ RelationCacheInsert

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

Definition at line 176 of file relcache.c.

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

◆ RelationIdCacheLookup

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

Definition at line 198 of file relcache.c.

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

◆ RELCACHE_INIT_FILEMAGIC

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

Definition at line 91 of file relcache.c.

Referenced by load_relcache_init_file(), and write_relcache_init_file().

◆ SWAPFIELD

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

Referenced by RelationClearRelation().

Typedef Documentation

◆ OpClassCacheEnt

◆ RelIdCacheEnt

Function Documentation

◆ AllocateRelationDesc()

static Relation AllocateRelationDesc ( Form_pg_class  relp)
static

Definition at line 374 of file relcache.c.

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

Referenced by RelationBuildDesc().

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

◆ AtEOSubXact_cleanup()

static void AtEOSubXact_cleanup ( Relation  relation,
bool  isCommit,
SubTransactionId  mySubid,
SubTransactionId  parentSubid 
)
static

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

3096 {
3097  /*
3098  * Is it a relation created in the current subtransaction?
3099  *
3100  * During subcommit, mark it as belonging to the parent, instead. During
3101  * subabort, simply delete the relcache entry.
3102  */
3103  if (relation->rd_createSubid == mySubid)
3104  {
3105  if (isCommit)
3106  relation->rd_createSubid = parentSubid;
3107  else if (RelationHasReferenceCountZero(relation))
3108  {
3109  RelationClearRelation(relation, false);
3110  return;
3111  }
3112  else
3113  {
3114  /*
3115  * Hmm, somewhere there's a (leaked?) reference to the relation.
3116  * We daren't remove the entry for fear of dereferencing a
3117  * dangling pointer later. Bleat, and transfer it to the parent
3118  * subtransaction so we can try again later. This must be just a
3119  * WARNING to avoid error-during-error-recovery loops.
3120  */
3121  relation->rd_createSubid = parentSubid;
3122  elog(WARNING, "cannot remove relcache entry for \"%s\" because it has nonzero refcount",
3123  RelationGetRelationName(relation));
3124  }
3125  }
3126 
3127  /*
3128  * Likewise, update or drop any new-relfilenode-in-subtransaction hint.
3129  */
3130  if (relation->rd_newRelfilenodeSubid == mySubid)
3131  {
3132  if (isCommit)
3133  relation->rd_newRelfilenodeSubid = parentSubid;
3134  else
3136  }
3137 
3138  /*
3139  * Flush any temporary index list.
3140  */
3141  if (relation->rd_indexvalid == 2)
3142  {
3143  list_free(relation->rd_indexlist);
3144  relation->rd_indexlist = NIL;
3145  relation->rd_oidindex = InvalidOid;
3146  relation->rd_pkindex = InvalidOid;
3147  relation->rd_replidindex = InvalidOid;
3148  relation->rd_indexvalid = 0;
3149  }
3150 }
#define NIL
Definition: pg_list.h:69
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2366
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:445
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:469
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:409
void list_free(List *list)
Definition: list.c:1133
#define elog
Definition: elog.h:219

◆ AtEOSubXact_RelationCache()

void AtEOSubXact_RelationCache ( bool  isCommit,
SubTransactionId  mySubid,
SubTransactionId  parentSubid 
)

Definition at line 3047 of file relcache.c.

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

3049 {
3051  RelIdCacheEnt *idhentry;
3052  int i;
3053 
3054  /*
3055  * Unless the eoxact_list[] overflowed, we only need to examine the rels
3056  * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3057  * logic as in AtEOXact_RelationCache.
3058  */
3060  {
3061  hash_seq_init(&status, RelationIdCache);
3062  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3063  {
3064  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3065  mySubid, parentSubid);
3066  }
3067  }
3068  else
3069  {
3070  for (i = 0; i < eoxact_list_len; i++)
3071  {
3072  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
3073  (void *) &eoxact_list[i],
3074  HASH_FIND,
3075  NULL);
3076  if (idhentry != NULL)
3077  AtEOSubXact_cleanup(idhentry->reldesc, isCommit,
3078  mySubid, parentSubid);
3079  }
3080  }
3081 
3082  /* Don't reset the list; we still need more cleanup later */
3083 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:152
static void AtEOSubXact_cleanup(Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
Definition: relcache.c:3094
Relation reldesc
Definition: relcache.c:116
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:904
static HTAB * RelationIdCache
Definition: relcache.c:119
static bool eoxact_list_overflowed
Definition: relcache.c:154
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1387
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1377
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
static int eoxact_list_len
Definition: relcache.c:153

◆ AtEOXact_cleanup()

static void AtEOXact_cleanup ( Relation  relation,
bool  isCommit 
)
static

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

2960 {
2961  /*
2962  * The relcache entry's ref count should be back to its normal
2963  * not-in-a-transaction state: 0 unless it's nailed in cache.
2964  *
2965  * In bootstrap mode, this is NOT true, so don't check it --- the
2966  * bootstrap code expects relations to stay open across start/commit
2967  * transaction calls. (That seems bogus, but it's not worth fixing.)
2968  *
2969  * Note: ideally this check would be applied to every relcache entry, not
2970  * just those that have eoxact work to do. But it's not worth forcing a
2971  * scan of the whole relcache just for this. (Moreover, doing so would
2972  * mean that assert-enabled testing never tests the hash_search code path
2973  * above, which seems a bad idea.)
2974  */
2975 #ifdef USE_ASSERT_CHECKING
2977  {
2978  int expected_refcnt;
2979 
2980  expected_refcnt = relation->rd_isnailed ? 1 : 0;
2981  Assert(relation->rd_refcnt == expected_refcnt);
2982  }
2983 #endif
2984 
2985  /*
2986  * Is it a relation created in the current transaction?
2987  *
2988  * During commit, reset the flag to zero, since we are now out of the
2989  * creating transaction. During abort, simply delete the relcache entry
2990  * --- it isn't interesting any longer. (NOTE: if we have forgotten the
2991  * new-ness of a new relation due to a forced cache flush, the entry will
2992  * get deleted anyway by shared-cache-inval processing of the aborted
2993  * pg_class insertion.)
2994  */
2995  if (relation->rd_createSubid != InvalidSubTransactionId)
2996  {
2997  if (isCommit)
2999  else if (RelationHasReferenceCountZero(relation))
3000  {
3001  RelationClearRelation(relation, false);
3002  return;
3003  }
3004  else
3005  {
3006  /*
3007  * Hmm, somewhere there's a (leaked?) reference to the relation.
3008  * We daren't remove the entry for fear of dereferencing a
3009  * dangling pointer later. Bleat, and mark it as not belonging to
3010  * the current transaction. Hopefully it'll get cleaned up
3011  * eventually. This must be just a WARNING to avoid
3012  * error-during-error-recovery loops.
3013  */
3015  elog(WARNING, "cannot remove relcache entry for \"%s\" because it has nonzero refcount",
3016  RelationGetRelationName(relation));
3017  }
3018  }
3019 
3020  /*
3021  * Likewise, reset the hint about the relfilenode being new.
3022  */
3024 
3025  /*
3026  * Flush any temporary index list.
3027  */
3028  if (relation->rd_indexvalid == 2)
3029  {
3030  list_free(relation->rd_indexlist);
3031  relation->rd_indexlist = NIL;
3032  relation->rd_oidindex = InvalidOid;
3033  relation->rd_pkindex = InvalidOid;
3034  relation->rd_replidindex = InvalidOid;
3035  relation->rd_indexvalid = 0;
3036  }
3037 }
#define NIL
Definition: pg_list.h:69
static void RelationClearRelation(Relation relation, bool rebuild)
Definition: relcache.c:2366
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:445
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:688
#define InvalidSubTransactionId
Definition: c.h:469
#define RelationHasReferenceCountZero(relation)
Definition: rel.h:409
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:368
int rd_refcnt
Definition: rel.h:88
void list_free(List *list)
Definition: list.c:1133
#define elog
Definition: elog.h:219

◆ AtEOXact_RelationCache()

void AtEOXact_RelationCache ( bool  isCommit)

Definition at line 2896 of file relcache.c.

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

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

2897 {
2899  RelIdCacheEnt *idhentry;
2900  int i;
2901 
2902  /*
2903  * Unless the eoxact_list[] overflowed, we only need to examine the rels
2904  * listed in it. Otherwise fall back on a hash_seq_search scan.
2905  *
2906  * For simplicity, eoxact_list[] entries are not deleted till end of
2907  * top-level transaction, even though we could remove them at
2908  * subtransaction end in some cases, or remove relations from the list if
2909  * they are cleared for other reasons. Therefore we should expect the
2910  * case that list entries are not found in the hashtable; if not, there's
2911  * nothing to do for them.
2912  */
2914  {
2915  hash_seq_init(&status, RelationIdCache);
2916  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
2917  {
2918  AtEOXact_cleanup(idhentry->reldesc, isCommit);
2919  }
2920  }
2921  else
2922  {
2923  for (i = 0; i < eoxact_list_len; i++)
2924  {
2925  idhentry = (RelIdCacheEnt *) hash_search(RelationIdCache,
2926  (void *) &eoxact_list[i],
2927  HASH_FIND,
2928  NULL);
2929  if (idhentry != NULL)
2930  AtEOXact_cleanup(idhentry->reldesc, isCommit);
2931  }
2932  }
2933 
2934  if (EOXactTupleDescArrayLen > 0)
2935  {
2936  Assert(EOXactTupleDescArray != NULL);
2937  for (i = 0; i < NextEOXactTupleDescNum; i++)
2940  EOXactTupleDescArray = NULL;
2941  }
2942 
2943  /* Now we're out of the transaction and can clear the lists */
2944  eoxact_list_len = 0;
2945  eoxact_list_overflowed = false;
2946  NextEOXactTupleDescNum = 0;
2948 }
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition: relcache.c:152
static int EOXactTupleDescArrayLen
Definition: relcache.c:171
Relation reldesc
Definition: relcache.c:116
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:904
static HTAB * RelationIdCache
Definition: relcache.c:119
static void AtEOXact_cleanup(Relation relation, bool isCommit)
Definition: relcache.c:2959
static bool eoxact_list_overflowed
Definition: relcache.c:154
static int NextEOXactTupleDescNum
Definition: relcache.c:170
void pfree(void *pointer)
Definition: mcxt.c:936
#define Assert(condition)
Definition: c.h:688
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1387
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1377
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:289
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
static int eoxact_list_len
Definition: relcache.c:153
static TupleDesc * EOXactTupleDescArray
Definition: relcache.c:169

◆ AttrDefaultFetch()

static void AttrDefaultFetch ( Relation  relation)
static

Definition at line 3998 of file relcache.c.

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

Referenced by RelationBuildTupleDesc().

3999 {
4000  AttrDefault *attrdef = relation->rd_att->constr->defval;
4001  int ndef = relation->rd_att->constr->num_defval;
4002  Relation adrel;
4003  SysScanDesc adscan;
4004  ScanKeyData skey;
4005  HeapTuple htup;
4006  Datum val;
4007  bool isnull;
4008  int found;
4009  int i;
4010 
4011  ScanKeyInit(&skey,
4013  BTEqualStrategyNumber, F_OIDEQ,
4014  ObjectIdGetDatum(RelationGetRelid(relation)));
4015 
4017  adscan = systable_beginscan(adrel, AttrDefaultIndexId, true,
4018  NULL, 1, &skey);
4019  found = 0;
4020 
4021  while (HeapTupleIsValid(htup = systable_getnext(adscan)))
4022  {
4023  Form_pg_attrdef adform = (Form_pg_attrdef) GETSTRUCT(htup);
4024  Form_pg_attribute attr = TupleDescAttr(relation->rd_att, adform->adnum - 1);
4025 
4026  for (i = 0; i < ndef; i++)
4027  {
4028  if (adform->adnum != attrdef[i].adnum)
4029  continue;
4030  if (attrdef[i].adbin != NULL)
4031  elog(WARNING, "multiple attrdef records found for attr %s of rel %s",
4032  NameStr(attr->attname),
4033  RelationGetRelationName(relation));
4034  else
4035  found++;
4036 
4037  val = fastgetattr(htup,
4039  adrel->rd_att, &isnull);
4040  if (isnull)
4041  elog(WARNING, "null adbin for attr %s of rel %s",
4042  NameStr(attr->attname),
4043  RelationGetRelationName(relation));
4044  else
4045  {
4046  /* detoast and convert to cstring in caller's context */
4047  char *s = TextDatumGetCString(val);
4048 
4050  pfree(s);
4051  }
4052  break;
4053  }
4054 
4055  if (i >= ndef)
4056  elog(WARNING, "unexpected attrdef record found for attr %d of rel %s",
4057  adform->adnum, RelationGetRelationName(relation));
4058  }
4059 
4060  systable_endscan(adscan);
4061  heap_close(adrel, AccessShareLock);
4062 
4063  if (found != ndef)
4064  elog(WARNING, "%d attrdef record(s) missing for rel %s",
4065  ndef - found, RelationGetRelationName(relation));
4066 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:724
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
#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:936
AttrDefault * defval
Definition: tupdesc.h:39
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define AttrDefaultIndexId
Definition: indexing.h:87
AttrNumber adnum
Definition: tupdesc.h:24
#define RelationGetRelationName(relation)
Definition: rel.h:445
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
char * adbin
Definition: tupdesc.h:25
FormData_pg_attrdef * Form_pg_attrdef
Definition: pg_attrdef.h:47
#define WARNING
Definition: elog.h:40
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:365
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
TupleDesc rd_att
Definition: rel.h:115
#define Anum_pg_attrdef_adrelid
Definition: pg_attrdef.h:54
uint16 num_defval
Definition: tupdesc.h:41
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
TupleConstr * constr
Definition: tupdesc.h:84
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1050
int i
#define NameStr(name)
Definition: c.h:565
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:425
long val
Definition: informix.c:689
#define BTEqualStrategyNumber
Definition: stratnum.h:31
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ BuildHardcodedDescriptor()

static TupleDesc BuildHardcodedDescriptor ( int  natts,
const FormData_pg_attribute attrs,
bool  hasoids 
)
static

Definition at line 3936 of file relcache.c.

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

Referenced by GetPgClassDescriptor(), and GetPgIndexDescriptor().

3938 {
3939  TupleDesc result;
3940  MemoryContext oldcxt;
3941  int i;
3942 
3944 
3945  result = CreateTemplateTupleDesc(natts, hasoids);
3946  result->tdtypeid = RECORDOID; /* not right, but we don't care */
3947  result->tdtypmod = -1;
3948 
3949  for (i = 0; i < natts; i++)
3950  {
3951  memcpy(TupleDescAttr(result, i), &attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
3952  /* make sure attcacheoff is valid */
3953  TupleDescAttr(result, i)->attcacheoff = -1;
3954  }
3955 
3956  /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
3957  TupleDescAttr(result, 0)->attcacheoff = 0;
3958 
3959  /* Note: we don't bother to set up a TupleConstr entry */
3960 
3961  MemoryContextSwitchTo(oldcxt);
3962 
3963  return result;
3964 }
Oid tdtypeid
Definition: tupdesc.h:80
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int32 tdtypmod
Definition: tupdesc.h:81
#define RECORDOID
Definition: pg_type.h:680
#define ATTRIBUTE_FIXED_PART_SIZE
Definition: pg_attribute.h:179
TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid)
Definition: tupdesc.c:43
int i
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ CheckConstraintCmp()

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

Definition at line 4143 of file relcache.c.

References constrCheck::ccname.

Referenced by CheckConstraintFetch().

4144 {
4145  const ConstrCheck *ca = (const ConstrCheck *) a;
4146  const ConstrCheck *cb = (const ConstrCheck *) b;
4147 
4148  return strcmp(ca->ccname, cb->ccname);
4149 }
char * ccname
Definition: tupdesc.h:30

◆ CheckConstraintFetch()

static void CheckConstraintFetch ( Relation  relation)
static

Definition at line 4072 of file relcache.c.

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

Referenced by RelationBuildTupleDesc().

4073 {
4074  ConstrCheck *check = relation->rd_att->constr->check;
4075  int ncheck = relation->rd_att->constr->num_check;
4076  Relation conrel;
4077  SysScanDesc conscan;
4078  ScanKeyData skey[1];
4079  HeapTuple htup;
4080  int found = 0;
4081 
4082  ScanKeyInit(&skey[0],
4084  BTEqualStrategyNumber, F_OIDEQ,
4085  ObjectIdGetDatum(RelationGetRelid(relation)));
4086 
4088  conscan = systable_beginscan(conrel, ConstraintRelidIndexId, true,
4089  NULL, 1, skey);
4090 
4091  while (HeapTupleIsValid(htup = systable_getnext(conscan)))
4092  {
4094  Datum val;
4095  bool isnull;
4096  char *s;
4097 
4098  /* We want check constraints only */
4099  if (conform->contype != CONSTRAINT_CHECK)
4100  continue;
4101 
4102  if (found >= ncheck)
4103  elog(ERROR, "unexpected constraint record found for rel %s",
4104  RelationGetRelationName(relation));
4105 
4106  check[found].ccvalid = conform->convalidated;
4107  check[found].ccnoinherit = conform->connoinherit;
4109  NameStr(conform->conname));
4110 
4111  /* Grab and test conbin is actually set */
4112  val = fastgetattr(htup,
4114  conrel->rd_att, &isnull);
4115  if (isnull)
4116  elog(ERROR, "null conbin for rel %s",
4117  RelationGetRelationName(relation));
4118 
4119  /* detoast and convert to cstring in caller's context */
4120  s = TextDatumGetCString(val);
4121  check[found].ccbin = MemoryContextStrdup(CacheMemoryContext, s);
4122  pfree(s);
4123 
4124  found++;
4125  }
4126 
4127  systable_endscan(conscan);
4128  heap_close(conrel, AccessShareLock);
4129 
4130  if (found != ncheck)
4131  elog(ERROR, "%d constraint record(s) missing for rel %s",
4132  ncheck - found, RelationGetRelationName(relation));
4133 
4134  /* Sort the records so that CHECKs are applied in a deterministic order */
4135  if (ncheck > 1)
4136  qsort(check, ncheck, sizeof(ConstrCheck), CheckConstraintCmp);
4137 }
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define fastgetattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:724
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:4143
#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:936
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
#define RelationGetRelationName(relation)
Definition: rel.h:445
#define TextDatumGetCString(d)
Definition: builtins.h:92
uintptr_t Datum
Definition: postgres.h:365
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
TupleDesc rd_att
Definition: rel.h:115
FormData_pg_constraint * Form_pg_constraint
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
TupleConstr * constr
Definition: tupdesc.h:84
bool ccvalid
Definition: tupdesc.h:32
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1050
#define NameStr(name)
Definition: c.h:565
#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:408
#define RelationGetRelid(relation)
Definition: rel.h:425
long val
Definition: informix.c:689
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define ConstraintRelidIndexId
Definition: indexing.h:126
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ equalPartitionDescs()

static bool equalPartitionDescs ( PartitionKey  key,
PartitionDesc  partdesc1,
PartitionDesc  partdesc2 
)
static

Definition at line 1146 of file relcache.c.

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

Referenced by RelationClearRelation().

1148 {
1149  int i;
1150 
1151  if (partdesc1 != NULL)
1152  {
1153  if (partdesc2 == NULL)
1154  return false;
1155  if (partdesc1->nparts != partdesc2->nparts)
1156  return false;
1157 
1158  Assert(key != NULL || partdesc1->nparts == 0);
1159 
1160  /*
1161  * Same oids? If the partitioning structure did not change, that is,
1162  * no partitions were added or removed to the relation, the oids array
1163  * should still match element-by-element.
1164  */
1165  for (i = 0; i < partdesc1->nparts; i++)
1166  {
1167  if (partdesc1->oids[i] != partdesc2->oids[i])
1168  return false;
1169  }
1170 
1171  /*
1172  * Now compare partition bound collections. The logic to iterate over
1173  * the collections is private to partition.c.
1174  */
1175  if (partdesc1->boundinfo != NULL)
1176  {
1177  if (partdesc2->boundinfo == NULL)
1178  return false;
1179 
1181  key->parttypbyval,
1182  partdesc1->boundinfo,
1183  partdesc2->boundinfo))
1184  return false;
1185  }
1186  else if (partdesc2->boundinfo != NULL)
1187  return false;
1188  }
1189  else if (partdesc2 != NULL)
1190  return false;
1191 
1192  return true;
1193 }
bool partition_bounds_equal(int partnatts, int16 *parttyplen, bool *parttypbyval, PartitionBoundInfo b1, PartitionBoundInfo b2)
Definition: partition.c:747
PartitionBoundInfo boundinfo
Definition: partition.h:40
int16 partnatts
Definition: rel.h:55
bool * parttypbyval
Definition: rel.h:72
#define Assert(condition)
Definition: c.h:688
int16 * parttyplen
Definition: rel.h:71
int i

◆ equalPolicy()

static bool equalPolicy ( RowSecurityPolicy policy1,
RowSecurityPolicy policy2 
)
static

Definition at line 1067 of file relcache.c.

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

Referenced by equalRSDesc().

1068 {
1069  int i;
1070  Oid *r1,
1071  *r2;
1072 
1073  if (policy1 != NULL)
1074  {
1075  if (policy2 == NULL)
1076  return false;
1077 
1078  if (policy1->polcmd != policy2->polcmd)
1079  return false;
1080  if (policy1->hassublinks != policy2->hassublinks)
1081  return false;
1082  if (strcmp(policy1->policy_name, policy2->policy_name) != 0)
1083  return false;
1084  if (ARR_DIMS(policy1->roles)[0] != ARR_DIMS(policy2->roles)[0])
1085  return false;
1086 
1087  r1 = (Oid *) ARR_DATA_PTR(policy1->roles);
1088  r2 = (Oid *) ARR_DATA_PTR(policy2->roles);
1089 
1090  for (i = 0; i < ARR_DIMS(policy1->roles)[0]; i++)
1091  {
1092  if (r1[i] != r2[i])
1093  return false;
1094  }
1095 
1096  if (!equal(policy1->qual, policy2->qual))
1097  return false;
1098  if (!equal(policy1->with_check_qual, policy2->with_check_qual))
1099  return false;
1100  }
1101  else if (policy2 != NULL)
1102  return false;
1103 
1104  return true;
1105 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2991
unsigned int Oid
Definition: postgres_ext.h:31
#define ARR_DIMS(a)
Definition: array.h:279
#define ARR_DATA_PTR(a)
Definition: array.h:307
Expr * with_check_qual
Definition: rowsecurity.h:27
ArrayType * roles
Definition: rowsecurity.h:24
int i

◆ equalRSDesc()

static bool equalRSDesc ( RowSecurityDesc rsdesc1,
RowSecurityDesc rsdesc2 
)
static

Definition at line 1113 of file relcache.c.

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

Referenced by RelationClearRelation().

1114 {
1115  ListCell *lc,
1116  *rc;
1117 
1118  if (rsdesc1 == NULL && rsdesc2 == NULL)
1119  return true;
1120 
1121  if ((rsdesc1 != NULL && rsdesc2 == NULL) ||
1122  (rsdesc1 == NULL && rsdesc2 != NULL))
1123  return false;
1124 
1125  if (list_length(rsdesc1->policies) != list_length(rsdesc2->policies))
1126  return false;
1127 
1128  /* RelationBuildRowSecurity should build policies in order */
1129  forboth(lc, rsdesc1->policies, rc, rsdesc2->policies)
1130  {
1133 
1134  if (!equalPolicy(l, r))
1135  return false;
1136  }
1137 
1138  return true;
1139 }
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:180
static bool equalPolicy(RowSecurityPolicy *policy1, RowSecurityPolicy *policy2)
Definition: relcache.c:1067
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89

◆ equalRuleLocks()

static bool equalRuleLocks ( RuleLock rlock1,
RuleLock rlock2 
)
static

Definition at line 1022 of file relcache.c.

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

Referenced by RelationClearRelation().

1023 {
1024  int i;
1025 
1026  /*
1027  * As of 7.3 we assume the rule ordering is repeatable, because
1028  * RelationBuildRuleLock should read 'em in a consistent order. So just
1029  * compare corresponding slots.
1030  */
1031  if (rlock1 != NULL)
1032  {
1033  if (rlock2 == NULL)
1034  return false;
1035  if (rlock1->numLocks != rlock2->numLocks)
1036  return false;
1037  for (i = 0; i < rlock1->numLocks; i++)
1038  {
1039  RewriteRule *rule1 = rlock1->rules[i];
1040  RewriteRule *rule2 = rlock2->rules[i];
1041 
1042  if (rule1->ruleId != rule2->ruleId)
1043  return false;
1044  if (rule1->event != rule2->event)
1045  return false;
1046  if (rule1->enabled != rule2->enabled)
1047  return false;
1048  if (rule1->isInstead != rule2->isInstead)
1049  return false;
1050  if (!equal(rule1->qual, rule2->qual))
1051  return false;
1052  if (!equal(rule1->actions, rule2->actions))
1053  return false;
1054  }
1055  }
1056  else if (rlock2 != NULL)
1057  return false;
1058  return true;
1059 }
Node * qual
Definition: prs2lock.h:28
int numLocks
Definition: prs2lock.h:42
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2991
bool isInstead
Definition: prs2lock.h:31
CmdType event
Definition: prs2lock.h:27
RewriteRule ** rules
Definition: prs2lock.h:43
List * actions
Definition: prs2lock.h:29
int i
Oid ruleId
Definition: prs2lock.h:26
char enabled
Definition: prs2lock.h:30

◆ errtable()

int errtable ( Relation  rel)

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

5228 {
5232 
5233  return 0; /* return value does not matter */
5234 }
#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:3051
#define RelationGetRelationName(relation)
Definition: rel.h:445
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
#define RelationGetNamespace(relation)
Definition: rel.h:452

◆ errtablecol()

int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 5244 of file relcache.c.

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

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

5245 {
5246  TupleDesc reldesc = RelationGetDescr(rel);
5247  const char *colname;
5248 
5249  /* Use reldesc if it's a user attribute, else consult the catalogs */
5250  if (attnum > 0 && attnum <= reldesc->natts)
5251  colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
5252  else
5253  colname = get_attname(RelationGetRelid(rel), attnum, false);
5254 
5255  return errtablecolname(rel, colname);
5256 }
#define RelationGetDescr(relation)
Definition: rel.h:437
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
#define NameStr(name)
Definition: c.h:565
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition: lsyscache.c:775
#define RelationGetRelid(relation)
Definition: rel.h:425
int errtablecolname(Relation rel, const char *colname)
Definition: relcache.c:5268

◆ errtablecolname()

int errtablecolname ( Relation  rel,
const char *  colname 
)

Definition at line 5268 of file relcache.c.

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

Referenced by errtablecol().

5269 {
5270  errtable(rel);
5272 
5273  return 0; /* return value does not matter */
5274 }
#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:5227

◆ errtableconstraint()

int errtableconstraint ( Relation  rel,
const char *  conname 
)

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

5282 {
5283  errtable(rel);
5285 
5286  return 0; /* return value does not matter */
5287 }
#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:5227

◆ formrdesc()

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

Definition at line 1863 of file relcache.c.

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

Referenced by RelationCacheInitializePhase2(), and RelationCacheInitializePhase3().

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

◆ GetPgClassDescriptor()

static TupleDesc GetPgClassDescriptor ( void  )
static

Definition at line 3967 of file relcache.c.

References BuildHardcodedDescriptor(), Desc_pg_class, and Natts_pg_class.

Referenced by RelationParseRelOptions().

3968 {
3969  static TupleDesc pgclassdesc = NULL;
3970 
3971  /* Already done? */
3972  if (pgclassdesc == NULL)
3974  Desc_pg_class,
3975  true);
3976 
3977  return pgclassdesc;
3978 }
#define Natts_pg_class
Definition: pg_class.h:102
static TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs, bool hasoids)
Definition: relcache.c:3936
static const FormData_pg_attribute Desc_pg_class[Natts_pg_class]
Definition: relcache.c:96

◆ GetPgIndexDescriptor()

static TupleDesc GetPgIndexDescriptor ( void  )
static

Definition at line 3981 of file relcache.c.

References BuildHardcodedDescriptor(), Desc_pg_index, and Natts_pg_index.

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

3982 {
3983  static TupleDesc pgindexdesc = NULL;
3984 
3985  /* Already done? */
3986  if (pgindexdesc == NULL)
3988  Desc_pg_index,
3989  false);
3990 
3991  return pgindexdesc;
3992 }
static TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs, bool hasoids)
Definition: relcache.c:3936
static const FormData_pg_attribute Desc_pg_index[Natts_pg_index]
Definition: relcache.c:103
#define Natts_pg_index
Definition: pg_index.h:73

◆ GetRelationPublicationActions()

struct PublicationActions* GetRelationPublicationActions ( Relation  relation)

Definition at line 5156 of file relcache.c.

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

Referenced by CheckCmdReplicaIdentity().

5157 {
5158  List *puboids;
5159  ListCell *lc;
5160  MemoryContext oldcxt;
5161  PublicationActions *pubactions = palloc0(sizeof(PublicationActions));
5162 
5163  if (relation->rd_pubactions)
5164  return memcpy(pubactions, relation->rd_pubactions,
5165  sizeof(PublicationActions));
5166 
5167  /* Fetch the publication membership info. */
5168  puboids = GetRelationPublications(RelationGetRelid(relation));
5169  puboids = list_concat_unique_oid(puboids, GetAllTablesPublications());
5170 
5171  foreach(lc, puboids)
5172  {
5173  Oid pubid = lfirst_oid(lc);
5174  HeapTuple tup;
5175  Form_pg_publication pubform;
5176 
5178 
5179  if (!HeapTupleIsValid(tup))
5180  elog(ERROR, "cache lookup failed for publication %u", pubid);
5181 
5182  pubform = (Form_pg_publication) GETSTRUCT(tup);
5183 
5184  pubactions->pubinsert |= pubform->pubinsert;
5185  pubactions->pubupdate |= pubform->pubupdate;
5186  pubactions->pubdelete |= pubform->pubdelete;
5187 
5188  ReleaseSysCache(tup);
5189 
5190  /*
5191  * If we know everything is replicated, there is no point to check for
5192  * other publications.
5193  */
5194  if (pubactions->pubinsert && pubactions->pubupdate &&
5195  pubactions->pubdelete)
5196  break;
5197  }
5198 
5199  if (relation->rd_pubactions)
5200  {
5201  pfree(relation->rd_pubactions);
5202  relation->rd_pubactions = NULL;
5203  }
5204 
5205  /* Now save copy of the actions in the relcache entry. */
5207  relation->rd_pubactions = palloc(sizeof(PublicationActions));
5208  memcpy(relation->rd_pubactions, pubactions, sizeof(PublicationActions));
5209  MemoryContextSwitchTo(oldcxt);
5210 
5211  return pubactions;
5212 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
PublicationActions * rd_pubactions
Definition: rel.h:149
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned int Oid
Definition: postgres_ext.h:31
List * list_concat_unique_oid(List *list1, List *list2)
Definition: list.c:1082
List * GetRelationPublications(Oid relid)
void pfree(void *pointer)
Definition: mcxt.c:936
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void * palloc0(Size size)
Definition: mcxt.c:864
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
List * GetAllTablesPublications(void)
void * palloc(Size size)
Definition: mcxt.c:835
#define elog
Definition: elog.h:219
FormData_pg_publication * Form_pg_publication
Definition: pg_list.h:45
#define RelationGetRelid(relation)
Definition: rel.h:425
#define lfirst_oid(lc)
Definition: pg_list.h:108
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ IndexSupportInitialize()

static void IndexSupportInitialize ( oidvector indclass,
RegProcedure indexSupport,
Oid opFamily,
Oid opcInType,
StrategyNumber  maxSupportNumber,
AttrNumber  maxAttributeNumber 
)
static

Definition at line 1644 of file relcache.c.

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

Referenced by RelationInitIndexAccessInfo().

1650 {
1651  int attIndex;
1652 
1653  for (attIndex = 0; attIndex < maxAttributeNumber; attIndex++)
1654  {
1655  OpClassCacheEnt *opcentry;
1656 
1657  if (!OidIsValid(indclass->values[attIndex]))
1658  elog(ERROR, "bogus pg_index tuple");
1659 
1660  /* look up the info for this opclass, using a cache */
1661  opcentry = LookupOpclassInfo(indclass->values[attIndex],
1662  maxSupportNumber);
1663 
1664  /* copy cached data into relcache entry */
1665  opFamily[attIndex] = opcentry->opcfamily;
1666  opcInType[attIndex] = opcentry->opcintype;
1667  if (maxSupportNumber > 0)
1668  memcpy(&indexSupport[attIndex * maxSupportNumber],
1669  opcentry->supportProcs,
1670  maxSupportNumber * sizeof(RegProcedure));
1671  }
1672 }
regproc RegProcedure
Definition: c.h:461
#define OidIsValid(objectId)
Definition: c.h:594
#define ERROR
Definition: elog.h:43
RegProcedure * supportProcs
Definition: relcache.c:235
static OpClassCacheEnt * LookupOpclassInfo(Oid operatorClassOid, StrategyNumber numSupport)
Definition: relcache.c:1695
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:552
#define elog
Definition: elog.h:219

◆ InitIndexAmRoutine()

static void InitIndexAmRoutine ( Relation  relation)
static

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

1457 {
1458  IndexAmRoutine *cached,
1459  *tmp;
1460 
1461  /*
1462  * Call the amhandler in current, short-lived memory context, just in case
1463  * it leaks anything (it probably won't, but let's be paranoid).
1464  */
1465  tmp = GetIndexAmRoutine(relation->rd_amhandler);
1466 
1467  /* OK, now transfer the data into relation's rd_indexcxt. */
1468  cached = (IndexAmRoutine *) MemoryContextAlloc(relation->rd_indexcxt,
1469  sizeof(IndexAmRoutine));
1470  memcpy(cached, tmp, sizeof(IndexAmRoutine));
1471  relation->rd_amroutine = cached;
1472 
1473  pfree(tmp);
1474 }
struct IndexAmRoutine * rd_amroutine
Definition: rel.h:181
void pfree(void *pointer)
Definition: mcxt.c:936
Oid rd_amhandler
Definition: rel.h:178
IndexAmRoutine * GetIndexAmRoutine(Oid amhandler)
Definition: amapi.c:33
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:693
MemoryContext rd_indexcxt
Definition: rel.h:179

◆ insert_ordered_oid()

static List * insert_ordered_oid ( List list,
Oid  datum 
)
static

Definition at line 4535 of file relcache.c.

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

Referenced by RelationGetIndexList(), and RelationGetStatExtList().

4536 {
4537  ListCell *prev;
4538 
4539  /* Does the datum belong at the front? */
4540  if (list == NIL || datum < linitial_oid(list))
4541  return lcons_oid(datum, list);
4542  /* No, so find the entry it belongs after */
4543  prev = list_head(list);
4544  for (;;)
4545  {
4546  ListCell *curr = lnext(prev);
4547 
4548  if (curr == NULL || datum < lfirst_oid(curr))
4549  break; /* it belongs after 'prev', before 'curr' */
4550 
4551  prev = curr;
4552  }
4553  /* Insert datum into list after 'prev' */
4554  lappend_cell_oid(list, prev, datum);
4555  return list;
4556 }
#define NIL
Definition: pg_list.h:69
List * lcons_oid(Oid datum, List *list)
Definition: list.c:295
ListCell * lappend_cell_oid(List *list, ListCell *prev, Oid datum)
Definition: list.c:235
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
#define linitial_oid(l)
Definition: pg_list.h:113
#define lfirst_oid(lc)
Definition: pg_list.h:108

◆ load_critical_index()

static void load_critical_index ( Oid  indexoid,
Oid  heapoid 
)
static

Definition at line 3902 of file relcache.c.

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

Referenced by RelationCacheInitializePhase3().

3903 {
3904  Relation ird;
3905 
3906  /*
3907  * We must lock the underlying catalog before locking the index to avoid
3908  * deadlock, since RelationBuildDesc might well need to read the catalog,
3909  * and if anyone else is exclusive-locking this catalog and index they'll
3910  * be doing it in that order.
3911  */
3912  LockRelationOid(heapoid, AccessShareLock);
3913  LockRelationOid(indexoid, AccessShareLock);
3914  ird = RelationBuildDesc(indexoid, true);
3915  if (ird == NULL)
3916  elog(PANIC, "could not open critical system index %u", indexoid);
3917  ird->rd_isnailed = true;
3918  ird->rd_refcnt = 1;
3921 }
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:182
bool rd_isnailed
Definition: rel.h:91
#define AccessShareLock
Definition: lockdefs.h:36
#define PANIC
Definition: elog.h:53
static Relation RelationBuildDesc(Oid targetRelId, bool insertIt)
Definition: relcache.c:1208
int rd_refcnt
Definition: rel.h:88
#define elog
Definition: elog.h:219
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105

◆ load_relcache_init_file()

static bool load_relcache_init_file ( bool  shared)
static

Definition at line 5345 of file relcache.c.

References AllocateFile(), ALLOCSET_SMALL_SIZES, AllocSetContextCreateExtended(), IndexAmRoutine::amsupport, Assert, ATTRIBUTE_FIXED_PART_SIZE, CacheMemoryContext, tupleDesc::constr, CreateTemplateTupleDesc(), criticalRelcachesBuilt, criticalSharedRelcachesBuilt, DatabasePath, elog, FreeFile(), GETSTRUCT, tupleConstr::has_not_null, HEAPTUPLESIZE, i, InitIndexAmRoutine(), InvalidOid, InvalidSubTransactionId, MAXPGPATH, MEMCONTEXT_COPY_NAME, MemoryContextAlloc(), MemoryContextAllocZero(), MemSet, NIL, NUM_CRITICAL_LOCAL_INDEXES, NUM_CRITICAL_LOCAL_RELS, NUM_CRITICAL_SHARED_INDEXES, NUM_CRITICAL_SHARED_RELS, palloc(), palloc0(), pfree(), PG_BINARY_R, RelationData::pgstat_info, RelationData::rd_amcache, RelationData::rd_amroutine, RelationData::rd_att, RelationData::rd_createSubid, RelationData::rd_exclops, RelationData::rd_exclprocs, RelationData::rd_exclstrats, RelationData::rd_fdwroutine, RelationData::rd_fkeylist, RelationData::rd_fkeyvalid, RelationData::rd_idattr, RelationData::rd_indcollation, RelationData::rd_index, RelationData::rd_indexattr, RelationData::rd_indexcxt, RelationData::rd_indexlist, RelationData::rd_indexprs, RelationData::rd_indextuple, RelationData::rd_indexvalid, RelationData::rd_indoption, RelationData::rd_indpred, RelationData::rd_isnailed, RelationData::rd_keyattr, RelationData::rd_newRelfilenodeSubid, RelationData::rd_oidindex, RelationData::rd_opcintype, RelationData::rd_opfamily, RelationData::rd_options, RelationData::rd_partcheck, RelationData::rd_partdesc, RelationData::rd_partkey, RelationData::rd_partkeycxt, RelationData::rd_pdcxt, RelationData::rd_pkattr, RelationData::rd_pkindex, RelationData::rd_pubactions, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_replidindex, RelationData::rd_rsdesc, RelationData::rd_rules, RelationData::rd_rulescxt, RelationData::rd_smgr, RelationData::rd_statlist, RelationData::rd_statvalid, RelationData::rd_support, RelationData::rd_supportinfo, RelationCacheInsert, RelationGetRelationName, RelationInitLockInfo(), RelationInitPhysicalAddr(), RELCACHE_INIT_FILEMAGIC, RELCACHE_INIT_FILENAME, RELKIND_INDEX, repalloc(), snprintf(), HeapTupleData::t_data, tupleDesc::tdrefcount, tupleDesc::tdtypeid, tupleDesc::tdtypmod, RelationData::trigdesc, TupleDescAttr, VARSIZE, and WARNING.

Referenced by RelationCacheInitializePhase2(), and RelationCacheInitializePhase3().

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

◆ LookupOpclassInfo()

static OpClassCacheEnt * LookupOpclassInfo ( Oid  operatorClassOid,
StrategyNumber  numSupport 
)
static

Definition at line 1695 of file relcache.c.

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

Referenced by IndexSupportInitialize().

1697 {
1698  OpClassCacheEnt *opcentry;
1699  bool found;
1700  Relation rel;
1701  SysScanDesc scan;
1702  ScanKeyData skey[3];
1703  HeapTuple htup;
1704  bool indexOK;
1705 
1706  if (OpClassCache == NULL)
1707  {
1708  /* First time through: initialize the opclass cache */
1709  HASHCTL ctl;
1710 
1711  MemSet(&ctl, 0, sizeof(ctl));
1712  ctl.keysize = sizeof(Oid);
1713  ctl.entrysize = sizeof(OpClassCacheEnt);
1714  OpClassCache = hash_create("Operator class cache", 64,
1715  &ctl, HASH_ELEM | HASH_BLOBS);
1716 
1717  /* Also make sure CacheMemoryContext exists */
1718  if (!CacheMemoryContext)
1720  }
1721 
1722  opcentry = (OpClassCacheEnt *) hash_search(OpClassCache,
1723  (void *) &operatorClassOid,
1724  HASH_ENTER, &found);
1725 
1726  if (!found)
1727  {
1728  /* Need to allocate memory for new entry */
1729  opcentry->valid = false; /* until known OK */
1730  opcentry->numSupport = numSupport;
1731 
1732  if (numSupport > 0)
1733  opcentry->supportProcs = (RegProcedure *)
1735  numSupport * sizeof(RegProcedure));
1736  else
1737  opcentry->supportProcs = NULL;
1738  }
1739  else
1740  {
1741  Assert(numSupport == opcentry->numSupport);
1742  }
1743 
1744  /*
1745  * When testing for cache-flush hazards, we intentionally disable the
1746  * operator class cache and force reloading of the info on each call. This
1747  * is helpful because we want to test the case where a cache flush occurs
1748  * while we are loading the info, and it's very hard to provoke that if
1749  * this happens only once per opclass per backend.
1750  */
1751 #if defined(CLOBBER_CACHE_ALWAYS)
1752  opcentry->valid = false;
1753 #endif
1754 
1755  if (opcentry->valid)
1756  return opcentry;
1757 
1758  /*
1759  * Need to fill in new entry.
1760  *
1761  * To avoid infinite recursion during startup, force heap scans if we're
1762  * looking up info for the opclasses used by the indexes we would like to
1763  * reference here.
1764  */
1765  indexOK = criticalRelcachesBuilt ||
1766  (operatorClassOid != OID_BTREE_OPS_OID &&
1767  operatorClassOid != INT2_BTREE_OPS_OID);
1768 
1769  /*
1770  * We have to fetch the pg_opclass row to determine its opfamily and
1771  * opcintype, which are needed to look up related operators and functions.
1772  * It'd be convenient to use the syscache here, but that probably doesn't
1773  * work while bootstrapping.
1774  */
1775  ScanKeyInit(&skey[0],
1777  BTEqualStrategyNumber, F_OIDEQ,
1778  ObjectIdGetDatum(operatorClassOid));
1780  scan = systable_beginscan(rel, OpclassOidIndexId, indexOK,
1781  NULL, 1, skey);
1782 
1783  if (HeapTupleIsValid(htup = systable_getnext(scan)))
1784  {
1785  Form_pg_opclass opclassform = (Form_pg_opclass) GETSTRUCT(htup);
1786 
1787  opcentry->opcfamily = opclassform->opcfamily;
1788  opcentry->opcintype = opclassform->opcintype;
1789  }
1790  else
1791  elog(ERROR, "could not find tuple for opclass %u", operatorClassOid);
1792 
1793  systable_endscan(scan);
1795 
1796  /*
1797  * Scan pg_amproc to obtain support procs for the opclass. We only fetch
1798  * the default ones (those with lefttype = righttype = opcintype).
1799  */
1800  if (numSupport > 0)
1801  {
1802  ScanKeyInit(&skey[0],
1804  BTEqualStrategyNumber, F_OIDEQ,
1805  ObjectIdGetDatum(opcentry->opcfamily));
1806  ScanKeyInit(&skey[1],
1808  BTEqualStrategyNumber, F_OIDEQ,
1809  ObjectIdGetDatum(opcentry->opcintype));
1810  ScanKeyInit(&skey[2],
1812  BTEqualStrategyNumber, F_OIDEQ,
1813  ObjectIdGetDatum(opcentry->opcintype));
1815  scan = systable_beginscan(rel, AccessMethodProcedureIndexId, indexOK,
1816  NULL, 3, skey);
1817 
1818  while (HeapTupleIsValid(htup = systable_getnext(scan)))
1819  {
1820  Form_pg_amproc amprocform = (Form_pg_amproc) GETSTRUCT(htup);
1821 
1822  if (amprocform->amprocnum <= 0 ||
1823  (StrategyNumber) amprocform->amprocnum > numSupport)
1824  elog(ERROR, "invalid amproc number %d for opclass %u",
1825  amprocform->amprocnum, operatorClassOid);
1826 
1827  opcentry->supportProcs[amprocform->amprocnum - 1] =
1828  amprocform->amproc;
1829  }
1830 
1831  systable_endscan(scan);
1833  }
1834 
1835  opcentry->valid = true;
1836  return opcentry;
1837 }
struct opclasscacheent OpClassCacheEnt
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#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:461
#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:897
#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:904
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:232
#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:490
#define ERROR
Definition: elog.h:43
RegProcedure * supportProcs
Definition: relcache.c:235
#define Anum_pg_amproc_amprocfamily
Definition: pg_amproc.h:66
static HTAB * OpClassCache
Definition: relcache.c:238
#define Anum_pg_amproc_amprocrighttype
Definition: pg_amproc.h:68
#define HASH_BLOBS
Definition: hsearch.h:88
#define AccessMethodProcedureIndexId
Definition: indexing.h:82
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1290
Size keysize
Definition: hsearch.h:72
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:728
#define OpclassOidIndexId
Definition: indexing.h:200
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:688
void CreateCacheMemoryContext(void)
Definition: catcache.c:636
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define elog
Definition: elog.h:219
bool criticalRelcachesBuilt
Definition: relcache.c:125
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

◆ RelationBuildDesc()

static Relation RelationBuildDesc ( Oid  targetRelId,
bool  insertIt 
)
static

Definition at line 1208 of file relcache.c.

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

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

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

◆ RelationBuildLocalRelation()

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 3159 of file relcache.c.

References Assert, AssertArg, AttributeRelationId, AuthIdRelationId, AuthMemRelationId, BackendIdForTempRelations, BOOTSTRAP_SUPERUSERID, CacheMemoryContext, CLASS_TUPLE_SIZE, tupleDesc::constr, CreateCacheMemoryContext(), CreateTupleDescCopy(), DatabaseRelationId, elog, EOXactListAdd, ERROR, GetCurrentSubTransactionId(), tupleConstr::has_not_null, i, InvalidBackendId, InvalidOid, InvalidSubTransactionId, IsSharedRelation(), IsSystemNamespace(), isTempOrTempToastNamespace(), MemoryContextSwitchTo(), namestrcpy(), tupleDesc::natts, palloc0(), ProcedureRelationId, RelationData::rd_att, RelationData::rd_backend, RelationData::rd_createSubid, RelationData::rd_islocaltemp, RelationData::rd_isnailed, RelationData::rd_isvalid, RelationData::rd_newRelfilenodeSubid, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_smgr, RelationCacheInsert, RelationGetRelid, RelationIncrementReferenceCount(), RelationInitLockInfo(), RelationInitPhysicalAddr(), RelationMapUpdateMap(), RelationRelationId, RELKIND_MATVIEW, RELKIND_PARTITIONED_TABLE, RELKIND_RELATION, RELPERSISTENCE_PERMANENT, RELPERSISTENCE_TEMP, RELPERSISTENCE_UNLOGGED, REPLICA_IDENTITY_DEFAULT, REPLICA_IDENTITY_NOTHING, tupleDesc::tdhasoid, tupleDesc::tdrefcount, TupleDescAttr, and TypeRelationId.

Referenced by heap_create().

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

◆ RelationBuildPartitionKey()

static void RelationBuildPartitionKey ( Relation  relation)
static

Definition at line 827 of file relcache.c.

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

Referenced by RelationBuildDesc(), and RelationCacheInitializePhase3().

828 {
830  HeapTuple tuple;
831  bool isnull;
832  int i;
833  PartitionKey key;
834  AttrNumber *attrs;
835  oidvector *opclass;
836  oidvector *collation;
837  ListCell *partexprs_item;
838  Datum datum;
839  MemoryContext partkeycxt,
840  oldcxt;
841  int16 procnum;
842 
843  tuple = SearchSysCache1(PARTRELID,
845 
846  /*
847  * The following happens when we have created our pg_class entry but not
848  * the pg_partitioned_table entry yet.
849  */
850  if (!HeapTupleIsValid(tuple))
851  return;
852 
854  RelationGetRelationName(relation),
857 
858  key = (PartitionKey) MemoryContextAllocZero(partkeycxt,
859  sizeof(PartitionKeyData));
860 
861  /* Fixed-length attributes */
862  form = (Form_pg_partitioned_table) GETSTRUCT(tuple);
863  key->strategy = form->partstrat;
864  key->partnatts = form->partnatts;
865 
866  /*
867  * We can rely on the first variable-length attribute being mapped to the
868  * relevant field of the catalog's C struct, because all previous
869  * attributes are non-nullable and fixed-length.
870  */
871  attrs = form->partattrs.values;
872 
873  /* But use the hard way to retrieve further variable-length attributes */
874  /* Operator class */
875  datum = SysCacheGetAttr(PARTRELID, tuple,
877  Assert(!isnull);
878  opclass = (oidvector *) DatumGetPointer(datum);
879 
880  /* Collation */
881  datum = SysCacheGetAttr(PARTRELID, tuple,
883  Assert(!isnull);
884  collation = (oidvector *) DatumGetPointer(datum);
885 
886  /* Expressions */
887  datum = SysCacheGetAttr(PARTRELID, tuple,
889  if (!isnull)
890  {
891  char *exprString;
892  Node *expr;
893 
894  exprString = TextDatumGetCString(datum);
895  expr = stringToNode(exprString);
896  pfree(exprString);
897 
898  /*
899  * Run the expressions through const-simplification since the planner
900  * will be comparing them to similarly-processed qual clause operands,
901  * and may fail to detect valid matches without this step; fix
902  * opfuncids while at it. We don't need to bother with
903  * canonicalize_qual() though, because partition expressions are not
904  * full-fledged qualification clauses.
905  */
906  expr = eval_const_expressions(NULL, expr);
907  fix_opfuncids(expr);
908 
909  oldcxt = MemoryContextSwitchTo(partkeycxt);
910  key->partexprs = (List *) copyObject(expr);
911  MemoryContextSwitchTo(oldcxt);
912  }
913 
914  oldcxt = MemoryContextSwitchTo(partkeycxt);
915  key->partattrs = (AttrNumber *) palloc0(key->partnatts * sizeof(AttrNumber));
916  key->partopfamily = (Oid *) palloc0(key->partnatts * sizeof(Oid));
917  key->partopcintype = (Oid *) palloc0(key->partnatts * sizeof(Oid));
918  key->partsupfunc = (FmgrInfo *) palloc0(key->partnatts * sizeof(FmgrInfo));
919 
920  key->partcollation = (Oid *) palloc0(key->partnatts * sizeof(Oid));
921 
922  /* Gather type and collation info as well */
923  key->parttypid = (Oid *) palloc0(key->partnatts * sizeof(Oid));
924  key->parttypmod = (int32 *) palloc0(key->partnatts * sizeof(int32));
925  key->parttyplen = (int16 *) palloc0(key->partnatts * sizeof(int16));
926  key->parttypbyval = (bool *) palloc0(key->partnatts * sizeof(bool));
927  key->parttypalign = (char *) palloc0(key->partnatts * sizeof(char));
928  key->parttypcoll = (Oid *) palloc0(key->partnatts * sizeof(Oid));
929  MemoryContextSwitchTo(oldcxt);
930 
931  /* determine support function number to search for */
932  procnum = (key->strategy == PARTITION_STRATEGY_HASH) ?
934 
935  /* Copy partattrs and fill other per-attribute info */
936  memcpy(key->partattrs, attrs, key->partnatts * sizeof(int16));
937  partexprs_item = list_head(key->partexprs);
938  for (i = 0; i < key->partnatts; i++)
939  {
940  AttrNumber attno = key->partattrs[i];
941  HeapTuple opclasstup;
942  Form_pg_opclass opclassform;
943  Oid funcid;
944 
945  /* Collect opfamily information */
946  opclasstup = SearchSysCache1(CLAOID,
947  ObjectIdGetDatum(opclass->values[i]));
948  if (!HeapTupleIsValid(opclasstup))
949  elog(ERROR, "cache lookup failed for opclass %u", opclass->values[i]);
950 
951  opclassform = (Form_pg_opclass) GETSTRUCT(opclasstup);
952  key->partopfamily[i] = opclassform->opcfamily;
953  key->partopcintype[i] = opclassform->opcintype;
954 
955  /* Get a support function for the specified opfamily and datatypes */
956  funcid = get_opfamily_proc(opclassform->opcfamily,
957  opclassform->opcintype,
958  opclassform->opcintype,
959  procnum);
960  if (!OidIsValid(funcid))
961  ereport(ERROR,
962  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
963  errmsg("operator class \"%s\" of access method %s is missing support function %d for type %s",
964  NameStr(opclassform->opcname),
966  "hash" : "btree",
967  procnum,
968  format_type_be(opclassform->opcintype))));
969 
970  fmgr_info(funcid, &key->partsupfunc[i]);
971 
972  /* Collation */
973  key->partcollation[i] = collation->values[i];
974 
975  /* Collect type information */
976  if (attno != 0)
977  {
978  Form_pg_attribute att = TupleDescAttr(relation->rd_att, attno - 1);
979 
980  key->parttypid[i] = att->atttypid;
981  key->parttypmod[i] = att->atttypmod;
982  key->parttypcoll[i] = att->attcollation;
983  }
984  else
985  {
986  if (partexprs_item == NULL)
987  elog(ERROR, "wrong number of partition key expressions");
988 
989  key->parttypid[i] = exprType(lfirst(partexprs_item));
990  key->parttypmod[i] = exprTypmod(lfirst(partexprs_item));
991  key->parttypcoll[i] = exprCollation(lfirst(partexprs_item));
992 
993  partexprs_item = lnext(partexprs_item);
994  }
996  &key->parttyplen[i],
997  &key->parttypbyval[i],
998  &key->parttypalign[i]);
999 
1000  ReleaseSysCache(opclasstup);
1001  }
1002 
1003  ReleaseSysCache(tuple);
1004 
1005  /*
1006  * Success --- reparent our context and make the relcache point to the
1007  * newly constructed key
1008  */
1010  relation->rd_partkeycxt = partkeycxt;
1011  relation->rd_partkey = key;
1012 }
signed short int16
Definition: c.h:301
Definition: c.h:544
Definition: fmgr.h:56
void * stringToNode(char *str)
Definition: read.c:38
#define BTORDER_PROC
Definition: nbtree.h:235
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define MEMCONTEXT_COPY_NAME
Definition: memutils.h:188
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:2025
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:317
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1582
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:207
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext CurTransactionContext
Definition: mcxt.c:49
Definition: nodes.h:513
int errcode(int sqlerrcode)
Definition: elog.c:575
#define HASHEXTENDED_PROC
Definition: hash.h:352
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2462
char * format_type_be(Oid type_oid)
Definition: format_type.c:320
List * partexprs
Definition: rel.h:58
char strategy
Definition: rel.h:54
unsigned int Oid
Definition: postgres_ext.h:31
FormData_pg_partitioned_table * Form_pg_partitioned_table
#define OidIsValid(objectId)
Definition: c.h:594
signed int int32
Definition: c.h:302
void pfree(void *pointer)
Definition: mcxt.c:936
Oid * parttypcoll
Definition: rel.h:74
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
MemoryContext AllocSetContextCreateExtended(MemoryContext parent, const char *name, int flags, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:394
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:122
struct PartitionKeyData * rd_partkey
Definition: rel.h:129
#define Anum_pg_partitioned_table_partcollation
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:552
#define RelationGetRelationName(relation)
Definition: rel.h:445
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define lnext(lc)
Definition: pg_list.h:105
#define ereport(elevel, rest)
Definition: elog.h:122
Oid * parttypid
Definition: rel.h:69
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
Oid * partcollation
Definition: rel.h:66
#define TextDatumGetCString(d)
Definition: builtins.h:92
void * palloc0(Size size)
Definition: mcxt.c:864
AttrNumber * partattrs
Definition: rel.h:56
uintptr_t Datum
Definition: postgres.h:365
int16 partnatts
Definition: rel.h:55
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
char * parttypalign
Definition: rel.h:73
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
TupleDesc rd_att
Definition: rel.h:115
#define PARTITION_STRATEGY_HASH
Definition: parsenodes.h:795
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:728
int32 * parttypmod
Definition: rel.h:70
bool * parttypbyval
Definition: rel.h:72
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
int16 * parttyplen
Definition: rel.h:71
MemoryContext rd_partkeycxt
Definition: rel.h:128
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:744
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:720
#define DatumGetPointer(X)
Definition: postgres.h:532
struct PartitionKeyData * PartitionKey
Definition: rel.h:77
int errmsg(const char *fmt,...)
Definition: elog.c:797
Oid * partopcintype
Definition: rel.h:62
int i
#define NameStr(name)
Definition: c.h:565
#define elog
Definition: elog.h:219
#define Anum_pg_partitioned_table_partclass
#define copyObject(obj)
Definition: nodes.h:626
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:425
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ RelationBuildRuleLock()

static void RelationBuildRuleLock ( Relation  relation)
static

Definition at line 659 of file relcache.c.

References AccessShareLock, RewriteRule::actions, ALLOCSET_SMALL_SIZES, AllocSetContextCreateExtended(), 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, MEMCONTEXT_COPY_NAME, MemoryContextAlloc(), MemoryContextDelete(), MemoryContextSwitchTo(), RuleLock::numLocks, ObjectIdGetDatum, pfree(), RewriteRule::qual, RelationData::rd_rel, RelationData::rd_rules, RelationData::rd_rulescxt, RelationGetDescr, RelationGetRelationName, RelationGetRelid, repalloc(), RewriteRelationId, RewriteRelRulenameIndexId, RewriteRule::ruleId, RuleLock::rules, rules, ScanKeyInit(), setRuleCheckAsUser(), stringToNode(), systable_beginscan(), systable_endscan(), systable_getnext(), and TextDatumGetCString.

Referenced by RelationBuildDesc(), and RelationCacheInitializePhase3().

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

◆ RelationBuildTupleDesc()

static void RelationBuildTupleDesc ( Relation  relation)
static

Definition at line 487 of file relcache.c.

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

Referenced by RelationBuildDesc().

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

◆ RelationCacheInitFilePostInvalidate()

void RelationCacheInitFilePostInvalidate ( void  )

Definition at line 6064 of file relcache.c.

References LWLockRelease().

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

6065 {
6066  LWLockRelease(RelCacheInitLock);
6067 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1724

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )

Definition at line 6038 of file relcache.c.

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

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

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

◆ RelationCacheInitFileRemove()

void RelationCacheInitFileRemove ( void  )

Definition at line 6079 of file relcache.c.

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

Referenced by StartupXLOG().

6080 {
6081  const char *tblspcdir = "pg_tblspc";
6082  DIR *dir;
6083  struct dirent *de;
6084  char path[MAXPGPATH + 10 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6085 
6086  /*
6087  * We zap the shared cache file too. In theory it can't get out of sync
6088  * enough to be a problem, but in data-corruption cases, who knows ...
6089  */
6090  snprintf(path, sizeof(path), "global/%s",
6092  unlink_initfile(path);
6093 
6094  /* Scan everything in the default tablespace */
6096 
6097  /* Scan the tablespace link directory to find non-default tablespaces */
6098  dir = AllocateDir(tblspcdir);
6099 
6100  while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6101  {
6102  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6103  {
6104  /* Scan the tablespace dir for per-database dirs */
6105  snprintf(path, sizeof(path), "%s/%s/%s",
6106  tblspcdir, de->d_name, TABLESPACE_VERSION_DIRECTORY);
6108  }
6109  }
6110 
6111  FreeDir(dir);
6112 }
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition: relcache.c:6116
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2688
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:2607
static void unlink_initfile(const char *initfilename)
Definition: relcache.c:6140
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:24
#define TABLESPACE_VERSION_DIRECTORY
Definition: catalog.h:26
char d_name[MAX_PATH]
Definition: dirent.h:14
int FreeDir(DIR *dir)
Definition: fd.c:2725

◆ RelationCacheInitFileRemoveInDir()

static void RelationCacheInitFileRemoveInDir ( const char *  tblspcpath)
static

Definition at line 6116 of file relcache.c.

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

Referenced by RelationCacheInitFileRemove().

6117 {
6118  DIR *dir;
6119  struct dirent *de;
6120  char initfilename[MAXPGPATH * 2];
6121 
6122  /* Scan the tablespace directory to find per-database directories */
6123  dir = AllocateDir(tblspcpath);
6124 
6125  while ((de = ReadDirExtended(dir, tblspcpath, LOG)) != NULL)
6126  {
6127  if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6128  {
6129  /* Try to remove the init file in each database */
6130  snprintf(initfilename, sizeof(initfilename), "%s/%s/%s",
6131  tblspcpath, de->d_name, RELCACHE_INIT_FILENAME);
6132  unlink_initfile(initfilename);
6133  }
6134  }
6135 
6136  FreeDir(dir);
6137 }
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2688
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:2607
static void unlink_initfile(const char *initfilename)
Definition: relcache.c:6140
#define RELCACHE_INIT_FILENAME
Definition: relcache.h:24
char d_name[MAX_PATH]
Definition: dirent.h:14
int FreeDir(DIR *dir)
Definition: fd.c:2725

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 3511 of file relcache.c.

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

Referenced by InitPostgres().

3512 {
3513  HASHCTL ctl;
3514 
3515  /*
3516  * make sure cache memory context exists
3517  */
3518  if (!CacheMemoryContext)
3520 
3521  /*
3522  * create hashtable that indexes the relcache
3523  */
3524  MemSet(&ctl, 0, sizeof(ctl));
3525  ctl.keysize = sizeof(Oid);
3526  ctl.entrysize = sizeof(RelIdCacheEnt);
3527  RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
3528  &ctl, HASH_ELEM | HASH_BLOBS);
3529 
3530  /*
3531  * relation mapper needs to be initialized too
3532  */
3534 }
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:897
static HTAB * RelationIdCache
Definition: relcache.c:119
unsigned int Oid
Definition: postgres_ext.h:31
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Size keysize
Definition: hsearch.h:72
void CreateCacheMemoryContext(void)
Definition: catcache.c:636
#define INITRELCACHESIZE
Definition: relcache.c:3508
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ RelationCacheInitializePhase2()

void RelationCacheInitializePhase2 ( void  )

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

3549 {
3550  MemoryContext oldcxt;
3551 
3552  /*
3553  * relation mapper needs initialized too
3554  */
3556 
3557  /*
3558  * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
3559  * nothing.
3560  */
3562  return;
3563 
3564  /*
3565  * switch to cache memory context
3566  */
3568 
3569  /*
3570  * Try to load the shared relcache cache file. If unsuccessful, bootstrap
3571  * the cache with pre-made descriptors for the critical shared catalogs.
3572  */
3573  if (!load_relcache_init_file(true))
3574  {
3575  formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
3577  formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
3579  formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
3581  formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
3583  formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
3585 
3586 #define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
3587  }
3588 
3589  MemoryContextSwitchTo(oldcxt);
3590 }
static const FormData_pg_attribute Desc_pg_auth_members[Natts_pg_auth_members]
Definition: relcache.c:102
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5345
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, bool hasoids, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1863
#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:101
static const FormData_pg_attribute Desc_pg_subscription[Natts_pg_subscription]
Definition: relcache.c:105
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:100
#define Natts_pg_shseclabel
Definition: pg_shseclabel.h:41
static const FormData_pg_attribute Desc_pg_shseclabel[Natts_pg_shseclabel]
Definition: relcache.c:104
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:368
#define DatabaseRelation_Rowtype_Id
Definition: pg_database.h:30
#define Natts_pg_authid
Definition: pg_authid.h:78
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ RelationCacheInitializePhase3()

void RelationCacheInitializePhase3 ( void  )

Definition at line 3607 of file relcache.c.

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

Referenced by InitPostgres().

3608 {
3610  RelIdCacheEnt *idhentry;
3611  MemoryContext oldcxt;
3612  bool needNewCacheFile = !criticalSharedRelcachesBuilt;
3613 
3614  /*
3615  * relation mapper needs initialized too
3616  */
3618 
3619  /*
3620  * switch to cache memory context
3621  */
3623 
3624  /*
3625  * Try to load the local relcache cache file. If unsuccessful, bootstrap
3626  * the cache with pre-made descriptors for the critical "nailed-in" system
3627  * catalogs.
3628  */
3629  if (IsBootstrapProcessingMode() ||
3630  !load_relcache_init_file(false))
3631  {
3632  needNewCacheFile = true;
3633 
3634  formrdesc("pg_class", RelationRelation_Rowtype_Id, false,
3635  true, Natts_pg_class, Desc_pg_class);
3636  formrdesc("pg_attribute", AttributeRelation_Rowtype_Id, false,
3638  formrdesc("pg_proc", ProcedureRelation_Rowtype_Id, false,
3639  true, Natts_pg_proc, Desc_pg_proc);
3640  formrdesc("pg_type", TypeRelation_Rowtype_Id, false,
3641  true, Natts_pg_type, Desc_pg_type);
3642 
3643 #define NUM_CRITICAL_LOCAL_RELS 4 /* fix if you change list above */
3644  }
3645 
3646  MemoryContextSwitchTo(oldcxt);
3647 
3648  /* In bootstrap mode, the faked-up formrdesc info is all we'll have */
3650  return;
3651 
3652  /*
3653  * If we didn't get the critical system indexes loaded into relcache, do
3654  * so now. These are critical because the catcache and/or opclass cache
3655  * depend on them for fetches done during relcache load. Thus, we have an
3656  * infinite-recursion problem. We can break the recursion by doing
3657  * heapscans instead of indexscans at certain key spots. To avoid hobbling
3658  * performance, we only want to do that until we have the critical indexes
3659  * loaded into relcache. Thus, the flag criticalRelcachesBuilt is used to
3660  * decide whether to do heapscan or indexscan at the key spots, and we set
3661  * it true after we've loaded the critical indexes.
3662  *
3663  * The critical indexes are marked as "nailed in cache", partly to make it
3664  * easy for load_relcache_init_file to count them, but mainly because we
3665  * cannot flush and rebuild them once we've set criticalRelcachesBuilt to
3666  * true. (NOTE: perhaps it would be possible to reload them by
3667  * temporarily setting criticalRelcachesBuilt to false again. For now,
3668  * though, we just nail 'em in.)
3669  *
3670  * RewriteRelRulenameIndexId and TriggerRelidNameIndexId are not critical
3671  * in the same way as the others, because the critical catalogs don't
3672  * (currently) have any rules or triggers, and so these indexes can be
3673  * rebuilt without inducing recursion. However they are used during
3674  * relcache load when a rel does have rules or triggers, so we choose to
3675  * nail them for performance reasons.
3676  */
3678  {
3684  IndexRelationId);
3693 
3694 #define NUM_CRITICAL_LOCAL_INDEXES 7 /* fix if you change list above */
3695 
3696  criticalRelcachesBuilt = true;
3697  }
3698 
3699  /*
3700  * Process critical shared indexes too.
3701  *
3702  * DatabaseNameIndexId isn't critical for relcache loading, but rather for
3703  * initial lookup of MyDatabaseId, without which we'll never find any
3704  * non-shared catalogs at all. Autovacuum calls InitPostgres with a
3705  * database OID, so it instead depends on DatabaseOidIndexId. We also
3706  * need to nail up some indexes on pg_authid and pg_auth_members for use
3707  * during client authentication. SharedSecLabelObjectIndexId isn't
3708  * critical for the core system, but authentication hooks might be
3709  * interested in it.
3710  */
3712  {
3725 
3726 #define NUM_CRITICAL_SHARED_INDEXES 6 /* fix if you change list above */
3727 
3729  }
3730 
3731  /*
3732  * Now, scan all the relcache entries and update anything that might be
3733  * wrong in the results from formrdesc or the relcache cache file. If we
3734  * faked up relcache entries using formrdesc, then read the real pg_class
3735  * rows and replace the fake entries with them. Also, if any of the
3736  * relcache entries have rules, triggers, or security policies, load that
3737  * info the hard way since it isn't recorded in the cache file.
3738  *
3739  * Whenever we access the catalogs to read data, there is a possibility of
3740  * a shared-inval cache flush causing relcache entries to be removed.
3741  * Since hash_seq_search only guarantees to still work after the *current*
3742  * entry is removed, it's unsafe to continue the hashtable scan afterward.
3743  * We handle this by restarting the scan from scratch after each access.
3744  * This is theoretically O(N^2), but the number of entries that actually
3745  * need to be fixed is small enough that it doesn't matter.
3746  */
3747  hash_seq_init(&status, RelationIdCache);
3748 
3749  while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3750  {
3751  Relation relation = idhentry->reldesc;
3752  bool restart = false;
3753 
3754  /*
3755  * Make sure *this* entry doesn't get flushed while we work with it.
3756  */
3758 
3759  /*
3760  * If it's a faked-up entry, read the real pg_class tuple.
3761  */
3762  if (relation->rd_rel->relowner == InvalidOid)
3763  {
3764  HeapTuple htup;
3765  Form_pg_class relp;
3766 
3767  htup = SearchSysCache1(RELOID,
3768  ObjectIdGetDatum(RelationGetRelid(relation)));
3769  if (!HeapTupleIsValid(htup))
3770  elog(FATAL, "cache lookup failed for relation %u",
3771  RelationGetRelid(relation));
3772  relp = (Form_pg_class) GETSTRUCT(htup);
3773 
3774  /*
3775  * Copy tuple to relation->rd_rel. (See notes in
3776  * AllocateRelationDesc())
3777  */
3778  memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
3779 
3780  /* Update rd_options while we have the tuple */
3781  if (relation->rd_options)
3782  pfree(relation->rd_options);
3783  RelationParseRelOptions(relation, htup);
3784 
3785  /*
3786  * Check the values in rd_att were set up correctly. (We cannot
3787  * just copy them over now: formrdesc must have set up the rd_att
3788  * data correctly to start with, because it may already have been
3789  * copied into one or more catcache entries.)
3790  */
3791  Assert(relation->rd_att->tdtypeid == relp->reltype);
3792  Assert(relation->rd_att->tdtypmod == -1);
3793  Assert(relation->rd_att->tdhasoid == relp->relhasoids);
3794 
3795  ReleaseSysCache(htup);
3796 
3797  /* relowner had better be OK now, else we'll loop forever */
3798  if (relation->rd_rel->relowner == InvalidOid)
3799  elog(ERROR, "invalid relowner in pg_class entry for \"%s\"",
3800  RelationGetRelationName(relation));
3801 
3802  restart = true;
3803  }
3804 
3805  /*
3806  * Fix data that isn't saved in relcache cache file.
3807  *
3808  * relhasrules or relhastriggers could possibly be wrong or out of
3809  * date. If we don't actually find any rules or triggers, clear the
3810  * local copy of the flag so that we don't get into an infinite loop
3811  * here. We don't make any attempt to fix the pg_class entry, though.
3812  */
3813  if (relation->rd_rel->relhasrules && relation->rd_rules == NULL)
3814  {
3815  RelationBuildRuleLock(relation);
3816  if (relation->rd_rules == NULL)
3817  relation->rd_rel->relhasrules = false;
3818  restart = true;
3819  }
3820  if (relation->rd_rel->relhastriggers && relation->trigdesc == NULL)
3821  {
3822  RelationBuildTriggers(relation);
3823  if (relation->trigdesc == NULL)
3824  relation->rd_rel->relhastriggers = false;
3825  restart = true;
3826  }
3827 
3828  /*
3829  * Re-load the row security policies if the relation has them, since
3830  * they are not preserved in the cache. Note that we can never NOT
3831  * have a policy while relrowsecurity is true,
3832  * RelationBuildRowSecurity will create a single default-deny policy
3833  * if there is no policy defined in pg_policy.
3834  */
3835  if (relation->rd_rel->relrowsecurity && relation->rd_rsdesc == NULL)
3836  {
3837  RelationBuildRowSecurity(relation);
3838 
3839  Assert(relation->rd_rsdesc != NULL);
3840  restart = true;
3841  }
3842 
3843  /*
3844  * Reload the partition key and descriptor for a partitioned table.
3845  */
3846  if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
3847  relation->rd_partkey == NULL)
3848  {
3849  RelationBuildPartitionKey(relation);
3850  Assert(relation->rd_partkey != NULL);
3851 
3852  restart = true;
3853  }
3854 
3855  if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
3856  relation->rd_partdesc == NULL)
3857  {
3858  RelationBuildPartitionDesc(relation);
3859  Assert(relation->rd_partdesc != NULL);
3860 
3861  restart = true;
3862  }
3863 
3864  /* Release hold on the relation */
3866 
3867  /* Now, restart the hashtable scan if needed */
3868  if (restart)
3869  {
3870  hash_seq_term(&status);
3871  hash_seq_init(&status, RelationIdCache);
3872  }
3873  }
3874 
3875  /*
3876  * Lastly, write out new relcache cache files if needed. We don't bother
3877  * to distinguish cases where only one of the two needs an update.
3878  */
3879  if (needNewCacheFile)
3880  {
3881  /*
3882  * Force all the catcaches to finish initializing and thereby open the
3883  * catalogs and indexes they use. This will preload the relcache with
3884  * entries for all the most important system catalogs and indexes, so
3885  * that the init files will be most useful for future backends.
3886  */
3888 
3889  /* now write the files */
3891  write_relcache_init_file(false);
3892  }
3893 }
#define Natts_pg_class
Definition: pg_class.h:102
#define AttributeRelidNumIndexId
Definition: indexing.h:94
struct PartitionDescData * rd_partdesc
Definition: rel.h:131
static bool load_relcache_init_file(bool shared)
Definition: relcache.c:5345
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, bool hasoids, int natts, const FormData_pg_attribute *attrs)
Definition: relcache.c:1863
Oid tdtypeid
Definition: tupdesc.h:80
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define IndexRelidIndexId
Definition: indexing.h:164
bool tdhasoid
Definition: tupdesc.h:82
#define RewriteRelRulenameIndexId
Definition: indexing.h:223
void RelationBuildRowSecurity(Relation relation)
Definition: policy.c:191
#define AuthMemRelationId
#define IndexRelationId
Definition: pg_index.h:29
#define DatabaseRelationId
Definition: pg_database.h:29
#define RelationRelationId
Definition: pg_class.h:29
Relation reldesc
Definition: relcache.c:116
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define OperatorClassRelationId
Definition: pg_opclass.h:49
#define AttributeRelationId
Definition: pg_attribute.h:33
bool criticalSharedRelcachesBuilt
Definition: relcache.c:131
#define AuthIdOidIndexId
Definition: indexing.h:99
static HTAB * RelationIdCache
Definition: relcache.c:119
Form_pg_class rd_rel
Definition: rel.h:114
static void RelationBuildPartitionKey(Relation relation)
Definition: relcache.c:827
void RelationBuildPartitionDesc(Relation rel)
Definition: partition.c:200
int32 tdtypmod
Definition: tupdesc.h:81
#define AuthIdRelationId
Definition: pg_authid.h:42
#define TriggerRelidNameIndexId
Definition: indexing.h:249
void RelationDecrementReferenceCount(Relation rel)
Definition: relcache.c:2113
void pfree(void *pointer)
Definition: mcxt.c:936
#define Natts_pg_proc
Definition: pg_proc.h:89
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
#define ProcedureRelation_Rowtype_Id
Definition: pg_proc.h:34
#define FATAL
Definition: elog.h:52
static void write_relcache_init_file(bool shared)
Definition: relcache.c:5734
struct PartitionKeyData * rd_partkey
Definition: rel.h:129
TriggerDesc * trigdesc
Definition: rel.h:120
static void RelationParseRelOptions(Relation relation, HeapTuple tuple)
Definition: relcache.c:430
static void load_critical_index(Oid indexoid, Oid heapoid)
Definition: relcache.c:3902
static const FormData_pg_attribute Desc_pg_proc[Natts_pg_proc]
Definition: relcache.c:98
#define RelationGetRelationName(relation)
Definition: rel.h:445
#define DatabaseOidIndexId
Definition: indexing.h:142
#define ClassOidIndexId
Definition: indexing.h:112
struct RowSecurityDesc * rd_rsdesc
Definition: rel.h:122
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112