PostgreSQL Source Code git master
Loading...
Searching...
No Matches
relcache.c File Reference
#include "postgres.h"
#include <sys/file.h>
#include <fcntl.h>
#include <unistd.h>
#include "access/htup_details.h"
#include "access/multixact.h"
#include "access/parallel.h"
#include "access/reloptions.h"
#include "access/sysattr.h"
#include "access/table.h"
#include "access/tableam.h"
#include "access/tupdesc_details.h"
#include "access/xact.h"
#include "catalog/binary_upgrade.h"
#include "catalog/catalog.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_auth_members.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_database.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.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/publicationcmds.h"
#include "commands/trigger.h"
#include "common/int.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/optimizer.h"
#include "pgstat.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/catcache.h"
#include "utils/datum.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/relmapper.h"
#include "utils/resowner.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
Include dependency graph for relcache.c:

Go to the source code of this file.

Data Structures

struct  relidcacheent
 
struct  inprogressent
 
struct  opclasscacheent
 

Macros

#define RELCACHE_INIT_FILEMAGIC   0x573266 /* version ID value */
 
#define RECOVER_RELATION_BUILD_MEMORY   0
 
#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 inprogressent InProgressEnt
 
typedef struct opclasscacheent OpClassCacheEnt
 

Functions

static void RelationCloseCleanup (Relation relation)
 
static void RelationDestroyRelation (Relation relation, bool remember_tupdesc)
 
static void RelationInvalidateRelation (Relation relation)
 
static void RelationClearRelation (Relation relation)
 
static void RelationRebuildRelation (Relation relation)
 
static void RelationReloadIndexInfo (Relation relation)
 
static void RelationReloadNailed (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, 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 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, int ndef)
 
static int AttrDefaultCmp (const void *a, const void *b)
 
static void CheckNNConstraintFetch (Relation relation)
 
static int CheckConstraintCmp (const void *a, const void *b)
 
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, int elevel)
 
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)
 
static void InitTableAmRoutine (Relation relation)
 
void RelationInitTableAccessMethod (Relation relation)
 
Relation RelationIdGetRelation (Oid relationId)
 
static void ResOwnerReleaseRelation (Datum res)
 
static charResOwnerPrintRelCache (Datum res)
 
static void ResourceOwnerRememberRelationRef (ResourceOwner owner, Relation rel)
 
static void ResourceOwnerForgetRelationRef (ResourceOwner owner, Relation rel)
 
void RelationIncrementReferenceCount (Relation rel)
 
void RelationDecrementReferenceCount (Relation rel)
 
void RelationClose (Relation relation)
 
void RelationForgetRelation (Oid rid)
 
void RelationCacheInvalidateEntry (Oid relationId)
 
void RelationCacheInvalidate (bool debug_discard)
 
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 accessmtd, RelFileNumber relfilenumber, Oid reltablespace, bool shared_relation, bool mapped_relation, char relpersistence, char relkind)
 
void RelationSetNewRelfilenumber (Relation relation, char persistence)
 
void RelationAssumeNewRelfilelocator (Relation relation)
 
void RelationCacheInitialize (void)
 
void RelationCacheInitializePhase2 (void)
 
void RelationCacheInitializePhase3 (void)
 
static TupleDesc BuildHardcodedDescriptor (int natts, const FormData_pg_attribute *attrs)
 
ListRelationGetFKeyList (Relation relation)
 
ListRelationGetIndexList (Relation relation)
 
ListRelationGetStatExtList (Relation relation)
 
Oid RelationGetPrimaryKeyIndex (Relation relation, bool deferrable_ok)
 
Oid RelationGetReplicaIndex (Relation relation)
 
ListRelationGetIndexExpressions (Relation relation)
 
ListRelationGetDummyIndexExpressions (Relation relation)
 
ListRelationGetIndexPredicate (Relation relation)
 
BitmapsetRelationGetIndexAttrBitmap (Relation relation, IndexAttrBitmapKind attrKind)
 
BitmapsetRelationGetIdentityKeyBitmap (Relation relation)
 
void RelationGetExclusionInfo (Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
 
void RelationBuildPublicationDesc (Relation relation, PublicationDesc *pubdesc)
 
static bytea ** CopyIndexAttOptions (bytea **srcopts, int natts)
 
bytea ** RelationGetIndexAttOptions (Relation relation, bool copy)
 
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)
 
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 InProgressEntin_progress_list
 
static int in_progress_list_len
 
static int in_progress_list_maxlen
 
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
 
static const ResourceOwnerDesc relref_resowner_desc
 

Macro Definition Documentation

◆ EOXactListAdd

#define EOXactListAdd (   rel)
Value:
do { \
eoxact_list[eoxact_list_len++] = (rel)->rd_id; \
} while (0)
static int fb(int x)
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition relcache.c:185
#define MAX_EOXACT_LIST
Definition relcache.c:184
static int eoxact_list_len
Definition relcache.c:186

Definition at line 189 of file relcache.c.

190 { \
192 eoxact_list[eoxact_list_len++] = (rel)->rd_id; \
193 else \
195 } while (0)

◆ INITRELCACHESIZE

#define INITRELCACHESIZE   400

Definition at line 3994 of file relcache.c.

◆ MAX_EOXACT_LIST

#define MAX_EOXACT_LIST   32

Definition at line 184 of file relcache.c.

◆ NUM_CRITICAL_LOCAL_INDEXES

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

◆ NUM_CRITICAL_LOCAL_RELS

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

◆ NUM_CRITICAL_SHARED_INDEXES

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

◆ NUM_CRITICAL_SHARED_RELS

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

◆ RECOVER_RELATION_BUILD_MEMORY

#define RECOVER_RELATION_BUILD_MEMORY   0

Definition at line 102 of file relcache.c.

◆ RelationCacheDelete

#define RelationCacheDelete (   RELATION)
Value:
do { \
&((RELATION)->rd_id), \
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:952
#define WARNING
Definition elog.h:36
@ HASH_REMOVE
Definition hsearch.h:115
static HTAB * RelationIdCache
Definition relcache.c:134

Definition at line 243 of file relcache.c.

244 { \
247 &((RELATION)->rd_id), \
249 if (hentry == NULL) \
250 elog(WARNING, "failed to delete relcache entry for OID %u", \
251 (RELATION)->rd_id); \
252} while(0)

◆ RelationCacheInsert

#define RelationCacheInsert (   RELATION,
  replace_allowed 
)
Value:
do { \
RelIdCacheEnt *hentry; bool found; \
&((RELATION)->rd_id), \
HASH_ENTER, &found); \
if (found) \
{ \
/* see comments in RelationBuildDesc and RelationBuildLocalRelation */ \
Relation _old_rel = hentry->reldesc; \
hentry->reldesc = (RELATION); \
elog(WARNING, "leaking still-referenced relcache entry for \"%s\"", \
} \
hentry->reldesc = (RELATION); \
} while(0)
@ HASH_ENTER
Definition hsearch.h:114
#define IsBootstrapProcessingMode()
Definition miscadmin.h:477
#define RelationHasReferenceCountZero(relation)
Definition rel.h:498
#define RelationGetRelationName(relation)
Definition rel.h:548

Definition at line 209 of file relcache.c.

210 { \
211 RelIdCacheEnt *hentry; bool found; \
213 &((RELATION)->rd_id), \
214 HASH_ENTER, &found); \
215 if (found) \
216 { \
217 /* see comments in RelationBuildDesc and RelationBuildLocalRelation */ \
218 Relation _old_rel = hentry->reldesc; \
220 hentry->reldesc = (RELATION); \
223 else if (!IsBootstrapProcessingMode()) \
224 elog(WARNING, "leaking still-referenced relcache entry for \"%s\"", \
226 } \
227 else \
228 hentry->reldesc = (RELATION); \
229} while(0)

◆ RelationIdCacheLookup

#define RelationIdCacheLookup (   ID,
  RELATION 
)
Value:

Definition at line 231 of file relcache.c.

232 { \
235 &(ID), \
236 HASH_FIND, NULL); \
237 if (hentry) \
239 else \
240 RELATION = NULL; \
241} while(0)

◆ RELCACHE_INIT_FILEMAGIC

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

Definition at line 93 of file relcache.c.

◆ SWAPFIELD

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

Typedef Documentation

◆ InProgressEnt

◆ OpClassCacheEnt

◆ RelIdCacheEnt

Function Documentation

◆ AllocateRelationDesc()

static Relation AllocateRelationDesc ( Form_pg_class  relp)
static

Definition at line 413 of file relcache.c.

414{
415 Relation relation;
418
419 /* Relcache entries must live in CacheMemoryContext */
421
422 /*
423 * allocate and zero space for new relation descriptor
424 */
425 relation = palloc0_object(RelationData);
426
427 /* make sure relation is marked as having no open file yet */
428 relation->rd_smgr = NULL;
429
430 /*
431 * Copy the relation tuple form
432 *
433 * We only allocate space for the fixed fields, ie, CLASS_TUPLE_SIZE. The
434 * variable-length fields (relacl, reloptions) are NOT stored in the
435 * relcache --- there'd be little point in it, since we don't copy the
436 * tuple's nulls bitmap and hence wouldn't know if the values are valid.
437 * Bottom line is that relacl *cannot* be retrieved from the relcache. Get
438 * it from the syscache if you need it. The same goes for the original
439 * form of reloptions (however, we do store the parsed form of reloptions
440 * in rd_options).
441 */
443
445
446 /* initialize relation tuple form */
447 relation->rd_rel = relationForm;
448
449 /* and allocate attribute tuple form storage */
450 relation->rd_att = CreateTemplateTupleDesc(relationForm->relnatts);
451 /* which we mark as a reference-counted tupdesc */
452 relation->rd_att->tdrefcount = 1;
453
455
456 return relation;
457}
#define palloc0_object(type)
Definition fe_memutils.h:75
void * palloc(Size size)
Definition mcxt.c:1387
MemoryContext CacheMemoryContext
Definition mcxt.c:169
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
FormData_pg_class * Form_pg_class
Definition pg_class.h:156
#define CLASS_TUPLE_SIZE
Definition pg_class.h:148
TupleDesc rd_att
Definition rel.h:112
SMgrRelation rd_smgr
Definition rel.h:58
Form_pg_class rd_rel
Definition rel.h:111
TupleDesc CreateTemplateTupleDesc(int natts)
Definition tupdesc.c:182

References CacheMemoryContext, CLASS_TUPLE_SIZE, CreateTemplateTupleDesc(), fb(), MemoryContextSwitchTo(), palloc(), palloc0_object, RelationData::rd_att, RelationData::rd_rel, RelationData::rd_smgr, and TupleDescData::tdrefcount.

Referenced by RelationBuildDesc().

◆ AtEOSubXact_cleanup()

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

Definition at line 3428 of file relcache.c.

3430{
3431 /*
3432 * Is it a relation created in the current subtransaction?
3433 *
3434 * During subcommit, mark it as belonging to the parent, instead, as long
3435 * as it has not been dropped. Otherwise simply delete the relcache entry.
3436 * --- it isn't interesting any longer.
3437 */
3438 if (relation->rd_createSubid == mySubid)
3439 {
3440 /*
3441 * Valid rd_droppedSubid means the corresponding relation is dropped
3442 * but the relcache entry is preserved for at-commit pending sync. We
3443 * need to drop it explicitly here not to make the entry orphan.
3444 */
3445 Assert(relation->rd_droppedSubid == mySubid ||
3448 relation->rd_createSubid = parentSubid;
3449 else if (RelationHasReferenceCountZero(relation))
3450 {
3451 /* allow the entry to be removed */
3456 RelationClearRelation(relation);
3457 return;
3458 }
3459 else
3460 {
3461 /*
3462 * Hmm, somewhere there's a (leaked?) reference to the relation.
3463 * We daren't remove the entry for fear of dereferencing a
3464 * dangling pointer later. Bleat, and transfer it to the parent
3465 * subtransaction so we can try again later. This must be just a
3466 * WARNING to avoid error-during-error-recovery loops.
3467 */
3468 relation->rd_createSubid = parentSubid;
3469 elog(WARNING, "cannot remove relcache entry for \"%s\" because it has nonzero refcount",
3470 RelationGetRelationName(relation));
3471 }
3472 }
3473
3474 /*
3475 * Likewise, update or drop any new-relfilenumber-in-subtransaction record
3476 * or drop record.
3477 */
3478 if (relation->rd_newRelfilelocatorSubid == mySubid)
3479 {
3480 if (isCommit)
3482 else
3484 }
3485
3486 if (relation->rd_firstRelfilelocatorSubid == mySubid)
3487 {
3488 if (isCommit)
3490 else
3492 }
3493
3494 if (relation->rd_droppedSubid == mySubid)
3495 {
3496 if (isCommit)
3497 relation->rd_droppedSubid = parentSubid;
3498 else
3500 }
3501}
#define InvalidSubTransactionId
Definition c.h:682
#define Assert(condition)
Definition c.h:883
#define elog(elevel,...)
Definition elog.h:226
static void RelationClearRelation(Relation relation)
Definition relcache.c:2541
SubTransactionId rd_firstRelfilelocatorSubid
Definition rel.h:106
SubTransactionId rd_newRelfilelocatorSubid
Definition rel.h:104
SubTransactionId rd_createSubid
Definition rel.h:103
SubTransactionId rd_droppedSubid
Definition rel.h:109

References Assert, elog, fb(), InvalidSubTransactionId, RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_firstRelfilelocatorSubid, RelationData::rd_newRelfilelocatorSubid, RelationClearRelation(), RelationGetRelationName, RelationHasReferenceCountZero, and WARNING.

Referenced by AtEOSubXact_RelationCache().

◆ AtEOSubXact_RelationCache()

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

Definition at line 3373 of file relcache.c.

3375{
3376 HASH_SEQ_STATUS status;
3378 int i;
3379
3380 /*
3381 * Forget in_progress_list. This is relevant when we're aborting due to
3382 * an error during RelationBuildDesc(). We don't commit subtransactions
3383 * during RelationBuildDesc().
3384 */
3387
3388 /*
3389 * Unless the eoxact_list[] overflowed, we only need to examine the rels
3390 * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3391 * logic as in AtEOXact_RelationCache.
3392 */
3394 {
3396 while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3397 {
3400 }
3401 }
3402 else
3403 {
3404 for (i = 0; i < eoxact_list_len; i++)
3405 {
3407 &eoxact_list[i],
3408 HASH_FIND,
3409 NULL);
3410 if (idhentry != NULL)
3413 }
3414 }
3415
3416 /* Don't reset the list; we still need more cleanup later */
3417}
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition dynahash.c:1415
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition dynahash.c:1380
int i
Definition isn.c:77
static int in_progress_list_len
Definition relcache.c:171
static void AtEOSubXact_cleanup(Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
Definition relcache.c:3428
static bool eoxact_list_overflowed
Definition relcache.c:187

References Assert, AtEOSubXact_cleanup(), eoxact_list, eoxact_list_len, eoxact_list_overflowed, fb(), HASH_FIND, hash_search(), hash_seq_init(), hash_seq_search(), i, in_progress_list_len, and RelationIdCache.

Referenced by AbortSubTransaction(), and CommitSubTransaction().

◆ AtEOXact_cleanup()

static void AtEOXact_cleanup ( Relation  relation,
bool  isCommit 
)
static

Definition at line 3291 of file relcache.c.

3292{
3293 bool clear_relcache = false;
3294
3295 /*
3296 * The relcache entry's ref count should be back to its normal
3297 * not-in-a-transaction state: 0 unless it's nailed in cache.
3298 *
3299 * In bootstrap mode, this is NOT true, so don't check it --- the
3300 * bootstrap code expects relations to stay open across start/commit
3301 * transaction calls. (That seems bogus, but it's not worth fixing.)
3302 *
3303 * Note: ideally this check would be applied to every relcache entry, not
3304 * just those that have eoxact work to do. But it's not worth forcing a
3305 * scan of the whole relcache just for this. (Moreover, doing so would
3306 * mean that assert-enabled testing never tests the hash_search code path
3307 * above, which seems a bad idea.)
3308 */
3309#ifdef USE_ASSERT_CHECKING
3311 {
3312 int expected_refcnt;
3313
3314 expected_refcnt = relation->rd_isnailed ? 1 : 0;
3315 Assert(relation->rd_refcnt == expected_refcnt);
3316 }
3317#endif
3318
3319 /*
3320 * Is the relation live after this transaction ends?
3321 *
3322 * During commit, clear the relcache entry if it is preserved after
3323 * relation drop, in order not to orphan the entry. During rollback,
3324 * clear the relcache entry if the relation is created in the current
3325 * transaction since it isn't interesting any longer once we are out of
3326 * the transaction.
3327 */
3329 (isCommit ?
3332
3333 /*
3334 * Since we are now out of the transaction, reset the subids to zero. That
3335 * also lets RelationClearRelation() drop the relcache entry.
3336 */
3341
3342 if (clear_relcache)
3343 {
3344 if (RelationHasReferenceCountZero(relation))
3345 {
3346 RelationClearRelation(relation);
3347 return;
3348 }
3349 else
3350 {
3351 /*
3352 * Hmm, somewhere there's a (leaked?) reference to the relation.
3353 * We daren't remove the entry for fear of dereferencing a
3354 * dangling pointer later. Bleat, and mark it as not belonging to
3355 * the current transaction. Hopefully it'll get cleaned up
3356 * eventually. This must be just a WARNING to avoid
3357 * error-during-error-recovery loops.
3358 */
3359 elog(WARNING, "cannot remove relcache entry for \"%s\" because it has nonzero refcount",
3360 RelationGetRelationName(relation));
3361 }
3362 }
3363}
int rd_refcnt
Definition rel.h:59
bool rd_isnailed
Definition rel.h:62

References Assert, elog, fb(), InvalidSubTransactionId, IsBootstrapProcessingMode, RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_firstRelfilelocatorSubid, RelationData::rd_isnailed, RelationData::rd_newRelfilelocatorSubid, RelationData::rd_refcnt, RelationClearRelation(), RelationGetRelationName, RelationHasReferenceCountZero, and WARNING.

Referenced by AtEOXact_RelationCache().

◆ AtEOXact_RelationCache()

void AtEOXact_RelationCache ( bool  isCommit)

Definition at line 3221 of file relcache.c.

3222{
3223 HASH_SEQ_STATUS status;
3225 int i;
3226
3227 /*
3228 * Forget in_progress_list. This is relevant when we're aborting due to
3229 * an error during RelationBuildDesc().
3230 */
3233
3234 /*
3235 * Unless the eoxact_list[] overflowed, we only need to examine the rels
3236 * listed in it. Otherwise fall back on a hash_seq_search scan.
3237 *
3238 * For simplicity, eoxact_list[] entries are not deleted till end of
3239 * top-level transaction, even though we could remove them at
3240 * subtransaction end in some cases, or remove relations from the list if
3241 * they are cleared for other reasons. Therefore we should expect the
3242 * case that list entries are not found in the hashtable; if not, there's
3243 * nothing to do for them.
3244 */
3246 {
3248 while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3249 {
3251 }
3252 }
3253 else
3254 {
3255 for (i = 0; i < eoxact_list_len; i++)
3256 {
3258 &eoxact_list[i],
3259 HASH_FIND,
3260 NULL);
3261 if (idhentry != NULL)
3263 }
3264 }
3265
3267 {
3269 for (i = 0; i < NextEOXactTupleDescNum; i++)
3273 }
3274
3275 /* Now we're out of the transaction and can clear the lists */
3276 eoxact_list_len = 0;
3277 eoxact_list_overflowed = false;
3280}
void pfree(void *pointer)
Definition mcxt.c:1616
static int NextEOXactTupleDescNum
Definition relcache.c:203
static int EOXactTupleDescArrayLen
Definition relcache.c:204
static void AtEOXact_cleanup(Relation relation, bool isCommit)
Definition relcache.c:3291
static TupleDesc * EOXactTupleDescArray
Definition relcache.c:202
void FreeTupleDesc(TupleDesc tupdesc)
Definition tupdesc.c:502

References Assert, AtEOXact_cleanup(), eoxact_list, eoxact_list_len, eoxact_list_overflowed, EOXactTupleDescArray, EOXactTupleDescArrayLen, fb(), FreeTupleDesc(), HASH_FIND, hash_search(), hash_seq_init(), hash_seq_search(), i, in_progress_list_len, NextEOXactTupleDescNum, pfree(), and RelationIdCache.

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

◆ AttrDefaultCmp()

static int AttrDefaultCmp ( const void a,
const void b 
)
static

Definition at line 4570 of file relcache.c.

4571{
4572 const AttrDefault *ada = (const AttrDefault *) a;
4573 const AttrDefault *adb = (const AttrDefault *) b;
4574
4575 return pg_cmp_s16(ada->adnum, adb->adnum);
4576}
static int pg_cmp_s16(int16 a, int16 b)
Definition int.h:701
int b
Definition isn.c:74
int a
Definition isn.c:73

References a, b, fb(), and pg_cmp_s16().

Referenced by AttrDefaultFetch().

◆ AttrDefaultFetch()

static void AttrDefaultFetch ( Relation  relation,
int  ndef 
)
static

Definition at line 4490 of file relcache.c.

4491{
4496 HeapTuple htup;
4497 int found = 0;
4498
4499 /* Allocate array with room for as many entries as expected */
4500 attrdef = (AttrDefault *)
4502 ndef * sizeof(AttrDefault));
4503
4504 /* Search pg_attrdef for relevant entries */
4509
4512 NULL, 1, &skey);
4513
4515 {
4517 Datum val;
4518 bool isnull;
4519
4520 /* protect limited size of array */
4521 if (found >= ndef)
4522 {
4523 elog(WARNING, "unexpected pg_attrdef record found for attribute %d of relation \"%s\"",
4524 adform->adnum, RelationGetRelationName(relation));
4525 break;
4526 }
4527
4528 val = fastgetattr(htup,
4530 adrel->rd_att, &isnull);
4531 if (isnull)
4532 elog(WARNING, "null adbin for attribute %d of relation \"%s\"",
4533 adform->adnum, RelationGetRelationName(relation));
4534 else
4535 {
4536 /* detoast and convert to cstring in caller's context */
4537 char *s = TextDatumGetCString(val);
4538
4539 attrdef[found].adnum = adform->adnum;
4541 pfree(s);
4542 found++;
4543 }
4544 }
4545
4548
4549 if (found != ndef)
4550 elog(WARNING, "%d pg_attrdef record(s) missing for relation \"%s\"",
4551 ndef - found, RelationGetRelationName(relation));
4552
4553 /*
4554 * Sort the AttrDefault entries by adnum, for the convenience of
4555 * equalTupleDescs(). (Usually, they already will be in order, but this
4556 * might not be so if systable_getnext isn't using an index.)
4557 */
4558 if (found > 1)
4559 qsort(attrdef, found, sizeof(AttrDefault), AttrDefaultCmp);
4560
4561 /* Install array only after it's fully valid */
4562 relation->rd_att->constr->defval = attrdef;
4563 relation->rd_att->constr->num_defval = found;
4564}
#define TextDatumGetCString(d)
Definition builtins.h:98
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:603
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:514
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition genam.c:388
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
static Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
long val
Definition informix.c:689
#define AccessShareLock
Definition lockdefs.h:36
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition mcxt.c:1768
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition mcxt.c:1266
FormData_pg_attrdef * Form_pg_attrdef
Definition pg_attrdef.h:49
#define qsort(a, b, c, d)
Definition port.h:495
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
uint64_t Datum
Definition postgres.h:70
#define RelationGetRelid(relation)
Definition rel.h:514
static int AttrDefaultCmp(const void *a, const void *b)
Definition relcache.c:4570
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition scankey.c:76
#define BTEqualStrategyNumber
Definition stratnum.h:31
AttrDefault * defval
Definition tupdesc.h:40
uint16 num_defval
Definition tupdesc.h:43
TupleConstr * constr
Definition tupdesc.h:141
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40

References AccessShareLock, AttrDefaultCmp(), BTEqualStrategyNumber, CacheMemoryContext, TupleDescData::constr, TupleConstr::defval, elog, fastgetattr(), fb(), GETSTRUCT(), HeapTupleIsValid, MemoryContextAllocZero(), MemoryContextStrdup(), TupleConstr::num_defval, ObjectIdGetDatum(), pfree(), qsort, RelationData::rd_att, RelationGetRelationName, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TextDatumGetCString, val, and WARNING.

Referenced by RelationBuildTupleDesc().

◆ BuildHardcodedDescriptor()

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

Definition at line 4425 of file relcache.c.

4426{
4427 TupleDesc result;
4429 int i;
4430
4432
4433 result = CreateTemplateTupleDesc(natts);
4434 result->tdtypeid = RECORDOID; /* not right, but we don't care */
4435 result->tdtypmod = -1;
4436
4437 for (i = 0; i < natts; i++)
4438 {
4440
4442 }
4443
4444 /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
4445 TupleDescCompactAttr(result, 0)->attcacheoff = 0;
4446
4447 /* Note: we don't bother to set up a TupleConstr entry */
4448
4450
4451 return result;
4452}
#define ATTRIBUTE_FIXED_PART_SIZE
int32 attcacheoff
Definition tupdesc.h:70
int32 tdtypmod
Definition tupdesc.h:139
void populate_compact_attribute(TupleDesc tupdesc, int attnum)
Definition tupdesc.c:117
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:160
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:175

References CompactAttribute::attcacheoff, ATTRIBUTE_FIXED_PART_SIZE, CacheMemoryContext, CreateTemplateTupleDesc(), fb(), i, MemoryContextSwitchTo(), populate_compact_attribute(), TupleDescData::tdtypeid, TupleDescData::tdtypmod, TupleDescAttr(), and TupleDescCompactAttr().

Referenced by GetPgClassDescriptor(), and GetPgIndexDescriptor().

◆ CheckConstraintCmp()

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

Definition at line 4703 of file relcache.c.

4704{
4705 const ConstrCheck *ca = (const ConstrCheck *) a;
4706 const ConstrCheck *cb = (const ConstrCheck *) b;
4707
4708 return strcmp(ca->ccname, cb->ccname);
4709}
char * ccname
Definition tupdesc.h:30

References a, b, ConstrCheck::ccname, and fb().

Referenced by CheckNNConstraintFetch().

◆ CheckNNConstraintFetch()

static void CheckNNConstraintFetch ( Relation  relation)
static

Definition at line 4586 of file relcache.c.

4587{
4588 ConstrCheck *check;
4589 int ncheck = relation->rd_rel->relchecks;
4592 ScanKeyData skey[1];
4593 HeapTuple htup;
4594 int found = 0;
4595
4596 /* Allocate array with room for as many entries as expected, if needed */
4597 if (ncheck > 0)
4598 check = (ConstrCheck *)
4600 ncheck * sizeof(ConstrCheck));
4601 else
4602 check = NULL;
4603
4604 /* Search pg_constraint for relevant entries */
4605 ScanKeyInit(&skey[0],
4609
4612 NULL, 1, skey);
4613
4615 {
4617 Datum val;
4618 bool isnull;
4619
4620 /*
4621 * If this is a not-null constraint, then only look at it if it's
4622 * invalid, and if so, mark the TupleDesc entry as known invalid.
4623 * Otherwise move on. We'll mark any remaining columns that are still
4624 * in UNKNOWN state as known valid later. This allows us not to have
4625 * to extract the attnum from this constraint tuple in the vast
4626 * majority of cases.
4627 */
4628 if (conform->contype == CONSTRAINT_NOTNULL)
4629 {
4630 if (!conform->convalidated)
4631 {
4633
4637 relation->rd_att->compact_attrs[attnum - 1].attnullability =
4639 }
4640
4641 continue;
4642 }
4643
4644 /* For what follows, consider check constraints only */
4645 if (conform->contype != CONSTRAINT_CHECK)
4646 continue;
4647
4648 /* protect limited size of array */
4649 if (found >= ncheck)
4650 {
4651 elog(WARNING, "unexpected pg_constraint record found for relation \"%s\"",
4652 RelationGetRelationName(relation));
4653 break;
4654 }
4655
4656 /* Grab and test conbin is actually set */
4657 val = fastgetattr(htup,
4659 conrel->rd_att, &isnull);
4660 if (isnull)
4661 elog(WARNING, "null conbin for relation \"%s\"",
4662 RelationGetRelationName(relation));
4663 else
4664 {
4665 /* detoast and convert to cstring in caller's context */
4666 char *s = TextDatumGetCString(val);
4667
4668 check[found].ccenforced = conform->conenforced;
4669 check[found].ccvalid = conform->convalidated;
4670 check[found].ccnoinherit = conform->connoinherit;
4672 NameStr(conform->conname));
4673 check[found].ccbin = MemoryContextStrdup(CacheMemoryContext, s);
4674
4675 pfree(s);
4676 found++;
4677 }
4678 }
4679
4682
4683 if (found != ncheck)
4684 elog(WARNING, "%d pg_constraint record(s) missing for relation \"%s\"",
4685 ncheck - found, RelationGetRelationName(relation));
4686
4687 /*
4688 * Sort the records by name. This ensures that CHECKs are applied in a
4689 * deterministic order, and it also makes equalTupleDescs() faster.
4690 */
4691 if (found > 1)
4692 qsort(check, found, sizeof(ConstrCheck), CheckConstraintCmp);
4693
4694 /* Install array only after it's fully valid */
4695 relation->rd_att->constr->check = check;
4696 relation->rd_att->constr->num_check = found;
4697}
int16 AttrNumber
Definition attnum.h:21
#define NameStr(name)
Definition c.h:775
int16 attnum
AttrNumber extractNotNullColumn(HeapTuple constrTup)
FormData_pg_constraint * Form_pg_constraint
static int CheckConstraintCmp(const void *a, const void *b)
Definition relcache.c:4703
char attnullability
Definition tupdesc.h:79
bool ccenforced
Definition tupdesc.h:32
bool ccnoinherit
Definition tupdesc.h:34
bool ccvalid
Definition tupdesc.h:33
char * ccbin
Definition tupdesc.h:31
ConstrCheck * check
Definition tupdesc.h:41
uint16 num_check
Definition tupdesc.h:44
CompactAttribute compact_attrs[FLEXIBLE_ARRAY_MEMBER]
Definition tupdesc.h:143
#define ATTNULLABLE_UNKNOWN
Definition tupdesc.h:85
#define ATTNULLABLE_INVALID
Definition tupdesc.h:87

References AccessShareLock, Assert, CompactAttribute::attnullability, ATTNULLABLE_INVALID, ATTNULLABLE_UNKNOWN, attnum, BTEqualStrategyNumber, CacheMemoryContext, ConstrCheck::ccbin, ConstrCheck::ccenforced, ConstrCheck::ccname, ConstrCheck::ccnoinherit, ConstrCheck::ccvalid, TupleConstr::check, CheckConstraintCmp(), TupleDescData::compact_attrs, TupleDescData::constr, elog, extractNotNullColumn(), fastgetattr(), fb(), GETSTRUCT(), HeapTupleIsValid, MemoryContextAllocZero(), MemoryContextStrdup(), NameStr, TupleConstr::num_check, ObjectIdGetDatum(), pfree(), qsort, RelationData::rd_att, RelationData::rd_rel, RelationGetRelationName, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TextDatumGetCString, val, and WARNING.

Referenced by RelationBuildTupleDesc().

◆ CopyIndexAttOptions()

static bytea ** CopyIndexAttOptions ( bytea **  srcopts,
int  natts 
)
static

Definition at line 5963 of file relcache.c.

