PostgreSQL Source Code git master
Loading...
Searching...
No Matches
relcache.c File Reference
#include "postgres.h"
#include <sys/file.h>
#include <fcntl.h>
#include <unistd.h>
#include "access/htup_details.h"
#include "access/multixact.h"
#include "access/parallel.h"
#include "access/reloptions.h"
#include "access/sysattr.h"
#include "access/table.h"
#include "access/tableam.h"
#include "access/tupdesc_details.h"
#include "access/xact.h"
#include "catalog/binary_upgrade.h"
#include "catalog/catalog.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/partition.h"
#include "catalog/pg_am.h"
#include "catalog/pg_amproc.h"
#include "catalog/pg_attrdef.h"
#include "catalog/pg_auth_members.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_database.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_publication.h"
#include "catalog/pg_rewrite.h"
#include "catalog/pg_shseclabel.h"
#include "catalog/pg_statistic_ext.h"
#include "catalog/pg_subscription.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
#include "catalog/schemapg.h"
#include "catalog/storage.h"
#include "commands/policy.h"
#include "commands/publicationcmds.h"
#include "commands/trigger.h"
#include "common/int.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/optimizer.h"
#include "pgstat.h"
#include "rewrite/rewriteDefine.h"
#include "rewrite/rowsecurity.h"
#include "storage/fd.h"
#include "storage/lmgr.h"
#include "storage/smgr.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/datum.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/relmapper.h"
#include "utils/resowner.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
Include dependency graph for relcache.c:

Go to the source code of this file.

Data Structures

struct  relidcacheent
 
struct  inprogressent
 
struct  opclasscacheent
 

Macros

#define RELCACHE_INIT_FILEMAGIC   0x573266 /* version ID value */
 
#define RECOVER_RELATION_BUILD_MEMORY   0
 
#define MAX_EOXACT_LIST   32
 
#define EOXactListAdd(rel)
 
#define RelationCacheInsert(RELATION, replace_allowed)
 
#define RelationIdCacheLookup(ID, RELATION)
 
#define RelationCacheDelete(RELATION)
 
#define SWAPFIELD(fldtype, fldname)
 
#define INITRELCACHESIZE   400
 
#define NUM_CRITICAL_SHARED_RELS   5 /* fix if you change list above */
 
#define NUM_CRITICAL_LOCAL_RELS   4 /* fix if you change list above */
 
#define NUM_CRITICAL_LOCAL_INDEXES   7 /* fix if you change list above */
 
#define NUM_CRITICAL_SHARED_INDEXES   6 /* fix if you change list above */
 

Typedefs

typedef struct relidcacheent RelIdCacheEnt
 
typedef struct inprogressent InProgressEnt
 
typedef struct opclasscacheent OpClassCacheEnt
 

Functions

static void RelationCloseCleanup (Relation relation)
 
static void RelationDestroyRelation (Relation relation, bool remember_tupdesc)
 
static void RelationInvalidateRelation (Relation relation)
 
static void RelationClearRelation (Relation relation)
 
static void RelationRebuildRelation (Relation relation)
 
static void RelationReloadIndexInfo (Relation relation)
 
static void RelationReloadNailed (Relation relation)
 
static void RelationFlushRelation (Relation relation)
 
static void RememberToFreeTupleDescAtEOX (TupleDesc td)
 
static void AtEOXact_cleanup (Relation relation, bool isCommit)
 
