diff options
| author | Alexander Korotkov | 2024-04-08 08:23:28 +0000 |
|---|---|---|
| committer | Alexander Korotkov | 2024-04-08 08:23:28 +0000 |
| commit | 9bd99f4c26fe37b8ee2f199aa868a0e2fdba4c43 (patch) | |
| tree | acbadc21922045fa7f729f5c199e4e33c30e2541 /src/include | |
| parent | 6f3d8d5e7cc2f2e2367cd6da6f8affe98d1f5729 (diff) | |
Custom reloptions for table AM
Let table AM define custom reloptions for its tables. This allows specifying
AM-specific parameters by the WITH clause when creating a table.
The reloptions, which could be used outside of table AM, are now extracted
into the CommonRdOptions data structure. These options could be by decision
of table AM directly specified by a user or calculated in some way.
The new test module test_tam_options evaluates the ability to set up custom
reloptions and calculate fields of CommonRdOptions on their base.
The code may use some parts from prior work by Hao Wu.
Discussion: https://postgr.es/m/CAPpHfdurb9ycV8udYqM%3Do0sPS66PJ4RCBM1g-bBpvzUfogY0EA%40mail.gmail.com
Discussion: https://postgr.es/m/AMUA1wBBBxfc3tKRLLdU64rb.1.1683276279979.Hmail.wuhao%40hashdata.cn
Reviewed-by: Reviewed-by: Pavel Borisov, Matthias van de Meent, Jess Davis
Diffstat (limited to 'src/include')
| -rw-r--r-- | src/include/access/reloptions.h | 10 | ||||
| -rw-r--r-- | src/include/access/tableam.h | 50 | ||||
| -rw-r--r-- | src/include/utils/rel.h | 148 |
3 files changed, 134 insertions, 74 deletions
diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h index 81829b8270a..342b9cdd6ed 100644 --- a/src/include/access/reloptions.h +++ b/src/include/access/reloptions.h @@ -21,6 +21,7 @@ #include "access/amapi.h" #include "access/htup.h" +#include "access/tableam.h" #include "access/tupdesc.h" #include "nodes/pg_list.h" #include "storage/lock.h" @@ -224,7 +225,9 @@ extern Datum transformRelOptions(Datum oldOptions, List *defList, bool acceptOidsOff, bool isReset); extern List *untransformRelOptions(Datum options); extern bytea *extractRelOptions(HeapTuple tuple, TupleDesc tupdesc, - amoptions_function amoptions); + const TableAmRoutine *tableam, + amoptions_function amoptions, + CommonRdOptions *common); extern void *build_reloptions(Datum reloptions, bool validate, relopt_kind kind, Size relopt_struct_size, @@ -233,9 +236,8 @@ extern void *build_reloptions(Datum reloptions, bool validate, extern void *build_local_reloptions(local_relopts *relopts, Datum options, bool validate); -extern bytea *default_reloptions(Datum reloptions, bool validate, - relopt_kind kind); -extern bytea *heap_reloptions(char relkind, Datum reloptions, bool validate); +extern bytea *heap_reloptions(char relkind, Datum reloptions, + CommonRdOptions *common, bool validate); extern bytea *view_reloptions(Datum reloptions, bool validate); extern bytea *partitioned_table_reloptions(Datum reloptions, bool validate); extern bytea *index_reloptions(amoptions_function amoptions, Datum reloptions, diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h index be198fa3158..ec827ac12bf 100644 --- a/src/include/access/tableam.h +++ b/src/include/access/tableam.h @@ -746,6 +746,34 @@ typedef struct TableAmRoutine int32 slicelength, struct varlena *result); + /* + * This callback parses and validates the reloptions array for a table. + * + * This is called only when a non-null reloptions array exists for the + * table. 'reloptions' is a text array containing entries of the form + * "name=value". The function should construct a bytea value, which will + * be copied into the rd_options field of the table's relcache entry. The + * data contents of the bytea value are open for the access method to + * define. + * + * The '*common' represents the common values, which the table access + * method exposes for autovacuum, query planner, and others. The caller + * should fill them with default values. The table access method may + * modify them on the base of options specified by a user. + * + * When 'validate' is true, the function should report a suitable error + * message if any of the options are unrecognized or have invalid values; + * when 'validate' is false, invalid entries should be silently ignored. + * ('validate' is false when loading options already stored in pg_catalog; + * an invalid entry could only be found if the access method has changed + * its rules for options, and in that case ignoring obsolete entries is + * appropriate.) + * + * It is OK to return NULL if default behavior is wanted. + */ + bytea *(*reloptions) (char relkind, Datum reloptions, + CommonRdOptions *common, bool validate); + /* ------------------------------------------------------------------------ * Planner related functions. @@ -1945,6 +1973,27 @@ table_relation_fetch_toast_slice(Relation toastrel, Oid valueid, result); } +/* + * Parse table options without knowledge of particular table. + */ +static inline bytea * +tableam_reloptions(const TableAmRoutine *tableam, char relkind, + Datum reloptions, CommonRdOptions *common, bool validate) +{ + return tableam->reloptions(relkind, reloptions, common, validate); +} + +/* + * Parse options for given table. + */ +static inline bytea * +table_reloptions(Relation rel, char relkind, + Datum reloptions, CommonRdOptions *common, bool validate) +{ + return tableam_reloptions(rel->rd_tableam, relkind, reloptions, + common, validate); +} + /* ---------------------------------------------------------------------------- * Planner related functionality @@ -2123,6 +2172,7 @@ extern void table_block_relation_estimate_size(Relation rel, */ extern const TableAmRoutine *GetTableAmRoutine(Oid amhandler); +extern const TableAmRoutine *GetTableAmRoutineByAmOid(Oid amoid); /* ---------------------------------------------------------------------------- * Functions in heapam_handler.c diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index f25f769af2b..56e3e782d27 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -48,6 +48,52 @@ typedef struct LockInfoData typedef LockInfoData *LockInfo; + /* autovacuum-related reloptions. */ +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; + +/* StdRdOptions->vacuum_index_cleanup values */ +typedef enum StdRdOptIndexCleanup +{ + STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO = 0, + STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF, + STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON, +} StdRdOptIndexCleanup; + +/* + * CommonRdOptions + * Contents of rd_common_options for tables. It contains the options, + * which the table access method exposes for autovacuum, query planner, + * and others. These options could be by decision of table AM directly + * specified by a user or calculated in some way. + */ +typedef struct CommonRdOptions +{ + AutoVacOpts autovacuum; /* autovacuum-related options */ + bool user_catalog_table; /* use as an additional catalog relation */ + int parallel_workers; /* max number of parallel workers */ + StdRdOptIndexCleanup vacuum_index_cleanup; /* controls index vacuuming */ + bool vacuum_truncate; /* enables vacuum to truncate a relation */ +} CommonRdOptions; + + /* * Here are the contents of a relation cache entry. */ @@ -168,11 +214,19 @@ typedef struct RelationData 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". + * rd_options and rd_common_options are set whenever rd_rel is loaded into + * the relcache entry. Note that you can NOT look into rd_rel for this + * data. NULLs means "use defaults". + */ + CommonRdOptions *rd_common_options; /* the options, which table AM exposes + * for external usage */ + + /* + * am-specific part of pg_class.reloptions parsed by table am specific + * structure (e.g. struct HeapRdOptions) Contents are not to be accessed + * outside of table am */ - bytea *rd_options; /* parsed pg_class.reloptions */ + bytea *rd_options; /* * Oid of the handler for this relation. For an index this is a function @@ -297,88 +351,42 @@ typedef struct ForeignKeyCacheInfo Oid conpfeqop[INDEX_MAX_KEYS] pg_node_attr(array_size(nkeys)); } ForeignKeyCacheInfo; - /* - * StdRdOptions - * Standard contents of rd_options for heaps. - * - * RelationGetFillFactor() and RelationGetTargetPageFreeSpace() can only - * be applied to relations that use this format or a superset for - * private options data. + * HeapRdOptions + * Contents of rd_options specific for heap tables. */ - /* autovacuum-related reloptions. */ -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; - -/* StdRdOptions->vacuum_index_cleanup values */ -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 +typedef struct HeapRdOptions { int32 vl_len_; /* varlena header (do not touch directly!) */ + CommonRdOptions common; int fillfactor; /* page fill factor in percent (0..100) */ int toast_tuple_target; /* target for tuple toasting */ - AutoVacOpts autovacuum; /* autovacuum-related options */ - bool user_catalog_table; /* use as an additional catalog relation */ - int parallel_workers; /* max number of parallel workers */ - StdRdOptIndexCleanup vacuum_index_cleanup; /* controls index vacuuming */ - bool vacuum_truncate; /* enables vacuum to truncate a relation */ -} StdRdOptions; +} HeapRdOptions; #define HEAP_MIN_FILLFACTOR 10 #define HEAP_DEFAULT_FILLFACTOR 100 /* - * RelationGetToastTupleTarget - * Returns the relation's toast_tuple_target. Note multiple eval of argument! + * HeapGetFillFactor + * Returns the heap relation's fillfactor. Note multiple eval of argument! */ -#define RelationGetToastTupleTarget(relation, defaulttarg) \ +#define HeapGetFillFactor(relation, defaultff) \ ((relation)->rd_options ? \ - ((StdRdOptions *) (relation)->rd_options)->toast_tuple_target : (defaulttarg)) + ((HeapRdOptions *) (relation)->rd_options)->fillfactor : (defaultff)) /* - * RelationGetFillFactor - * Returns the relation's fillfactor. Note multiple eval of argument! - */ -#define RelationGetFillFactor(relation, defaultff) \ - ((relation)->rd_options ? \ - ((StdRdOptions *) (relation)->rd_options)->fillfactor : (defaultff)) - -/* - * RelationGetTargetPageUsage + * HeapGetTargetPageUsage * Returns the relation's desired space usage per page in bytes. */ -#define RelationGetTargetPageUsage(relation, defaultff) \ - (BLCKSZ * RelationGetFillFactor(relation, defaultff) / 100) +#define HeapGetTargetPageUsage(relation, defaultff) \ + (BLCKSZ * HeapGetFillFactor(relation, defaultff) / 100) /* - * RelationGetTargetPageFreeSpace + * HeapGetTargetPageFreeSpace * Returns the relation's desired freespace per page in bytes. */ -#define RelationGetTargetPageFreeSpace(relation, defaultff) \ - (BLCKSZ * (100 - RelationGetFillFactor(relation, defaultff)) / 100) +#define HeapGetTargetPageFreeSpace(relation, defaultff) \ + (BLCKSZ * (100 - HeapGetFillFactor(relation, defaultff)) / 100) /* * RelationIsUsedAsCatalogTable @@ -386,10 +394,10 @@ typedef struct StdRdOptions * from the pov of logical decoding. Note multiple eval of argument! */ #define RelationIsUsedAsCatalogTable(relation) \ - ((relation)->rd_options && \ - ((relation)->rd_rel->relkind == RELKIND_RELATION || \ + ((relation)->rd_common_options && \ + ((relation)->rd_rel->relkind == RELKIND_RELATION || \ (relation)->rd_rel->relkind == RELKIND_MATVIEW) ? \ - ((StdRdOptions *) (relation)->rd_options)->user_catalog_table : false) + (relation)->rd_common_options->user_catalog_table : false) /* * RelationGetParallelWorkers @@ -397,8 +405,8 @@ typedef struct StdRdOptions * Note multiple eval of argument! */ #define RelationGetParallelWorkers(relation, defaultpw) \ - ((relation)->rd_options ? \ - ((StdRdOptions *) (relation)->rd_options)->parallel_workers : (defaultpw)) + ((relation)->rd_common_options ? \ + (relation)->rd_common_options->parallel_workers : (defaultpw)) /* ViewOptions->check_option values */ typedef enum ViewOptCheckOption |