5964{
5965 bytea **opts = palloc_array(bytea *, natts);
5966
5967 for (int i = 0; i < natts; i++)
5968 {
5969 bytea *opt = srcopts[i];
5970
5971 opts[i] = !opt ? NULL : (bytea *)
5972 DatumGetPointer(datumCopy(PointerGetDatum(opt), false, -1));
5973 }
5974
5975 return opts;
5976}
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition datum.c:132
#define palloc_array(type, count)
Definition fe_memutils.h:76
static AmcheckOptions opts
Definition pg_amcheck.c:112
static Datum PointerGetDatum(const void *X)
Definition postgres.h:352
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:342
Definition c.h:716

References datumCopy(), DatumGetPointer(), fb(), i, opts, palloc_array, and PointerGetDatum().

Referenced by RelationGetIndexAttOptions().

◆ equalPolicy()

static bool equalPolicy ( RowSecurityPolicy policy1,
RowSecurityPolicy policy2 
)
static

Definition at line 972 of file relcache.c.

973{
974 int i;
975 Oid *r1,
976 *r2;
977
978 if (policy1 != NULL)
979 {
980 if (policy2 == NULL)
981 return false;
982
983 if (policy1->polcmd != policy2->polcmd)
984 return false;
985 if (policy1->hassublinks != policy2->hassublinks)
986 return false;
987 if (strcmp(policy1->policy_name, policy2->policy_name) != 0)
988 return false;
989 if (ARR_DIMS(policy1->roles)[0] != ARR_DIMS(policy2->roles)[0])
990 return false;
991
992 r1 = (Oid *) ARR_DATA_PTR(policy1->roles);
993 r2 = (Oid *) ARR_DATA_PTR(policy2->roles);
994
995 for (i = 0; i < ARR_DIMS(policy1->roles)[0]; i++)
996 {
997 if (r1[i] != r2[i])
998 return false;
999 }
1000
1001 if (!equal(policy1->qual, policy2->qual))
1002 return false;
1003 if (!equal(policy1->with_check_qual, policy2->with_check_qual))
1004 return false;
1005 }
1006 else if (policy2 != NULL)
1007 return false;
1008
1009 return true;
1010}
#define ARR_DATA_PTR(a)
Definition array.h:322
#define ARR_DIMS(a)
Definition array.h:294
bool equal(const void *a, const void *b)
Definition equalfuncs.c:223
unsigned int Oid

References ARR_DATA_PTR, ARR_DIMS, equal(), fb(), and i.

Referenced by equalRSDesc().

◆ equalRSDesc()

static bool equalRSDesc ( RowSecurityDesc rsdesc1,
RowSecurityDesc rsdesc2 
)
static

Definition at line 1018 of file relcache.c.

1019{
1020 ListCell *lc,
1021 *rc;
1022
1023 if (rsdesc1 == NULL && rsdesc2 == NULL)
1024 return true;
1025
1026 if ((rsdesc1 != NULL && rsdesc2 == NULL) ||
1027 (rsdesc1 == NULL && rsdesc2 != NULL))
1028 return false;
1029
1030 if (list_length(rsdesc1->policies) != list_length(rsdesc2->policies))
1031 return false;
1032
1033 /* RelationBuildRowSecurity should build policies in order */
1034 forboth(lc, rsdesc1->policies, rc, rsdesc2->policies)
1035 {
1038
1039 if (!equalPolicy(l, r))
1040 return false;
1041 }
1042
1043 return true;
1044}
#define lfirst(lc)
Definition pg_list.h:172
static int list_length(const List *l)
Definition pg_list.h:152
#define forboth(cell1, list1, cell2, list2)
Definition pg_list.h:518
static bool equalPolicy(RowSecurityPolicy *policy1, RowSecurityPolicy *policy2)
Definition relcache.c:972

References equalPolicy(), fb(), forboth, lfirst, and list_length().

Referenced by RelationRebuildRelation().

◆ equalRuleLocks()

static bool equalRuleLocks ( RuleLock rlock1,
RuleLock rlock2 
)
static

Definition at line 927 of file relcache.c.

928{
929 int i;
930
931 /*
932 * As of 7.3 we assume the rule ordering is repeatable, because
933 * RelationBuildRuleLock should read 'em in a consistent order. So just
934 * compare corresponding slots.
935 */
936 if (rlock1 != NULL)
937 {
938 if (rlock2 == NULL)
939 return false;
940 if (rlock1->numLocks != rlock2->numLocks)
941 return false;
942 for (i = 0; i < rlock1->numLocks; i++)
943 {
944 RewriteRule *rule1 = rlock1->rules[i];
945 RewriteRule *rule2 = rlock2->rules[i];
946
947 if (rule1->ruleId != rule2->ruleId)
948 return false;
949 if (rule1->event != rule2->event)
950 return false;
951 if (rule1->enabled != rule2->enabled)
952 return false;
953 if (rule1->isInstead != rule2->isInstead)
954 return false;
955 if (!equal(rule1->qual, rule2->qual))
956 return false;
957 if (!equal(rule1->actions, rule2->actions))
958 return false;
959 }
960 }
961 else if (rlock2 != NULL)
962 return false;
963 return true;
964}

References equal(), fb(), and i.

Referenced by RelationRebuildRelation().

◆ errtable()

int errtable ( Relation  rel)

Definition at line 6044 of file relcache.c.

6045{
6049
6050 return 0; /* return value does not matter */
6051}
int err_generic_string(int field, const char *str)
Definition elog.c:1546
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3516
#define PG_DIAG_SCHEMA_NAME
#define PG_DIAG_TABLE_NAME
#define RelationGetNamespace(relation)
Definition rel.h:555

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

Referenced by ATPrepChangePersistence(), ATRewriteTable(), BuildRelationExtStatistics(), check_default_partition_contents(), errtablecolname(), errtableconstraint(), ExecFindPartition(), ExecPartitionCheckEmitError(), and SplitPartitionMoveRows().

◆ errtablecol()

int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 6061 of file relcache.c.

6062{
6063 TupleDesc reldesc = RelationGetDescr(rel);
6064 const char *colname;
6065
6066 /* Use reldesc if it's a user attribute, else consult the catalogs */
6067 if (attnum > 0 && attnum <= reldesc->natts)
6068 colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
6069 else
6070 colname = get_attname(RelationGetRelid(rel), attnum, false);
6071
6072 return errtablecolname(rel, colname);
6073}
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:903
NameData attname
#define RelationGetDescr(relation)
Definition rel.h:540
int errtablecolname(Relation rel, const char *colname)
Definition relcache.c:6085

References attname, attnum, errtablecolname(), fb(), get_attname(), NameStr, RelationGetDescr, RelationGetRelid, and TupleDescAttr().

Referenced by ATRewriteTable(), ReportNotNullViolationError(), validateDomainCheckConstraint(), and validateDomainNotNullConstraint().

◆ errtablecolname()

int errtablecolname ( Relation  rel,
const char colname 
)

Definition at line 6085 of file relcache.c.

6086{
6087 errtable(rel);
6089
6090 return 0; /* return value does not matter */
6091}
#define PG_DIAG_COLUMN_NAME
int errtable(Relation rel)
Definition relcache.c:6044

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

Referenced by errtablecol().

◆ errtableconstraint()

◆ formrdesc()

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

Definition at line 1889 of file relcache.c.

1892{
1893 Relation relation;
1894 int i;
1895 bool has_not_null;
1896
1897 /*
1898 * allocate new relation desc, clear all fields of reldesc
1899 */
1900 relation = palloc0_object(RelationData);
1901
1902 /* make sure relation is marked as having no open file yet */
1903 relation->rd_smgr = NULL;
1904
1905 /*
1906 * initialize reference count: 1 because it is nailed in cache
1907 */
1908 relation->rd_refcnt = 1;
1909
1910 /*
1911 * all entries built with this routine are nailed-in-cache; none are for
1912 * new or temp relations.
1913 */
1914 relation->rd_isnailed = true;
1919 relation->rd_backend = INVALID_PROC_NUMBER;
1920 relation->rd_islocaltemp = false;
1921
1922 /*
1923 * initialize relation tuple form
1924 *
1925 * The data we insert here is pretty incomplete/bogus, but it'll serve to
1926 * get us launched. RelationCacheInitializePhase3() will read the real
1927 * data from pg_class and replace what we've done here. Note in
1928 * particular that relowner is left as zero; this cues
1929 * RelationCacheInitializePhase3 that the real data isn't there yet.
1930 */
1932
1933 namestrcpy(&relation->rd_rel->relname, relationName);
1934 relation->rd_rel->relnamespace = PG_CATALOG_NAMESPACE;
1935 relation->rd_rel->reltype = relationReltype;
1936
1937 /*
1938 * It's important to distinguish between shared and non-shared relations,
1939 * even at bootstrap time, to make sure we know where they are stored.
1940 */
1941 relation->rd_rel->relisshared = isshared;
1942 if (isshared)
1943 relation->rd_rel->reltablespace = GLOBALTABLESPACE_OID;
1944
1945 /* formrdesc is used only for permanent relations */
1946 relation->rd_rel->relpersistence = RELPERSISTENCE_PERMANENT;
1947
1948 /* ... and they're always populated, too */
1949 relation->rd_rel->relispopulated = true;
1950
1951 relation->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
1952 relation->rd_rel->relpages = 0;
1953 relation->rd_rel->reltuples = -1;
1954 relation->rd_rel->relallvisible = 0;
1955 relation->rd_rel->relallfrozen = 0;
1956 relation->rd_rel->relkind = RELKIND_RELATION;
1957 relation->rd_rel->relnatts = (int16) natts;
1958
1959 /*
1960 * initialize attribute tuple form
1961 *
1962 * Unlike the case with the relation tuple, this data had better be right
1963 * because it will never be replaced. The data comes from
1964 * src/include/catalog/ headers via genbki.pl.
1965 */
1966 relation->rd_att = CreateTemplateTupleDesc(natts);
1967 relation->rd_att->tdrefcount = 1; /* mark as refcounted */
1968
1969 relation->rd_att->tdtypeid = relationReltype;
1970 relation->rd_att->tdtypmod = -1; /* just to be sure */
1971
1972 /*
1973 * initialize tuple desc info
1974 */
1975 has_not_null = false;
1976 for (i = 0; i < natts; i++)
1977 {
1978 memcpy(TupleDescAttr(relation->rd_att, i),
1979 &attrs[i],
1981 has_not_null |= attrs[i].attnotnull;
1982
1984 }
1985
1986 /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
1987 TupleDescCompactAttr(relation->rd_att, 0)->attcacheoff = 0;
1988
1989 /* mark not-null status */
1990 if (has_not_null)
1991 {
1993
1994 constr->has_not_null = true;
1995 relation->rd_att->constr = constr;
1996 }
1997
1998 /*
1999 * initialize relation id from info in att array (my, this is ugly)
2000 */
2001 RelationGetRelid(relation) = TupleDescAttr(relation->rd_att, 0)->attrelid;
2002
2003 /*
2004 * All relations made with formrdesc are mapped. This is necessarily so
2005 * because there is no other way to know what filenumber they currently
2006 * have. In bootstrap mode, add them to the initial relation mapper data,
2007 * specifying that the initial filenumber is the same as the OID.
2008 */
2009 relation->rd_rel->relfilenode = InvalidRelFileNumber;
2012 RelationGetRelid(relation),
2013 isshared, true);
2014
2015 /*
2016 * initialize the relation lock manager information
2017 */
2018 RelationInitLockInfo(relation); /* see lmgr.c */
2019
2020 /*
2021 * initialize physical addressing information for the relation
2022 */
2023 RelationInitPhysicalAddr(relation);
2024
2025 /*
2026 * initialize the table am handler
2027 */
2028 relation->rd_rel->relam = HEAP_TABLE_AM_OID;
2029 relation->rd_tableam = GetHeapamTableAmRoutine();
2030
2031 /*
2032 * initialize the rel-has-index flag, using hardwired knowledge
2033 */
2035 {
2036 /* In bootstrap mode, we have no indexes */
2037 relation->rd_rel->relhasindex = false;
2038 }
2039 else
2040 {
2041 /* Otherwise, all the rels formrdesc is used for have indexes */
2042 relation->rd_rel->relhasindex = true;
2043 }
2044
2045 /*
2046 * add new reldesc to relcache
2047 */
2048 RelationCacheInsert(relation, false);
2049
2050 /* It's fully valid */
2051 relation->rd_isvalid = true;
2052}
int16_t int16
Definition c.h:551
const TableAmRoutine * GetHeapamTableAmRoutine(void)
void RelationInitLockInfo(Relation relation)
Definition lmgr.c:70
void * palloc0(Size size)
Definition mcxt.c:1417
void namestrcpy(Name name, const char *str)
Definition name.c:233
#define INVALID_PROC_NUMBER
Definition procnumber.h:26
#define RelationCacheInsert(RELATION, replace_allowed)
Definition relcache.c:209
static void RelationInitPhysicalAddr(Relation relation)
Definition relcache.c:1339
void RelationMapUpdateMap(Oid relationId, RelFileNumber fileNumber, bool shared, bool immediate)
Definition relmapper.c:325
#define InvalidRelFileNumber
Definition relpath.h:26
ProcNumber rd_backend
Definition rel.h:60
const struct TableAmRoutine * rd_tableam
Definition rel.h:189
bool rd_isvalid
Definition rel.h:63
bool rd_islocaltemp
Definition rel.h:61
bool has_not_null
Definition tupdesc.h:45

References CompactAttribute::attcacheoff, ATTRIBUTE_FIXED_PART_SIZE, CLASS_TUPLE_SIZE, TupleDescData::constr, CreateTemplateTupleDesc(), fb(), GetHeapamTableAmRoutine(), TupleConstr::has_not_null, i, INVALID_PROC_NUMBER, InvalidRelFileNumber, InvalidSubTransactionId, IsBootstrapProcessingMode, namestrcpy(), palloc0(), palloc0_object, populate_compact_attribute(), RelationData::rd_att, RelationData::rd_backend, RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_firstRelfilelocatorSubid, RelationData::rd_islocaltemp, RelationData::rd_isnailed, RelationData::rd_isvalid, RelationData::rd_newRelfilelocatorSubid, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_smgr, RelationData::rd_tableam, RelationCacheInsert, RelationGetRelid, RelationInitLockInfo(), RelationInitPhysicalAddr(), RelationMapUpdateMap(), TupleDescData::tdrefcount, TupleDescData::tdtypeid, TupleDescData::tdtypmod, TupleDescAttr(), and TupleDescCompactAttr().

Referenced by RelationCacheInitializePhase2(), and RelationCacheInitializePhase3().

◆ GetPgClassDescriptor()

static TupleDesc GetPgClassDescriptor ( void  )
static

Definition at line 4455 of file relcache.c.

4456{
4457 static TupleDesc pgclassdesc = NULL;
4458
4459 /* Already done? */
4460 if (pgclassdesc == NULL)
4463
4464 return pgclassdesc;
4465}
static TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs)
Definition relcache.c:4425
static const FormData_pg_attribute Desc_pg_class[Natts_pg_class]
Definition relcache.c:111

References BuildHardcodedDescriptor(), Desc_pg_class, and fb().

Referenced by RelationParseRelOptions().

◆ GetPgIndexDescriptor()

static TupleDesc GetPgIndexDescriptor ( void  )
static

Definition at line 4468 of file relcache.c.

4469{
4470 static TupleDesc pgindexdesc = NULL;
4471
4472 /* Already done? */
4473 if (pgindexdesc == NULL)
4476
4477 return pgindexdesc;
4478}
static const FormData_pg_attribute Desc_pg_index[Natts_pg_index]
Definition relcache.c:118

References BuildHardcodedDescriptor(), Desc_pg_index, and fb().

Referenced by RelationGetDummyIndexExpressions(), RelationGetIndexAttrBitmap(), RelationGetIndexExpressions(), RelationGetIndexPredicate(), and RelationInitIndexAccessInfo().

◆ IndexSupportInitialize()

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

Definition at line 1611 of file relcache.c.

1617{
1618 int attIndex;
1619
1621 {
1623
1624 if (!OidIsValid(indclass->values[attIndex]))
1625 elog(ERROR, "bogus pg_index tuple");
1626
1627 /* look up the info for this opclass, using a cache */
1630
1631 /* copy cached data into relcache entry */
1632 opFamily[attIndex] = opcentry->opcfamily;
1633 opcInType[attIndex] = opcentry->opcintype;
1634 if (maxSupportNumber > 0)
1636 opcentry->supportProcs,
1637 maxSupportNumber * sizeof(RegProcedure));
1638 }
1639}
regproc RegProcedure
Definition c.h:674
#define OidIsValid(objectId)
Definition c.h:798
#define ERROR
Definition elog.h:39
static OpClassCacheEnt * LookupOpclassInfo(Oid operatorClassOid, StrategyNumber numSupport)
Definition relcache.c:1662

References elog, ERROR, fb(), LookupOpclassInfo(), and OidIsValid.

Referenced by RelationInitIndexAccessInfo().

◆ InitIndexAmRoutine()

static void InitIndexAmRoutine ( Relation  relation)
static

Definition at line 1421 of file relcache.c.

1422{
1424
1425 /*
1426 * We formerly specified that the amhandler should return a palloc'd
1427 * struct. That's now deprecated in favor of returning a pointer to a
1428 * static struct, but to avoid completely breaking old external AMs, run
1429 * the amhandler in the relation's rd_indexcxt.
1430 */
1432 relation->rd_indam = GetIndexAmRoutine(relation->rd_amhandler);
1434}
const IndexAmRoutine * GetIndexAmRoutine(Oid amhandler)
Definition amapi.c:33
const struct IndexAmRoutine * rd_indam
Definition rel.h:206
Oid rd_amhandler
Definition rel.h:184
MemoryContext rd_indexcxt
Definition rel.h:204

References fb(), GetIndexAmRoutine(), MemoryContextSwitchTo(), RelationData::rd_amhandler, RelationData::rd_indam, and RelationData::rd_indexcxt.

Referenced by load_relcache_init_file(), and RelationInitIndexAccessInfo().

◆ InitTableAmRoutine()

static void InitTableAmRoutine ( Relation  relation)
static

Definition at line 1815 of file relcache.c.

1816{
1817 relation->rd_tableam = GetTableAmRoutine(relation->rd_amhandler);
1818}
const TableAmRoutine * GetTableAmRoutine(Oid amhandler)
Definition tableamapi.c:27

References GetTableAmRoutine(), RelationData::rd_amhandler, and RelationData::rd_tableam.

Referenced by RelationInitTableAccessMethod().

◆ load_critical_index()

static void load_critical_index ( Oid  indexoid,
Oid  heapoid 
)
static

Definition at line 4387 of file relcache.c.

4388{
4389 Relation ird;
4390
4391 /*
4392 * We must lock the underlying catalog before locking the index to avoid
4393 * deadlock, since RelationBuildDesc might well need to read the catalog,
4394 * and if anyone else is exclusive-locking this catalog and index they'll
4395 * be doing it in that order.
4396 */
4399 ird = RelationBuildDesc(indexoid, true);
4400 if (ird == NULL)
4401 ereport(PANIC,
4403 errmsg_internal("could not open critical system index %u", indexoid));
4404 ird->rd_isnailed = true;
4405 ird->rd_refcnt = 1;
4408
4410}
int errmsg_internal(const char *fmt,...)
Definition elog.c:1170
int errcode(int sqlerrcode)
Definition elog.c:863
#define PANIC
Definition elog.h:42
#define ereport(elevel,...)
Definition elog.h:150
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition lmgr.c:229
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition lmgr.c:107
#define ERRCODE_DATA_CORRUPTED
static Relation RelationBuildDesc(Oid targetRelId, bool insertIt)
Definition relcache.c:1059
bytea ** RelationGetIndexAttOptions(Relation relation, bool copy)
Definition relcache.c:5983

References AccessShareLock, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errmsg_internal(), fb(), LockRelationOid(), PANIC, RelationBuildDesc(), RelationGetIndexAttOptions(), and UnlockRelationOid().

Referenced by RelationCacheInitializePhase3().

◆ load_relcache_init_file()

static bool load_relcache_init_file ( bool  shared)
static

Definition at line 6162 of file relcache.c.