static void AtEOSubXact_cleanup (Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
 
static bool load_relcache_init_file (bool shared)
 
static void write_relcache_init_file (bool shared)
 
static void write_item (const void *data, Size len, FILE *fp)
 
static void formrdesc (const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
 
static HeapTuple ScanPgRelation (Oid targetRelId, bool indexOK, bool force_non_historic)
 
static Relation AllocateRelationDesc (Form_pg_class relp)
 
static void RelationParseRelOptions (Relation relation, HeapTuple tuple)
 
static void RelationBuildTupleDesc (Relation relation)
 
static Relation RelationBuildDesc (Oid targetRelId, bool insertIt)
 
static void RelationInitPhysicalAddr (Relation relation)
 
static void load_critical_index (Oid indexoid, Oid heapoid)
 
static TupleDesc GetPgClassDescriptor (void)
 
static TupleDesc GetPgIndexDescriptor (void)
 
static void AttrDefaultFetch (Relation relation, int ndef)
 
static int AttrDefaultCmp (const void *a, const void *b)
 
static void CheckNNConstraintFetch (Relation relation)
 
static int CheckConstraintCmp (const void *a, const void *b)
 
static void InitIndexAmRoutine (Relation relation)
 
static void IndexSupportInitialize (oidvector *indclass, RegProcedure *indexSupport, Oid *opFamily, Oid *opcInType, StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber)
 
static OpClassCacheEntLookupOpclassInfo (Oid operatorClassOid, StrategyNumber numSupport)
 
static void RelationCacheInitFileRemoveInDir (const char *tblspcpath)
 
static void unlink_initfile (const char *initfilename, int elevel)
 
static void RelationBuildRuleLock (Relation relation)
 
static bool equalRuleLocks (RuleLock *rlock1, RuleLock *rlock2)
 
static bool equalPolicy (RowSecurityPolicy *policy1, RowSecurityPolicy *policy2)
 
static bool equalRSDesc (RowSecurityDesc *rsdesc1, RowSecurityDesc *rsdesc2)
 
void RelationInitIndexAccessInfo (Relation relation)
 
static void InitTableAmRoutine (Relation relation)
 
void RelationInitTableAccessMethod (Relation relation)
 
Relation RelationIdGetRelation (Oid relationId)
 
static void ResOwnerReleaseRelation (Datum res)
 
static charResOwnerPrintRelCache (Datum res)
 
static void ResourceOwnerRememberRelationRef (ResourceOwner owner, Relation rel)
 
static void ResourceOwnerForgetRelationRef (ResourceOwner owner, Relation rel)
 
void RelationIncrementReferenceCount (Relation rel)
 
void RelationDecrementReferenceCount (Relation rel)
 
void RelationClose (Relation relation)
 
void RelationForgetRelation (Oid rid)
 
void RelationCacheInvalidateEntry (Oid relationId)
 
void RelationCacheInvalidate (bool debug_discard)
 
void AtEOXact_RelationCache (bool isCommit)
 
void AtEOSubXact_RelationCache (bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
 
Relation RelationBuildLocalRelation (const char *relname, Oid relnamespace, TupleDesc tupDesc, Oid relid, Oid accessmtd, RelFileNumber relfilenumber, Oid reltablespace, bool shared_relation, bool mapped_relation, char relpersistence, char relkind)
 
void RelationSetNewRelfilenumber (Relation relation, char persistence)
 
void RelationAssumeNewRelfilelocator (Relation relation)
 
void RelationCacheInitialize (void)
 
void RelationCacheInitializePhase2 (void)
 
void RelationCacheInitializePhase3 (void)
 
static TupleDesc BuildHardcodedDescriptor (int natts, const FormData_pg_attribute *attrs)
 
ListRelationGetFKeyList (Relation relation)
 
ListRelationGetIndexList (Relation relation)
 
ListRelationGetStatExtList (Relation relation)
 
Oid RelationGetPrimaryKeyIndex (Relation relation, bool deferrable_ok)
 
Oid RelationGetReplicaIndex (Relation relation)
 
ListRelationGetIndexExpressions (Relation relation)
 
ListRelationGetDummyIndexExpressions (Relation relation)
 
ListRelationGetIndexPredicate (Relation relation)
 
BitmapsetRelationGetIndexAttrBitmap (Relation relation, IndexAttrBitmapKind attrKind)
 
BitmapsetRelationGetIdentityKeyBitmap (Relation relation)
 
void RelationGetExclusionInfo (Relation indexRelation, Oid **operators, Oid **procs, uint16 **strategies)
 
void RelationBuildPublicationDesc (Relation relation, PublicationDesc *pubdesc)
 
static bytea ** CopyIndexAttOptions (bytea **srcopts, int natts)
 
bytea ** RelationGetIndexAttOptions (Relation relation, bool copy)
 
int errtable (Relation rel)
 
int errtablecol (Relation rel, int attnum)
 
int errtablecolname (Relation rel, const char *colname)
 
int errtableconstraint (Relation rel, const char *conname)
 
bool RelationIdIsInInitFile (Oid relationId)
 
void RelationCacheInitFilePreInvalidate (void)
 
void RelationCacheInitFilePostInvalidate (void)
 
void RelationCacheInitFileRemove (void)
 

Variables

static const FormData_pg_attribute Desc_pg_class [Natts_pg_class] = {Schema_pg_class}
 
static const FormData_pg_attribute Desc_pg_attribute [Natts_pg_attribute] = {Schema_pg_attribute}
 
static const FormData_pg_attribute Desc_pg_proc [Natts_pg_proc] = {Schema_pg_proc}
 
static const FormData_pg_attribute Desc_pg_type [Natts_pg_type] = {Schema_pg_type}
 
static const FormData_pg_attribute Desc_pg_database [Natts_pg_database] = {Schema_pg_database}
 
static const FormData_pg_attribute Desc_pg_authid [Natts_pg_authid] = {Schema_pg_authid}
 
static const FormData_pg_attribute Desc_pg_auth_members [Natts_pg_auth_members] = {Schema_pg_auth_members}
 
static const FormData_pg_attribute Desc_pg_index [Natts_pg_index] = {Schema_pg_index}
 
static const FormData_pg_attribute Desc_pg_shseclabel [Natts_pg_shseclabel] = {Schema_pg_shseclabel}
 
static const FormData_pg_attribute Desc_pg_subscription [Natts_pg_subscription] = {Schema_pg_subscription}
 
static HTABRelationIdCache
 
bool criticalRelcachesBuilt = false
 
bool criticalSharedRelcachesBuilt = false
 
static long relcacheInvalsReceived = 0L
 
static InProgressEntin_progress_list
 
static int in_progress_list_len
 
static int in_progress_list_maxlen
 
static Oid eoxact_list [MAX_EOXACT_LIST]
 
static int eoxact_list_len = 0
 
static bool eoxact_list_overflowed = false
 
static TupleDescEOXactTupleDescArray
 
static int NextEOXactTupleDescNum = 0
 
static int EOXactTupleDescArrayLen = 0
 
static HTABOpClassCache = NULL
 
static const ResourceOwnerDesc relref_resowner_desc
 

Macro Definition Documentation

◆ EOXactListAdd

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

Definition at line 190 of file relcache.c.

191 { \
193 eoxact_list[eoxact_list_len++] = (rel)->rd_id; \
194 else \
196 } while (0)

◆ INITRELCACHESIZE

#define INITRELCACHESIZE   400

Definition at line 3990 of file relcache.c.

◆ MAX_EOXACT_LIST

#define MAX_EOXACT_LIST   32

Definition at line 185 of file relcache.c.

◆ NUM_CRITICAL_LOCAL_INDEXES

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

◆ NUM_CRITICAL_LOCAL_RELS

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

◆ NUM_CRITICAL_SHARED_INDEXES

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

◆ NUM_CRITICAL_SHARED_RELS

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

◆ RECOVER_RELATION_BUILD_MEMORY

#define RECOVER_RELATION_BUILD_MEMORY   0

Definition at line 103 of file relcache.c.

◆ RelationCacheDelete

#define RelationCacheDelete (   RELATION)
Value:
do { \
&((RELATION)->rd_id), \
elog(WARNING, "failed to delete relcache entry for OID %u", \
(RELATION)->rd_id); \
} while(0)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition dynahash.c:952
#define WARNING
Definition elog.h:36
@ HASH_REMOVE
Definition hsearch.h:115
static HTAB * RelationIdCache
Definition relcache.c:135

Definition at line 244 of file relcache.c.

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

◆ RelationCacheInsert

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

Definition at line 210 of file relcache.c.

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

◆ RelationIdCacheLookup

#define RelationIdCacheLookup (   ID,
  RELATION 
)
Value:

Definition at line 232 of file relcache.c.

233 { \
236 &(ID), \
237 HASH_FIND, NULL); \
238 if (hentry) \
240 else \
241 RELATION = NULL; \
242} while(0)

◆ RELCACHE_INIT_FILEMAGIC

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

Definition at line 94 of file relcache.c.

◆ SWAPFIELD

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

Typedef Documentation

◆ InProgressEnt

◆ OpClassCacheEnt

◆ RelIdCacheEnt

Function Documentation

◆ AllocateRelationDesc()

static Relation AllocateRelationDesc ( Form_pg_class  relp)
static

Definition at line 414 of file relcache.c.

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

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

Referenced by RelationBuildDesc().

◆ AtEOSubXact_cleanup()

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

Definition at line 3422 of file relcache.c.

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

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

Referenced by AtEOSubXact_RelationCache().

◆ AtEOSubXact_RelationCache()

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

Definition at line 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}
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition dynahash.c:1415
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition dynahash.c:1380
int i
Definition isn.c:77
static int in_progress_list_len
Definition relcache.c:172
static void AtEOSubXact_cleanup(Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
Definition relcache.c:3422
static bool eoxact_list_overflowed
Definition relcache.c:188

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

◆ AtEOXact_cleanup()

static void AtEOXact_cleanup ( Relation  relation,
bool  isCommit 
)
static

Definition at line 3285 of file relcache.c.

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

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

Referenced by AtEOXact_RelationCache().

◆ AtEOXact_RelationCache()

void AtEOXact_RelationCache ( bool  isCommit)

Definition at line 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().

◆ AttrDefaultCmp()

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

Definition at line 4565 of file relcache.c.

4566{
4567 const AttrDefault *ada = (const AttrDefault *) a;
4568 const AttrDefault *adb = (const AttrDefault *) b;
4569
4570 return pg_cmp_s16(ada->adnum, adb->adnum);
4571}
static int pg_cmp_s16(int16 a, int16 b)
Definition int.h:701
int b
Definition isn.c:74
int a
Definition isn.c:73

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

Referenced by AttrDefaultFetch().

◆ AttrDefaultFetch()

static void AttrDefaultFetch ( Relation  relation,
int  ndef 
)
static

Definition at line 4485 of file relcache.c.

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

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

Referenced by RelationBuildTupleDesc().

◆ BuildHardcodedDescriptor()

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

Definition at line 4421 of file relcache.c.

4422{
4423 TupleDesc result;
4425 int i;
4426
4428
4429 result = CreateTemplateTupleDesc(natts);
4430 result->tdtypeid = RECORDOID; /* not right, but we don't care */
4431 result->tdtypmod = -1;
4432
4433 for (i = 0; i < natts; i++)
4434 {
4436
4438 }
4439
4440 TupleDescFinalize(result);
4441
4442 /* Note: we don't bother to set up a TupleConstr entry */
4443
4445
4446 return result;
4447}
#define ATTRIBUTE_FIXED_PART_SIZE
int32 tdtypmod
Definition tupdesc.h:152
void TupleDescFinalize(TupleDesc tupdesc)
Definition tupdesc.c:508
void populate_compact_attribute(TupleDesc tupdesc, int attnum)
Definition tupdesc.c:100
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178

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

Referenced by GetPgClassDescriptor(), and GetPgIndexDescriptor().

◆ CheckConstraintCmp()

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

Definition at line 4698 of file relcache.c.

4699{
4700 const ConstrCheck *ca = (const ConstrCheck *) a;
4701 const ConstrCheck *cb = (const ConstrCheck *) b;
4702
4703 return strcmp(ca->ccname, cb->ccname);
4704}
char * ccname
Definition tupdesc.h:30

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

Referenced by CheckNNConstraintFetch().

◆ CheckNNConstraintFetch()

static void CheckNNConstraintFetch ( Relation  relation)
static

Definition at line 4581 of file relcache.c.

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

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

Referenced by RelationBuildTupleDesc().

◆ CopyIndexAttOptions()

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

Definition at line 5981 of file relcache.c.

5982{
5983 bytea **opts = palloc_array(bytea *, natts);
5984
5985 for (int i = 0; i < natts; i++)
5986 {
5987 bytea *opt = srcopts[i];
5988
5989 opts[i] = !opt ? NULL : (bytea *)
5990 DatumGetPointer(datumCopy(PointerGetDatum(opt), false, -1));
5991 }
5992
5993 return opts;
5994}
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition datum.c:132
#define palloc_array(type, count)
Definition fe_memutils.h:76
static AmcheckOptions opts
Definition pg_amcheck.c:112
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
Definition c.h:778

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

Referenced by RelationGetIndexAttOptions().

◆ equalPolicy()

static bool equalPolicy ( RowSecurityPolicy policy1,
RowSecurityPolicy policy2 
)
static

Definition at line 967 of file relcache.c.

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

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

Referenced by equalRSDesc().

◆ equalRSDesc()

static bool equalRSDesc ( RowSecurityDesc rsdesc1,
RowSecurityDesc rsdesc2 
)
static

Definition at line 1013 of file relcache.c.

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

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

Referenced by RelationRebuildRelation().

◆ equalRuleLocks()

static bool equalRuleLocks ( RuleLock rlock1,
RuleLock rlock2 
)
static

Definition at line 922 of file relcache.c.

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

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

Referenced by RelationRebuildRelation().

◆ errtable()

int errtable ( Relation  rel)

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 RelationGetNamespace(relation)
Definition rel.h:555

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

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

◆ errtablecol()

int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 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}
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:946
NameData attname
#define RelationGetDescr(relation)
Definition rel.h:540
int errtablecolname(Relation rel, const char *colname)
Definition relcache.c:6103

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

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

