PostgreSQL Source Code git master
Loading...
Searching...
No Matches
relcache.h File Reference
#include "access/tupdesc.h"
#include "common/relpath.h"
#include "nodes/bitmapset.h"
Include dependency graph for relcache.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define RELCACHE_INIT_FILENAME   "pg_internal.init"
 
#define AssertPendingSyncs_RelationCache()   do {} while (0)
 

Typedefs

typedef struct RelationDataRelation
 
typedef RelationRelationPtr
 
typedef enum IndexAttrBitmapKind IndexAttrBitmapKind
 

Enumerations

enum  IndexAttrBitmapKind {
  INDEX_ATTR_BITMAP_KEY , INDEX_ATTR_BITMAP_PRIMARY_KEY , INDEX_ATTR_BITMAP_IDENTITY_KEY , INDEX_ATTR_BITMAP_HOT_BLOCKING ,
  INDEX_ATTR_BITMAP_SUMMARIZED
}
 

Functions

static void AssertCouldGetRelation (void)
 
Relation RelationIdGetRelation (Oid relationId)
 
charRelationGetQualifiedRelationName (Relation rel)
 
void RelationClose (Relation relation)
 
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)
 
bytea ** RelationGetIndexAttOptions (Relation relation, bool copy)
 
BitmapsetRelationGetIndexAttrBitmap (Relation relation, IndexAttrBitmapKind attrKind)
 
BitmapsetRelationGetIdentityKeyBitmap (Relation relation)
 
void RelationGetExclusionInfo (Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
 
void RelationInitIndexAccessInfo (Relation relation)
 
void RelationBuildPublicationDesc (Relation relation, struct PublicationDesc *pubdesc)
 
void RelationInitTableAccessMethod (Relation relation)
 
int errtable (Relation rel)
 
int errtablecol (Relation rel, int attnum)
 
int errtablecolname (Relation rel, const char *colname)
 
int errtableconstraint (Relation rel, const char *conname)
 
void RelationCacheInitialize (void)
 
void RelationCacheInitializePhase2 (void)
 
void RelationCacheInitializePhase3 (void)
 
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 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)
 
bool RelationIdIsInInitFile (Oid relationId)
 
void RelationCacheInitFilePreInvalidate (void)
 
void RelationCacheInitFilePostInvalidate (void)
 
void RelationCacheInitFileRemove (void)
 

Variables

PGDLLIMPORT bool criticalRelcachesBuilt
 
PGDLLIMPORT bool criticalSharedRelcachesBuilt
 

Macro Definition Documentation

◆ AssertPendingSyncs_RelationCache

#define AssertPendingSyncs_RelationCache ( )    do {} while (0)

Definition at line 144 of file relcache.h.

◆ RELCACHE_INIT_FILENAME

#define RELCACHE_INIT_FILENAME   "pg_internal.init"

Definition at line 25 of file relcache.h.

Typedef Documentation

◆ IndexAttrBitmapKind

◆ Relation

Definition at line 27 of file relcache.h.

◆ RelationPtr

Definition at line 35 of file relcache.h.

Enumeration Type Documentation

◆ IndexAttrBitmapKind

Enumerator
INDEX_ATTR_BITMAP_KEY 
INDEX_ATTR_BITMAP_PRIMARY_KEY 
INDEX_ATTR_BITMAP_IDENTITY_KEY 
INDEX_ATTR_BITMAP_HOT_BLOCKING 
INDEX_ATTR_BITMAP_SUMMARIZED 

Definition at line 68 of file relcache.h.

69{
IndexAttrBitmapKind
Definition relcache.h:69
@ INDEX_ATTR_BITMAP_KEY
Definition relcache.h:70
@ INDEX_ATTR_BITMAP_HOT_BLOCKING
Definition relcache.h:73
@ INDEX_ATTR_BITMAP_PRIMARY_KEY
Definition relcache.h:71
@ INDEX_ATTR_BITMAP_SUMMARIZED
Definition relcache.h:74
@ INDEX_ATTR_BITMAP_IDENTITY_KEY
Definition relcache.h:72

Function Documentation

◆ AssertCouldGetRelation()

◆ AtEOSubXact_RelationCache()

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

Definition at line 3378 of file relcache.c.

3380{
3381 HASH_SEQ_STATUS status;
3383 int i;
3384
3385 /*
3386 * Forget in_progress_list. This is relevant when we're aborting due to
3387 * an error during RelationBuildDesc(). We don't commit subtransactions
3388 * during RelationBuildDesc().
3389 */
3392
3393 /*
3394 * Unless the eoxact_list[] overflowed, we only need to examine the rels
3395 * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3396 * logic as in AtEOXact_RelationCache.
3397 */
3399 {
3401 while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3402 {
3405 }
3406 }
3407 else
3408 {
3409 for (i = 0; i < eoxact_list_len; i++)
3410 {
3412 &eoxact_list[i],
3413 HASH_FIND,
3414 NULL);
3415 if (idhentry != NULL)
3418 }
3419 }
3420
3421 /* Don't reset the list; we still need more cleanup later */
3422}
#define Assert(condition)
Definition c.h:943
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition dynahash.c:889
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
@ HASH_FIND
Definition hsearch.h:108
int i
Definition isn.c:77
static int fb(int x)
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition relcache.c:187
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:3433
static int eoxact_list_len
Definition relcache.c:188
static bool eoxact_list_overflowed
Definition relcache.c:189
static HTAB * RelationIdCache
Definition relcache.c:136

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_RelationCache()

void AtEOXact_RelationCache ( bool  isCommit)
extern

Definition at line 3226 of file relcache.c.

3227{
3228 HASH_SEQ_STATUS status;
3230 int i;
3231
3232 /*
3233 * Forget in_progress_list. This is relevant when we're aborting due to
3234 * an error during RelationBuildDesc().
3235 */
3238
3239 /*
3240 * Unless the eoxact_list[] overflowed, we only need to examine the rels
3241 * listed in it. Otherwise fall back on a hash_seq_search scan.
3242 *
3243 * For simplicity, eoxact_list[] entries are not deleted till end of
3244 * top-level transaction, even though we could remove them at
3245 * subtransaction end in some cases, or remove relations from the list if
3246 * they are cleared for other reasons. Therefore we should expect the
3247 * case that list entries are not found in the hashtable; if not, there's
3248 * nothing to do for them.
3249 */
3251 {
3253 while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3254 {
3256 }
3257 }
3258 else
3259 {
3260 for (i = 0; i < eoxact_list_len; i++)
3261 {
3263 &eoxact_list[i],
3264 HASH_FIND,
3265 NULL);
3266 if (idhentry != NULL)
3268 }
3269 }
3270
3272 {
3274 for (i = 0; i < NextEOXactTupleDescNum; i++)
3278 }
3279
3280 /* Now we're out of the transaction and can clear the lists */
3281 eoxact_list_len = 0;
3282 eoxact_list_overflowed = false;
3285}
void pfree(void *pointer)
Definition mcxt.c:1619
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:3296
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().

◆ errtable()

int errtable ( Relation  rel)
extern

Definition at line 6073 of file relcache.c.

