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_parameter_acl.h"
#include "catalog/pg_shseclabel.h"
#include "catalog/pg_statistic_ext.h"
#include "catalog/pg_subscription.h"
#include "catalog/pg_tablespace.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
#include "catalog/schemapg.h"
#include "catalog/storage.h"
#include "commands/policy.h"
#include "commands/publicationcmds.h"
#include "commands/trigger.h"
#include "common/int.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/optimizer.h"
#include "pgstat.h"
#include "rewrite/rewriteDefine.h"
#include "rewrite/rowsecurity.h"
#include "storage/fd.h"
#include "storage/lmgr.h"
#include "storage/lock.h"
#include "storage/smgr.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/datum.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/relmapper.h"
#include "utils/resowner.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
Include dependency graph for relcache.c:

Go to the source code of this file.

Data Structures

struct  relidcacheent
 
struct  inprogressent
 
struct  opclasscacheent
 

Macros

#define RELCACHE_INIT_FILEMAGIC   0x573266 /* version ID value */
 
#define RECOVER_RELATION_BUILD_MEMORY   0
 
#define MAX_EOXACT_LIST   32
 
#define EOXactListAdd(rel)
 
#define RelationCacheInsert(RELATION, replace_allowed)
 
#define RelationIdCacheLookup(ID, RELATION)
 
#define RelationCacheDelete(RELATION)
 
#define SWAPFIELD(fldtype, fldname)
 
#define INITRELCACHESIZE   400
 
#define NUM_CRITICAL_SHARED_RELS   6 /* 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   8 /* 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)
 
charRelationGetQualifiedRelationName (Relation rel)
 
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 const FormData_pg_attribute Desc_pg_parameter_acl [Natts_pg_parameter_acl] = {Schema_pg_parameter_acl}
 
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:189
#define MAX_EOXACT_LIST
Definition relcache.c:188
static int eoxact_list_len
Definition relcache.c:190

Definition at line 193 of file relcache.c.

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

◆ INITRELCACHESIZE

#define INITRELCACHESIZE   400

Definition at line 4003 of file relcache.c.

◆ MAX_EOXACT_LIST

#define MAX_EOXACT_LIST   32

Definition at line 188 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   8 /* fix if you change list above */

◆ NUM_CRITICAL_SHARED_RELS

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

◆ RECOVER_RELATION_BUILD_MEMORY

#define RECOVER_RELATION_BUILD_MEMORY   0

Definition at line 105 of file relcache.c.

◆ RelationCacheDelete

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

Definition at line 247 of file relcache.c.

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

◆ RelationCacheInsert

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

Definition at line 213 of file relcache.c.

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

◆ RelationIdCacheLookup

#define RelationIdCacheLookup (   ID,
  RELATION 
)
Value:

Definition at line 235 of file relcache.c.

236 { \
239 &(ID), \
240 HASH_FIND, NULL); \
241 if (hentry) \
243 else \
244 RELATION = NULL; \
245} while(0)

◆ RELCACHE_INIT_FILEMAGIC

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

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

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

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

Referenced by RelationBuildDesc().

◆ AtEOSubXact_cleanup()

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

Definition at line 3435 of file relcache.c.

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

3382{
3383 HASH_SEQ_STATUS status;
3385 int i;
3386
3387 /*
3388 * Forget in_progress_list. This is relevant when we're aborting due to
3389 * an error during RelationBuildDesc(). We don't commit subtransactions
3390 * during RelationBuildDesc().
3391 */
3394
3395 /*
3396 * Unless the eoxact_list[] overflowed, we only need to examine the rels
3397 * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3398 * logic as in AtEOXact_RelationCache.
3399 */
3401 {
3403 while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3404 {
3407 }
3408 }
3409 else
3410 {
3411 for (i = 0; i < eoxact_list_len; i++)
3412 {
3414 &eoxact_list[i],
3415 HASH_FIND,
3416 NULL);
3417 if (idhentry != NULL)
3420 }
3421 }
3422
3423 /* Don't reset the list; we still need more cleanup later */
3424}
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition dynahash.c:1352
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition dynahash.c:1317
int i
Definition isn.c:77
static int in_progress_list_len
Definition relcache.c:175
static void AtEOSubXact_cleanup(Relation relation, bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid)
Definition relcache.c:3435
static bool eoxact_list_overflowed
Definition relcache.c:191

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

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

3229{
3230 HASH_SEQ_STATUS status;
3232 int i;
3233
3234 /*
3235 * Forget in_progress_list. This is relevant when we're aborting due to
3236 * an error during RelationBuildDesc().
3237 */
3240
3241 /*
3242 * Unless the eoxact_list[] overflowed, we only need to examine the rels
3243 * listed in it. Otherwise fall back on a hash_seq_search scan.
3244 *
3245 * For simplicity, eoxact_list[] entries are not deleted till end of
3246 * top-level transaction, even though we could remove them at
3247 * subtransaction end in some cases, or remove relations from the list if
3248 * they are cleared for other reasons. Therefore we should expect the
3249 * case that list entries are not found in the hashtable; if not, there's
3250 * nothing to do for them.
3251 */
3253 {
3255 while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3256 {
3258 }
3259 }
3260 else
3261 {
3262 for (i = 0; i < eoxact_list_len; i++)
3263 {
3265 &eoxact_list[i],
3266 HASH_FIND,
3267 NULL);
3268 if (idhentry != NULL)
3270 }
3271 }
3272
3274 {
3276 for (i = 0; i < NextEOXactTupleDescNum; i++)
3280 }
3281
3282 /* Now we're out of the transaction and can clear the lists */
3283 eoxact_list_len = 0;
3284 eoxact_list_overflowed = false;
3287}
void pfree(void *pointer)
Definition mcxt.c:1619
static int NextEOXactTupleDescNum
Definition relcache.c:207
static int EOXactTupleDescArrayLen
Definition relcache.c:208
static void AtEOXact_cleanup(Relation relation, bool isCommit)
Definition relcache.c:3298
static TupleDesc * EOXactTupleDescArray
Definition relcache.c:206
void FreeTupleDesc(TupleDesc tupdesc)
Definition tupdesc.c:569

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

4586{
4587 const AttrDefault *ada = (const AttrDefault *) a;
4588 const AttrDefault *adb = (const AttrDefault *) b;
4589
4590 return pg_cmp_s16(ada->adnum, adb->adnum);
4591}
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 4505 of file relcache.c.

4506{
4511 HeapTuple htup;
4512 int found = 0;
4513
4514 /* Allocate array with room for as many entries as expected */
4515 attrdef = (AttrDefault *)
4517 ndef * sizeof(AttrDefault));
4518
4519 /* Search pg_attrdef for relevant entries */
4524
4527 NULL, 1, &skey);
4528
4530 {
4532 Datum val;
4533 bool isnull;
4534
4535 /* protect limited size of array */
4536 if (found >= ndef)
4537 {
4538 elog(WARNING, "unexpected pg_attrdef record found for attribute %d of relation \"%s\"",
4539 adform->adnum, RelationGetRelationName(relation));
4540 break;
4541 }
4542
4543 val = fastgetattr(htup,
4545 adrel->rd_att, &isnull);
4546 if (isnull)
4547 elog(WARNING, "null adbin for attribute %d of relation \"%s\"",
4548 adform->adnum, RelationGetRelationName(relation));
4549 else
4550 {
4551 /* detoast and convert to cstring in caller's context */
4552 char *s = TextDatumGetCString(val);
4553
4554 attrdef[found].adnum = adform->adnum;
4556 pfree(s);
4557 found++;
4558 }
4559 }
4560
4563
4564 if (found != ndef)
4565 elog(WARNING, "%d pg_attrdef record(s) missing for relation \"%s\"",
4566 ndef - found, RelationGetRelationName(relation));
4567
4568 /*
4569 * Sort the AttrDefault entries by adnum, for the convenience of
4570 * equalTupleDescs(). (Usually, they already will be in order, but this
4571 * might not be so if systable_getnext isn't using an index.)
4572 */
4573 if (found > 1)
4574 qsort(attrdef, found, sizeof(AttrDefault), AttrDefaultCmp);
4575
4576 /* Install array only after it's fully valid */
4577 relation->rd_att->constr->defval = attrdef;
4578 relation->rd_att->constr->num_defval = found;
4579}
#define TextDatumGetCString(d)
Definition builtins.h:99
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:604
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:515
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:1897
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition mcxt.c:1269
END_CATALOG_STRUCT typedef FormData_pg_attrdef * Form_pg_attrdef
Definition pg_attrdef.h:53
#define qsort(a, b, c, d)
Definition port.h:496
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
uint64_t Datum
Definition postgres.h:70
#define RelationGetRelid(relation)
Definition rel.h:516
static int AttrDefaultCmp(const void *a, const void *b)
Definition relcache.c:4585
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 4441 of file relcache.c.