◆ errtablecolname()

int errtablecolname ( Relation  rel,
const char colname 
)

Definition at line 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()

◆ formrdesc()

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

Definition at line 1884 of file relcache.c.

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

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

Referenced by RelationCacheInitializePhase2(), and RelationCacheInitializePhase3().

◆ GetPgClassDescriptor()

static TupleDesc GetPgClassDescriptor ( void  )
static

Definition at line 4450 of file relcache.c.

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

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

Referenced by RelationParseRelOptions().

◆ GetPgIndexDescriptor()

static TupleDesc GetPgIndexDescriptor ( void  )
static

Definition at line 4463 of file relcache.c.

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

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

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

◆ IndexSupportInitialize()

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

Definition at line 1606 of file relcache.c.

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

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

Referenced by RelationInitIndexAccessInfo().

◆ InitIndexAmRoutine()

static void InitIndexAmRoutine ( Relation  relation)
static

Definition at line 1416 of file relcache.c.

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

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

Referenced by load_relcache_init_file(), and RelationInitIndexAccessInfo().

◆ InitTableAmRoutine()

static void InitTableAmRoutine ( Relation  relation)
static

Definition at line 1810 of file relcache.c.

1811{
1812 relation->rd_tableam = GetTableAmRoutine(relation->rd_amhandler);
1813}
const TableAmRoutine * GetTableAmRoutine(Oid amhandler)
Definition tableamapi.c:27

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