6163{
6164 FILE *fp;
6165 char initfilename[MAXPGPATH];
6166 Relation *rels;
6167 int relno,
6168 num_rels,
6169 max_rels,
6172 magic;
6173 int i;
6174
6175 if (shared)
6176 snprintf(initfilename, sizeof(initfilename), "global/%s",
6178 else
6179 snprintf(initfilename, sizeof(initfilename), "%s/%s",
6181
6183 if (fp == NULL)
6184 return false;
6185
6186 /*
6187 * Read the index relcache entries from the file. Note we will not enter
6188 * any of them into the cache if the read fails partway through; this
6189 * helps to guard against broken init files.
6190 */
6191 max_rels = 100;
6192 rels = (Relation *) palloc(max_rels * sizeof(Relation));
6193 num_rels = 0;
6195
6196 /* check for correct magic number (compatible version) */
6197 if (fread(&magic, 1, sizeof(magic), fp) != sizeof(magic))
6198 goto read_failed;
6199 if (magic != RELCACHE_INIT_FILEMAGIC)
6200 goto read_failed;
6201
6202 for (relno = 0;; relno++)
6203 {
6204 Size len;
6205 size_t nread;
6206 Relation rel;
6208 bool has_not_null;
6209
6210 /* first read the relation descriptor length */
6211 nread = fread(&len, 1, sizeof(len), fp);
6212 if (nread != sizeof(len))
6213 {
6214 if (nread == 0)
6215 break; /* end of file */
6216 goto read_failed;
6217 }
6218
6219 /* safety check for incompatible relcache layout */
6220 if (len != sizeof(RelationData))
6221 goto read_failed;
6222
6223 /* allocate another relcache header */
6224 if (num_rels >= max_rels)
6225 {
6226 max_rels *= 2;
6227 rels = (Relation *) repalloc(rels, max_rels * sizeof(Relation));
6228 }
6229
6230 rel = rels[num_rels++] = (Relation) palloc(len);
6231
6232 /* then, read the Relation structure */
6233 if (fread(rel, 1, len, fp) != len)
6234 goto read_failed;
6235
6236 /* next read the relation tuple form */
6237 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6238 goto read_failed;
6239
6241 if (fread(relform, 1, len, fp) != len)
6242 goto read_failed;
6243
6244 rel->rd_rel = relform;
6245
6246 /* initialize attribute tuple forms */
6247 rel->rd_att = CreateTemplateTupleDesc(relform->relnatts);
6248 rel->rd_att->tdrefcount = 1; /* mark as refcounted */
6249
6250 rel->rd_att->tdtypeid = relform->reltype ? relform->reltype : RECORDOID;
6251 rel->rd_att->tdtypmod = -1; /* just to be sure */
6252
6253 /* next read all the attribute tuple form data entries */
6254 has_not_null = false;
6255 for (i = 0; i < relform->relnatts; i++)
6256 {
6258
6259 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6260 goto read_failed;
6262 goto read_failed;
6263 if (fread(attr, 1, len, fp) != len)
6264 goto read_failed;
6265
6266 has_not_null |= attr->attnotnull;
6267
6269 }
6270
6271 /* next read the access method specific field */
6272 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6273 goto read_failed;
6274 if (len > 0)
6275 {
6276 rel->rd_options = palloc(len);
6277 if (fread(rel->rd_options, 1, len, fp) != len)
6278 goto read_failed;
6279 if (len != VARSIZE(rel->rd_options))
6280 goto read_failed; /* sanity check */
6281 }
6282 else
6283 {
6284 rel->rd_options = NULL;
6285 }
6286
6287 /* mark not-null status */
6288 if (has_not_null)
6289 {
6291
6292 constr->has_not_null = true;
6293 rel->rd_att->constr = constr;
6294 }
6295
6296 /*
6297 * If it's an index, there's more to do. Note we explicitly ignore
6298 * partitioned indexes here.
6299 */
6300 if (rel->rd_rel->relkind == RELKIND_INDEX)
6301 {
6303 Oid *opfamily;
6304 Oid *opcintype;
6306 int nsupport;
6309
6310 /* Count nailed indexes to ensure we have 'em all */
6311 if (rel->rd_isnailed)
6313
6314 /* read the pg_index tuple */
6315 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6316 goto read_failed;
6317
6319 if (fread(rel->rd_indextuple, 1, len, fp) != len)
6320 goto read_failed;
6321
6322 /* Fix up internal pointers in the tuple -- see heap_copytuple */
6325
6326 /*
6327 * prepare index info context --- parameters should match
6328 * RelationInitIndexAccessInfo
6329 */
6331 "index info",
6333 rel->rd_indexcxt = indexcxt;
6336
6337 /*
6338 * Now we can fetch the index AM's API struct. (We can't store
6339 * that in the init file, since it contains function pointers that
6340 * might vary across server executions. Fortunately, it should be
6341 * safe to call the amhandler even while bootstrapping indexes.)
6342 */
6343 InitIndexAmRoutine(rel);
6344
6345 /* read the vector of opfamily OIDs */
6346 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6347 goto read_failed;
6348
6349 opfamily = (Oid *) MemoryContextAlloc(indexcxt, len);
6350 if (fread(opfamily, 1, len, fp) != len)
6351 goto read_failed;
6352
6353 rel->rd_opfamily = opfamily;
6354
6355 /* read the vector of opcintype OIDs */
6356 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6357 goto read_failed;
6358
6359 opcintype = (Oid *) MemoryContextAlloc(indexcxt, len);
6360 if (fread(opcintype, 1, len, fp) != len)
6361 goto read_failed;
6362
6363 rel->rd_opcintype = opcintype;
6364
6365 /* read the vector of support procedure OIDs */
6366 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6367 goto read_failed;
6369 if (fread(support, 1, len, fp) != len)
6370 goto read_failed;
6371
6372 rel->rd_support = support;
6373
6374 /* read the vector of collation OIDs */
6375 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6376 goto read_failed;
6377
6379 if (fread(indcollation, 1, len, fp) != len)
6380 goto read_failed;
6381
6383
6384 /* read the vector of indoption values */
6385 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6386 goto read_failed;
6387
6389 if (fread(indoption, 1, len, fp) != len)
6390 goto read_failed;
6391
6392 rel->rd_indoption = indoption;
6393
6394 /* read the vector of opcoptions values */
6395 rel->rd_opcoptions = (bytea **)
6396 MemoryContextAllocZero(indexcxt, sizeof(*rel->rd_opcoptions) * relform->relnatts);
6397
6398 for (i = 0; i < relform->relnatts; i++)
6399 {
6400 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6401 goto read_failed;
6402
6403 if (len > 0)
6404 {
6406 if (fread(rel->rd_opcoptions[i], 1, len, fp) != len)
6407 goto read_failed;
6408 }
6409 }
6410
6411 /* set up zeroed fmgr-info vector */
6412 nsupport = relform->relnatts * rel->rd_indam->amsupport;
6413 rel->rd_supportinfo = (FmgrInfo *)
6415 }
6416 else
6417 {
6418 /* Count nailed rels to ensure we have 'em all */
6419 if (rel->rd_isnailed)
6420 nailed_rels++;
6421
6422 /* Load table AM data */
6423 if (RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind) || rel->rd_rel->relkind == RELKIND_SEQUENCE)
6425
6426 Assert(rel->rd_index == NULL);
6427 Assert(rel->rd_indextuple == NULL);
6428 Assert(rel->rd_indexcxt == NULL);
6429 Assert(rel->rd_indam == NULL);
6430 Assert(rel->rd_opfamily == NULL);
6431 Assert(rel->rd_opcintype == NULL);
6432 Assert(rel->rd_support == NULL);
6433 Assert(rel->rd_supportinfo == NULL);
6434 Assert(rel->rd_indoption == NULL);
6435 Assert(rel->rd_indcollation == NULL);
6436 Assert(rel->rd_opcoptions == NULL);
6437 }
6438
6439 /*
6440 * Rules and triggers are not saved (mainly because the internal
6441 * format is complex and subject to change). They must be rebuilt if
6442 * needed by RelationCacheInitializePhase3. This is not expected to
6443 * be a big performance hit since few system catalogs have such. Ditto
6444 * for RLS policy data, partition info, index expressions, predicates,
6445 * exclusion info, and FDW info.
6446 */
6447 rel->rd_rules = NULL;
6448 rel->rd_rulescxt = NULL;
6449 rel->trigdesc = NULL;
6450 rel->rd_rsdesc = NULL;
6451 rel->rd_partkey = NULL;
6452 rel->rd_partkeycxt = NULL;
6453 rel->rd_partdesc = NULL;
6456 rel->rd_pdcxt = NULL;
6457 rel->rd_pddcxt = NULL;
6458 rel->rd_partcheck = NIL;
6459 rel->rd_partcheckvalid = false;
6460 rel->rd_partcheckcxt = NULL;
6461 rel->rd_indexprs = NIL;
6462 rel->rd_indpred = NIL;
6463 rel->rd_exclops = NULL;
6464 rel->rd_exclprocs = NULL;
6465 rel->rd_exclstrats = NULL;
6466 rel->rd_fdwroutine = NULL;
6467
6468 /*
6469 * Reset transient-state fields in the relcache entry
6470 */
6471 rel->rd_smgr = NULL;
6472 if (rel->rd_isnailed)
6473 rel->rd_refcnt = 1;
6474 else
6475 rel->rd_refcnt = 0;
6476 rel->rd_indexvalid = false;
6477 rel->rd_indexlist = NIL;
6478 rel->rd_pkindex = InvalidOid;
6480 rel->rd_attrsvalid = false;
6481 rel->rd_keyattr = NULL;
6482 rel->rd_pkattr = NULL;
6483 rel->rd_idattr = NULL;
6484 rel->rd_pubdesc = NULL;
6485 rel->rd_statvalid = false;
6486 rel->rd_statlist = NIL;
6487 rel->rd_fkeyvalid = false;
6488 rel->rd_fkeylist = NIL;
6493 rel->rd_amcache = NULL;
6494 rel->pgstat_info = NULL;
6495
6496 /*
6497 * Recompute lock and physical addressing info. This is needed in
6498 * case the pg_internal.init file was copied from some other database
6499 * by CREATE DATABASE.
6500 */
6503 }
6504
6505 /*
6506 * We reached the end of the init file without apparent problem. Did we
6507 * get the right number of nailed items? This is a useful crosscheck in
6508 * case the set of critical rels or indexes changes. However, that should
6509 * not happen in a normally-running system, so let's bleat if it does.
6510 *
6511 * For the shared init file, we're called before client authentication is
6512 * done, which means that elog(WARNING) will go only to the postmaster
6513 * log, where it's easily missed. To ensure that developers notice bad
6514 * values of NUM_CRITICAL_SHARED_RELS/NUM_CRITICAL_SHARED_INDEXES, we put
6515 * an Assert(false) there.
6516 */
6517 if (shared)
6518 {
6521 {
6522 elog(WARNING, "found %d nailed shared rels and %d nailed shared indexes in init file, but expected %d and %d respectively",
6525 /* Make sure we get developers' attention about this */
6526 Assert(false);
6527 /* In production builds, recover by bootstrapping the relcache */
6528 goto read_failed;
6529 }
6530 }
6531 else
6532 {
6535 {
6536 elog(WARNING, "found %d nailed rels and %d nailed indexes in init file, but expected %d and %d respectively",
6539 /* We don't need an Assert() in this case */
6540 goto read_failed;
6541 }
6542 }
6543
6544 /*
6545 * OK, all appears well.
6546 *
6547 * Now insert all the new relcache entries into the cache.
6548 */
6549 for (relno = 0; relno < num_rels; relno++)
6550 {
6551 RelationCacheInsert(rels[relno], false);
6552 }
6553
6554 pfree(rels);
6555 FreeFile(fp);
6556
6557 if (shared)
6559 else
6561 return true;
6562
6563 /*
6564 * init file is broken, so do it the hard way. We don't bother trying to
6565 * free the clutter we just allocated; it's not in the relcache so it
6566 * won't hurt.
6567 */
6569 pfree(rels);
6570 FreeFile(fp);
6571
6572 return false;
6573}
#define PG_BINARY_R
Definition c.h:1283
size_t Size
Definition c.h:629
int FreeFile(FILE *file)
Definition fd.c:2823
FILE * AllocateFile(const char *name, const char *mode)
Definition fd.c:2624
struct RelationData * Relation
Definition genam.h:31
char * DatabasePath
Definition globals.c:104
#define HEAPTUPLESIZE
Definition htup.h:73
HeapTupleData * HeapTuple
Definition htup.h:71
HeapTupleHeaderData * HeapTupleHeader
Definition htup.h:23
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition mcxt.c:1232
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1632
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_SMALL_SIZES
Definition memutils.h:170
#define MemoryContextCopyAndSetIdentifier(cxt, id)
Definition memutils.h:101
FormData_pg_attribute * Form_pg_attribute
#define MAXPGPATH
const void size_t len
FormData_pg_index * Form_pg_index
Definition pg_index.h:70
#define NIL
Definition pg_list.h:68
#define snprintf
Definition port.h:260
#define InvalidOid
#define NUM_CRITICAL_LOCAL_RELS
#define NUM_CRITICAL_SHARED_INDEXES
bool criticalRelcachesBuilt
Definition relcache.c:140
bool criticalSharedRelcachesBuilt
Definition relcache.c:146
static void InitIndexAmRoutine(Relation relation)
Definition relcache.c:1421
#define NUM_CRITICAL_SHARED_RELS
void RelationInitTableAccessMethod(Relation relation)
Definition relcache.c:1824
#define NUM_CRITICAL_LOCAL_INDEXES
#define RELCACHE_INIT_FILEMAGIC
Definition relcache.c:93
#define RELCACHE_INIT_FILENAME
Definition relcache.h:25
HeapTupleHeader t_data
Definition htup.h:68
uint16 amsupport
Definition amapi.h:242
List * rd_partcheck
Definition rel.h:147
Bitmapset * rd_keyattr
Definition rel.h:162
bool rd_partcheckvalid
Definition rel.h:148
MemoryContext rd_pdcxt
Definition rel.h:131
MemoryContext rd_partkeycxt
Definition rel.h:127
TransactionId rd_partdesc_nodetached_xmin
Definition rel.h:144
bool rd_indexvalid
Definition rel.h:64
List * rd_indpred
Definition rel.h:213
List * rd_fkeylist
Definition rel.h:122
Oid * rd_exclprocs
Definition rel.h:215
uint16 * rd_exclstrats
Definition rel.h:216
List * rd_indexlist
Definition rel.h:152
struct RowSecurityDesc * rd_rsdesc
Definition rel.h:119
PartitionDesc rd_partdesc
Definition rel.h:130
Oid rd_replidindex
Definition rel.h:155
RegProcedure * rd_support
Definition rel.h:209
PartitionDesc rd_partdesc_nodetached
Definition rel.h:134
bytea ** rd_opcoptions
Definition rel.h:218
PublicationDesc * rd_pubdesc
Definition rel.h:168
struct FdwRoutine * rd_fdwroutine
Definition rel.h:240
TriggerDesc * trigdesc
Definition rel.h:117
Bitmapset * rd_idattr
Definition rel.h:164
List * rd_indexprs
Definition rel.h:212
bool rd_attrsvalid
Definition rel.h:161
Oid * rd_exclops
Definition rel.h:214
Oid * rd_opcintype
Definition rel.h:208
struct HeapTupleData * rd_indextuple
Definition rel.h:194
MemoryContext rd_partcheckcxt
Definition rel.h:149
int16 * rd_indoption
Definition rel.h:211
Form_pg_index rd_index
Definition rel.h:192
void * rd_amcache
Definition rel.h:229
Oid rd_pkindex
Definition rel.h:153
bool rd_fkeyvalid
Definition rel.h:123
bool rd_statvalid
Definition rel.h:66
List * rd_statlist
Definition rel.h:158
MemoryContext rd_pddcxt
Definition rel.h:135
RuleLock * rd_rules
Definition rel.h:115
struct FmgrInfo * rd_supportinfo
Definition rel.h:210
Oid * rd_opfamily
Definition rel.h:207
MemoryContext rd_rulescxt
Definition rel.h:116
Bitmapset * rd_pkattr
Definition rel.h:163
PartitionKey rd_partkey
Definition rel.h:126
bytea * rd_options
Definition rel.h:175
Oid * rd_indcollation
Definition rel.h:217
struct PgStat_TableStatus * pgstat_info
Definition rel.h:255
#define InvalidTransactionId
Definition transam.h:31
static Size VARSIZE(const void *PTR)
Definition varatt.h:298

References AllocateFile(), ALLOCSET_SMALL_SIZES, AllocSetContextCreate, IndexAmRoutine::amsupport, Assert, ATTRIBUTE_FIXED_PART_SIZE, CacheMemoryContext, TupleDescData::constr, CreateTemplateTupleDesc(), criticalRelcachesBuilt, criticalSharedRelcachesBuilt, DatabasePath, elog, fb(), FreeFile(), GETSTRUCT(), TupleConstr::has_not_null, HEAPTUPLESIZE, i, InitIndexAmRoutine(), InvalidOid, InvalidSubTransactionId, InvalidTransactionId, len, MAXPGPATH, MemoryContextAlloc(), MemoryContextAllocZero(), MemoryContextCopyAndSetIdentifier, NIL, NUM_CRITICAL_LOCAL_INDEXES, NUM_CRITICAL_LOCAL_RELS, NUM_CRITICAL_SHARED_INDEXES, NUM_CRITICAL_SHARED_RELS, palloc(), palloc0_object, pfree(), PG_BINARY_R, RelationData::pgstat_info, populate_compact_attribute(), RelationData::rd_amcache, RelationData::rd_att, RelationData::rd_attrsvalid, RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_exclops, RelationData::rd_exclprocs, RelationData::rd_exclstrats, RelationData::rd_fdwroutine, RelationData::rd_firstRelfilelocatorSubid, RelationData::rd_fkeylist, RelationData::rd_fkeyvalid, RelationData::rd_idattr, RelationData::rd_indam, RelationData::rd_indcollation, RelationData::rd_index, 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_newRelfilelocatorSubid, RelationData::rd_opcintype, RelationData::rd_opcoptions, RelationData::rd_opfamily, RelationData::rd_options, RelationData::rd_partcheck, RelationData::rd_partcheckcxt, RelationData::rd_partcheckvalid, RelationData::rd_partdesc, RelationData::rd_partdesc_nodetached, RelationData::rd_partdesc_nodetached_xmin, RelationData::rd_partkey, RelationData::rd_partkeycxt, RelationData::rd_pdcxt, RelationData::rd_pddcxt, RelationData::rd_pkattr, RelationData::rd_pkindex, RelationData::rd_pubdesc, 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(), RelationInitTableAccessMethod(), RELCACHE_INIT_FILEMAGIC, RELCACHE_INIT_FILENAME, repalloc(), snprintf, HeapTupleData::t_data, TupleDescData::tdrefcount, TupleDescData::tdtypeid, TupleDescData::tdtypmod, RelationData::trigdesc, TupleDescAttr(), VARSIZE(), and WARNING.

Referenced by RelationCacheInitializePhase2(), and RelationCacheInitializePhase3().

◆ LookupOpclassInfo()

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

Definition at line 1662 of file relcache.c.

1664{
1666 bool found;
1667 Relation rel;
1668 SysScanDesc scan;
1669 ScanKeyData skey[3];
1670 HeapTuple htup;
1671 bool indexOK;
1672
1673 if (OpClassCache == NULL)
1674 {
1675 /* First time through: initialize the opclass cache */
1676 HASHCTL ctl;
1677
1678 /* Also make sure CacheMemoryContext exists */
1679 if (!CacheMemoryContext)
1681
1682 ctl.keysize = sizeof(Oid);
1683 ctl.entrysize = sizeof(OpClassCacheEnt);
1684 OpClassCache = hash_create("Operator class cache", 64,
1686 }
1687
1690 HASH_ENTER, &found);
1691
1692 if (!found)
1693 {
1694 /* Initialize new entry */
1695 opcentry->valid = false; /* until known OK */
1696 opcentry->numSupport = numSupport;
1697 opcentry->supportProcs = NULL; /* filled below */
1698 }
1699 else
1700 {
1701 Assert(numSupport == opcentry->numSupport);
1702 }
1703
1704 /*
1705 * When aggressively testing cache-flush hazards, we disable the operator
1706 * class cache and force reloading of the info on each call. This models
1707 * no real-world behavior, since the cache entries are never invalidated
1708 * otherwise. However it can be helpful for detecting bugs in the cache
1709 * loading logic itself, such as reliance on a non-nailed index. Given
1710 * the limited use-case and the fact that this adds a great deal of
1711 * expense, we enable it only for high values of debug_discard_caches.
1712 */
1713#ifdef DISCARD_CACHES_ENABLED
1714 if (debug_discard_caches > 2)
1715 opcentry->valid = false;
1716#endif
1717
1718 if (opcentry->valid)
1719 return opcentry;
1720
1721 /*
1722 * Need to fill in new entry. First allocate space, unless we already did
1723 * so in some previous attempt.
1724 */
1725 if (opcentry->supportProcs == NULL && numSupport > 0)
1726 opcentry->supportProcs = (RegProcedure *)
1728 numSupport * sizeof(RegProcedure));
1729
1730 /*
1731 * To avoid infinite recursion during startup, force heap scans if we're
1732 * looking up info for the opclasses used by the indexes we would like to
1733 * reference here.
1734 */
1738
1739 /*
1740 * We have to fetch the pg_opclass row to determine its opfamily and
1741 * opcintype, which are needed to look up related operators and functions.
1742 * It'd be convenient to use the syscache here, but that probably doesn't
1743 * work while bootstrapping.
1744 */
1745 ScanKeyInit(&skey[0],
1751 NULL, 1, skey);
1752
1753 if (HeapTupleIsValid(htup = systable_getnext(scan)))
1754 {
1756
1757 opcentry->opcfamily = opclassform->opcfamily;
1758 opcentry->opcintype = opclassform->opcintype;
1759 }
1760 else
1761 elog(ERROR, "could not find tuple for opclass %u", operatorClassOid);
1762
1763 systable_endscan(scan);
1765
1766 /*
1767 * Scan pg_amproc to obtain support procs for the opclass. We only fetch
1768 * the default ones (those with lefttype = righttype = opcintype).
1769 */
1770 if (numSupport > 0)
1771 {
1772 ScanKeyInit(&skey[0],
1775 ObjectIdGetDatum(opcentry->opcfamily));
1776 ScanKeyInit(&skey[1],
1779 ObjectIdGetDatum(opcentry->opcintype));
1780 ScanKeyInit(&skey[2],
1783 ObjectIdGetDatum(opcentry->opcintype));
1786 NULL, 3, skey);
1787
1788 while (HeapTupleIsValid(htup = systable_getnext(scan)))
1789 {
1791
1792 if (amprocform->amprocnum <= 0 ||
1793 (StrategyNumber) amprocform->amprocnum > numSupport)
1794 elog(ERROR, "invalid amproc number %d for opclass %u",
1795 amprocform->amprocnum, operatorClassOid);
1796
1797 opcentry->supportProcs[amprocform->amprocnum - 1] =
1798 amprocform->amproc;
1799 }
1800
1801 systable_endscan(scan);
1803 }
1804
1805 opcentry->valid = true;
1806 return opcentry;
1807}
void CreateCacheMemoryContext(void)
Definition catcache.c:715
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition dynahash.c:358
#define HASH_ELEM
Definition hsearch.h:95
#define HASH_BLOBS
Definition hsearch.h:97
int debug_discard_caches
Definition inval.c:260
FormData_pg_amproc * Form_pg_amproc
Definition pg_amproc.h:68
FormData_pg_opclass * Form_pg_opclass
Definition pg_opclass.h:83
tree ctl
Definition radixtree.h:1838
static HTAB * OpClassCache
Definition relcache.c:271
struct opclasscacheent OpClassCacheEnt
uint16 StrategyNumber
Definition stratnum.h:22

References AccessShareLock, Assert, BTEqualStrategyNumber, CacheMemoryContext, CreateCacheMemoryContext(), criticalRelcachesBuilt, ctl, debug_discard_caches, elog, ERROR, fb(), GETSTRUCT(), HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), HeapTupleIsValid, MemoryContextAllocZero(), ObjectIdGetDatum(), OpClassCache, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by IndexSupportInitialize().

◆ RelationAssumeNewRelfilelocator()

void RelationAssumeNewRelfilelocator ( Relation  relation)

Definition at line 3971 of file relcache.c.

3972{
3976
3977 /* Flag relation as needing eoxact cleanup (to clear these fields) */
3978 EOXactListAdd(relation);
3979}
#define EOXactListAdd(rel)
Definition relcache.c:189
SubTransactionId GetCurrentSubTransactionId(void)
Definition xact.c:792

References EOXactListAdd, GetCurrentSubTransactionId(), InvalidSubTransactionId, RelationData::rd_firstRelfilelocatorSubid, and RelationData::rd_newRelfilelocatorSubid.

Referenced by ATExecSetTableSpace(), reindex_index(), RelationSetNewRelfilenumber(), and swap_relation_files().

◆ RelationBuildDesc()

static Relation RelationBuildDesc ( Oid  targetRelId,
bool  insertIt 
)
static

Definition at line 1059 of file relcache.c.

1060{
1062 Relation relation;
1063 Oid relid;
1066
1067 /*
1068 * This function and its subroutines can allocate a good deal of transient
1069 * data in CurrentMemoryContext. Traditionally we've just leaked that
1070 * data, reasoning that the caller's context is at worst of transaction
1071 * scope, and relcache loads shouldn't happen so often that it's essential
1072 * to recover transient data before end of statement/transaction. However
1073 * that's definitely not true when debug_discard_caches is active, and
1074 * perhaps it's not true in other cases.
1075 *
1076 * When debug_discard_caches is active or when forced to by
1077 * RECOVER_RELATION_BUILD_MEMORY=1, arrange to allocate the junk in a
1078 * temporary context that we'll free before returning. Make it a child of
1079 * caller's context so that it will get cleaned up appropriately if we
1080 * error out partway through.
1081 */
1082#ifdef MAYBE_RECOVER_RELATION_BUILD_MEMORY
1085
1087 {
1089 "RelationBuildDesc workspace",
1092 }
1093#endif
1094
1095 /* Register to catch invalidation messages */
1097 {
1098 int allocsize;
1099
1100 allocsize = in_progress_list_maxlen * 2;
1102 allocsize * sizeof(*in_progress_list));
1103 in_progress_list_maxlen = allocsize;
1104 }
1107retry:
1109
1110 /*
1111 * find the tuple in pg_class corresponding to the given relation id
1112 */
1114
1115 /*
1116 * if no such tuple exists, return NULL
1117 */
1119 {
1120#ifdef MAYBE_RECOVER_RELATION_BUILD_MEMORY
1121 if (tmpcxt)
1122 {
1123 /* Return to caller's context, and blow away the temporary context */
1126 }
1127#endif
1130 return NULL;
1131 }
1132
1133 /*
1134 * get information from the pg_class_tuple
1135 */
1137 relid = relp->oid;
1138 Assert(relid == targetRelId);
1139
1140 /*
1141 * allocate storage for the relation descriptor, and copy pg_class_tuple
1142 * to relation->rd_rel.
1143 */
1144 relation = AllocateRelationDesc(relp);
1145
1146 /*
1147 * initialize the relation's relation id (relation->rd_id)
1148 */
1149 RelationGetRelid(relation) = relid;
1150
1151 /*
1152 * Normal relations are not nailed into the cache. Since we don't flush
1153 * new relations, it won't be new. It could be temp though.
1154 */
1155 relation->rd_refcnt = 0;
1156 relation->rd_isnailed = false;
1161 switch (relation->rd_rel->relpersistence)
1162 {
1165 relation->rd_backend = INVALID_PROC_NUMBER;
1166 relation->rd_islocaltemp = false;
1167 break;
1169 if (isTempOrTempToastNamespace(relation->rd_rel->relnamespace))
1170 {
1172 relation->rd_islocaltemp = true;
1173 }
1174 else
1175 {
1176 /*
1177 * If it's a temp table, but not one of ours, we have to use
1178 * the slow, grotty method to figure out the owning backend.
1179 *
1180 * Note: it's possible that rd_backend gets set to
1181 * MyProcNumber here, in case we are looking at a pg_class
1182 * entry left over from a crashed backend that coincidentally
1183 * had the same ProcNumber we're using. We should *not*
1184 * consider such a table to be "ours"; this is why we need the
1185 * separate rd_islocaltemp flag. The pg_class entry will get
1186 * flushed if/when we clean out the corresponding temp table
1187 * namespace in preparation for using it.
1188 */
1189 relation->rd_backend =
1190 GetTempNamespaceProcNumber(relation->rd_rel->relnamespace);
1192 relation->rd_islocaltemp = false;
1193 }
1194 break;
1195 default:
1196 elog(ERROR, "invalid relpersistence: %c",
1197 relation->rd_rel->relpersistence);
1198 break;
1199 }
1200
1201 /*
1202 * initialize the tuple descriptor (relation->rd_att).
1203 */
1204 RelationBuildTupleDesc(relation);
1205
1206 /* foreign key data is not loaded till asked for */
1207 relation->rd_fkeylist = NIL;
1208 relation->rd_fkeyvalid = false;
1209
1210 /* partitioning data is not loaded till asked for */
1211 relation->rd_partkey = NULL;
1212 relation->rd_partkeycxt = NULL;
1213 relation->rd_partdesc = NULL;
1214 relation->rd_partdesc_nodetached = NULL;
1216 relation->rd_pdcxt = NULL;
1217 relation->rd_pddcxt = NULL;
1218 relation->rd_partcheck = NIL;
1219 relation->rd_partcheckvalid = false;
1220 relation->rd_partcheckcxt = NULL;
1221
1222 /*
1223 * initialize access method information
1224 */
1225 if (relation->rd_rel->relkind == RELKIND_INDEX ||
1226 relation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
1228 else if (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind) ||
1229 relation->rd_rel->relkind == RELKIND_SEQUENCE)
1231 else if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1232 {
1233 /*
1234 * Do nothing: access methods are a setting that partitions can
1235 * inherit.
1236 */
1237 }
1238 else
1239 Assert(relation->rd_rel->relam == InvalidOid);
1240
1241 /* extract reloptions if any */
1243
1244 /*
1245 * Fetch rules and triggers that affect this relation.
1246 *
1247 * Note that RelationBuildRuleLock() relies on this being done after
1248 * extracting the relation's reloptions.
1249 */
1250 if (relation->rd_rel->relhasrules)
1251 RelationBuildRuleLock(relation);
1252 else
1253 {
1254 relation->rd_rules = NULL;
1255 relation->rd_rulescxt = NULL;
1256 }
1257
1258 if (relation->rd_rel->relhastriggers)
1259 RelationBuildTriggers(relation);
1260 else
1261 relation->trigdesc = NULL;
1262
1263 if (relation->rd_rel->relrowsecurity)
1264 RelationBuildRowSecurity(relation);
1265 else
1266 relation->rd_rsdesc = NULL;
1267
1268 /*
1269 * initialize the relation lock manager information
1270 */
1271 RelationInitLockInfo(relation); /* see lmgr.c */
1272
1273 /*
1274 * initialize physical addressing information for the relation
1275 */
1276 RelationInitPhysicalAddr(relation);
1277
1278 /* make sure relation is marked as having no open file yet */
1279 relation->rd_smgr = NULL;
1280
1281 /*
1282 * now we can free the memory allocated for pg_class_tuple
1283 */
1285
1286 /*
1287 * If an invalidation arrived mid-build, start over. Between here and the
1288 * end of this function, don't add code that does or reasonably could read
1289 * system catalogs. That range must be free from invalidation processing
1290 * for the !insertIt case. For the insertIt case, RelationCacheInsert()
1291 * will enroll this relation in ordinary relcache invalidation processing,
1292 */
1293 if (in_progress_list[in_progress_offset].invalidated)
1294 {
1295 RelationDestroyRelation(relation, false);
1296 goto retry;
1297 }
1300
1301 /*
1302 * Insert newly created relation into relcache hash table, if requested.
1303 *
1304 * There is one scenario in which we might find a hashtable entry already
1305 * present, even though our caller failed to find it: if the relation is a
1306 * system catalog or index that's used during relcache load, we might have
1307 * recursively created the same relcache entry during the preceding steps.
1308 * So allow RelationCacheInsert to delete any already-present relcache
1309 * entry for the same OID. The already-present entry should have refcount
1310 * zero (else somebody forgot to close it); in the event that it doesn't,
1311 * we'll elog a WARNING and leak the already-present entry.
1312 */
1313 if (insertIt)
1314 RelationCacheInsert(relation, true);
1315
1316 /* It's fully valid */
1317 relation->rd_isvalid = true;
1318
1319#ifdef MAYBE_RECOVER_RELATION_BUILD_MEMORY
1320 if (tmpcxt)
1321 {
1322 /* Return to caller's context, and blow away the temporary context */
1325 }
1326#endif
1327
1328 return relation;
1329}
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1435
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition namespace.c:3743
ProcNumber GetTempNamespaceProcNumber(Oid namespaceId)
Definition namespace.c:3836
void RelationBuildRowSecurity(Relation relation)
Definition policy.c:193
#define ProcNumberForTempRelations()
Definition procnumber.h:53
#define RECOVER_RELATION_BUILD_MEMORY
Definition relcache.c:102
static void RelationParseRelOptions(Relation relation, HeapTuple tuple)
Definition relcache.c:468
static Relation AllocateRelationDesc(Form_pg_class relp)
Definition relcache.c:413
void RelationInitIndexAccessInfo(Relation relation)
Definition relcache.c:1440
static int in_progress_list_maxlen
Definition relcache.c:172
static void RelationDestroyRelation(Relation relation, bool remember_tupdesc)
Definition relcache.c:2434
static void RelationBuildRuleLock(Relation relation)
Definition relcache.c:752
static HeapTuple ScanPgRelation(Oid targetRelId, bool indexOK, bool force_non_historic)
Definition relcache.c:340
static void RelationBuildTupleDesc(Relation relation)
Definition relcache.c:525
static InProgressEnt * in_progress_list
Definition relcache.c:170
bool invalidated
Definition relcache.c:167
void RelationBuildTriggers(Relation relation)
Definition trigger.c:1861