4442{
4445 int i;
4446
4448
4450 result->tdtypeid = RECORDOID; /* not right, but we don't care */
4451 result->tdtypmod = -1;
4452
4453 for (i = 0; i < natts; i++)
4454 {
4456
4458 }
4459
4461
4462 /* Note: we don't bother to set up a TupleConstr entry */
4463
4465
4466 return result;
4467}
uint32 result
#define ATTRIBUTE_FIXED_PART_SIZE
void TupleDescFinalize(TupleDesc tupdesc)
Definition tupdesc.c:511
void populate_compact_attribute(TupleDesc tupdesc, int attnum)
Definition tupdesc.c:100
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178

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

Referenced by GetPgClassDescriptor(), and GetPgIndexDescriptor().

◆ CheckConstraintCmp()

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

Definition at line 4718 of file relcache.c.

4719{
4720 const ConstrCheck *ca = (const ConstrCheck *) a;
4721 const ConstrCheck *cb = (const ConstrCheck *) b;
4722
4723 return strcmp(ca->ccname, cb->ccname);
4724}
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 4601 of file relcache.c.

4602{
4603 ConstrCheck *check;
4604 int ncheck = relation->rd_rel->relchecks;
4607 ScanKeyData skey[1];
4608 HeapTuple htup;
4609 int found = 0;
4610
4611 /* Allocate array with room for as many entries as expected, if needed */
4612 if (ncheck > 0)
4613 check = (ConstrCheck *)
4615 ncheck * sizeof(ConstrCheck));
4616 else
4617 check = NULL;
4618
4619 /* Search pg_constraint for relevant entries */
4620 ScanKeyInit(&skey[0],
4624
4627 NULL, 1, skey);
4628
4630 {
4632 Datum val;
4633 bool isnull;
4634
4635 /*
4636 * If this is a not-null constraint, then only look at it if it's
4637 * invalid, and if so, mark the TupleDesc entry as known invalid.
4638 * Otherwise move on. We'll mark any remaining columns that are still
4639 * in UNKNOWN state as known valid later. This allows us not to have
4640 * to extract the attnum from this constraint tuple in the vast
4641 * majority of cases.
4642 */
4643 if (conform->contype == CONSTRAINT_NOTNULL)
4644 {
4645 if (!conform->convalidated)
4646 {
4648
4652 relation->rd_att->compact_attrs[attnum - 1].attnullability =
4654 }
4655
4656 continue;
4657 }
4658
4659 /* For what follows, consider check constraints only */
4660 if (conform->contype != CONSTRAINT_CHECK)
4661 continue;
4662
4663 /* protect limited size of array */
4664 if (found >= ncheck)
4665 {
4666 elog(WARNING, "unexpected pg_constraint record found for relation \"%s\"",
4667 RelationGetRelationName(relation));
4668 break;
4669 }
4670
4671 /* Grab and test conbin is actually set */
4672 val = fastgetattr(htup,
4674 conrel->rd_att, &isnull);
4675 if (isnull)
4676 elog(WARNING, "null conbin for relation \"%s\"",
4677 RelationGetRelationName(relation));
4678 else
4679 {
4680 /* detoast and convert to cstring in caller's context */
4681 char *s = TextDatumGetCString(val);
4682
4683 check[found].ccenforced = conform->conenforced;
4684 check[found].ccvalid = conform->convalidated;
4685 check[found].ccnoinherit = conform->connoinherit;
4687 NameStr(conform->conname));
4688 check[found].ccbin = MemoryContextStrdup(CacheMemoryContext, s);
4689
4690 pfree(s);
4691 found++;
4692 }
4693 }
4694
4697
4698 if (found != ncheck)
4699 elog(WARNING, "%d pg_constraint record(s) missing for relation \"%s\"",
4700 ncheck - found, RelationGetRelationName(relation));
4701
4702 /*
4703 * Sort the records by name. This ensures that CHECKs are applied in a
4704 * deterministic order, and it also makes equalTupleDescs() faster.
4705 */
4706 if (found > 1)
4707 qsort(check, found, sizeof(ConstrCheck), CheckConstraintCmp);
4708
4709 /* Install array only after it's fully valid */
4710 relation->rd_att->constr->check = check;
4711 relation->rd_att->constr->num_check = found;
4712}
int16 AttrNumber
Definition attnum.h:21
#define NameStr(name)
Definition c.h:835
int16 attnum
AttrNumber extractNotNullColumn(HeapTuple constrTup)
END_CATALOG_STRUCT typedef FormData_pg_constraint * Form_pg_constraint
static int CheckConstraintCmp(const void *a, const void *b)
Definition relcache.c:4718
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 6001 of file relcache.c.

6002{
6003 bytea **opts = palloc_array(bytea *, natts);
6004
6005 for (int i = 0; i < natts; i++)
6006 {
6007 bytea *opt = srcopts[i];
6008
6009 opts[i] = !opt ? NULL : (bytea *)
6010 DatumGetPointer(datumCopy(PointerGetDatum(opt), false, -1));
6011 }
6012
6013 return opts;
6014}
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition datum.c:132
#define palloc_array(type, count)
Definition fe_memutils.h:91
static AmcheckOptions opts
Definition pg_amcheck.c:112
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
#define PointerGetDatum(X)
Definition postgres.h:354
Definition c.h:776

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

Referenced by RelationGetIndexAttOptions().

◆ equalPolicy()

static bool equalPolicy ( RowSecurityPolicy policy1,
RowSecurityPolicy policy2 
)
static

Definition at line 970 of file relcache.c.

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

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

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

Referenced by RelationRebuildRelation().

◆ equalRuleLocks()

static bool equalRuleLocks ( RuleLock rlock1,
RuleLock rlock2 
)
static

Definition at line 925 of file relcache.c.

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

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

Referenced by RelationRebuildRelation().

◆ errtable()

int errtable ( Relation  rel)

Definition at line 6082 of file relcache.c.

6083{
6087
6088 return 0; /* return value does not matter */
6089}
int err_generic_string(int field, const char *str)
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3674
#define PG_DIAG_SCHEMA_NAME
#define PG_DIAG_TABLE_NAME
#define RelationGetNamespace(relation)
Definition rel.h:557

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

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

◆ errtablecol()

int errtablecol ( Relation  rel,
int  attnum 
)

Definition at line 6099 of file relcache.c.

6100{
6101 TupleDesc reldesc = RelationGetDescr(rel);
6102 const char *colname;
6103
6104 /* Use reldesc if it's a user attribute, else consult the catalogs */
6105 if (attnum > 0 && attnum <= reldesc->natts)
6106 colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname);
6107 else
6108 colname = get_attname(RelationGetRelid(rel), attnum, false);
6109
6110 return errtablecolname(rel, colname);
6111}
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:1045
NameData attname
#define RelationGetDescr(relation)
Definition rel.h:542
int errtablecolname(Relation rel, const char *colname)
Definition relcache.c:6123

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

6124{
6125 errtable(rel);
6127
6128 return 0; /* return value does not matter */
6129}
#define PG_DIAG_COLUMN_NAME
int errtable(Relation rel)
Definition relcache.c:6082

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

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

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

Referenced by RelationCacheInitializePhase2(), and RelationCacheInitializePhase3().

◆ GetPgClassDescriptor()

static TupleDesc GetPgClassDescriptor ( void  )
static

Definition at line 4470 of file relcache.c.

4471{
4472 static TupleDesc pgclassdesc = NULL;
4473
4474 /* Already done? */
4475 if (pgclassdesc == NULL)
4478
4479 return pgclassdesc;
4480}
static TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs)
Definition relcache.c:4441
static const FormData_pg_attribute Desc_pg_class[Natts_pg_class]
Definition relcache.c:114

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

Referenced by RelationParseRelOptions().

◆ GetPgIndexDescriptor()

static TupleDesc GetPgIndexDescriptor ( void  )
static

Definition at line 4483 of file relcache.c.

4484{
4485 static TupleDesc pgindexdesc = NULL;
4486
4487 /* Already done? */
4488 if (pgindexdesc == NULL)
4491
4492 return pgindexdesc;
4493}
static const FormData_pg_attribute Desc_pg_index[Natts_pg_index]
Definition relcache.c:121

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

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

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

Referenced by RelationInitIndexAccessInfo().

◆ InitIndexAmRoutine()

static void InitIndexAmRoutine ( Relation  relation)
static

Definition at line 1419 of file relcache.c.

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

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