6074{
6078
6079 return 0; /* return value does not matter */
6080}
int err_generic_string(int field, const char *str)
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3599
#define PG_DIAG_SCHEMA_NAME
#define PG_DIAG_TABLE_NAME
#define RelationGetRelationName(relation)
Definition rel.h:550
#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 
)
extern

Definition at line 6090 of file relcache.c.

6091{
6092 TupleDesc reldesc = RelationGetDescr(rel);
6093 const char *colname;
6094
6095 /* Use reldesc if it's a user attribute, else consult the catalogs */
6096 if (attnum > 0 && attnum <= reldesc->natts)
6097 colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
6098 else
6099 colname = get_attname(RelationGetRelid(rel), attnum, false);
6100
6101 return errtablecolname(rel, colname);
6102}
#define NameStr(name)
Definition c.h:835
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:984
NameData attname
int16 attnum
#define RelationGetRelid(relation)
Definition rel.h:516
#define RelationGetDescr(relation)
Definition rel.h:542
int errtablecolname(Relation rel, const char *colname)
Definition relcache.c:6114
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178

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 
)
extern

Definition at line 6114 of file relcache.c.

6115{
6116 errtable(rel);
6118
6119 return 0; /* return value does not matter */
6120}
#define PG_DIAG_COLUMN_NAME
int errtable(Relation rel)
Definition relcache.c:6073

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

Referenced by errtablecol().

◆ errtableconstraint()

◆ RelationAssumeNewRelfilelocator()

void RelationAssumeNewRelfilelocator ( Relation  relation)
extern

Definition at line 3978 of file relcache.c.

3979{
3983
3984 /* Flag relation as needing eoxact cleanup (to clear these fields) */
3985 EOXactListAdd(relation);
3986}
#define InvalidSubTransactionId
Definition c.h:742
#define EOXactListAdd(rel)
Definition relcache.c:191
SubTransactionId rd_firstRelfilelocatorSubid
Definition rel.h:106
SubTransactionId rd_newRelfilelocatorSubid
Definition rel.h:104
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().

◆ 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 
)
extern

Definition at line 3515 of file relcache.c.

3526{
3527 Relation rel;
3529 int natts = tupDesc->natts;
3530 int i;
3531 bool has_not_null;
3532 bool nailit;
3533
3534 Assert(natts >= 0);
3535
3536 /*
3537 * check for creation of a rel that must be nailed in cache.
3538 *
3539 * XXX this list had better match the relations specially handled in
3540 * RelationCacheInitializePhase2/3.
3541 */
3542 switch (relid)
3543 {
3544 case DatabaseRelationId:
3545 case AuthIdRelationId:
3546 case AuthMemRelationId:
3547 case RelationRelationId:
3550 case TypeRelationId:
3551 nailit = true;
3552 break;
3553 default:
3554 nailit = false;
3555 break;
3556 }
3557
3558 /*
3559 * check that hardwired list of shared rels matches what's in the
3560 * bootstrap .bki file. If you get a failure here during initdb, you
3561 * probably need to fix IsSharedRelation() to match whatever you've done
3562 * to the set of shared relations.
3563 */
3564 if (shared_relation != IsSharedRelation(relid))
3565 elog(ERROR, "shared_relation flag for \"%s\" does not match IsSharedRelation(%u)",
3566 relname, relid);
3567
3568 /* Shared relations had better be mapped, too */
3570
3571 /*
3572 * switch to the cache context to create the relcache entry.
3573 */
3574 if (!CacheMemoryContext)
3576
3578
3579 /*
3580 * allocate a new relation descriptor and fill in basic state fields.
3581 */
3583
3584 /* make sure relation is marked as having no open file yet */
3585 rel->rd_smgr = NULL;
3586
3587 /* mark it nailed if appropriate */
3588 rel->rd_isnailed = nailit;
3589
3590 rel->rd_refcnt = nailit ? 1 : 0;
3591
3592 /* it's being created in this transaction */
3597
3598 /*
3599 * create a new tuple descriptor from the one passed in. We do this
3600 * partly to copy it into the cache context, and partly because the new
3601 * relation can't have any defaults or constraints yet; they have to be
3602 * added in later steps, because they require additions to multiple system
3603 * catalogs. We can copy attnotnull constraints here, however.
3604 */
3605 rel->rd_att = CreateTupleDescCopy(tupDesc);
3606 rel->rd_att->tdrefcount = 1; /* mark as refcounted */
3607 has_not_null = false;
3608 for (i = 0; i < natts; i++)
3609 {
3612
3613 datt->attidentity = satt->attidentity;
3614 datt->attgenerated = satt->attgenerated;
3615 datt->attnotnull = satt->attnotnull;
3616 has_not_null |= satt->attnotnull;
3618
3619 if (satt->attnotnull)
3620 {
3623
3624 dcatt->attnullability = scatt->attnullability;
3625 }
3626 }
3627
3628 if (has_not_null)
3629 {
3631
3632 constr->has_not_null = true;
3633 rel->rd_att->constr = constr;
3634 }
3635
3636 /*
3637 * initialize relation tuple form (caller may add/override data later)
3638 */
3640
3641 namestrcpy(&rel->rd_rel->relname, relname);
3642 rel->rd_rel->relnamespace = relnamespace;
3643
3644 rel->rd_rel->relkind = relkind;
3645 rel->rd_rel->relnatts = natts;
3646 rel->rd_rel->reltype = InvalidOid;
3647 /* needed when bootstrapping: */
3648 rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;
3649
3650 /* set up persistence and relcache fields dependent on it */
3651 rel->rd_rel->relpersistence = relpersistence;
3652 switch (relpersistence)
3653 {
3657 rel->rd_islocaltemp = false;
3658 break;
3660 Assert(isTempOrTempToastNamespace(relnamespace));
3662 rel->rd_islocaltemp = true;
3663 break;
3664 default:
3665 elog(ERROR, "invalid relpersistence: %c", relpersistence);
3666 break;
3667 }
3668
3669 /* if it's a materialized view, it's not populated initially */
3670 if (relkind == RELKIND_MATVIEW)
3671 rel->rd_rel->relispopulated = false;
3672 else
3673 rel->rd_rel->relispopulated = true;
3674
3675 /* set replica identity -- system catalogs and non-tables don't have one */
3676 if (!IsCatalogNamespace(relnamespace) &&
3677 (relkind == RELKIND_RELATION ||
3678 relkind == RELKIND_MATVIEW ||
3679 relkind == RELKIND_PARTITIONED_TABLE))
3680 rel->rd_rel->relreplident = REPLICA_IDENTITY_DEFAULT;
3681 else
3682 rel->rd_rel->relreplident = REPLICA_IDENTITY_NOTHING;
3683
3684 /*
3685 * Insert relation physical and logical identifiers (OIDs) into the right
3686 * places. For a mapped relation, we set relfilenumber to zero and rely
3687 * on RelationInitPhysicalAddr to consult the map.
3688 */
3689 rel->rd_rel->relisshared = shared_relation;
3690
3691 RelationGetRelid(rel) = relid;
3692
3693 for (i = 0; i < natts; i++)
3694 TupleDescAttr(rel->rd_att, i)->attrelid = relid;
3695
3697
3698 rel->rd_rel->reltablespace = reltablespace;
3699
3700 if (mapped_relation)
3701 {
3702 rel->rd_rel->relfilenode = InvalidRelFileNumber;
3703 /* Add it to the active mapping information */
3704 RelationMapUpdateMap(relid, relfilenumber, shared_relation, true);
3705 }
3706 else
3707 rel->rd_rel->relfilenode = relfilenumber;
3708
3709 RelationInitLockInfo(rel); /* see lmgr.c */
3710
3712
3713 rel->rd_rel->relam = accessmtd;
3714
3715 /*
3716 * RelationInitTableAccessMethod will do syscache lookups, so we mustn't
3717 * run it in CacheMemoryContext. Fortunately, the remaining steps don't
3718 * require a long-lived current context.
3719 */
3721
3722 if (RELKIND_HAS_TABLE_AM(relkind) || relkind == RELKIND_SEQUENCE)
3724
3725 /*
3726 * Leave index access method uninitialized, because the pg_index row has
3727 * not been inserted at this stage of index creation yet. The cache
3728 * invalidation after pg_index row has been inserted will initialize it.
3729 */
3730
3731 /*
3732 * Okay to insert into the relcache hash table.
3733 *
3734 * Ordinarily, there should certainly not be an existing hash entry for
3735 * the same OID; but during bootstrap, when we create a "real" relcache
3736 * entry for one of the bootstrap relations, we'll be overwriting the
3737 * phony one created with formrdesc. So allow that to happen for nailed
3738 * rels.
3739 */
3741
3742 /*
3743 * Flag relation as needing eoxact cleanup (to clear rd_createSubid). We
3744 * can't do this before storing relid in it.
3745 */
3746 EOXactListAdd(rel);
3747
3748 /* It's fully valid */
3749 rel->rd_isvalid = true;
3750
3751 /*
3752 * Caller expects us to pin the returned entry.
3753 */
3755
3756 return rel;
3757}
bool IsCatalogNamespace(Oid namespaceId)
Definition catalog.c:243
bool IsSharedRelation(Oid relationId)
Definition catalog.c:304
void CreateCacheMemoryContext(void)
Definition catcache.c:726
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define palloc0_object(type)
Definition fe_memutils.h:90
void RelationInitLockInfo(Relation relation)
Definition lmgr.c:70
void * palloc0(Size size)
Definition mcxt.c:1420
MemoryContext CacheMemoryContext
Definition mcxt.c:170
void namestrcpy(Name name, const char *str)
Definition name.c:233
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition namespace.c:3745
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
FormData_pg_attribute * Form_pg_attribute
NameData relname
Definition pg_class.h:40
FormData_pg_class * Form_pg_class
Definition pg_class.h:160
#define CLASS_TUPLE_SIZE
Definition pg_class.h:152
#define InvalidOid
#define INVALID_PROC_NUMBER
Definition procnumber.h:26
#define ProcNumberForTempRelations()
Definition procnumber.h:53
#define RelationCacheInsert(RELATION, replace_allowed)
Definition relcache.c:211
void RelationIncrementReferenceCount(Relation rel)
Definition relcache.c:2187
void RelationInitTableAccessMethod(Relation relation)
Definition relcache.c:1820
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
int rd_refcnt
Definition rel.h:59
bool rd_isvalid
Definition rel.h:63
bool rd_islocaltemp
Definition rel.h:61
TupleDesc rd_att
Definition rel.h:112
bool rd_isnailed
Definition rel.h:62
SMgrRelation rd_smgr
Definition rel.h:58
SubTransactionId rd_createSubid
Definition rel.h:103
SubTransactionId rd_droppedSubid
Definition rel.h:109
Form_pg_class rd_rel
Definition rel.h:111
bool has_not_null
Definition tupdesc.h:45
TupleConstr * constr
Definition tupdesc.h:159
void TupleDescFinalize(TupleDesc tupdesc)
Definition tupdesc.c:511
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition tupdesc.c:242
void populate_compact_attribute(TupleDesc tupdesc, int attnum)
Definition tupdesc.c:100
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,
struct PublicationDesc pubdesc 
)
extern