References AllocateRelationDesc(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, CurrentMemoryContext, debug_discard_caches, elog, ERROR, fb(), GETSTRUCT(), GetTempNamespaceProcNumber(), heap_freetuple(), HeapTupleIsValid, in_progress_list, in_progress_list_len, in_progress_list_maxlen, INVALID_PROC_NUMBER, inprogressent::invalidated, InvalidOid, InvalidSubTransactionId, InvalidTransactionId, isTempOrTempToastNamespace(), MemoryContextDelete(), MemoryContextSwitchTo(), NIL, ProcNumberForTempRelations, RelationData::rd_backend, RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_firstRelfilelocatorSubid, RelationData::rd_fkeylist, RelationData::rd_fkeyvalid, RelationData::rd_islocaltemp, RelationData::rd_isnailed, RelationData::rd_isvalid, RelationData::rd_newRelfilelocatorSubid, RelationData::rd_partcheck, RelationData::rd_partcheckcxt, RelationData::rd_partcheckvalid, RelationData::rd_partdesc, RelationData::rd_partdesc_nodetached, RelationData::rd_partdesc_nodetached_xmin, RelationData::rd_partkey, RelationData::rd_partkeycxt, RelationData::rd_pdcxt, RelationData::rd_pddcxt, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_rsdesc, RelationData::rd_rules, RelationData::rd_rulescxt, RelationData::rd_smgr, RECOVER_RELATION_BUILD_MEMORY, RelationBuildRowSecurity(), RelationBuildRuleLock(), RelationBuildTriggers(), RelationBuildTupleDesc(), RelationCacheInsert, RelationDestroyRelation(), RelationGetRelid, RelationInitIndexAccessInfo(), RelationInitLockInfo(), RelationInitPhysicalAddr(), RelationInitTableAccessMethod(), RelationParseRelOptions(), inprogressent::reloid, repalloc(), ScanPgRelation(), and RelationData::trigdesc.

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

◆ RelationBuildLocalRelation()

Relation RelationBuildLocalRelation ( const char relname,
Oid  relnamespace,
TupleDesc  tupDesc,
Oid  relid,
Oid  accessmtd,
RelFileNumber  relfilenumber,
Oid  reltablespace,
bool  shared_relation,
bool  mapped_relation,
char  relpersistence,
char  relkind 
)

Definition at line 3510 of file relcache.c.

3521{
3522 Relation rel;
3524 int natts = tupDesc->natts;
3525 int i;
3526 bool has_not_null;
3527 bool nailit;
3528
3529 Assert(natts >= 0);
3530
3531 /*
3532 * check for creation of a rel that must be nailed in cache.
3533 *
3534 * XXX this list had better match the relations specially handled in
3535 * RelationCacheInitializePhase2/3.
3536 */
3537 switch (relid)
3538 {
3539 case DatabaseRelationId:
3540 case AuthIdRelationId:
3541 case AuthMemRelationId:
3542 case RelationRelationId:
3545 case TypeRelationId:
3546 nailit = true;
3547 break;
3548 default:
3549 nailit = false;
3550 break;
3551 }
3552
3553 /*
3554 * check that hardwired list of shared rels matches what's in the
3555 * bootstrap .bki file. If you get a failure here during initdb, you
3556 * probably need to fix IsSharedRelation() to match whatever you've done
3557 * to the set of shared relations.
3558 */
3559 if (shared_relation != IsSharedRelation(relid))
3560 elog(ERROR, "shared_relation flag for \"%s\" does not match IsSharedRelation(%u)",
3561 relname, relid);
3562
3563 /* Shared relations had better be mapped, too */
3565
3566 /*
3567 * switch to the cache context to create the relcache entry.
3568 */
3569 if (!CacheMemoryContext)
3571
3573
3574 /*
3575 * allocate a new relation descriptor and fill in basic state fields.
3576 */
3578
3579 /* make sure relation is marked as having no open file yet */
3580 rel->rd_smgr = NULL;
3581
3582 /* mark it nailed if appropriate */
3583 rel->rd_isnailed = nailit;
3584
3585 rel->rd_refcnt = nailit ? 1 : 0;
3586
3587 /* it's being created in this transaction */
3592
3593 /*
3594 * create a new tuple descriptor from the one passed in. We do this
3595 * partly to copy it into the cache context, and partly because the new
3596 * relation can't have any defaults or constraints yet; they have to be
3597 * added in later steps, because they require additions to multiple system
3598 * catalogs. We can copy attnotnull constraints here, however.
3599 */
3600 rel->rd_att = CreateTupleDescCopy(tupDesc);
3601 rel->rd_att->tdrefcount = 1; /* mark as refcounted */
3602 has_not_null = false;
3603 for (i = 0; i < natts; i++)
3604 {
3607
3608 datt->attidentity = satt->attidentity;
3609 datt->attgenerated = satt->attgenerated;
3610 datt->attnotnull = satt->attnotnull;
3611 has_not_null |= satt->attnotnull;
3613
3614 if (satt->attnotnull)
3615 {
3618
3619 dcatt->attnullability = scatt->attnullability;
3620 }
3621 }
3622
3623 if (has_not_null)
3624 {
3626
3627 constr->has_not_null = true;
3628 rel->rd_att->constr = constr;
3629 }
3630
3631 /*
3632 * initialize relation tuple form (caller may add/override data later)
3633 */
3635
3636 namestrcpy(&rel->rd_rel->relname, relname);
3637 rel->rd_rel->relnamespace = relnamespace;
3638
3639 rel->rd_rel->relkind = relkind;
3640 rel->rd_rel->relnatts = natts;
3641 rel->rd_rel->reltype = InvalidOid;
3642 /* needed when bootstrapping: */
3643 rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;
3644
3645 /* set up persistence and relcache fields dependent on it */
3646 rel->rd_rel->relpersistence = relpersistence;
3647 switch (relpersistence)
3648 {
3652 rel->rd_islocaltemp = false;
3653 break;
3655 Assert(isTempOrTempToastNamespace(relnamespace));
3657 rel->rd_islocaltemp = true;
3658 break;
3659 default:
3660 elog(ERROR, "invalid relpersistence: %c", relpersistence);
3661 break;
3662 }
3663
3664 /* if it's a materialized view, it's not populated initially */
3665 if (relkind == RELKIND_MATVIEW)
3666 rel->rd_rel->relispopulated = false;
3667 else
3668 rel->rd_rel->relispopulated = true;
3669
3670 /* set replica identity -- system catalogs and non-tables don't have one */
3671 if (!IsCatalogNamespace(relnamespace) &&
3672 (relkind == RELKIND_RELATION ||
3673 relkind == RELKIND_MATVIEW ||
3674 relkind == RELKIND_PARTITIONED_TABLE))
3675 rel->rd_rel->relreplident = REPLICA_IDENTITY_DEFAULT;
3676 else
3677 rel->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
3678
3679 /*
3680 * Insert relation physical and logical identifiers (OIDs) into the right
3681 * places. For a mapped relation, we set relfilenumber to zero and rely
3682 * on RelationInitPhysicalAddr to consult the map.
3683 */
3684 rel->rd_rel->relisshared = shared_relation;
3685
3686 RelationGetRelid(rel) = relid;
3687
3688 for (i = 0; i < natts; i++)
3689 TupleDescAttr(rel->rd_att, i)->attrelid = relid;
3690
3691 rel->rd_rel->reltablespace = reltablespace;
3692
3693 if (mapped_relation)
3694 {
3695 rel->rd_rel->relfilenode = InvalidRelFileNumber;
3696 /* Add it to the active mapping information */
3697 RelationMapUpdateMap(relid, relfilenumber, shared_relation, true);
3698 }
3699 else
3700 rel->rd_rel->relfilenode = relfilenumber;
3701
3702 RelationInitLockInfo(rel); /* see lmgr.c */
3703
3705
3706 rel->rd_rel->relam = accessmtd;
3707
3708 /*
3709 * RelationInitTableAccessMethod will do syscache lookups, so we mustn't
3710 * run it in CacheMemoryContext. Fortunately, the remaining steps don't
3711 * require a long-lived current context.
3712 */
3714
3715 if (RELKIND_HAS_TABLE_AM(relkind) || relkind == RELKIND_SEQUENCE)
3717
3718 /*
3719 * Leave index access method uninitialized, because the pg_index row has
3720 * not been inserted at this stage of index creation yet. The cache
3721 * invalidation after pg_index row has been inserted will initialize it.
3722 */
3723
3724 /*
3725 * Okay to insert into the relcache hash table.
3726 *
3727 * Ordinarily, there should certainly not be an existing hash entry for
3728 * the same OID; but during bootstrap, when we create a "real" relcache
3729 * entry for one of the bootstrap relations, we'll be overwriting the
3730 * phony one created with formrdesc. So allow that to happen for nailed
3731 * rels.
3732 */
3734
3735 /*
3736 * Flag relation as needing eoxact cleanup (to clear rd_createSubid). We
3737 * can't do this before storing relid in it.
3738 */
3739 EOXactListAdd(rel);
3740
3741 /* It's fully valid */
3742 rel->rd_isvalid = true;
3743
3744 /*
3745 * Caller expects us to pin the returned entry.
3746 */
3748
3749 return rel;
3750}
bool IsCatalogNamespace(Oid namespaceId)
Definition catalog.c:243
bool IsSharedRelation(Oid relationId)
Definition catalog.c:304
NameData relname
Definition pg_class.h:38
void RelationIncrementReferenceCount(Relation rel)
Definition relcache.c:2182
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition tupdesc.c:252

References Assert, CacheMemoryContext, CLASS_TUPLE_SIZE, TupleDescData::constr, CreateCacheMemoryContext(), CreateTupleDescCopy(), elog, EOXactListAdd, ERROR, fb(), GetCurrentSubTransactionId(), TupleConstr::has_not_null, i, INVALID_PROC_NUMBER, InvalidOid, InvalidRelFileNumber, InvalidSubTransactionId, IsCatalogNamespace(), IsSharedRelation(), isTempOrTempToastNamespace(), MemoryContextSwitchTo(), namestrcpy(), TupleDescData::natts, palloc0(), palloc0_object, populate_compact_attribute(), ProcNumberForTempRelations, RelationData::rd_att, RelationData::rd_backend, RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_firstRelfilelocatorSubid, RelationData::rd_islocaltemp, RelationData::rd_isnailed, RelationData::rd_isvalid, RelationData::rd_newRelfilelocatorSubid, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_smgr, RelationCacheInsert, RelationGetRelid, RelationIncrementReferenceCount(), RelationInitLockInfo(), RelationInitPhysicalAddr(), RelationInitTableAccessMethod(), RelationMapUpdateMap(), relname, TupleDescData::tdrefcount, TupleDescAttr(), and TupleDescCompactAttr().

Referenced by heap_create().

◆ RelationBuildPublicationDesc()

void RelationBuildPublicationDesc ( Relation  relation,
PublicationDesc pubdesc 
)

Definition at line 5789 of file relcache.c.

5790{
5791 List *puboids;
5792 ListCell *lc;
5794 Oid schemaid;
5795 List *ancestors = NIL;
5796 Oid relid = RelationGetRelid(relation);
5797
5798 /*
5799 * If not publishable, it publishes no actions. (pgoutput_change() will
5800 * ignore it.)
5801 */
5802 if (!is_publishable_relation(relation))
5803 {
5804 memset(pubdesc, 0, sizeof(PublicationDesc));
5805 pubdesc->rf_valid_for_update = true;
5806 pubdesc->rf_valid_for_delete = true;
5807 pubdesc->cols_valid_for_update = true;
5808 pubdesc->cols_valid_for_delete = true;
5809 pubdesc->gencols_valid_for_update = true;
5810 pubdesc->gencols_valid_for_delete = true;
5811 return;
5812 }
5813
5814 if (relation->rd_pubdesc)
5815 {
5816 memcpy(pubdesc, relation->rd_pubdesc, sizeof(PublicationDesc));
5817 return;
5818 }
5819
5820 memset(pubdesc, 0, sizeof(PublicationDesc));
5821 pubdesc->rf_valid_for_update = true;
5822 pubdesc->rf_valid_for_delete = true;
5823 pubdesc->cols_valid_for_update = true;
5824 pubdesc->cols_valid_for_delete = true;
5825 pubdesc->gencols_valid_for_update = true;
5826 pubdesc->gencols_valid_for_delete = true;
5827
5828 /* Fetch the publication membership info. */
5830 schemaid = RelationGetNamespace(relation);
5832
5833 if (relation->rd_rel->relispartition)
5834 {
5835 /* Add publications that the ancestors are in too. */
5836 ancestors = get_partition_ancestors(relid);
5837
5838 foreach(lc, ancestors)
5839 {
5841
5847 }
5848 }
5850
5851 foreach(lc, puboids)
5852 {
5853 Oid pubid = lfirst_oid(lc);
5854 HeapTuple tup;
5857 bool invalid_gen_col;
5858
5860
5861 if (!HeapTupleIsValid(tup))
5862 elog(ERROR, "cache lookup failed for publication %u", pubid);
5863
5865
5866 pubdesc->pubactions.pubinsert |= pubform->pubinsert;
5867 pubdesc->pubactions.pubupdate |= pubform->pubupdate;
5868 pubdesc->pubactions.pubdelete |= pubform->pubdelete;
5869 pubdesc->pubactions.pubtruncate |= pubform->pubtruncate;
5870
5871 /*
5872 * Check if all columns referenced in the filter expression are part
5873 * of the REPLICA IDENTITY index or not.
5874 *
5875 * If the publication is FOR ALL TABLES then it means the table has no
5876 * row filters and we can skip the validation.
5877 */
5878 if (!pubform->puballtables &&
5879 (pubform->pubupdate || pubform->pubdelete) &&
5880 pub_rf_contains_invalid_column(pubid, relation, ancestors,
5881 pubform->pubviaroot))
5882 {
5883 if (pubform->pubupdate)
5884 pubdesc->rf_valid_for_update = false;
5885 if (pubform->pubdelete)
5886 pubdesc->rf_valid_for_delete = false;
5887 }
5888
5889 /*
5890 * Check if all columns are part of the REPLICA IDENTITY index or not.
5891 *
5892 * Check if all generated columns included in the REPLICA IDENTITY are
5893 * published.
5894 */
5895 if ((pubform->pubupdate || pubform->pubdelete) &&
5896 pub_contains_invalid_column(pubid, relation, ancestors,
5897 pubform->pubviaroot,
5898 pubform->pubgencols,
5901 {
5902 if (pubform->pubupdate)
5903 {
5904 pubdesc->cols_valid_for_update = !invalid_column_list;
5905 pubdesc->gencols_valid_for_update = !invalid_gen_col;
5906 }
5907
5908 if (pubform->pubdelete)
5909 {
5910 pubdesc->cols_valid_for_delete = !invalid_column_list;
5911 pubdesc->gencols_valid_for_delete = !invalid_gen_col;
5912 }
5913 }
5914
5916
5917 /*
5918 * If we know everything is replicated and the row filter is invalid
5919 * for update and delete, there is no point to check for other
5920 * publications.
5921 */
5922 if (pubdesc->pubactions.pubinsert && pubdesc->pubactions.pubupdate &&
5923 pubdesc->pubactions.pubdelete && pubdesc->pubactions.pubtruncate &&
5924 !pubdesc->rf_valid_for_update && !pubdesc->rf_valid_for_delete)
5925 break;
5926
5927 /*
5928 * If we know everything is replicated and the column list is invalid
5929 * for update and delete, there is no point to check for other
5930 * publications.
5931 */
5932 if (pubdesc->pubactions.pubinsert && pubdesc->pubactions.pubupdate &&
5933 pubdesc->pubactions.pubdelete && pubdesc->pubactions.pubtruncate &&
5934 !pubdesc->cols_valid_for_update && !pubdesc->cols_valid_for_delete)
5935 break;
5936
5937 /*
5938 * If we know everything is replicated and replica identity has an
5939 * unpublished generated column, there is no point to check for other
5940 * publications.
5941 */
5942 if (pubdesc->pubactions.pubinsert && pubdesc->pubactions.pubupdate &&
5943 pubdesc->pubactions.pubdelete && pubdesc->pubactions.pubtruncate &&
5944 !pubdesc->gencols_valid_for_update &&
5945 !pubdesc->gencols_valid_for_delete)
5946 break;
5947 }
5948
5949 if (relation->rd_pubdesc)
5950 {
5951 pfree(relation->rd_pubdesc);
5952 relation->rd_pubdesc = NULL;
5953 }
5954
5955 /* Now save copy of the descriptor in the relcache entry. */
5958 memcpy(relation->rd_pubdesc, pubdesc, sizeof(PublicationDesc));
5960}
#define palloc_object(type)
Definition fe_memutils.h:74
List * list_concat_unique_oid(List *list1, const List *list2)
Definition list.c:1469
Oid get_rel_namespace(Oid relid)
Definition lsyscache.c:2102
List * get_partition_ancestors(Oid relid)
Definition partition.c:134
#define lfirst_oid(lc)
Definition pg_list.h:174
List * GetRelationPublications(Oid relid)
List * GetAllTablesPublications(void)
List * GetSchemaPublications(Oid schemaid)
bool is_publishable_relation(Relation rel)
FormData_pg_publication * Form_pg_publication
bool pub_contains_invalid_column(Oid pubid, Relation relation, List *ancestors, bool pubviaroot, char pubgencols_type, bool *invalid_column_list, bool *invalid_gen_col)
bool pub_rf_contains_invalid_column(Oid pubid, Relation relation, List *ancestors, bool pubviaroot)
Definition pg_list.h:54
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition syscache.c:220

References CacheMemoryContext, elog, ERROR, fb(), get_partition_ancestors(), get_rel_namespace(), GetAllTablesPublications(), GetRelationPublications(), GetSchemaPublications(), GETSTRUCT(), HeapTupleIsValid, is_publishable_relation(), lfirst_oid, list_concat_unique_oid(), MemoryContextSwitchTo(), NIL, ObjectIdGetDatum(), palloc_object, pfree(), pub_contains_invalid_column(), pub_rf_contains_invalid_column(), RelationData::rd_pubdesc, RelationData::rd_rel, RelationGetNamespace, RelationGetRelid, ReleaseSysCache(), and SearchSysCache1().

Referenced by CheckCmdReplicaIdentity().

◆ RelationBuildRuleLock()

static void RelationBuildRuleLock ( Relation  relation)
static

Definition at line 752 of file relcache.c.

753{
762 int numlocks;
764 int maxlocks;
765
766 /*
767 * Make the private context. Assume it'll not contain much data.
768 */
770 "relation rules",
772 relation->rd_rulescxt = rulescxt;
774 RelationGetRelationName(relation));
775
776 /*
777 * allocate an array to hold the rewrite rules (the array is extended if
778 * necessary)
779 */
780 maxlocks = 4;
781 rules = (RewriteRule **)
782 MemoryContextAlloc(rulescxt, sizeof(RewriteRule *) * maxlocks);
783 numlocks = 0;
784
785 /*
786 * form a scan key
787 */
788 ScanKeyInit(&key,
792
793 /*
794 * open pg_rewrite and begin a scan
795 *
796 * Note: since we scan the rules using RewriteRelRulenameIndexId, we will
797 * be reading the rules in name order, except possibly during
798 * emergency-recovery operations (ie, IgnoreSystemIndexes). This in turn
799 * ensures that rules will be fired in name order.
800 */
805 true, NULL,
806 1, &key);
807
809 {
811 bool isnull;
813 char *rule_str;
815 Oid check_as_user;
816
818 sizeof(RewriteRule));
819
820 rule->ruleId = rewrite_form->oid;
821
822 rule->event = rewrite_form->ev_type - '0';
823 rule->enabled = rewrite_form->ev_enabled;
824 rule->isInstead = rewrite_form->is_instead;
825
826 /*
827 * Must use heap_getattr to fetch ev_action and ev_qual. Also, the
828 * rule strings are often large enough to be toasted. To avoid
829 * leaking memory in the caller's context, do the detoasting here so
830 * we can free the detoasted version.
831 */
835 &isnull);
836 Assert(!isnull);
839 rule->actions = (List *) stringToNode(rule_str);
842
846 &isnull);
847 Assert(!isnull);
850 rule->qual = (Node *) stringToNode(rule_str);
853
854 /*
855 * If this is a SELECT rule defining a view, and the view has
856 * "security_invoker" set, we must perform all permissions checks on
857 * relations referred to by the rule as the invoking user.
858 *
859 * In all other cases (including non-SELECT rules on security invoker
860 * views), perform the permissions checks as the relation owner.
861 */
862 if (rule->event == CMD_SELECT &&
863 relation->rd_rel->relkind == RELKIND_VIEW &&
865 check_as_user = InvalidOid;
866 else
867 check_as_user = relation->rd_rel->relowner;
868
869 /*
870 * Scan through the rule's actions and set the checkAsUser field on
871 * all RTEPermissionInfos. We have to look at the qual as well, in
872 * case it contains sublinks.
873 *
874 * The reason for doing this when the rule is loaded, rather than when
875 * it is stored, is that otherwise ALTER TABLE OWNER would have to
876 * grovel through stored rules to update checkAsUser fields. Scanning
877 * the rule tree during load is relatively cheap (compared to
878 * constructing it in the first place), so we do it here.
879 */
880 setRuleCheckAsUser((Node *) rule->actions, check_as_user);
881 setRuleCheckAsUser(rule->qual, check_as_user);
882
883 if (numlocks >= maxlocks)
884 {
885 maxlocks *= 2;
886 rules = (RewriteRule **)
887 repalloc(rules, sizeof(RewriteRule *) * maxlocks);
888 }
889 rules[numlocks++] = rule;
890 }
891
892 /*
893 * end the scan and close the attribute relation
894 */
897
898 /*
899 * there might not be any rules (if relhasrules is out-of-date)
900 */
901 if (numlocks == 0)
902 {
903 relation->rd_rules = NULL;
904 relation->rd_rulescxt = NULL;
906 return;
907 }
908
909 /*
910 * form a RuleLock and insert into relation
911 */
913 rulelock->numLocks = numlocks;
914 rulelock->rules = rules;
915
916 relation->rd_rules = rulelock;
917}
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
@ CMD_SELECT
Definition nodes.h:275
FormData_pg_rewrite * Form_pg_rewrite
Definition pg_rewrite.h:52
void * stringToNode(const char *str)
Definition read.c:90
#define RelationHasSecurityInvoker(relation)
Definition rel.h:447
void setRuleCheckAsUser(Node *node, Oid userid)
Definition nodes.h:135
static struct rule * rules
Definition zic.c:286

References AccessShareLock, ALLOCSET_SMALL_SIZES, AllocSetContextCreate, Assert, BTEqualStrategyNumber, CacheMemoryContext, CMD_SELECT, fb(), GETSTRUCT(), heap_getattr(), HeapTupleIsValid, InvalidOid, MemoryContextAlloc(), MemoryContextCopyAndSetIdentifier, MemoryContextDelete(), MemoryContextSwitchTo(), ObjectIdGetDatum(), pfree(), RelationData::rd_rel, RelationData::rd_rules, RelationData::rd_rulescxt, RelationGetDescr, RelationGetRelationName, RelationGetRelid, RelationHasSecurityInvoker, repalloc(), rules, ScanKeyInit(), setRuleCheckAsUser(), stringToNode(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), and TextDatumGetCString.

Referenced by RelationBuildDesc(), and RelationCacheInitializePhase3().

◆ RelationBuildTupleDesc()

static void RelationBuildTupleDesc ( Relation  relation)
static

Definition at line 525 of file relcache.c.

526{
530 ScanKeyData skey[2];
531 int need;
532 TupleConstr *constr;
534 int ndef = 0;
535
536 /* fill rd_att's type ID fields (compare heap.c's AddNewRelationTuple) */
537 relation->rd_att->tdtypeid =
538 relation->rd_rel->reltype ? relation->rd_rel->reltype : RECORDOID;
539 relation->rd_att->tdtypmod = -1; /* just to be sure */
540
542 sizeof(TupleConstr));
543
544 /*
545 * Form a scan key that selects only user attributes (attnum > 0).
546 * (Eliminating system attribute rows at the index level is lots faster
547 * than fetching them.)
548 */
549 ScanKeyInit(&skey[0],
553 ScanKeyInit(&skey[1],
556 Int16GetDatum(0));
557
558 /*
559 * Open pg_attribute and begin a scan. Force heap scan if we haven't yet
560 * built the critical relcache entries (this includes initdb and startup
561 * without a pg_internal.init file).
562 */
567 NULL,
568 2, skey);
569
570 /*
571 * add attribute data to relation->rd_att
572 */
574
576 {
578 int attnum;
579
581
582 attnum = attp->attnum;
584 elog(ERROR, "invalid attribute number %d for relation \"%s\"",
585 attp->attnum, RelationGetRelationName(relation));
586
587 memcpy(TupleDescAttr(relation->rd_att, attnum - 1),
588 attp,
590
592
593 /* Update constraint/default info */
594 if (attp->attnotnull)
595 constr->has_not_null = true;
596 if (attp->attgenerated == ATTRIBUTE_GENERATED_STORED)
597 constr->has_generated_stored = true;
598 if (attp->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
599 constr->has_generated_virtual = true;
600 if (attp->atthasdef)
601 ndef++;
602
603 /* If the column has a "missing" value, put it in the attrmiss array */
604 if (attp->atthasmissing)
605 {
607 bool missingNull;
608
609 /* Do we have a missing value? */
612 pg_attribute_desc->rd_att,
613 &missingNull);
614 if (!missingNull)
615 {
616 /* Yes, fetch from the array */
618 bool is_null;
619 int one = 1;
621
622 if (attrmiss == NULL)
625 relation->rd_rel->relnatts *
626 sizeof(AttrMissing));
627
629 1,
630 &one,
631 -1,
632 attp->attlen,
633 attp->attbyval,
634 attp->attalign,
635 &is_null);
636 Assert(!is_null);
637 if (attp->attbyval)
638 {
639 /* for copy by val just copy the datum direct */
640 attrmiss[attnum - 1].am_value = missval;
641 }
642 else
643 {
644 /* otherwise copy in the correct context */
646 attrmiss[attnum - 1].am_value = datumCopy(missval,
647 attp->attbyval,
648 attp->attlen);
650 }
651 attrmiss[attnum - 1].am_present = true;
652 }
653 }
654 need--;
655 if (need == 0)
656 break;
657 }
658
659 /*
660 * end the scan and close the attribute relation
661 */
664
665 if (need != 0)
666 elog(ERROR, "pg_attribute catalog is missing %d attribute(s) for relation OID %u",
667 need, RelationGetRelid(relation));
668
669 /*
670 * We can easily set the attcacheoff value for the first attribute: it
671 * must be zero. This eliminates the need for special cases for attnum=1
672 * that used to exist in fastgetattr() and index_getattr().
673 */
674 if (RelationGetNumberOfAttributes(relation) > 0)
675 TupleDescCompactAttr(relation->rd_att, 0)->attcacheoff = 0;
676
677 /*
678 * Set up constraint/default info
679 */
680 if (constr->has_not_null ||
681 constr->has_generated_stored ||
682 constr->has_generated_virtual ||
683 ndef > 0 ||
684 attrmiss ||
685 relation->rd_rel->relchecks > 0)
686 {
687 bool is_catalog = IsCatalogRelation(relation);
688
689 relation->rd_att->constr = constr;
690
691 if (ndef > 0) /* DEFAULTs */
692 AttrDefaultFetch(relation, ndef);
693 else
694 constr->num_defval = 0;
695
696 constr->missing = attrmiss;
697
698 /* CHECK and NOT NULLs */
699 if (relation->rd_rel->relchecks > 0 ||
700 (!is_catalog && constr->has_not_null))
701 CheckNNConstraintFetch(relation);
702
703 /*
704 * Any not-null constraint that wasn't marked invalid by
705 * CheckNNConstraintFetch must necessarily be valid; make it so in the
706 * CompactAttribute array.
707 */
708 if (!is_catalog)
709 {
710 for (int i = 0; i < relation->rd_rel->relnatts; i++)
711 {
712 CompactAttribute *attr;
713
714 attr = TupleDescCompactAttr(relation->rd_att, i);
715
718 else
721 }
722 }
723
724 if (relation->rd_rel->relchecks == 0)
725 constr->num_check = 0;
726 }
727 else
728 {
729 pfree(constr);
730 relation->rd_att->constr = NULL;
731 }
732}
Datum array_get_element(Datum arraydatum, int nSubscripts, int *indx, int arraytyplen, int elmlen, bool elmbyval, char elmalign, bool *isNull)
bool IsCatalogRelation(Relation relation)
Definition catalog.c:104
static Datum Int16GetDatum(int16 X)
Definition postgres.h:182
#define RelationGetNumberOfAttributes(relation)
Definition rel.h:520
static void CheckNNConstraintFetch(Relation relation)
Definition relcache.c:4586
static void AttrDefaultFetch(Relation relation, int ndef)
Definition relcache.c:4490
#define BTGreaterStrategyNumber
Definition stratnum.h:33
bool has_generated_virtual
Definition tupdesc.h:47
bool has_generated_stored
Definition tupdesc.h:46
struct AttrMissing * missing
Definition tupdesc.h:42
#define ATTNULLABLE_VALID
Definition tupdesc.h:86
#define ATTNULLABLE_UNRESTRICTED
Definition tupdesc.h:84

References AccessShareLock, array_get_element(), Assert, CompactAttribute::attcacheoff, CompactAttribute::attnullability, ATTNULLABLE_INVALID, ATTNULLABLE_UNKNOWN, ATTNULLABLE_UNRESTRICTED, ATTNULLABLE_VALID, attnum, AttrDefaultFetch(), ATTRIBUTE_FIXED_PART_SIZE, BTEqualStrategyNumber, BTGreaterStrategyNumber, CacheMemoryContext, CheckNNConstraintFetch(), TupleDescData::constr, criticalRelcachesBuilt, datumCopy(), elog, ERROR, fb(), GETSTRUCT(), TupleConstr::has_generated_stored, TupleConstr::has_generated_virtual, TupleConstr::has_not_null, heap_getattr(), HeapTupleIsValid, i, Int16GetDatum(), IsCatalogRelation(), MemoryContextAllocZero(), MemoryContextSwitchTo(), TupleConstr::missing, TupleConstr::num_check, TupleConstr::num_defval, ObjectIdGetDatum(), pfree(), populate_compact_attribute(), RelationData::rd_att, RelationData::rd_rel, RelationGetNumberOfAttributes, RelationGetRelationName, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TupleDescData::tdtypeid, TupleDescData::tdtypmod, TupleDescAttr(), and TupleDescCompactAttr().

Referenced by RelationBuildDesc().

◆ RelationCacheInitFilePostInvalidate()

void RelationCacheInitFilePostInvalidate ( void  )

Definition at line 6880 of file relcache.c.

6881{
6883}
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1793

References fb(), and LWLockRelease().

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

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )

Definition at line 6855 of file relcache.c.

