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/fd.h"
#include "storage/lmgr.h"
#include "storage/lock.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:187
#define MAX_EOXACT_LIST
Definition relcache.c:186
static int eoxact_list_len
Definition relcache.c:188

Definition at line 191 of file relcache.c.

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

◆ INITRELCACHESIZE

#define INITRELCACHESIZE   400

Definition at line 3991 of file relcache.c.

◆ MAX_EOXACT_LIST

#define MAX_EOXACT_LIST   32

Definition at line 186 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 104 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:889
#define WARNING
Definition elog.h:37
@ HASH_REMOVE
Definition hsearch.h:110
static HTAB * RelationIdCache
Definition relcache.c:136

Definition at line 245 of file relcache.c.

246 { \
249 &((RELATION)->rd_id), \
251 if (hentry == NULL) \
252 elog(WARNING, "failed to delete relcache entry for OID %u", \
253 (RELATION)->rd_id); \
254} 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:109
#define IsBootstrapProcessingMode()
Definition miscadmin.h:495
#define RelationHasReferenceCountZero(relation)
Definition rel.h:500
#define RelationGetRelationName(relation)
Definition rel.h:550

Definition at line 211 of file relcache.c.

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

◆ RelationIdCacheLookup

#define RelationIdCacheLookup (   ID,
  RELATION 
)
Value:

Definition at line 233 of file relcache.c.

234 { \
237 &(ID), \
238 HASH_FIND, NULL); \
239 if (hentry) \
241 else \
242 RELATION = NULL; \
243} while(0)

◆ RELCACHE_INIT_FILEMAGIC

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

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

416{
417 Relation relation;
420
421 /* Relcache entries must live in CacheMemoryContext */
423
424 /*
425 * allocate and zero space for new relation descriptor
426 */
427 relation = palloc0_object(RelationData);
428
429 /* make sure relation is marked as having no open file yet */
430 relation->rd_smgr = NULL;
431
432 /*
433 * Copy the relation tuple form
434 *
435 * We only allocate space for the fixed fields, ie, CLASS_TUPLE_SIZE. The
436 * variable-length fields (relacl, reloptions) are NOT stored in the
437 * relcache --- there'd be little point in it, since we don't copy the
438 * tuple's nulls bitmap and hence wouldn't know if the values are valid.
439 * Bottom line is that relacl *cannot* be retrieved from the relcache. Get
440 * it from the syscache if you need it. The same goes for the original
441 * form of reloptions (however, we do store the parsed form of reloptions
442 * in rd_options).
443 */
445
447
448 /* initialize relation tuple form */
449 relation->rd_rel = relationForm;
450
451 /* and allocate attribute tuple form storage */
452 relation->rd_att = CreateTemplateTupleDesc(relationForm->relnatts);
453 /* which we mark as a reference-counted tupdesc */
454 relation->rd_att->tdrefcount = 1;
455
457
458 return relation;
459}
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
#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:160
#define CLASS_TUPLE_SIZE
Definition pg_class.h:152
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:165

References CacheMemoryContext, CLASS_TUPLE_SIZE, CreateTemplateTupleDesc(), fb(), memcpy(), 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 3423 of file relcache.c.

3425{
3426 /*
3427 * Is it a relation created in the current subtransaction?
3428 *
3429 * During subcommit, mark it as belonging to the parent, instead, as long
3430 * as it has not been dropped. Otherwise simply delete the relcache entry.
3431 * --- it isn't interesting any longer.
3432 */
3433 if (relation->rd_createSubid == mySubid)
3434 {
3435 /*
3436 * Valid rd_droppedSubid means the corresponding relation is dropped
3437 * but the relcache entry is preserved for at-commit pending sync. We
3438 * need to drop it explicitly here not to make the entry orphan.
3439 */
3440 Assert(relation->rd_droppedSubid == mySubid ||
3443 relation->rd_createSubid = parentSubid;
3444 else if (RelationHasReferenceCountZero(relation))
3445 {
3446 /* allow the entry to be removed */
3451 RelationClearRelation(relation);
3452 return;
3453 }
3454 else
3455 {
3456 /*
3457 * Hmm, somewhere there's a (leaked?) reference to the relation.
3458 * We daren't remove the entry for fear of dereferencing a
3459 * dangling pointer later. Bleat, and transfer it to the parent
3460 * subtransaction so we can try again later. This must be just a
3461 * WARNING to avoid error-during-error-recovery loops.
3462 */
3463 relation->rd_createSubid = parentSubid;
3464 elog(WARNING, "cannot remove relcache entry for \"%s\" because it has nonzero refcount",
3465 RelationGetRelationName(relation));
3466 }
3467 }
3468
3469 /*
3470 * Likewise, update or drop any new-relfilenumber-in-subtransaction record
3471 * or drop record.
3472 */
3473 if (relation->rd_newRelfilelocatorSubid == mySubid)
3474 {
3475 if (isCommit)
3477 else
3479 }
3480
3481 if (relation->rd_firstRelfilelocatorSubid == mySubid)
3482 {
3483 if (isCommit)
3485 else
3487 }
3488
3489 if (relation->rd_droppedSubid == mySubid)
3490 {
3491 if (isCommit)
3492 relation->rd_droppedSubid = parentSubid;
3493 else
3495 }
3496}
#define InvalidSubTransactionId
Definition c.h:742
#define Assert(condition)
Definition c.h:943
#define elog(elevel,...)
Definition elog.h:228
static void RelationClearRelation(Relation relation)
Definition relcache.c:2536
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 3368 of file relcache.c.

3370{
3371 HASH_SEQ_STATUS status;
3373 int i;
3374
3375 /*
3376 * Forget in_progress_list. This is relevant when we're aborting due to
3377 * an error during RelationBuildDesc(). We don't commit subtransactions
3378 * during RelationBuildDesc().
3379 */
3382
3383 /*
3384 * Unless the eoxact_list[] overflowed, we only need to examine the rels
3385 * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3386 * logic as in AtEOXact_RelationCache.
3387 */
3389 {
3391 while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3392 {
3395 }
3396 }
3397 else
3398 {
3399 for (i = 0; i < eoxact_list_len; i++)
3400 {
3402 &eoxact_list[i],
3403 HASH_FIND,
3404 NULL);
3405 if (idhentry != NULL)
3408 }
3409 }
3410
3411 /* Don't reset the list; we still need more cleanup later */
3412}
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition dynahash.c:1352
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition dynahash.c:1317
int i
Definition isn.c:77
static int in_progress_list_len
Definition relcache.c:173
static void AtEOSubXact_cleanup(Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
Definition relcache.c:3423
static bool eoxact_list_overflowed
Definition relcache.c:189

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

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

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

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

4567{
4568 const AttrDefault *ada = (const AttrDefault *) a;
4569 const AttrDefault *adb = (const AttrDefault *) b;
4570
4571 return pg_cmp_s16(ada->adnum, adb->adnum);
4572}
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 4486 of file relcache.c.

4487{
4492 HeapTuple htup;
4493 int found = 0;
4494
4495 /* Allocate array with room for as many entries as expected */
4496 attrdef = (AttrDefault *)
4498 ndef * sizeof(AttrDefault));
4499
4500 /* Search pg_attrdef for relevant entries */
4505
4508 NULL, 1, &skey);
4509
4511 {
4513 Datum val;
4514 bool isnull;
4515
4516 /* protect limited size of array */
4517 if (found >= ndef)
4518 {
4519 elog(WARNING, "unexpected pg_attrdef record found for attribute %d of relation \"%s\"",
4520 adform->adnum, RelationGetRelationName(relation));
4521 break;
4522 }
4523
4524 val = fastgetattr(htup,
4526 adrel->rd_att, &isnull);
4527 if (isnull)
4528 elog(WARNING, "null adbin for attribute %d of relation \"%s\"",
4529 adform->adnum, RelationGetRelationName(relation));
4530 else
4531 {
4532 /* detoast and convert to cstring in caller's context */
4533 char *s = TextDatumGetCString(val);
4534
4535 attrdef[found].adnum = adform->adnum;
4537 pfree(s);
4538 found++;
4539 }
4540 }
4541
4544
4545 if (found != ndef)
4546 elog(WARNING, "%d pg_attrdef record(s) missing for relation \"%s\"",
4547 ndef - found, RelationGetRelationName(relation));
4548
4549 /*
4550 * Sort the AttrDefault entries by adnum, for the convenience of
4551 * equalTupleDescs(). (Usually, they already will be in order, but this
4552 * might not be so if systable_getnext isn't using an index.)
4553 */
4554 if (found > 1)
4555 qsort(attrdef, found, sizeof(AttrDefault), AttrDefaultCmp);
4556
4557 /* Install array only after it's fully valid */
4558 relation->rd_att->constr->defval = attrdef;
4559 relation->rd_att->constr->num_defval = found;
4560}
#define TextDatumGetCString(d)
Definition builtins.h:99
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:612
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:523
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
END_CATALOG_STRUCT typedef FormData_pg_attrdef * Form_pg_attrdef
Definition pg_attrdef.h:53
#define qsort(a, b, c, d)
Definition port.h:495
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
uint64_t Datum
Definition postgres.h:70
#define RelationGetRelid(relation)
Definition rel.h:516
static int AttrDefaultCmp(const void *a, const void *b)
Definition relcache.c:4566
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:159
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(), Form_pg_attrdef, 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 4422 of file relcache.c.

4423{
4426 int i;
4427
4429
4431 result->tdtypeid = RECORDOID; /* not right, but we don't care */
4432 result->tdtypmod = -1;
4433
4434 for (i = 0; i < natts; i++)
4435 {
4437
4439 }
4440
4442
4443 /* Note: we don't bother to set up a TupleConstr entry */
4444
4446
4447 return result;
4448}
uint32 result
#define ATTRIBUTE_FIXED_PART_SIZE
void TupleDescFinalize(TupleDesc tupdesc)
Definition tupdesc.c:511
void populate_compact_attribute(TupleDesc tupdesc, int attnum)
Definition tupdesc.c:100
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178