4404{
4405 Relation ird;
4406
4407 /*
4408 * We must lock the underlying catalog before locking the index to avoid
4409 * deadlock, since RelationBuildDesc might well need to read the catalog,
4410 * and if anyone else is exclusive-locking this catalog and index they'll
4411 * be doing it in that order.
4412 */
4415 ird = RelationBuildDesc(indexoid, true);
4416 if (ird == NULL)
4417 ereport(PANIC,
4419 errmsg_internal("could not open critical system index %u", indexoid));
4420 ird->rd_isnailed = true;
4421 ird->rd_refcnt = 1;
4424
4426}
int errcode(int sqlerrcode)
Definition elog.c:875
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#define PANIC
Definition elog.h:44
#define ereport(elevel,...)
Definition elog.h:152
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition lmgr.c:229
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition lmgr.c:107
#define ERRCODE_DATA_CORRUPTED
static Relation RelationBuildDesc(Oid targetRelId, bool insertIt)
Definition relcache.c:1057
bytea ** RelationGetIndexAttOptions(Relation relation, bool copy)
Definition relcache.c:6021

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

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

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

3981{
3985
3986 /* Flag relation as needing eoxact cleanup (to clear these fields) */
3987 EOXactListAdd(relation);
3988}
#define EOXactListAdd(rel)
Definition relcache.c:193
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 1057 of file relcache.c.

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

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

References Assert, CacheMemoryContext, CLASS_TUPLE_SIZE, TupleDescData::constr, CreateCacheMemoryContext(), CreateTupleDescCopy(), elog, EOXactListAdd, ERROR, fb(), GetCurrentSubTransactionId(), TupleConstr::has_not_null, i, INVALID_PROC_NUMBER, InvalidOid, InvalidRelFileNumber, InvalidSubTransactionId, IsCatalogNamespace(), IsSharedRelation(), isTempOrTempToastNamespace(), MemoryContextSwitchTo(), namestrcpy(), TupleDescData::natts, palloc0(), palloc0_object, populate_compact_attribute(), ProcNumberForTempRelations, RelationData::rd_att, RelationData::rd_backend, RelationData::rd_createSubid, RelationData::rd_droppedSubid, RelationData::rd_firstRelfilelocatorSubid, RelationData::rd_islocaltemp, RelationData::rd_isnailed, RelationData::rd_isvalid, RelationData::rd_newRelfilelocatorSubid, RelationData::rd_refcnt, RelationData::rd_rel, RelationData::rd_smgr, RelationCacheInsert, RelationGetRelid, RelationIncrementReferenceCount(), RelationInitLockInfo(), RelationInitPhysicalAddr(), RelationInitTableAccessMethod(), RelationMapUpdateMap(), relname, TupleDescData::tdrefcount, TupleDescAttr(), TupleDescCompactAttr(), and TupleDescFinalize().

Referenced by heap_create().

◆ RelationBuildPublicationDesc()

void RelationBuildPublicationDesc ( Relation  relation,
PublicationDesc pubdesc 
)

Definition at line 5804 of file relcache.c.

