Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c95c25f

Browse filesBrowse files
committed
Custom reloptions for table AM
Let table AM define custom reloptions for its tables. This allows to specify AM-specific parameters by WITH clause when creating a table. 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
1 parent 27bc177 commit c95c25f
Copy full SHA for c95c25f

File tree

Expand file treeCollapse file tree

8 files changed

+126
-27
lines changed
Filter options
Expand file treeCollapse file tree

8 files changed

+126
-27
lines changed

‎src/backend/access/common/reloptions.c

Copy file name to clipboardExpand all lines: src/backend/access/common/reloptions.c
+4-2Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "access/nbtree.h"
2525
#include "access/reloptions.h"
2626
#include "access/spgist_private.h"
27+
#include "access/tableam.h"
2728
#include "catalog/pg_type.h"
2829
#include "commands/defrem.h"
2930
#include "commands/tablespace.h"
@@ -1377,7 +1378,7 @@ untransformRelOptions(Datum options)
13771378
*/
13781379
bytea *
13791380
extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
1380-
amoptions_function amoptions)
1381+
const TableAmRoutine *tableam, amoptions_function amoptions)
13811382
{
13821383
bytea *options;
13831384
bool isnull;
@@ -1399,7 +1400,8 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
13991400
case RELKIND_RELATION:
14001401
case RELKIND_TOASTVALUE:
14011402
case RELKIND_MATVIEW:
1402-
options = heap_reloptions(classForm->relkind, datum, false);
1403+
options = tableam_reloptions(tableam, classForm->relkind,
1404+
datum, false);
14031405
break;
14041406
case RELKIND_PARTITIONED_TABLE:
14051407
options = partitioned_table_reloptions(datum, false);

‎src/backend/access/heap/heapam_handler.c

Copy file name to clipboardExpand all lines: src/backend/access/heap/heapam_handler.c
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "access/heapam.h"
2424
#include "access/heaptoast.h"
2525
#include "access/multixact.h"
26+
#include "access/reloptions.h"
2627
#include "access/rewriteheap.h"
2728
#include "access/syncscan.h"
2829
#include "access/tableam.h"
@@ -2155,6 +2156,16 @@ heapam_relation_toast_am(Relation rel)
21552156
return rel->rd_rel->relam;
21562157
}
21572158

2159+
static bytea *
2160+
heapam_reloptions(char relkind, Datum reloptions, bool validate)
2161+
{
2162+
Assert(relkind == RELKIND_RELATION ||
2163+
relkind == RELKIND_TOASTVALUE ||
2164+
relkind == RELKIND_MATVIEW);
2165+
2166+
return heap_reloptions(relkind, reloptions, validate);
2167+
}
2168+
21582169

21592170
/* ------------------------------------------------------------------------
21602171
* Planner related callbacks for the heap AM
@@ -2660,6 +2671,7 @@ static const TableAmRoutine heapam_methods = {
26602671
.relation_needs_toast_table = heapam_relation_needs_toast_table,
26612672
.relation_toast_am = heapam_relation_toast_am,
26622673
.relation_fetch_toast_slice = heap_fetch_toast_slice,
2674+
.reloptions = heapam_reloptions,
26632675

26642676
.relation_estimate_size = heapam_estimate_rel_size,
26652677

‎src/backend/access/table/tableamapi.c

Copy file name to clipboardExpand all lines: src/backend/access/table/tableamapi.c
+25Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313

1414
#include "access/tableam.h"
1515
#include "access/xact.h"
16+
#include "catalog/pg_am.h"
1617
#include "commands/defrem.h"
1718
#include "miscadmin.h"
1819
#include "utils/guc_hooks.h"
20+
#include "utils/syscache.h"
1921

2022

2123
/*
@@ -98,6 +100,29 @@ GetTableAmRoutine(Oid amhandler)
98100
return routine;
99101
}
100102

103+
/*
104+
* GetTableAmRoutineByAmOid
105+
* Given the table access method oid get its TableAmRoutine struct, which
106+
* will be palloc'd in the caller's memory context.
107+
*/
108+
const TableAmRoutine *
109+
GetTableAmRoutineByAmOid(Oid amoid)
110+
{
111+
HeapTuple ht_am;
112+
Form_pg_am amrec;
113+
const TableAmRoutine *tableam = NULL;
114+
115+
ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(amoid));
116+
if (!HeapTupleIsValid(ht_am))
117+
elog(ERROR, "cache lookup failed for access method %u",
118+
amoid);
119+
amrec = (Form_pg_am) GETSTRUCT(ht_am);
120+
121+
tableam = GetTableAmRoutine(amrec->amhandler);
122+
ReleaseSysCache(ht_am);
123+
return tableam;
124+
}
125+
101126
/* check_hook: validate new default_table_access_method */
102127
bool
103128
check_default_table_access_method(char **newval, void **extra, GucSource source)

‎src/backend/commands/tablecmds.c

