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

3369{
3370 HASH_SEQ_STATUS status;
3372 int i;
3373
3374 /*
3375 * Forget in_progress_list. This is relevant when we're aborting due to
3376 * an error during RelationBuildDesc(). We don't commit subtransactions
3377 * during RelationBuildDesc().
3378 */
3381
3382 /*
3383 * Unless the eoxact_list[] overflowed, we only need to examine the rels
3384 * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3385 * logic as in AtEOXact_RelationCache.
3386 */
3388 {
3390 while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3391 {
3394 }
3395 }
3396 else
3397 {
3398 for (i = 0; i < eoxact_list_len; i++)
3399 {
3401 &eoxact_list[i],
3402 HASH_FIND,
3403 NULL);
3404 if (idhentry != NULL)
3407 }
3408 }
3409
3410 /* Don't reset the list; we still need more cleanup later */
3411}
#define Assert(condition)
Definition c.h:945
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition dynahash.c:952
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition dynahash.c:1415
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition dynahash.c:1380
@ HASH_FIND
Definition hsearch.h:113
int i
Definition isn.c:77
static int fb(int x)
static Oid eoxact_list[MAX_EOXACT_LIST]
Definition relcache.c:186
static int in_progress_list_len
Definition relcache.c:172
static void AtEOSubXact_cleanup(Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
Definition relcache.c:3422
static int eoxact_list_len
Definition relcache.c:187
static bool eoxact_list_overflowed
Definition relcache.c:188
static HTAB * RelationIdCache
Definition relcache.c:135

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

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

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

6063{
6067
6068 return 0; /* return value does not matter */
6069}
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:548
#define RelationGetNamespace(relation)
Definition rel.h:555

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

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

◆ errtablecol()

int errtablecol ( Relation  rel,
int  attnum 
)
extern

Definition at line 6079 of file relcache.c.

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

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

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

Referenced by errtablecol().

◆ errtableconstraint()

◆ RelationAssumeNewRelfilelocator()

void RelationAssumeNewRelfilelocator ( Relation  relation)
extern

Definition at line 3967 of file relcache.c.

3968{
3972
3973 /* Flag relation as needing eoxact cleanup (to clear these fields) */
3974 EOXactListAdd(relation);
3975}
#define InvalidSubTransactionId
Definition c.h:744
#define EOXactListAdd(rel)
Definition relcache.c:190
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 3504 of file relcache.c.

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

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

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

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

6901{
6903}
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1794

References fb(), and LWLockRelease().

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

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )
extern

Definition at line 6875 of file relcache.c.

6876{
6879
6880 if (DatabasePath)
6881 snprintf(localinitfname, sizeof(localinitfname), "%s/%s",
6883 snprintf(sharedinitfname, sizeof(sharedinitfname), "global/%s",
6885
6887
6888 /*
6889 * The files might not be there if no backend has been started since the
6890 * last removal. But complain about failures other than ENOENT with
6891 * ERROR. Fortunately, it's not too late to abort the transaction if we
6892 * can't get rid of the would-be-obsolete init file.
6893 */
6894 if (DatabasePath)
6897}
char * DatabasePath
Definition globals.c:104
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1177
@ LW_EXCLUSIVE
Definition lwlock.h:112
#define MAXPGPATH
#define snprintf
Definition port.h:260
static void unlink_initfile(const char *initfilename, int elevel)
Definition relcache.c:6972
#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 6915 of file relcache.c.

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

3994{
3995 HASHCTL ctl;
3996 int allocsize;
3997
3998 /*
3999 * make sure cache memory context exists
4000 */
4001 if (!CacheMemoryContext)
4003
4004 /*
4005 * create hashtable that indexes the relcache
4006 */
4007 ctl.keysize = sizeof(Oid);
4008 ctl.entrysize = sizeof(RelIdCacheEnt);
4009 RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
4011
4012 /*
4013 * reserve enough in_progress_list slots for many cases
4014 */
4015 allocsize = 4;
4018 allocsize * sizeof(*in_progress_list));
4019 in_progress_list_maxlen = allocsize;
4020
4021 /*
4022 * relation mapper needs to be initialized too
4023 */
4025}
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition dynahash.c:358
#define HASH_ELEM
Definition hsearch.h:95
#define HASH_BLOBS
Definition hsearch.h:97
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:173
#define INITRELCACHESIZE
Definition relcache.c:3990
struct relidcacheent RelIdCacheEnt
static InProgressEnt * in_progress_list
Definition relcache.c:171
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 4039 of file relcache.c.

4040{
4042
4043 /*
4044 * relation mapper needs initialized too
4045 */
4047
4048 /*
4049 * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
4050 * nothing.
4051 */
4053 return;
4054
4055 /*
4056 * switch to cache memory context
4057 */
4059
4060 /*
4061 * Try to load the shared relcache cache file. If unsuccessful, bootstrap
4062 * the cache with pre-made descriptors for the critical shared catalogs.
4063 */
4064 if (!load_relcache_init_file(true))
4065 {
4066 formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
4068 formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
4070 formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
4072 formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
4074 formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
4076
4077#define NUM_CRITICAL_SHARED_RELS 5 /* fix if you change list above */
4078 }
4079
4081}
#define IsBootstrapProcessingMode()
Definition miscadmin.h:477
static bool load_relcache_init_file(bool shared)
Definition relcache.c:6180
static const FormData_pg_attribute Desc_pg_shseclabel[Natts_pg_shseclabel]
Definition relcache.c:120
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
Definition relcache.c:1884
static const FormData_pg_attribute Desc_pg_database[Natts_pg_database]
Definition relcache.c:116
static const FormData_pg_attribute Desc_pg_authid[Natts_pg_authid]
Definition relcache.c:117
static const FormData_pg_attribute Desc_pg_subscription[Natts_pg_subscription]
Definition relcache.c:121
static const FormData_pg_attribute Desc_pg_auth_members[Natts_pg_auth_members]
Definition relcache.c:118
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 4098 of file relcache.c.

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

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

2928{
2929 Relation relation;
2930
2932
2933 if (relation)
2934 {
2936 RelationFlushRelation(relation);
2937 }
2938 else
2939 {
2940 int i;
2941
2942 for (i = 0; i < in_progress_list_len; i++)
2943 if (in_progress_list[i].reloid == relationId)
2945 }
2946}
#define RelationIdCacheLookup(ID, RELATION)
Definition relcache.c:232
static void RelationFlushRelation(Relation relation)
Definition relcache.c:2816
bool invalidated
Definition relcache.c:168

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

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

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

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

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

5147{
5148 List *result;
5150 bool isnull;
5151 char *exprsString;
5152 List *rawExprs;
5153 ListCell *lc;
5154
5155 /* Quick exit if there is nothing to do. */
5156 if (relation->rd_indextuple == NULL ||
5158 return NIL;
5159
5160 /* Extract raw node tree(s) from index tuple. */
5164 &isnull);
5165 Assert(!isnull);
5169
5170 /* Construct null Consts; the typlen and typbyval are arbitrary. */
5171 result = NIL;
5172 foreach(lc, rawExprs)
5173 {
5174 Node *rawExpr = (Node *) lfirst(lc);
5175
5176 result = lappend(result,
5180 1,
5181 (Datum) 0,
5182 true,
5183 true));
5184 }
5185
5186 return result;
5187}
#define TextDatumGetCString(d)
Definition builtins.h:99
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:4463
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, stringToNode(), and TextDatumGetCString.