5805{
5806 List *puboids = NIL;
5809 ListCell *lc;
5811 Oid schemaid;
5812 List *ancestors = NIL;
5813 Oid relid = RelationGetRelid(relation);
5814
5815 /*
5816 * If not publishable, it publishes no actions. (pgoutput_change() will
5817 * ignore it.)
5818 */
5819 if (!is_publishable_relation(relation))
5820 {
5821 memset(pubdesc, 0, sizeof(PublicationDesc));
5822 pubdesc->rf_valid_for_update = true;
5823 pubdesc->rf_valid_for_delete = true;
5824 pubdesc->cols_valid_for_update = true;
5825 pubdesc->cols_valid_for_delete = true;
5826 pubdesc->gencols_valid_for_update = true;
5827 pubdesc->gencols_valid_for_delete = true;
5828 return;
5829 }
5830
5831 if (relation->rd_pubdesc)
5832 {
5833 memcpy(pubdesc, relation->rd_pubdesc, sizeof(PublicationDesc));
5834 return;
5835 }
5836
5837 memset(pubdesc, 0, sizeof(PublicationDesc));
5838 pubdesc->rf_valid_for_update = true;
5839 pubdesc->rf_valid_for_delete = true;
5840 pubdesc->cols_valid_for_update = true;
5841 pubdesc->cols_valid_for_delete = true;
5842 pubdesc->gencols_valid_for_update = true;
5843 pubdesc->gencols_valid_for_delete = true;
5844
5845 /* Fetch the publication membership info. */
5847 schemaid = RelationGetNamespace(relation);
5849
5850 if (relation->rd_rel->relispartition)
5851 {
5853
5854 /* Add publications that the ancestors are in too. */
5855 ancestors = get_partition_ancestors(relid);
5856 last_ancestor_relid = llast_oid(ancestors);
5857
5858 foreach(lc, ancestors)
5859 {
5861
5867 }
5868
5869 /*
5870 * Only the top-most ancestor can appear in the EXCEPT clause.
5871 * Therefore, for a partition, exclusion must be evaluated at the
5872 * top-most ancestor.
5873 */
5875 }
5876 else
5877 {
5878 /*
5879 * For a regular table or a root partitioned table, check exclusion on
5880 * table itself.
5881 */
5883 }
5884
5888 exceptpuboids));
5889 foreach(lc, puboids)
5890 {
5891 Oid pubid = lfirst_oid(lc);
5892 HeapTuple tup;
5895 bool invalid_gen_col;
5896
5898
5899 if (!HeapTupleIsValid(tup))
5900 elog(ERROR, "cache lookup failed for publication %u", pubid);
5901
5903
5904 pubdesc->pubactions.pubinsert |= pubform->pubinsert;
5905 pubdesc->pubactions.pubupdate |= pubform->pubupdate;
5906 pubdesc->pubactions.pubdelete |= pubform->pubdelete;
5907 pubdesc->pubactions.pubtruncate |= pubform->pubtruncate;
5908
5909 /*
5910 * Check if all columns referenced in the filter expression are part
5911 * of the REPLICA IDENTITY index or not.
5912 *
5913 * If the publication is FOR ALL TABLES then it means the table has no
5914 * row filters and we can skip the validation.
5915 */
5916 if (!pubform->puballtables &&
5917 (pubform->pubupdate || pubform->pubdelete) &&
5918 pub_rf_contains_invalid_column(pubid, relation, ancestors,
5919 pubform->pubviaroot))
5920 {
5921 if (pubform->pubupdate)
5922 pubdesc->rf_valid_for_update = false;
5923 if (pubform->pubdelete)
5924 pubdesc->rf_valid_for_delete = false;
5925 }
5926
5927 /*
5928 * Check if all columns are part of the REPLICA IDENTITY index or not.
5929 *
5930 * Check if all generated columns included in the REPLICA IDENTITY are
5931 * published.
5932 */
5933 if ((pubform->pubupdate || pubform->pubdelete) &&
5934 pub_contains_invalid_column(pubid, relation, ancestors,
5935 pubform->pubviaroot,
5936 pubform->pubgencols,
5939 {
5940 if (pubform->pubupdate)
5941 {
5942 pubdesc->cols_valid_for_update = !invalid_column_list;
5943 pubdesc->gencols_valid_for_update = !invalid_gen_col;
5944 }
5945
5946 if (pubform->pubdelete)
5947 {
5948 pubdesc->cols_valid_for_delete = !invalid_column_list;
5949 pubdesc->gencols_valid_for_delete = !invalid_gen_col;
5950 }
5951 }
5952
5954
5955 /*
5956 * If we know everything is replicated and the row filter is invalid
5957 * for update and delete, 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->rf_valid_for_update && !pubdesc->rf_valid_for_delete)
5963 break;
5964
5965 /*
5966 * If we know everything is replicated and the column list is invalid
5967 * for update and delete, there is no point to check for other
5968 * publications.
5969 */
5970 if (pubdesc->pubactions.pubinsert && pubdesc->pubactions.pubupdate &&
5971 pubdesc->pubactions.pubdelete && pubdesc->pubactions.pubtruncate &&
5972 !pubdesc->cols_valid_for_update && !pubdesc->cols_valid_for_delete)
5973 break;
5974
5975 /*
5976 * If we know everything is replicated and replica identity has an
5977 * unpublished generated column, there is no point to check for other
5978 * publications.
5979 */
5980 if (pubdesc->pubactions.pubinsert && pubdesc->pubactions.pubupdate &&
5981 pubdesc->pubactions.pubdelete && pubdesc->pubactions.pubtruncate &&
5982 !pubdesc->gencols_valid_for_update &&
5983 !pubdesc->gencols_valid_for_delete)
5984 break;
5985 }
5986
5987 if (relation->rd_pubdesc)
5988 {
5989 pfree(relation->rd_pubdesc);
5990 relation->rd_pubdesc = NULL;
5991 }
5992
5993 /* Now save copy of the descriptor in the relcache entry. */
5996 memcpy(relation->rd_pubdesc, pubdesc, sizeof(PublicationDesc));
5998}
#define palloc_object(type)
Definition fe_memutils.h:89
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:2258
List * get_partition_ancestors(Oid relid)
Definition partition.c:134
#define llast_oid(l)
Definition pg_list.h:200
#define lfirst_oid(lc)
Definition pg_list.h:174
List * GetAllTablesPublications(void)
List * GetRelationIncludedPublications(Oid relid)
List * GetSchemaPublications(Oid schemaid)
List * GetRelationExcludedPublications(Oid relid)
bool is_publishable_relation(Relation rel)
END_CATALOG_STRUCT typedef FormData_pg_publication * Form_pg_publication
bool pub_contains_invalid_column(Oid pubid, Relation relation, List *ancestors, bool pubviaroot, char pubgencols_type, bool *invalid_column_list, bool *invalid_gen_col)
bool pub_rf_contains_invalid_column(Oid pubid, Relation relation, List *ancestors, bool pubviaroot)
Definition pg_list.h:54
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221

References CacheMemoryContext, elog, ERROR, fb(), Form_pg_publication, get_partition_ancestors(), get_rel_namespace(), GetAllTablesPublications(), GetRelationExcludedPublications(), GetRelationIncludedPublications(), GetSchemaPublications(), GETSTRUCT(), HeapTupleIsValid, is_publishable_relation(), lfirst_oid, list_concat_unique_oid(), list_difference_oid(), llast_oid, memcpy(), MemoryContextSwitchTo(), NIL, ObjectIdGetDatum(), palloc_object, pfree(), pub_contains_invalid_column(), pub_rf_contains_invalid_column(), RelationData::rd_pubdesc, RelationData::rd_rel, RelationGetNamespace, RelationGetRelid, ReleaseSysCache(), and SearchSysCache1().

Referenced by CheckCmdReplicaIdentity().

◆ RelationBuildRuleLock()

static void RelationBuildRuleLock ( Relation  relation)
static

Definition at line 750 of file relcache.c.

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

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

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

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

Referenced by RelationBuildDesc().

◆ RelationCacheInitFilePostInvalidate()

void RelationCacheInitFilePostInvalidate ( void  )

Definition at line 6920 of file relcache.c.

6921{
6923}
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1767

References fb(), and LWLockRelease().

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

◆ RelationCacheInitFilePreInvalidate()

void RelationCacheInitFilePreInvalidate ( void  )

Definition at line 6895 of file relcache.c.

6896{
6899
6900 if (DatabasePath)
6901 snprintf(localinitfname, sizeof(localinitfname), "%s/%s",
6903 snprintf(sharedinitfname, sizeof(sharedinitfname), "global/%s",
6905
6907
6908 /*
6909 * The files might not be there if no backend has been started since the
6910 * last removal. But complain about failures other than ENOENT with
6911 * ERROR. Fortunately, it's not too late to abort the transaction if we
6912 * can't get rid of the would-be-obsolete init file.
6913 */
6914 if (DatabasePath)
6917}
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1150
@ LW_EXCLUSIVE
Definition lwlock.h:104
static void unlink_initfile(const char *initfilename, int elevel)
Definition relcache.c:6992

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

6936{
6937 const char *tblspcdir = PG_TBLSPC_DIR;
6938 DIR *dir;
6939 struct dirent *de;
6940 char path[MAXPGPATH + sizeof(PG_TBLSPC_DIR) + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6941
6942 snprintf(path, sizeof(path), "global/%s",
6944 unlink_initfile(path, LOG);
6945
6946 /* Scan everything in the default tablespace */
6948
6949 /* Scan the tablespace link directory to find non-default tablespaces */
6950 dir = AllocateDir(tblspcdir);
6951
6952 while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6953 {
6954 if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6955 {
6956 /* Scan the tablespace dir for per-database dirs */
6957 snprintf(path, sizeof(path), "%s/%s/%s",
6960 }
6961 }
6962
6963 FreeDir(dir);
6964}
#define LOG
Definition elog.h:32
int FreeDir(DIR *dir)
Definition fd.c:3009
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition fd.c:2972
DIR * AllocateDir(const char *dirname)
Definition fd.c:2891
static void RelationCacheInitFileRemoveInDir(const char *tblspcpath)
Definition relcache.c:6968
#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 6968 of file relcache.c.

6969{
6970 DIR *dir;
6971 struct dirent *de;
6972 char initfilename[MAXPGPATH * 2];
6973
6974 /* Scan the tablespace directory to find per-database directories */
6975 dir = AllocateDir(tblspcpath);
6976
6977 while ((de = ReadDirExtended(dir, tblspcpath, LOG)) != NULL)
6978 {
6979 if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6980 {
6981 /* Try to remove the init file in each database */
6982 snprintf(initfilename, sizeof(initfilename), "%s/%s/%s",
6985 }
6986 }
6987
6988 FreeDir(dir);
6989}

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

Referenced by RelationCacheInitFileRemove().

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 4006 of file relcache.c.

4007{
4008 HASHCTL ctl;
4009 int allocsize;
4010
4011 /*
4012 * make sure cache memory context exists
4013 */
4014 if (!CacheMemoryContext)
4016
4017 /*
4018 * create hashtable that indexes the relcache
4019 */
4020 ctl.keysize = sizeof(Oid);
4021 ctl.entrysize = sizeof(RelIdCacheEnt);
4022 RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
4024
4025 /*
4026 * reserve enough in_progress_list slots for many cases
4027 */
4028 allocsize = 4;
4031 allocsize * sizeof(*in_progress_list));
4032 in_progress_list_maxlen = allocsize;
4033
4034 /*
4035 * relation mapper needs to be initialized too
4036 */
4038}
#define INITRELCACHESIZE
Definition relcache.c:4003
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 4052 of file relcache.c.

4053{
4055
4056 /*
4057 * relation mapper needs initialized too
4058 */
4060
4061 /*
4062 * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
4063 * nothing.
4064 */
4066 return;
4067
4068 /*
4069 * switch to cache memory context
4070 */
4072
4073 /*
4074 * Try to load the shared relcache cache file. If unsuccessful, bootstrap
4075 * the cache with pre-made descriptors for the critical shared catalogs.
4076 */
4077 if (!load_relcache_init_file(true))
4078 {
4079 formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
4081 formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
4083 formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
4085 formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
4087 formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
4089 formrdesc("pg_parameter_acl", ParameterAclRelation_Rowtype_Id, true,
4091
4092#define NUM_CRITICAL_SHARED_RELS 6 /* fix if you change list above */
4093 }
4094
4096}
static bool load_relcache_init_file(bool shared)
Definition relcache.c:6200
static const FormData_pg_attribute Desc_pg_shseclabel[Natts_pg_shseclabel]
Definition relcache.c:122
static void formrdesc(const char *relationName, Oid relationReltype, bool isshared, int natts, const FormData_pg_attribute *attrs)
Definition relcache.c:1887
static const FormData_pg_attribute Desc_pg_database[Natts_pg_database]
Definition relcache.c:118
static const FormData_pg_attribute Desc_pg_authid[Natts_pg_authid]
Definition relcache.c:119
static const FormData_pg_attribute Desc_pg_subscription[Natts_pg_subscription]
Definition relcache.c:123
static const FormData_pg_attribute Desc_pg_auth_members[Natts_pg_auth_members]
Definition relcache.c:120
static const FormData_pg_attribute Desc_pg_parameter_acl[Natts_pg_parameter_acl]
Definition relcache.c:124
void RelationMapInitializePhase2(void)
Definition relmapper.c:672

References CacheMemoryContext, Desc_pg_auth_members, Desc_pg_authid, Desc_pg_database, Desc_pg_parameter_acl, 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 4113 of file relcache.c.

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

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

Referenced by InitPostgres().

◆ RelationCacheInvalidate()

void RelationCacheInvalidate ( bool  debug_discard)

Definition at line 2996 of file relcache.c.

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

2941{
2942 Relation relation;
2943
2945
2946 if (relation)
2947 {
2949 RelationFlushRelation(relation);
2950 }
2951 else
2952 {
2953 int i;
2954
2955 for (i = 0; i < in_progress_list_len; i++)
2956 if (in_progress_list[i].reloid == relationId)
2958 }
2959}
#define RelationIdCacheLookup(ID, RELATION)
Definition relcache.c:235
static void RelationFlushRelation(Relation relation)
Definition relcache.c:2829

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

2549{
2551 Assert(!relation->rd_isnailed);
2552
2553 /*
2554 * Relations created in the same transaction must never be removed, see
2555 * RelationFlushRelation.
2556 */
2560
2561 /* first mark it as invalid */
2563
2564 /* Remove it from the hash table */
2565 RelationCacheDelete(relation);
2566
2567 /* And release storage */
2568 RelationDestroyRelation(relation, false);
2569}
#define RelationCacheDelete(RELATION)
Definition relcache.c:247

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

2223{
2224 /* Note: no locking manipulations needed */
2226
2227 RelationCloseCleanup(relation);
2228}
static void RelationCloseCleanup(Relation relation)
Definition relcache.c:2231

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

2232{
2233 /*
2234 * If the relation is no longer open in this session, we can clean up any
2235 * stale partition descriptors it has. This is unlikely, so check to see
2236 * if there are child contexts before expending a call to mcxt.c.
2237 */
2238 if (RelationHasReferenceCountZero(relation))
2239 {
2240 if (relation->rd_pdcxt != NULL &&
2241 relation->rd_pdcxt->firstchild != NULL)
2243
2244 if (relation->rd_pddcxt != NULL &&
2245 relation->rd_pddcxt->firstchild != NULL)
2247 }
2248
2249#ifdef RELCACHE_FORCE_RELEASE
2250 if (RelationHasReferenceCountZero(relation) &&
2253 RelationClearRelation(relation);
2254#endif
2255}
void MemoryContextDeleteChildren(MemoryContext context)
Definition mcxt.c:558
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 2202 of file relcache.c.

2203{
2204 Assert(rel->rd_refcnt > 0);
2205 rel->rd_refcnt -= 1;
2208}
static void ResourceOwnerForgetRelationRef(ResourceOwner owner, Relation rel)
Definition relcache.c:2175
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 2441 of file relcache.c.

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

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

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

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

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

5167{
5168 List *result;
5170 bool isnull;
5171 char *exprsString;
5172 List *rawExprs;
5173 ListCell *lc;
5174
5175 /* Quick exit if there is nothing to do. */
5176 if (relation->rd_indextuple == NULL ||
5178 return NIL;
5179
5180 /* Extract raw node tree(s) from index tuple. */
5184 &isnull);
5185 Assert(!isnull);
5189
5190 /* Construct null Consts; the typlen and typbyval are arbitrary. */
5191 result = NIL;
5192 foreach(lc, rawExprs)
5193 {
5194 Node *rawExpr = (Node *) lfirst(lc);
5195
5200 1,
5201 (Datum) 0,
5202 true,
5203 true));
5204 }
5205
5206 return result;
5207}
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:4483

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

Referenced by BuildDummyIndexInfo().

◆ RelationGetExclusionInfo()

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

Definition at line 5663 of file relcache.c.

5667{
5668 int indnkeyatts;
5669 Oid *ops;
5670 Oid *funcs;
5671 uint16 *strats;
5674 ScanKeyData skey[1];
5675 HeapTuple htup;
5676 bool found;
5678 int i;
5679
5681
5682 /* Allocate result space in caller context */
5683 *operators = ops = palloc_array(Oid, indnkeyatts);
5684 *procs = funcs = palloc_array(Oid, indnkeyatts);
5686
5687 /* Quick exit if we have the data cached already */
5688 if (indexRelation->rd_exclstrats != NULL)
5689 {
5690 memcpy(ops, indexRelation->rd_exclops, sizeof(Oid) * indnkeyatts);
5691 memcpy(funcs, indexRelation->rd_exclprocs, sizeof(Oid) * indnkeyatts);
5692 memcpy(strats, indexRelation->rd_exclstrats, sizeof(uint16) * indnkeyatts);
5693 return;
5694 }
5695
5696 /*
5697 * Search pg_constraint for the constraint associated with the index. To
5698 * make this not too painfully slow, we use the index on conrelid; that
5699 * will hold the parent relation's OID not the index's own OID.
5700 *
5701 * Note: if we wanted to rely on the constraint name matching the index's
5702 * name, we could just do a direct lookup using pg_constraint's unique
5703 * index. For the moment it doesn't seem worth requiring that.
5704 */
5705 ScanKeyInit(&skey[0],
5708 ObjectIdGetDatum(indexRelation->rd_index->indrelid));
5709
5712 NULL, 1, skey);
5713 found = false;
5714
5716 {
5718 Datum val;
5719 bool isnull;
5720 ArrayType *arr;
5721 int nelem;
5722
5723 /* We want the exclusion constraint owning the index */
5724 if ((conform->contype != CONSTRAINT_EXCLUSION &&
5725 !(conform->conperiod && (conform->contype == CONSTRAINT_PRIMARY
5726 || conform->contype == CONSTRAINT_UNIQUE))) ||
5727 conform->conindid != RelationGetRelid(indexRelation))
5728 continue;
5729
5730 /* There should be only one */
5731 if (found)
5732 elog(ERROR, "unexpected exclusion constraint record found for rel %s",
5733 RelationGetRelationName(indexRelation));
5734 found = true;
5735
5736 /* Extract the operator OIDS from conexclop */
5737 val = fastgetattr(htup,
5739 conrel->rd_att, &isnull);
5740 if (isnull)
5741 elog(ERROR, "null conexclop for rel %s",
5742 RelationGetRelationName(indexRelation));
5743
5744 arr = DatumGetArrayTypeP(val); /* ensure not toasted */
5745 nelem = ARR_DIMS(arr)[0];
5746 if (ARR_NDIM(arr) != 1 ||
5747 nelem != indnkeyatts ||
5748 ARR_HASNULL(arr) ||
5749 ARR_ELEMTYPE(arr) != OIDOID)
5750 elog(ERROR, "conexclop is not a 1-D Oid array");
5751
5752 memcpy(ops, ARR_DATA_PTR(arr), sizeof(Oid) * indnkeyatts);
5753 }
5754
5757
5758 if (!found)
5759 elog(ERROR, "exclusion constraint record missing for rel %s",
5760 RelationGetRelationName(indexRelation));
5761
5762 /* We need the func OIDs and strategy numbers too */
5763 for (i = 0; i < indnkeyatts; i++)
5764 {
5765 funcs[i] = get_opcode(ops[i]);
5766 strats[i] = get_op_opfamily_strategy(ops[i],
5767 indexRelation->rd_opfamily[i]);
5768 /* shouldn't fail, since it was checked at index creation */
5769 if (strats[i] == InvalidStrategy)
5770 elog(ERROR, "could not find strategy for operator %u in family %u",
5771 ops[i], indexRelation->rd_opfamily[i]);
5772 }
5773
5774 /* Save a copy of the results in the relcache entry. */
5775 oldcxt = MemoryContextSwitchTo(indexRelation->rd_indexcxt);
5776 indexRelation->rd_exclops = palloc_array(Oid, indnkeyatts);
5777 indexRelation->rd_exclprocs = palloc_array(Oid, indnkeyatts);
5778 indexRelation->rd_exclstrats = palloc_array(uint16, indnkeyatts);
5779 memcpy(indexRelation->rd_exclops, ops, sizeof(Oid) * indnkeyatts);
5780 memcpy(indexRelation->rd_exclprocs, funcs, sizeof(Oid) * indnkeyatts);
5781 memcpy(indexRelation->rd_exclstrats, strats, sizeof(uint16) * indnkeyatts);
5783}
#define ARR_NDIM(a)
Definition array.h:290
#define DatumGetArrayTypeP(X)
Definition array.h:261
#define ARR_ELEMTYPE(a)
Definition array.h:292
#define ARR_HASNULL(a)
Definition array.h:291
uint16_t uint16
Definition c.h:623
RegProcedure get_opcode(Oid opno)
Definition lsyscache.c:1577
int get_op_opfamily_strategy(Oid opno, Oid opfamily)
Definition lsyscache.c:87
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition rel.h:535
#define InvalidStrategy
Definition stratnum.h:24

References AccessShareLock, ARR_DATA_PTR, ARR_DIMS, ARR_ELEMTYPE, ARR_HASNULL, ARR_NDIM, BTEqualStrategyNumber, DatumGetArrayTypeP, elog, ERROR, fastgetattr(), fb(), Form_pg_constraint, get_op_opfamily_strategy(), get_opcode(), GETSTRUCT(), HeapTupleIsValid, i, IndexRelationGetNumberOfKeyAttributes, InvalidStrategy, memcpy(), MemoryContextSwitchTo(), ObjectIdGetDatum(), palloc_array, RelationData::rd_exclops, RelationData::rd_exclprocs, RelationData::rd_exclstrats, RelationData::rd_index, RelationData::rd_indexcxt, RelationData::rd_opfamily, RelationGetRelationName, RelationGetRelid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), and val.

Referenced by BuildIndexInfo(), and CheckIndexCompatible().

◆ RelationGetFKeyList()

List * RelationGetFKeyList ( Relation  relation)

Definition at line 4741 of file relcache.c.

4742{
4743 List *result;
4747 HeapTuple htup;
4748 List *oldlist;
4750
4751 /* Quick exit if we already computed the list. */
4752 if (relation->rd_fkeyvalid)
4753 return relation->rd_fkeylist;
4754
4755 /*
4756 * We build the list we intend to return (in the caller's context) while
4757 * doing the scan. After successfully completing the scan, we copy that
4758 * list into the relcache entry. This avoids cache-context memory leakage
4759 * if we get some sort of error partway through.
4760 */
4761 result = NIL;
4762
4763 /* Prepare to scan pg_constraint for entries having conrelid = this rel. */
4768
4771 NULL, 1, &skey);
4772
4774 {
4775 Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(htup);
4776 ForeignKeyCacheInfo *info;
4777
4778 /* consider only foreign keys */
4779 if (constraint->contype != CONSTRAINT_FOREIGN)
4780 continue;
4781
4783 info->conoid = constraint->oid;
4784 info->conrelid = constraint->conrelid;
4785 info->confrelid = constraint->confrelid;
4786 info->conenforced = constraint->conenforced;
4787
4788 DeconstructFkConstraintRow(htup, &info->nkeys,
4789 info->conkey,
4790 info->confkey,
4791 info->conpfeqop,
4792 NULL, NULL, NULL, NULL);
4793
4794 /* Add FK's node to the result list */
4795 result = lappend(result, info);
4796 }
4797
4800
4801 /* Now save a copy of the completed list in the relcache entry. */
4803 oldlist = relation->rd_fkeylist;
4804 relation->rd_fkeylist = copyObject(result);
4805 relation->rd_fkeyvalid = true;
4807
4808 /* Don't leak the old list, if there is one */
4810
4811 return result;
4812}
#define copyObject(obj)
Definition nodes.h:230
#define makeNode(_type_)
Definition nodes.h:159
void DeconstructFkConstraintRow(HeapTuple tuple, int *numfks, AttrNumber *conkey, AttrNumber *confkey, Oid *pf_eq_oprs, Oid *pp_eq_oprs, Oid *ff_eq_oprs, int *num_fk_del_set_cols, AttrNumber *fk_del_set_cols)

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

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

◆ RelationGetIdentityKeyBitmap()

Bitmapset * RelationGetIdentityKeyBitmap ( Relation  relation)

Definition at line 5586 of file relcache.c.

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

6022{
6024 bytea **opts = relation->rd_opcoptions;
6025 Oid relid = RelationGetRelid(relation);
6026 int natts = RelationGetNumberOfAttributes(relation); /* XXX
6027 * IndexRelationGetNumberOfKeyAttributes */
6028 int i;
6029
6030 /* Try to copy cached options. */
6031 if (opts)
6032 return copy ? CopyIndexAttOptions(opts, natts) : opts;
6033
6034 /* Get and parse opclass options. */
6035 opts = palloc0_array(bytea *, natts);
6036
6037 for (i = 0; i < natts; i++)
6038 {
6040 {
6041 Datum attoptions = get_attoptions(relid, i + 1);
6042
6043 opts[i] = index_opclass_options(relation, i + 1, attoptions, false);
6044
6045 if (attoptions != (Datum) 0)
6046 pfree(DatumGetPointer(attoptions));
6047 }
6048 }
6049
6050 /* Copy parsed options to the cache. */
6052 relation->rd_opcoptions = CopyIndexAttOptions(opts, natts);
6054
6055 if (copy)
6056 return opts;
6057
6058 for (i = 0; i < natts; i++)
6059 {
6060 if (opts[i])
6061 pfree(opts[i]);
6062 }
6063
6064 pfree(opts);
6065
6066 return relation->rd_opcoptions;
6067}
#define palloc0_array(type, count)
Definition fe_memutils.h:92
bytea * index_opclass_options(Relation indrel, AttrNumber attnum, Datum attoptions, bool validate)
Definition indexam.c:1016
Datum get_attoptions(Oid relid, int16 attnum)
Definition lsyscache.c:1188
static bytea ** CopyIndexAttOptions(bytea **srcopts, int natts)
Definition relcache.c:6001

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

5314{
5315 Bitmapset *uindexattrs; /* columns in unique indexes */
5316 Bitmapset *pkindexattrs; /* columns in the primary index */
5317 Bitmapset *idindexattrs; /* columns in the replica identity */
5318 Bitmapset *hotblockingattrs; /* columns with HOT blocking indexes */
5319 Bitmapset *summarizedattrs; /* columns with summarizing indexes */
5324 ListCell *l;
5326
5327 /* Quick exit if we already computed the result. */
5328 if (relation->rd_attrsvalid)
5329 {
5330 switch (attrKind)
5331 {
5333 return bms_copy(relation->rd_keyattr);
5335 return bms_copy(relation->rd_pkattr);
5337 return bms_copy(relation->rd_idattr);
5339 return bms_copy(relation->rd_hotblockingattr);
5341 return bms_copy(relation->rd_summarizedattr);
5342 default:
5343 elog(ERROR, "unknown attrKind %u", attrKind);
5344 }
5345 }
5346
5347 /* Fast path if definitely no indexes */
5348 if (!RelationGetForm(relation)->relhasindex)
5349 return NULL;
5350
5351 /*
5352 * Get cached list of index OIDs. If we have to start over, we do so here.
5353 */
5354restart:
5356
5357 /* Fall out if no indexes (but relhasindex was set) */
5358 if (indexoidlist == NIL)
5359 return NULL;
5360
5361 /*
5362 * Copy the rd_pkindex and rd_replidindex values computed by
5363 * RelationGetIndexList before proceeding. This is needed because a
5364 * relcache flush could occur inside index_open below, resetting the
5365 * fields managed by RelationGetIndexList. We need to do the work with
5366 * stable values of these fields.
5367 */
5368 relpkindex = relation->rd_pkindex;
5369 relreplindex = relation->rd_replidindex;
5370
5371 /*
5372 * For each index, add referenced attributes to indexattrs.
5373 *
5374 * Note: we consider all indexes returned by RelationGetIndexList, even if
5375 * they are not indisready or indisvalid. This is important because an
5376 * index for which CREATE INDEX CONCURRENTLY has just started must be
5377 * included in HOT-safety decisions (see README.HOT). If a DROP INDEX
5378 * CONCURRENTLY is far enough along that we should ignore the index, it
5379 * won't be returned at all by RelationGetIndexList.
5380 */
5381 uindexattrs = NULL;
5386 foreach(l, indexoidlist)
5387 {
5388 Oid indexOid = lfirst_oid(l);
5390 Datum datum;
5391 bool isnull;
5394 int i;
5395 bool isKey; /* candidate key */
5396 bool isPK; /* primary key */
5397 bool isIDKey; /* replica identity index */
5398 Bitmapset **attrs;
5399
5401
5402 /*
5403 * Extract index expressions and index predicate. Note: Don't use
5404 * RelationGetIndexExpressions()/RelationGetIndexPredicate(), because
5405 * those might run constant expressions evaluation, which needs a
5406 * snapshot, which we might not have here. (Also, it's probably more
5407 * sound to collect the bitmaps before any transformations that might
5408 * eliminate columns, but the practical impact of this is limited.)
5409 */
5410
5411 datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indexprs,
5412 GetPgIndexDescriptor(), &isnull);
5413 if (!isnull)
5415 else
5417
5418 datum = heap_getattr(indexDesc->rd_indextuple, Anum_pg_index_indpred,
5419 GetPgIndexDescriptor(), &isnull);
5420 if (!isnull)
5422 else
5424
5425 /* Can this index be referenced by a foreign key? */
5426 isKey = indexDesc->rd_index->indisunique &&
5429
5430 /* Is this a primary key? */
5431 isPK = (indexOid == relpkindex);
5432
5433 /* Is this index the configured (or default) replica identity? */
5434 isIDKey = (indexOid == relreplindex);
5435
5436 /*
5437 * If the index is summarizing, it doesn't block HOT updates, but we
5438 * may still need to update it (if the attributes were modified). So
5439 * decide which bitmap we'll update in the following loop.
5440 */
5441 if (indexDesc->rd_indam->amsummarizing)
5443 else
5445
5446 /* Collect simple attribute references */
5447 for (i = 0; i < indexDesc->rd_index->indnatts; i++)
5448 {
5449 int attrnum = indexDesc->rd_index->indkey.values[i];
5450
5451 /*
5452 * Since we have covering indexes with non-key columns, we must
5453 * handle them accurately here. non-key columns must be added into
5454 * hotblockingattrs or summarizedattrs, since they are in index,
5455 * and update shouldn't miss them.
5456 *
5457 * Summarizing indexes do not block HOT, but do need to be updated
5458 * when the column value changes, thus require a separate
5459 * attribute bitmapset.
5460 *
5461 * Obviously, non-key columns couldn't be referenced by foreign
5462 * key or identity key. Hence we do not include them into
5463 * uindexattrs, pkindexattrs and idindexattrs bitmaps.
5464 */
5465 if (attrnum != 0)
5466 {
5469
5470 if (isKey && i < indexDesc->rd_index->indnkeyatts)
5473
5474 if (isPK && i < indexDesc->rd_index->indnkeyatts)
5477
5478 if (isIDKey && i < indexDesc->rd_index->indnkeyatts)
5481 }
5482 }
5483
5484 /* Collect all attributes used in expressions, too */
5486
5487 /* Collect all attributes in the index predicate, too */
5489
5491 }
5492
5493 /*
5494 * During one of the index_opens in the above loop, we might have received
5495 * a relcache flush event on this relcache entry, which might have been
5496 * signaling a change in the rel's index list. If so, we'd better start
5497 * over to ensure we deliver up-to-date attribute bitmaps.
5498 */
5501 relpkindex == relation->rd_pkindex &&
5502 relreplindex == relation->rd_replidindex)
5503 {
5504 /* Still the same index set, so proceed */
5507 }
5508 else
5509 {
5510 /* Gotta do it over ... might as well not leak memory */
5518
5519 goto restart;
5520 }
5521
5522 /* Don't leak the old values of these bitmaps, if any */
5523 relation->rd_attrsvalid = false;
5524 bms_free(relation->rd_keyattr);
5525 relation->rd_keyattr = NULL;
5526 bms_free(relation->rd_pkattr);
5527 relation->rd_pkattr = NULL;
5528 bms_free(relation->rd_idattr);
5529 relation->rd_idattr = NULL;
5530 bms_free(relation->rd_hotblockingattr);
5531 relation->rd_hotblockingattr = NULL;
5532 bms_free(relation->rd_summarizedattr);
5533 relation->rd_summarizedattr = NULL;
5534
5535 /*
5536 * Now save copies of the bitmaps in the relcache entry. We intentionally
5537 * set rd_attrsvalid last, because that's the one that signals validity of
5538 * the values; if we run out of memory before making that copy, we won't
5539 * leave the relcache entry looking like the other ones are valid but
5540 * empty.
5541 */
5543 relation->rd_keyattr = bms_copy(uindexattrs);
5544 relation->rd_pkattr = bms_copy(pkindexattrs);
5545 relation->rd_idattr = bms_copy(idindexattrs);
5548 relation->rd_attrsvalid = true;
5550
5551 /* We return our original working copy for caller to play with */
5552 switch (attrKind)
5553 {
5555 return uindexattrs;
5557 return pkindexattrs;
5559 return idindexattrs;
5561 return hotblockingattrs;
5563 return summarizedattrs;
5564 default:
5565 elog(ERROR, "unknown attrKind %u", attrKind);
5566 return NULL;
5567 }
5568}
void index_close(Relation relation, LOCKMODE lockmode)
Definition indexam.c:178
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition indexam.c:134
List * RelationGetIndexList(Relation relation)
Definition relcache.c:4846
@ INDEX_ATTR_BITMAP_KEY
Definition relcache.h:70
@ INDEX_ATTR_BITMAP_HOT_BLOCKING
Definition relcache.h:73
@ INDEX_ATTR_BITMAP_PRIMARY_KEY
Definition relcache.h:71
@ INDEX_ATTR_BITMAP_SUMMARIZED
Definition relcache.h:74
@ INDEX_ATTR_BITMAP_IDENTITY_KEY
Definition relcache.h:72
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 5107 of file relcache.c.

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

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

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

◆ RelationGetIndexList()

List * RelationGetIndexList ( Relation  relation)

Definition at line 4846 of file relcache.c.

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

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

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

◆ RelationGetIndexPredicate()

List * RelationGetIndexPredicate ( Relation  relation)

Definition at line 5220 of file relcache.c.

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

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

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

◆ RelationGetPrimaryKeyIndex()

Oid RelationGetPrimaryKeyIndex ( Relation  relation,
bool  deferrable_ok 
)

Definition at line 5057 of file relcache.c.

5058{
5059 List *ilist;
5060
5061 if (!relation->rd_indexvalid)
5062 {
5063 /* RelationGetIndexList does the heavy lifting. */
5064 ilist = RelationGetIndexList(relation);
5066 Assert(relation->rd_indexvalid);
5067 }
5068
5069 if (deferrable_ok)
5070 return relation->rd_pkindex;
5071 else if (relation->rd_ispkdeferrable)
5072 return InvalidOid;
5073 return relation->rd_pkindex;
5074}

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

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

◆ RelationGetQualifiedRelationName()

char * RelationGetQualifiedRelationName ( Relation  rel)

Definition at line 2144 of file relcache.c.

2145{
2148}
char * get_qualified_objname(Oid nspid, char *objname)
Definition lsyscache.c:3712

References get_qualified_objname(), RelationGetNamespace, and RelationGetRelationName.

Referenced by check_publication_add_relation().

◆ RelationGetReplicaIndex()

Oid RelationGetReplicaIndex ( Relation  relation)

Definition at line 5082 of file relcache.c.

5083{
5084 List *ilist;
5085
5086 if (!relation->rd_indexvalid)
5087 {
5088 /* RelationGetIndexList does the heavy lifting. */
5089 ilist = RelationGetIndexList(relation);
5091 Assert(relation->rd_indexvalid);
5092 }
5093
5094 return relation->rd_replidindex;
5095}

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

4988{
4992 HeapTuple htup;
4993 List *result;
4994 List *oldlist;
4996
4997 /* Quick exit if we already computed the list. */
4998 if (relation->rd_statvalid != 0)
4999 return list_copy(relation->rd_statlist);
5000
5001 /*
5002 * We build the list we intend to return (in the caller's context) while
5003 * doing the scan. After successfully completing the scan, we copy that
5004 * list into the relcache entry. This avoids cache-context memory leakage
5005 * if we get some sort of error partway through.
5006 */
5007 result = NIL;
5008
5009 /*
5010 * Prepare to scan pg_statistic_ext for entries having stxrelid = this
5011 * rel.
5012 */
5017
5020 NULL, 1, &skey);
5021
5023 {
5024 Oid oid = ((Form_pg_statistic_ext) GETSTRUCT(htup))->oid;
5025
5026 result = lappend_oid(result, oid);
5027 }
5028
5030
5032
5033 /* Sort the result list into OID order, per API spec. */
5035
5036 /* Now save a copy of the completed list in the relcache entry. */
5038 oldlist = relation->rd_statlist;
5039 relation->rd_statlist = list_copy(result);
5040
5041 relation->rd_statvalid = true;
5043
5044 /* Don't leak the old list, if there is one */
5046
5047 return result;
5048}
END_CATALOG_STRUCT typedef FormData_pg_statistic_ext * Form_pg_statistic_ext