References ATTRIBUTE_FIXED_PART_SIZE, CacheMemoryContext, CreateTemplateTupleDesc(), fb(), i, memcpy(), MemoryContextSwitchTo(), populate_compact_attribute(), result, TupleDescAttr(), and TupleDescFinalize().

Referenced by GetPgClassDescriptor(), and GetPgIndexDescriptor().

◆ CheckConstraintCmp()

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

Definition at line 4699 of file relcache.c.

4700{
4701 const ConstrCheck *ca = (const ConstrCheck *) a;
4702 const ConstrCheck *cb = (const ConstrCheck *) b;
4703
4704 return strcmp(ca->ccname, cb->ccname);
4705}
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 4582 of file relcache.c.

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

5983{
5984 bytea **opts = palloc_array(bytea *, natts);
5985
5986 for (int i = 0; i < natts; i++)
5987 {
5988 bytea *opt = srcopts[i];
5989
5990 opts[i] = !opt ? NULL : (bytea *)
5991 DatumGetPointer(datumCopy(PointerGetDatum(opt), false, -1));
5992 }
5993
5994 return opts;
5995}
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:342
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
Definition c.h:776

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

969{
970 int i;
971 Oid *r1,
972 *r2;
973
974 if (policy1 != NULL)
975 {
976 if (policy2 == NULL)
977 return false;
978
979 if (policy1->polcmd != policy2->polcmd)
980 return false;
981 if (policy1->hassublinks != policy2->hassublinks)
982 return false;
983 if (strcmp(policy1->policy_name, policy2->policy_name) != 0)
984 return false;
985 if (ARR_DIMS(policy1->roles)[0] != ARR_DIMS(policy2->roles)[0])
986 return false;
987
988 r1 = (Oid *) ARR_DATA_PTR(policy1->roles);
989 r2 = (Oid *) ARR_DATA_PTR(policy2->roles);
990
991 for (i = 0; i < ARR_DIMS(policy1->roles)[0]; i++)
992 {
993 if (r1[i] != r2[i])
994 return false;
995 }
996
997 if (!equal(policy1->qual, policy2->qual))
998 return false;
999 if (!equal(policy1->with_check_qual, policy2->with_check_qual))
1000 return false;
1001 }
1002 else if (policy2 != NULL)
1003 return false;
1004
1005 return true;
1006}
#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 1014 of file relcache.c.

1015{
1016 ListCell *lc,
1017 *rc;
1018
1019 if (rsdesc1 == NULL && rsdesc2 == NULL)
1020 return true;
1021
1022 if ((rsdesc1 != NULL && rsdesc2 == NULL) ||
1023 (rsdesc1 == NULL && rsdesc2 != NULL))
1024 return false;
1025
1026 if (list_length(rsdesc1->policies) != list_length(rsdesc2->policies))
1027 return false;
1028
1029 /* RelationBuildRowSecurity should build policies in order */
1030 forboth(lc, rsdesc1->policies, rc, rsdesc2->policies)
1031 {
1034
1035 if (!equalPolicy(l, r))
1036 return false;
1037 }
1038
1039 return true;
1040}
#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:550
static bool equalPolicy(RowSecurityPolicy *policy1, RowSecurityPolicy *policy2)
Definition relcache.c:968

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

Referenced by RelationRebuildRelation().

◆ equalRuleLocks()

static bool equalRuleLocks ( RuleLock rlock1,
RuleLock rlock2 
)
static

Definition at line 923 of file relcache.c.

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

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

Referenced by RelationRebuildRelation().

◆ errtable()

int errtable ( Relation  rel)

Definition at line 6063 of file relcache.c.

6064{
6068
6069 return 0; /* return value does not matter */
6070}
int err_generic_string(int field, const char *str)
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3588
#define PG_DIAG_SCHEMA_NAME
#define PG_DIAG_TABLE_NAME
#define RelationGetNamespace(relation)
Definition rel.h:557

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

6081{
6082 TupleDesc reldesc = RelationGetDescr(rel);
6083 const char *colname;
6084
6085 /* Use reldesc if it's a user attribute, else consult the catalogs */
6086 if (attnum > 0 && attnum <= reldesc->natts)
6087 colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
6088 else
6089 colname = get_attname(RelationGetRelid(rel), attnum, false);
6090
6091 return errtablecolname(rel, colname);
6092}
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:946
NameData attname
#define RelationGetDescr(relation)
Definition rel.h:542
int errtablecolname(Relation rel, const char *colname)
Definition relcache.c:6104

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

6105{
6106 errtable(rel);
6108
6109 return 0; /* return value does not matter */
6110}
#define PG_DIAG_COLUMN_NAME
int errtable(Relation rel)
Definition relcache.c:6063

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

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

References ATTRIBUTE_FIXED_PART_SIZE, CLASS_TUPLE_SIZE, TupleDescData::constr, CreateTemplateTupleDesc(), fb(), GetHeapamTableAmRoutine(), TupleConstr::has_not_null, i, INVALID_PROC_NUMBER, InvalidRelFileNumber, InvalidSubTransactionId, IsBootstrapProcessingMode, memcpy(), 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 TupleDescFinalize().

Referenced by RelationCacheInitializePhase2(), and RelationCacheInitializePhase3().

◆ GetPgClassDescriptor()

static TupleDesc GetPgClassDescriptor ( void  )
static

Definition at line 4451 of file relcache.c.

4452{
4453 static TupleDesc pgclassdesc = NULL;
4454
4455 /* Already done? */
4456 if (pgclassdesc == NULL)
4459
4460 return pgclassdesc;
4461}
static TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs)
Definition relcache.c:4422
static const FormData_pg_attribute Desc_pg_class[Natts_pg_class]
Definition relcache.c:113

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

Referenced by RelationParseRelOptions().

◆ GetPgIndexDescriptor()

static TupleDesc GetPgIndexDescriptor ( void  )
static

Definition at line 4464 of file relcache.c.

4465{
4466 static TupleDesc pgindexdesc = NULL;
4467
4468 /* Already done? */
4469 if (pgindexdesc == NULL)
4472
4473 return pgindexdesc;
4474}
static const FormData_pg_attribute Desc_pg_index[Natts_pg_index]
Definition relcache.c:120

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

1613{
1614 int attIndex;
1615
1617 {
1619
1620 if (!OidIsValid(indclass->values[attIndex]))
1621 elog(ERROR, "bogus pg_index tuple");
1622
1623 /* look up the info for this opclass, using a cache */
1626
1627 /* copy cached data into relcache entry */
1628 opFamily[attIndex] = opcentry->opcfamily;
1629 opcInType[attIndex] = opcentry->opcintype;
1630 if (maxSupportNumber > 0)
1632 opcentry->supportProcs,
1633 maxSupportNumber * sizeof(RegProcedure));
1634 }
1635}
regproc RegProcedure
Definition c.h:734
#define OidIsValid(objectId)
Definition c.h:858
#define ERROR
Definition elog.h:40
static OpClassCacheEnt * LookupOpclassInfo(Oid operatorClassOid, StrategyNumber numSupport)
Definition relcache.c:1658

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

Referenced by RelationInitIndexAccessInfo().

◆ InitIndexAmRoutine()

static void InitIndexAmRoutine ( Relation  relation)
static

Definition at line 1417 of file relcache.c.

1418{
1420
1421 /*
1422 * We formerly specified that the amhandler should return a palloc'd
1423 * struct. That's now deprecated in favor of returning a pointer to a
1424 * static struct, but to avoid completely breaking old external AMs, run
1425 * the amhandler in the relation's rd_indexcxt.
1426 */
1428 relation->rd_indam = GetIndexAmRoutine(relation->rd_amhandler);
1430}
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 1811 of file relcache.c.

1812{
1813 relation->rd_tableam = GetTableAmRoutine(relation->rd_amhandler);
1814}
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 4384 of file relcache.c.

4385{
4386 Relation ird;
4387
4388 /*
4389 * We must lock the underlying catalog before locking the index to avoid
4390 * deadlock, since RelationBuildDesc might well need to read the catalog,
4391 * and if anyone else is exclusive-locking this catalog and index they'll
4392 * be doing it in that order.
4393 */
4396 ird = RelationBuildDesc(indexoid, true);
4397 if (ird == NULL)
4398 ereport(PANIC,
4400 errmsg_internal("could not open critical system index %u", indexoid));
4401 ird->rd_isnailed = true;
4402 ird->rd_refcnt = 1;
4405
4407}
int errcode(int sqlerrcode)
Definition elog.c:874
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#define PANIC
Definition elog.h:44
#define ereport(elevel,...)
Definition elog.h:152
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:1055
bytea ** RelationGetIndexAttOptions(Relation relation, bool copy)
Definition relcache.c:6002

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