Referenced by RelationInitTableAccessMethod().

◆ load_critical_index()

static void load_critical_index ( Oid  indexoid,
Oid  heapoid 
)
static

Definition at line 4383 of file relcache.c.

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

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

Referenced by RelationCacheInitializePhase3().

◆ load_relcache_init_file()

static bool load_relcache_init_file ( bool  shared)
static

Definition at line 6180 of file relcache.c.

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

References AllocateFile(), ALLOCSET_SMALL_SIZES, AllocSetContextCreate, IndexAmRoutine::amsupport, Assert, ATTRIBUTE_FIXED_PART_SIZE, CacheMemoryContext, TupleDescData::constr, CreateTemplateTupleDesc(), criticalRelcachesBuilt, criticalSharedRelcachesBuilt, DatabasePath, elog, fb(), Form_pg_index, FreeFile(), GETSTRUCT(), TupleConstr::has_not_null, HEAPTUPLESIZE, i, InitIndexAmRoutine(), InvalidOid, InvalidSubTransactionId, InvalidTransactionId, len, MAXPGPATH, MemoryContextAlloc(), MemoryContextAllocZero(), MemoryContextCopyAndSetIdentifier, NIL, NUM_CRITICAL_LOCAL_INDEXES, NUM_CRITICAL_LOCAL_RELS, NUM_CRITICAL_SHARED_INDEXES, NUM_CRITICAL_SHARED_RELS, palloc(), palloc0_object, pfree(), PG_BINARY_R, RelationData::pgstat_info, populate_compact_attribute(), RelationData::rd_amcache, RelationData::rd_att, RelationData::rd_attrsvalid, RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_exclops, RelationData::rd_exclprocs, RelationData::rd_exclstrats, RelationData::rd_fdwroutine, RelationData::rd_firstRelfilelocatorSubid, RelationData::rd_fkeylist, RelationData::rd_fkeyvalid, RelationData::rd_idattr, RelationData::rd_indam, RelationData::rd_indcollation, RelationData::rd_index, RelationData::rd_indexcxt, RelationData::rd_indexlist, RelationData::rd_indexprs, RelationData::rd_indextuple, RelationData::rd_indexvalid, RelationData::rd_indoption, RelationData::rd_indpred, RelationData::rd_isnailed, RelationData::rd_keyattr, RelationData::rd_newRelfilelocatorSubid, RelationData::rd_opcintype, RelationData::rd_opcoptions, RelationData::rd_opfamily, RelationData::rd_options, RelationData::rd_partcheck, RelationData::rd_partcheckcxt, RelationData::rd_partcheckvalid, RelationData::rd_partdesc, RelationData::rd_partdesc_nodetached, RelationData::rd_partdesc_nodetached_xmin, RelationData::rd_partkey, RelationData::rd_partkeycxt, RelationData::rd_pdcxt, RelationData::rd_pddcxt, RelationData::rd_pkattr, RelationData::rd_pkindex, RelationData::rd_pubdesc, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_replidindex, RelationData::rd_rsdesc, RelationData::rd_rules, RelationData::rd_rulescxt, RelationData::rd_smgr, RelationData::rd_statlist, RelationData::rd_statvalid, RelationData::rd_support, RelationData::rd_supportinfo, RelationCacheInsert, RelationGetRelationName, RelationInitLockInfo(), RelationInitPhysicalAddr(), RelationInitTableAccessMethod(), RELCACHE_INIT_FILEMAGIC, RELCACHE_INIT_FILENAME, repalloc(), snprintf, HeapTupleData::t_data, TupleDescData::tdrefcount, TupleDescData::tdtypeid, TupleDescData::tdtypmod, RelationData::trigdesc, TupleDescAttr(), TupleDescFinalize(), VARSIZE(), and WARNING.