Definition at line 5795 of file relcache.c.

5796{
5797 List *puboids = NIL;
5800 ListCell *lc;
5802 Oid schemaid;
5803 List *ancestors = NIL;
5804 Oid relid = RelationGetRelid(relation);
5805
5806 /*
5807 * If not publishable, it publishes no actions. (pgoutput_change() will
5808 * ignore it.)
5809 */
5810 if (!is_publishable_relation(relation))
5811 {
5812 memset(pubdesc, 0, sizeof(PublicationDesc));
5813 pubdesc->rf_valid_for_update = true;
5814 pubdesc->rf_valid_for_delete = true;
5815 pubdesc->cols_valid_for_update = true;
5816 pubdesc->cols_valid_for_delete = true;
5817 pubdesc->gencols_valid_for_update = true;
5818 pubdesc->gencols_valid_for_delete = true;
5819 return;
5820 }
5821
5822 if (relation->rd_pubdesc)
5823 {
5824 memcpy(pubdesc, relation->rd_pubdesc, sizeof(PublicationDesc));
5825 return;
5826 }
5827
5828 memset(pubdesc, 0, sizeof(PublicationDesc));
5829 pubdesc->rf_valid_for_update = true;
5830 pubdesc->rf_valid_for_delete = true;
5831 pubdesc->cols_valid_for_update = true;
5832 pubdesc->cols_valid_for_delete = true;
5833 pubdesc->gencols_valid_for_update = true;
5834 pubdesc->gencols_valid_for_delete = true;
5835
5836 /* Fetch the publication membership info. */
5838 schemaid = RelationGetNamespace(relation);
5840
5841 if (relation->rd_rel->relispartition)
5842 {
5844
5845 /* Add publications that the ancestors are in too. */
5846 ancestors = get_partition_ancestors(relid);
5847 last_ancestor_relid = llast_oid(ancestors);
5848
5849 foreach(lc, ancestors)
5850 {
5852
5858 }
5859
5860 /*
5861 * Only the top-most ancestor can appear in the EXCEPT clause.
5862 * Therefore, for a partition, exclusion must be evaluated at the
5863 * top-most ancestor.
5864 */
5866 }
5867 else
5868 {
5869 /*
5870 * For a regular table or a root partitioned table, check exclusion on
5871 * table itself.
5872 */
5874 }
5875
5879 exceptpuboids));
5880 foreach(lc, puboids)
5881 {
5882 Oid pubid = lfirst_oid(lc);
5883 HeapTuple tup;
5886 bool invalid_gen_col;
5887
5889
5890 if (!HeapTupleIsValid(tup))
5891 elog(ERROR, "cache lookup failed for publication %u", pubid);
5892
5894
5895 pubdesc->pubactions.pubinsert |= pubform->pubinsert;
5896 pubdesc->pubactions.pubupdate |= pubform->pubupdate;
5897 pubdesc->pubactions.pubdelete |= pubform->pubdelete;
5898 pubdesc->pubactions.pubtruncate |= pubform->pubtruncate;
5899
5900 /*
5901 * Check if all columns referenced in the filter expression are part
5902 * of the REPLICA IDENTITY index or not.
5903 *
5904 * If the publication is FOR ALL TABLES then it means the table has no
5905 * row filters and we can skip the validation.
5906 */
5907 if (!pubform->puballtables &&
5908 (pubform->pubupdate || pubform->pubdelete) &&
5909 pub_rf_contains_invalid_column(pubid, relation, ancestors,
5910 pubform->pubviaroot))
5911 {
5912 if (pubform->pubupdate)
5913 pubdesc->rf_valid_for_update = false;
5914 if (pubform->pubdelete)
5915 pubdesc->rf_valid_for_delete = false;
5916 }
5917
5918 /*
5919 * Check if all columns are part of the REPLICA IDENTITY index or not.
5920 *
5921 * Check if all generated columns included in the REPLICA IDENTITY are
5922 * published.
5923 */
5924 if ((pubform->pubupdate || pubform->pubdelete) &&
5925 pub_contains_invalid_column(pubid, relation, ancestors,
5926 pubform->pubviaroot,
5927 pubform->pubgencols,
5930 {
5931 if (pubform->pubupdate)
5932 {
5933 pubdesc->cols_valid_for_update = !invalid_column_list;
5934 pubdesc->gencols_valid_for_update = !invalid_gen_col;
5935 }
5936
5937 if (pubform->pubdelete)
5938 {
5939 pubdesc->cols_valid_for_delete = !invalid_column_list;
5940 pubdesc->gencols_valid_for_delete = !invalid_gen_col;
5941 }
5942 }
5943
5945
5946 /*
5947 * If we know everything is replicated and the row filter 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->rf_valid_for_update && !pubdesc->rf_valid_for_delete)
5954 break;
5955
5956 /*
5957 * If we know everything is replicated and the column list is invalid
5958 * for update and delete, 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->cols_valid_for_update && !pubdesc->cols_valid_for_delete)
5964 break;
5965
5966 /*
5967 * If we know everything is replicated and replica identity has an
5968 * unpublished generated column, there is no point to check for other
5969 * publications.
5970 */
5971 if (pubdesc->pubactions.pubinsert && pubdesc->pubactions.pubupdate &&
5972 pubdesc->pubactions.pubdelete && pubdesc->pubactions.pubtruncate &&
5973 !pubdesc->gencols_valid_for_update &&
5974 !pubdesc->gencols_valid_for_delete)
5975 break;
5976 }
5977
5978 if (relation->rd_pubdesc)
5979 {
5980 pfree(relation->rd_pubdesc);
5981 relation->rd_pubdesc = NULL;
5982 }
5983
5984 /* Now save copy of the descriptor in the relcache entry. */
5987 memcpy(relation->rd_pubdesc, pubdesc, sizeof(PublicationDesc));
5989}
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
#define palloc_object(type)
Definition fe_memutils.h:89
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
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:2183
List * get_partition_ancestors(Oid relid)
Definition partition.c:134
#define NIL
Definition pg_list.h:68
#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
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
unsigned int Oid
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
PublicationDesc * rd_pubdesc
Definition rel.h:168
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().

◆ RelationCacheInitFilePostInvalidate()

void RelationCacheInitFilePostInvalidate ( void  )
extern

Definition at line 6911 of file relcache.c.

6912{
6914}
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  )
extern