References AccessShareLock, BTEqualStrategyNumber, CacheMemoryContext, fb(), Form_pg_statistic_ext, GETSTRUCT(), HeapTupleIsValid, lappend_oid(), list_copy(), list_free(), list_oid_cmp(), list_sort(), MemoryContextSwitchTo(), NIL, ObjectIdGetDatum(), RelationData::rd_statlist, RelationData::rd_statvalid, RelationGetRelid, result, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by expandTableLikeClause(), and get_relation_statistics().

◆ RelationIdGetRelation()

Relation RelationIdGetRelation ( Oid  relationId)

Definition at line 2091 of file relcache.c.

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

6856{
6861 {
6862 /*
6863 * If this Assert fails, we don't need the applicable special case
6864 * anymore.
6865 */
6867 return true;
6868 }
6870}
bool RelationSupportsSysCache(Oid relid)
Definition syscache.c:763

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

Referenced by RegisterRelcacheInvalidation(), and write_relcache_init_file().

◆ RelationIncrementReferenceCount()

◆ RelationInitIndexAccessInfo()

void RelationInitIndexAccessInfo ( Relation  relation)

Definition at line 1438 of file relcache.c.

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

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, IndexAmRoutine::amsupport, Assert, CacheMemoryContext, DatumGetPointer(), elog, ERROR, fastgetattr(), fb(), Form_pg_am, Form_pg_index, GetPgIndexDescriptor(), GETSTRUCT(), heap_copytuple(), HeapTupleIsValid, IndexRelationGetNumberOfAttributes, IndexRelationGetNumberOfKeyAttributes, IndexSupportInitialize(), InitIndexAmRoutine(), InvalidOid, memcpy(), MemoryContextAllocZero(), MemoryContextCopyAndSetIdentifier, MemoryContextSwitchTo(), NIL, ObjectIdGetDatum(), RelationData::rd_amcache, RelationData::rd_amhandler, RelationData::rd_exclops, RelationData::rd_exclprocs, RelationData::rd_exclstrats, RelationData::rd_indam, RelationData::rd_indcollation, RelationData::rd_index, RelationData::rd_indexcxt, RelationData::rd_indexprs, RelationData::rd_indextuple, RelationData::rd_indoption, RelationData::rd_indpred, RelationData::rd_opcintype, RelationData::rd_opfamily, RelationData::rd_rel, RelationData::rd_support, RelationData::rd_supportinfo, RelationGetIndexAttOptions(), RelationGetNumberOfAttributes, RelationGetRelationName, RelationGetRelid, ReleaseSysCache(), and SearchSysCache1().