Referenced by RelationCacheInitializePhase2(), and RelationCacheInitializePhase3().

◆ LookupOpclassInfo()

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

Definition at line 1657 of file relcache.c.

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

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

Referenced by IndexSupportInitialize().

◆ RelationAssumeNewRelfilelocator()

void RelationAssumeNewRelfilelocator ( Relation  relation)

Definition at line 3967 of file relcache.c.

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

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

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

◆ RelationBuildDesc()

static Relation RelationBuildDesc ( Oid  targetRelId,
bool  insertIt 
)
static

Definition at line 1054 of file relcache.c.

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

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

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

◆ RelationBuildLocalRelation()

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

Definition at line 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
NameData relname
Definition pg_class.h:40
void RelationIncrementReferenceCount(Relation rel)
Definition relcache.c:2176
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition tupdesc.c:242
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,
PublicationDesc pubdesc 
)

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
List * list_concat_unique_oid(List *list1, const List *list2)
Definition list.c:1469
List * list_difference_oid(const List *list1, const List *list2)
Definition list.c:1313
Oid get_rel_namespace(Oid relid)
Definition lsyscache.c:2172
List * get_partition_ancestors(Oid relid)
Definition partition.c:134
#define llast_oid(l)
Definition pg_list.h:200
#define lfirst_oid(lc)
Definition pg_list.h:174
List * GetAllTablesPublications(void)
List * GetRelationIncludedPublications(Oid relid)
List * GetSchemaPublications(Oid schemaid)
List * GetRelationExcludedPublications(Oid relid)
bool is_publishable_relation(Relation rel)
END_CATALOG_STRUCT typedef FormData_pg_publication * Form_pg_publication
bool pub_contains_invalid_column(Oid pubid, Relation relation, List *ancestors, bool pubviaroot, char pubgencols_type, bool *invalid_column_list, bool *invalid_gen_col)
bool pub_rf_contains_invalid_column(Oid pubid, Relation relation, List *ancestors, bool pubviaroot)
Definition pg_list.h:54
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c: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().

◆ RelationBuildRuleLock()

static void RelationBuildRuleLock ( Relation  relation)
static

Definition at line 747 of file relcache.c.

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

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

Referenced by RelationBuildDesc(), and RelationCacheInitializePhase3().

◆ RelationBuildTupleDesc()