6182{
6183 FILE *fp;
6184 char initfilename[MAXPGPATH];
6185 Relation *rels;
6186 int relno,
6187 num_rels,
6188 max_rels,
6191 magic;
6192 int i;
6193
6194 if (shared)
6195 snprintf(initfilename, sizeof(initfilename), "global/%s",
6197 else
6198 snprintf(initfilename, sizeof(initfilename), "%s/%s",
6200
6202 if (fp == NULL)
6203 return false;
6204
6205 /*
6206 * Read the index relcache entries from the file. Note we will not enter
6207 * any of them into the cache if the read fails partway through; this
6208 * helps to guard against broken init files.
6209 */
6210 max_rels = 100;
6211 rels = (Relation *) palloc(max_rels * sizeof(Relation));
6212 num_rels = 0;
6214
6215 /* check for correct magic number (compatible version) */
6216 if (fread(&magic, 1, sizeof(magic), fp) != sizeof(magic))
6217 goto read_failed;
6218 if (magic != RELCACHE_INIT_FILEMAGIC)
6219 goto read_failed;
6220
6221 for (relno = 0;; relno++)
6222 {
6223 Size len;
6224 size_t nread;
6225 Relation rel;
6227 bool has_not_null;
6228
6229 /* first read the relation descriptor length */
6230 nread = fread(&len, 1, sizeof(len), fp);
6231 if (nread != sizeof(len))
6232 {
6233 if (nread == 0)
6234 break; /* end of file */
6235 goto read_failed;
6236 }
6237
6238 /* safety check for incompatible relcache layout */
6239 if (len != sizeof(RelationData))
6240 goto read_failed;
6241
6242 /* allocate another relcache header */
6243 if (num_rels >= max_rels)
6244 {
6245 max_rels *= 2;
6246 rels = (Relation *) repalloc(rels, max_rels * sizeof(Relation));
6247 }
6248
6249 rel = rels[num_rels++] = (Relation) palloc(len);
6250
6251 /* then, read the Relation structure */
6252 if (fread(rel, 1, len, fp) != len)
6253 goto read_failed;
6254
6255 /* next read the relation tuple form */
6256 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6257 goto read_failed;
6258
6260 if (fread(relform, 1, len, fp) != len)
6261 goto read_failed;
6262
6263 rel->rd_rel = relform;
6264
6265 /* initialize attribute tuple forms */
6266 rel->rd_att = CreateTemplateTupleDesc(relform->relnatts);
6267 rel->rd_att->tdrefcount = 1; /* mark as refcounted */
6268
6269 rel->rd_att->tdtypeid = relform->reltype ? relform->reltype : RECORDOID;
6270 rel->rd_att->tdtypmod = -1; /* just to be sure */
6271
6272 /* next read all the attribute tuple form data entries */
6273 has_not_null = false;
6274 for (i = 0; i < relform->relnatts; i++)
6275 {
6277
6278 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6279 goto read_failed;
6281 goto read_failed;
6282 if (fread(attr, 1, len, fp) != len)
6283 goto read_failed;
6284
6285 has_not_null |= attr->attnotnull;
6286
6288 }
6289
6291
6292 /* next read the access method specific field */
6293 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6294 goto read_failed;
6295 if (len > 0)
6296 {
6297 rel->rd_options = palloc(len);
6298 if (fread(rel->rd_options, 1, len, fp) != len)
6299 goto read_failed;
6300 if (len != VARSIZE(rel->rd_options))
6301 goto read_failed; /* sanity check */
6302 }
6303 else
6304 {
6305 rel->rd_options = NULL;
6306 }
6307
6308 /* mark not-null status */
6309 if (has_not_null)
6310 {
6312
6313 constr->has_not_null = true;
6314 rel->rd_att->constr = constr;
6315 }
6316
6317 /*
6318 * If it's an index, there's more to do. Note we explicitly ignore
6319 * partitioned indexes here.
6320 */
6321 if (rel->rd_rel->relkind == RELKIND_INDEX)
6322 {
6324 Oid *opfamily;
6325 Oid *opcintype;
6327 int nsupport;
6330
6331 /* Count nailed indexes to ensure we have 'em all */
6332 if (rel->rd_isnailed)
6334
6335 /* read the pg_index tuple */
6336 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6337 goto read_failed;
6338
6340 if (fread(rel->rd_indextuple, 1, len, fp) != len)
6341 goto read_failed;
6342
6343 /* Fix up internal pointers in the tuple -- see heap_copytuple */
6346
6347 /*
6348 * prepare index info context --- parameters should match
6349 * RelationInitIndexAccessInfo
6350 */
6352 "index info",
6354 rel->rd_indexcxt = indexcxt;
6357
6358 /*
6359 * Now we can fetch the index AM's API struct. (We can't store
6360 * that in the init file, since it contains function pointers that
6361 * might vary across server executions. Fortunately, it should be
6362 * safe to call the amhandler even while bootstrapping indexes.)
6363 */
6364 InitIndexAmRoutine(rel);
6365
6366 /* read the vector of opfamily OIDs */
6367 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6368 goto read_failed;
6369
6370 opfamily = (Oid *) MemoryContextAlloc(indexcxt, len);
6371 if (fread(opfamily, 1, len, fp) != len)
6372 goto read_failed;
6373
6374 rel->rd_opfamily = opfamily;
6375
6376 /* read the vector of opcintype OIDs */
6377 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6378 goto read_failed;
6379
6380 opcintype = (Oid *) MemoryContextAlloc(indexcxt, len);
6381 if (fread(opcintype, 1, len, fp) != len)
6382 goto read_failed;
6383
6384 rel->rd_opcintype = opcintype;
6385
6386 /* read the vector of support procedure OIDs */
6387 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6388 goto read_failed;
6390 if (fread(support, 1, len, fp) != len)
6391 goto read_failed;
6392
6393 rel->rd_support = support;
6394
6395 /* read the vector of collation OIDs */
6396 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6397 goto read_failed;
6398
6400 if (fread(indcollation, 1, len, fp) != len)
6401 goto read_failed;
6402
6404
6405 /* read the vector of indoption values */
6406 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6407 goto read_failed;
6408
6410 if (fread(indoption, 1, len, fp) != len)
6411 goto read_failed;
6412
6413 rel->rd_indoption = indoption;
6414
6415 /* read the vector of opcoptions values */
6416 rel->rd_opcoptions = (bytea **)
6417 MemoryContextAllocZero(indexcxt, sizeof(*rel->rd_opcoptions) * relform->relnatts);
6418
6419 for (i = 0; i < relform->relnatts; i++)
6420 {
6421 if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
6422 goto read_failed;
6423
6424 if (len > 0)
6425 {
6427 if (fread(rel->rd_opcoptions[i], 1, len, fp) != len)
6428 goto read_failed;
6429 }
6430 }
6431
6432 /* set up zeroed fmgr-info vector */
6433 nsupport = relform->relnatts * rel->rd_indam->amsupport;
6434 rel->rd_supportinfo = (FmgrInfo *)
6436 }
6437 else
6438 {
6439 /* Count nailed rels to ensure we have 'em all */
6440 if (rel->rd_isnailed)
6441 nailed_rels++;
6442
6443 /* Load table AM data */
6444 if (RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind) || rel->rd_rel->relkind == RELKIND_SEQUENCE)
6446
6447 Assert(rel->rd_index == NULL);
6448 Assert(rel->rd_indextuple == NULL);
6449 Assert(rel->rd_indexcxt == NULL);
6450 Assert(rel->rd_indam == NULL);
6451 Assert(rel->rd_opfamily == NULL);
6452 Assert(rel->rd_opcintype == NULL);
6453 Assert(rel->rd_support == NULL);
6454 Assert(rel->rd_supportinfo == NULL);
6455 Assert(rel->rd_indoption == NULL);
6456 Assert(rel->rd_indcollation == NULL);
6457 Assert(rel->rd_opcoptions == NULL);
6458 }
6459
6460 /*
6461 * Rules and triggers are not saved (mainly because the internal
6462 * format is complex and subject to change). They must be rebuilt if
6463 * needed by RelationCacheInitializePhase3. This is not expected to
6464 * be a big performance hit since few system catalogs have such. Ditto
6465 * for RLS policy data, partition info, index expressions, predicates,
6466 * exclusion info, and FDW info.
6467 */
6468 rel->rd_rules = NULL;
6469 rel->rd_rulescxt = NULL;
6470 rel->trigdesc = NULL;
6471 rel->rd_rsdesc = NULL;
6472 rel->rd_partkey = NULL;
6473 rel->rd_partkeycxt = NULL;
6474 rel->rd_partdesc = NULL;
6477 rel->rd_pdcxt = NULL;
6478 rel->rd_pddcxt = NULL;
6479 rel->rd_partcheck = NIL;
6480 rel->rd_partcheckvalid = false;
6481 rel->rd_partcheckcxt = NULL;
6482 rel->rd_indexprs = NIL;
6483 rel->rd_indpred = NIL;
6484 rel->rd_exclops = NULL;
6485 rel->rd_exclprocs = NULL;
6486 rel->rd_exclstrats = NULL;
6487 rel->rd_fdwroutine = NULL;
6488
6489 /*
6490 * Reset transient-state fields in the relcache entry
6491 */
6492 rel->rd_smgr = NULL;
6493 if (rel->rd_isnailed)
6494 rel->rd_refcnt = 1;
6495 else
6496 rel->rd_refcnt = 0;
6497 rel->rd_indexvalid = false;
6498 rel->rd_indexlist = NIL;
6499 rel->rd_pkindex = InvalidOid;
6501 rel->rd_attrsvalid = false;
6502 rel->rd_keyattr = NULL;
6503 rel->rd_pkattr = NULL;
6504 rel->rd_idattr = NULL;
6505 rel->rd_pubdesc = NULL;
6506 rel->rd_statvalid = false;
6507 rel->rd_statlist = NIL;
6508 rel->rd_fkeyvalid = false;
6509 rel->rd_fkeylist = NIL;
6514 rel->rd_amcache = NULL;
6515 rel->pgstat_info = NULL;
6516
6517 /*
6518 * Recompute lock and physical addressing info. This is needed in
6519 * case the pg_internal.init file was copied from some other database
6520 * by CREATE DATABASE.
6521 */
6524 }
6525
6526 /*
6527 * We reached the end of the init file without apparent problem. Did we
6528 * get the right number of nailed items? This is a useful crosscheck in
6529 * case the set of critical rels or indexes changes. However, that should
6530 * not happen in a normally-running system, so let's bleat if it does.
6531 *
6532 * For the shared init file, we're called before client authentication is
6533 * done, which means that elog(WARNING) will go only to the postmaster
6534 * log, where it's easily missed. To ensure that developers notice bad
6535 * values of NUM_CRITICAL_SHARED_RELS/NUM_CRITICAL_SHARED_INDEXES, we put
6536 * an Assert(false) there.
6537 */
6538 if (shared)
6539 {
6542 {
6543 elog(WARNING, "found %d nailed shared rels and %d nailed shared indexes in init file, but expected %d and %d respectively",
6546 /* Make sure we get developers' attention about this */
6547 Assert(false);
6548 /* In production builds, recover by bootstrapping the relcache */
6549 goto read_failed;
6550 }
6551 }
6552 else
6553 {
6556 {
6557 elog(WARNING, "found %d nailed rels and %d nailed indexes in init file, but expected %d and %d respectively",
6560 /* We don't need an Assert() in this case */
6561 goto read_failed;
6562 }
6563 }
6564
6565 /*
6566 * OK, all appears well.
6567 *
6568 * Now insert all the new relcache entries into the cache.
6569 */
6570 for (relno = 0; relno < num_rels; relno++)
6571 {
6572 RelationCacheInsert(rels[relno], false);
6573 }
6574
6575 pfree(rels);
6576 FreeFile(fp);
6577
6578 if (shared)
6580 else
6582 return true;
6583
6584 /*
6585 * init file is broken, so do it the hard way. We don't bother trying to
6586 * free the clutter we just allocated; it's not in the relcache so it
6587 * won't hurt.
6588 */
6590 pfree(rels);
6591 FreeFile(fp);
6592
6593 return false;
6594}
#define PG_BINARY_R
Definition c.h:1376
size_t Size
Definition c.h:689
int FreeFile(FILE *file)
Definition fd.c:2827
FILE * AllocateFile(const char *name, const char *mode)
Definition fd.c:2628
struct RelationData * Relation
Definition genam.h:30
char * DatabasePath
Definition globals.c:106
#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
END_CATALOG_STRUCT typedef FormData_pg_index * Form_pg_index
Definition pg_index.h:74
#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:142
bool criticalSharedRelcachesBuilt
Definition relcache.c:148
static void InitIndexAmRoutine(Relation relation)
Definition relcache.c:1417
#define NUM_CRITICAL_SHARED_RELS
void RelationInitTableAccessMethod(Relation relation)
Definition relcache.c:1820
#define NUM_CRITICAL_LOCAL_INDEXES
#define RELCACHE_INIT_FILEMAGIC
Definition relcache.c:95
#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(), Form_pg_index, 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(), TupleDescFinalize(), VARSIZE(), and WARNING.

Referenced by RelationCacheInitializePhase2(), and RelationCacheInitializePhase3().

◆ LookupOpclassInfo()

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

Definition at line 1658 of file relcache.c.

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

References AccessShareLock, Assert, BTEqualStrategyNumber, CacheMemoryContext, CreateCacheMemoryContext(), criticalRelcachesBuilt, ctl, debug_discard_caches, elog, ERROR, fb(), Form_pg_amproc, Form_pg_opclass, 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 3968 of file relcache.c.

3969{
3973
3974 /* Flag relation as needing eoxact cleanup (to clear these fields) */
3975 EOXactListAdd(relation);
3976}
#define EOXactListAdd(rel)
Definition relcache.c:191
SubTransactionId GetCurrentSubTransactionId(void)
Definition xact.c:793

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

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

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

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

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(), TupleDescCompactAttr(), and TupleDescFinalize().

Referenced by heap_create().

◆ RelationBuildPublicationDesc()

void RelationBuildPublicationDesc ( Relation  relation,
PublicationDesc pubdesc 
)

Definition at line 5785 of file relcache.c.

5786{
5787 List *puboids = NIL;
5790 ListCell *lc;
5792 Oid schemaid;
5793 List *ancestors = NIL;
5794 Oid relid = RelationGetRelid(relation);
5795
5796 /*
5797 * If not publishable, it publishes no actions. (pgoutput_change() will
5798 * ignore it.)
5799 */
5800 if (!is_publishable_relation(relation))
5801 {
5802 memset(pubdesc, 0, sizeof(PublicationDesc));
5803 pubdesc->rf_valid_for_update = true;
5804 pubdesc->rf_valid_for_delete = true;
5805 pubdesc->cols_valid_for_update = true;
5806 pubdesc->cols_valid_for_delete = true;
5807 pubdesc->gencols_valid_for_update = true;
5808 pubdesc->gencols_valid_for_delete = true;
5809 return;
5810 }
5811
5812 if (relation->rd_pubdesc)
5813 {
5814 memcpy(pubdesc, relation->rd_pubdesc, sizeof(PublicationDesc));
5815 return;
5816 }
5817
5818 memset(pubdesc, 0, sizeof(PublicationDesc));
5819 pubdesc->rf_valid_for_update = true;
5820 pubdesc->rf_valid_for_delete = true;
5821 pubdesc->cols_valid_for_update = true;
5822 pubdesc->cols_valid_for_delete = true;
5823 pubdesc->gencols_valid_for_update = true;
5824 pubdesc->gencols_valid_for_delete = true;
5825
5826 /* Fetch the publication membership info. */
5828 schemaid = RelationGetNamespace(relation);
5830
5831 if (relation->rd_rel->relispartition)
5832 {
5834
5835 /* Add publications that the ancestors are in too. */
5836 ancestors = get_partition_ancestors(relid);
5837 last_ancestor_relid = llast_oid(ancestors);
5838
5839 foreach(lc, ancestors)
5840 {
5842
5848 }
5849
5850 /*
5851 * Only the top-most ancestor can appear in the EXCEPT clause.
5852 * Therefore, for a partition, exclusion must be evaluated at the
5853 * top-most ancestor.
5854 */
5856 }
5857 else
5858 {
5859 /*
5860 * For a regular table or a root partitioned table, check exclusion on
5861 * table itself.
5862 */
5864 }
5865
5869 exceptpuboids));
5870 foreach(lc, puboids)
5871 {
5872 Oid pubid = lfirst_oid(lc);
5873 HeapTuple tup;
5876 bool invalid_gen_col;
5877
5879
5880 if (!HeapTupleIsValid(tup))
5881 elog(ERROR, "cache lookup failed for publication %u", pubid);
5882
5884
5885 pubdesc->pubactions.pubinsert |= pubform->pubinsert;
5886 pubdesc->pubactions.pubupdate |= pubform->pubupdate;
5887 pubdesc->pubactions.pubdelete |= pubform->pubdelete;
5888 pubdesc->pubactions.pubtruncate |= pubform->pubtruncate;
5889
5890 /*
5891 * Check if all columns referenced in the filter expression are part
5892 * of the REPLICA IDENTITY index or not.
5893 *
5894 * If the publication is FOR ALL TABLES then it means the table has no
5895 * row filters and we can skip the validation.
5896 */
5897 if (!pubform->puballtables &&
5898 (pubform->pubupdate || pubform->pubdelete) &&
5899 pub_rf_contains_invalid_column(pubid, relation, ancestors,
5900 pubform->pubviaroot))
5901 {
5902 if (pubform->pubupdate)
5903 pubdesc->rf_valid_for_update = false;
5904 if (pubform->pubdelete)
5905 pubdesc->rf_valid_for_delete = false;
5906 }
5907
5908 /*
5909 * Check if all columns are part of the REPLICA IDENTITY index or not.
5910 *
5911 * Check if all generated columns included in the REPLICA IDENTITY are
5912 * published.
5913 */
5914 if ((pubform->pubupdate || pubform->pubdelete) &&
5915 pub_contains_invalid_column(pubid, relation, ancestors,
5916 pubform->pubviaroot,
5917 pubform->pubgencols,
5920 {
5921 if (pubform->pubupdate)
5922 {
5923 pubdesc->cols_valid_for_update = !invalid_column_list;
5924 pubdesc->gencols_valid_for_update = !invalid_gen_col;
5925 }
5926
5927 if (pubform->pubdelete)
5928 {
5929 pubdesc->cols_valid_for_delete = !invalid_column_list;
5930 pubdesc->gencols_valid_for_delete = !invalid_gen_col;
5931 }
5932 }
5933
5935
5936 /*
5937 * If we know everything is replicated and the row filter is invalid
5938 * for update and delete, there is no point to check for other
5939 * publications.
5940 */
5941 if (pubdesc->pubactions.pubinsert && pubdesc->pubactions.pubupdate &&
5942 pubdesc->pubactions.pubdelete && pubdesc->pubactions.pubtruncate &&
5943 !pubdesc->rf_valid_for_update && !pubdesc->rf_valid_for_delete)
5944 break;
5945
5946 /*
5947 * If we know everything is replicated and the column list is invalid
5948 * for update and delete, there is no point to check for other
5949 * publications.
5950 */
5951 if (pubdesc->pubactions.pubinsert && pubdesc->pubactions.pubupdate &&
5952 pubdesc->pubactions.pubdelete && pubdesc->pubactions.pubtruncate &&
5953 !pubdesc->cols_valid_for_update && !pubdesc->cols_valid_for_delete)
5954 break;
5955
5956 /*
5957 * If we know everything is replicated and replica identity has an
5958 * unpublished generated column, there is no point to check for other
5959 * publications.
5960 */
5961 if (pubdesc->pubactions.pubinsert && pubdesc->pubactions.pubupdate &&
5962 pubdesc->pubactions.pubdelete && pubdesc->pubactions.pubtruncate &&
5963 !pubdesc->gencols_valid_for_update &&
5964 !pubdesc->gencols_valid_for_delete)
5965 break;
5966 }
5967
5968 if (relation->rd_pubdesc)
5969 {
5970 pfree(relation->rd_pubdesc);
5971 relation->rd_pubdesc = NULL;
5972 }
5973
5974 /* Now save copy of the descriptor in the relcache entry. */
5977 memcpy(relation->rd_pubdesc, pubdesc, sizeof(PublicationDesc));
5979}
#define palloc_object(type)
Definition fe_memutils.h:74
List * list_concat_unique_oid(List *list1, const List *list2)
Definition list.c:1469
List * list_difference_oid(const List *list1, const List *list2)
Definition list.c:1313
Oid get_rel_namespace(Oid relid)
Definition lsyscache.c:2172
List * get_partition_ancestors(Oid relid)
Definition partition.c:134
#define llast_oid(l)
Definition pg_list.h:200
#define lfirst_oid(lc)
Definition pg_list.h:174
List * GetAllTablesPublications(void)
List * GetRelationIncludedPublications(Oid relid)
List * GetSchemaPublications(Oid schemaid)
List * GetRelationExcludedPublications(Oid relid)
bool is_publishable_relation(Relation rel)
END_CATALOG_STRUCT typedef 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:265
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221

References CacheMemoryContext, elog, ERROR, fb(), Form_pg_publication, get_partition_ancestors(), get_rel_namespace(), GetAllTablesPublications(), GetRelationExcludedPublications(), GetRelationIncludedPublications(), GetSchemaPublications(), GETSTRUCT(), HeapTupleIsValid, is_publishable_relation(), lfirst_oid, list_concat_unique_oid(), list_difference_oid(), llast_oid, memcpy(), 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 748 of file relcache.c.

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

528{
532 ScanKeyData skey[2];
533 int need;
534 TupleConstr *constr;
536 int ndef = 0;
537
538 /* fill rd_att's type ID fields (compare heap.c's AddNewRelationTuple) */
539 relation->rd_att->tdtypeid =
540 relation->rd_rel->reltype ? relation->rd_rel->reltype : RECORDOID;
541 relation->rd_att->tdtypmod = -1; /* just to be sure */
542
544 sizeof(TupleConstr));
545
546 /*
547 * Form a scan key that selects only user attributes (attnum > 0).
548 * (Eliminating system attribute rows at the index level is lots faster
549 * than fetching them.)
550 */
551 ScanKeyInit(&skey[0],
555 ScanKeyInit(&skey[1],
558 Int16GetDatum(0));
559
560 /*
561 * Open pg_attribute and begin a scan. Force heap scan if we haven't yet
562 * built the critical relcache entries (this includes initdb and startup
563 * without a pg_internal.init file).
564 */
569 NULL,
570 2, skey);
571
572 /*
573 * add attribute data to relation->rd_att
574 */
576
578 {
580 int attnum;
581
583
584 attnum = attp->attnum;
586 elog(ERROR, "invalid attribute number %d for relation \"%s\"",
587 attp->attnum, RelationGetRelationName(relation));
588
589 memcpy(TupleDescAttr(relation->rd_att, attnum - 1),
590 attp,
592
594
595 /* Update constraint/default info */
596 if (attp->attnotnull)
597 constr->has_not_null = true;
598 if (attp->attgenerated == ATTRIBUTE_GENERATED_STORED)
599 constr->has_generated_stored = true;
600 if (attp->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
601 constr->has_generated_virtual = true;
602 if (attp->atthasdef)
603 ndef++;
604
605 /* If the column has a "missing" value, put it in the attrmiss array */
606 if (attp->atthasmissing)
607 {
609 bool missingNull;
610
611 /* Do we have a missing value? */
614 pg_attribute_desc->rd_att,
615 &missingNull);
616 if (!missingNull)
617 {
618 /* Yes, fetch from the array */
620 bool is_null;
621 int one = 1;
623
624 if (attrmiss == NULL)
627 relation->rd_rel->relnatts *
628 sizeof(AttrMissing));
629
631 1,
632 &one,
633 -1,
634 attp->attlen,
635 attp->attbyval,
636 attp->attalign,
637 &is_null);
638 Assert(!is_null);
639 if (attp->attbyval)
640 {
641 /* for copy by val just copy the datum direct */
642 attrmiss[attnum - 1].am_value = missval;
643 }
644 else
645 {
646 /* otherwise copy in the correct context */
648 attrmiss[attnum - 1].am_value = datumCopy(missval,
649 attp->attbyval,
650 attp->attlen);
652 }
653 attrmiss[attnum - 1].am_present = true;
654 }
655 }
656 need--;
657 if (need == 0)
658 break;
659 }
660
661 /*
662 * end the scan and close the attribute relation
663 */
666
667 if (need != 0)
668 elog(ERROR, "pg_attribute catalog is missing %d attribute(s) for relation OID %u",
669 need, RelationGetRelid(relation));
670
671 /*
672 * Set up constraint/default info
673 */
674 if (constr->has_not_null ||
675 constr->has_generated_stored ||
676 constr->has_generated_virtual ||
677 ndef > 0 ||
678 attrmiss ||
679 relation->rd_rel->relchecks > 0)
680 {
681 bool is_catalog = IsCatalogRelation(relation);
682
683 relation->rd_att->constr = constr;
684
685 if (ndef > 0) /* DEFAULTs */
686 AttrDefaultFetch(relation, ndef);
687 else
688 constr->num_defval = 0;
689
690 constr->missing = attrmiss;
691
692 /* CHECK and NOT NULLs */
693 if (relation->rd_rel->relchecks > 0 ||
694 (!is_catalog && constr->has_not_null))
695 CheckNNConstraintFetch(relation);
696
697 /*
698 * Any not-null constraint that wasn't marked invalid by
699 * CheckNNConstraintFetch must necessarily be valid; make it so in the
700 * CompactAttribute array.
701 */
702 if (!is_catalog)
703 {
704 for (int i = 0; i < relation->rd_rel->relnatts; i++)
705 {
706 CompactAttribute *attr;
707
708 attr = TupleDescCompactAttr(relation->rd_att, i);
709
712 else
715 }
716 }
717
718 if (relation->rd_rel->relchecks == 0)
719 constr->num_check = 0;
720 }
721 else
722 {
723 pfree(constr);
724 relation->rd_att->constr = NULL;
725 }
726
727 TupleDescFinalize(relation->rd_att);
728}
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:172
#define RelationGetNumberOfAttributes(relation)
Definition rel.h:522
static void CheckNNConstraintFetch(Relation relation)
Definition relcache.c:4582
static void AttrDefaultFetch(Relation relation, int ndef)
Definition relcache.c:4486
#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::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(), memcpy(), 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(), TupleDescCompactAttr(), and TupleDescFinalize().

Referenced by RelationBuildDesc().

◆ RelationCacheInitFilePostInvalidate()

void RelationCacheInitFilePostInvalidate ( void  )

Definition at line 6901 of file relcache.c.

6902{
6904}
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1767

References fb(), and LWLockRelease().

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

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )

Definition at line 6876 of file relcache.c.

6877{
6880
6881 if (DatabasePath)
6882 snprintf(localinitfname, sizeof(localinitfname), "%s/%s",
6884 snprintf(sharedinitfname, sizeof(sharedinitfname), "global/%s",
6886
6888
6889 /*
6890 * The files might not be there if no backend has been started since the
6891 * last removal. But complain about failures other than ENOENT with
6892 * ERROR. Fortunately, it's not too late to abort the transaction if we
6893 * can't get rid of the would-be-obsolete init file.
6894 */
6895 if (DatabasePath)
6898}
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1150
@ LW_EXCLUSIVE
Definition lwlock.h:104
static void unlink_initfile(const char *initfilename, int elevel)
Definition relcache.c:6973

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

6917{
6918 const char *tblspcdir = PG_TBLSPC_DIR;
6919 DIR *dir;
6920 struct dirent *de;
6921 char path[MAXPGPATH + sizeof(PG_TBLSPC_DIR) + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6922
6923 snprintf(path, sizeof(path), "global/%s",
6925 unlink_initfile(path, LOG);
6926
6927 /* Scan everything in the default tablespace */
6929
6930 /* Scan the tablespace link directory to find non-default tablespaces */
6931 dir = AllocateDir(tblspcdir);
6932
6933 while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6934 {
6935 if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6936 {
6937 /* Scan the tablespace dir for per-database dirs */
6938 snprintf(path, sizeof(path), "%s/%s/%s",
6941 }
6942 }
6943
6944 FreeDir(dir);
6945}
#define LOG
Definition elog.h:32
int FreeDir(DIR *dir)
Definition fd.c:3009
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition fd.c:2972
DIR * AllocateDir(const char *dirname)
Definition fd.c:2891
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition relcache.c:6949
#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 6949 of file relcache.c.

6950{
6951 DIR *dir;
6952 struct dirent *de;
6953 char initfilename[MAXPGPATH * 2];
6954
6955 /* Scan the tablespace directory to find per-database directories */
6956 dir = AllocateDir(tblspcpath);
6957
6958 while ((de = ReadDirExtended(dir, tblspcpath, LOG)) != NULL)
6959 {
6960 if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6961 {
6962 /* Try to remove the init file in each database */
6963 snprintf(initfilename, sizeof(initfilename), "%s/%s/%s",
6966 }
6967 }
6968
6969 FreeDir(dir);
6970}

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

Referenced by RelationCacheInitFileRemove().

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 3994 of file relcache.c.

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

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

4041{
4043
4044 /*
4045 * relation mapper needs initialized too
4046 */
4048
4049 /*
4050 * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
4051 * nothing.
4052 */
4054 return;
4055
4056 /*
4057 * switch to cache memory context
4058 */
4060
4061 /*
4062 * Try to load the shared relcache cache file. If unsuccessful, bootstrap
4063 * the cache with pre-made descriptors for the critical shared catalogs.
4064 */
4065 if (!load_relcache_init_file(true))
4066 {
4067 formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
4069 formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
4071 formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
4073 formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
4075 formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
4077
4078#define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
4079 }
4080
4082}
static bool load_relcache_init_file(bool shared)
Definition relcache.c:6181
static const FormData_pg_attribute Desc_pg_shseclabel[Natts_pg_shseclabel]
Definition relcache.c:121
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
Definition relcache.c:1885
static const FormData_pg_attribute Desc_pg_database[Natts_pg_database]
Definition relcache.c:117
static const FormData_pg_attribute Desc_pg_authid[Natts_pg_authid]
Definition relcache.c:118
static const FormData_pg_attribute Desc_pg_subscription[Natts_pg_subscription]
Definition relcache.c:122
static const FormData_pg_attribute Desc_pg_auth_members[Natts_pg_auth_members]
Definition relcache.c:119
void RelationMapInitializePhase2(void)
Definition relmapper.c:672

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

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

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(), memcpy(), 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 2984 of file relcache.c.

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

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

2929{
2930 Relation relation;
2931
2933
2934 if (relation)
2935 {
2937 RelationFlushRelation(relation);
2938 }
2939 else
2940 {
2941 int i;
2942
2943 for (i = 0; i < in_progress_list_len; i++)
2944 if (in_progress_list[i].reloid == relationId)
2946 }
2947}
#define RelationIdCacheLookup(ID, RELATION)
Definition relcache.c:233
static void RelationFlushRelation(Relation relation)
Definition relcache.c:2817

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

2537{
2539 Assert(!relation->rd_isnailed);
2540
2541 /*
2542 * Relations created in the same transaction must never be removed, see
2543 * RelationFlushRelation.
2544 */
2548
2549 /* first mark it as invalid */
2551
2552 /* Remove it from the hash table */
2553 RelationCacheDelete(relation);
2554
2555 /* And release storage */
2556 RelationDestroyRelation(relation, false);
2557}
#define RelationCacheDelete(RELATION)
Definition relcache.c:245

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

2211{
2212 /* Note: no locking manipulations needed */
2214
2215 RelationCloseCleanup(relation);
2216}
static void RelationCloseCleanup(Relation relation)
Definition relcache.c:2219

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

2220{
2221 /*
2222 * If the relation is no longer open in this session, we can clean up any
2223 * stale partition descriptors it has. This is unlikely, so check to see
2224 * if there are child contexts before expending a call to mcxt.c.
2225 */
2226 if (RelationHasReferenceCountZero(relation))
2227 {
2228 if (relation->rd_pdcxt != NULL &&
2229 relation->rd_pdcxt->firstchild != NULL)
2231
2232 if (relation->rd_pddcxt != NULL &&
2233 relation->rd_pddcxt->firstchild != NULL)
2235 }
2236
2237#ifdef RELCACHE_FORCE_RELEASE
2238 if (RelationHasReferenceCountZero(relation) &&
2241 RelationClearRelation(relation);
2242#endif
2243}
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 2190 of file relcache.c.

2191{
2192 Assert(rel->rd_refcnt > 0);
2193 rel->rd_refcnt -= 1;
2196}
static void ResourceOwnerForgetRelationRef(ResourceOwner owner, Relation rel)
Definition relcache.c:2163
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 2429 of file relcache.c.

2430{
2432
2433 /*
2434 * Make sure smgr and lower levels close the relation's files, if they
2435 * weren't closed already. (This was probably done by caller, but let's
2436 * just be real sure.)
2437 */
2438 RelationCloseSmgr(relation);
2439
2440 /* break mutual link with stats entry */
2441 pgstat_unlink_relation(relation);
2442
2443 /*
2444 * Free all the subsidiary data structures of the relcache entry, then the
2445 * entry itself.
2446 */
2447 if (relation->rd_rel)
2448 pfree(relation->rd_rel);
2449 /* can't use DecrTupleDescRefCount here */
2450 Assert(relation->rd_att->tdrefcount > 0);
2451 if (--relation->rd_att->tdrefcount == 0)
2452 {
2453 /*
2454 * If we Rebuilt a relcache entry during a transaction then its
2455 * possible we did that because the TupDesc changed as the result of
2456 * an ALTER TABLE that ran at less than AccessExclusiveLock. It's
2457 * possible someone copied that TupDesc, in which case the copy would
2458 * point to free'd memory. So if we rebuild an entry we keep the
2459 * TupDesc around until end of transaction, to be safe.
2460 */
2461 if (remember_tupdesc)
2463 else
2464 FreeTupleDesc(relation->rd_att);
2465 }
2466 FreeTriggerDesc(relation->trigdesc);
2467 list_free_deep(relation->rd_fkeylist);
2468 list_free(relation->rd_indexlist);
2469 list_free(relation->rd_statlist);
2470 bms_free(relation->rd_keyattr);
2471 bms_free(relation->rd_pkattr);
2472 bms_free(relation->rd_idattr);
2473 bms_free(relation->rd_hotblockingattr);
2474 bms_free(relation->rd_summarizedattr);
2475 if (relation->rd_pubdesc)
2476 pfree(relation->rd_pubdesc);
2477 if (relation->rd_options)
2478 pfree(relation->rd_options);
2479 if (relation->rd_indextuple)
2480 pfree(relation->rd_indextuple);
2481 if (relation->rd_amcache)
2482 pfree(relation->rd_amcache);
2483 if (relation->rd_fdwroutine)
2484 pfree(relation->rd_fdwroutine);
2485 if (relation->rd_indexcxt)
2487 if (relation->rd_rulescxt)
2489 if (relation->rd_rsdesc)
2491 if (relation->rd_partkeycxt)
2493 if (relation->rd_pdcxt)
2494 MemoryContextDelete(relation->rd_pdcxt);
2495 if (relation->rd_pddcxt)
2496 MemoryContextDelete(relation->rd_pddcxt);
2497 if (relation->rd_partcheckcxt)
2499 pfree(relation);
2500}
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:3094
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:2147

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

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

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

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

References Assert, elog, ERROR, 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 5147 of file relcache.c.

5148{
5149 List *result;
5151 bool isnull;
5152 char *exprsString;
5153 List *rawExprs;
5154 ListCell *lc;
5155
5156 /* Quick exit if there is nothing to do. */
5157 if (relation->rd_indextuple == NULL ||
5159 return NIL;
5160
5161 /* Extract raw node tree(s) from index tuple. */
5165 &isnull);
5166 Assert(!isnull);
5170
5171 /* Construct null Consts; the typlen and typbyval are arbitrary. */
5172 result = NIL;
5173 foreach(lc, rawExprs)
5174 {
5175 Node *rawExpr = (Node *) lfirst(lc);
5176
5181 1,
5182 (Datum) 0,
5183 true,
5184 true));
5185 }
5186
5187 return result;
5188}
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:304
Oid exprCollation(const Node *expr)
Definition nodeFuncs.c:826
static TupleDesc GetPgIndexDescriptor(void)
Definition relcache.c:4464

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

Referenced by BuildDummyIndexInfo().

◆ RelationGetExclusionInfo()

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

Definition at line 5644 of file relcache.c.

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

4723{
4724 List *result;
4728 HeapTuple htup;
4729 List *oldlist;
4731
4732 /* Quick exit if we already computed the list. */
4733 if (relation->rd_fkeyvalid)
4734 return relation->rd_fkeylist;
4735
4736 /*
4737 * We build the list we intend to return (in the caller's context) while
4738 * doing the scan. After successfully completing the scan, we copy that
4739 * list into the relcache entry. This avoids cache-context memory leakage
4740 * if we get some sort of error partway through.
4741 */
4742 result = NIL;
4743
4744 /* Prepare to scan pg_constraint for entries having conrelid = this rel. */
4749
4752 NULL, 1, &skey);
4753
4755 {
4756 Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(htup);
4757 ForeignKeyCacheInfo *info;
4758
4759 /* consider only foreign keys */
4760 if (constraint->contype != CONSTRAINT_FOREIGN)
4761 continue;
4762
4764 info->conoid = constraint->oid;
4765 info->conrelid = constraint->conrelid;
4766 info->confrelid = constraint->confrelid;
4767 info->conenforced = constraint->conenforced;
4768
4769 DeconstructFkConstraintRow(htup, &info->nkeys,
4770 info->conkey,
4771 info->confkey,
4772 info->conpfeqop,
4773 NULL, NULL, NULL, NULL);
4774
4775 /* Add FK's node to the result list */
4776 result = lappend(result, info);
4777 }
4778
4781
4782 /* Now save a copy of the completed list in the relcache entry. */
4784 oldlist = relation->rd_fkeylist;
4785 relation->rd_fkeylist = copyObject(result);
4786 relation->rd_fkeyvalid = true;
4788
4789 /* Don't leak the old list, if there is one */
4791
4792 return result;
4793}
#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(), Form_pg_constraint, GETSTRUCT(), HeapTupleIsValid, lappend(), list_free_deep(), makeNode, MemoryContextSwitchTo(), NIL, ForeignKeyCacheInfo::nkeys, ObjectIdGetDatum(), RelationData::rd_fkeylist, RelationData::rd_fkeyvalid, RelationGetRelid, result, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

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

◆ RelationGetIdentityKeyBitmap()

Bitmapset * RelationGetIdentityKeyBitmap ( Relation  relation)

Definition at line 5567 of file relcache.c.

5568{
5569 Bitmapset *idindexattrs = NULL; /* columns in the replica identity */
5571 int i;
5574
5575 /* Quick exit if we already computed the result */
5576 if (relation->rd_idattr != NULL)
5577 return bms_copy(relation->rd_idattr);
5578
5579 /* Fast path if definitely no indexes */
5580 if (!RelationGetForm(relation)->relhasindex)
5581 return NULL;
5582
5583 /* Historic snapshot must be set. */
5585
5587
5588 /* Fall out if there is no replica identity index */
5589 if (!OidIsValid(replidindex))
5590 return NULL;
5591
5592 /* Look up the description for the replica identity index */
5594
5596 elog(ERROR, "could not open relation with OID %u",
5597 relation->rd_replidindex);
5598
5599 /* Add referenced attributes to idindexattrs */
5600 for (i = 0; i < indexDesc->rd_index->indnatts; i++)
5601 {
5602 int attrnum = indexDesc->rd_index->indkey.values[i];
5603
5604 /*
5605 * We don't include non-key columns into idindexattrs bitmaps. See
5606 * RelationGetIndexAttrBitmap.
5607 */
5608 if (attrnum != 0)
5609 {
5610 if (i < indexDesc->rd_index->indnkeyatts)
5613 }
5614 }
5615
5617
5618 /* Don't leak the old values of these bitmaps, if any */
5619 bms_free(relation->rd_idattr);
5620 relation->rd_idattr = NULL;
5621
5622 /* Now save copy of the bitmap in the relcache entry */
5624 relation->rd_idattr = bms_copy(idindexattrs);
5626
5627 /* We return our original working copy for caller to play with */
5628 return idindexattrs;
5629}
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:799
Bitmapset * bms_copy(const Bitmapset *a)
Definition bitmapset.c:122
#define RelationGetForm(relation)
Definition rel.h:510
#define RelationIsValid(relation)
Definition rel.h:491
Oid RelationGetReplicaIndex(Relation relation)
Definition relcache.c:5063
Relation RelationIdGetRelation(Oid relationId)
Definition relcache.c:2089
void RelationClose(Relation relation)
Definition relcache.c:2210
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 6002 of file relcache.c.

6003{
6005 bytea **opts = relation->rd_opcoptions;
6006 Oid relid = RelationGetRelid(relation);
6007 int natts = RelationGetNumberOfAttributes(relation); /* XXX
6008 * IndexRelationGetNumberOfKeyAttributes */
6009 int i;
6010
6011 /* Try to copy cached options. */
6012 if (opts)
6013 return copy ? CopyIndexAttOptions(opts, natts) : opts;
6014
6015 /* Get and parse opclass options. */
6016 opts = palloc0_array(bytea *, natts);
6017
6018 for (i = 0; i < natts; i++)
6019 {
6021 {
6022 Datum attoptions = get_attoptions(relid, i + 1);
6023
6024 opts[i] = index_opclass_options(relation, i + 1, attoptions, false);
6025
6026 if (attoptions != (Datum) 0)
6027 pfree(DatumGetPointer(attoptions));
6028 }
6029 }
6030
6031 /* Copy parsed options to the cache. */
6033 relation->rd_opcoptions = CopyIndexAttOptions(opts, natts);
6035
6036 if (copy)
6037 return opts;
6038
6039 for (i = 0; i < natts; i++)
6040 {
6041 if (opts[i])
6042 pfree(opts[i]);
6043 }
6044
6045 pfree(opts);
6046
6047 return relation->rd_opcoptions;
6048}
#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:1016
Datum get_attoptions(Oid relid, int16 attnum)
Definition lsyscache.c:1089
static bytea ** CopyIndexAttOptions(bytea **srcopts, int natts)
Definition relcache.c:5982

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

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

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

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, result, 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 4827 of file relcache.c.

4828{
4832 HeapTuple htup;
4833 List *result;
4834 List *oldlist;
4835 char replident = relation->rd_rel->relreplident;
4838 bool pkdeferrable = false;
4840
4841 /* Quick exit if we already computed the list. */
4842 if (relation->rd_indexvalid)
4843 return list_copy(relation->rd_indexlist);
4844
4845 /*
4846 * We build the list we intend to return (in the caller's context) while
4847 * doing the scan. After successfully completing the scan, we copy that
4848 * list into the relcache entry. This avoids cache-context memory leakage
4849 * if we get some sort of error partway through.
4850 */
4851 result = NIL;
4852
4853 /* Prepare to scan pg_index for entries having indrelid = this rel. */
4858
4861 NULL, 1, &skey);
4862
4864 {
4866
4867 /*
4868 * Ignore any indexes that are currently being dropped. This will
4869 * prevent them from being searched, inserted into, or considered in
4870 * HOT-safety decisions. It's unsafe to touch such an index at all
4871 * since its catalog entries could disappear at any instant.
4872 */
4873 if (!index->indislive)
4874 continue;
4875
4876 /* add index's OID to result list */
4877 result = lappend_oid(result, index->indexrelid);
4878
4879 /*
4880 * Non-unique or predicate indexes aren't interesting for either oid
4881 * indexes or replication identity indexes, so don't check them.
4882 * Deferred ones are not useful for replication identity either; but
4883 * we do include them if they are PKs.
4884 */
4885 if (!index->indisunique ||
4887 continue;
4888
4889 /*
4890 * Remember primary key index, if any. For regular tables we do this
4891 * only if the index is valid; but for partitioned tables, then we do
4892 * it even if it's invalid.
4893 *
4894 * The reason for returning invalid primary keys for partitioned
4895 * tables is that we need it to prevent drop of not-null constraints
4896 * that may underlie such a primary key, which is only a problem for
4897 * partitioned tables.
4898 */
4899 if (index->indisprimary &&
4900 (index->indisvalid ||
4901 relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
4902 {
4903 pkeyIndex = index->indexrelid;
4904 pkdeferrable = !index->indimmediate;
4905 }
4906
4907 if (!index->indimmediate)
4908 continue;
4909
4910 if (!index->indisvalid)
4911 continue;
4912
4913 /* remember explicitly chosen replica index */
4914 if (index->indisreplident)
4915 candidateIndex = index->indexrelid;
4916 }
4917
4919
4921
4922 /* Sort the result list into OID order, per API spec. */
4924
4925 /* Now save a copy of the completed list in the relcache entry. */
4927 oldlist = relation->rd_indexlist;
4928 relation->rd_indexlist = list_copy(result);
4929 relation->rd_pkindex = pkeyIndex;
4930 relation->rd_ispkdeferrable = pkdeferrable;
4932 relation->rd_replidindex = pkeyIndex;
4933 else if (replident == REPLICA_IDENTITY_INDEX && OidIsValid(candidateIndex))
4934 relation->rd_replidindex = candidateIndex;
4935 else
4936 relation->rd_replidindex = InvalidOid;
4937 relation->rd_indexvalid = true;
4939
4940 /* Don't leak the old list, if there is one */
4942
4943 return result;
4944}
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(), Form_pg_index, 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, result, 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(), DefineIndex(), DefineRelation(), DetachPartitionFinalize(), determine_clustered_index(), do_analyze_rel(), ExecOpenIndices(), expandTableLikeClause(), FindUsableIndexForReplicaIdentityFull(), get_relation_info(), GetParentedForeignKeyRefs(), index_get_partition(), infer_arbiter_indexes(), mark_index_clustered(), rebuild_relation_finish_concurrent(), 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 5201 of file relcache.c.

5202{
5203 List *result;
5205 bool isnull;
5206 char *predString;
5208
5209 /* Quick exit if we already computed the result. */
5210 if (relation->rd_indpred)
5211 return copyObject(relation->rd_indpred);
5212
5213 /* Quick exit if there is nothing to do. */
5214 if (relation->rd_indextuple == NULL ||
5216 return NIL;
5217
5218 /*
5219 * We build the tree we intend to return in the caller's context. After
5220 * successfully completing the work, we copy it into the relcache entry.
5221 * This avoids problems if we get some sort of error partway through.
5222 */
5226 &isnull);
5227 Assert(!isnull);
5231
5232 /*
5233 * Run the expression through const-simplification and canonicalization.
5234 * This is not just an optimization, but is necessary, because the planner
5235 * will be comparing it to similarly-processed qual clauses, and may fail
5236 * to detect valid matches without this. This must match the processing
5237 * done to qual clauses in preprocess_expression()! (We can skip the
5238 * stuff involving subqueries, however, since we don't allow any in index
5239 * predicates.)
5240 */
5242
5243 result = (List *) canonicalize_qual((Expr *) result, false);
5244
5245 /* Also convert to implicit-AND format */
5247
5248 /* May as well fix opfuncids too */
5250
5251 /* Now save a copy of the completed tree in the relcache entry. */
5253 relation->rd_indpred = copyObject(result);
5255
5256 return result;
5257}
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, result, 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 5038 of file relcache.c.

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

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

Referenced by dropconstraint_internal(), GetRelationIdentityOrPK(), and propgraph_element_get_key().

◆ RelationGetReplicaIndex()

Oid RelationGetReplicaIndex ( Relation  relation)

Definition at line 5063 of file relcache.c.

5064{
5065 List *ilist;
5066
5067 if (!relation->rd_indexvalid)
5068 {
5069 /* RelationGetIndexList does the heavy lifting. */
5070 ilist = RelationGetIndexList(relation);
5072 Assert(relation->rd_indexvalid);
5073 }
5074
5075 return relation->rd_replidindex;
5076}

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

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

◆ RelationGetStatExtList()

List * RelationGetStatExtList ( Relation  relation)

Definition at line 4968 of file relcache.c.

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

References AccessShareLock, BTEqualStrategyNumber, CacheMemoryContext, fb(), Form_pg_statistic_ext, GETSTRUCT(), HeapTupleIsValid, lappend_oid(), list_copy(), list_free(), list_oid_cmp(), list_sort(), MemoryContextSwitchTo(), NIL, ObjectIdGetDatum(), RelationData::rd_statlist, RelationData::rd_statvalid, RelationGetRelid, result, 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 2089 of file relcache.c.

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

6837{
6842 {
6843 /*
6844 * If this Assert fails, we don't need the applicable special case
6845 * anymore.
6846 */
6848 return true;
6849 }
6851}
bool RelationSupportsSysCache(Oid relid)
Definition syscache.c:763

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

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

◆ RelationIncrementReferenceCount()

◆ RelationInitIndexAccessInfo()

void RelationInitIndexAccessInfo ( Relation  relation)

Definition at line 1436 of file relcache.c.

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

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, IndexAmRoutine::amsupport, Assert, CacheMemoryContext, DatumGetPointer(), elog, ERROR, fastgetattr(), fb(), Form_pg_am, Form_pg_index, GetPgIndexDescriptor(), GETSTRUCT(), heap_copytuple(), HeapTupleIsValid, IndexRelationGetNumberOfAttributes, IndexRelationGetNumberOfKeyAttributes, IndexSupportInitialize(), InitIndexAmRoutine(), InvalidOid, memcpy(), 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 1335 of file relcache.c.

1336{
1338
1339 /* these relations kinds never have storage */
1340 if (!RELKIND_HAS_STORAGE(relation->rd_rel->relkind))
1341 return;
1342
1343 if (relation->rd_rel->reltablespace)
1344 relation->rd_locator.spcOid = relation->rd_rel->reltablespace;
1345 else
1347 if (relation->rd_locator.spcOid == GLOBALTABLESPACE_OID)
1348 relation->rd_locator.dbOid = InvalidOid;
1349 else
1350 relation->rd_locator.dbOid = MyDatabaseId;
1351
1352 if (relation->rd_rel->relfilenode)
1353 {
1354 /*
1355 * Even if we are using a decoding snapshot that doesn't represent the
1356 * current state of the catalog we need to make sure the filenode
1357 * points to the current file since the older file will be gone (or
1358 * truncated). The new file will still contain older rows so lookups
1359 * in them will work correctly. This wouldn't work correctly if
1360 * rewrites were allowed to change the schema in an incompatible way,
1361 * but those are prevented both on catalog tables and on user tables
1362 * declared as additional catalog tables.
1363 */
1366 && IsTransactionState())
1367 {
1370
1372 RelationGetRelid(relation) != ClassOidIndexId,
1373 true);
1375 elog(ERROR, "could not find pg_class entry for %u",
1376 RelationGetRelid(relation));
1378
1379 relation->rd_rel->reltablespace = physrel->reltablespace;
1380 relation->rd_rel->relfilenode = physrel->relfilenode;
1382 }
1383
1384 relation->rd_locator.relNumber = relation->rd_rel->relfilenode;
1385 }
1386 else
1387 {
1388 /* Consult the relation mapper */
1389 relation->rd_locator.relNumber =
1391 relation->rd_rel->relisshared);
1393 elog(ERROR, "could not find relation mapping for relation \"%s\", OID %u",
1394 RelationGetRelationName(relation), relation->rd_id);
1395 }
1396
1397 /*
1398 * For RelationNeedsWAL() to answer correctly on parallel workers, restore
1399 * rd_firstRelfilelocatorSubid. No subtransactions start or end while in
1400 * parallel mode, so the specific SubTransactionId does not matter.
1401 */
1402 if (IsParallelWorker() && oldnumber != relation->rd_locator.relNumber)
1403 {
1406 else
1408 }
1409}
#define TopSubTransactionId
Definition c.h:743
Oid MyDatabaseTableSpace
Definition globals.c:98
Oid MyDatabaseId
Definition globals.c:96
#define IsParallelWorker()
Definition parallel.h:62
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition rel.h:695
RelFileNumber RelationMapOidToFilenumber(Oid relationId, bool shared)
Definition relmapper.c:166
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 1820 of file relcache.c.

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

References Assert, elog, ERROR, fb(), Form_pg_am, 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 2508 of file relcache.c.

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

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

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

References IndexAmRoutine::amoptions, CacheMemoryContext, extractRelOptions(), fb(), GetPgClassDescriptor(), memcpy(), 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 2575 of file relcache.c.

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

References Assert, AssertCouldGetRelation(), CLASS_TUPLE_SIZE, elog, equalRSDesc(), equalRuleLocks(), equalTupleDescs(), ERROR, fb(), HistoricSnapshotActive(), InvalidSubTransactionId, InvalidTransactionId, memcpy(), 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 2266 of file relcache.c.

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

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

References Assert, AssertCouldGetRelation(), CLASS_TUPLE_SIZE, criticalRelcachesBuilt, fb(), GETSTRUCT(), heap_freetuple(), memcpy(), 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 3765 of file relcache.c.

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

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

2164{
2166}
static const ResourceOwnerDesc relref_resowner_desc
Definition relcache.c:2147
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 2158 of file relcache.c.

2159{
2161}
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 6990 of file relcache.c.

6991{
6992 Relation rel = (Relation) DatumGetPointer(res);
6993
6994 return psprintf("relation \"%s\"", RelationGetRelationName(rel));
6995}
char * psprintf(const char *fmt,...)
Definition psprintf.c:43

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

◆ ResOwnerReleaseRelation()

static void ResOwnerReleaseRelation ( Datum  res)
static

Definition at line 6998 of file relcache.c.

6999{
7000 Relation rel = (Relation) DatumGetPointer(res);
7001
7002 /*
7003 * This reference has already been removed from the resource owner, so
7004 * just decrement reference count without calling
7005 * ResourceOwnerForgetRelationRef.
7006 */
7007 Assert(rel->rd_refcnt > 0);
7008 rel->rd_refcnt -= 1;
7009
7011}

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

◆ ScanPgRelation()

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

Definition at line 342 of file relcache.c.

343{
347 ScanKeyData key[1];
348 Snapshot snapshot = NULL;
349
350 /*
351 * If something goes wrong during backend startup, we might find ourselves
352 * trying to read pg_class before we've selected a database. That ain't
353 * gonna work, so bail out with a useful error message. If this happens,
354 * it probably means a relcache entry that needs to be nailed isn't.
355 */
357 elog(FATAL, "cannot read pg_class without having selected a database");
358
359 /*
360 * form a scan key
361 */
362 ScanKeyInit(&key[0],
366
367 /*
368 * Open pg_class and fetch a tuple. Force heap scan if we haven't yet
369 * built the critical relcache entries (this includes initdb and startup
370 * without a pg_internal.init file). The caller can also force a heap
371 * scan by setting indexOK == false.
372 */
374
375 /*
376 * The caller might need a tuple that's newer than what's visible to the
377 * historic snapshot; currently the only case requiring to do so is
378 * looking up the relfilenumber of non mapped system relations during
379 * decoding.
380 */
383
386 snapshot,
387 1, key);
388
390
391 /*
392 * Must copy tuple before releasing buffer.
393 */
396
397 /* all done */
399
400 if (snapshot)
401 UnregisterSnapshot(snapshot);
402
404
405 return pg_class_tuple;
406}
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 6973 of file relcache.c.

6974{
6975 if (unlink(initfilename) < 0)
6976 {
6977 /* It might not be there, but log any error other than ENOENT */
6978 if (errno != ENOENT)
6979 ereport(elevel,
6981 errmsg("could not remove cache file \"%s\": %m",
6982 initfilename)));
6983 }
6984}
int errcode_for_file_access(void)
Definition elog.c:897

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

6814{
6815 if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len))
6816 ereport(FATAL,
6818 errmsg_internal("could not write init file: %m"));
6819 if (len > 0 && fwrite(data, 1, len, fp) != len)
6820 ereport(FATAL,
6822 errmsg_internal("could not write init file: %m"));
6823}
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 6601 of file relcache.c.

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