Referenced by index_create(), and RelationBuildDesc().

◆ RelationInitPhysicalAddr()

static void RelationInitPhysicalAddr ( Relation  relation)
static

Definition at line 1337 of file relcache.c.

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

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

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

2521{
2522 /*
2523 * Make sure smgr and lower levels close the relation's files, if they
2524 * weren't closed already. If the relation is not getting deleted, the
2525 * next smgr access should reopen the files automatically. This ensures
2526 * that the low-level file access state is updated after, say, a vacuum
2527 * truncation.
2528 */
2529 RelationCloseSmgr(relation);
2530
2531 /* Free AM cached data, if any */
2532 if (relation->rd_amcache)
2533 pfree(relation->rd_amcache);
2534 relation->rd_amcache = NULL;
2535
2536 relation->rd_isvalid = false;
2537}

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

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

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

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

◆ RelationRebuildRelation()

static void RelationRebuildRelation ( Relation  relation)
static

Definition at line 2587 of file relcache.c.

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

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

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

◆ RelationReloadIndexInfo()

static void RelationReloadIndexInfo ( Relation  relation)
static

Definition at line 2278 of file relcache.c.

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

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

Referenced by RelationRebuildRelation().

◆ RelationReloadNailed()

static void RelationReloadNailed ( Relation  relation)
static