static void RelationBuildTupleDesc ( Relation  relation)
static

Definition at line 526 of file relcache.c.

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

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

Referenced by RelationBuildDesc().

◆ RelationCacheInitFilePostInvalidate()

void RelationCacheInitFilePostInvalidate ( void  )

Definition at line 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  )

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}
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1177
@ LW_EXCLUSIVE
Definition lwlock.h:112
static void unlink_initfile(const char *initfilename, int elevel)
Definition relcache.c:6972

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

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

◆ RelationCacheInitFileRemove()

void RelationCacheInitFileRemove ( void  )

Definition at line 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().

◆ RelationCacheInitFileRemoveInDir()

static void RelationCacheInitFileRemoveInDir ( const char tblspcpath)
static

Definition at line 6948 of file relcache.c.

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

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

Referenced by RelationCacheInitFileRemove().

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

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}
#define INITRELCACHESIZE
Definition relcache.c:3990
struct relidcacheent RelIdCacheEnt
void RelationMapInitialize(void)
Definition relmapper.c:652

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

Referenced by InitPostgres().

◆ RelationCacheInitializePhase2()

void RelationCacheInitializePhase2 ( void  )

Definition at line 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}
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  )

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
#define FATAL
Definition elog.h:41
void RelationDecrementReferenceCount(Relation rel)
Definition relcache.c:2189
static const FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute]
Definition relcache.c:113
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
void InitCatalogCachePhase2(void)
Definition syscache.c:180

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

Referenced by InitPostgres().

◆ RelationCacheInvalidate()

void RelationCacheInvalidate ( bool  debug_discard)

Definition at line 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}
List * lappend(List *list, void *datum)
Definition list.c:339
List * lcons(void *datum, List *list)
Definition list.c:495
void list_free(List *list)
Definition list.c:1546
#define RelationIsMapped(relation)
Definition rel.h:563
static void RelationCloseSmgr(Relation relation)
Definition rel.h:591
static void RelationRebuildRelation(Relation relation)
Definition relcache.c: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)

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

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

Referenced by LocalExecuteInvalidationMessage().

◆ RelationClearRelation()

static void RelationClearRelation ( Relation  relation)
static

Definition at line 2535 of file relcache.c.

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

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

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

◆ RelationClose()

void RelationClose ( Relation  relation)

Definition at line 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().

◆ RelationCloseCleanup()

static void RelationCloseCleanup ( Relation  relation)
static

Definition at line 2218 of file relcache.c.

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

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

Referenced by RelationClose(), and ResOwnerReleaseRelation().

◆ RelationDecrementReferenceCount()

void RelationDecrementReferenceCount ( Relation  rel)

Definition at line 2189 of file relcache.c.

2190{
2191 Assert(rel->rd_refcnt > 0);
2192 rel->rd_refcnt -= 1;
2195}
static void ResourceOwnerForgetRelationRef(ResourceOwner owner, Relation rel)
Definition relcache.c:2162
ResourceOwner CurrentResourceOwner
Definition resowner.c:173

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

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

◆ RelationDestroyRelation()

static void RelationDestroyRelation ( Relation  relation,
bool  remember_tupdesc 
)
static

Definition at line 2428 of file relcache.c.

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

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

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

◆ RelationFlushRelation()

static void RelationFlushRelation ( Relation  relation)
static

Definition at line 2816 of file relcache.c.

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

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

Referenced by RelationCacheInvalidateEntry().

◆ RelationForgetRelation()

void RelationForgetRelation ( Oid  rid)

Definition at line 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)

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}
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition heaptuple.c:456
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition makefuncs.c:350
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
int32 exprTypmod(const Node *expr)
Definition nodeFuncs.c:304
Oid exprCollation(const Node *expr)
Definition nodeFuncs.c:826
static TupleDesc GetPgIndexDescriptor(void)
Definition relcache.c:4463

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

Referenced by BuildDummyIndexInfo().

◆ RelationGetExclusionInfo()

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

Definition at line 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 DatumGetArrayTypeP(X)
Definition array.h:261
#define ARR_ELEMTYPE(a)
Definition array.h:292
#define ARR_HASNULL(a)
Definition array.h:291
uint16_t uint16
Definition c.h:617
RegProcedure get_opcode(Oid opno)
Definition lsyscache.c:1505
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition lsyscache.c:87
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition rel.h:533
#define InvalidStrategy
Definition stratnum.h:24

References AccessShareLock, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, BTEqualStrategyNumber, DatumGetArrayTypeP, elog, ERROR, fastgetattr(), fb(), 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)

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}
#define copyObject(obj)
Definition nodes.h:232
#define makeNode(_type_)
Definition nodes.h:161
void DeconstructFkConstraintRow(HeapTuple tuple, int *numfks, AttrNumber *conkey, AttrNumber *confkey, Oid *pf_eq_oprs, Oid *pp_eq_oprs, Oid *ff_eq_oprs, int *num_fk_del_set_cols, AttrNumber *fk_del_set_cols)

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

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

◆ RelationGetIdentityKeyBitmap()