Definition at line 6886 of file relcache.c.

6887{
6890
6891 if (DatabasePath)
6892 snprintf(localinitfname, sizeof(localinitfname), "%s/%s",
6894 snprintf(sharedinitfname, sizeof(sharedinitfname), "global/%s",
6896
6898
6899 /*
6900 * The files might not be there if no backend has been started since the
6901 * last removal. But complain about failures other than ENOENT with
6902 * ERROR. Fortunately, it's not too late to abort the transaction if we
6903 * can't get rid of the would-be-obsolete init file.
6904 */
6905 if (DatabasePath)
6908}
char * DatabasePath
Definition globals.c:106
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1150
@ LW_EXCLUSIVE
Definition lwlock.h:104
#define MAXPGPATH
#define snprintf
Definition port.h:261
static void unlink_initfile(const char *initfilename, int elevel)
Definition relcache.c:6983
#define RELCACHE_INIT_FILENAME
Definition relcache.h:25

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  )
extern

Definition at line 6926 of file relcache.c.

6927{
6928 const char *tblspcdir = PG_TBLSPC_DIR;
6929 DIR *dir;
6930 struct dirent *de;
6931 char path[MAXPGPATH + sizeof(PG_TBLSPC_DIR) + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6932
6933 snprintf(path, sizeof(path), "global/%s",
6935 unlink_initfile(path, LOG);
6936
6937 /* Scan everything in the default tablespace */
6939
6940 /* Scan the tablespace link directory to find non-default tablespaces */
6941 dir = AllocateDir(tblspcdir);
6942
6943 while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6944 {
6945 if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6946 {
6947 /* Scan the tablespace dir for per-database dirs */
6948 snprintf(path, sizeof(path), "%s/%s/%s",
6951 }
6952 }
6953
6954 FreeDir(dir);
6955}
#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:6959
#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().

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )
extern

Definition at line 4004 of file relcache.c.

4005{
4006 HASHCTL ctl;
4007 int allocsize;
4008
4009 /*
4010 * make sure cache memory context exists
4011 */
4012 if (!CacheMemoryContext)
4014
4015 /*
4016 * create hashtable that indexes the relcache
4017 */
4018 ctl.keysize = sizeof(Oid);
4019 ctl.entrysize = sizeof(RelIdCacheEnt);
4020 RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
4022
4023 /*
4024 * reserve enough in_progress_list slots for many cases
4025 */
4026 allocsize = 4;
4029 allocsize * sizeof(*in_progress_list));
4030 in_progress_list_maxlen = allocsize;
4031
4032 /*
4033 * relation mapper needs to be initialized too
4034 */
4036}
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
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition mcxt.c:1235
tree ctl
Definition radixtree.h:1838
static int in_progress_list_maxlen
Definition relcache.c:174
#define INITRELCACHESIZE
Definition relcache.c:4001
struct relidcacheent RelIdCacheEnt
static InProgressEnt * in_progress_list
Definition relcache.c:172
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  )
extern

Definition at line 4050 of file relcache.c.

4051{
4053
4054 /*
4055 * relation mapper needs initialized too
4056 */
4058
4059 /*
4060 * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
4061 * nothing.
4062 */
4064 return;
4065
4066 /*
4067 * switch to cache memory context
4068 */
4070
4071 /*
4072 * Try to load the shared relcache cache file. If unsuccessful, bootstrap
4073 * the cache with pre-made descriptors for the critical shared catalogs.
4074 */
4075 if (!load_relcache_init_file(true))
4076 {
4077 formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
4079 formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
4081 formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
4083 formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
4085 formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
4087
4088#define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
4089 }
4090
4092}
#define IsBootstrapProcessingMode()
Definition miscadmin.h:495
static bool load_relcache_init_file(bool shared)
Definition relcache.c:6191
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  )
extern

Definition at line 4109 of file relcache.c.

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

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)
extern