Definition at line 2387 of file relcache.c.

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

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

Referenced by RelationRebuildRelation().

◆ RelationSetNewRelfilenumber()

void RelationSetNewRelfilenumber ( Relation  relation,
char  persistence 
)

Definition at line 3777 of file relcache.c.

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

References Assert, binary_upgrade_next_heap_pg_class_relfilenumber, binary_upgrade_next_index_pg_class_relfilenumber, CacheInvalidateRelcache(), CatalogTupleUpdate(), CommandCounterIncrement(), elog, ereport, errcode(), errmsg, ERROR, fb(), GetCurrentTransactionId(), GetNewRelFileNumber(), GETSTRUCT(), heap_freetuple(), HeapTupleIsValid, InplaceUpdateTupleLock, InvalidMultiXactId, InvalidOid, InvalidTransactionId, IsBinaryUpgrade, ObjectIdGetDatum(), OidIsValid, RelationData::rd_backend, RelationData::rd_locator, RelationData::rd_rel, RelationAssumeNewRelfilelocator(), RelationCreateStorage(), RelationDropStorage(), RelationGetRelationName, RelationGetRelid, RelationIsMapped, RelationMapUpdateMap(), RelFileLocator::relNumber, RowExclusiveLock, SearchSysCacheLockedCopy1(), smgrclose(), smgrdounlinkall(), smgropen(), HeapTupleData::t_self, table_close(), table_open(), table_relation_set_new_filelocator(), and UnlockTuple().