Referenced by BuildDummyIndexInfo().

◆ RelationGetExclusionInfo()

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

Definition at line 5643 of file relcache.c.

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

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

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

6002{
6004 bytea **opts = relation->rd_opcoptions;
6005 Oid relid = RelationGetRelid(relation);
6006 int natts = RelationGetNumberOfAttributes(relation); /* XXX
6007 * IndexRelationGetNumberOfKeyAttributes */
6008 int i;
6009
6010 /* Try to copy cached options. */
6011 if (opts)
6012 return copy ? CopyIndexAttOptions(opts, natts) : opts;
6013
6014 /* Get and parse opclass options. */
6015 opts = palloc0_array(bytea *, natts);
6016
6017 for (i = 0; i < natts; i++)
6018 {
6020 {
6021 Datum attoptions = get_attoptions(relid, i + 1);
6022
6023 opts[i] = index_opclass_options(relation, i + 1, attoptions, false);
6024
6025 if (attoptions != (Datum) 0)
6026 pfree(DatumGetPointer(attoptions));
6027 }
6028 }
6029
6030 /* Copy parsed options to the cache. */
6032 relation->rd_opcoptions = CopyIndexAttOptions(opts, natts);
6034
6035 if (copy)
6036 return opts;
6037
6038 for (i = 0; i < natts; i++)
6039 {
6040 if (opts[i])
6041 pfree(opts[i]);
6042 }
6043
6044 pfree(opts);
6045
6046 return relation->rd_opcoptions;
6047}
#define palloc0_array(type, count)
Definition fe_memutils.h:77
bytea * index_opclass_options(Relation indrel, AttrNumber attnum, Datum attoptions, bool validate)
Definition indexam.c:1048
Datum get_attoptions(Oid relid, int16 attnum)
Definition lsyscache.c:1089
static AmcheckOptions opts
Definition pg_amcheck.c:112
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
#define RelationGetNumberOfAttributes(relation)
Definition rel.h:520
static bytea ** CopyIndexAttOptions(bytea **srcopts, int natts)
Definition relcache.c:5981
bytea ** rd_opcoptions
Definition rel.h:218
Definition c.h:778

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

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

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

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

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

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

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

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

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

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

◆ RelationGetStatExtList()

List * RelationGetStatExtList ( Relation  relation)
extern

Definition at line 4967 of file relcache.c.

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

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

6836{
6841 {
6842 /*
6843 * If this Assert fails, we don't need the applicable special case
6844 * anymore.
6845 */
6847 return true;
6848 }
6850}
bool RelationSupportsSysCache(Oid relid)
Definition syscache.c:762

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

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

◆ RelationInitIndexAccessInfo()

void RelationInitIndexAccessInfo ( Relation  relation)
extern

Definition at line 1435 of file relcache.c.

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

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

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

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

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