From a3b51f49266bd8d085a3de4a4950353957503001 Mon Sep 17 00:00:00 2001 From: David Geier Date: Wed, 2 Sep 2026 14:06:21 +0200 Subject: [PATCH v1 1/8] Move RelationData to new include --- src/include/utils/rel.h | 228 +---------------------------- src/include/utils/rel_internal.h | 244 +++++++++++++++++++++++++++++++ 2 files changed, 245 insertions(+), 227 deletions(-) create mode 100644 src/include/utils/rel_internal.h diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index 41ab4586c6b..5dfbbc1715b 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -28,233 +28,7 @@ #include "storage/smgr.h" #include "utils/relcache.h" #include "utils/reltrigger.h" - - -/* - * LockRelId and LockInfo really belong to lmgr.h, but it's more convenient - * to declare them here so we can have a LockInfoData field in a Relation. - */ - -typedef struct LockRelId -{ - Oid relId; /* a relation identifier */ - Oid dbId; /* a database identifier */ -} LockRelId; - -typedef struct LockInfoData -{ - LockRelId lockRelId; -} LockInfoData; - -typedef LockInfoData *LockInfo; - -/* - * Here are the contents of a relation cache entry. - */ - -typedef struct RelationData -{ - RelFileLocator rd_locator; /* relation physical identifier */ - SMgrRelation rd_smgr; /* cached file handle, or NULL */ - int rd_refcnt; /* reference count */ - ProcNumber rd_backend; /* owning backend's proc number, if temp rel */ - 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 or its storage was created before the - * current top transaction. (IndexStmt.oldNumber leads to the case of a new - * rel with an old rd_locator.) rd_firstRelfilelocatorSubid is the ID of the - * highest subtransaction an rd_locator change has survived into or zero if - * rd_locator matches the value it had at the start of the current top - * transaction. (Rolling back the subtransaction that - * rd_firstRelfilelocatorSubid denotes would restore rd_locator to the value it - * had at the start of the current top transaction. Rolling back any - * lower subtransaction would not.) Their accuracy is critical to - * RelationNeedsWAL(). - * - * rd_newRelfilelocatorSubid is the ID of the highest subtransaction the - * most-recent relfilenumber change has survived into or zero if not changed - * in the current transaction (or we have forgotten changing it). This - * field is accurate when non-zero, but it can be zero when a relation has - * multiple new relfilenumbers 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_newRelfilelocatorSubid is now forgotten - * - * If every rd_*Subid field is zero, they are read-only outside - * relcache.c. Files that trigger rd_locator changes by updating - * pg_class.reltablespace and/or pg_class.relfilenode call - * RelationAssumeNewRelfilelocator() to update rd_*Subid. - * - * rd_droppedSubid is the ID of the highest subtransaction that a drop of - * the rel has survived into. In entries visible outside relcache.c, this - * is always zero. - */ - SubTransactionId rd_createSubid; /* rel was created in current xact */ - SubTransactionId rd_newRelfilelocatorSubid; /* highest subxact changing - * rd_locator to current value */ - SubTransactionId rd_firstRelfilelocatorSubid; /* highest subxact - * changing rd_locator to - * any value */ - SubTransactionId rd_droppedSubid; /* dropped with another Subid set */ - - 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 */ - - /* data managed by RelationGetPartitionKey: */ - PartitionKey rd_partkey; /* partition key, or NULL */ - MemoryContext rd_partkeycxt; /* private context for rd_partkey, if any */ - - /* data managed by RelationGetPartitionDesc: */ - PartitionDesc rd_partdesc; /* partition descriptor, or NULL */ - MemoryContext rd_pdcxt; /* private context for rd_partdesc, if any */ - - /* Same as above, for partdescs that omit detached partitions */ - PartitionDesc rd_partdesc_nodetached; /* partdesc w/o detached parts */ - MemoryContext rd_pddcxt; /* for rd_partdesc_nodetached, if any */ - - /* - * pg_inherits.xmin of the partition that was excluded in - * rd_partdesc_nodetached. This informs a future user of that partdesc: - * if this value is not in progress for the active snapshot, then the - * partdesc can be used, otherwise they have to build a new one. (This - * matches what find_inheritance_children_extended would do). - */ - TransactionId rd_partdesc_nodetached_xmin; - - /* data managed by RelationGetPartitionQual: */ - 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 (deferrable?) primary key, if any */ - bool rd_ispkdeferrable; /* is rd_pkindex a deferrable PK? */ - 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: */ - bool rd_attrsvalid; /* are bitmaps of attrs valid? */ - 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 */ - Bitmapset *rd_hotblockingattr; /* cols blocking HOT update */ - Bitmapset *rd_summarizedattr; /* cols indexed by summarizing indexes */ - - PublicationDesc *rd_pubdesc; /* publication descriptor, or NULL */ - - /* - * 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: */ - const 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 */ - struct 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 */ - bytea **rd_opcoptions; /* parsed opclass-specific options */ - - /* - * 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 */ - - bool pgstat_enabled; /* should relation stats be counted */ - /* use "struct" here to avoid needing to include pgstat.h: */ - struct PgStat_RelationStatus *pgstat_info; /* statistics collection area */ -} RelationData; - +#include "utils/rel_internal.h" /* * ForeignKeyCacheInfo diff --git a/src/include/utils/rel_internal.h b/src/include/utils/rel_internal.h new file mode 100644 index 00000000000..675252a641e --- /dev/null +++ b/src/include/utils/rel_internal.h @@ -0,0 +1,244 @@ +#ifndef REL_INTERNAL_H +#define REL_INTERNAL_H + +#include "access/tupdesc.h" +#include "access/xlog.h" +#include "catalog/catalog.h" +#include "catalog/pg_class.h" +#include "catalog/pg_index.h" +#include "catalog/pg_publication.h" +#include "nodes/bitmapset.h" +#include "partitioning/partdefs.h" +#include "rewrite/prs2lock.h" +#include "storage/block.h" +#include "storage/relfilelocator.h" +#include "storage/smgr.h" +#include "utils/relcache.h" +#include "utils/reltrigger.h" + +/* + * LockRelId and LockInfo really belong to lmgr.h, but it's more convenient + * to declare them here so we can have a LockInfoData field in a Relation. + */ + +typedef struct LockRelId +{ + Oid relId; /* a relation identifier */ + Oid dbId; /* a database identifier */ +} LockRelId; + +typedef struct LockInfoData +{ + LockRelId lockRelId; +} LockInfoData; + +typedef LockInfoData *LockInfo; + +/* + * Here are the contents of a relation cache entry. + */ + +typedef struct RelationData +{ + RelFileLocator rd_locator; /* relation physical identifier */ + SMgrRelation rd_smgr; /* cached file handle, or NULL */ + int rd_refcnt; /* reference count */ + ProcNumber rd_backend; /* owning backend's proc number, if temp rel */ + 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 or its storage was created before the + * current top transaction. (IndexStmt.oldNumber leads to the case of a new + * rel with an old rd_locator.) rd_firstRelfilelocatorSubid is the ID of the + * highest subtransaction an rd_locator change has survived into or zero if + * rd_locator matches the value it had at the start of the current top + * transaction. (Rolling back the subtransaction that + * rd_firstRelfilelocatorSubid denotes would restore rd_locator to the value it + * had at the start of the current top transaction. Rolling back any + * lower subtransaction would not.) Their accuracy is critical to + * RelationNeedsWAL(). + * + * rd_newRelfilelocatorSubid is the ID of the highest subtransaction the + * most-recent relfilenumber change has survived into or zero if not changed + * in the current transaction (or we have forgotten changing it). This + * field is accurate when non-zero, but it can be zero when a relation has + * multiple new relfilenumbers 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_newRelfilelocatorSubid is now forgotten + * + * If every rd_*Subid field is zero, they are read-only outside + * relcache.c. Files that trigger rd_locator changes by updating + * pg_class.reltablespace and/or pg_class.relfilenode call + * RelationAssumeNewRelfilelocator() to update rd_*Subid. + * + * rd_droppedSubid is the ID of the highest subtransaction that a drop of + * the rel has survived into. In entries visible outside relcache.c, this + * is always zero. + */ + SubTransactionId rd_createSubid; /* rel was created in current xact */ + SubTransactionId rd_newRelfilelocatorSubid; /* highest subxact changing + * rd_locator to current value */ + SubTransactionId rd_firstRelfilelocatorSubid; /* highest subxact + * changing rd_locator to + * any value */ + SubTransactionId rd_droppedSubid; /* dropped with another Subid set */ + + 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 */ + + /* data managed by RelationGetPartitionKey: */ + PartitionKey rd_partkey; /* partition key, or NULL */ + MemoryContext rd_partkeycxt; /* private context for rd_partkey, if any */ + + /* data managed by RelationGetPartitionDesc: */ + PartitionDesc rd_partdesc; /* partition descriptor, or NULL */ + MemoryContext rd_pdcxt; /* private context for rd_partdesc, if any */ + + /* Same as above, for partdescs that omit detached partitions */ + PartitionDesc rd_partdesc_nodetached; /* partdesc w/o detached parts */ + MemoryContext rd_pddcxt; /* for rd_partdesc_nodetached, if any */ + + /* + * pg_inherits.xmin of the partition that was excluded in + * rd_partdesc_nodetached. This informs a future user of that partdesc: + * if this value is not in progress for the active snapshot, then the + * partdesc can be used, otherwise they have to build a new one. (This + * matches what find_inheritance_children_extended would do). + */ + TransactionId rd_partdesc_nodetached_xmin; + + /* data managed by RelationGetPartitionQual: */ + 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 (deferrable?) primary key, if any */ + bool rd_ispkdeferrable; /* is rd_pkindex a deferrable PK? */ + 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: */ + bool rd_attrsvalid; /* are bitmaps of attrs valid? */ + 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 */ + Bitmapset *rd_hotblockingattr; /* cols blocking HOT update */ + Bitmapset *rd_summarizedattr; /* cols indexed by summarizing indexes */ + + PublicationDesc *rd_pubdesc; /* publication descriptor, or NULL */ + + /* + * 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: */ + const 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 */ + struct 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 */ + bytea **rd_opcoptions; /* parsed opclass-specific options */ + + /* + * 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 */ + + bool pgstat_enabled; /* should relation stats be counted */ + /* use "struct" here to avoid needing to include pgstat.h: */ + struct PgStat_RelationStatus *pgstat_info; /* statistics collection area */ +} RelationData; + +#endif /* REL_INTERNAL_H */ \ No newline at end of file -- 2.55.0