Referenced by AlterSequence(), ExecuteTruncateGuts(), reindex_index(), ResetSequence(), and SequenceChangePersistence().

◆ RememberToFreeTupleDescAtEOX()

◆ ResourceOwnerForgetRelationRef()

static void ResourceOwnerForgetRelationRef ( ResourceOwner  owner,
Relation  rel 
)
inlinestatic

Definition at line 2175 of file relcache.c.

2176{
2178}
static const ResourceOwnerDesc relref_resowner_desc
Definition relcache.c:2159
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition resowner.c:571

References PointerGetDatum, relref_resowner_desc, and ResourceOwnerForget().

Referenced by RelationDecrementReferenceCount().

◆ ResourceOwnerRememberRelationRef()

static void ResourceOwnerRememberRelationRef ( ResourceOwner  owner,
Relation  rel 
)
inlinestatic

Definition at line 2170 of file relcache.c.

2171{
2173}
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition resowner.c:531

References PointerGetDatum, relref_resowner_desc, and ResourceOwnerRemember().

Referenced by RelationIncrementReferenceCount().

◆ ResOwnerPrintRelCache()

static char * ResOwnerPrintRelCache ( Datum  res)
static

Definition at line 7009 of file relcache.c.

7010{
7011 Relation rel = (Relation) DatumGetPointer(res);
7012
7013 return psprintf("relation \"%s\"", RelationGetRelationName(rel));
7014}
char * psprintf(const char *fmt,...)
Definition psprintf.c:43

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

◆ ResOwnerReleaseRelation()

static void ResOwnerReleaseRelation ( Datum  res)
static

Definition at line 7017 of file relcache.c.

7018{
7019 Relation rel = (Relation) DatumGetPointer(res);
7020
7021 /*
7022 * This reference has already been removed from the resource owner, so
7023 * just decrement reference count without calling
7024 * ResourceOwnerForgetRelationRef.
7025 */
7026 Assert(rel->rd_refcnt > 0);
7027 rel->rd_refcnt -= 1;
7028
7030}

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

◆ ScanPgRelation()

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

Definition at line 344 of file relcache.c.

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

6993{
6994 if (unlink(initfilename) < 0)
6995 {
6996 /* It might not be there, but log any error other than ENOENT */
6997 if (errno != ENOENT)
6998 ereport(elevel,
7000 errmsg("could not remove cache file \"%s\": %m",
7001 initfilename)));
7002 }
7003}
int errcode_for_file_access(void)
Definition elog.c:898

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

6833{
6834 if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len))
6835 ereport(FATAL,
6837 errmsg_internal("could not write init file: %m"));
6838 if (len > 0 && fwrite(data, 1, len, fp) != len)
6839 ereport(FATAL,
6841 errmsg_internal("could not write init file: %m"));
6842}
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 6620 of file relcache.c.

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

Referenced by RelationCacheInitializePhase3().

◆ Desc_pg_auth_members

Definition at line 120 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_authid

Definition at line 119 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_class

◆ Desc_pg_database

Definition at line 118 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_index

Definition at line 121 of file relcache.c.

Referenced by GetPgIndexDescriptor().

◆ Desc_pg_parameter_acl

Definition at line 124 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_proc

Definition at line 116 of file relcache.c.

Referenced by RelationCacheInitializePhase3().

◆ Desc_pg_shseclabel

Definition at line 122 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_subscription

Definition at line 123 of file relcache.c.

Referenced by RelationCacheInitializePhase2().

◆ Desc_pg_type

Definition at line 117 of file relcache.c.

Referenced by RelationCacheInitializePhase3().

◆ eoxact_list

Oid eoxact_list[MAX_EOXACT_LIST]
static

Definition at line 189 of file relcache.c.

Referenced by AtEOSubXact_RelationCache(), and AtEOXact_RelationCache().

◆ eoxact_list_len

int eoxact_list_len = 0
static

Definition at line 190 of file relcache.c.

Referenced by AtEOSubXact_RelationCache(), and AtEOXact_RelationCache().

◆ eoxact_list_overflowed

bool eoxact_list_overflowed = false
static

Definition at line 191 of file relcache.c.

Referenced by AtEOSubXact_RelationCache(), and AtEOXact_RelationCache().

◆ EOXactTupleDescArray

TupleDesc* EOXactTupleDescArray
static

Definition at line 206 of file relcache.c.

Referenced by AtEOXact_RelationCache(), and RememberToFreeTupleDescAtEOX().

◆ EOXactTupleDescArrayLen

int EOXactTupleDescArrayLen = 0
static

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

Referenced by RelationBuildDesc(), and RelationCacheInitialize().

◆ NextEOXactTupleDescNum

int NextEOXactTupleDescNum = 0
static

Definition at line 207 of file relcache.c.

Referenced by AtEOXact_RelationCache(), and RememberToFreeTupleDescAtEOX().

◆ OpClassCache

HTAB* OpClassCache = NULL
static

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

Definition at line 2159 of file relcache.c.

2160{
2161 .name = "relcache reference",
2162 .release_phase = RESOURCE_RELEASE_BEFORE_LOCKS,
2163 .release_priority = RELEASE_PRIO_RELCACHE_REFS,
2164 .ReleaseResource = ResOwnerReleaseRelation,
2165 .DebugPrint = ResOwnerPrintRelCache
2166};

Referenced by ResourceOwnerForgetRelationRef(), and ResourceOwnerRememberRelationRef().