Referenced by RelationCacheInitializePhase3().

◆ Desc_pg_auth_members

Definition at line 119 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_authid

Definition at line 118 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_class

◆ Desc_pg_database

Definition at line 117 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_index

Definition at line 120 of file relcache.c.

Referenced by GetPgIndexDescriptor().

◆ Desc_pg_proc

Definition at line 115 of file relcache.c.

Referenced by RelationCacheInitializePhase3().

◆ Desc_pg_shseclabel

Definition at line 121 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_subscription

Definition at line 122 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_type

Definition at line 116 of file relcache.c.

Referenced by RelationCacheInitializePhase3().

◆ eoxact_list

Oid eoxact_list[MAX_EOXACT_LIST]
static

Definition at line 187 of file relcache.c.

Referenced by AtEOSubXact_RelationCache(), and AtEOXact_RelationCache().

◆ eoxact_list_len

int eoxact_list_len = 0
static

Definition at line 188 of file relcache.c.

Referenced by AtEOSubXact_RelationCache(), and AtEOXact_RelationCache().

◆ eoxact_list_overflowed

bool eoxact_list_overflowed = false
static

Definition at line 189 of file relcache.c.

Referenced by AtEOSubXact_RelationCache(), and AtEOXact_RelationCache().

◆ EOXactTupleDescArray

