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

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

3384{
3385 HASH_SEQ_STATUS status;
3387 int i;
3388
3389 /*
3390 * Forget in_progress_list. This is relevant when we're aborting due to
3391 * an error during RelationBuildDesc(). We don't commit subtransactions
3392 * during RelationBuildDesc().
3393 */
3396
3397 /*
3398 * Unless the eoxact_list[] overflowed, we only need to examine the rels
3399 * listed in it. Otherwise fall back on a hash_seq_search scan. Same
3400 * logic as in AtEOXact_RelationCache.
3401 */
3403 {
3405 while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
3406 {
3409 }
3410 }
3411 else
3412 {
3413 for (i = 0; i < eoxact_list_len; i++)
3414 {
3416 &eoxact_list[i],
3417 HASH_FIND,
3418 NULL);
3419 if (idhentry != NULL)
3422 }
3423 }
3424
3425 /* Don't reset the list; we still need more cleanup later */
3426}
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:3437
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 3300 of file relcache.c.

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

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

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

4508{
4513 HeapTuple htup;
4514 int found = 0;
4515
4516 /* Allocate array with room for as many entries as expected */
4517 attrdef = (AttrDefault *)
4519 ndef * sizeof(AttrDefault));
4520
4521 /* Search pg_attrdef for relevant entries */
4526
4529 NULL, 1, &skey);
4530
4532 {
4534 Datum val;
4535 bool isnull;
4536
4537 /* protect limited size of array */
4538 if (found >= ndef)
4539 {
4540 elog(WARNING, "unexpected pg_attrdef record found for attribute %d of relation \"%s\"",
4541 adform->adnum, RelationGetRelationName(relation));
4542 break;
4543 }
4544
4545 val = fastgetattr(htup,
4547 adrel->rd_att, &isnull);
4548 if (isnull)
4549 elog(WARNING, "null adbin for attribute %d of relation \"%s\"",
4550 adform->adnum, RelationGetRelationName(relation));
4551 else
4552 {
4553 /* detoast and convert to cstring in caller's context */
4554 char *s = TextDatumGetCString(val);
4555
4556 attrdef[found].adnum = adform->adnum;
4558 pfree(s);
4559 found++;
4560 }
4561 }
4562
4565
4566 if (found != ndef)
4567 elog(WARNING, "%d pg_attrdef record(s) missing for relation \"%s\"",
4568 ndef - found, RelationGetRelationName(relation));
4569
4570 /*
4571 * Sort the AttrDefault entries by adnum, for the convenience of
4572 * equalTupleDescs(). (Usually, they already will be in order, but this
4573 * might not be so if systable_getnext isn't using an index.)
4574 */
4575 if (found > 1)
4576 qsort(attrdef, found, sizeof(AttrDefault), AttrDefaultCmp);
4577
4578 /* Install array only after it's fully valid */
4579 relation->rd_att->constr->defval = attrdef;
4580 relation->rd_att->constr->num_defval = found;
4581}
#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:4587
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 4443 of file relcache.c.

4444{
4447 int i;
4448
4450
4452 result->tdtypeid = RECORDOID; /* not right, but we don't care */
4453 result->tdtypmod = -1;
4454
4455 for (i = 0; i < natts; i++)
4456 {
4458
4460 }
4461
4463
4464 /* Note: we don't bother to set up a TupleConstr entry */
4465
4467
4468 return result;
4469}
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 4720 of file relcache.c.

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

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