6856{
6859
6860 if (DatabasePath)
6861 snprintf(localinitfname, sizeof(localinitfname), "%s/%s",
6863 snprintf(sharedinitfname, sizeof(sharedinitfname), "global/%s",
6865
6867
6868 /*
6869 * The files might not be there if no backend has been started since the
6870 * last removal. But complain about failures other than ENOENT with
6871 * ERROR. Fortunately, it's not too late to abort the transaction if we
6872 * can't get rid of the would-be-obsolete init file.
6873 */
6874 if (DatabasePath)
6877}
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1176
@ LW_EXCLUSIVE
Definition lwlock.h:112
static void unlink_initfile(const char *initfilename, int elevel)
Definition relcache.c:6952

References DatabasePath, ERROR, fb(), LW_EXCLUSIVE, LWLockAcquire(), MAXPGPATH, RELCACHE_INIT_FILENAME, snprintf, and unlink_initfile().

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

◆ RelationCacheInitFileRemove()

void RelationCacheInitFileRemove ( void  )

Definition at line 6895 of file relcache.c.

6896{
6897 const char *tblspcdir = PG_TBLSPC_DIR;
6898 DIR *dir;
6899 struct dirent *de;
6900 char path[MAXPGPATH + sizeof(PG_TBLSPC_DIR) + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6901
6902 snprintf(path, sizeof(path), "global/%s",
6904 unlink_initfile(path, LOG);
6905
6906 /* Scan everything in the default tablespace */
6908
6909 /* Scan the tablespace link directory to find non-default tablespaces */
6910 dir = AllocateDir(tblspcdir);
6911
6912 while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6913 {
6914 if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6915 {
6916 /* Scan the tablespace dir for per-database dirs */
6917 snprintf(path, sizeof(path), "%s/%s/%s",
6920 }
6921 }
6922
6923 FreeDir(dir);
6924}
#define LOG
Definition elog.h:31
int FreeDir(DIR *dir)
Definition fd.c:3005
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition fd.c:2968
DIR * AllocateDir(const char *dirname)
Definition fd.c:2887
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition relcache.c:6928
#define PG_TBLSPC_DIR
Definition relpath.h:41
#define TABLESPACE_VERSION_DIRECTORY
Definition relpath.h:33
Definition dirent.c:26

References AllocateDir(), fb(), FreeDir(), LOG, MAXPGPATH, PG_TBLSPC_DIR, ReadDirExtended(), RelationCacheInitFileRemoveInDir(), RELCACHE_INIT_FILENAME, snprintf, TABLESPACE_VERSION_DIRECTORY, and unlink_initfile().

Referenced by StartupXLOG().

◆ RelationCacheInitFileRemoveInDir()

static void RelationCacheInitFileRemoveInDir ( const char tblspcpath)
static

Definition at line 6928 of file relcache.c.

6929{
6930 DIR *dir;
6931 struct dirent *de;
6932 char initfilename[MAXPGPATH * 2];
6933
6934 /* Scan the tablespace directory to find per-database directories */
6935 dir = AllocateDir(tblspcpath);
6936
6937 while ((de = ReadDirExtended(dir, tblspcpath, LOG)) != NULL)
6938 {
6939 if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6940 {
6941 /* Try to remove the init file in each database */
6942 snprintf(initfilename, sizeof(initfilename), "%s/%s/%s",
6945 }
6946 }
6947
6948 FreeDir(dir);
6949}

References AllocateDir(), fb(), FreeDir(), LOG, MAXPGPATH, ReadDirExtended(), RELCACHE_INIT_FILENAME, snprintf, and unlink_initfile().

Referenced by RelationCacheInitFileRemove().

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 3997 of file relcache.c.

3998{
3999 HASHCTL ctl;
4000 int allocsize;
4001
4002 /*
4003 * make sure cache memory context exists
4004 */
4005 if (!CacheMemoryContext)
4007
4008 /*
4009 * create hashtable that indexes the relcache
4010 */
4011 ctl.keysize = sizeof(Oid);
4012 ctl.entrysize = sizeof(RelIdCacheEnt);
4013 RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
4015
4016 /*
4017 * reserve enough in_progress_list slots for many cases
4018 */
4019 allocsize = 4;
4022 allocsize * sizeof(*in_progress_list));
4023 in_progress_list_maxlen = allocsize;
4024
4025 /*
4026 * relation mapper needs to be initialized too
4027 */
4029}
#define INITRELCACHESIZE
Definition relcache.c:3994
struct relidcacheent RelIdCacheEnt
void RelationMapInitialize(void)
Definition relmapper.c:651

References CacheMemoryContext, CreateCacheMemoryContext(), ctl, HASH_BLOBS, hash_create(), HASH_ELEM, in_progress_list, in_progress_list_maxlen, INITRELCACHESIZE, MemoryContextAlloc(), RelationIdCache, and RelationMapInitialize().

Referenced by InitPostgres().

◆ RelationCacheInitializePhase2()

void RelationCacheInitializePhase2 ( void  )

Definition at line 4043 of file relcache.c.

4044{
4046
4047 /*
4048 * relation mapper needs initialized too
4049 */
4051
4052 /*
4053 * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
4054 * nothing.
4055 */
4057 return;
4058
4059 /*
4060 * switch to cache memory context
4061 */
4063
4064 /*
4065 * Try to load the shared relcache cache file. If unsuccessful, bootstrap
4066 * the cache with pre-made descriptors for the critical shared catalogs.
4067 */
4068 if (!load_relcache_init_file(true))
4069 {
4070 formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
4072 formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
4074 formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
4076 formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
4078 formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
4080
4081#define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
4082 }
4083
4085}
static bool load_relcache_init_file(bool shared)
Definition relcache.c:6162
static const FormData_pg_attribute Desc_pg_shseclabel[Natts_pg_shseclabel]
Definition relcache.c:119
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
Definition relcache.c:1889
static const FormData_pg_attribute Desc_pg_database[Natts_pg_database]
Definition relcache.c:115
static const FormData_pg_attribute Desc_pg_authid[Natts_pg_authid]
Definition relcache.c:116
static const FormData_pg_attribute Desc_pg_subscription[Natts_pg_subscription]
Definition relcache.c:120
static const FormData_pg_attribute Desc_pg_auth_members[Natts_pg_auth_members]
Definition relcache.c:117
void RelationMapInitializePhase2(void)
Definition relmapper.c:671

References CacheMemoryContext, Desc_pg_auth_members, Desc_pg_authid, Desc_pg_database, Desc_pg_shseclabel, Desc_pg_subscription, fb(), formrdesc(), IsBootstrapProcessingMode, load_relcache_init_file(), MemoryContextSwitchTo(), and RelationMapInitializePhase2().

Referenced by InitPostgres().

◆ RelationCacheInitializePhase3()

void RelationCacheInitializePhase3 ( void  )

Definition at line 4102 of file relcache.c.

4103{
4104 HASH_SEQ_STATUS status;
4108
4109 /*
4110 * relation mapper needs initialized too
4111 */
4113
4114 /*
4115 * switch to cache memory context
4116 */
4118
4119 /*
4120 * Try to load the local relcache cache file. If unsuccessful, bootstrap
4121 * the cache with pre-made descriptors for the critical "nailed-in" system
4122 * catalogs.
4123 */
4126 {
4127 needNewCacheFile = true;
4128
4129 formrdesc("pg_class", RelationRelation_Rowtype_Id, false,
4131 formrdesc("pg_attribute", AttributeRelation_Rowtype_Id, false,
4133 formrdesc("pg_proc", ProcedureRelation_Rowtype_Id, false,
4135 formrdesc("pg_type", TypeRelation_Rowtype_Id, false,
4137
4138#define NUM_CRITICAL_LOCAL_RELS 4 /* fix if you change list above */
4139 }
4140
4142
4143 /* In bootstrap mode, the faked-up formrdesc info is all we'll have */
4145 return;
4146
4147 /*
4148 * If we didn't get the critical system indexes loaded into relcache, do
4149 * so now. These are critical because the catcache and/or opclass cache
4150 * depend on them for fetches done during relcache load. Thus, we have an
4151 * infinite-recursion problem. We can break the recursion by doing
4152 * heapscans instead of indexscans at certain key spots. To avoid hobbling
4153 * performance, we only want to do that until we have the critical indexes
4154 * loaded into relcache. Thus, the flag criticalRelcachesBuilt is used to
4155 * decide whether to do heapscan or indexscan at the key spots, and we set
4156 * it true after we've loaded the critical indexes.
4157 *
4158 * The critical indexes are marked as "nailed in cache", partly to make it
4159 * easy for load_relcache_init_file to count them, but mainly because we
4160 * cannot flush and rebuild them once we've set criticalRelcachesBuilt to
4161 * true. (NOTE: perhaps it would be possible to reload them by
4162 * temporarily setting criticalRelcachesBuilt to false again. For now,
4163 * though, we just nail 'em in.)
4164 *
4165 * RewriteRelRulenameIndexId and TriggerRelidNameIndexId are not critical
4166 * in the same way as the others, because the critical catalogs don't
4167 * (currently) have any rules or triggers, and so these indexes can be
4168 * rebuilt without inducing recursion. However they are used during
4169 * relcache load when a rel does have rules or triggers, so we choose to
4170 * nail them for performance reasons.
4171 */
4173 {
4188
4189#define NUM_CRITICAL_LOCAL_INDEXES 7 /* fix if you change list above */
4190
4192 }
4193
4194 /*
4195 * Process critical shared indexes too.
4196 *
4197 * DatabaseNameIndexId isn't critical for relcache loading, but rather for
4198 * initial lookup of MyDatabaseId, without which we'll never find any
4199 * non-shared catalogs at all. Autovacuum calls InitPostgres with a
4200 * database OID, so it instead depends on DatabaseOidIndexId. We also
4201 * need to nail up some indexes on pg_authid and pg_auth_members for use
4202 * during client authentication. SharedSecLabelObjectIndexId isn't
4203 * critical for the core system, but authentication hooks might be
4204 * interested in it.
4205 */
4207 {
4220
4221#define NUM_CRITICAL_SHARED_INDEXES 6 /* fix if you change list above */
4222
4224 }
4225
4226 /*
4227 * Now, scan all the relcache entries and update anything that might be
4228 * wrong in the results from formrdesc or the relcache cache file. If we
4229 * faked up relcache entries using formrdesc, then read the real pg_class
4230 * rows and replace the fake entries with them. Also, if any of the
4231 * relcache entries have rules, triggers, or security policies, load that
4232 * info the hard way since it isn't recorded in the cache file.
4233 *
4234 * Whenever we access the catalogs to read data, there is a possibility of
4235 * a shared-inval cache flush causing relcache entries to be removed.
4236 * Since hash_seq_search only guarantees to still work after the *current*
4237 * entry is removed, it's unsafe to continue the hashtable scan afterward.
4238 * We handle this by restarting the scan from scratch after each access.
4239 * This is theoretically O(N^2), but the number of entries that actually
4240 * need to be fixed is small enough that it doesn't matter.
4241 */
4243
4244 while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
4245 {
4246 Relation relation = idhentry->reldesc;
4247 bool restart = false;
4248
4249 /*
4250 * Make sure *this* entry doesn't get flushed while we work with it.
4251 */
4253
4254 /*
4255 * If it's a faked-up entry, read the real pg_class tuple.
4256 */
4257 if (relation->rd_rel->relowner == InvalidOid)
4258 {
4259 HeapTuple htup;
4261
4262 htup = SearchSysCache1(RELOID,
4264 if (!HeapTupleIsValid(htup))
4265 ereport(FATAL,
4267 errmsg_internal("cache lookup failed for relation %u",
4268 RelationGetRelid(relation)));
4269 relp = (Form_pg_class) GETSTRUCT(htup);
4270
4271 /*
4272 * Copy tuple to relation->rd_rel. (See notes in
4273 * AllocateRelationDesc())
4274 */
4275 memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
4276
4277 /* Update rd_options while we have the tuple */
4278 if (relation->rd_options)
4279 pfree(relation->rd_options);
4280 RelationParseRelOptions(relation, htup);
4281
4282 /*
4283 * Check the values in rd_att were set up correctly. (We cannot
4284 * just copy them over now: formrdesc must have set up the rd_att
4285 * data correctly to start with, because it may already have been
4286 * copied into one or more catcache entries.)
4287 */
4288 Assert(relation->rd_att->tdtypeid == relp->reltype);
4289 Assert(relation->rd_att->tdtypmod == -1);
4290
4291 ReleaseSysCache(htup);
4292
4293 /* relowner had better be OK now, else we'll loop forever */
4294 if (relation->rd_rel->relowner == InvalidOid)
4295 elog(ERROR, "invalid relowner in pg_class entry for \"%s\"",
4296 RelationGetRelationName(relation));
4297
4298 restart = true;
4299 }
4300
4301 /*
4302 * Fix data that isn't saved in relcache cache file.
4303 *
4304 * relhasrules or relhastriggers could possibly be wrong or out of
4305 * date. If we don't actually find any rules or triggers, clear the
4306 * local copy of the flag so that we don't get into an infinite loop
4307 * here. We don't make any attempt to fix the pg_class entry, though.
4308 */
4309 if (relation->rd_rel->relhasrules && relation->rd_rules == NULL)
4310 {
4311 RelationBuildRuleLock(relation);
4312 if (relation->rd_rules == NULL)
4313 relation->rd_rel->relhasrules = false;
4314 restart = true;
4315 }
4316 if (relation->rd_rel->relhastriggers && relation->trigdesc == NULL)
4317 {
4318 RelationBuildTriggers(relation);
4319 if (relation->trigdesc == NULL)
4320 relation->rd_rel->relhastriggers = false;
4321 restart = true;
4322 }
4323
4324 /*
4325 * Re-load the row security policies if the relation has them, since
4326 * they are not preserved in the cache. Note that we can never NOT
4327 * have a policy while relrowsecurity is true,
4328 * RelationBuildRowSecurity will create a single default-deny policy
4329 * if there is no policy defined in pg_policy.
4330 */
4331 if (relation->rd_rel->relrowsecurity && relation->rd_rsdesc == NULL)
4332 {
4333 RelationBuildRowSecurity(relation);
4334
4335 Assert(relation->rd_rsdesc != NULL);
4336 restart = true;
4337 }
4338
4339 /* Reload tableam data if needed */
4340 if (relation->rd_tableam == NULL &&
4341 (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind) || relation->rd_rel->relkind == RELKIND_SEQUENCE))
4342 {
4344 Assert(relation->rd_tableam != NULL);
4345
4346 restart = true;
4347 }
4348
4349 /* Release hold on the relation */
4351
4352 /* Now, restart the hashtable scan if needed */
4353 if (restart)
4354 {
4355 hash_seq_term(&status);
4357 }
4358 }
4359
4360 /*
4361 * Lastly, write out new relcache cache files if needed. We don't bother
4362 * to distinguish cases where only one of the two needs an update.
4363 */
4364 if (needNewCacheFile)
4365 {
4366 /*
4367 * Force all the catcaches to finish initializing and thereby open the
4368 * catalogs and indexes they use. This will preload the relcache with
4369 * entries for all the most important system catalogs and indexes, so
4370 * that the init files will be most useful for future backends.
4371 */
4373
4374 /* now write the files */
4377 }
4378}
void hash_seq_term(HASH_SEQ_STATUS *status)
Definition dynahash.c:1509
#define FATAL
Definition elog.h:41
void RelationDecrementReferenceCount(Relation rel)
Definition relcache.c:2195
static const FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute]
Definition relcache.c:112
static const FormData_pg_attribute Desc_pg_proc[Natts_pg_proc]
Definition relcache.c:113
static void write_relcache_init_file(bool shared)
Definition relcache.c:6580
static const FormData_pg_attribute Desc_pg_type[Natts_pg_type]
Definition relcache.c:114
static void load_critical_index(Oid indexoid, Oid heapoid)
Definition relcache.c:4387
void RelationMapInitializePhase3(void)
Definition relmapper.c:692
void InitCatalogCachePhase2(void)
Definition syscache.c:180

References Assert, CacheMemoryContext, CLASS_TUPLE_SIZE, criticalRelcachesBuilt, criticalSharedRelcachesBuilt, Desc_pg_attribute, Desc_pg_class, Desc_pg_proc, Desc_pg_type, elog, ereport, errcode(), errmsg_internal(), ERROR, FATAL, fb(), formrdesc(), GETSTRUCT(), hash_seq_init(), hash_seq_search(), hash_seq_term(), HeapTupleIsValid, InitCatalogCachePhase2(), InvalidOid, IsBootstrapProcessingMode, load_critical_index(), load_relcache_init_file(), MemoryContextSwitchTo(), ObjectIdGetDatum(), pfree(), RelationData::rd_att, RelationData::rd_options, RelationData::rd_rel, RelationData::rd_rsdesc, RelationData::rd_rules, RelationData::rd_tableam, RelationBuildRowSecurity(), RelationBuildRuleLock(), RelationBuildTriggers(), RelationDecrementReferenceCount(), RelationGetRelationName, RelationGetRelid, RelationIdCache, RelationIncrementReferenceCount(), RelationInitTableAccessMethod(), RelationMapInitializePhase3(), RelationParseRelOptions(), ReleaseSysCache(), SearchSysCache1(), TupleDescData::tdtypeid, TupleDescData::tdtypmod, RelationData::trigdesc, and write_relcache_init_file().

Referenced by InitPostgres().

◆ RelationCacheInvalidate()

void RelationCacheInvalidate ( bool  debug_discard)

Definition at line 2989 of file relcache.c.

2990{
2991 HASH_SEQ_STATUS status;
2993 Relation relation;
2995 List *rebuildList = NIL;
2996 ListCell *l;
2997 int i;
2998
2999 /*
3000 * Reload relation mapping data before starting to reconstruct cache.
3001 */
3003
3004 /* Phase 1 */
3006
3007 while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3008 {
3009 relation = idhentry->reldesc;
3010
3011 /*
3012 * Ignore new relations; no other backend will manipulate them before
3013 * we commit. Likewise, before replacing a relation's relfilelocator,
3014 * we shall have acquired AccessExclusiveLock and drained any
3015 * applicable pending invalidations.
3016 */
3017 if (relation->rd_createSubid != InvalidSubTransactionId ||
3019 continue;
3020
3022
3023 if (RelationHasReferenceCountZero(relation))
3024 {
3025 /* Delete this entry immediately */
3026 RelationClearRelation(relation);
3027 }
3028 else
3029 {
3030 /*
3031 * If it's a mapped relation, immediately update its rd_locator in
3032 * case its relfilenumber changed. We must do this during phase 1
3033 * in case the relation is consulted during rebuild of other
3034 * relcache entries in phase 2. It's safe since consulting the
3035 * map doesn't involve any access to relcache entries.
3036 */
3037 if (RelationIsMapped(relation))
3038 {
3039 RelationCloseSmgr(relation);
3040 RelationInitPhysicalAddr(relation);
3041 }
3042
3043 /*
3044 * Add this entry to list of stuff to rebuild in second pass.
3045 * pg_class goes to the front of rebuildFirstList while
3046 * pg_class_oid_index goes to the back of rebuildFirstList, so
3047 * they are done first and second respectively. Other nailed
3048 * relations go to the front of rebuildList, so they'll be done
3049 * next in no particular order; and everything else goes to the
3050 * back of rebuildList.
3051 */
3052 if (RelationGetRelid(relation) == RelationRelationId)
3054 else if (RelationGetRelid(relation) == ClassOidIndexId)
3056 else if (relation->rd_isnailed)
3057 rebuildList = lcons(relation, rebuildList);
3058 else
3059 rebuildList = lappend(rebuildList, relation);
3060 }
3061 }
3062
3063 /*
3064 * We cannot destroy the SMgrRelations as there might still be references
3065 * to them, but close the underlying file descriptors.
3066 */
3068
3069 /*
3070 * Phase 2: rebuild (or invalidate) the items found to need rebuild in
3071 * phase 1
3072 */
3073 foreach(l, rebuildFirstList)
3074 {
3075 relation = (Relation) lfirst(l);
3076 if (!IsTransactionState() || (relation->rd_isnailed && relation->rd_refcnt == 1))
3078 else
3079 RelationRebuildRelation(relation);
3080 }
3082 foreach(l, rebuildList)
3083 {
3084 relation = (Relation) lfirst(l);
3085 if (!IsTransactionState() || (relation->rd_isnailed && relation->rd_refcnt == 1))
3087 else
3088 RelationRebuildRelation(relation);
3089 }
3091
3092 if (!debug_discard)
3093 /* Any RelationBuildDesc() on the stack must start over. */
3094 for (i = 0; i < in_progress_list_len; i++)
3095 in_progress_list[i].invalidated = true;
3096}
List * lappend(List *list, void *datum)
Definition list.c:339
List * lcons(void *datum, List *list)
Definition list.c:495
void list_free(List *list)
Definition list.c:1546
#define RelationIsMapped(relation)
Definition rel.h:563
static void RelationCloseSmgr(Relation relation)
Definition rel.h:591
static void RelationRebuildRelation(Relation relation)
Definition relcache.c:2580
static long relcacheInvalsReceived
Definition relcache.c:154
static void RelationInvalidateRelation(Relation relation)
Definition relcache.c:2513
void RelationMapInvalidateAll(void)
Definition relmapper.c:490
void smgrreleaseall(void)
Definition smgr.c:412
bool IsTransactionState(void)
Definition xact.c:388

References fb(), hash_seq_init(), hash_seq_search(), i, in_progress_list, in_progress_list_len, InvalidSubTransactionId, IsTransactionState(), lappend(), lcons(), lfirst, list_free(), NIL, RelationData::rd_createSubid, RelationData::rd_firstRelfilelocatorSubid, RelationData::rd_isnailed, RelationData::rd_refcnt, RelationClearRelation(), RelationCloseSmgr(), RelationGetRelid, RelationHasReferenceCountZero, RelationIdCache, RelationInitPhysicalAddr(), RelationInvalidateRelation(), RelationIsMapped, RelationMapInvalidateAll(), RelationRebuildRelation(), relcacheInvalsReceived, and smgrreleaseall().

Referenced by InvalidateSystemCachesExtended(), and LocalExecuteInvalidationMessage().

◆ RelationCacheInvalidateEntry()

void RelationCacheInvalidateEntry ( Oid  relationId)

Definition at line 2933 of file relcache.c.

2934{
2935 Relation relation;
2936
2938
2939 if (relation)
2940 {
2942 RelationFlushRelation(relation);
2943 }
2944 else
2945 {
2946 int i;
2947
2948 for (i = 0; i < in_progress_list_len; i++)
2949 if (in_progress_list[i].reloid == relationId)
2951 }
2952}
#define RelationIdCacheLookup(ID, RELATION)
Definition relcache.c:231
static void RelationFlushRelation(Relation relation)
Definition relcache.c:2822

References fb(), i, in_progress_list, in_progress_list_len, inprogressent::invalidated, RelationFlushRelation(), RelationIdCacheLookup, and relcacheInvalsReceived.

Referenced by LocalExecuteInvalidationMessage().

◆ RelationClearRelation()

static void RelationClearRelation ( Relation  relation)
static

Definition at line 2541 of file relcache.c.

2542{
2544 Assert(!relation->rd_isnailed);
2545
2546 /*
2547 * Relations created in the same transaction must never be removed, see
2548 * RelationFlushRelation.
2549 */
2553
2554 /* first mark it as invalid */
2556
2557 /* Remove it from the hash table */
2558 RelationCacheDelete(relation);
2559
2560 /* And release storage */
2561 RelationDestroyRelation(relation, false);
2562}
#define RelationCacheDelete(RELATION)
Definition relcache.c:243

References Assert, InvalidSubTransactionId, RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_firstRelfilelocatorSubid, RelationData::rd_isnailed, RelationCacheDelete, RelationDestroyRelation(), RelationHasReferenceCountZero, and RelationInvalidateRelation().

Referenced by AtEOSubXact_cleanup(), AtEOXact_cleanup(), RelationCacheInvalidate(), RelationCloseCleanup(), RelationFlushRelation(), and RelationForgetRelation().

◆ RelationClose()

void RelationClose ( Relation  relation)

Definition at line 2215 of file relcache.c.

2216{
2217 /* Note: no locking manipulations needed */
2219
2220 RelationCloseCleanup(relation);
2221}
static void RelationCloseCleanup(Relation relation)
Definition relcache.c:2224

References RelationCloseCleanup(), and RelationDecrementReferenceCount().

Referenced by index_close(), init_tuple_slot(), maybe_send_schema(), pgoutput_change(), pgoutput_column_list_init(), pgoutput_row_filter_init(), relation_close(), RelationGetIdentityKeyBitmap(), ReorderBufferProcessTXN(), and ReorderBufferToastReplace().

◆ RelationCloseCleanup()

static void RelationCloseCleanup ( Relation  relation)
static

Definition at line 2224 of file relcache.c.

2225{
2226 /*
2227 * If the relation is no longer open in this session, we can clean up any
2228 * stale partition descriptors it has. This is unlikely, so check to see
2229 * if there are child contexts before expending a call to mcxt.c.
2230 */
2231 if (RelationHasReferenceCountZero(relation))
2232 {
2233 if (relation->rd_pdcxt != NULL &&
2234 relation->rd_pdcxt->firstchild != NULL)
2236
2237 if (relation->rd_pddcxt != NULL &&
2238 relation->rd_pddcxt->firstchild != NULL)
2240 }
2241
2242#ifdef RELCACHE_FORCE_RELEASE
2243 if (RelationHasReferenceCountZero(relation) &&
2246 RelationClearRelation(relation);
2247#endif
2248}
void MemoryContextDeleteChildren(MemoryContext context)
Definition mcxt.c:555
MemoryContext firstchild
Definition memnodes.h:128

References fb(), MemoryContextData::firstchild, InvalidSubTransactionId, MemoryContextDeleteChildren(), RelationData::rd_createSubid, RelationData::rd_firstRelfilelocatorSubid, RelationData::rd_pdcxt, RelationData::rd_pddcxt, RelationClearRelation(), and RelationHasReferenceCountZero.

Referenced by RelationClose(), and ResOwnerReleaseRelation().

◆ RelationDecrementReferenceCount()

void RelationDecrementReferenceCount ( Relation  rel)

Definition at line 2195 of file relcache.c.

2196{
2197 Assert(rel->rd_refcnt > 0);
2198 rel->rd_refcnt -= 1;
2201}
static void ResourceOwnerForgetRelationRef(ResourceOwner owner, Relation rel)
Definition relcache.c:2168
ResourceOwner CurrentResourceOwner
Definition resowner.c:173

References Assert, CurrentResourceOwner, IsBootstrapProcessingMode, RelationData::rd_refcnt, and ResourceOwnerForgetRelationRef().

Referenced by DestroyPartitionDirectory(), heap_endscan(), index_endscan(), RelationCacheInitializePhase3(), RelationClose(), and RelationFlushRelation().

◆ RelationDestroyRelation()

static void RelationDestroyRelation ( Relation  relation,
bool  remember_tupdesc 
)
static

Definition at line 2434 of file relcache.c.

2435{
2437
2438 /*
2439 * Make sure smgr and lower levels close the relation's files, if they
2440 * weren't closed already. (This was probably done by caller, but let's
2441 * just be real sure.)
2442 */
2443 RelationCloseSmgr(relation);
2444
2445 /* break mutual link with stats entry */
2446 pgstat_unlink_relation(relation);
2447
2448 /*
2449 * Free all the subsidiary data structures of the relcache entry, then the
2450 * entry itself.
2451 */
2452 if (relation->rd_rel)
2453 pfree(relation->rd_rel);
2454 /* can't use DecrTupleDescRefCount here */
2455 Assert(relation->rd_att->tdrefcount > 0);
2456 if (--relation->rd_att->tdrefcount == 0)
2457 {
2458 /*
2459 * If we Rebuilt a relcache entry during a transaction then its
2460 * possible we did that because the TupDesc changed as the result of
2461 * an ALTER TABLE that ran at less than AccessExclusiveLock. It's
2462 * possible someone copied that TupDesc, in which case the copy would
2463 * point to free'd memory. So if we rebuild an entry we keep the
2464 * TupDesc around until end of transaction, to be safe.
2465 */
2466 if (remember_tupdesc)
2468 else
2469 FreeTupleDesc(relation->rd_att);
2470 }
2471 FreeTriggerDesc(relation->trigdesc);
2472 list_free_deep(relation->rd_fkeylist);
2473 list_free(relation->rd_indexlist);
2474 list_free(relation->rd_statlist);
2475 bms_free(relation->rd_keyattr);
2476 bms_free(relation->rd_pkattr);
2477 bms_free(relation->rd_idattr);
2478 bms_free(relation->rd_hotblockingattr);
2479 bms_free(relation->rd_summarizedattr);
2480 if (relation->rd_pubdesc)
2481 pfree(relation->rd_pubdesc);
2482 if (relation->rd_options)
2483 pfree(relation->rd_options);
2484 if (relation->rd_indextuple)
2485 pfree(relation->rd_indextuple);
2486 if (relation->rd_amcache)
2487 pfree(relation->rd_amcache);
2488 if (relation->rd_fdwroutine)
2489 pfree(relation->rd_fdwroutine);
2490 if (relation->rd_indexcxt)
2492 if (relation->rd_rulescxt)
2494 if (relation->rd_rsdesc)
2496 if (relation->rd_partkeycxt)
2498 if (relation->rd_pdcxt)
2499 MemoryContextDelete(relation->rd_pdcxt);
2500 if (relation->rd_pddcxt)
2501 MemoryContextDelete(relation->rd_pddcxt);
2502 if (relation->rd_partcheckcxt)
2504 pfree(relation);
2505}
void bms_free(Bitmapset *a)
Definition bitmapset.c:239
void list_free_deep(List *list)
Definition list.c:1560
void pgstat_unlink_relation(Relation rel)
static void RememberToFreeTupleDescAtEOX(TupleDesc td)
Definition relcache.c:3099
Bitmapset * rd_hotblockingattr
Definition rel.h:165
Bitmapset * rd_summarizedattr
Definition rel.h:166
MemoryContext rscxt
Definition rowsecurity.h:33
void FreeTriggerDesc(TriggerDesc *trigdesc)
Definition trigger.c:2145

References Assert, bms_free(), fb(), FreeTriggerDesc(), FreeTupleDesc(), list_free(), list_free_deep(), MemoryContextDelete(), pfree(), pgstat_unlink_relation(), RelationData::rd_amcache, RelationData::rd_att, RelationData::rd_fdwroutine, RelationData::rd_fkeylist, RelationData::rd_hotblockingattr, RelationData::rd_idattr, RelationData::rd_indexcxt, RelationData::rd_indexlist, RelationData::rd_indextuple, RelationData::rd_keyattr, RelationData::rd_options, RelationData::rd_partcheckcxt, RelationData::rd_partkeycxt, RelationData::rd_pdcxt, RelationData::rd_pddcxt, RelationData::rd_pkattr, RelationData::rd_pubdesc, RelationData::rd_rel, RelationData::rd_rsdesc, RelationData::rd_rulescxt, RelationData::rd_statlist, RelationData::rd_summarizedattr, RelationCloseSmgr(), RelationHasReferenceCountZero, RememberToFreeTupleDescAtEOX(), RowSecurityDesc::rscxt, TupleDescData::tdrefcount, and RelationData::trigdesc.

Referenced by RelationBuildDesc(), RelationClearRelation(), and RelationRebuildRelation().

◆ RelationFlushRelation()

static void RelationFlushRelation ( Relation  relation)
static

Definition at line 2822 of file relcache.c.

2823{
2824 if (relation->rd_createSubid != InvalidSubTransactionId ||
2826 {
2827 /*
2828 * New relcache entries are always rebuilt, not flushed; else we'd
2829 * forget the "new" status of the relation. Ditto for the
2830 * new-relfilenumber status.
2831 */
2833 {
2834 /*
2835 * The rel could have zero refcnt here, so temporarily increment
2836 * the refcnt to ensure it's safe to rebuild it. We can assume
2837 * that the current transaction has some lock on the rel already.
2838 */
2840 RelationRebuildRelation(relation);
2842 }
2843 else
2845 }
2846 else
2847 {
2848 /*
2849 * Pre-existing rels can be dropped from the relcache if not open.
2850 *
2851 * If the entry is in use, rebuild it if possible. If we're not
2852 * inside a valid transaction, we can't do any catalog access so it's
2853 * not possible to rebuild yet. Just mark it as invalid in that case,
2854 * so that the rebuild will occur when the entry is next opened.
2855 *
2856 * Note: it's possible that we come here during subtransaction abort,
2857 * and the reason for wanting to rebuild is that the rel is open in
2858 * the outer transaction. In that case it might seem unsafe to not
2859 * rebuild immediately, since whatever code has the rel already open
2860 * will keep on using the relcache entry as-is. However, in such a
2861 * case the outer transaction should be holding a lock that's
2862 * sufficient to prevent any significant change in the rel's schema,
2863 * so the existing entry contents should be good enough for its
2864 * purposes; at worst we might be behind on statistics updates or the
2865 * like. (See also CheckTableNotInUse() and its callers.)
2866 */
2867 if (RelationHasReferenceCountZero(relation))
2868 RelationClearRelation(relation);
2869 else if (!IsTransactionState())
2871 else if (relation->rd_isnailed && relation->rd_refcnt == 1)
2872 {
2873 /*
2874 * A nailed relation with refcnt == 1 is unused. We cannot clear
2875 * it, but there's also no need no need to rebuild it immediately.
2876 */
2878 }
2879 else
2880 RelationRebuildRelation(relation);
2881 }
2882}

References InvalidSubTransactionId, IsTransactionState(), RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_firstRelfilelocatorSubid, RelationData::rd_isnailed, RelationData::rd_refcnt, RelationClearRelation(), RelationDecrementReferenceCount(), RelationHasReferenceCountZero, RelationIncrementReferenceCount(), RelationInvalidateRelation(), and RelationRebuildRelation().

Referenced by RelationCacheInvalidateEntry().

◆ RelationForgetRelation()

void RelationForgetRelation ( Oid  rid)

Definition at line 2888 of file relcache.c.

2889{
2890 Relation relation;
2891
2892 RelationIdCacheLookup(rid, relation);
2893
2894 if (!relation)
2895 return; /* not in cache, nothing to do */
2896
2897 if (!RelationHasReferenceCountZero(relation))
2898 elog(ERROR, "relation %u is still open", rid);
2899
2901 if (relation->rd_createSubid != InvalidSubTransactionId ||
2903 {
2904 /*
2905 * In the event of subtransaction rollback, we must not forget
2906 * rd_*Subid. Mark the entry "dropped" and invalidate it, instead of
2907 * destroying it right away. (If we're in a top transaction, we could
2908 * opt to destroy the entry.)
2909 */
2912 }
2913 else
2914 RelationClearRelation(relation);
2915}

References Assert, elog, ERROR, fb(), GetCurrentSubTransactionId(), InvalidSubTransactionId, RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_firstRelfilelocatorSubid, RelationClearRelation(), RelationHasReferenceCountZero, RelationIdCacheLookup, and RelationInvalidateRelation().

Referenced by heap_drop_with_catalog(), and index_drop().

◆ RelationGetDummyIndexExpressions()

List * RelationGetDummyIndexExpressions ( Relation  relation)

Definition at line 5151 of file relcache.c.

5152{
5153 List *result;
5155 bool isnull;
5156 char *exprsString;
5157 List *rawExprs;
5158 ListCell *lc;
5159
5160 /* Quick exit if there is nothing to do. */
5161 if (relation->rd_indextuple == NULL ||
5163 return NIL;
5164
5165 /* Extract raw node tree(s) from index tuple. */
5169 &isnull);
5170 Assert(!isnull);
5174
5175 /* Construct null Consts; the typlen and typbyval are arbitrary. */
5176 result = NIL;
5177 foreach(lc, rawExprs)
5178 {
5179 Node *rawExpr = (Node *) lfirst(lc);
5180
5181 result = lappend(result,
5185 1,
5186 (Datum) 0,
5187 true,
5188 true));
5189 }
5190
5191 return result;
5192}
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition heaptuple.c:456
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition makefuncs.c:350
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
int32 exprTypmod(const Node *expr)
Definition nodeFuncs.c:301
Oid exprCollation(const Node *expr)
Definition nodeFuncs.c:821
static TupleDesc GetPgIndexDescriptor(void)
Definition relcache.c:4468

References Assert, exprCollation(), exprType(), exprTypmod(), fb(), GetPgIndexDescriptor(), heap_attisnull(), heap_getattr(), lappend(), lfirst, makeConst(), NIL, pfree(), RelationData::rd_indextuple, stringToNode(), and TextDatumGetCString.

Referenced by BuildDummyIndexInfo().

◆ RelationGetExclusionInfo()

void RelationGetExclusionInfo ( Relation  indexRelation,
Oid **  operators,
Oid **  procs,
uint16 **  strategies 
)

Definition at line 5648 of file relcache.c.

5652{
5653 int indnkeyatts;
5654 Oid *ops;
5655 Oid *funcs;
5656 uint16 *strats;
5659 ScanKeyData skey[1];
5660 HeapTuple htup;
5661 bool found;
5663 int i;
5664
5666
5667 /* Allocate result space in caller context */
5668 *operators = ops = palloc_array(Oid, indnkeyatts);
5669 *procs = funcs = palloc_array(Oid, indnkeyatts);
5671
5672 /* Quick exit if we have the data cached already */
5673 if (indexRelation->rd_exclstrats != NULL)
5674 {
5675 memcpy(ops, indexRelation->rd_exclops, sizeof(Oid) * indnkeyatts);
5676 memcpy(funcs, indexRelation->rd_exclprocs, sizeof(Oid) * indnkeyatts);
5677 memcpy(strats, indexRelation->rd_exclstrats, sizeof(uint16) * indnkeyatts);
5678 return;
5679 }
5680
5681 /*
5682 * Search pg_constraint for the constraint associated with the index. To
5683 * make this not too painfully slow, we use the index on conrelid; that
5684 * will hold the parent relation's OID not the index's own OID.
5685 *
5686 * Note: if we wanted to rely on the constraint name matching the index's
5687 * name, we could just do a direct lookup using pg_constraint's unique
5688 * index. For the moment it doesn't seem worth requiring that.
5689 */
5690 ScanKeyInit(&skey[0],
5693 ObjectIdGetDatum(indexRelation->rd_index->indrelid));
5694
5697 NULL, 1, skey);
5698 found = false;
5699
5701 {
5703 Datum val;
5704 bool isnull;
5705 ArrayType *arr;
5706 int nelem;
5707
5708 /* We want the exclusion constraint owning the index */
5709 if ((conform->contype != CONSTRAINT_EXCLUSION &&
5710 !(conform->conperiod && (conform->contype == CONSTRAINT_PRIMARY
5711 || conform->contype == CONSTRAINT_UNIQUE))) ||
5712 conform->conindid != RelationGetRelid(indexRelation))
5713 continue;
5714
5715 /* There should be only one */
5716 if (found)
5717 elog(ERROR, "unexpected exclusion constraint record found for rel %s",
5718 RelationGetRelationName(indexRelation));
5719 found = true;
5720
5721 /* Extract the operator OIDS from conexclop */
5722 val = fastgetattr(htup,
5724 conrel->rd_att, &isnull);
5725 if (isnull)
5726 elog(ERROR, "null conexclop for rel %s",
5727 RelationGetRelationName(indexRelation));
5728
5729 arr = DatumGetArrayTypeP(val); /* ensure not toasted */
5730 nelem = ARR_DIMS(arr)[0];
5731 if (ARR_NDIM(arr) != 1 ||
5732 nelem != indnkeyatts ||
5733 ARR_HASNULL(arr) ||
5734 ARR_ELEMTYPE(arr) != OIDOID)
5735 elog(ERROR, "conexclop is not a 1-D Oid array");
5736
5737 memcpy(ops, ARR_DATA_PTR(arr), sizeof(Oid) * indnkeyatts);
5738 }
5739
5742
5743 if (!found)
5744 elog(ERROR, "exclusion constraint record missing for rel %s",
5745 RelationGetRelationName(indexRelation));
5746
5747 /* We need the func OIDs and strategy numbers too */
5748 for (i = 0; i < indnkeyatts; i++)
5749 {
5750 funcs[i] = get_opcode(ops[i]);
5752 indexRelation->rd_opfamily[i]);
5753 /* shouldn't fail, since it was checked at index creation */
5754 if (strats[i] == InvalidStrategy)
5755 elog(ERROR, "could not find strategy for operator %u in family %u",
5756 ops[i], indexRelation->rd_opfamily[i]);
5757 }
5758
5759 /* Save a copy of the results in the relcache entry. */
5760 oldcxt = MemoryContextSwitchTo(indexRelation->rd_indexcxt);
5761 indexRelation->rd_exclops = palloc_array(Oid, indnkeyatts);
5762 indexRelation->rd_exclprocs = palloc_array(Oid, indnkeyatts);
5763 indexRelation->rd_exclstrats = palloc_array(uint16, indnkeyatts);
5764 memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * indnkeyatts);
5765 memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * indnkeyatts);
5766 memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * indnkeyatts);
5768}
#define ARR_NDIM(a)
Definition array.h:290
#define DatumGetArrayTypeP(X)
Definition array.h:261
#define ARR_ELEMTYPE(a)
Definition array.h:292
#define ARR_HASNULL(a)
Definition array.h:291
uint16_t uint16
Definition c.h:555
RegProcedure get_opcode(Oid opno)
Definition lsyscache.c:1435
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition lsyscache.c:85
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition rel.h:533
#define InvalidStrategy
Definition stratnum.h:24

References AccessShareLock, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, BTEqualStrategyNumber, DatumGetArrayTypeP, elog, ERROR, fastgetattr(), fb(), get_op_opfamily_strategy(), get_opcode(), GETSTRUCT(), HeapTupleIsValid, i, IndexRelationGetNumberOfKeyAttributes, InvalidStrategy, MemoryContextSwitchTo(), ObjectIdGetDatum(), palloc_array, RelationData::rd_exclops, RelationData::rd_exclprocs, RelationData::rd_exclstrats, RelationData::rd_index, RelationData::rd_indexcxt, RelationData::rd_opfamily, RelationGetRelationName, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), and val.

Referenced by BuildIndexInfo(), and CheckIndexCompatible().

◆ RelationGetFKeyList()

List * RelationGetFKeyList ( Relation  relation)

Definition at line 4726 of file relcache.c.

4727{
4728 List *result;
4732 HeapTuple htup;
4733 List *oldlist;
4735
4736 /* Quick exit if we already computed the list. */
4737 if (relation->rd_fkeyvalid)
4738 return relation->rd_fkeylist;
4739
4740 /*
4741 * We build the list we intend to return (in the caller's context) while
4742 * doing the scan. After successfully completing the scan, we copy that
4743 * list into the relcache entry. This avoids cache-context memory leakage
4744 * if we get some sort of error partway through.
4745 */
4746 result = NIL;
4747
4748 /* Prepare to scan pg_constraint for entries having conrelid = this rel. */
4753
4756 NULL, 1, &skey);
4757
4759 {
4760 Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(htup);
4761 ForeignKeyCacheInfo *info;
4762
4763 /* consider only foreign keys */
4764 if (constraint->contype != CONSTRAINT_FOREIGN)
4765 continue;
4766
4768 info->conoid = constraint->oid;
4769 info->conrelid = constraint->conrelid;
4770 info->confrelid = constraint->confrelid;
4771 info->conenforced = constraint->conenforced;
4772
4773 DeconstructFkConstraintRow(htup, &info->nkeys,
4774 info->conkey,
4775 info->confkey,
4776 info->conpfeqop,
4777 NULL, NULL, NULL, NULL);
4778
4779 /* Add FK's node to the result list */
4780 result = lappend(result, info);
4781 }
4782
4785
4786 /* Now save a copy of the completed list in the relcache entry. */
4788 oldlist = relation->rd_fkeylist;
4789 relation->rd_fkeylist = copyObject(result);
4790 relation->rd_fkeyvalid = true;
4792
4793 /* Don't leak the old list, if there is one */
4795
4796 return result;
4797}
#define copyObject(obj)
Definition nodes.h:232
#define makeNode(_type_)
Definition nodes.h:161
void DeconstructFkConstraintRow(HeapTuple tuple, int *numfks, AttrNumber *conkey, AttrNumber *confkey, Oid *pf_eq_oprs, Oid *pp_eq_oprs, Oid *ff_eq_oprs, int *num_fk_del_set_cols, AttrNumber *fk_del_set_cols)

References AccessShareLock, BTEqualStrategyNumber, CacheMemoryContext, ForeignKeyCacheInfo::conenforced, ForeignKeyCacheInfo::confrelid, ForeignKeyCacheInfo::conoid, ForeignKeyCacheInfo::conrelid, copyObject, DeconstructFkConstraintRow(), fb(), GETSTRUCT(), HeapTupleIsValid, lappend(), list_free_deep(), makeNode, MemoryContextSwitchTo(), NIL, ForeignKeyCacheInfo::nkeys, ObjectIdGetDatum(), RelationData::rd_fkeylist, RelationData::rd_fkeyvalid, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by addFkRecurseReferencing(), CloneFkReferencing(), DetachPartitionFinalize(), and get_relation_foreign_keys().

◆ RelationGetIdentityKeyBitmap()

Bitmapset * RelationGetIdentityKeyBitmap ( Relation  relation)

Definition at line 5571 of file relcache.c.

5572{
5573 Bitmapset *idindexattrs = NULL; /* columns in the replica identity */
5575 int i;
5578
5579 /* Quick exit if we already computed the result */
5580 if (relation->rd_idattr != NULL)
5581 return bms_copy(relation->rd_idattr);
5582
5583 /* Fast path if definitely no indexes */
5584 if (!RelationGetForm(relation)->relhasindex)
5585 return NULL;
5586
5587 /* Historic snapshot must be set. */
5589
5591
5592 /* Fall out if there is no replica identity index */
5593 if (!OidIsValid(replidindex))
5594 return NULL;
5595
5596 /* Look up the description for the replica identity index */
5598
5600 elog(ERROR, "could not open relation with OID %u",
5601 relation->rd_replidindex);
5602
5603 /* Add referenced attributes to idindexattrs */
5604 for (i = 0; i < indexDesc->rd_index->indnatts; i++)
5605 {
5606 int attrnum = indexDesc->rd_index->indkey.values[i];
5607
5608 /*
5609 * We don't include non-key columns into idindexattrs bitmaps. See
5610 * RelationGetIndexAttrBitmap.
5611 */
5612 if (attrnum != 0)
5613 {
5614 if (i < indexDesc->rd_index->indnkeyatts)
5617 }
5618 }
5619
5621
5622 /* Don't leak the old values of these bitmaps, if any */
5623 bms_free(relation->rd_idattr);
5624 relation->rd_idattr = NULL;
5625
5626 /* Now save copy of the bitmap in the relcache entry */
5628 relation->rd_idattr = bms_copy(idindexattrs);
5630
5631 /* We return our original working copy for caller to play with */
5632 return idindexattrs;
5633}
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:814
Bitmapset * bms_copy(const Bitmapset *a)
Definition bitmapset.c:122
#define RelationGetForm(relation)
Definition rel.h:508
#define RelationIsValid(relation)
Definition rel.h:489
Oid RelationGetReplicaIndex(Relation relation)
Definition relcache.c:5067
Relation RelationIdGetRelation(Oid relationId)
Definition relcache.c:2094
void RelationClose(Relation relation)
Definition relcache.c:2215
bool HistoricSnapshotActive(void)
Definition snapmgr.c:1692
#define FirstLowInvalidHeapAttributeNumber
Definition sysattr.h:27

References Assert, bms_add_member(), bms_copy(), bms_free(), CacheMemoryContext, elog, ERROR, fb(), FirstLowInvalidHeapAttributeNumber, HistoricSnapshotActive(), i, MemoryContextSwitchTo(), OidIsValid, RelationData::rd_idattr, RelationData::rd_replidindex, RelationClose(), RelationGetForm, RelationGetReplicaIndex(), RelationIdGetRelation(), and RelationIsValid.

Referenced by logicalrep_write_attrs().

◆ RelationGetIndexAttOptions()

bytea ** RelationGetIndexAttOptions ( Relation  relation,
bool  copy 
)

Definition at line 5983 of file relcache.c.

5984{
5986 bytea **opts = relation->rd_opcoptions;
5987 Oid relid = RelationGetRelid(relation);
5988 int natts = RelationGetNumberOfAttributes(relation); /* XXX
5989 * IndexRelationGetNumberOfKeyAttributes */
5990 int i;
5991
5992 /* Try to copy cached options. */
5993 if (opts)
5994 return copy ? CopyIndexAttOptions(opts, natts) : opts;
5995
5996 /* Get and parse opclass options. */
5997 opts = palloc0_array(bytea *, natts);
5998
5999 for (i = 0; i < natts; i++)
6000 {
6002 {
6003 Datum attoptions = get_attoptions(relid, i + 1);
6004
6005 opts[i] = index_opclass_options(relation, i + 1, attoptions, false);
6006
6007 if (attoptions != (Datum) 0)
6008 pfree(DatumGetPointer(attoptions));
6009 }
6010 }
6011
6012 /* Copy parsed options to the cache. */
6014 relation->rd_opcoptions = CopyIndexAttOptions(opts, natts);
6016
6017 if (copy)
6018 return opts;
6019
6020 for (i = 0; i < natts; i++)
6021 {
6022 if (opts[i])
6023 pfree(opts[i]);
6024 }
6025
6026 pfree(opts);
6027
6028 return relation->rd_opcoptions;
6029}
#define palloc0_array(type, count)
Definition fe_memutils.h:77
bytea * index_opclass_options(Relation indrel, AttrNumber attnum, Datum attoptions, bool validate)
Definition indexam.c:1048
Datum get_attoptions(Oid relid, int16 attnum)
Definition lsyscache.c:1046
static bytea ** CopyIndexAttOptions(bytea **srcopts, int natts)
Definition relcache.c:5963

References CopyIndexAttOptions(), criticalRelcachesBuilt, DatumGetPointer(), fb(), get_attoptions(), i, index_opclass_options(), MemoryContextSwitchTo(), opts, palloc0_array, pfree(), RelationData::rd_indexcxt, RelationData::rd_opcoptions, RelationGetNumberOfAttributes, and RelationGetRelid.

Referenced by get_relation_info(), index_getprocinfo(), load_critical_index(), and RelationInitIndexAccessInfo().

◆ RelationGetIndexAttrBitmap()

Bitmapset * RelationGetIndexAttrBitmap ( Relation  relation,
IndexAttrBitmapKind  attrKind 
)

Definition at line 5298 of file relcache.c.

5299{
5300 Bitmapset *uindexattrs; /* columns in unique indexes */
5301 Bitmapset *pkindexattrs; /* columns in the primary index */
5302 Bitmapset *idindexattrs; /* columns in the replica identity */
5303 Bitmapset *hotblockingattrs; /* columns with HOT blocking indexes */
5304 Bitmapset *summarizedattrs; /* columns with summarizing indexes */
5309 ListCell *l;
5311
5312 /* Quick exit if we already computed the result. */
5313 if (relation->rd_attrsvalid)
5314 {
5315 switch (attrKind)
5316 {
5318 return bms_copy(relation->rd_keyattr);
5320 return bms_copy(relation->rd_pkattr);
5322 return bms_copy(relation->rd_idattr);
5324 return bms_copy(relation->rd_hotblockingattr);
5326 return bms_copy(relation->rd_summarizedattr);
5327 default:
5328 elog(ERROR, "unknown attrKind %u", attrKind);
5329 }
5330 }
5331
5332 /* Fast path if definitely no indexes */
5333 if (!RelationGetForm(relation)->relhasindex)
5334 return NULL;
5335
5336 /*
5337 * Get cached list of index OIDs. If we have to start over, we do so here.
5338 */
5339restart:
5341
5342 /* Fall out if no indexes (but relhasindex was set) */
5343 if (indexoidlist == NIL)
5344 return NULL;
5345
5346 /*
5347 * Copy the rd_pkindex and rd_replidindex values computed by
5348 * RelationGetIndexList before proceeding. This is needed because a
5349 * relcache flush could occur inside index_open below, resetting the
5350 * fields managed by RelationGetIndexList. We need to do the work with
5351 * stable values of these fields.
5352 */
5353 relpkindex = relation->rd_pkindex;
5354 relreplindex = relation->rd_replidindex;
5355
5356 /*
5357 * For each index, add referenced attributes to indexattrs.
5358 *
5359 * Note: we consider all indexes returned by RelationGetIndexList, even if
5360 * they are not indisready or indisvalid. This is important because an
5361 * index for which CREATE INDEX CONCURRENTLY has just started must be
5362 * included in HOT-safety decisions (see README.HOT). If a DROP INDEX
5363 * CONCURRENTLY is far enough along that we should ignore the index, it
5364 * won't be returned at all by RelationGetIndexList.
5365 */
5366 uindexattrs = NULL;
5371 foreach(l, indexoidlist)
5372 {
5373 Oid indexOid = lfirst_oid(l);
5375 Datum datum;
5376 bool isnull;
5379 int i;
5380 bool isKey; /* candidate key */
5381 bool isPK; /* primary key */
5382 bool isIDKey; /* replica identity index */
5383 Bitmapset **attrs;
5384
5386
5387 /*
5388 * Extract index expressions and index predicate. Note: Don't use
5389 * RelationGetIndexExpressions()/RelationGetIndexPredicate(), because
5390 * those might run constant expressions evaluation, which needs a
5391 * snapshot, which we might not have here. (Also, it's probably more
5392 * sound to collect the bitmaps before any transformations that might
5393 * eliminate columns, but the practical impact of this is limited.)
5394 */
5395
5396 datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indexprs,
5397 GetPgIndexDescriptor(), &isnull);
5398 if (!isnull)
5400 else
5402
5403 datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indpred,
5404 GetPgIndexDescriptor(), &isnull);
5405 if (!isnull)
5407 else
5409
5410 /* Can this index be referenced by a foreign key? */
5411 isKey = indexDesc->rd_index->indisunique &&
5414
5415 /* Is this a primary key? */
5416 isPK = (indexOid == relpkindex);
5417
5418 /* Is this index the configured (or default) replica identity? */
5419 isIDKey = (indexOid == relreplindex);
5420
5421 /*
5422 * If the index is summarizing, it doesn't block HOT updates, but we
5423 * may still need to update it (if the attributes were modified). So
5424 * decide which bitmap we'll update in the following loop.
5425 */
5426 if (indexDesc->rd_indam->amsummarizing)
5428 else
5430
5431 /* Collect simple attribute references */
5432 for (i = 0; i < indexDesc->rd_index->indnatts; i++)
5433 {
5434 int attrnum = indexDesc->rd_index->indkey.values[i];
5435
5436 /*
5437 * Since we have covering indexes with non-key columns, we must
5438 * handle them accurately here. non-key columns must be added into
5439 * hotblockingattrs or summarizedattrs, since they are in index,
5440 * and update shouldn't miss them.
5441 *
5442 * Summarizing indexes do not block HOT, but do need to be updated
5443 * when the column value changes, thus require a separate
5444 * attribute bitmapset.
5445 *
5446 * Obviously, non-key columns couldn't be referenced by foreign
5447 * key or identity key. Hence we do not include them into
5448 * uindexattrs, pkindexattrs and idindexattrs bitmaps.
5449 */
5450 if (attrnum != 0)
5451 {
5454
5455 if (isKey && i < indexDesc->rd_index->indnkeyatts)
5458
5459 if (isPK && i < indexDesc->rd_index->indnkeyatts)
5462
5463 if (isIDKey && i < indexDesc->rd_index->indnkeyatts)
5466 }
5467 }
5468
5469 /* Collect all attributes used in expressions, too */
5471
5472 /* Collect all attributes in the index predicate, too */
5474
5476 }
5477
5478 /*
5479 * During one of the index_opens in the above loop, we might have received
5480 * a relcache flush event on this relcache entry, which might have been
5481 * signaling a change in the rel's index list. If so, we'd better start
5482 * over to ensure we deliver up-to-date attribute bitmaps.
5483 */
5486 relpkindex == relation->rd_pkindex &&
5487 relreplindex == relation->rd_replidindex)
5488 {
5489 /* Still the same index set, so proceed */
5492 }
5493 else
5494 {
5495 /* Gotta do it over ... might as well not leak memory */
5503
5504 goto restart;
5505 }
5506
5507 /* Don't leak the old values of these bitmaps, if any */
5508 relation->rd_attrsvalid = false;
5509 bms_free(relation->rd_keyattr);
5510 relation->rd_keyattr = NULL;
5511 bms_free(relation->rd_pkattr);
5512 relation->rd_pkattr = NULL;
5513 bms_free(relation->rd_idattr);
5514 relation->rd_idattr = NULL;
5515 bms_free(relation->rd_hotblockingattr);
5516 relation->rd_hotblockingattr = NULL;
5517 bms_free(relation->rd_summarizedattr);
5518 relation->rd_summarizedattr = NULL;
5519
5520 /*
5521 * Now save copies of the bitmaps in the relcache entry. We intentionally
5522 * set rd_attrsvalid last, because that's the one that signals validity of
5523 * the values; if we run out of memory before making that copy, we won't
5524 * leave the relcache entry looking like the other ones are valid but
5525 * empty.
5526 */
5528 relation->rd_keyattr = bms_copy(uindexattrs);
5529 relation->rd_pkattr = bms_copy(pkindexattrs);
5530 relation->rd_idattr = bms_copy(idindexattrs);
5533 relation->rd_attrsvalid = true;
5535
5536 /* We return our original working copy for caller to play with */
5537 switch (attrKind)
5538 {
5540 return uindexattrs;
5542 return pkindexattrs;
5544 return idindexattrs;
5546 return hotblockingattrs;
5548 return summarizedattrs;
5549 default:
5550 elog(ERROR, "unknown attrKind %u", attrKind);
5551 return NULL;
5552 }
5553}
void index_close(Relation relation, LOCKMODE lockmode)
Definition indexam.c:177
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition indexam.c:133
List * RelationGetIndexList(Relation relation)
Definition relcache.c:4831
@ INDEX_ATTR_BITMAP_KEY
Definition relcache.h:69
@ INDEX_ATTR_BITMAP_HOT_BLOCKING
Definition relcache.h:72
@ INDEX_ATTR_BITMAP_PRIMARY_KEY
Definition relcache.h:70
@ INDEX_ATTR_BITMAP_SUMMARIZED
Definition relcache.h:73
@ INDEX_ATTR_BITMAP_IDENTITY_KEY
Definition relcache.h:71
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition var.c:296

References AccessShareLock, bms_add_member(), bms_copy(), bms_free(), CacheMemoryContext, elog, equal(), ERROR, fb(), FirstLowInvalidHeapAttributeNumber, GetPgIndexDescriptor(), heap_getattr(), i, INDEX_ATTR_BITMAP_HOT_BLOCKING, INDEX_ATTR_BITMAP_IDENTITY_KEY, INDEX_ATTR_BITMAP_KEY, INDEX_ATTR_BITMAP_PRIMARY_KEY, INDEX_ATTR_BITMAP_SUMMARIZED, index_close(), index_open(), lfirst_oid, list_free(), MemoryContextSwitchTo(), NIL, pull_varattnos(), RelationData::rd_attrsvalid, RelationData::rd_hotblockingattr, RelationData::rd_idattr, RelationData::rd_keyattr, RelationData::rd_pkattr, RelationData::rd_pkindex, RelationData::rd_replidindex, RelationData::rd_summarizedattr, RelationGetForm, RelationGetIndexList(), stringToNode(), and TextDatumGetCString.

Referenced by dropconstraint_internal(), ExecUpdateLockMode(), ExtractReplicaIdentity(), GetParentedForeignKeyRefs(), heap_update(), logicalrep_rel_mark_updatable(), pub_contains_invalid_column(), pub_rf_contains_invalid_column(), and RelationFindDeletedTupleInfoSeq().

◆ RelationGetIndexExpressions()

List * RelationGetIndexExpressions ( Relation  relation)

Definition at line 5092 of file relcache.c.

5093{
5094 List *result;
5096 bool isnull;
5097 char *exprsString;
5099
5100 /* Quick exit if we already computed the result. */
5101 if (relation->rd_indexprs)
5102 return copyObject(relation->rd_indexprs);
5103
5104 /* Quick exit if there is nothing to do. */
5105 if (relation->rd_indextuple == NULL ||
5107 return NIL;
5108
5109 /*
5110 * We build the tree we intend to return in the caller's context. After
5111 * successfully completing the work, we copy it into the relcache entry.
5112 * This avoids problems if we get some sort of error partway through.
5113 */
5117 &isnull);
5118 Assert(!isnull);
5120 result = (List *) stringToNode(exprsString);
5122
5123 /*
5124 * Run the expressions through eval_const_expressions. This is not just an
5125 * optimization, but is necessary, because the planner will be comparing
5126 * them to similarly-processed qual clauses, and may fail to detect valid
5127 * matches without this. We must not use canonicalize_qual, however,
5128 * since these aren't qual expressions.
5129 */
5130 result = (List *) eval_const_expressions(NULL, (Node *) result);
5131
5132 /* May as well fix opfuncids too */
5133 fix_opfuncids((Node *) result);
5134
5135 /* Now save a copy of the completed tree in the relcache entry. */
5137 relation->rd_indexprs = copyObject(result);
5139
5140 return result;
5141}
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition clauses.c:2270
void fix_opfuncids(Node *node)
Definition nodeFuncs.c:1840

References Assert, copyObject, eval_const_expressions(), fb(), fix_opfuncids(), GetPgIndexDescriptor(), heap_attisnull(), heap_getattr(), MemoryContextSwitchTo(), NIL, pfree(), RelationData::rd_indexcxt, RelationData::rd_indexprs, RelationData::rd_indextuple, stringToNode(), and TextDatumGetCString.

Referenced by ATExecReplicaIdentity(), BuildIndexInfo(), get_relation_info(), GetIndexInputType(), index_unchanged_by_update(), infer_arbiter_indexes(), IsIndexCompatibleAsArbiter(), plan_create_index_workers(), ReindexRelationConcurrently(), statatt_get_index_expr(), and transformIndexConstraint().

◆ RelationGetIndexList()

List * RelationGetIndexList ( Relation  relation)

Definition at line 4831 of file relcache.c.

4832{
4836 HeapTuple htup;
4837 List *result;
4838 List *oldlist;
4839 char replident = relation->rd_rel->relreplident;
4842 bool pkdeferrable = false;
4844
4845 /* Quick exit if we already computed the list. */
4846 if (relation->rd_indexvalid)
4847 return list_copy(relation->rd_indexlist);
4848
4849 /*
4850 * We build the list we intend to return (in the caller's context) while
4851 * doing the scan. After successfully completing the scan, we copy that
4852 * list into the relcache entry. This avoids cache-context memory leakage
4853 * if we get some sort of error partway through.
4854 */
4855 result = NIL;
4856
4857 /* Prepare to scan pg_index for entries having indrelid = this rel. */
4862
4865 NULL, 1, &skey);
4866
4868 {
4870
4871 /*
4872 * Ignore any indexes that are currently being dropped. This will
4873 * prevent them from being searched, inserted into, or considered in
4874 * HOT-safety decisions. It's unsafe to touch such an index at all
4875 * since its catalog entries could disappear at any instant.
4876 */
4877 if (!index->indislive)
4878 continue;
4879
4880 /* add index's OID to result list */
4881 result = lappend_oid(result, index->indexrelid);
4882
4883 /*
4884 * Non-unique or predicate indexes aren't interesting for either oid
4885 * indexes or replication identity indexes, so don't check them.
4886 * Deferred ones are not useful for replication identity either; but
4887 * we do include them if they are PKs.
4888 */
4889 if (!index->indisunique ||
4891 continue;
4892
4893 /*
4894 * Remember primary key index, if any. For regular tables we do this
4895 * only if the index is valid; but for partitioned tables, then we do
4896 * it even if it's invalid.
4897 *
4898 * The reason for returning invalid primary keys for partitioned
4899 * tables is that we need it to prevent drop of not-null constraints
4900 * that may underlie such a primary key, which is only a problem for
4901 * partitioned tables.
4902 */
4903 if (index->indisprimary &&
4904 (index->indisvalid ||
4905 relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
4906 {
4907 pkeyIndex = index->indexrelid;
4908 pkdeferrable = !index->indimmediate;
4909 }
4910
4911 if (!index->indimmediate)
4912 continue;
4913
4914 if (!index->indisvalid)
4915 continue;
4916
4917 /* remember explicitly chosen replica index */
4918 if (index->indisreplident)
4919 candidateIndex = index->indexrelid;
4920 }
4921
4923
4925
4926 /* Sort the result list into OID order, per API spec. */
4927 list_sort(result, list_oid_cmp);
4928
4929 /* Now save a copy of the completed list in the relcache entry. */
4931 oldlist = relation->rd_indexlist;
4932 relation->rd_indexlist = list_copy(result);
4933 relation->rd_pkindex = pkeyIndex;
4934 relation->rd_ispkdeferrable = pkdeferrable;
4936 relation->rd_replidindex = pkeyIndex;
4937 else if (replident == REPLICA_IDENTITY_INDEX && OidIsValid(candidateIndex))
4938 relation->rd_replidindex = candidateIndex;
4939 else
4940 relation->rd_replidindex = InvalidOid;
4941 relation->rd_indexvalid = true;
4943
4944 /* Don't leak the old list, if there is one */
4946
4947 return result;
4948}
void list_sort(List *list, list_sort_comparator cmp)
Definition list.c:1674
List * list_copy(const List *oldlist)
Definition list.c:1573
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
int list_oid_cmp(const ListCell *p1, const ListCell *p2)
Definition list.c:1703
bool rd_ispkdeferrable
Definition rel.h:154
Definition type.h:96

References AccessShareLock, BTEqualStrategyNumber, CacheMemoryContext, fb(), GETSTRUCT(), heap_attisnull(), HeapTupleIsValid, InvalidOid, lappend_oid(), list_copy(), list_free(), list_oid_cmp(), list_sort(), MemoryContextSwitchTo(), NIL, ObjectIdGetDatum(), OidIsValid, RelationData::rd_indexlist, RelationData::rd_indexvalid, RelationData::rd_ispkdeferrable, RelationData::rd_pkindex, RelationData::rd_rel, RelationData::rd_replidindex, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by AlterIndexNamespaces(), apply_handle_delete_internal(), apply_handle_insert_internal(), ATExecChangeOwner(), ATExecSetTableSpace(), AttachPartitionEnsureIndexes(), calculate_indexes_size(), calculate_toast_table_size(), cluster(), DefineIndex(), DefineRelation(), DetachPartitionFinalize(), do_analyze_rel(), ExecOpenIndices(), expandTableLikeClause(), FindUsableIndexForReplicaIdentityFull(), get_relation_info(), GetParentedForeignKeyRefs(), index_get_partition(), infer_arbiter_indexes(), mark_index_clustered(), refresh_by_match_merge(), RefreshMatViewByOid(), reindex_relation(), ReindexRelationConcurrently(), relation_mark_replica_identity(), RelationGetIndexAttrBitmap(), RelationGetPrimaryKeyIndex(), RelationGetReplicaIndex(), relationHasPrimaryKey(), RelationTruncateIndexes(), SetIndexStorageProperties(), toast_open_indexes(), transformFkeyCheckAttrs(), transformFkeyGetPrimaryKey(), triggered_change_notification(), and vac_open_indexes().

◆ RelationGetIndexPredicate()

List * RelationGetIndexPredicate ( Relation  relation)

Definition at line 5205 of file relcache.c.

5206{
5207 List *result;
5209 bool isnull;
5210 char *predString;
5212
5213 /* Quick exit if we already computed the result. */
5214 if (relation->rd_indpred)
5215 return copyObject(relation->rd_indpred);
5216
5217 /* Quick exit if there is nothing to do. */
5218 if (relation->rd_indextuple == NULL ||
5220 return NIL;
5221
5222 /*
5223 * We build the tree we intend to return in the caller's context. After
5224 * successfully completing the work, we copy it into the relcache entry.
5225 * This avoids problems if we get some sort of error partway through.
5226 */
5230 &isnull);
5231 Assert(!isnull);
5233 result = (List *) stringToNode(predString);
5235
5236 /*
5237 * Run the expression through const-simplification and canonicalization.
5238 * This is not just an optimization, but is necessary, because the planner
5239 * will be comparing it to similarly-processed qual clauses, and may fail
5240 * to detect valid matches without this. This must match the processing
5241 * done to qual clauses in preprocess_expression()! (We can skip the
5242 * stuff involving subqueries, however, since we don't allow any in index
5243 * predicates.)
5244 */
5245 result = (List *) eval_const_expressions(NULL, (Node *) result);
5246
5247 result = (List *) canonicalize_qual((Expr *) result, false);
5248
5249 /* Also convert to implicit-AND format */
5250 result = make_ands_implicit((Expr *) result);
5251
5252 /* May as well fix opfuncids too */
5253 fix_opfuncids((Node *) result);
5254
5255 /* Now save a copy of the completed tree in the relcache entry. */
5257 relation->rd_indpred = copyObject(result);
5259
5260 return result;
5261}
List * make_ands_implicit(Expr *clause)
Definition makefuncs.c:810
Expr * canonicalize_qual(Expr *qual, bool is_check)
Definition prepqual.c:293

References Assert, canonicalize_qual(), copyObject, eval_const_expressions(), fb(), fix_opfuncids(), GetPgIndexDescriptor(), heap_attisnull(), heap_getattr(), make_ands_implicit(), MemoryContextSwitchTo(), NIL, pfree(), RelationData::rd_indexcxt, RelationData::rd_indextuple, RelationData::rd_indpred, stringToNode(), and TextDatumGetCString.

Referenced by ATExecReplicaIdentity(), BuildIndexInfo(), get_relation_info(), infer_arbiter_indexes(), is_usable_unique_index(), IsIndexCompatibleAsArbiter(), plan_create_index_workers(), ReindexRelationConcurrently(), and transformIndexConstraint().

◆ RelationGetPrimaryKeyIndex()

Oid RelationGetPrimaryKeyIndex ( Relation  relation,
bool  deferrable_ok 
)

Definition at line 5042 of file relcache.c.

5043{
5044 List *ilist;
5045
5046 if (!relation->rd_indexvalid)
5047 {
5048 /* RelationGetIndexList does the heavy lifting. */
5049 ilist = RelationGetIndexList(relation);
5051 Assert(relation->rd_indexvalid);
5052 }
5053
5054 if (deferrable_ok)
5055 return relation->rd_pkindex;
5056 else if (relation->rd_ispkdeferrable)
5057 return InvalidOid;
5058 return relation->rd_pkindex;
5059}

References Assert, fb(), InvalidOid, list_free(), RelationData::rd_indexvalid, RelationData::rd_ispkdeferrable, RelationData::rd_pkindex, and RelationGetIndexList().

Referenced by dropconstraint_internal(), and GetRelationIdentityOrPK().

◆ RelationGetReplicaIndex()

Oid RelationGetReplicaIndex ( Relation  relation)

Definition at line 5067 of file relcache.c.

5068{
5069 List *ilist;
5070
5071 if (!relation->rd_indexvalid)
5072 {
5073 /* RelationGetIndexList does the heavy lifting. */
5074 ilist = RelationGetIndexList(relation);
5076 Assert(relation->rd_indexvalid);
5077 }
5078
5079 return relation->rd_replidindex;
5080}

References Assert, fb(), list_free(), RelationData::rd_indexvalid, RelationData::rd_replidindex, and RelationGetIndexList().

Referenced by CheckCmdReplicaIdentity(), GetRelationIdentityOrPK(), pg_get_replica_identity_index(), and RelationGetIdentityKeyBitmap().

◆ RelationGetStatExtList()

List * RelationGetStatExtList ( Relation  relation)

Definition at line 4972 of file relcache.c.

4973{
4977 HeapTuple htup;
4978 List *result;
4979 List *oldlist;
4981
4982 /* Quick exit if we already computed the list. */
4983 if (relation->rd_statvalid != 0)
4984 return list_copy(relation->rd_statlist);
4985
4986 /*
4987 * We build the list we intend to return (in the caller's context) while
4988 * doing the scan. After successfully completing the scan, we copy that
4989 * list into the relcache entry. This avoids cache-context memory leakage
4990 * if we get some sort of error partway through.
4991 */
4992 result = NIL;
4993
4994 /*
4995 * Prepare to scan pg_statistic_ext for entries having stxrelid = this
4996 * rel.
4997 */
5002
5005 NULL, 1, &skey);
5006
5008 {
5009 Oid oid = ((Form_pg_statistic_ext) GETSTRUCT(htup))->oid;
5010
5011 result = lappend_oid(result, oid);
5012 }
5013
5015
5017
5018 /* Sort the result list into OID order, per API spec. */
5019 list_sort(result, list_oid_cmp);
5020
5021 /* Now save a copy of the completed list in the relcache entry. */
5023 oldlist = relation->rd_statlist;
5024 relation->rd_statlist = list_copy(result);
5025
5026 relation->rd_statvalid = true;
5028
5029 /* Don't leak the old list, if there is one */
5031
5032 return result;
5033}
FormData_pg_statistic_ext * Form_pg_statistic_ext

References AccessShareLock, BTEqualStrategyNumber, CacheMemoryContext, fb(), GETSTRUCT(), HeapTupleIsValid, lappend_oid(), list_copy(), list_free(), list_oid_cmp(), list_sort(), MemoryContextSwitchTo(), NIL, ObjectIdGetDatum(), RelationData::rd_statlist, RelationData::rd_statvalid, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by expandTableLikeClause(), and get_relation_statistics().

◆ RelationIdGetRelation()

Relation RelationIdGetRelation ( Oid  relationId)

Definition at line 2094 of file relcache.c.

2095{
2096 Relation rd;
2097
2099
2100 /*
2101 * first try to find reldesc in the cache
2102 */
2104
2105 if (RelationIsValid(rd))
2106 {
2107 /* return NULL for dropped relations */
2108 if (rd->rd_droppedSubid != InvalidSubTransactionId)
2109 {
2110 Assert(!rd->rd_isvalid);
2111 return NULL;
2112 }
2113
2115 /* revalidate cache entry if necessary */
2116 if (!rd->rd_isvalid)
2117 {
2119
2120 /*
2121 * Normally entries need to be valid here, but before the relcache
2122 * has been initialized, not enough infrastructure exists to
2123 * perform pg_class lookups. The structure of such entries doesn't
2124 * change, but we still want to update the rd_rel entry. So
2125 * rd_isvalid = false is left in place for a later lookup.
2126 */
2127 Assert(rd->rd_isvalid ||
2128 (rd->rd_isnailed && !criticalRelcachesBuilt));
2129 }
2130 return rd;
2131 }
2132
2133 /*
2134 * no reldesc in the cache, so have RelationBuildDesc() build one and add
2135 * it.
2136 */
2138 if (RelationIsValid(rd))
2140 return rd;
2141}
static void AssertCouldGetRelation(void)
Definition relcache.h:44

References Assert, AssertCouldGetRelation(), criticalRelcachesBuilt, fb(), InvalidSubTransactionId, RelationBuildDesc(), RelationIdCacheLookup, RelationIncrementReferenceCount(), RelationIsValid, and RelationRebuildRelation().

Referenced by check_and_init_gencol(), init_tuple_slot(), maybe_send_schema(), pgoutput_change(), pgoutput_column_list_init(), pgoutput_ensure_entry_cxt(), pgoutput_row_filter_init(), relation_open(), RelationGetIdentityKeyBitmap(), ReorderBufferProcessTXN(), ReorderBufferToastReplace(), and try_relation_open().

◆ RelationIdIsInInitFile()

bool RelationIdIsInInitFile ( Oid  relationId)

Definition at line 6815 of file relcache.c.

6816{
6821 {
6822 /*
6823 * If this Assert fails, we don't need the applicable special case
6824 * anymore.
6825 */
6827 return true;
6828 }
6830}
bool RelationSupportsSysCache(Oid relid)
Definition syscache.c:762

References Assert, fb(), and RelationSupportsSysCache().

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

◆ RelationIncrementReferenceCount()

◆ RelationInitIndexAccessInfo()

void RelationInitIndexAccessInfo ( Relation  relation)

Definition at line 1440 of file relcache.c.

1441{
1442 HeapTuple tuple;
1447 bool isnull;
1452 MemoryContext oldcontext;
1453 int indnatts;
1454 int indnkeyatts;
1455 uint16 amsupport;
1456
1457 /*
1458 * Make a copy of the pg_index entry for the index. Since pg_index
1459 * contains variable-length and possibly-null fields, we have to do this
1460 * honestly rather than just treating it as a Form_pg_index struct.
1461 */
1464 if (!HeapTupleIsValid(tuple))
1465 elog(ERROR, "cache lookup failed for index %u",
1466 RelationGetRelid(relation));
1468 relation->rd_indextuple = heap_copytuple(tuple);
1469 relation->rd_index = (Form_pg_index) GETSTRUCT(relation->rd_indextuple);
1470 MemoryContextSwitchTo(oldcontext);
1471 ReleaseSysCache(tuple);
1472
1473 /*
1474 * Look up the index's access method, save the OID of its handler function
1475 */
1476 Assert(relation->rd_rel->relam != InvalidOid);
1477 tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(relation->rd_rel->relam));
1478 if (!HeapTupleIsValid(tuple))
1479 elog(ERROR, "cache lookup failed for access method %u",
1480 relation->rd_rel->relam);
1481 aform = (Form_pg_am) GETSTRUCT(tuple);
1482 relation->rd_amhandler = aform->amhandler;
1483 ReleaseSysCache(tuple);
1484
1487 elog(ERROR, "relnatts disagrees with indnatts for index %u",
1488 RelationGetRelid(relation));
1490
1491 /*
1492 * Make the private context to hold index access info. The reason we need
1493 * a context, and not just a couple of pallocs, is so that we won't leak
1494 * any subsidiary info attached to fmgr lookup records.
1495 */
1497 "index info",
1499 relation->rd_indexcxt = indexcxt;
1501 RelationGetRelationName(relation));
1502
1503 /*
1504 * Now we can fetch the index AM's API struct
1505 */
1506 InitIndexAmRoutine(relation);
1507
1508 /*
1509 * Allocate arrays to hold data. Opclasses are not used for included
1510 * columns, so allocate them for indnkeyatts only.
1511 */
1512 relation->rd_opfamily = (Oid *)
1514 relation->rd_opcintype = (Oid *)
1516
1517 amsupport = relation->rd_indam->amsupport;
1518 if (amsupport > 0)
1519 {
1520 int nsupport = indnatts * amsupport;
1521
1522 relation->rd_support = (RegProcedure *)
1524 relation->rd_supportinfo = (FmgrInfo *)
1526 }
1527 else
1528 {
1529 relation->rd_support = NULL;
1530 relation->rd_supportinfo = NULL;
1531 }
1532
1533 relation->rd_indcollation = (Oid *)
1535
1536 relation->rd_indoption = (int16 *)
1538
1539 /*
1540 * indcollation cannot be referenced directly through the C struct,
1541 * because it comes after the variable-width indkey field. Must extract
1542 * the datum the hard way...
1543 */
1547 &isnull);
1548 Assert(!isnull);
1550 memcpy(relation->rd_indcollation, indcoll->values, indnkeyatts * sizeof(Oid));
1551
1552 /*
1553 * indclass cannot be referenced directly through the C struct, because it
1554 * comes after the variable-width indkey field. Must extract the datum
1555 * the hard way...
1556 */
1560 &isnull);
1561 Assert(!isnull);
1563
1564 /*
1565 * Fill the support procedure OID array, as well as the info about
1566 * opfamilies and opclass input types. (aminfo and supportinfo are left
1567 * as zeroes, and are filled on-the-fly when used)
1568 */
1570 relation->rd_opfamily, relation->rd_opcintype,
1571 amsupport, indnkeyatts);
1572
1573 /*
1574 * Similarly extract indoption and copy it to the cache entry
1575 */
1579 &isnull);
1580 Assert(!isnull);
1582 memcpy(relation->rd_indoption, indoption->values, indnkeyatts * sizeof(int16));
1583
1584 (void) RelationGetIndexAttOptions(relation, false);
1585
1586 /*
1587 * expressions, predicate, exclusion caches will be filled later
1588 */
1589 relation->rd_indexprs = NIL;
1590 relation->rd_indpred = NIL;
1591 relation->rd_exclops = NULL;
1592 relation->rd_exclprocs = NULL;
1593 relation->rd_exclstrats = NULL;
1594 relation->rd_amcache = NULL;
1595}
HeapTuple heap_copytuple(HeapTuple tuple)
Definition heaptuple.c:778
FormData_pg_am * Form_pg_am
Definition pg_am.h:48
#define IndexRelationGetNumberOfAttributes(relation)
Definition rel.h:526
static void IndexSupportInitialize(oidvector *indclass, RegProcedure *indexSupport, Oid *opFamily, Oid *opcInType, StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber)
Definition relcache.c:1611
Definition c.h:755

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, IndexAmRoutine::amsupport, Assert, CacheMemoryContext, DatumGetPointer(), elog, ERROR, fastgetattr(), fb(), GetPgIndexDescriptor(), GETSTRUCT(), heap_copytuple(), HeapTupleIsValid, IndexRelationGetNumberOfAttributes, IndexRelationGetNumberOfKeyAttributes, IndexSupportInitialize(), InitIndexAmRoutine(), InvalidOid, MemoryContextAllocZero(), MemoryContextCopyAndSetIdentifier, MemoryContextSwitchTo(), NIL, ObjectIdGetDatum(), RelationData::rd_amcache, RelationData::rd_amhandler, RelationData::rd_exclops, RelationData::rd_exclprocs, RelationData::rd_exclstrats, RelationData::rd_indam, RelationData::rd_indcollation, RelationData::rd_index, RelationData::rd_indexcxt, RelationData::rd_indexprs, RelationData::rd_indextuple, RelationData::rd_indoption, RelationData::rd_indpred, RelationData::rd_opcintype, RelationData::rd_opfamily, RelationData::rd_rel, RelationData::rd_support, RelationData::rd_supportinfo, RelationGetIndexAttOptions(), RelationGetNumberOfAttributes, RelationGetRelationName, RelationGetRelid, ReleaseSysCache(), and SearchSysCache1().