Definition at line 2994 of file relcache.c.

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

Definition at line 2938 of file relcache.c.

2939{
2940 Relation relation;
2941
2943
2944 if (relation)
2945 {
2947 RelationFlushRelation(relation);
2948 }
2949 else
2950 {
2951 int i;
2952
2953 for (i = 0; i < in_progress_list_len; i++)
2954 if (in_progress_list[i].reloid == relationId)
2956 }
2957}
#define RelationIdCacheLookup(ID, RELATION)
Definition relcache.c:233
static void RelationFlushRelation(Relation relation)
Definition relcache.c:2827
bool invalidated
Definition relcache.c:169

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

Referenced by LocalExecuteInvalidationMessage().

◆ RelationClose()

void RelationClose ( Relation  relation)
extern

Definition at line 2220 of file relcache.c.

2221{
2222 /* Note: no locking manipulations needed */
2224
2225 RelationCloseCleanup(relation);
2226}
static void RelationCloseCleanup(Relation relation)
Definition relcache.c:2229

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().

◆ RelationForgetRelation()

void RelationForgetRelation ( Oid  rid)
extern

Definition at line 2893 of file relcache.c.

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

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)
extern

Definition at line 5157 of file relcache.c.

5158{
5159 List *result;
5161 bool isnull;
5162 char *exprsString;
5163 List *rawExprs;
5164 ListCell *lc;
5165
5166 /* Quick exit if there is nothing to do. */
5167 if (relation->rd_indextuple == NULL ||
5169 return NIL;
5170
5171 /* Extract raw node tree(s) from index tuple. */
5175 &isnull);
5176 Assert(!isnull);
5180
5181 /* Construct null Consts; the typlen and typbyval are arbitrary. */
5182 result = NIL;
5183 foreach(lc, rawExprs)
5184 {
5185 Node *rawExpr = (Node *) lfirst(lc);
5186
5191 1,
5192 (Datum) 0,
5193 true,
5194 true));
5195 }
5196
5197 return result;
5198}
#define TextDatumGetCString(d)
Definition builtins.h:99
uint32 result
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition heaptuple.c:456
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
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
uint64_t Datum
Definition postgres.h:70
void * stringToNode(const char *str)
Definition read.c:90
static TupleDesc GetPgIndexDescriptor(void)
Definition relcache.c:4474
Definition nodes.h:135
struct HeapTupleData * rd_indextuple
Definition rel.h:194

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 
)
extern

Definition at line 5654 of file relcache.c.

5658{
5659 int indnkeyatts;
5660 Oid *ops;
5661 Oid *funcs;
5662 uint16 *strats;
5665 ScanKeyData skey[1];
5666 HeapTuple htup;
5667 bool found;
5669 int i;
5670
5672
5673 /* Allocate result space in caller context */
5674 *operators = ops = palloc_array(Oid, indnkeyatts);
5675 *procs = funcs = palloc_array(Oid, indnkeyatts);
5677
5678 /* Quick exit if we have the data cached already */
5679 if (indexRelation->rd_exclstrats != NULL)
5680 {
5681 memcpy(ops, indexRelation->rd_exclops, sizeof(Oid) * indnkeyatts);
5682 memcpy(funcs, indexRelation->rd_exclprocs, sizeof(Oid) * indnkeyatts);
5683 memcpy(strats, indexRelation->rd_exclstrats, sizeof(uint16) * indnkeyatts);
5684 return;
5685 }
5686
5687 /*
5688 * Search pg_constraint for the constraint associated with the index. To
5689 * make this not too painfully slow, we use the index on conrelid; that
5690 * will hold the parent relation's OID not the index's own OID.
5691 *
5692 * Note: if we wanted to rely on the constraint name matching the index's
5693 * name, we could just do a direct lookup using pg_constraint's unique
5694 * index. For the moment it doesn't seem worth requiring that.
5695 */
5696 ScanKeyInit(&skey[0],
5699 ObjectIdGetDatum(indexRelation->rd_index->indrelid));
5700
5703 NULL, 1, skey);
5704 found = false;
5705
5707 {
5709 Datum val;
5710 bool isnull;
5711 ArrayType *arr;
5712 int nelem;
5713
5714 /* We want the exclusion constraint owning the index */
5715 if ((conform->contype != CONSTRAINT_EXCLUSION &&
5716 !(conform->conperiod && (conform->contype == CONSTRAINT_PRIMARY
5717 || conform->contype == CONSTRAINT_UNIQUE))) ||
5718 conform->conindid != RelationGetRelid(indexRelation))
5719 continue;
5720
5721 /* There should be only one */
5722 if (found)
5723 elog(ERROR, "unexpected exclusion constraint record found for rel %s",
5724 RelationGetRelationName(indexRelation));
5725 found = true;
5726
5727 /* Extract the operator OIDS from conexclop */
5728 val = fastgetattr(htup,
5730 conrel->rd_att, &isnull);
5731 if (isnull)
5732 elog(ERROR, "null conexclop for rel %s",
5733 RelationGetRelationName(indexRelation));
5734
5735 arr = DatumGetArrayTypeP(val); /* ensure not toasted */
5736 nelem = ARR_DIMS(arr)[0];
5737 if (ARR_NDIM(arr) != 1 ||
5738 nelem != indnkeyatts ||
5739 ARR_HASNULL(arr) ||
5740 ARR_ELEMTYPE(arr) != OIDOID)
5741 elog(ERROR, "conexclop is not a 1-D Oid array");
5742
5743 memcpy(ops, ARR_DATA_PTR(arr), sizeof(Oid) * indnkeyatts);
5744 }
5745
5748
5749 if (!found)
5750 elog(ERROR, "exclusion constraint record missing for rel %s",
5751 RelationGetRelationName(indexRelation));
5752
5753 /* We need the func OIDs and strategy numbers too */
5754 for (i = 0; i < indnkeyatts; i++)
5755 {
5756 funcs[i] = get_opcode(ops[i]);
5757 strats[i] = get_op_opfamily_strategy(ops[i],
5758 indexRelation->rd_opfamily[i]);
5759 /* shouldn't fail, since it was checked at index creation */
5760 if (strats[i] == InvalidStrategy)
5761 elog(ERROR, "could not find strategy for operator %u in family %u",
5762 ops[i], indexRelation->rd_opfamily[i]);
5763 }
5764
5765 /* Save a copy of the results in the relcache entry. */
5766 oldcxt = MemoryContextSwitchTo(indexRelation->rd_indexcxt);
5767 indexRelation->rd_exclops = palloc_array(Oid, indnkeyatts);
5768 indexRelation->rd_exclprocs = palloc_array(Oid, indnkeyatts);
5769 indexRelation->rd_exclstrats = palloc_array(uint16, indnkeyatts);
5770 memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * indnkeyatts);
5771 memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * indnkeyatts);
5772 memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * indnkeyatts);
5774}
#define ARR_NDIM(a)
Definition array.h:290
#define ARR_DATA_PTR(a)
Definition array.h:322
#define DatumGetArrayTypeP(X)
Definition array.h:261
#define ARR_ELEMTYPE(a)
Definition array.h:292
#define ARR_DIMS(a)
Definition array.h:294
#define ARR_HASNULL(a)
Definition array.h:291
uint16_t uint16
Definition c.h:623
#define palloc_array(type, count)
Definition fe_memutils.h:91
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
static Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
long val
Definition informix.c:689
#define AccessShareLock
Definition lockdefs.h:36
RegProcedure get_opcode(Oid opno)
Definition lsyscache.c:1516
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition lsyscache.c:87
END_CATALOG_STRUCT typedef FormData_pg_constraint * Form_pg_constraint
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition rel.h:535
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition scankey.c:76
#define InvalidStrategy
Definition stratnum.h:24
#define BTEqualStrategyNumber
Definition stratnum.h:31
Oid * rd_exclprocs
Definition rel.h:215
uint16 * rd_exclstrats
Definition rel.h:216
Oid * rd_exclops
Definition rel.h:214
Form_pg_index rd_index
Definition rel.h:192
MemoryContext rd_indexcxt
Definition rel.h:204
Oid * rd_opfamily
Definition rel.h:207
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40

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)
extern