6004{
6005 bytea **opts = palloc_array(bytea *, natts);
6006
6007 for (int i = 0; i < natts; i++)
6008 {
6009 bytea *opt = srcopts[i];
6010
6011 opts[i] = !opt ? NULL : (bytea *)
6012 DatumGetPointer(datumCopy(PointerGetDatum(opt), false, -1));
6013 }
6014
6015 return opts;
6016}
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:835

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->permissive != policy2->permissive)
984 return false;
985 if (policy1->hassublinks != policy2->hassublinks)
986 return false;
987 if (strcmp(policy1->policy_name, policy2->policy_name) != 0)
988 return false;
989 if (ARR_DIMS(policy1->roles)[0] != ARR_DIMS(policy2->roles)[0])
990 return false;
991
992 r1 = (Oid *) ARR_DATA_PTR(policy1->roles);
993 r2 = (Oid *) ARR_DATA_PTR(policy2->roles);
994
995 for (i = 0; i < ARR_DIMS(policy1->roles)[0]; i++)
996 {
997 if (r1[i] != r2[i])
998 return false;
999 }
1000
1001 if (!equal(policy1->qual, policy2->qual))
1002 return false;
1003 if (!equal(policy1->with_check_qual, policy2->with_check_qual))
1004 return false;
1005 }
1006 else if (policy2 != NULL)
1007 return false;
1008
1009 return true;
1010}
#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 1018 of file relcache.c.

1019{
1020 ListCell *lc,
1021 *rc;
1022
1023 if (rsdesc1 == NULL && rsdesc2 == NULL)
1024 return true;
1025
1026 if ((rsdesc1 != NULL && rsdesc2 == NULL) ||
1027 (rsdesc1 == NULL && rsdesc2 != NULL))
1028 return false;
1029
1030 if (list_length(rsdesc1->policies) != list_length(rsdesc2->policies))
1031 return false;
1032
1033 /* RelationBuildRowSecurity should build policies in order */
1034 forboth(lc, rsdesc1->policies, rc, rsdesc2->policies)
1035 {
1038
1039 if (!equalPolicy(l, r))
1040 return false;
1041 }
1042
1043 return true;
1044}
#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 6084 of file relcache.c.

6085{
6089
6090 return 0; /* return value does not matter */
6091}
int err_generic_string(int field, const char *str)
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3682
#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 6101 of file relcache.c.

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

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

6126{
6127 errtable(rel);
6129
6130 return 0; /* return value does not matter */
6131}
#define PG_DIAG_COLUMN_NAME
int errtable(Relation rel)
Definition relcache.c:6084

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

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

4473{
4474 static TupleDesc pgclassdesc = NULL;
4475
4476 /* Already done? */
4477 if (pgclassdesc == NULL)
4480
4481 return pgclassdesc;
4482}
static TupleDesc BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs)
Definition relcache.c:4443
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 4485 of file relcache.c.

4486{
4487 static TupleDesc pgindexdesc = NULL;
4488
4489 /* Already done? */
4490 if (pgindexdesc == NULL)
4493
4494 return pgindexdesc;
4495}
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 1611 of file relcache.c.

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

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

Referenced by RelationInitIndexAccessInfo().

◆ InitIndexAmRoutine()

static void InitIndexAmRoutine ( Relation  relation)
static

Definition at line 1421 of file relcache.c.

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

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

4406{
4407 Relation ird;
4408
4409 /*
4410 * We must lock the underlying catalog before locking the index to avoid
4411 * deadlock, since RelationBuildDesc might well need to read the catalog,
4412 * and if anyone else is exclusive-locking this catalog and index they'll
4413 * be doing it in that order.
4414 */
4417 ird = RelationBuildDesc(indexoid, true);
4418 if (ird == NULL)
4419 ereport(PANIC,
4421 errmsg_internal("could not open critical system index %u", indexoid));
4422 ird->rd_isnailed = true;
4423 ird->rd_refcnt = 1;
4426
4428}
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:1059
bytea ** RelationGetIndexAttOptions(Relation relation, bool copy)
Definition relcache.c:6023

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

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

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

3983{
3987
3988 /* Flag relation as needing eoxact cleanup (to clear these fields) */
3989 EOXactListAdd(relation);
3990}
#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 1059 of file relcache.c.

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

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

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