Copy file name to clipboardExpand all lines: src/backend/commands/tablecmds.c
+32-23Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
715715
ObjectAddress address;
716716
LOCKMODE parentLockmode;
717717
Oid accessMethodId = InvalidOid;
718+
const TableAmRoutine *tableam = NULL;
718719

719720
/*
720721
* Truncate relname to appropriate length (probably a waste of time, as
@@ -850,6 +851,28 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
850851
if (!OidIsValid(ownerId))
851852
ownerId = GetUserId();
852853

854+
/*
855+
* For relations with table AM and partitioned tables, select access
856+
* method to use: an explicitly indicated one, or (in the case of a
857+
* partitioned table) the parent's, if it has one.
858+
*/
859+
if (stmt->accessMethod != NULL)
860+
{
861+
Assert(RELKIND_HAS_TABLE_AM(relkind) || relkind == RELKIND_PARTITIONED_TABLE);
862+
accessMethodId = get_table_am_oid(stmt->accessMethod, false);
863+
}
864+
else if (RELKIND_HAS_TABLE_AM(relkind) || relkind == RELKIND_PARTITIONED_TABLE)
865+
{
866+
if (stmt->partbound)
867+
{
868+
Assert(list_length(inheritOids) == 1);
869+
accessMethodId = get_rel_relam(linitial_oid(inheritOids));
870+
}
871+
872+
if (RELKIND_HAS_TABLE_AM(relkind) && !OidIsValid(accessMethodId))
873+
accessMethodId = get_table_am_oid(default_table_access_method, false);
874+
}
875+
853876
/*
854877
* Parse and validate reloptions, if any.
855878
*/
@@ -858,6 +881,12 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
858881

859882
switch (relkind)
860883
{
884+
case RELKIND_RELATION:
885+
case RELKIND_TOASTVALUE:
886+
case RELKIND_MATVIEW:
887+
tableam = GetTableAmRoutineByAmOid(accessMethodId);
888+
(void) tableam_reloptions(tableam, relkind, reloptions, true);
889+
break;
861890
case RELKIND_VIEW:
862891
(void) view_reloptions(reloptions, true);
863892
break;
@@ -866,6 +895,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
866895
break;
867896
default:
868897
(void) heap_reloptions(relkind, reloptions, true);
898+
break;
869899
}
870900

871901
if (stmt->ofTypename)
@@ -957,28 +987,6 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
957987
}
958988
}
959989

960-
/*
961-
* For relations with table AM and partitioned tables, select access
962-
* method to use: an explicitly indicated one, or (in the case of a
963-
* partitioned table) the parent's, if it has one.
964-
*/
965-
if (stmt->accessMethod != NULL)
966-
{
967-
Assert(RELKIND_HAS_TABLE_AM(relkind) || relkind == RELKIND_PARTITIONED_TABLE);
968-
accessMethodId = get_table_am_oid(stmt->accessMethod, false);
969-
}
970-
else if (RELKIND_HAS_TABLE_AM(relkind) || relkind == RELKIND_PARTITIONED_TABLE)
971-
{
972-
if (stmt->partbound)
973-
{
974-
Assert(list_length(inheritOids) == 1);
975-
accessMethodId = get_rel_relam(linitial_oid(inheritOids));
976-
}
977-
978-
if (RELKIND_HAS_TABLE_AM(relkind) && !OidIsValid(accessMethodId))
979-
accessMethodId = get_table_am_oid(default_table_access_method, false);
980-
}
981-
982990
/*
983991
* Create the relation. Inherited defaults and constraints are passed in
984992
* for immediate handling --- since they don't need parsing, they can be
@@ -15524,7 +15532,8 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
1552415532
case RELKIND_RELATION:
1552515533
case RELKIND_TOASTVALUE:
1552615534
case RELKIND_MATVIEW:
15527-
(void) heap_reloptions(rel->rd_rel->relkind, newOptions, true);
15535+
(void) table_reloptions(rel, rel->rd_rel->relkind,
15536+
newOptions, true);
1552815537
break;
1552915538
case RELKIND_PARTITIONED_TABLE:
1553015539
(void) partitioned_table_reloptions(newOptions, true);

‎src/backend/postmaster/autovacuum.c

Copy file name to clipboardExpand all lines: src/backend/postmaster/autovacuum.c
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2661,7 +2661,9 @@ extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc)
26612661
((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_MATVIEW ||
26622662
((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_TOASTVALUE);
26632663

2664-
relopts = extractRelOptions(tup, pg_class_desc, NULL);
2664+
relopts = extractRelOptions(tup, pg_class_desc,
2665+
GetTableAmRoutineByAmOid(((Form_pg_class) GETSTRUCT(tup))->relam),
2666+
NULL);
26652667
if (relopts == NULL)
26662668
return NULL;
26672669

‎src/backend/utils/cache/relcache.c

Copy file name to clipboardExpand all lines: src/backend/utils/cache/relcache.c
+5-1Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "access/htup_details.h"
3434
#include "access/multixact.h"
3535
#include "access/parallel.h"
36+
#include "access/relation.h"
3637
#include "access/reloptions.h"
3738
#include "access/sysattr.h"
3839
#include "access/table.h"
@@ -464,6 +465,7 @@ RelationParseRelOptions(Relation relation, HeapTuple tuple)
464465
{
465466
bytea *options;
466467
amoptions_function amoptsfn;
468+
const TableAmRoutine *tableam = NULL;
467469

468470
relation->rd_options = NULL;
469471

@@ -478,6 +480,7 @@ RelationParseRelOptions(Relation relation, HeapTuple tuple)
478480
case RELKIND_VIEW:
479481
case RELKIND_MATVIEW:
480482
case RELKIND_PARTITIONED_TABLE:
483+
tableam = relation->rd_tableam;
481484
amoptsfn = NULL;
482485
break;
483486
case RELKIND_INDEX:
@@ -493,7 +496,8 @@ RelationParseRelOptions(Relation relation, HeapTuple tuple)
493496
* we might not have any other for pg_class yet (consider executing this
494497
* code for pg_class itself)
495498
*/
496-
options = extractRelOptions(tuple, GetPgClassDescriptor(), amoptsfn);
499+
options = extractRelOptions(tuple, GetPgClassDescriptor(),
500+
tableam, amoptsfn);
497501

