#ifndef REL_H
#define REL_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"
typedef struct LockRelId
{
Oid relId;
Oid dbId;
} LockRelId;
typedef struct LockInfoData
{
LockRelId lockRelId;
} LockInfoData;
typedef LockInfoData *LockInfo;
typedef struct RelationData
{
RelFileLocator rd_locator;
SMgrRelation rd_smgr;
int rd_refcnt;
ProcNumber rd_backend;
bool rd_islocaltemp;
bool rd_isnailed;
bool rd_isvalid;
bool rd_indexvalid;
bool rd_statvalid;
SubTransactionId rd_createSubid;
SubTransactionId rd_newRelfilelocatorSubid;
SubTransactionId rd_firstRelfilelocatorSubid;
SubTransactionId rd_droppedSubid;
Form_pg_class rd_rel;
TupleDesc rd_att;
Oid rd_id;
LockInfoData rd_lockInfo;
RuleLock *rd_rules;
MemoryContext rd_rulescxt;
TriggerDesc *trigdesc;
struct RowSecurityDesc *rd_rsdesc;
List *rd_fkeylist;
bool rd_fkeyvalid;
PartitionKey rd_partkey;
MemoryContext rd_partkeycxt;
PartitionDesc rd_partdesc;
MemoryContext rd_pdcxt;
PartitionDesc rd_partdesc_nodetached;
MemoryContext rd_pddcxt;
TransactionId rd_partdesc_nodetached_xmin;
List *rd_partcheck;
bool rd_partcheckvalid;
MemoryContext rd_partcheckcxt;
List *rd_indexlist;
Oid rd_pkindex;
bool rd_ispkdeferrable;
Oid rd_replidindex;
List *rd_statlist;
bool rd_attrsvalid;
Bitmapset *rd_keyattr;
Bitmapset *rd_pkattr;
Bitmapset *rd_idattr;
Bitmapset *rd_hotblockingattr;
Bitmapset *rd_summarizedattr;
PublicationDesc *rd_pubdesc;
bytea *rd_options;
Oid rd_amhandler;
const struct TableAmRoutine *rd_tableam;
Form_pg_index rd_index;
struct HeapTupleData *rd_indextuple;
MemoryContext rd_indexcxt;
struct IndexAmRoutine *rd_indam;
Oid *rd_opfamily;
Oid *rd_opcintype;
RegProcedure *rd_support;
struct FmgrInfo *rd_supportinfo;
int16 *rd_indoption;
List *rd_indexprs;
List *rd_indpred;
Oid *rd_exclops;
Oid *rd_exclprocs;
uint16 *rd_exclstrats;
Oid *rd_indcollation;
bytea **rd_opcoptions;
void *rd_amcache;
struct FdwRoutine *rd_fdwroutine;
Oid rd_toastoid;
bool pgstat_enabled;
struct PgStat_TableStatus *pgstat_info;
} RelationData;
typedef struct ForeignKeyCacheInfo
{
pg_node_attr(no_equal, no_read, no_query_jumble)
NodeTag type;
Oid conoid;
Oid conrelid;
Oid confrelid;
int nkeys;
AttrNumber conkey[INDEX_MAX_KEYS] pg_node_attr(array_size(nkeys));
AttrNumber confkey[INDEX_MAX_KEYS] pg_node_attr(array_size(nkeys));
Oid conpfeqop[INDEX_MAX_KEYS] pg_node_attr(array_size(nkeys));
} ForeignKeyCacheInfo;
typedef struct AutoVacOpts
{
bool enabled;
int vacuum_threshold;
int vacuum_ins_threshold;
int analyze_threshold;
int vacuum_cost_limit;
int freeze_min_age;
int freeze_max_age;
int freeze_table_age;
int multixact_freeze_min_age;
int multixact_freeze_max_age;
int multixact_freeze_table_age;
int log_min_duration;
float8 vacuum_cost_delay;
float8 vacuum_scale_factor;
float8 vacuum_ins_scale_factor;
float8 analyze_scale_factor;
} AutoVacOpts;
typedef enum StdRdOptIndexCleanup
{
STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO = 0,
STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF,
STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON,
} StdRdOptIndexCleanup;
typedef struct StdRdOptions
{
int32 vl_len_;
int fillfactor;
int toast_tuple_target;
AutoVacOpts autovacuum;
bool user_catalog_table;
int parallel_workers;
StdRdOptIndexCleanup vacuum_index_cleanup;
bool vacuum_truncate;
} StdRdOptions;
#define HEAP_MIN_FILLFACTOR 10
#define HEAP_DEFAULT_FILLFACTOR 100
#define RelationGetToastTupleTarget(relation, defaulttarg) \
((relation)->rd_options ? \
((StdRdOptions *) (relation)->rd_options)->toast_tuple_target : (defaulttarg))
#define RelationGetFillFactor(relation, defaultff) \
((relation)->rd_options ? \
((StdRdOptions *) (relation)->rd_options)->fillfactor : (defaultff))
#define RelationGetTargetPageUsage(relation, defaultff) \
(BLCKSZ * RelationGetFillFactor(relation, defaultff) / 100)
#define RelationGetTargetPageFreeSpace(relation, defaultff) \
(BLCKSZ * (100 - RelationGetFillFactor(relation, defaultff)) / 100)
#define RelationIsUsedAsCatalogTable(relation) \
((relation)->rd_options && \
((relation)->rd_rel->relkind == RELKIND_RELATION || \
(relation)->rd_rel->relkind == RELKIND_MATVIEW) ? \
((StdRdOptions *) (relation)->rd_options)->user_catalog_table : false)
#define RelationGetParallelWorkers(relation, defaultpw) \
((relation)->rd_options ? \
((StdRdOptions *) (relation)->rd_options)->parallel_workers : (defaultpw))
typedef enum ViewOptCheckOption
{
VIEW_OPTION_CHECK_OPTION_NOT_SET,
VIEW_OPTION_CHECK_OPTION_LOCAL,
VIEW_OPTION_CHECK_OPTION_CASCADED,
} ViewOptCheckOption;
typedef struct ViewOptions
{
int32 vl_len_;
bool security_barrier;
bool security_invoker;
ViewOptCheckOption check_option;
} ViewOptions;
#define RelationIsSecurityView(relation) \
(AssertMacro(relation->rd_rel->relkind == RELKIND_VIEW), \
(relation)->rd_options ? \
((ViewOptions *) (relation)->rd_options)->security_barrier : false)
#define RelationHasSecurityInvoker(relation) \
(AssertMacro(relation->rd_rel->relkind == RELKIND_VIEW), \
(relation)->rd_options ? \
((ViewOptions *) (relation)->rd_options)->security_invoker : false)
#define RelationHasCheckOption(relation) \
(AssertMacro(relation->rd_rel->relkind == RELKIND_VIEW), \
(relation)->rd_options && \
((ViewOptions *) (relation)->rd_options)->check_option != \
VIEW_OPTION_CHECK_OPTION_NOT_SET)
#define RelationHasLocalCheckOption(relation) \
(AssertMacro(relation->rd_rel->relkind == RELKIND_VIEW), \
(relation)->rd_options && \
((ViewOptions *) (relation)->rd_options)->check_option == \
VIEW_OPTION_CHECK_OPTION_LOCAL)
#define RelationHasCascadedCheckOption(relation) \
(AssertMacro(relation->rd_rel->relkind == RELKIND_VIEW), \
(relation)->rd_options && \
((ViewOptions *) (relation)->rd_options)->check_option == \
VIEW_OPTION_CHECK_OPTION_CASCADED)
#define RelationIsValid(relation) PointerIsValid(relation)
#define InvalidRelation ((Relation) NULL)
#define RelationHasReferenceCountZero(relation) \
((bool)((relation)->rd_refcnt == 0))
#define RelationGetForm(relation) ((relation)->rd_rel)
#define RelationGetRelid(relation) ((relation)->rd_id)
#define RelationGetNumberOfAttributes(relation) ((relation)->rd_rel->relnatts)
#define IndexRelationGetNumberOfAttributes(relation) \
((relation)->rd_index->indnatts)
#define IndexRelationGetNumberOfKeyAttributes(relation) \
((relation)->rd_index->indnkeyatts)
#define RelationGetDescr(relation) ((relation)->rd_att)
#define RelationGetRelationName(relation) \
(NameStr((relation)->rd_rel->relname))
#define RelationGetNamespace(relation) \
((relation)->rd_rel->relnamespace)
#define RelationIsMapped(relation) \
(RELKIND_HAS_STORAGE((relation)->rd_rel->relkind) && \
((relation)->rd_rel->relfilenode == InvalidRelFileNumber))
#ifndef FRONTEND
static inline SMgrRelation
RelationGetSmgr(Relation rel)
{
if (unlikely(rel->rd_smgr == NULL))
{
rel->rd_smgr = smgropen(rel->rd_locator, rel->rd_backend);
smgrpin(rel->rd_smgr);
}
return rel->rd_smgr;
}
static inline void
RelationCloseSmgr(Relation relation)
{
if (relation->rd_smgr != NULL)
{
smgrunpin(relation->rd_smgr);
smgrclose(relation->rd_smgr);
relation->rd_smgr = NULL;
}
}
#endif
#define RelationGetTargetBlock(relation) \
( (relation)->rd_smgr != NULL ? (relation)->rd_smgr->smgr_targblock : InvalidBlockNumber )
#define RelationSetTargetBlock(relation, targblock) \
do { \
RelationGetSmgr(relation)->smgr_targblock = (targblock); \
} while (0)
#define RelationIsPermanent(relation) \
((relation)->rd_rel->relpersistence == RELPERSISTENCE_PERMANENT)
#define RelationNeedsWAL(relation) \
(RelationIsPermanent(relation) && (XLogIsNeeded() || \
(relation->rd_createSubid == InvalidSubTransactionId && \
relation->rd_firstRelfilelocatorSubid == InvalidSubTransactionId)))
#define RelationUsesLocalBuffers(relation) \
((relation)->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
#define RELATION_IS_LOCAL(relation) \
((relation)->rd_islocaltemp || \
(relation)->rd_createSubid != InvalidSubTransactionId)
#define RELATION_IS_OTHER_TEMP(relation) \
((relation)->rd_rel->relpersistence == RELPERSISTENCE_TEMP && \
!(relation)->rd_islocaltemp)
#define RelationIsScannable(relation) ((relation)->rd_rel->relispopulated)
#define RelationIsPopulated(relation) ((relation)->rd_rel->relispopulated)
#define RelationIsAccessibleInLogicalDecoding(relation) \
(XLogLogicalInfoActive() && \
RelationNeedsWAL(relation) && \
(IsCatalogRelation(relation) || RelationIsUsedAsCatalogTable(relation)))
#define RelationIsLogicallyLogged(relation) \
(XLogLogicalInfoActive() && \
RelationNeedsWAL(relation) && \
(relation)->rd_rel->relkind != RELKIND_FOREIGN_TABLE && \
!IsCatalogRelation(relation))
extern void RelationIncrementReferenceCount(Relation rel);
extern void RelationDecrementReferenceCount(Relation rel);
#endif