Definition at line 4732 of file relcache.c.

4733{
4734 List *result;
4738 HeapTuple htup;
4739 List *oldlist;
4741
4742 /* Quick exit if we already computed the list. */
4743 if (relation->rd_fkeyvalid)
4744 return relation->rd_fkeylist;
4745
4746 /*
4747 * We build the list we intend to return (in the caller's context) while
4748 * doing the scan. After successfully completing the scan, we copy that
4749 * list into the relcache entry. This avoids cache-context memory leakage
4750 * if we get some sort of error partway through.
4751 */
4752 result = NIL;
4753
4754 /* Prepare to scan pg_constraint for entries having conrelid = this rel. */
4759
4762 NULL, 1, &skey);
4763
4765 {
4766 Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(htup);
4767 ForeignKeyCacheInfo *info;
4768
4769 /* consider only foreign keys */
4770 if (constraint->contype != CONSTRAINT_FOREIGN)
4771 continue;
4772
4774 info->conoid = constraint->oid;
4775 info->conrelid = constraint->conrelid;
4776 info->confrelid = constraint->confrelid;
4777 info->conenforced = constraint->conenforced;
4778
4779 DeconstructFkConstraintRow(htup, &info->nkeys,
4780 info->conkey,
4781 info->confkey,
4782 info->conpfeqop,
4783 NULL, NULL, NULL, NULL);
4784
4785 /* Add FK's node to the result list */
4786 result = lappend(result, info);
4787 }
4788
4791
4792 /* Now save a copy of the completed list in the relcache entry. */
4794 oldlist = relation->rd_fkeylist;
4795 relation->rd_fkeylist = copyObject(result);
4796 relation->rd_fkeyvalid = true;
4798
4799 /* Don't leak the old list, if there is one */
4801
4802 return result;
4803}
void list_free_deep(List *list)
Definition list.c:1560
#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)
List * rd_fkeylist
Definition rel.h:122
bool rd_fkeyvalid
Definition rel.h:123

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)
extern

Definition at line 5577 of file relcache.c.

5578{
5579 Bitmapset *idindexattrs = NULL; /* columns in the replica identity */
5581 int i;
5584
5585 /* Quick exit if we already computed the result */
5586 if (relation->rd_idattr != NULL)
5587 return bms_copy(relation->rd_idattr);
5588
5589 /* Fast path if definitely no indexes */
5590 if (!RelationGetForm(relation)->relhasindex)
5591 return NULL;
5592
5593 /* Historic snapshot must be set. */
5595
5597
5598 /* Fall out if there is no replica identity index */
5599 if (!OidIsValid(replidindex))
5600 return NULL;
5601
5602 /* Look up the description for the replica identity index */
5604
5606 elog(ERROR, "could not open relation with OID %u",
5607 relation->rd_replidindex);
5608
5609 /* Add referenced attributes to idindexattrs */
5610 for (i = 0; i < indexDesc->rd_index->indnatts; i++)
5611 {
5612 int attrnum = indexDesc->rd_index->indkey.values[i];
5613
5614 /*
5615 * We don't include non-key columns into idindexattrs bitmaps. See
5616 * RelationGetIndexAttrBitmap.
5617 */
5618 if (attrnum != 0)
5619 {
5620 if (i < indexDesc->rd_index->indnkeyatts)
5623 }
5624 }
5625
5627
5628 /* Don't leak the old values of these bitmaps, if any */
5629 bms_free(relation->rd_idattr);
5630 relation->rd_idattr = NULL;
5631
5632 /* Now save copy of the bitmap in the relcache entry */
5634 relation->rd_idattr = bms_copy(idindexattrs);
5636
5637 /* We return our original working copy for caller to play with */
5638 return idindexattrs;
5639}
void bms_free(Bitmapset *a)
Definition bitmapset.c:239
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:799
Bitmapset * bms_copy(const Bitmapset *a)
Definition bitmapset.c:122
#define OidIsValid(objectId)
Definition c.h:858
#define RelationGetForm(relation)
Definition rel.h:510
#define RelationIsValid(relation)
Definition rel.h:491
Oid RelationGetReplicaIndex(Relation relation)
Definition relcache.c:5073
Relation RelationIdGetRelation(Oid relationId)
Definition relcache.c:2089
void RelationClose(Relation relation)
Definition relcache.c:2220
bool HistoricSnapshotActive(void)
Definition snapmgr.c:1692
Oid rd_replidindex
Definition rel.h:155
Bitmapset * rd_idattr
Definition rel.h:164
#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 
)
extern

Definition at line 6012 of file relcache.c.

6013{
6015 bytea **opts = relation->rd_opcoptions;
6016 Oid relid = RelationGetRelid(relation);
6017 int natts = RelationGetNumberOfAttributes(relation); /* XXX
6018 * IndexRelationGetNumberOfKeyAttributes */
6019 int i;
6020
6021 /* Try to copy cached options. */
6022 if (opts)
6023 return copy ? CopyIndexAttOptions(opts, natts) : opts;
6024
6025 /* Get and parse opclass options. */
6026 opts = palloc0_array(bytea *, natts);
6027
6028 for (i = 0; i < natts; i++)
6029 {
6031 {
6032 Datum attoptions = get_attoptions(relid, i + 1);
6033
6034 opts[i] = index_opclass_options(relation, i + 1, attoptions, false);
6035
6036 if (attoptions != (Datum) 0)
6037 pfree(DatumGetPointer(attoptions));
6038 }
6039 }
6040
6041 /* Copy parsed options to the cache. */
6043 relation->rd_opcoptions = CopyIndexAttOptions(opts, natts);
6045
6046 if (copy)
6047 return opts;
6048
6049 for (i = 0; i < natts; i++)
6050 {
6051 if (opts[i])
6052 pfree(opts[i]);
6053 }
6054
6055 pfree(opts);
6056
6057 return relation->rd_opcoptions;
6058}
#define palloc0_array(type, count)
Definition fe_memutils.h:92
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:1127
static AmcheckOptions opts
Definition pg_amcheck.c:112
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
#define RelationGetNumberOfAttributes(relation)
Definition rel.h:522
static bytea ** CopyIndexAttOptions(bytea **srcopts, int natts)
Definition relcache.c:5992
bytea ** rd_opcoptions
Definition rel.h:218
Definition c.h:776

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 
)
extern