Referenced by index_create(), and RelationBuildDesc().

◆ RelationInitPhysicalAddr()

static void RelationInitPhysicalAddr ( Relation  relation)
static

Definition at line 1339 of file relcache.c.

1340{
1342
1343 /* these relations kinds never have storage */
1344 if (!RELKIND_HAS_STORAGE(relation->rd_rel->relkind))
1345 return;
1346
1347 if (relation->rd_rel->reltablespace)
1348 relation->rd_locator.spcOid = relation->rd_rel->reltablespace;
1349 else
1351 if (relation->rd_locator.spcOid == GLOBALTABLESPACE_OID)
1352 relation->rd_locator.dbOid = InvalidOid;
1353 else
1354 relation->rd_locator.dbOid = MyDatabaseId;
1355
1356 if (relation->rd_rel->relfilenode)
1357 {
1358 /*
1359 * Even if we are using a decoding snapshot that doesn't represent the
1360 * current state of the catalog we need to make sure the filenode
1361 * points to the current file since the older file will be gone (or
1362 * truncated). The new file will still contain older rows so lookups
1363 * in them will work correctly. This wouldn't work correctly if
1364 * rewrites were allowed to change the schema in an incompatible way,
1365 * but those are prevented both on catalog tables and on user tables
1366 * declared as additional catalog tables.
1367 */
1370 && IsTransactionState())
1371 {
1374
1376 RelationGetRelid(relation) != ClassOidIndexId,
1377 true);
1379 elog(ERROR, "could not find pg_class entry for %u",
1380 RelationGetRelid(relation));
1382
1383 relation->rd_rel->reltablespace = physrel->reltablespace;
1384 relation->rd_rel->relfilenode = physrel->relfilenode;
1386 }
1387
1388 relation->rd_locator.relNumber = relation->rd_rel->relfilenode;
1389 }
1390 else
1391 {
1392 /* Consult the relation mapper */
1393 relation->rd_locator.relNumber =
1395 relation->rd_rel->relisshared);
1397 elog(ERROR, "could not find relation mapping for relation \"%s\", OID %u",
1398 RelationGetRelationName(relation), relation->rd_id);
1399 }
1400
1401 /*
1402 * For RelationNeedsWAL() to answer correctly on parallel workers, restore
1403 * rd_firstRelfilelocatorSubid. No subtransactions start or end while in
1404 * parallel mode, so the specific SubTransactionId does not matter.
1405 */
1406 if (IsParallelWorker() && oldnumber != relation->rd_locator.relNumber)
1407 {
1410 else
1412 }
1413}
#define TopSubTransactionId
Definition c.h:683
Oid MyDatabaseTableSpace
Definition globals.c:96
Oid MyDatabaseId
Definition globals.c:94
#define IsParallelWorker()
Definition parallel.h:60
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition rel.h:693
RelFileNumber RelationMapOidToFilenumber(Oid relationId, bool shared)
Definition relmapper.c:165
Oid RelFileNumber
Definition relpath.h:25
#define RelFileNumberIsValid(relnumber)
Definition relpath.h:27
bool RelFileLocatorSkippingWAL(RelFileLocator rlocator)
Definition storage.c:573
RelFileNumber relNumber
Oid rd_id
Definition rel.h:113
RelFileLocator rd_locator
Definition rel.h:57

