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)
 
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 143 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 67 of file relcache.h.

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

Function Documentation

◆ AssertCouldGetRelation()

◆ AtEOSubXact_RelationCache()

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

Definition at line 3368 of file relcache.c.

3370{
3371 HASH_SEQ_STATUS status;
3373 int i;
3374
3375 /*
3376 * Forget in_progress_list. This is relevant when we're aborting due to
3377 * an error during RelationBuildDesc(). We don't commit subtransactions
3378 * during RelationBuildDesc().
3379 */
3382
3383 /*
3384 * Unless the eoxact_list[] overflowed, we only need to examine the rels
3385 * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3386 * logic as in AtEOXact_RelationCache.
3387 */
3389 {
3391 while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3392 {
3395 }
3396 }
3397 else
3398 {
3399 for (i = 0; i < eoxact_list_len; i++)
3400 {
3402 &eoxact_list[i],
3403 HASH_FIND,
3404 NULL);
3405 if (idhentry != NULL)
3408 }
3409 }
3410
3411 /* Don't reset the list; we still need more cleanup later */
3412}
#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:3423
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 3216 of file relcache.c.

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

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

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

◆ errtable()

int errtable ( Relation  rel)
extern

Definition at line 6063 of file relcache.c.

6064{
6068
6069 return 0; /* return value does not matter */
6070}
int err_generic_string(int field, const char *str)
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3588
#define PG_DIAG_SCHEMA_NAME
#define PG_DIAG_TABLE_NAME
#define 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 6080 of file relcache.c.

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

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

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

Referenced by errtablecol().

◆ errtableconstraint()

◆ RelationAssumeNewRelfilelocator()

void RelationAssumeNewRelfilelocator ( Relation  relation)
extern

Definition at line 3968 of file relcache.c.

3969{
3973
3974 /* Flag relation as needing eoxact cleanup (to clear these fields) */
3975 EOXactListAdd(relation);
3976}
#define 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 3505 of file relcache.c.

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

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

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

References fb(), and LWLockRelease().

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

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )
extern

Definition at line 6876 of file relcache.c.

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

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

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

Referenced by StartupXLOG().

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )
extern

Definition at line 3994 of file relcache.c.

3995{
3996 HASHCTL ctl;
3997 int allocsize;
3998
3999 /*
4000 * make sure cache memory context exists
4001 */
4002 if (!CacheMemoryContext)
4004
4005 /*
4006 * create hashtable that indexes the relcache
4007 */
4008 ctl.keysize = sizeof(Oid);
4009 ctl.entrysize = sizeof(RelIdCacheEnt);
4010 RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
4012
4013 /*
4014 * reserve enough in_progress_list slots for many cases
4015 */
4016 allocsize = 4;
4019 allocsize * sizeof(*in_progress_list));
4020 in_progress_list_maxlen = allocsize;
4021
4022 /*
4023 * relation mapper needs to be initialized too
4024 */
4026}
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:1232
tree ctl
Definition radixtree.h:1838
static int in_progress_list_maxlen
Definition relcache.c:174
#define INITRELCACHESIZE
Definition relcache.c:3991
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 4040 of file relcache.c.

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

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

Referenced by InitPostgres().

◆ RelationCacheInitializePhase3()

void RelationCacheInitializePhase3 ( void  )
extern

Definition at line 4099 of file relcache.c.

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

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

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

Referenced by InvalidateSystemCachesExtended(), and LocalExecuteInvalidationMessage().

◆ RelationCacheInvalidateEntry()

void RelationCacheInvalidateEntry ( Oid  relationId)
extern

Definition at line 2928 of file relcache.c.

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

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

References RelationCloseCleanup(), and RelationDecrementReferenceCount().

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

◆ RelationForgetRelation()

void RelationForgetRelation ( Oid  rid)
extern

Definition at line 2883 of file relcache.c.

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

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

Referenced by heap_drop_with_catalog(), and index_drop().

◆ RelationGetDummyIndexExpressions()

List * RelationGetDummyIndexExpressions ( Relation  relation)
extern

Definition at line 5147 of file relcache.c.

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

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

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

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

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

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

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

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

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

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

◆ RelationGetIndexPredicate()

List * RelationGetIndexPredicate ( Relation  relation)
extern

Definition at line 5201 of file relcache.c.

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

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

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

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

◆ RelationGetReplicaIndex()

Oid RelationGetReplicaIndex ( Relation  relation)
extern

Definition at line 5063 of file relcache.c.

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

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

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

◆ RelationGetStatExtList()

List * RelationGetStatExtList ( Relation  relation)
extern

Definition at line 4968 of file relcache.c.

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

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

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

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

◆ 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:1266
#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:6002
uint16 amsupport
Definition amapi.h:242
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 3765 of file relcache.c.

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