5807{
5808 List *puboids = NIL;
5811 ListCell *lc;
5813 Oid schemaid;
5814 List *ancestors = NIL;
5815 Oid relid = RelationGetRelid(relation);
5816
5817 /*
5818 * If not publishable, it publishes no actions. (pgoutput_change() will
5819 * ignore it.)
5820 */
5821 if (!is_publishable_relation(relation))
5822 {
5823 memset(pubdesc, 0, sizeof(PublicationDesc));
5824 pubdesc->rf_valid_for_update = true;
5825 pubdesc->rf_valid_for_delete = true;
5826 pubdesc->cols_valid_for_update = true;
5827 pubdesc->cols_valid_for_delete = true;
5828 pubdesc->gencols_valid_for_update = true;
5829 pubdesc->gencols_valid_for_delete = true;
5830 return;
5831 }
5832
5833 if (relation->rd_pubdesc)
5834 {
5835 memcpy(pubdesc, relation->rd_pubdesc, sizeof(PublicationDesc));
5836 return;
5837 }
5838
5839 memset(pubdesc, 0, sizeof(PublicationDesc));
5840 pubdesc->rf_valid_for_update = true;
5841 pubdesc->rf_valid_for_delete = true;
5842 pubdesc->cols_valid_for_update = true;
5843 pubdesc->cols_valid_for_delete = true;
5844 pubdesc->gencols_valid_for_update = true;
5845 pubdesc->gencols_valid_for_delete = true;
5846
5847 /* Fetch the publication membership info. */
5849 schemaid = RelationGetNamespace(relation);
5851
5852 if (relation->rd_rel->relispartition)
5853 {
5855
5856 /* Add publications that the ancestors are in too. */
5857 ancestors = get_partition_ancestors(relid);
5858 last_ancestor_relid = llast_oid(ancestors);
5859
5860 foreach(lc, ancestors)
5861 {
5863
5869 }
5870
5871 /*
5872 * Only the top-most ancestor can appear in the EXCEPT clause.
5873 * Therefore, for a partition, exclusion must be evaluated at the
5874 * top-most ancestor.
5875 */
5877 }
5878 else
5879 {
5880 /*
5881 * For a regular table or a root partitioned table, check exclusion on
5882 * table itself.
5883 */
5885 }
5886
5890 exceptpuboids));
5891 foreach(lc, puboids)
5892 {
5893 Oid pubid = lfirst_oid(lc);
5894 HeapTuple tup;
5897 bool invalid_gen_col;
5898
5900
5901 if (!HeapTupleIsValid(tup))
5902 elog(ERROR, "cache lookup failed for publication %u", pubid);
5903
5905
5906 pubdesc->pubactions.pubinsert |= pubform->pubinsert;
5907 pubdesc->pubactions.pubupdate |= pubform->pubupdate;
5908 pubdesc->pubactions.pubdelete |= pubform->pubdelete;
5909 pubdesc->pubactions.pubtruncate |= pubform->pubtruncate;
5910
5911 /*
5912 * Check if all columns referenced in the filter expression are part
5913 * of the REPLICA IDENTITY index or not.
5914 *
5915 * If the publication is FOR ALL TABLES then it means the table has no
5916 * row filters and we can skip the validation.
5917 */
5918 if (!pubform->puballtables &&
5919 (pubform->pubupdate || pubform->pubdelete) &&
5920 pub_rf_contains_invalid_column(pubid, relation, ancestors,
5921 pubform->pubviaroot))
5922 {
5923 if (pubform->pubupdate)
5924 pubdesc->rf_valid_for_update = false;
5925 if (pubform->pubdelete)
5926 pubdesc->rf_valid_for_delete = false;
5927 }
5928
5929 /*
5930 * Check if all columns are part of the REPLICA IDENTITY index or not.
5931 *
5932 * Check if all generated columns included in the REPLICA IDENTITY are
5933 * published.
5934 */
5935 if ((pubform->pubupdate || pubform->pubdelete) &&
5936 pub_contains_invalid_column(pubid, relation, ancestors,
5937 pubform->pubviaroot,
5938 pubform->pubgencols,
5941 {
5942 if (pubform->pubupdate)
5943 {
5944 pubdesc->cols_valid_for_update = !invalid_column_list;
5945 pubdesc->gencols_valid_for_update = !invalid_gen_col;
5946 }
5947
5948 if (pubform->pubdelete)
5949 {
5950 pubdesc->cols_valid_for_delete = !invalid_column_list;
5951 pubdesc->gencols_valid_for_delete = !invalid_gen_col;
5952 }
5953 }
5954
5956
5957 /*
5958 * If we know everything is replicated and the row filter is invalid
5959 * for update and delete, there is no point to check for other
5960 * publications.
5961 */
5962 if (pubdesc->pubactions.pubinsert && pubdesc->pubactions.pubupdate &&
5963 pubdesc->pubactions.pubdelete && pubdesc->pubactions.pubtruncate &&
5964 !pubdesc->rf_valid_for_update && !pubdesc->rf_valid_for_delete)
5965 break;
5966
5967 /*
5968 * If we know everything is replicated and the column list is invalid
5969 * for update and delete, there is no point to check for other
5970 * publications.
5971 */
5972 if (pubdesc->pubactions.pubinsert && pubdesc->pubactions.pubupdate &&
5973 pubdesc->pubactions.pubdelete && pubdesc->pubactions.pubtruncate &&
5974 !pubdesc->cols_valid_for_update && !pubdesc->cols_valid_for_delete)
5975 break;
5976
5977 /*
5978 * If we know everything is replicated and replica identity has an
5979 * unpublished generated column, there is no point to check for other
5980 * publications.
5981 */
5982 if (pubdesc->pubactions.pubinsert && pubdesc->pubactions.pubupdate &&
5983 pubdesc->pubactions.pubdelete && pubdesc->pubactions.pubtruncate &&
5984 !pubdesc->gencols_valid_for_update &&
5985 !pubdesc->gencols_valid_for_delete)
5986 break;
5987 }
5988
5989 if (relation->rd_pubdesc)
5990 {
5991 pfree(relation->rd_pubdesc);
5992 relation->rd_pubdesc = NULL;
5993 }
5994
5995 /* Now save copy of the descriptor in the relcache entry. */
5998 memcpy(relation->rd_pubdesc, pubdesc, sizeof(PublicationDesc));
6000}
#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:2266
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:369

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:106
static Datum Int16GetDatum(int16 X)
Definition postgres.h:172
#define RelationGetNumberOfAttributes(relation)
Definition rel.h:522
static void CheckNNConstraintFetch(Relation relation)
Definition relcache.c:4603
static void AttrDefaultFetch(Relation relation, int ndef)
Definition relcache.c:4507
#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 6922 of file relcache.c.

6923{
6925}
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 6897 of file relcache.c.

6898{
6901
6902 if (DatabasePath)
6903 snprintf(localinitfname, sizeof(localinitfname), "%s/%s",
6905 snprintf(sharedinitfname, sizeof(sharedinitfname), "global/%s",
6907
6909
6910 /*
6911 * The files might not be there if no backend has been started since the
6912 * last removal. But complain about failures other than ENOENT with
6913 * ERROR. Fortunately, it's not too late to abort the transaction if we
6914 * can't get rid of the would-be-obsolete init file.
6915 */
6916 if (DatabasePath)
6919}
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:6994

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

6938{
6939 const char *tblspcdir = PG_TBLSPC_DIR;
6940 DIR *dir;
6941 struct dirent *de;
6942 char path[MAXPGPATH + sizeof(PG_TBLSPC_DIR) + sizeof(TABLESPACE_VERSION_DIRECTORY)];
6943
6944 snprintf(path, sizeof(path), "global/%s",
6946 unlink_initfile(path, LOG);
6947
6948 /* Scan everything in the default tablespace */
6950
6951 /* Scan the tablespace link directory to find non-default tablespaces */
6952 dir = AllocateDir(tblspcdir);
6953
6954 while ((de = ReadDirExtended(dir, tblspcdir, LOG)) != NULL)
6955 {
6956 if (strspn(de->d_name, "0123456789") == strlen(de->d_name))
6957 {
6958 /* Scan the tablespace dir for per-database dirs */
6959 snprintf(path, sizeof(path), "%s/%s/%s",
6962 }
6963 }
6964
6965 FreeDir(dir);
6966}
#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:6970
#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 6970 of file relcache.c.

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

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

Referenced by RelationCacheInitFileRemove().

◆ RelationCacheInitialize()

void RelationCacheInitialize ( void  )

Definition at line 4008 of file relcache.c.

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

4055{
4057
4058 /*
4059 * relation mapper needs initialized too
4060 */
4062
4063 /*
4064 * In bootstrap mode, the shared catalogs aren't there yet anyway, so do
4065 * nothing.
4066 */
4068 return;
4069
4070 /*
4071 * switch to cache memory context
4072 */
4074
4075 /*
4076 * Try to load the shared relcache cache file. If unsuccessful, bootstrap
4077 * the cache with pre-made descriptors for the critical shared catalogs.
4078 */
4079 if (!load_relcache_init_file(true))
4080 {
4081 formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
4083 formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
4085 formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
4087 formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
4089 formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
4091 formrdesc("pg_parameter_acl", ParameterAclRelation_Rowtype_Id, true,
4093
4094#define NUM_CRITICAL_SHARED_RELS 6 /* fix if you change list above */
4095 }
4096
4098}
static bool load_relcache_init_file(bool shared)
Definition relcache.c:6202
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:1889
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 4115 of file relcache.c.

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

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

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

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

2551{
2553 Assert(!relation->rd_isnailed);
2554
2555 /*
2556 * Relations created in the same transaction must never be removed, see
2557 * RelationFlushRelation.
2558 */
2562
2563 /* first mark it as invalid */
2565
2566 /* Remove it from the hash table */
2567 RelationCacheDelete(relation);
2568
2569 /* And release storage */
2570 RelationDestroyRelation(relation, false);
2571}
#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 2224 of file relcache.c.

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

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

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

2205{
2206 Assert(rel->rd_refcnt > 0);
2207 rel->rd_refcnt -= 1;
2210}
static void ResourceOwnerForgetRelationRef(ResourceOwner owner, Relation rel)
Definition relcache.c:2177
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 2443 of file relcache.c.

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

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

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

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

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

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

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

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

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

4744{
4745 List *result;
4749 HeapTuple htup;
4750 List *oldlist;
4752
4753 /* Quick exit if we already computed the list. */
4754 if (relation->rd_fkeyvalid)
4755 return relation->rd_fkeylist;
4756
4757 /*
4758 * We build the list we intend to return (in the caller's context) while
4759 * doing the scan. After successfully completing the scan, we copy that
4760 * list into the relcache entry. This avoids cache-context memory leakage
4761 * if we get some sort of error partway through.
4762 */
4763 result = NIL;
4764
4765 /* Prepare to scan pg_constraint for entries having conrelid = this rel. */
4770
4773 NULL, 1, &skey);
4774
4776 {
4777 Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(htup);
4778 ForeignKeyCacheInfo *info;
4779
4780 /* consider only foreign keys */
4781 if (constraint->contype != CONSTRAINT_FOREIGN)
4782 continue;
4783
4785 info->conoid = constraint->oid;
4786 info->conrelid = constraint->conrelid;
4787 info->confrelid = constraint->confrelid;
4788 info->conenforced = constraint->conenforced;
4789
4790 DeconstructFkConstraintRow(htup, &info->nkeys,
4791 info->conkey,
4792 info->confkey,
4793 info->conpfeqop,
4794 NULL, NULL, NULL, NULL);
4795
4796 /* Add FK's node to the result list */
4797 result = lappend(result, info);
4798 }
4799
4802
4803 /* Now save a copy of the completed list in the relcache entry. */
4805 oldlist = relation->rd_fkeylist;
4806 relation->rd_fkeylist = copyObject(result);
4807 relation->rd_fkeyvalid = true;
4809
4810 /* Don't leak the old list, if there is one */
4812
4813 return result;
4814}
#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 5588 of file relcache.c.

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

6024{
6026 bytea **opts = relation->rd_opcoptions;
6027 Oid relid = RelationGetRelid(relation);
6028 int natts = RelationGetNumberOfAttributes(relation); /* XXX
6029 * IndexRelationGetNumberOfKeyAttributes */
6030 int i;
6031
6032 /* Try to copy cached options. */
6033 if (opts)
6034 return copy ? CopyIndexAttOptions(opts, natts) : opts;
6035
6036 /* Get and parse opclass options. */
6037 opts = palloc0_array(bytea *, natts);
6038
6039 for (i = 0; i < natts; i++)
6040 {
6042 {
6043 Datum attoptions = get_attoptions(relid, i + 1);
6044
6045 opts[i] = index_opclass_options(relation, i + 1, attoptions, false);
6046
6047 if (attoptions != (Datum) 0)
6048 pfree(DatumGetPointer(attoptions));
6049 }
6050 }
6051
6052 /* Copy parsed options to the cache. */
6054 relation->rd_opcoptions = CopyIndexAttOptions(opts, natts);
6056
6057 if (copy)
6058 return opts;
6059
6060 for (i = 0; i < natts; i++)
6061 {
6062 if (opts[i])
6063 pfree(opts[i]);
6064 }
6065
6066 pfree(opts);
6067
6068 return relation->rd_opcoptions;
6069}
#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:1196
static bytea ** CopyIndexAttOptions(bytea **srcopts, int natts)
Definition relcache.c:6003

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

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

5110{
5111 List *result;
5113 bool isnull;
5114 char *exprsString;
5116
5117 /* Quick exit if we already computed the result. */
5118 if (relation->rd_indexprs)
5119 return copyObject(relation->rd_indexprs);
5120
5121 /* Quick exit if there is nothing to do. */
5122 if (relation->rd_indextuple == NULL ||
5124 return NIL;
5125
5126 /*
5127 * We build the tree we intend to return in the caller's context. After
5128 * successfully completing the work, we copy it into the relcache entry.
5129 * This avoids problems if we get some sort of error partway through.
5130 */
5134 &isnull);
5135 Assert(!isnull);
5139
5140 /*
5141 * Run the expressions through eval_const_expressions. This is not just an
5142 * optimization, but is necessary, because the planner will be comparing
5143 * them to similarly-processed qual clauses, and may fail to detect valid
5144 * matches without this. We must not use canonicalize_qual, however,
5145 * since these aren't qual expressions.
5146 */
5148
5149 /* May as well fix opfuncids too */
5151
5152 /* Now save a copy of the completed tree in the relcache entry. */
5154 relation->rd_indexprs = copyObject(result);
5156
5157 return result;
5158}
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition clauses.c:2516
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 4848 of file relcache.c.

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

5223{
5224 List *result;
5226 bool isnull;
5227 char *predString;
5229
5230 /* Quick exit if we already computed the result. */
5231 if (relation->rd_indpred)
5232 return copyObject(relation->rd_indpred);
5233
5234 /* Quick exit if there is nothing to do. */
5235 if (relation->rd_indextuple == NULL ||
5237 return NIL;
5238
5239 /*
5240 * We build the tree we intend to return in the caller's context. After
5241 * successfully completing the work, we copy it into the relcache entry.
5242 * This avoids problems if we get some sort of error partway through.
5243 */
5247 &isnull);
5248 Assert(!isnull);
5252
5253 /*
5254 * Run the expression through const-simplification and canonicalization.
5255 * This is not just an optimization, but is necessary, because the planner
5256 * will be comparing it to similarly-processed qual clauses, and may fail
5257 * to detect valid matches without this. This must match the processing
5258 * done to qual clauses in preprocess_expression()! (We can skip the
5259 * stuff involving subqueries, however, since we don't allow any in index
5260 * predicates.)
5261 */
5263
5264 result = (List *) canonicalize_qual((Expr *) result, false);
5265
5266 /* Also convert to implicit-AND format */
5268
5269 /* May as well fix opfuncids too */
5271
5272 /* Now save a copy of the completed tree in the relcache entry. */
5274 relation->rd_indpred = copyObject(result);
5276
5277 return result;
5278}
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 5059 of file relcache.c.

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

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

2147{
2150}
char * get_qualified_objname(Oid nspid, char *objname)
Definition lsyscache.c:3720

References get_qualified_objname(), RelationGetNamespace, and RelationGetRelationName.

Referenced by check_publication_add_relation().

◆ RelationGetReplicaIndex()

Oid RelationGetReplicaIndex ( Relation  relation)

Definition at line 5084 of file relcache.c.

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

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

4990{
4994 HeapTuple htup;
4995 List *result;
4996 List *oldlist;
4998
4999 /* Quick exit if we already computed the list. */
5000 if (relation->rd_statvalid != 0)
5001 return list_copy(relation->rd_statlist);
5002
5003 /*
5004 * We build the list we intend to return (in the caller's context) while
5005 * doing the scan. After successfully completing the scan, we copy that
5006 * list into the relcache entry. This avoids cache-context memory leakage
5007 * if we get some sort of error partway through.
5008 */
5009 result = NIL;
5010
5011 /*
5012 * Prepare to scan pg_statistic_ext for entries having stxrelid = this
5013 * rel.
5014 */
5019
5022 NULL, 1, &skey);
5023
5025 {
5026 Oid oid = ((Form_pg_statistic_ext) GETSTRUCT(htup))->oid;
5027
5028 result = lappend_oid(result, oid);
5029 }
5030
5032
5034
5035 /* Sort the result list into OID order, per API spec. */
5037
5038 /* Now save a copy of the completed list in the relcache entry. */
5040 oldlist = relation->rd_statlist;
5041 relation->rd_statlist = list_copy(result);
5042
5043 relation->rd_statvalid = true;
5045
5046 /* Don't leak the old list, if there is one */
5048
5049 return result;
5050}
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 2093 of file relcache.c.

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

6858{
6863 {
6864 /*
6865 * If this Assert fails, we don't need the applicable special case
6866 * anymore.
6867 */
6869 return true;
6870 }
6872}
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 1440 of file relcache.c.

1441{
1442 HeapTuple tuple;
1447 bool isnull;
1452 MemoryContext oldcontext;
1453 int indnatts;
1454 int indnkeyatts;
1455 uint16 amsupport;
1456
1457 /*
1458 * Make a copy of the pg_index entry for the index. Since pg_index
1459 * contains variable-length and possibly-null fields, we have to do this
1460 * honestly rather than just treating it as a Form_pg_index struct.
1461 */
1464 if (!HeapTupleIsValid(tuple))
1465 elog(ERROR, "cache lookup failed for index %u",
1466 RelationGetRelid(relation));
1468 relation->rd_indextuple = heap_copytuple(tuple);
1469 relation->rd_index = (Form_pg_index) GETSTRUCT(relation->rd_indextuple);
1470 MemoryContextSwitchTo(oldcontext);
1471 ReleaseSysCache(tuple);
1472
1473 /*
1474 * Look up the index's access method, save the OID of its handler function
1475 */
1476 Assert(relation->rd_rel->relam != InvalidOid);
1477 tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(relation->rd_rel->relam));
1478 if (!HeapTupleIsValid(tuple))
1479 elog(ERROR, "cache lookup failed for access method %u",
1480 relation->rd_rel->relam);
1481 aform = (Form_pg_am) GETSTRUCT(tuple);
1482 relation->rd_amhandler = aform->amhandler;
1483 ReleaseSysCache(tuple);
1484
1487 elog(ERROR, "relnatts disagrees with indnatts for index %u",
1488 RelationGetRelid(relation));
1490
1491 /*
1492 * Make the private context to hold index access info. The reason we need
1493 * a context, and not just a couple of pallocs, is so that we won't leak
1494 * any subsidiary info attached to fmgr lookup records.
1495 */
1497 "index info",
1499 relation->rd_indexcxt = indexcxt;
1501 RelationGetRelationName(relation));
1502
1503 /*
1504 * Now we can fetch the index AM's API struct
1505 */
1506 InitIndexAmRoutine(relation);
1507
1508 /*
1509 * Allocate arrays to hold data. Opclasses are not used for included
1510 * columns, so allocate them for indnkeyatts only.
1511 */
1512 relation->rd_opfamily = (Oid *)
1514 relation->rd_opcintype = (Oid *)
1516
1517 amsupport = relation->rd_indam->amsupport;
1518 if (amsupport > 0)
1519 {
1520 int nsupport = indnatts * amsupport;
1521
1522 relation->rd_support = (RegProcedure *)
1524 relation->rd_supportinfo = (FmgrInfo *)
1526 }
1527 else
1528 {
1529 relation->rd_support = NULL;
1530 relation->rd_supportinfo = NULL;
1531 }
1532
1533 relation->rd_indcollation = (Oid *)
1535
1536 relation->rd_indoption = (int16 *)
1538
1539 /*
1540 * indcollation cannot be referenced directly through the C struct,
1541 * because it comes after the variable-width indkey field. Must extract
1542 * the datum the hard way...
1543 */
1547 &isnull);
1548 Assert(!isnull);
1550 memcpy(relation->rd_indcollation, indcoll->values, indnkeyatts * sizeof(Oid));
1551
1552 /*
1553 * indclass cannot be referenced directly through the C struct, because it
1554 * comes after the variable-width indkey field. Must extract the datum
1555 * the hard way...
1556 */
1560 &isnull);
1561 Assert(!isnull);
1563
1564 /*
1565 * Fill the support procedure OID array, as well as the info about
1566 * opfamilies and opclass input types. (aminfo and supportinfo are left
1567 * as zeroes, and are filled on-the-fly when used)
1568 */
1570 relation->rd_opfamily, relation->rd_opcintype,
1571 amsupport, indnkeyatts);
1572
1573 /*
1574 * Similarly extract indoption and copy it to the cache entry
1575 */
1579 &isnull);
1580 Assert(!isnull);
1582 memcpy(relation->rd_indoption, indoption->values, indnkeyatts * sizeof(int16));
1583
1584 (void) RelationGetIndexAttOptions(relation, false);
1585
1586 /*
1587 * expressions, predicate, exclusion caches will be filled later
1588 */
1589 relation->rd_indexprs = NIL;
1590 relation->rd_indpred = NIL;
1591 relation->rd_exclops = NULL;
1592 relation->rd_exclprocs = NULL;
1593 relation->rd_exclstrats = NULL;
1594 relation->rd_amcache = NULL;
1595}
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:1611
Definition c.h:874

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

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

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

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

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

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:4472
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 2589 of file relcache.c.

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

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

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

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

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

2178{
2180}
static const ResourceOwnerDesc relref_resowner_desc
Definition relcache.c:2161
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 2172 of file relcache.c.

2173{
2175}
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 7011 of file relcache.c.

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

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

◆ ResOwnerReleaseRelation()

static void ResOwnerReleaseRelation ( Datum  res)
static

Definition at line 7019 of file relcache.c.

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

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

6995{
6996 if (unlink(initfilename) < 0)
6997 {
6998 /* It might not be there, but log any error other than ENOENT */
6999 if (errno != ENOENT)
7000 ereport(elevel,
7002 errmsg("could not remove cache file \"%s\": %m",
7003 initfilename)));
7004 }
7005}
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 6834 of file relcache.c.

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

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

Definition at line 2161 of file relcache.c.

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

Referenced by ResourceOwnerForgetRelationRef(), and ResourceOwnerRememberRelationRef().