References RelFileLocator::dbOid, elog, ERROR, fb(), GETSTRUCT(), heap_freetuple(), HeapTupleIsValid, HistoricSnapshotActive(), InvalidOid, InvalidSubTransactionId, IsParallelWorker, IsTransactionState(), MyDatabaseId, MyDatabaseTableSpace, RelationData::rd_firstRelfilelocatorSubid, RelationData::rd_id, RelationData::rd_locator, RelationData::rd_rel, RelationGetRelationName, RelationGetRelid, RelationIsAccessibleInLogicalDecoding, RelationMapOidToFilenumber(), RelFileLocatorSkippingWAL(), RelFileNumberIsValid, RelFileLocator::relNumber, ScanPgRelation(), RelFileLocator::spcOid, and TopSubTransactionId.

Referenced by formrdesc(), load_relcache_init_file(), RelationBuildDesc(), RelationBuildLocalRelation(), RelationCacheInvalidate(), RelationReloadIndexInfo(), and RelationReloadNailed().

◆ RelationInitTableAccessMethod()

void RelationInitTableAccessMethod ( Relation  relation)

Definition at line 1824 of file relcache.c.

1825{
1826 HeapTuple tuple;
1828
1829 if (relation->rd_rel->relkind == RELKIND_SEQUENCE)
1830 {
1831 /*
1832 * Sequences are currently accessed like heap tables, but it doesn't
1833 * seem prudent to show that in the catalog. So just overwrite it
1834 * here.
1835 */
1836 Assert(relation->rd_rel->relam == InvalidOid);
1838 }
1839 else if (IsCatalogRelation(relation))
1840 {
1841 /*
1842 * Avoid doing a syscache lookup for catalog tables.
1843 */
1844 Assert(relation->rd_rel->relam == HEAP_TABLE_AM_OID);
1846 }
1847 else
1848 {
1849 /*
1850 * Look up the table access method, save the OID of its handler
1851 * function.
1852 */
1853 Assert(relation->rd_rel->relam != InvalidOid);
1854 tuple = SearchSysCache1(AMOID,
1855 ObjectIdGetDatum(relation->rd_rel->relam));
1856 if (!HeapTupleIsValid(tuple))
1857 elog(ERROR, "cache lookup failed for access method %u",
1858 relation->rd_rel->relam);
1859 aform = (Form_pg_am) GETSTRUCT(tuple);
1860 relation->rd_amhandler = aform->amhandler;
1861 ReleaseSysCache(tuple);
1862 }
1863
1864 /*
1865 * Now we can fetch the table AM's API struct
1866 */
1867 InitTableAmRoutine(relation);
1868}
static void InitTableAmRoutine(Relation relation)
Definition relcache.c:1815

References Assert, elog, ERROR, fb(), GETSTRUCT(), HeapTupleIsValid, InitTableAmRoutine(), InvalidOid, IsCatalogRelation(), ObjectIdGetDatum(), RelationData::rd_amhandler, RelationData::rd_rel, ReleaseSysCache(), and SearchSysCache1().

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

◆ RelationInvalidateRelation()

static void RelationInvalidateRelation ( Relation  relation)
static

Definition at line 2513 of file relcache.c.

2514{
2515 /*
2516 * Make sure smgr and lower levels close the relation's files, if they
2517 * weren't closed already. If the relation is not getting deleted, the
2518 * next smgr access should reopen the files automatically. This ensures
2519 * that the low-level file access state is updated after, say, a vacuum
2520 * truncation.
2521 */
2522 RelationCloseSmgr(relation);
2523
2524 /* Free AM cached data, if any */
2525 if (relation->rd_amcache)
2526 pfree(relation->rd_amcache);
2527 relation->rd_amcache = NULL;
2528
2529 relation->rd_isvalid = false;
2530}

References fb(), pfree(), RelationData::rd_amcache, RelationData::rd_isvalid, and RelationCloseSmgr().

Referenced by RelationCacheInvalidate(), RelationClearRelation(), RelationFlushRelation(), RelationForgetRelation(), and RelationRebuildRelation().

◆ RelationParseRelOptions()

static void RelationParseRelOptions ( Relation  relation,
HeapTuple  tuple 
)
static

Definition at line 468 of file relcache.c.

469{
470 bytea *options;
472
473 relation->rd_options = NULL;
474
475 /*
476 * Look up any AM-specific parse function; fall out if relkind should not
477 * have options.
478 */
479 switch (relation->rd_rel->relkind)
480 {
481 case RELKIND_RELATION:
483 case RELKIND_VIEW:
484 case RELKIND_MATVIEW:
486 amoptsfn = NULL;
487 break;
488 case RELKIND_INDEX:
490 amoptsfn = relation->rd_indam->amoptions;
491 break;
492 default:
493 return;
494 }
495
496 /*
497 * Fetch reloptions from tuple; have to use a hardwired descriptor because
498 * we might not have any other for pg_class yet (consider executing this
499 * code for pg_class itself)
500 */
502
503 /*
504 * Copy parsed data into CacheMemoryContext. To guard against the
505 * possibility of leaks in the reloptions code, we want to do the actual
506 * parsing in the caller's memory context and copy the results into
507 * CacheMemoryContext after the fact.
508 */
509 if (options)
510 {
514 pfree(options);
515 }
516}
bytea *(* amoptions_function)(Datum reloptions, bool validate)
Definition amapi.h:165
static TupleDesc GetPgClassDescriptor(void)
Definition relcache.c:4455
bytea * extractRelOptions(HeapTuple tuple, TupleDesc tupdesc, amoptions_function amoptions)
amoptions_function amoptions
Definition amapi.h:304

References IndexAmRoutine::amoptions, CacheMemoryContext, extractRelOptions(), fb(), GetPgClassDescriptor(), MemoryContextAlloc(), pfree(), RelationData::rd_indam, RelationData::rd_options, RelationData::rd_rel, and VARSIZE().

Referenced by RelationBuildDesc(), RelationCacheInitializePhase3(), and RelationReloadIndexInfo().

◆ RelationRebuildRelation()

static void RelationRebuildRelation ( Relation  relation)
static

Definition at line 2580 of file relcache.c.

2581{
2584 /* there is no reason to ever rebuild a dropped relation */
2586
2587 /* Close and mark it as invalid until we've finished the rebuild */
2589
2590 /*
2591 * Indexes only have a limited number of possible schema changes, and we
2592 * don't want to use the full-blown procedure because it's a headache for
2593 * indexes that reload itself depends on.
2594 *
2595 * As an exception, use the full procedure if the index access info hasn't
2596 * been initialized yet. Index creation relies on that: it first builds
2597 * the relcache entry with RelationBuildLocalRelation(), creates the
2598 * pg_index tuple only after that, and then relies on
2599 * CommandCounterIncrement to load the pg_index contents.
2600 */
2601 if ((relation->rd_rel->relkind == RELKIND_INDEX ||
2602 relation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX) &&
2603 relation->rd_indexcxt != NULL)
2604 {
2605 RelationReloadIndexInfo(relation);
2606 return;
2607 }
2608 /* Nailed relations are handled separately. */
2609 else if (relation->rd_isnailed)
2610 {
2611 RelationReloadNailed(relation);
2612 return;
2613 }
2614 else
2615 {
2616 /*
2617 * Our strategy for rebuilding an open relcache entry is to build a
2618 * new entry from scratch, swap its contents with the old entry, and
2619 * finally delete the new entry (along with any infrastructure swapped
2620 * over from the old entry). This is to avoid trouble in case an
2621 * error causes us to lose control partway through. The old entry
2622 * will still be marked !rd_isvalid, so we'll try to rebuild it again
2623 * on next access. Meanwhile it's not any less valid than it was
2624 * before, so any code that might expect to continue accessing it
2625 * isn't hurt by the rebuild failure. (Consider for example a
2626 * subtransaction that ALTERs a table and then gets canceled partway
2627 * through the cache entry rebuild. The outer transaction should
2628 * still see the not-modified cache entry as valid.) The worst
2629 * consequence of an error is leaking the necessarily-unreferenced new
2630 * entry, and this shouldn't happen often enough for that to be a big
2631 * problem.
2632 *
2633 * When rebuilding an open relcache entry, we must preserve ref count,
2634 * rd_*Subid, and rd_toastoid state. Also attempt to preserve the
2635 * pg_class entry (rd_rel), tupledesc, rewrite-rule, partition key,
2636 * and partition descriptor substructures in place, because various
2637 * places assume that these structures won't move while they are
2638 * working with an open relcache entry. (Note: the refcount
2639 * mechanism for tupledescs might someday allow us to remove this hack
2640 * for the tupledesc.)
2641 *
2642 * Note that this process does not touch CurrentResourceOwner; which
2643 * is good because whatever ref counts the entry may have do not
2644 * necessarily belong to that resource owner.
2645 */
2647 Oid save_relid = RelationGetRelid(relation);
2648 bool keep_tupdesc;
2649 bool keep_rules;
2650 bool keep_policies;
2651 bool keep_partkey;
2652
2653 /* Build temporary entry, but don't link it into hashtable */
2655
2656 /*
2657 * Between here and the end of the swap, don't add code that does or
2658 * reasonably could read system catalogs. That range must be free
2659 * from invalidation processing. See RelationBuildDesc() manipulation
2660 * of in_progress_list.
2661 */
2662
2663 if (newrel == NULL)
2664 {
2665 /*
2666 * We can validly get here, if we're using a historic snapshot in
2667 * which a relation, accessed from outside logical decoding, is
2668 * still invisible. In that case it's fine to just mark the
2669 * relation as invalid and return - it'll fully get reloaded by
2670 * the cache reset at the end of logical decoding (or at the next
2671 * access). During normal processing we don't want to ignore this
2672 * case as it shouldn't happen there, as explained below.
2673 */
2675 return;
2676
2677 /*
2678 * This shouldn't happen as dropping a relation is intended to be
2679 * impossible if still referenced (cf. CheckTableNotInUse()). But
2680 * if we get here anyway, we can't just delete the relcache entry,
2681 * as it possibly could get accessed later (as e.g. the error
2682 * might get trapped and handled via a subtransaction rollback).
2683 */
2684 elog(ERROR, "relation %u deleted while still in use", save_relid);
2685 }
2686
2687 /*
2688 * If we were to, again, have cases of the relkind of a relcache entry
2689 * changing, we would need to ensure that pgstats does not get
2690 * confused.
2691 */
2692 Assert(relation->rd_rel->relkind == newrel->rd_rel->relkind);
2693
2694 keep_tupdesc = equalTupleDescs(relation->rd_att, newrel->rd_att);
2695 keep_rules = equalRuleLocks(relation->rd_rules, newrel->rd_rules);
2696 keep_policies = equalRSDesc(relation->rd_rsdesc, newrel->rd_rsdesc);
2697 /* partkey is immutable once set up, so we can always keep it */
2698 keep_partkey = (relation->rd_partkey != NULL);
2699
2700 /*
2701 * Perform swapping of the relcache entry contents. Within this
2702 * process the old entry is momentarily invalid, so there *must* be no
2703 * possibility of CHECK_FOR_INTERRUPTS within this sequence. Do it in
2704 * all-in-line code for safety.
2705 *
2706 * Since the vast majority of fields should be swapped, our method is
2707 * to swap the whole structures and then re-swap those few fields we
2708 * didn't want swapped.
2709 */
2710#define SWAPFIELD(fldtype, fldname) \
2711 do { \
2712 fldtype _tmp = newrel->fldname; \
2713 newrel->fldname = relation->fldname; \
2714 relation->fldname = _tmp; \
2715 } while (0)
2716
2717 /* swap all Relation struct fields */
2718 {
2720
2721 memcpy(&tmpstruct, newrel, sizeof(RelationData));
2722 memcpy(newrel, relation, sizeof(RelationData));
2723 memcpy(relation, &tmpstruct, sizeof(RelationData));
2724 }
2725
2726 /* rd_smgr must not be swapped, due to back-links from smgr level */
2727 SWAPFIELD(SMgrRelation, rd_smgr);
2728 /* rd_refcnt must be preserved */
2729 SWAPFIELD(int, rd_refcnt);
2730 /* isnailed shouldn't change */
2731 Assert(newrel->rd_isnailed == relation->rd_isnailed);
2732 /* creation sub-XIDs must be preserved */
2733 SWAPFIELD(SubTransactionId, rd_createSubid);
2734 SWAPFIELD(SubTransactionId, rd_newRelfilelocatorSubid);
2735 SWAPFIELD(SubTransactionId, rd_firstRelfilelocatorSubid);
2736 SWAPFIELD(SubTransactionId, rd_droppedSubid);
2737 /* un-swap rd_rel pointers, swap contents instead */
2738 SWAPFIELD(Form_pg_class, rd_rel);
2739 /* ... but actually, we don't have to update newrel->rd_rel */
2740 memcpy(relation->rd_rel, newrel->rd_rel, CLASS_TUPLE_SIZE);
2741 /* preserve old tupledesc, rules, policies if no logical change */
2742 if (keep_tupdesc)
2743 SWAPFIELD(TupleDesc, rd_att);
2744 if (keep_rules)
2745 {
2746 SWAPFIELD(RuleLock *, rd_rules);
2747 SWAPFIELD(MemoryContext, rd_rulescxt);
2748 }
2749 if (keep_policies)
2750 SWAPFIELD(RowSecurityDesc *, rd_rsdesc);
2751 /* toast OID override must be preserved */
2752 SWAPFIELD(Oid, rd_toastoid);
2753 /* pgstat_info / enabled must be preserved */
2754 SWAPFIELD(struct PgStat_TableStatus *, pgstat_info);
2755 SWAPFIELD(bool, pgstat_enabled);
2756 /* preserve old partition key if we have one */
2757 if (keep_partkey)
2758 {
2759 SWAPFIELD(PartitionKey, rd_partkey);
2760 SWAPFIELD(MemoryContext, rd_partkeycxt);
2761 }
2762 if (newrel->rd_pdcxt != NULL || newrel->rd_pddcxt != NULL)
2763 {
2764 /*
2765 * We are rebuilding a partitioned relation with a non-zero
2766 * reference count, so we must keep the old partition descriptor
2767 * around, in case there's a PartitionDirectory with a pointer to
2768 * it. This means we can't free the old rd_pdcxt yet. (This is
2769 * necessary because RelationGetPartitionDesc hands out direct
2770 * pointers to the relcache's data structure, unlike our usual
2771 * practice which is to hand out copies. We'd have the same
2772 * problem with rd_partkey, except that we always preserve that
2773 * once created.)
2774 *
2775 * To ensure that it's not leaked completely, re-attach it to the
2776 * new reldesc, or make it a child of the new reldesc's rd_pdcxt
2777 * in the unlikely event that there is one already. (Compare hack
2778 * in RelationBuildPartitionDesc.) RelationClose will clean up
2779 * any such contexts once the reference count reaches zero.
2780 *
2781 * In the case where the reference count is zero, this code is not
2782 * reached, which should be OK because in that case there should
2783 * be no PartitionDirectory with a pointer to the old entry.
2784 *
2785 * Note that newrel and relation have already been swapped, so the
2786 * "old" partition descriptor is actually the one hanging off of
2787 * newrel.
2788 */
2789 relation->rd_partdesc = NULL; /* ensure rd_partdesc is invalid */
2790 relation->rd_partdesc_nodetached = NULL;
2792 if (relation->rd_pdcxt != NULL) /* probably never happens */
2793 MemoryContextSetParent(newrel->rd_pdcxt, relation->rd_pdcxt);
2794 else
2795 relation->rd_pdcxt = newrel->rd_pdcxt;
2796 if (relation->rd_pddcxt != NULL)
2797 MemoryContextSetParent(newrel->rd_pddcxt, relation->rd_pddcxt);
2798 else
2799 relation->rd_pddcxt = newrel->rd_pddcxt;
2800 /* drop newrel's pointers so we don't destroy it below */
2801 newrel->rd_partdesc = NULL;
2802 newrel->rd_partdesc_nodetached = NULL;
2803 newrel->rd_partdesc_nodetached_xmin = InvalidTransactionId;
2804 newrel->rd_pdcxt = NULL;
2805 newrel->rd_pddcxt = NULL;
2806 }
2807
2808#undef SWAPFIELD
2809
2810 /* And now we can throw away the temporary entry */
2812 }
2813}
uint32 SubTransactionId
Definition c.h:680
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition mcxt.c:686
static bool equalRuleLocks(RuleLock *rlock1, RuleLock *rlock2)
Definition relcache.c:927
static void RelationReloadNailed(Relation relation)
Definition relcache.c:2380
static bool equalRSDesc(RowSecurityDesc *rsdesc1, RowSecurityDesc *rsdesc2)
Definition relcache.c:1018
static void RelationReloadIndexInfo(Relation relation)
Definition relcache.c:2271
#define SWAPFIELD(fldtype, fldname)
bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
Definition tupdesc.c:590

References Assert, AssertCouldGetRelation(), CLASS_TUPLE_SIZE, elog, equalRSDesc(), equalRuleLocks(), equalTupleDescs(), ERROR, fb(), HistoricSnapshotActive(), InvalidSubTransactionId, InvalidTransactionId, MemoryContextSetParent(), RelationData::rd_att, RelationData::rd_droppedSubid, RelationData::rd_indexcxt, RelationData::rd_isnailed, RelationData::rd_partdesc, RelationData::rd_partdesc_nodetached, RelationData::rd_partdesc_nodetached_xmin, RelationData::rd_partkey, RelationData::rd_pdcxt, RelationData::rd_pddcxt, RelationData::rd_rel, RelationData::rd_rsdesc, RelationData::rd_rules, RelationBuildDesc(), RelationDestroyRelation(), RelationGetRelid, RelationHasReferenceCountZero, RelationInvalidateRelation(), RelationReloadIndexInfo(), RelationReloadNailed(), and SWAPFIELD.

Referenced by RelationCacheInvalidate(), RelationFlushRelation(), and RelationIdGetRelation().

◆ RelationReloadIndexInfo()

static void RelationReloadIndexInfo ( Relation  relation)
static

Definition at line 2271 of file relcache.c.