498502
/*
499503
* Copy parsed data into CacheMemoryContext. To guard against the

‎src/include/access/reloptions.h

Copy file name to clipboardExpand all lines: src/include/access/reloptions.h
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "access/amapi.h"
2323
#include "access/htup.h"
24+
#include "access/tableam.h"
2425
#include "access/tupdesc.h"
2526
#include "nodes/pg_list.h"
2627
#include "storage/lock.h"
@@ -224,6 +225,7 @@ extern Datum transformRelOptions(Datum oldOptions, List *defList,
224225
bool acceptOidsOff, bool isReset);
225226
extern List *untransformRelOptions(Datum options);
226227
extern bytea *extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
228+
const TableAmRoutine *tableam,
227229
amoptions_function amoptions);
228230
extern void *build_reloptions(Datum reloptions, bool validate,
229231
relopt_kind kind,

‎src/include/access/tableam.h

Copy file name to clipboardExpand all lines: src/include/access/tableam.h
+43Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,28 @@ typedef struct TableAmRoutine
737737
int32 slicelength,
738738
struct varlena *result);
739739

740+
/*
741+
* This callback parses and validates the reloptions array for a table.
742+
*
743+
* This is called only when a non-null reloptions array exists for the
744+
* table. 'reloptions' is a text array containing entries of the form
745+
* "name=value". The function should construct a bytea value, which will
746+
* be copied into the rd_options field of the table's relcache entry. The
747+
* data contents of the bytea value are open for the access method to
748+
* define.
749+
*
750+
* When 'validate' is true, the function should report a suitable error
751+
* message if any of the options are unrecognized or have invalid values;
752+
* when 'validate' is false, invalid entries should be silently ignored.
753+
* ('validate' is false when loading options already stored in pg_catalog;
754+
* an invalid entry could only be found if the access method has changed
755+
* its rules for options, and in that case ignoring obsolete entries is
756+
* appropriate.)
757+
*
758+
* It is OK to return NULL if default behavior is wanted.
759+
*/
760+
bytea *(*reloptions) (char relkind, Datum reloptions, bool validate);
761+
740762

741763
/* ------------------------------------------------------------------------
742764
* Planner related functions.
@@ -1925,6 +1947,26 @@ table_relation_fetch_toast_slice(Relation toastrel, Oid valueid,
19251947
result);
19261948
}
19271949

1950+
/*
1951+
* Parse options for given table.
1952+
*/
1953+
static inline bytea *
1954+
table_reloptions(Relation rel, char relkind,
1955+
Datum reloptions, bool validate)
1956+
{
1957+
return rel->rd_tableam->reloptions(relkind, reloptions, validate);
1958+
}
1959+
1960+
/*
1961+
* Parse table options without knowledge of particular table.
1962+
*/
1963+
static inline bytea *
1964+
tableam_reloptions(const TableAmRoutine *tableam, char relkind,
1965+
Datum reloptions, bool validate)
1966+
{
1967+
return tableam->reloptions(relkind, reloptions, validate);
1968+
}
1969+
19281970

19291971
/* ----------------------------------------------------------------------------
19301972
* Planner related functionality
@@ -2102,6 +2144,7 @@ extern void table_block_relation_estimate_size(Relation rel,
21022144
*/
21032145

21042146
extern const TableAmRoutine *GetTableAmRoutine(Oid amhandler);
2147+
extern const TableAmRoutine *GetTableAmRoutineByAmOid(Oid amoid);
21052148

21062149
/* ----------------------------------------------------------------------------
21072150
* Functions in heapam_handler.c

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.