From 554aafc58c1788bff6a9e3a4dc29e13853d8408b Mon Sep 17 00:00:00 2001 From: B Sadhu Prasad Patro Date: Wed, 29 Dec 2021 09:03:09 -0800 Subject: [PATCH v1] [PATCH v1] Per-table storage parameters for TableAM/IndexAM extensions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently all the storage options for a table are very much specific to the heap but a different AM might need some user defined AM specific parameters to help tune the AM. So here is a patch which provides an AM level routine so that instead of getting parameters validated using “heap_reloptions” it will call the registered AM routine. --- src/backend/access/common/reloptions.c | 29 ++++++++++++++++++++++++++--- src/backend/access/heap/heapam_handler.c | 1 + src/backend/access/table/tableamapi.c | 1 + src/backend/postmaster/autovacuum.c | 17 ++++++++++------- src/backend/utils/cache/relcache.c | 11 +++++++++-- src/include/access/reloptions.h | 6 +++++- src/include/access/tableam.h | 8 +++++++- 7 files changed, 59 insertions(+), 14 deletions(-) diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c index b5602f5..0e3b62c 100644 --- a/src/backend/access/common/reloptions.c +++ b/src/backend/access/common/reloptions.c @@ -1358,6 +1358,7 @@ untransformRelOptions(Datum options) return result; } + /* * Extract and parse reloptions from a pg_class tuple. * @@ -1372,7 +1373,8 @@ untransformRelOptions(Datum options) */ bytea * extractRelOptions(HeapTuple tuple, TupleDesc tupdesc, - amoptions_function amoptions) + amoptions_function amoptions, + reloptions_function taboptions) { bytea *options; bool isnull; @@ -1394,7 +1396,7 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc, case RELKIND_RELATION: case RELKIND_TOASTVALUE: case RELKIND_MATVIEW: - options = heap_reloptions(classForm->relkind, datum, false); + options = table_reloptions(taboptions, classForm->relkind, datum, false); break; case RELKIND_PARTITIONED_TABLE: options = partitioned_table_reloptions(datum, false); @@ -2007,7 +2009,8 @@ view_reloptions(Datum reloptions, bool validate) } /* - * Parse options for heaps, views and toast tables. + * Parse options for heaps, views and toast tables. This is + * implementation of relOptions for access method heapam. */ bytea * heap_reloptions(char relkind, Datum reloptions, bool validate) @@ -2038,6 +2041,26 @@ heap_reloptions(char relkind, Datum reloptions, bool validate) /* + * Parse options for tables. + * + * taboptions tables AM's option parser function + * reloptions options as text[] datum + * validate error flag + */ +bytea * +table_reloptions(reloptions_function taboptions, char relkind, + Datum reloptions, bool validate) +{ + Assert(taboptions != NULL); + + /* Assume function is strict */ + if (!PointerIsValid(DatumGetPointer(reloptions))) + return NULL; + + return taboptions(relkind, reloptions, validate); +} + +/* * Parse options for indexes. * * amoptions index AM's option parser function diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c index 9befe01..6324d7e 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -2581,6 +2581,7 @@ static const TableAmRoutine heapam_methods = { .index_build_range_scan = heapam_index_build_range_scan, .index_validate_scan = heapam_index_validate_scan, + .taboptions = heap_reloptions, .relation_size = table_block_relation_size, .relation_needs_toast_table = heapam_relation_needs_toast_table, .relation_toast_am = heapam_relation_toast_am, diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c index 325ecdc..cbe774b 100644 --- a/src/backend/access/table/tableamapi.c +++ b/src/backend/access/table/tableamapi.c @@ -92,6 +92,7 @@ GetTableAmRoutine(Oid amhandler) Assert(routine->index_build_range_scan != NULL); Assert(routine->index_validate_scan != NULL); + Assert(routine->taboptions != NULL); Assert(routine->relation_size != NULL); Assert(routine->relation_needs_toast_table != NULL); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index f6d0562..d7a8b99 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -327,6 +327,7 @@ static void FreeWorkerInfo(int code, Datum arg); static autovac_table *table_recheck_autovac(Oid relid, HTAB *table_toast_map, TupleDesc pg_class_desc, + reloptions_function taboptions, int effective_multixact_freeze_max_age); static void recheck_relation_needs_vacanalyze(Oid relid, AutoVacOpts *avopts, Form_pg_class classForm, @@ -341,7 +342,7 @@ static void relation_needs_vacanalyze(Oid relid, AutoVacOpts *relopts, static void autovacuum_do_vac_analyze(autovac_table *tab, BufferAccessStrategy bstrategy); static AutoVacOpts *extract_autovac_opts(HeapTuple tup, - TupleDesc pg_class_desc); + TupleDesc pg_class_desc, reloptions_function taboptions); static PgStat_StatTabEntry *get_pgstat_tabentry_relid(Oid relid, bool isshared, PgStat_StatDBEntry *shared, PgStat_StatDBEntry *dbentry); @@ -2118,7 +2119,7 @@ do_autovacuum(void) } /* Fetch reloptions and the pgstat entry for this table */ - relopts = extract_autovac_opts(tuple, pg_class_desc); + relopts = extract_autovac_opts(tuple, pg_class_desc, classRel->rd_tableam->taboptions); tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared, shared, dbentry); @@ -2191,7 +2192,7 @@ do_autovacuum(void) * fetch reloptions -- if this toast table does not have them, try the * main rel */ - relopts = extract_autovac_opts(tuple, pg_class_desc); + relopts = extract_autovac_opts(tuple, pg_class_desc, classRel->rd_tableam->taboptions); if (relopts == NULL) { av_relation *hentry; @@ -2427,7 +2428,7 @@ do_autovacuum(void) */ MemoryContextSwitchTo(AutovacMemCxt); tab = table_recheck_autovac(relid, table_toast_map, pg_class_desc, - effective_multixact_freeze_max_age); + classRel->rd_tableam->taboptions, effective_multixact_freeze_max_age); if (tab == NULL) { /* someone else vacuumed the table, or it went away */ @@ -2748,7 +2749,8 @@ deleted2: * be a risk; fortunately, it doesn't. */ static AutoVacOpts * -extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc) +extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc, + reloptions_function taboptions) { bytea *relopts; AutoVacOpts *av; @@ -2757,7 +2759,7 @@ extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc) ((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_MATVIEW || ((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_TOASTVALUE); - relopts = extractRelOptions(tup, pg_class_desc, NULL); + relopts = extractRelOptions(tup, pg_class_desc, NULL, taboptions); if (relopts == NULL) return NULL; @@ -2803,6 +2805,7 @@ get_pgstat_tabentry_relid(Oid relid, bool isshared, PgStat_StatDBEntry *shared, static autovac_table * table_recheck_autovac(Oid relid, HTAB *table_toast_map, TupleDesc pg_class_desc, + reloptions_function taboptions, int effective_multixact_freeze_max_age) { Form_pg_class classForm; @@ -2824,7 +2827,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, * Get the applicable reloptions. If it is a TOAST table, try to get the * main table reloptions if the toast table itself doesn't have. */ - avopts = extract_autovac_opts(classTup, pg_class_desc); + avopts = extract_autovac_opts(classTup, pg_class_desc, taboptions); if (classForm->relkind == RELKIND_TOASTVALUE && avopts == NULL && table_toast_map != NULL) { diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 105d8d4..7c39760 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -460,6 +460,7 @@ RelationParseRelOptions(Relation relation, HeapTuple tuple) { bytea *options; amoptions_function amoptsfn; + reloptions_function taboptsfn; relation->rd_options = NULL; @@ -471,13 +472,18 @@ RelationParseRelOptions(Relation relation, HeapTuple tuple) { case RELKIND_RELATION: case RELKIND_TOASTVALUE: - case RELKIND_VIEW: case RELKIND_MATVIEW: + taboptsfn = relation->rd_tableam->taboptions; + amoptsfn = NULL; + break; + case RELKIND_VIEW: case RELKIND_PARTITIONED_TABLE: + taboptsfn = NULL; amoptsfn = NULL; break; case RELKIND_INDEX: case RELKIND_PARTITIONED_INDEX: + taboptsfn = NULL; amoptsfn = relation->rd_indam->amoptions; break; default: @@ -489,7 +495,8 @@ RelationParseRelOptions(Relation relation, HeapTuple tuple) * we might not have any other for pg_class yet (consider executing this * code for pg_class itself) */ - options = extractRelOptions(tuple, GetPgClassDescriptor(), amoptsfn); + options = extractRelOptions(tuple, GetPgClassDescriptor(), + amoptsfn, taboptsfn); /* * Copy parsed data into CacheMemoryContext. To guard against the diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h index 7c5fbeb..0e11364 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,8 @@ 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); + amoptions_function amoptions, + reloptions_function taboptions); extern void *build_reloptions(Datum reloptions, bool validate, relopt_kind kind, Size relopt_struct_size, @@ -238,6 +240,8 @@ extern bytea *default_reloptions(Datum reloptions, bool validate, extern bytea *heap_reloptions(char relkind, Datum reloptions, bool validate); extern bytea *view_reloptions(Datum reloptions, bool validate); extern bytea *partitioned_table_reloptions(Datum reloptions, bool validate); +extern bytea *table_reloptions(reloptions_function taboptions, char relkind, + Datum reloptions, bool validate); extern bytea *index_reloptions(amoptions_function amoptions, Datum reloptions, bool validate); extern bytea *attribute_reloptions(Datum reloptions, bool validate); diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h index 808c144..fda6a47 100644 --- a/src/include/access/tableam.h +++ b/src/include/access/tableam.h @@ -252,6 +252,10 @@ typedef void (*IndexBuildCallback) (Relation index, bool tupleIsAlive, void *state); +/* This callback parse the table reloptions and returns in bytea format */ +typedef bytea *(*reloptions_function) (char relkind, + Datum reloptions, bool validate); + /* * API struct for a table AM. Note this must be allocated in a * server-lifetime manner, typically as a static const struct, which then gets @@ -692,6 +696,8 @@ typedef struct TableAmRoutine * ------------------------------------------------------------------------ */ + reloptions_function taboptions; + /* * See table_relation_size(). * @@ -702,7 +708,6 @@ typedef struct TableAmRoutine */ uint64 (*relation_size) (Relation rel, ForkNumber forkNumber); - /* * This callback should return true if the relation requires a TOAST table * and false if it does not. It may wish to examine the relation's tuple @@ -2073,5 +2078,6 @@ extern const TableAmRoutine *GetTableAmRoutine(Oid amhandler); extern const TableAmRoutine *GetHeapamTableAmRoutine(void); extern bool check_default_table_access_method(char **newval, void **extra, GucSource source); +extern bytea *heap_reloptions(char relkind, Datum reloptions, bool validate); #endif /* TABLEAM_H */ -- 1.8.3.1