2272{
2273 bool indexOK;
2276
2277 /* Should be called only for invalidated, live indexes */
2278 Assert((relation->rd_rel->relkind == RELKIND_INDEX ||
2279 relation->rd_rel->relkind == RELKIND_PARTITIONED_INDEX) &&
2280 !relation->rd_isvalid &&
2282
2283 /*
2284 * If it's a shared index, we might be called before backend startup has
2285 * finished selecting a database, in which case we have no way to read
2286 * pg_class yet. However, a shared index can never have any significant
2287 * schema updates, so it's okay to mostly ignore the invalidation signal.
2288 * Its physical relfilenumber might've changed, but that's all. Update
2289 * the physical relfilenumber, mark it valid and return without doing
2290 * anything more.
2291 */
2292 if (relation->rd_rel->relisshared && !criticalRelcachesBuilt)
2293 {
2294 RelationInitPhysicalAddr(relation);
2295 relation->rd_isvalid = true;
2296 return;
2297 }
2298
2299 /*
2300 * Read the pg_class row
2301 *
2302 * Don't try to use an indexscan of pg_class_oid_index to reload the info
2303 * for pg_class_oid_index ...
2304 */
2305 indexOK = (RelationGetRelid(relation) != ClassOidIndexId);
2308 elog(ERROR, "could not find pg_class tuple for index %u",
2309 RelationGetRelid(relation));
2311 memcpy(relation->rd_rel, relp, CLASS_TUPLE_SIZE);
2312 /* Reload reloptions in case they changed */
2313 if (relation->rd_options)
2314 pfree(relation->rd_options);
2316 /* done with pg_class tuple */
2318 /* We must recalculate physical address in case it changed */
2319 RelationInitPhysicalAddr(relation);
2320
2321 /*
2322 * For a non-system index, there are fields of the pg_index row that are
2323 * allowed to change, so re-read that row and update the relcache entry.
2324 * Most of the info derived from pg_index (such as support function lookup
2325 * info) cannot change, and indeed the whole point of this routine is to
2326 * update the relcache entry without clobbering that data; so wholesale
2327 * replacement is not appropriate.
2328 */
2329 if (!IsSystemRelation(relation))
2330 {
2331 HeapTuple tuple;
2333
2336 if (!HeapTupleIsValid(tuple))
2337 elog(ERROR, "cache lookup failed for index %u",
2338 RelationGetRelid(relation));
2339 index = (Form_pg_index) GETSTRUCT(tuple);
2340
2341 /*
2342 * Basically, let's just copy all the bool fields. There are one or
2343 * two of these that can't actually change in the current code, but
2344 * it's not worth it to track exactly which ones they are. None of
2345 * the array fields are allowed to change, though.
2346 */
2347 relation->rd_index->indisunique = index->indisunique;
2348 relation->rd_index->indnullsnotdistinct = index->indnullsnotdistinct;
2349 relation->rd_index->indisprimary = index->indisprimary;
2350 relation->rd_index->indisexclusion = index->indisexclusion;
2351 relation->rd_index->indimmediate = index->indimmediate;
2352 relation->rd_index->indisclustered = index->indisclustered;
2353 relation->rd_index->indisvalid = index->indisvalid;
2354 relation->rd_index->indcheckxmin = index->indcheckxmin;
2355 relation->rd_index->indisready = index->indisready;
2356 relation->rd_index->indislive = index->indislive;
2357 relation->rd_index->indisreplident = index->indisreplident;
2358
2359 /* Copy xmin too, as that is needed to make sense of indcheckxmin */
2362
2363 ReleaseSysCache(tuple);
2364 }
2365
2366 /* Okay, now it's valid again */
2367 relation->rd_isvalid = true;
2368}
bool IsSystemRelation(Relation relation)
Definition catalog.c:74
static TransactionId HeapTupleHeaderGetXmin(const HeapTupleHeaderData *tup)
static void HeapTupleHeaderSetXmin(HeapTupleHeaderData *tup, TransactionId xid)

References Assert, CLASS_TUPLE_SIZE, criticalRelcachesBuilt, elog, ERROR, fb(), GETSTRUCT(), heap_freetuple(), HeapTupleHeaderGetXmin(), HeapTupleHeaderSetXmin(), HeapTupleIsValid, InvalidSubTransactionId, IsSystemRelation(), ObjectIdGetDatum(), pfree(), RelationData::rd_droppedSubid, RelationData::rd_index, RelationData::rd_indextuple, RelationData::rd_isvalid, RelationData::rd_options, RelationData::rd_rel, RelationGetRelid, RelationInitPhysicalAddr(), RelationParseRelOptions(), ReleaseSysCache(), ScanPgRelation(), SearchSysCache1(), and HeapTupleData::t_data.

Referenced by RelationRebuildRelation().

◆ RelationReloadNailed()

static void RelationReloadNailed ( Relation  relation)
static

Definition at line 2380 of file relcache.c.

2381{
2382 /* Should be called only for invalidated, nailed relations */
2383 Assert(!relation->rd_isvalid);
2384 Assert(relation->rd_isnailed);
2385 /* nailed indexes are handled by RelationReloadIndexInfo() */
2386 Assert(relation->rd_rel->relkind == RELKIND_RELATION);
2388
2389 /*
2390 * Redo RelationInitPhysicalAddr in case it is a mapped relation whose
2391 * mapping changed.
2392 */
2393 RelationInitPhysicalAddr(relation);
2394
2395 /*
2396 * Reload a non-index entry. We can't easily do so if relcaches aren't
2397 * yet built, but that's fine because at that stage the attributes that
2398 * need to be current (like relfrozenxid) aren't yet accessed. To ensure
2399 * the entry will later be revalidated, we leave it in invalid state, but
2400 * allow use (cf. RelationIdGetRelation()).
2401 */
2403 {
2406
2407 /*
2408 * NB: Mark the entry as valid before starting to scan, to avoid
2409 * self-recursion when re-building pg_class.
2410 */
2411 relation->rd_isvalid = true;
2412
2414 true, false);
2416 memcpy(relation->rd_rel, relp, CLASS_TUPLE_SIZE);
2418
2419 /*
2420 * Again mark as valid, to protect against concurrently arriving
2421 * invalidations.
2422 */
2423 relation->rd_isvalid = true;
2424 }
2425}

References Assert, AssertCouldGetRelation(), CLASS_TUPLE_SIZE, criticalRelcachesBuilt, fb(), GETSTRUCT(), heap_freetuple(), RelationData::rd_isnailed, RelationData::rd_isvalid, RelationData::rd_rel, RelationGetRelid, RelationInitPhysicalAddr(), and ScanPgRelation().

Referenced by RelationRebuildRelation().

◆ RelationSetNewRelfilenumber()

void RelationSetNewRelfilenumber ( Relation  relation,
char  persistence 
)

Definition at line 3768 of file relcache.c.

3769{
3773 HeapTuple tuple;
3778
3779 if (!IsBinaryUpgrade)
3780 {
3781 /* Allocate a new relfilenumber */
3782 newrelfilenumber = GetNewRelFileNumber(relation->rd_rel->reltablespace,
3783 NULL, persistence);
3784 }
3785 else if (relation->rd_rel->relkind == RELKIND_INDEX)
3786 {
3788 ereport(ERROR,
3790 errmsg("index relfilenumber value not set when in binary upgrade mode")));
3791
3794 }
3795 else if (relation->rd_rel->relkind == RELKIND_RELATION)
3796 {
3798 ereport(ERROR,
3800 errmsg("heap relfilenumber value not set when in binary upgrade mode")));
3801
3804 }
3805 else
3806 ereport(ERROR,
3808 errmsg("unexpected request for new relfilenumber in binary upgrade mode")));
3809
3810 /*
3811 * Get a writable copy of the pg_class tuple for the given relation.
3812 */
3814
3817 if (!HeapTupleIsValid(tuple))
3818 elog(ERROR, "could not find tuple for relation %u",
3819 RelationGetRelid(relation));
3820 otid = tuple->t_self;
3822
3823 /*
3824 * Schedule unlinking of the old storage at transaction commit, except
3825 * when performing a binary upgrade, when we must do it immediately.
3826 */
3827 if (IsBinaryUpgrade)
3828 {
3829 SMgrRelation srel;
3830
3831 /*
3832 * During a binary upgrade, we use this code path to ensure that
3833 * pg_largeobject and its index have the same relfilenumbers as in the
3834 * old cluster. This is necessary because pg_upgrade treats
3835 * pg_largeobject like a user table, not a system table. It is however
3836 * possible that a table or index may need to end up with the same
3837 * relfilenumber in the new cluster as what it had in the old cluster.
3838 * Hence, we can't wait until commit time to remove the old storage.
3839 *
3840 * In general, this function needs to have transactional semantics,
3841 * and removing the old storage before commit time surely isn't.
3842 * However, it doesn't really matter, because if a binary upgrade
3843 * fails at this stage, the new cluster will need to be recreated
3844 * anyway.
3845 */
3846 srel = smgropen(relation->rd_locator, relation->rd_backend);
3847 smgrdounlinkall(&srel, 1, false);
3848 smgrclose(srel);
3849 }
3850 else
3851 {
3852 /* Not a binary upgrade, so just schedule it to happen later. */
3853 RelationDropStorage(relation);
3854 }
3855
3856 /*
3857 * Create storage for the main fork of the new relfilenumber. If it's a
3858 * table-like object, call into the table AM to do so, which'll also
3859 * create the table's init fork if needed.
3860 *
3861 * NOTE: If relevant for the AM, any conflict in relfilenumber value will
3862 * be caught here, if GetNewRelFileNumber messes up for any reason.
3863 */
3864 newrlocator = relation->rd_locator;
3866
3867 if (RELKIND_HAS_TABLE_AM(relation->rd_rel->relkind))
3868 {
3870 persistence,
3871 &freezeXid, &minmulti);
3872 }
3873 else if (RELKIND_HAS_STORAGE(relation->rd_rel->relkind))
3874 {
3875 /* handle these directly, at least for now */
3876 SMgrRelation srel;
3877
3878 srel = RelationCreateStorage(newrlocator, persistence, true);
3879 smgrclose(srel);
3880 }
3881 else
3882 {
3883 /* we shouldn't be called for anything else */
3884 elog(ERROR, "relation \"%s\" does not have storage",
3885 RelationGetRelationName(relation));
3886 }
3887
3888 /*
3889 * If we're dealing with a mapped index, pg_class.relfilenode doesn't
3890 * change; instead we have to send the update to the relation mapper.
3891 *
3892 * For mapped indexes, we don't actually change the pg_class entry at all;
3893 * this is essential when reindexing pg_class itself. That leaves us with
3894 * possibly-inaccurate values of relpages etc, but those will be fixed up
3895 * later.
3896 */
3897 if (RelationIsMapped(relation))
3898 {
3899 /* This case is only supported for indexes */
3900 Assert(relation->rd_rel->relkind == RELKIND_INDEX);
3901
3902 /* Since we're not updating pg_class, these had better not change */
3903 Assert(classform->relfrozenxid == freezeXid);
3904 Assert(classform->relminmxid == minmulti);
3905 Assert(classform->relpersistence == persistence);
3906
3907 /*
3908 * In some code paths it's possible that the tuple update we'd
3909 * otherwise do here is the only thing that would assign an XID for
3910 * the current transaction. However, we must have an XID to delete
3911 * files, so make sure one is assigned.
3912 */
3914
3915 /* Do the deed */
3918 relation->rd_rel->relisshared,
3919 false);
3920
3921 /* Since we're not updating pg_class, must trigger inval manually */
3922 CacheInvalidateRelcache(relation);
3923 }
3924 else
3925 {
3926 /* Normal case, update the pg_class entry */
3927 classform->relfilenode = newrelfilenumber;
3928
3929 /* relpages etc. never change for sequences */
3930 if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
3931 {
3932 classform->relpages = 0; /* it's empty until further notice */
3933 classform->reltuples = -1;
3934 classform->relallvisible = 0;
3935 classform->relallfrozen = 0;
3936 }
3937 classform->relfrozenxid = freezeXid;
3938 classform->relminmxid = minmulti;
3939 classform->relpersistence = persistence;
3940
3942 }
3943
3945 heap_freetuple(tuple);
3946
3948
3949 /*
3950 * Make the pg_class row change or relation map change visible. This will
3951 * cause the relcache entry to get updated, too.
3952 */
3954
3956}
TransactionId MultiXactId
Definition c.h:686
uint32 TransactionId
Definition c.h:676
RelFileNumber GetNewRelFileNumber(Oid reltablespace, Relation pg_class, char relpersistence)
Definition catalog.c:557
int errmsg(const char *fmt,...)
Definition elog.c:1080
bool IsBinaryUpgrade
Definition globals.c:121
RelFileNumber binary_upgrade_next_heap_pg_class_relfilenumber
Definition heap.c:83
RelFileNumber binary_upgrade_next_index_pg_class_relfilenumber
Definition index.c:86
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
Definition indexing.c:313
void CacheInvalidateRelcache(Relation relation)
Definition inval.c:1635
void UnlockTuple(Relation relation, const ItemPointerData *tid, LOCKMODE lockmode)
Definition lmgr.c:601
#define InplaceUpdateTupleLock
Definition lockdefs.h:48
#define RowExclusiveLock
Definition lockdefs.h:38
#define InvalidMultiXactId
Definition multixact.h:25
void RelationAssumeNewRelfilelocator(Relation relation)
Definition relcache.c:3971
SMgrRelation smgropen(RelFileLocator rlocator, ProcNumber backend)
Definition smgr.c:240
void smgrclose(SMgrRelation reln)
Definition smgr.c:374
void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
Definition smgr.c:538
SMgrRelation RelationCreateStorage(RelFileLocator rlocator, char relpersistence, bool register_delete)
Definition storage.c:122
void RelationDropStorage(Relation rel)
Definition storage.c:207
ItemPointerData t_self
Definition htup.h:65
HeapTuple SearchSysCacheLockedCopy1(int cacheId, Datum key1)
Definition syscache.c:399
static void table_relation_set_new_filelocator(Relation rel, const RelFileLocator *newrlocator, char persistence, TransactionId *freezeXid, MultiXactId *minmulti)
Definition tableam.h:1600
void CommandCounterIncrement(void)
Definition xact.c:1101
TransactionId GetCurrentTransactionId(void)
Definition xact.c:455

References Assert, binary_upgrade_next_heap_pg_class_relfilenumber, binary_upgrade_next_index_pg_class_relfilenumber, CacheInvalidateRelcache(), CatalogTupleUpdate(), CommandCounterIncrement(), elog, ereport, errcode(), errmsg(), ERROR, fb(), GetCurrentTransactionId(), GetNewRelFileNumber(), GETSTRUCT(), heap_freetuple(), HeapTupleIsValid, InplaceUpdateTupleLock, InvalidMultiXactId, InvalidOid, InvalidTransactionId, IsBinaryUpgrade, ObjectIdGetDatum(), OidIsValid, RelationData::rd_backend, RelationData::rd_locator, RelationData::rd_rel, RelationAssumeNewRelfilelocator(), RelationCreateStorage(), RelationDropStorage(), RelationGetRelationName, RelationGetRelid, RelationIsMapped, RelationMapUpdateMap(), RelFileLocator::relNumber, RowExclusiveLock, SearchSysCacheLockedCopy1(), smgrclose(), smgrdounlinkall(), smgropen(), HeapTupleData::t_self, table_close(), table_open(), table_relation_set_new_filelocator(), and UnlockTuple().

Referenced by AlterSequence(), ExecuteTruncateGuts(), reindex_index(), ResetSequence(), and SequenceChangePersistence().

◆ RememberToFreeTupleDescAtEOX()

◆ ResourceOwnerForgetRelationRef()

static void ResourceOwnerForgetRelationRef ( ResourceOwner  owner,
Relation  rel 
)
inlinestatic

Definition at line 2168 of file relcache.c.

2169{
2171}
static const ResourceOwnerDesc relref_resowner_desc
Definition relcache.c:2152
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition resowner.c:561

References PointerGetDatum(), relref_resowner_desc, and ResourceOwnerForget().

Referenced by RelationDecrementReferenceCount().

◆ ResourceOwnerRememberRelationRef()

static void ResourceOwnerRememberRelationRef ( ResourceOwner  owner,
Relation  rel 
)
inlinestatic

Definition at line 2163 of file relcache.c.

2164{
2166}
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition resowner.c:521

References PointerGetDatum(), relref_resowner_desc, and ResourceOwnerRemember().

Referenced by RelationIncrementReferenceCount().

◆ ResOwnerPrintRelCache()

static char * ResOwnerPrintRelCache ( Datum  res)
static

Definition at line 6969 of file relcache.c.

6970{
6971 Relation rel = (Relation) DatumGetPointer(res);
6972
6973 return psprintf("relation \"%s\"", RelationGetRelationName(rel));
6974}
char * psprintf(const char *fmt,...)
Definition psprintf.c:43

References DatumGetPointer(), psprintf(), and RelationGetRelationName.

◆ ResOwnerReleaseRelation()

static void ResOwnerReleaseRelation ( Datum  res)
static

Definition at line 6977 of file relcache.c.

6978{
6979 Relation rel = (Relation) DatumGetPointer(res);
6980
6981 /*
6982 * This reference has already been removed from the resource owner, so
6983 * just decrement reference count without calling
6984 * ResourceOwnerForgetRelationRef.
6985 */
6986 Assert(rel->rd_refcnt > 0);
6987 rel->rd_refcnt -= 1;
6988
6990}

References Assert, DatumGetPointer(), RelationData::rd_refcnt, and RelationCloseCleanup().

◆ ScanPgRelation()

static HeapTuple ScanPgRelation ( Oid  targetRelId,
bool  indexOK,
bool  force_non_historic 
)
static

Definition at line 340 of file relcache.c.

341{
345 ScanKeyData key[1];
346 Snapshot snapshot = NULL;
347
348 /*
349 * If something goes wrong during backend startup, we might find ourselves
350 * trying to read pg_class before we've selected a database. That ain't
351 * gonna work, so bail out with a useful error message. If this happens,
352 * it probably means a relcache entry that needs to be nailed isn't.
353 */
355 elog(FATAL, "cannot read pg_class without having selected a database");
356
357 /*
358 * form a scan key
359 */
360 ScanKeyInit(&key[0],
364
365 /*
366 * Open pg_class and fetch a tuple. Force heap scan if we haven't yet
367 * built the critical relcache entries (this includes initdb and startup
368 * without a pg_internal.init file). The caller can also force a heap
369 * scan by setting indexOK == false.
370 */
372
373 /*
374 * The caller might need a tuple that's newer than what's visible to the
375 * historic snapshot; currently the only case requiring to do so is
376 * looking up the relfilenumber of non mapped system relations during
377 * decoding.
378 */
381
384 snapshot,
385 1, key);
386
388
389 /*
390 * Must copy tuple before releasing buffer.
391 */
394
395 /* all done */
397
398 if (snapshot)
399 UnregisterSnapshot(snapshot);
400
402
403 return pg_class_tuple;
404}
void UnregisterSnapshot(Snapshot snapshot)
Definition snapmgr.c:866
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition snapmgr.c:824
Snapshot GetNonHistoricCatalogSnapshot(Oid relid)
Definition snapmgr.c:407

References AccessShareLock, BTEqualStrategyNumber, criticalRelcachesBuilt, elog, FATAL, fb(), GetNonHistoricCatalogSnapshot(), heap_copytuple(), HeapTupleIsValid, MyDatabaseId, ObjectIdGetDatum(), OidIsValid, RegisterSnapshot(), ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), and UnregisterSnapshot().

Referenced by RelationBuildDesc(), RelationInitPhysicalAddr(), RelationReloadIndexInfo(), and RelationReloadNailed().

◆ unlink_initfile()

static void unlink_initfile ( const char initfilename,
int  elevel 
)
static

Definition at line 6952 of file relcache.c.

6953{
6954 if (unlink(initfilename) < 0)
6955 {
6956 /* It might not be there, but log any error other than ENOENT */
6957 if (errno != ENOENT)
6958 ereport(elevel,
6960 errmsg("could not remove cache file \"%s\": %m",
6961 initfilename)));
6962 }
6963}
int errcode_for_file_access(void)
Definition elog.c:886

References ereport, errcode_for_file_access(), errmsg(), and fb().

Referenced by RelationCacheInitFilePreInvalidate(), RelationCacheInitFileRemove(), and RelationCacheInitFileRemoveInDir().

◆ write_item()

static void write_item ( const void data,
Size  len,
FILE fp 
)
static

Definition at line 6792 of file relcache.c.

6793{
6794 if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len))
6795 ereport(FATAL,
6797 errmsg_internal("could not write init file: %m"));
6798 if (len > 0 && fwrite(data, 1, len, fp) != len)
6799 ereport(FATAL,
6801 errmsg_internal("could not write init file: %m"));
6802}
const void * data

References data, ereport, errcode_for_file_access(), errmsg_internal(), FATAL, fb(), and len.

Referenced by write_relcache_init_file().

◆ write_relcache_init_file()

static void write_relcache_init_file ( bool  shared)
static

Definition at line 6580 of file relcache.c.

6581{
6582 FILE *fp;
6583 char tempfilename[MAXPGPATH];
6585 int magic;
6586 HASH_SEQ_STATUS status;
6588 int i;
6589
6590 /*
6591 * If we have already received any relcache inval events, there's no
6592 * chance of succeeding so we may as well skip the whole thing.
6593 */
6594 if (relcacheInvalsReceived != 0L)
6595 return;
6596
6597 /*
6598 * We must write a temporary file and rename it into place. Otherwise,
6599 * another backend starting at about the same time might crash trying to
6600 * read the partially-complete file.
6601 */
6602 if (shared)
6603 {
6604 snprintf(tempfilename, sizeof(tempfilename), "global/%s.%d",
6606 snprintf(finalfilename, sizeof(finalfilename), "global/%s",
6608 }
6609 else
6610 {
6611 snprintf(tempfilename, sizeof(tempfilename), "%s/%s.%d",
6613 snprintf(finalfilename, sizeof(finalfilename), "%s/%s",
6615 }
6616
6617 unlink(tempfilename); /* in case it exists w/wrong permissions */
6618
6620 if (fp == NULL)
6621 {
6622 /*
6623 * We used to consider this a fatal error, but we might as well
6624 * continue with backend startup ...
6625 */
6628 errmsg("could not create relation-cache initialization file \"%s\": %m",
6629 tempfilename),
6630 errdetail("Continuing anyway, but there's something wrong.")));
6631 return;
6632 }
6633
6634 /*
6635 * Write a magic number to serve as a file version identifier. We can
6636 * change the magic number whenever the relcache layout changes.
6637 */
6639 if (fwrite(&magic, 1, sizeof(magic), fp) != sizeof(magic))
6640 ereport(FATAL,
6642 errmsg_internal("could not write init file: %m"));
6643
6644 /*
6645 * Write all the appropriate reldescs (in no particular order).
6646 */
6648
6649 while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
6650 {
6651 Relation rel = idhentry->reldesc;
6653
6654 /* ignore if not correct group */
6655 if (relform->relisshared != shared)
6656 continue;
6657
6658 /*
6659 * Ignore if not supposed to be in init file. We can allow any shared
6660 * relation that's been loaded so far to be in the shared init file,
6661 * but unshared relations must be ones that should be in the local
6662 * file per RelationIdIsInInitFile. (Note: if you want to change the
6663 * criterion for rels to be kept in the init file, see also inval.c.
6664 * The reason for filtering here is to be sure that we don't put
6665 * anything into the local init file for which a relcache inval would
6666 * not cause invalidation of that init file.)
6667 */
6668 if (!shared && !RelationIdIsInInitFile(RelationGetRelid(rel)))
6669 {
6670 /* Nailed rels had better get stored. */
6671 Assert(!rel->rd_isnailed);
6672 continue;
6673 }
6674
6675 /* first write the relcache entry proper */
6676 write_item(rel, sizeof(RelationData), fp);
6677
6678 /* next write the relation tuple form */
6680
6681 /* next, do all the attribute tuple form data entries */
6682 for (i = 0; i < relform->relnatts; i++)
6683 {
6686 }
6687
6688 /* next, do the access method specific field */
6690 (rel->rd_options ? VARSIZE(rel->rd_options) : 0),
6691 fp);
6692
6693 /*
6694 * If it's an index, there's more to do. Note we explicitly ignore
6695 * partitioned indexes here.
6696 */
6697 if (rel->rd_rel->relkind == RELKIND_INDEX)
6698 {
6699 /* write the pg_index tuple */
6700 /* we assume this was created by heap_copytuple! */
6703 fp);
6704
6705 /* write the vector of opfamily OIDs */
6707 relform->relnatts * sizeof(Oid),
6708 fp);
6709
6710 /* write the vector of opcintype OIDs */
6712 relform->relnatts * sizeof(Oid),
6713 fp);
6714
6715 /* write the vector of support procedure OIDs */
6717 relform->relnatts * (rel->rd_indam->amsupport * sizeof(RegProcedure)),
6718 fp);
6719
6720 /* write the vector of collation OIDs */
6722 relform->relnatts * sizeof(Oid),
6723 fp);
6724
6725 /* write the vector of indoption values */
6727 relform->relnatts * sizeof(int16),
6728 fp);
6729
6730 Assert(rel->rd_opcoptions);
6731
6732 /* write the vector of opcoptions values */
6733 for (i = 0; i < relform->relnatts; i++)
6734 {
6735 bytea *opt = rel->rd_opcoptions[i];
6736
6737 write_item(opt, opt ? VARSIZE(opt) : 0, fp);
6738 }
6739 }
6740 }
6741
6742 if (FreeFile(fp))
6743 ereport(FATAL,
6745 errmsg_internal("could not write init file: %m"));
6746
6747 /*
6748 * Now we have to check whether the data we've so painstakingly
6749 * accumulated is already obsolete due to someone else's just-committed
6750 * catalog changes. If so, we just delete the temp file and leave it to
6751 * the next backend to try again. (Our own relcache entries will be
6752 * updated by SI message processing, but we can't be sure whether what we
6753 * wrote out was up-to-date.)
6754 *
6755 * This mustn't run concurrently with the code that unlinks an init file
6756 * and sends SI messages, so grab a serialization lock for the duration.
6757 */
6759
6760 /* Make sure we have seen all incoming SI messages */
6762
6763 /*
6764 * If we have received any SI relcache invals since backend start, assume
6765 * we may have written out-of-date data.
6766 */
6767 if (relcacheInvalsReceived == 0L)
6768 {
6769 /*
6770 * OK, rename the temp file to its final name, deleting any
6771 * previously-existing init file.
6772 *
6773 * Note: a failure here is possible under Cygwin, if some other
6774 * backend is holding open an unlinked-but-not-yet-gone init file. So
6775 * treat this as a noncritical failure; just remove the useless temp
6776 * file on failure.
6777 */
6780 }
6781 else
6782 {
6783 /* Delete the already-obsolete temp file */
6785 }
6786
6788}
#define PG_BINARY_W
Definition c.h:1284
int errdetail(const char *fmt,...)
Definition elog.c:1216
int MyProcPid
Definition globals.c:47
void AcceptInvalidationMessages(void)
Definition inval.c:930
static void write_item(const void *data, Size len, FILE *fp)
Definition relcache.c:6792
bool RelationIdIsInInitFile(Oid relationId)
Definition relcache.c:6815
uint32 t_len
Definition htup.h:64

References AcceptInvalidationMessages(), AllocateFile(), IndexAmRoutine::amsupport, Assert, ATTRIBUTE_FIXED_PART_SIZE, CLASS_TUPLE_SIZE, DatabasePath, ereport, errcode_for_file_access(), errdetail(), errmsg(), errmsg_internal(), FATAL, fb(), FreeFile(), hash_seq_init(), hash_seq_search(), HEAPTUPLESIZE, i, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MAXPGPATH, MyProcPid, PG_BINARY_W, RelationData::rd_att, RelationData::rd_indam, RelationData::rd_indcollation, RelationData::rd_indextuple, RelationData::rd_indoption, RelationData::rd_isnailed, RelationData::rd_opcintype, RelationData::rd_opcoptions, RelationData::rd_opfamily, RelationData::rd_options, RelationData::rd_rel, RelationData::rd_support, RelationGetRelid, RelationIdCache, RelationIdIsInInitFile(), RELCACHE_INIT_FILEMAGIC, RELCACHE_INIT_FILENAME, relcacheInvalsReceived, snprintf, HeapTupleData::t_len, TupleDescAttr(), VARSIZE(), WARNING, and write_item().

Referenced by RelationCacheInitializePhase3().

Variable Documentation

◆ criticalRelcachesBuilt

◆ criticalSharedRelcachesBuilt

◆ Desc_pg_attribute

Definition at line 112 of file relcache.c.

Referenced by RelationCacheInitializePhase3().

◆ Desc_pg_auth_members

Definition at line 117 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_authid

Definition at line 116 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_class

◆ Desc_pg_database

Definition at line 115 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_index

Definition at line 118 of file relcache.c.

Referenced by GetPgIndexDescriptor().

◆ Desc_pg_proc

Definition at line 113 of file relcache.c.

Referenced by RelationCacheInitializePhase3().

◆ Desc_pg_shseclabel

Definition at line 119 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_subscription

Definition at line 120 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_type

Definition at line 114 of file relcache.c.

Referenced by RelationCacheInitializePhase3().

◆ eoxact_list

Oid eoxact_list[MAX_EOXACT_LIST]
static

Definition at line 185 of file relcache.c.

Referenced by AtEOSubXact_RelationCache(), and AtEOXact_RelationCache().

◆ eoxact_list_len

int eoxact_list_len = 0
static

Definition at line 186 of file relcache.c.

Referenced by AtEOSubXact_RelationCache(), and AtEOXact_RelationCache().

◆ eoxact_list_overflowed

bool eoxact_list_overflowed = false
static

Definition at line 187 of file relcache.c.

Referenced by AtEOSubXact_RelationCache(), and AtEOXact_RelationCache().

◆ EOXactTupleDescArray

TupleDesc* EOXactTupleDescArray
static

Definition at line 202 of file relcache.c.

Referenced by AtEOXact_RelationCache(), and RememberToFreeTupleDescAtEOX().

◆ EOXactTupleDescArrayLen

int EOXactTupleDescArrayLen = 0
static

Definition at line 204 of file relcache.c.

Referenced by AtEOXact_RelationCache(), and RememberToFreeTupleDescAtEOX().

◆ in_progress_list

◆ in_progress_list_len

◆ in_progress_list_maxlen

int in_progress_list_maxlen
static

Definition at line 172 of file relcache.c.

Referenced by RelationBuildDesc(), and RelationCacheInitialize().

◆ NextEOXactTupleDescNum

int NextEOXactTupleDescNum = 0
static

Definition at line 203 of file relcache.c.

Referenced by AtEOXact_RelationCache(), and RememberToFreeTupleDescAtEOX().

◆ OpClassCache

HTAB* OpClassCache = NULL
static

Definition at line 271 of file relcache.c.

Referenced by LookupOpclassInfo().

◆ RelationIdCache

◆ relcacheInvalsReceived

long relcacheInvalsReceived = 0L
static

◆ relref_resowner_desc

const ResourceOwnerDesc relref_resowner_desc
static
Initial value:
=
{
.name = "relcache reference",
.release_priority = RELEASE_PRIO_RELCACHE_REFS,
.ReleaseResource = ResOwnerReleaseRelation,
.DebugPrint = ResOwnerPrintRelCache
}
static void ResOwnerReleaseRelation(Datum res)
Definition relcache.c:6977
static char * ResOwnerPrintRelCache(Datum res)
Definition relcache.c:6969
@ RESOURCE_RELEASE_BEFORE_LOCKS
Definition resowner.h:54
#define RELEASE_PRIO_RELCACHE_REFS
Definition resowner.h:64

Definition at line 2152 of file relcache.c.

2153{
2154 .name = "relcache reference",
2155 .release_phase = RESOURCE_RELEASE_BEFORE_LOCKS,
2156 .release_priority = RELEASE_PRIO_RELCACHE_REFS,
2157 .ReleaseResource = ResOwnerReleaseRelation,
2158 .DebugPrint = ResOwnerPrintRelCache
2159};

Referenced by ResourceOwnerForgetRelationRef(), and ResourceOwnerRememberRelationRef().