PostgreSQL数据库RelationAM——RelationData

RelationData是访问引擎中最重要的一个结构体,贯穿整个Relation访问的流程。const struct TableAmRoutine *rd_tableam用于存放该表的访问函数的结构体指针,见PostgreSQL数据库TableAM——Table Access Method。struct IndexAmRoutine *rd_indam;用于存放该表的索引访问函数的结构体指针。

/* Here are the contents of a relation cache entry. */typedef struct RelationData {RelFileNode rd_node;		/* relation physical identifier *//* use "struct" here to avoid needing to include smgr.h: */struct SMgrRelationData *rd_smgr;	/* cached file handle, or NULL */int			rd_refcnt;		/* reference count */BackendId	rd_backend;		/* owning backend id, if temporary relation */bool		rd_islocaltemp; /* rel is a temp rel of this session */bool		rd_isnailed;	/* rel is nailed in cache */bool		rd_isvalid;		/* relcache entry is valid */bool		rd_indexvalid;	/* is rd_indexlist valid? (also rd_pkindex and rd_replidindex) */bool		rd_statvalid;	/* is rd_statlist valid? *//*----------* rd_createSubid is the ID of the highest subtransaction the rel has* survived into; or zero if the rel was not created in the current top* transaction.  This can be now be relied on, whereas previously it could* be "forgotten" in earlier releases. Likewise, rd_newRelfilenodeSubid is* the ID of the highest subtransaction the relfilenode change has* survived into, or zero if not changed in the current transaction (or we* have forgotten changing it). rd_newRelfilenodeSubid can be forgotten* when a relation has multiple new relfilenodes within a single* transaction, with one of them occurring in a subsequently aborted* subtransaction, e.g.*		BEGIN;*		TRUNCATE t;*		SAVEPOINT save;*		TRUNCATE t;*		ROLLBACK TO save;*		-- rd_newRelfilenodeSubid is now forgotten*/SubTransactionId rd_createSubid;	/* rel was created in current xact */SubTransactionId rd_newRelfilenodeSubid;	/* new relfilenode assigned in current xact */Form_pg_class rd_rel;		/* RELATION tuple */TupleDesc	rd_att;			/* tuple descriptor */Oid			rd_id;			/* relation's object id */LockInfoData rd_lockInfo;	/* lock mgr's info for locking relation */RuleLock   *rd_rules;		/* rewrite rules */MemoryContext rd_rulescxt;	/* private memory cxt for rd_rules, if any */TriggerDesc *trigdesc;		/* Trigger info, or NULL if rel has none *//* use "struct" here to avoid needing to include rowsecurity.h: */struct RowSecurityDesc *rd_rsdesc;	/* row security policies, or NULL *//* data managed by RelationGetFKeyList: */List	   *rd_fkeylist;	/* list of ForeignKeyCacheInfo (see below) */bool		rd_fkeyvalid;	/* true if list has been computed */struct PartitionKeyData *rd_partkey;	/* partition key, or NULL */MemoryContext rd_partkeycxt;	/* private context for rd_partkey, if any */struct PartitionDescData *rd_partdesc;	/* partitions, or NULL */MemoryContext rd_pdcxt;		/* private context for rd_partdesc, if any */List	   *rd_partcheck;	/* partition CHECK quals */bool		rd_partcheckvalid;	/* true if list has been computed */MemoryContext rd_partcheckcxt;	/* private cxt for rd_partcheck, if any *//* data managed by RelationGetIndexList: */List	   *rd_indexlist;	/* list of OIDs of indexes on relation */Oid			rd_pkindex;		/* OID of primary key, if any */Oid			rd_replidindex; /* OID of replica identity index, if any *//* data managed by RelationGetStatExtList: */List	   *rd_statlist;	/* list of OIDs of extended stats *//* data managed by RelationGetIndexAttrBitmap: */Bitmapset  *rd_indexattr;	/* identifies columns used in indexes */Bitmapset  *rd_keyattr;		/* cols that can be ref'd by foreign keys */Bitmapset  *rd_pkattr;		/* cols included in primary key */Bitmapset  *rd_idattr;		/* included in replica identity index */PublicationActions *rd_pubactions;	/* publication actions *//* rd_options is set whenever rd_rel is loaded into the relcache entry.* Note that you can NOT look into rd_rel for this data.  NULL means "use* defaults". */bytea	   *rd_options;		/* parsed pg_class.reloptions *//* Oid of the handler for this relation. For an index this is a function* returning IndexAmRoutine, for table like relations a function returning* TableAmRoutine.  This is stored separately from rd_indam, rd_tableam as* its lookup requires syscache access, but during relcache bootstrap we* need to be able to initialize rd_tableam without syscache lookups. */Oid			rd_amhandler;	/* OID of index AM's handler function *//* Table access method. */const struct TableAmRoutine *rd_tableam;/* These are non-NULL only for an index relation: */Form_pg_index rd_index;		/* pg_index tuple describing this index *//* use "struct" here to avoid needing to include htup.h: */struct HeapTupleData *rd_indextuple;	/* all of pg_index tuple *//* index access support info (used only for an index relation)** Note: only default support procs for each opclass are cached, namely* those with lefttype and righttype equal to the opclass's opcintype. The* arrays are indexed by support function number, which is a sufficient* identifier given that restriction. */MemoryContext rd_indexcxt;	/* private memory cxt for this stuff *//* use "struct" here to avoid needing to include amapi.h: */struct IndexAmRoutine *rd_indam;	/* index AM's API struct */Oid		   *rd_opfamily;	/* OIDs of op families for each index col */Oid		   *rd_opcintype;	/* OIDs of opclass declared input data types */RegProcedure *rd_support;	/* OIDs of support procedures */FmgrInfo   *rd_supportinfo; /* lookup info for support procedures */int16	   *rd_indoption;	/* per-column AM-specific flags */List	   *rd_indexprs;	/* index expression trees, if any */List	   *rd_indpred;		/* index predicate tree, if any */Oid		   *rd_exclops;		/* OIDs of exclusion operators, if any */Oid		   *rd_exclprocs;	/* OIDs of exclusion ops' procs, if any */uint16	   *rd_exclstrats;	/* exclusion ops' strategy numbers, if any */Oid		   *rd_indcollation;	/* OIDs of index collations *//* rd_amcache is available for index and table AMs to cache private data* about the relation.  This must be just a cache since it may get reset* at any time (in particular, it will get reset by a relcache inval* message for the relation).  If used, it must point to a single memory* chunk palloc'd in CacheMemoryContext, or in rd_indexcxt for an index* relation.  A relcache reset will include freeing that chunk and setting* rd_amcache = NULL. */void	   *rd_amcache;		/* available for use by index/table AM *//* foreign-table support* rd_fdwroutine must point to a single memory chunk palloc'd in* CacheMemoryContext.  It will be freed and reset to NULL on a relcache* reset. *//* use "struct" here to avoid needing to include fdwapi.h: */struct FdwRoutine *rd_fdwroutine;	/* cached function pointers, or NULL *//** Hack for CLUSTER, rewriting ALTER TABLE, etc: when writing a new* version of a table, we need to make any toast pointers inserted into it* have the existing toast table's OID, not the OID of the transient toast* table.  If rd_toastoid isn't InvalidOid, it is the OID to place in* toast pointers inserted into this rel.  (Note it's set on the new* version of the main heap, not the toast table itself.)  This also* causes toast_save_datum() to try to preserve toast value OIDs.*/Oid			rd_toastoid;	/* Real TOAST table's OID, or InvalidOid *//* use "struct" here to avoid needing to include pgstat.h: */struct PgStat_TableStatus *pgstat_info; /* statistics collection area */
} RelationData;