Bitmapset * RelationGetIdentityKeyBitmap ( Relation  relation)

Definition at line 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}
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:799
Bitmapset * bms_copy(const Bitmapset *a)
Definition bitmapset.c:122
#define RelationGetForm(relation)
Definition rel.h: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
#define FirstLowInvalidHeapAttributeNumber
Definition sysattr.h:27

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

Referenced by logicalrep_write_attrs().

◆ RelationGetIndexAttOptions()

bytea ** RelationGetIndexAttOptions ( Relation  relation,
bool  copy 
)

Definition at line 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 bytea ** CopyIndexAttOptions(bytea **srcopts, int natts)
Definition relcache.c:5981

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

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

◆ RelationGetIndexAttrBitmap()

Bitmapset * RelationGetIndexAttrBitmap ( Relation  relation,
IndexAttrBitmapKind  attrKind 
)

Definition at line 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}
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
@ INDEX_ATTR_BITMAP_KEY
Definition relcache.h:69
@ INDEX_ATTR_BITMAP_HOT_BLOCKING
Definition relcache.h:72
@ INDEX_ATTR_BITMAP_PRIMARY_KEY
Definition relcache.h:70
@ INDEX_ATTR_BITMAP_SUMMARIZED
Definition relcache.h:73
@ INDEX_ATTR_BITMAP_IDENTITY_KEY
Definition relcache.h:71
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition var.c:296

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

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

◆ RelationGetIndexExpressions()

List * RelationGetIndexExpressions ( Relation  relation)

Definition at line 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

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

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

◆ RelationGetIndexList()

List * RelationGetIndexList ( Relation  relation)

Definition at line 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
bool rd_ispkdeferrable
Definition rel.h:154
Definition type.h:96

References AccessShareLock, BTEqualStrategyNumber, CacheMemoryContext, fb(), Form_pg_index, GETSTRUCT(), heap_attisnull(), HeapTupleIsValid, InvalidOid, lappend_oid(), list_copy(), list_free(), list_oid_cmp(), list_sort(), MemoryContextSwitchTo(), NIL, ObjectIdGetDatum(), OidIsValid, RelationData::rd_indexlist, RelationData::rd_indexvalid, RelationData::rd_ispkdeferrable, RelationData::rd_pkindex, RelationData::rd_rel, RelationData::rd_replidindex, RelationGetRelid, 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)

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

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

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

◆ RelationGetPrimaryKeyIndex()

Oid RelationGetPrimaryKeyIndex ( Relation  relation,
bool  deferrable_ok 
)

Definition at line 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)

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)

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

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)

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 void AssertCouldGetRelation(void)
Definition relcache.h:44

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

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

◆ RelationIdIsInInitFile()

bool RelationIdIsInInitFile ( Oid  relationId)

Definition at line 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().

◆ RelationIncrementReferenceCount()

◆ RelationInitIndexAccessInfo()

void RelationInitIndexAccessInfo ( Relation  relation)

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}
HeapTuple heap_copytuple(HeapTuple tuple)
Definition heaptuple.c:698
END_CATALOG_STRUCT typedef FormData_pg_am * Form_pg_am
Definition pg_am.h:52
#define IndexRelationGetNumberOfAttributes(relation)
Definition rel.h:526
static void IndexSupportInitialize(oidvector *indclass, RegProcedure *indexSupport, Oid *opFamily, Oid *opcInType, StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber)
Definition relcache.c:1606
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().

◆ RelationInitPhysicalAddr()

static void RelationInitPhysicalAddr ( Relation  relation)
static

Definition at line 1334 of file relcache.c.

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

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

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

◆ RelationInitTableAccessMethod()

void RelationInitTableAccessMethod ( Relation  relation)

Definition at line 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}
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().

◆ RelationInvalidateRelation()

static void RelationInvalidateRelation ( Relation  relation)
static

Definition at line 2507 of file relcache.c.

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

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

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

◆ RelationParseRelOptions()

static void RelationParseRelOptions ( Relation  relation,
HeapTuple  tuple 
)
static

Definition at line 469 of file relcache.c.

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

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

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

◆ RelationRebuildRelation()

static void RelationRebuildRelation ( Relation  relation)
static

Definition at line 2574 of file relcache.c.

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

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

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

◆ RelationReloadIndexInfo()

static void RelationReloadIndexInfo ( Relation  relation)
static

Definition at line 2265 of file relcache.c.

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

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

Referenced by RelationRebuildRelation().

◆ RelationReloadNailed()

static void RelationReloadNailed ( Relation  relation)
static

Definition at line 2374 of file relcache.c.

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

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

Referenced by RelationRebuildRelation().

◆ RelationSetNewRelfilenumber()

void RelationSetNewRelfilenumber ( Relation  relation,
char  persistence 
)