TupleDesc* EOXactTupleDescArray
static

Definition at line 204 of file relcache.c.

Referenced by AtEOXact_RelationCache(), and RememberToFreeTupleDescAtEOX().

◆ EOXactTupleDescArrayLen

int EOXactTupleDescArrayLen = 0
static

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

Referenced by RelationBuildDesc(), and RelationCacheInitialize().

◆ NextEOXactTupleDescNum

int NextEOXactTupleDescNum = 0
static

Definition at line 205 of file relcache.c.

Referenced by AtEOXact_RelationCache(), and RememberToFreeTupleDescAtEOX().

◆ OpClassCache

HTAB* OpClassCache = NULL
static

Definition at line 273 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:6998
static char * ResOwnerPrintRelCache(Datum res)
Definition relcache.c:6990
@ RESOURCE_RELEASE_BEFORE_LOCKS
Definition resowner.h:54
#define RELEASE_PRIO_RELCACHE_REFS
Definition resowner.h:64

Definition at line 2147 of file relcache.c.

2148{
2149 .name = "relcache reference",
2150 .release_phase = RESOURCE_RELEASE_BEFORE_LOCKS,
2151 .release_priority = RELEASE_PRIO_RELCACHE_REFS,
2152 .ReleaseResource = ResOwnerReleaseRelation,
2153 .DebugPrint = ResOwnerPrintRelCache
2154};

Referenced by ResourceOwnerForgetRelationRef(), and ResourceOwnerRememberRelationRef().