获取RelationData

src/backend/utils/cache/relcache.c
RelationIdGetRelation首先从cache中查看是否已经有相应的reldexc存在,则返回。如果不存在,调用RelationBuildDesc在cache中创建一个并返回。

Relation RelationIdGetRelation(Oid relationId) {Relation	rd;/* Make sure we're in an xact, even if this ends up being a cache hit */Assert(IsTransactionState());/* first try to find reldesc in the cache */RelationIdCacheLookup(relationId, rd);if (RelationIsValid(rd)){RelationIncrementReferenceCount(rd);/* revalidate cache entry if necessary */if (!rd->rd_isvalid){/* Indexes only have a limited number of possible schema changes,* and we don't want to use the full-blown procedure because it's* a headache for indexes that reload itself depends on. */if (rd->rd_rel->relkind == RELKIND_INDEX || rd->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)RelationReloadIndexInfo(rd);elseRelationClearRelation(rd, true);/* Normally entries need to be valid here, but before the relcache* has been initialized, not enough infrastructure exists to* perform pg_class lookups. The structure of such entries doesn't* change, but we still want to update the rd_rel entry. So* rd_isvalid = false is left in place for a later lookup. */Assert(rd->rd_isvalid || (rd->rd_isnailed && !criticalRelcachesBuilt));}return rd;}/* no reldesc in the cache, so have RelationBuildDesc() build one and add it. */rd = RelationBuildDesc(relationId, true);if (RelationIsValid(rd)) RelationIncrementReferenceCount(rd);return rd;
}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部