Definition at line 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
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
SMgrRelation smgropen(RelFileLocator rlocator, ProcNumber backend)
Definition smgr.c:240
void smgrclose(SMgrRelation reln)
Definition smgr.c:374
void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
Definition smgr.c:538
SMgrRelation RelationCreateStorage(RelFileLocator rlocator, char relpersistence, bool register_delete)
Definition storage.c:122
void RelationDropStorage(Relation rel)
Definition storage.c:207
ItemPointerData t_self
Definition htup.h:65
HeapTuple SearchSysCacheLockedCopy1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:399
static void table_relation_set_new_filelocator(Relation rel, const RelFileLocator *newrlocator, char persistence, TransactionId *freezeXid, MultiXactId *minmulti)
Definition tableam.h:1611
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().

◆ RememberToFreeTupleDescAtEOX()

◆ ResourceOwnerForgetRelationRef()

static void ResourceOwnerForgetRelationRef ( ResourceOwner  owner,
Relation  rel 
)
inlinestatic

Definition at line 2162 of file relcache.c.

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

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

Referenced by RelationDecrementReferenceCount().

◆ ResourceOwnerRememberRelationRef()

static void ResourceOwnerRememberRelationRef ( ResourceOwner  owner,
Relation  rel 
)
inlinestatic

Definition at line 2157 of file relcache.c.

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

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

Referenced by RelationIncrementReferenceCount().

◆ ResOwnerPrintRelCache()

static char * ResOwnerPrintRelCache ( Datum  res)
static

Definition at line 6989 of file relcache.c.

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

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

◆ ResOwnerReleaseRelation()

static void ResOwnerReleaseRelation ( Datum  res)
static

Definition at line 6997 of file relcache.c.

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

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

◆ ScanPgRelation()

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

Definition at line 341 of file relcache.c.

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

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

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

◆ unlink_initfile()

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

Definition at line 6972 of file relcache.c.

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

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

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

◆ write_item()

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

Definition at line 6812 of file relcache.c.

6813{
6814 if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len))
6815 ereport(FATAL,
6817 errmsg_internal("could not write init file: %m"));
6818 if (len > 0 && fwrite(data, 1, len, fp) != len)
6819 ereport(FATAL,
6821 errmsg_internal("could not write init file: %m"));
6822}
const void * data

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

Referenced by write_relcache_init_file().

◆ write_relcache_init_file()

static void write_relcache_init_file ( bool  shared)
static

Definition at line 6600 of file relcache.c.

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

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

Referenced by RelationCacheInitializePhase3().

Variable Documentation

◆ criticalRelcachesBuilt

◆ criticalSharedRelcachesBuilt

◆ Desc_pg_attribute

Definition at line 113 of file relcache.c.

Referenced by RelationCacheInitializePhase3().

◆ Desc_pg_auth_members

Definition at line 118 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_authid

Definition at line 117 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_class

◆ Desc_pg_database

Definition at line 116 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_index

Definition at line 119 of file relcache.c.

Referenced by GetPgIndexDescriptor().

◆ Desc_pg_proc

Definition at line 114 of file relcache.c.

Referenced by RelationCacheInitializePhase3().

◆ Desc_pg_shseclabel

Definition at line 120 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_subscription

Definition at line 121 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_type

Definition at line 115 of file relcache.c.

Referenced by RelationCacheInitializePhase3().

◆ eoxact_list

Oid eoxact_list[MAX_EOXACT_LIST]
static

Definition at line 186 of file relcache.c.

Referenced by AtEOSubXact_RelationCache(), and AtEOXact_RelationCache().

◆ eoxact_list_len

int eoxact_list_len = 0
static

Definition at line 187 of file relcache.c.

Referenced by AtEOSubXact_RelationCache(), and AtEOXact_RelationCache().

◆ eoxact_list_overflowed

bool eoxact_list_overflowed = false
static

Definition at line 188 of file relcache.c.

Referenced by AtEOSubXact_RelationCache(), and AtEOXact_RelationCache().

◆ EOXactTupleDescArray

TupleDesc* EOXactTupleDescArray
static

Definition at line 203 of file relcache.c.

Referenced by AtEOXact_RelationCache(), and RememberToFreeTupleDescAtEOX().

◆ EOXactTupleDescArrayLen

int EOXactTupleDescArrayLen = 0
static

Definition at line 205 of file relcache.c.

Referenced by AtEOXact_RelationCache(), and RememberToFreeTupleDescAtEOX().

◆ in_progress_list

◆ in_progress_list_len

◆ in_progress_list_maxlen

int in_progress_list_maxlen
static

Definition at line 173 of file relcache.c.

Referenced by RelationBuildDesc(), and RelationCacheInitialize().

◆ NextEOXactTupleDescNum

int NextEOXactTupleDescNum = 0
static

Definition at line 204 of file relcache.c.

Referenced by AtEOXact_RelationCache(), and RememberToFreeTupleDescAtEOX().

◆ OpClassCache

HTAB* OpClassCache = NULL
static

Definition at line 272 of file relcache.c.

Referenced by LookupOpclassInfo().

◆ RelationIdCache

◆ relcacheInvalsReceived

long relcacheInvalsReceived = 0L
static

◆ relref_resowner_desc

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

Definition at line 2146 of file relcache.c.

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

Referenced by ResourceOwnerForgetRelationRef(), and ResourceOwnerRememberRelationRef().