Definition at line 5304 of file relcache.c.

5305{
5306 Bitmapset *uindexattrs; /* columns in unique indexes */
5307 Bitmapset *pkindexattrs; /* columns in the primary index */
5308 Bitmapset *idindexattrs; /* columns in the replica identity */
5309 Bitmapset *hotblockingattrs; /* columns with HOT blocking indexes */
5310 Bitmapset *summarizedattrs; /* columns with summarizing indexes */
5315 ListCell *l;
5317
5318 /* Quick exit if we already computed the result. */
5319 if (relation->rd_attrsvalid)
5320 {
5321 switch (attrKind)
5322 {
5324 return bms_copy(relation->rd_keyattr);
5326 return bms_copy(relation->rd_pkattr);
5328 return bms_copy(relation->rd_idattr);
5330 return bms_copy(relation->rd_hotblockingattr);
5332 return bms_copy(relation->rd_summarizedattr);
5333 default:
5334 elog(ERROR, "unknown attrKind %u", attrKind);
5335 }
5336 }
5337
5338 /* Fast path if definitely no indexes */
5339 if (!RelationGetForm(relation)->relhasindex)
5340 return NULL;
5341
5342 /*
5343 * Get cached list of index OIDs. If we have to start over, we do so here.
5344 */
5345restart:
5347
5348 /* Fall out if no indexes (but relhasindex was set) */
5349 if (indexoidlist == NIL)
5350 return NULL;
5351
5352 /*
5353 * Copy the rd_pkindex and rd_replidindex values computed by
5354 * RelationGetIndexList before proceeding. This is needed because a
5355 * relcache flush could occur inside index_open below, resetting the
5356 * fields managed by RelationGetIndexList. We need to do the work with
5357 * stable values of these fields.
5358 */
5359 relpkindex = relation->rd_pkindex;
5360 relreplindex = relation->rd_replidindex;
5361
5362 /*
5363 * For each index, add referenced attributes to indexattrs.
5364 *
5365 * Note: we consider all indexes returned by RelationGetIndexList, even if
5366 * they are not indisready or indisvalid. This is important because an
5367 * index for which CREATE INDEX CONCURRENTLY has just started must be
5368 * included in HOT-safety decisions (see README.HOT). If a DROP INDEX
5369 * CONCURRENTLY is far enough along that we should ignore the index, it
5370 * won't be returned at all by RelationGetIndexList.
5371 */
5372 uindexattrs = NULL;
5377 foreach(l, indexoidlist)
5378 {
5379 Oid indexOid = lfirst_oid(l);
5381 Datum datum;
5382 bool isnull;
5385 int i;
5386 bool isKey; /* candidate key */
5387 bool isPK; /* primary key */
5388 bool isIDKey; /* replica identity index */
5389 Bitmapset **attrs;
5390
5392
5393 /*
5394 * Extract index expressions and index predicate. Note: Don't use
5395 * RelationGetIndexExpressions()/RelationGetIndexPredicate(), because
5396 * those might run constant expressions evaluation, which needs a
5397 * snapshot, which we might not have here. (Also, it's probably more
5398 * sound to collect the bitmaps before any transformations that might
5399 * eliminate columns, but the practical impact of this is limited.)
5400 */
5401
5402 datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indexprs,
5403 GetPgIndexDescriptor(), &isnull);
5404 if (!isnull)
5406 else
5408
5409 datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indpred,
5410 GetPgIndexDescriptor(), &isnull);
5411 if (!isnull)
5413 else
5415
5416 /* Can this index be referenced by a foreign key? */
5417 isKey = indexDesc->rd_index->indisunique &&
5420
5421 /* Is this a primary key? */
5422 isPK = (indexOid == relpkindex);
5423
5424 /* Is this index the configured (or default) replica identity? */
5425 isIDKey = (indexOid == relreplindex);
5426
5427 /*
5428 * If the index is summarizing, it doesn't block HOT updates, but we
5429 * may still need to update it (if the attributes were modified). So
5430 * decide which bitmap we'll update in the following loop.
5431 */
5432 if (indexDesc->rd_indam->amsummarizing)
5434 else
5436
5437 /* Collect simple attribute references */
5438 for (i = 0; i < indexDesc->rd_index->indnatts; i++)
5439 {
5440 int attrnum = indexDesc->rd_index->indkey.values[i];
5441
5442 /*
5443 * Since we have covering indexes with non-key columns, we must
5444 * handle them accurately here. non-key columns must be added into
5445 * hotblockingattrs or summarizedattrs, since they are in index,
5446 * and update shouldn't miss them.
5447 *
5448 * Summarizing indexes do not block HOT, but do need to be updated
5449 * when the column value changes, thus require a separate
5450 * attribute bitmapset.
5451 *
5452 * Obviously, non-key columns couldn't be referenced by foreign
5453 * key or identity key. Hence we do not include them into
5454 * uindexattrs, pkindexattrs and idindexattrs bitmaps.
5455 */
5456 if (attrnum != 0)
5457 {
5460
5461 if (isKey && i < indexDesc->rd_index->indnkeyatts)
5464
5465 if (isPK && i < indexDesc->rd_index->indnkeyatts)
5468
5469 if (isIDKey && i < indexDesc->rd_index->indnkeyatts)
5472 }
5473 }
5474
5475 /* Collect all attributes used in expressions, too */
5477
5478 /* Collect all attributes in the index predicate, too */
5480
5482 }
5483
5484 /*
5485 * During one of the index_opens in the above loop, we might have received
5486 * a relcache flush event on this relcache entry, which might have been
5487 * signaling a change in the rel's index list. If so, we'd better start
5488 * over to ensure we deliver up-to-date attribute bitmaps.
5489 */
5492 relpkindex == relation->rd_pkindex &&
5493 relreplindex == relation->rd_replidindex)
5494 {
5495 /* Still the same index set, so proceed */
5498 }
5499 else
5500 {
5501 /* Gotta do it over ... might as well not leak memory */
5509
5510 goto restart;
5511 }
5512
5513 /* Don't leak the old values of these bitmaps, if any */
5514 relation->rd_attrsvalid = false;
5515 bms_free(relation->rd_keyattr);
5516 relation->rd_keyattr = NULL;
5517 bms_free(relation->rd_pkattr);
5518 relation->rd_pkattr = NULL;
5519 bms_free(relation->rd_idattr);
5520 relation->rd_idattr = NULL;
5521 bms_free(relation->rd_hotblockingattr);
5522 relation->rd_hotblockingattr = NULL;
5523 bms_free(relation->rd_summarizedattr);
5524 relation->rd_summarizedattr = NULL;
5525
5526 /*
5527 * Now save copies of the bitmaps in the relcache entry. We intentionally
5528 * set rd_attrsvalid last, because that's the one that signals validity of
5529 * the values; if we run out of memory before making that copy, we won't
5530 * leave the relcache entry looking like the other ones are valid but
5531 * empty.
5532 */
5534 relation->rd_keyattr = bms_copy(uindexattrs);
5535 relation->rd_pkattr = bms_copy(pkindexattrs);
5536 relation->rd_idattr = bms_copy(idindexattrs);
5539 relation->rd_attrsvalid = true;
5541
5542 /* We return our original working copy for caller to play with */
5543 switch (attrKind)
5544 {
5546 return uindexattrs;
5548 return pkindexattrs;
5550 return idindexattrs;
5552 return hotblockingattrs;
5554 return summarizedattrs;
5555 default:
5556 elog(ERROR, "unknown attrKind %u", attrKind);
5557 return NULL;
5558 }
5559}
bool equal(const void *a, const void *b)
Definition equalfuncs.c:223
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:4837
Bitmapset * rd_keyattr
Definition rel.h:162
bool rd_attrsvalid
Definition rel.h:161
Bitmapset * rd_hotblockingattr
Definition rel.h:165
Oid rd_pkindex
Definition rel.h:153
Bitmapset * rd_summarizedattr
Definition rel.h:166
Bitmapset * rd_pkattr
Definition rel.h:163
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)
extern

Definition at line 5098 of file relcache.c.

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

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)
extern

Definition at line 4837 of file relcache.c.

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

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(), applyPartitionIndexExtDeps(), ATExecChangeOwner(), ATExecSetTableSpace(), AttachPartitionEnsureIndexes(), calculate_indexes_size(), calculate_toast_table_size(), collectPartitionIndexExtDeps(), 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)
extern

Definition at line 5211 of file relcache.c.

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

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 
)
extern

Definition at line 5048 of file relcache.c.

5049{
5050 List *ilist;
5051
5052 if (!relation->rd_indexvalid)
5053 {
5054 /* RelationGetIndexList does the heavy lifting. */
5055 ilist = RelationGetIndexList(relation);
5057 Assert(relation->rd_indexvalid);
5058 }
5059
5060 if (deferrable_ok)
5061 return relation->rd_pkindex;
5062 else if (relation->rd_ispkdeferrable)
5063 return InvalidOid;
5064 return relation->rd_pkindex;
5065}

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().

◆ RelationGetQualifiedRelationName()

char * RelationGetQualifiedRelationName ( Relation  rel)
extern

Definition at line 2142 of file relcache.c.

2143{
2146}
char * get_qualified_objname(Oid nspid, char *objname)
Definition lsyscache.c:3637

References get_qualified_objname(), RelationGetNamespace, and RelationGetRelationName.

Referenced by check_publication_add_relation().

◆ RelationGetReplicaIndex()

Oid RelationGetReplicaIndex ( Relation  relation)
extern

Definition at line 5073 of file relcache.c.

5074{
5075 List *ilist;
5076
5077 if (!relation->rd_indexvalid)
5078 {
5079 /* RelationGetIndexList does the heavy lifting. */
5080 ilist = RelationGetIndexList(relation);
5082 Assert(relation->rd_indexvalid);
5083 }
5084
5085 return relation->rd_replidindex;
5086}

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

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

◆ RelationGetStatExtList()

List * RelationGetStatExtList ( Relation  relation)
extern

Definition at line 4978 of file relcache.c.

4979{
4983 HeapTuple htup;
4984 List *result;
4985 List *oldlist;
4987
4988 /* Quick exit if we already computed the list. */
4989 if (relation->rd_statvalid != 0)
4990 return list_copy(relation->rd_statlist);
4991
4992 /*
4993 * We build the list we intend to return (in the caller's context) while
4994 * doing the scan. After successfully completing the scan, we copy that
4995 * list into the relcache entry. This avoids cache-context memory leakage
4996 * if we get some sort of error partway through.
4997 */
4998 result = NIL;
4999
5000 /*
5001 * Prepare to scan pg_statistic_ext for entries having stxrelid = this
5002 * rel.
5003 */
5008
5011 NULL, 1, &skey);
5012
5014 {
5015 Oid oid = ((Form_pg_statistic_ext) GETSTRUCT(htup))->oid;
5016
5017 result = lappend_oid(result, oid);
5018 }
5019
5021
5023
5024 /* Sort the result list into OID order, per API spec. */
5026
5027 /* Now save a copy of the completed list in the relcache entry. */
5029 oldlist = relation->rd_statlist;
5030 relation->rd_statlist = list_copy(result);
5031
5032 relation->rd_statvalid = true;
5034
5035 /* Don't leak the old list, if there is one */
5037
5038 return result;
5039}
END_CATALOG_STRUCT typedef FormData_pg_statistic_ext * Form_pg_statistic_ext
bool rd_statvalid
Definition rel.h:66
List * rd_statlist
Definition rel.h:158

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)
extern

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 Relation RelationBuildDesc(Oid targetRelId, bool insertIt)
Definition relcache.c:1055
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)
extern

Definition at line 6846 of file relcache.c.

6847{
6852 {
6853 /*
6854 * If this Assert fails, we don't need the applicable special case
6855 * anymore.
6856 */
6858 return true;
6859 }
6861}
bool RelationSupportsSysCache(Oid relid)
Definition syscache.c:763

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

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

◆ RelationInitIndexAccessInfo()

void RelationInitIndexAccessInfo ( Relation  relation)
extern

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}
int16_t int16
Definition c.h:619
regproc RegProcedure
Definition c.h:734
HeapTuple heap_copytuple(HeapTuple tuple)
Definition heaptuple.c:686
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition mcxt.c:1269
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_SMALL_SIZES
Definition memutils.h:170
#define MemoryContextCopyAndSetIdentifier(cxt, id)
Definition memutils.h:101
END_CATALOG_STRUCT typedef FormData_pg_am * Form_pg_am
Definition pg_am.h:52
#define IndexRelationGetNumberOfAttributes(relation)
Definition rel.h:528
static void InitIndexAmRoutine(Relation relation)
Definition relcache.c:1417
static void IndexSupportInitialize(oidvector *indclass, RegProcedure *indexSupport, Oid *opFamily, Oid *opcInType, StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber)
Definition relcache.c:1607
bytea ** RelationGetIndexAttOptions(Relation relation, bool copy)
Definition relcache.c:6012
uint16 amsupport
Definition amapi.h:243
const struct IndexAmRoutine * rd_indam
Definition rel.h:206
RegProcedure * rd_support
Definition rel.h:209
Oid * rd_opcintype
Definition rel.h:208
int16 * rd_indoption
Definition rel.h:211
void * rd_amcache
Definition rel.h:229
Oid rd_amhandler
Definition rel.h:184
struct FmgrInfo * rd_supportinfo
Definition rel.h:210
Oid * rd_indcollation
Definition rel.h:217
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().

◆ RelationInitTableAccessMethod()

void RelationInitTableAccessMethod ( Relation  relation)
extern

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}
bool IsCatalogRelation(Relation relation)
Definition catalog.c:104
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().

◆ RelationSetNewRelfilenumber()

void RelationSetNewRelfilenumber ( Relation  relation,
char  persistence 
)
extern

Definition at line 3775 of file relcache.c.

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

Variable Documentation

◆ criticalRelcachesBuilt

◆ criticalSharedRelcachesBuilt