Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 8586bf7

Browse files
committed
tableam: introduce table AM infrastructure.
This introduces the concept of table access methods, i.e. CREATE ACCESS METHOD ... TYPE TABLE and CREATE TABLE ... USING (storage-engine). No table access functionality is delegated to table AMs as of this commit, that'll be done in following commits. Subsequent commits will incrementally abstract table access functionality to be routed through table access methods. That change is too large to be reviewed & committed at once, so it'll be done incrementally. Docs will be updated at the end, as adding them incrementally would likely make them less coherent, and definitely is a lot more work, without a lot of benefit. Table access methods are specified similar to index access methods, i.e. pg_am.amhandler returns, as INTERNAL, a pointer to a struct with callbacks. In contrast to index AMs that struct needs to live as long as a backend, typically that's achieved by just returning a pointer to a constant struct. Psql's \d+ now displays a table's access method. That can be disabled with HIDE_TABLEAM=true, which is mainly useful so regression tests can be run against different AMs. It's quite possible that this behaviour still needs to be fine tuned. For now it's not allowed to set a table AM for a partitioned table, as we've not resolved how partitions would inherit that. Disallowing allows us to introduce, if we decide that's the way forward, such a behaviour without a compatibility break. Catversion bumped, to add the heap table AM and references to it. Author: Haribabu Kommi, Andres Freund, Alvaro Herrera, Dimitri Golgov and others Discussion: https://postgr.es/m/20180703070645.wchpu5muyto5n647@alap3.anarazel.de https://postgr.es/m/20160812231527.GA690404@alvherre.pgsql https://postgr.es/m/20190107235616.6lur25ph22u5u5av@alap3.anarazel.de https://postgr.es/m/20190304234700.w5tmhducs5wxgzls@alap3.anarazel.de
1 parent f217761 commit 8586bf7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1055
-74
lines changed

doc/src/sgml/ref/psql-ref.sgml

+11
Original file line numberDiff line numberDiff line change
@@ -3646,6 +3646,17 @@ bar
36463646
</listitem>
36473647
</varlistentry>
36483648

3649+
<varlistentry>
3650+
<term><varname>HIDE_TABLEAM</varname></term>
3651+
<listitem>
3652+
<para>
3653+
If this variable is set to <literal>true</literal>, a table's access
3654+
method details are not displayed. This is mainly useful for
3655+
regression tests.
3656+
</para>
3657+
</listitem>
3658+
</varlistentry>
3659+
36493660
<varlistentry>
36503661
<term><varname>HISTCONTROL</varname></term>
36513662
<listitem>

src/backend/access/heap/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ subdir = src/backend/access/heap
1212
top_builddir = ../../../..
1313
include $(top_builddir)/src/Makefile.global
1414

15-
OBJS = heapam.o heapam_visibility.o hio.o pruneheap.o rewriteheap.o \
15+
OBJS = heapam.o heapam_handler.o heapam_visibility.o hio.o pruneheap.o rewriteheap.o \
1616
syncscan.o tuptoaster.o vacuumlazy.o visibilitymap.o
1717

1818
include $(top_srcdir)/src/backend/common.mk
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* heapam_handler.c
4+
* heap table access method code
5+
*
6+
* Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7+
* Portions Copyright (c) 1994, Regents of the University of California
8+
*
9+
*
10+
* IDENTIFICATION
11+
* src/backend/access/heap/heapam_handler.c
12+
*
13+
*
14+
* NOTES
15+
* This files wires up the lower level heapam.c et routines with the
16+
* tableam abstraction.
17+
*
18+
*-------------------------------------------------------------------------
19+
*/
20+
#include "postgres.h"
21+
22+
#include "access/tableam.h"
23+
#include "utils/builtins.h"
24+
25+
26+
static const TableAmRoutine heapam_methods;
27+
28+
29+
static const TableAmRoutine heapam_methods = {
30+
.type = T_TableAmRoutine,
31+
};
32+
33+
34+
const TableAmRoutine *
35+
GetHeapamTableAmRoutine(void)
36+
{
37+
return &heapam_methods;
38+
}
39+
40+
Datum
41+
heap_tableam_handler(PG_FUNCTION_ARGS)
42+
{
43+
PG_RETURN_POINTER(&heapam_methods);
44+
}

src/backend/access/table/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ subdir = src/backend/access/table
1212
top_builddir = ../../../..
1313
include $(top_builddir)/src/Makefile.global
1414

15-
OBJS = table.o
15+
OBJS = table.o tableam.o tableamapi.o
1616

1717
include $(top_srcdir)/src/backend/common.mk

src/backend/access/table/tableam.c

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*----------------------------------------------------------------------
2+
*
3+
* tableam.c
4+
* Table access method routines too big to be inline functions.
5+
*
6+
* Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7+
* Portions Copyright (c) 1994, Regents of the University of California
8+
*
9+
* src/backend/access/table/tableam.c
10+
*----------------------------------------------------------------------
11+
*/
12+
#include "postgres.h"
13+
14+
#include "access/tableam.h"
15+
16+
17+
/* GUC variables */
18+
char *default_table_access_method = DEFAULT_TABLE_ACCESS_METHOD;

src/backend/access/table/tableamapi.c

+173
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/*----------------------------------------------------------------------
2+
*
3+
* tableamapi.c
4+
* Support routines for API for Postgres table access methods
5+
*
6+
* Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7+
* Portions Copyright (c) 1994, Regents of the University of California
8+
*
9+
* src/backend/access/table/tableamapi.c
10+
*----------------------------------------------------------------------
11+
*/
12+
#include "postgres.h"
13+
14+
#include "access/heapam.h"
15+
#include "access/htup_details.h"
16+
#include "access/tableam.h"
17+
#include "access/xact.h"
18+
#include "catalog/pg_am.h"
19+
#include "catalog/pg_proc.h"
20+
#include "utils/fmgroids.h"
21+
#include "utils/memutils.h"
22+
#include "utils/syscache.h"
23+
24+
25+
static Oid get_table_am_oid(const char *tableamname, bool missing_ok);
26+
27+
28+
/*
29+
* GetTableAmRoutine
30+
* Call the specified access method handler routine to get its
31+
* TableAmRoutine struct, which will be palloc'd in the caller's
32+
* memory context.
33+
*/
34+
const TableAmRoutine *
35+
GetTableAmRoutine(Oid amhandler)
36+
{
37+
Datum datum;
38+
const TableAmRoutine *routine;
39+
40+
datum = OidFunctionCall0(amhandler);
41+
routine = (TableAmRoutine *) DatumGetPointer(datum);
42+
43+
if (routine == NULL || !IsA(routine, TableAmRoutine))
44+
elog(ERROR, "Table access method handler %u did not return a TableAmRoutine struct",
45+
amhandler);
46+
47+
return routine;
48+
}
49+
50+
/*
51+
* GetTableAmRoutineByAmId - look up the handler of the table access
52+
* method with the given OID, and get its TableAmRoutine struct.
53+
*/
54+
const TableAmRoutine *
55+
GetTableAmRoutineByAmId(Oid amoid)
56+
{
57+
regproc amhandler;
58+
HeapTuple tuple;
59+
Form_pg_am amform;
60+
61+
/* Get handler function OID for the access method */
62+
tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(amoid));
63+
if (!HeapTupleIsValid(tuple))
64+
elog(ERROR, "cache lookup failed for access method %u",
65+
amoid);
66+
amform = (Form_pg_am) GETSTRUCT(tuple);
67+
68+
/* Check that it is a table access method */
69+
if (amform->amtype != AMTYPE_TABLE)
70+
ereport(ERROR,
71+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
72+
errmsg("access method \"%s\" is not of type %s",
73+
NameStr(amform->amname), "TABLE")));
74+
75+
amhandler = amform->amhandler;
76+
77+
/* Complain if handler OID is invalid */
78+
if (!RegProcedureIsValid(amhandler))
79+
ereport(ERROR,
80+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
81+
errmsg("table access method \"%s\" does not have a handler",
82+
NameStr(amform->amname))));
83+
84+
ReleaseSysCache(tuple);
85+
86+
/* And finally, call the handler function to get the API struct. */
87+
return GetTableAmRoutine(amhandler);
88+
}
89+
90+
/*
91+
* get_table_am_oid - given a table access method name, look up the OID
92+
*
93+
* If missing_ok is false, throw an error if table access method name not
94+
* found. If true, just return InvalidOid.
95+
*/
96+
static Oid
97+
get_table_am_oid(const char *tableamname, bool missing_ok)
98+
{
99+
Oid result;
100+
Relation rel;
101+
HeapScanDesc scandesc;
102+
HeapTuple tuple;
103+
ScanKeyData entry[1];
104+
105+
/*
106+
* Search pg_tablespace. We use a heapscan here even though there is an
107+
* index on name, on the theory that pg_tablespace will usually have just
108+
* a few entries and so an indexed lookup is a waste of effort.
109+
*/
110+
rel = heap_open(AccessMethodRelationId, AccessShareLock);
111+
112+
ScanKeyInit(&entry[0],
113+
Anum_pg_am_amname,
114+
BTEqualStrategyNumber, F_NAMEEQ,
115+
CStringGetDatum(tableamname));
116+
scandesc = heap_beginscan_catalog(rel, 1, entry);
117+
tuple = heap_getnext(scandesc, ForwardScanDirection);
118+
119+
/* We assume that there can be at most one matching tuple */
120+
if (HeapTupleIsValid(tuple) &&
121+
((Form_pg_am) GETSTRUCT(tuple))->amtype == AMTYPE_TABLE)
122+
result = ((Form_pg_am) GETSTRUCT(tuple))->oid;
123+
else
124+
result = InvalidOid;
125+
126+
heap_endscan(scandesc);
127+
heap_close(rel, AccessShareLock);
128+
129+
if (!OidIsValid(result) && !missing_ok)
130+
ereport(ERROR,
131+
(errcode(ERRCODE_UNDEFINED_OBJECT),
132+
errmsg("table access method \"%s\" does not exist",
133+
tableamname)));
134+
135+
return result;
136+
}
137+
138+
/* check_hook: validate new default_table_access_method */
139+
bool
140+
check_default_table_access_method(char **newval, void **extra, GucSource source)
141+
{
142+
/*
143+
* If we aren't inside a transaction, we cannot do database access so
144+
* cannot verify the name. Must accept the value on faith.
145+
*/
146+
if (IsTransactionState())
147+
{
148+
if (**newval != '\0' &&
149+
!OidIsValid(get_table_am_oid(*newval, true)))
150+
{
151+
/*
152+
* When source == PGC_S_TEST, don't throw a hard error for a
153+
* nonexistent table access method, only a NOTICE. See comments in
154+
* guc.h.
155+
*/
156+
if (source == PGC_S_TEST)
157+
{
158+
ereport(NOTICE,
159+
(errcode(ERRCODE_UNDEFINED_OBJECT),
160+
errmsg("Table access method \"%s\" does not exist",
161+
*newval)));
162+
}
163+
else
164+
{
165+
GUC_check_errdetail("Table access method \"%s\" does not exist.",
166+
*newval);
167+
return false;
168+
}
169+
}
170+
}
171+
172+
return true;
173+
}

src/backend/bootstrap/bootparse.y

+2
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ Boot_CreateStmt:
220220
shared_relation ? GLOBALTABLESPACE_OID : 0,
221221
$3,
222222
InvalidOid,
223+
HEAP_TABLE_AM_OID,
223224
tupdesc,
224225
RELKIND_RELATION,
225226
RELPERSISTENCE_PERMANENT,
@@ -239,6 +240,7 @@ Boot_CreateStmt:
239240
$6,
240241
InvalidOid,
241242
BOOTSTRAP_SUPERUSERID,
243+
HEAP_TABLE_AM_OID,
242244
tupdesc,
243245
NIL,
244246
RELKIND_RELATION,

src/backend/catalog/genbki.pl

+4
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,9 @@
160160
my $PG_CATALOG_NAMESPACE =
161161
Catalog::FindDefinedSymbolFromData($catalog_data{pg_namespace},
162162
'PG_CATALOG_NAMESPACE');
163+
my $PG_HEAP_AM =
164+
Catalog::FindDefinedSymbolFromData($catalog_data{pg_am},
165+
'HEAP_TABLE_AM_OID');
163166

164167

165168
# Build lookup tables.
@@ -464,6 +467,7 @@
464467
# (It's intentional that this can apply to parts of a field).
465468
$bki_values{$attname} =~ s/\bPGUID\b/$BOOTSTRAP_SUPERUSERID/g;
466469
$bki_values{$attname} =~ s/\bPGNSP\b/$PG_CATALOG_NAMESPACE/g;
470+
$bki_values{$attname} =~ s/\bPGHEAPAM\b/$PG_HEAP_AM/g;
467471
468472
# Replace OID synonyms with OIDs per the appropriate lookup rule.
469473
#

src/backend/catalog/heap.c

+21
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "catalog/index.h"
4646
#include "catalog/objectaccess.h"
4747
#include "catalog/partition.h"
48+
#include "catalog/pg_am.h"
4849
#include "catalog/pg_attrdef.h"
4950
#include "catalog/pg_collation.h"
5051
#include "catalog/pg_constraint.h"
@@ -293,6 +294,7 @@ heap_create(const char *relname,
293294
Oid reltablespace,
294295
Oid relid,
295296
Oid relfilenode,
297+
Oid accessmtd,
296298
TupleDesc tupDesc,
297299
char relkind,
298300
char relpersistence,
@@ -387,6 +389,7 @@ heap_create(const char *relname,
387389
relnamespace,
388390
tupDesc,
389391
relid,
392+
accessmtd,
390393
relfilenode,
391394
reltablespace,
392395
shared_relation,
@@ -1063,6 +1066,7 @@ heap_create_with_catalog(const char *relname,
10631066
Oid reltypeid,
10641067
Oid reloftypeid,
10651068
Oid ownerid,
1069+
Oid accessmtd,
10661070
TupleDesc tupdesc,
10671071
List *cooked_constraints,
10681072
char relkind,
@@ -1210,6 +1214,7 @@ heap_create_with_catalog(const char *relname,
12101214
reltablespace,
12111215
relid,
12121216
InvalidOid,
1217+
accessmtd,
12131218
tupdesc,
12141219
relkind,
12151220
relpersistence,
@@ -1366,6 +1371,22 @@ heap_create_with_catalog(const char *relname,
13661371
referenced.objectSubId = 0;
13671372
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
13681373
}
1374+
1375+
/*
1376+
* Make a dependency link to force the relation to be deleted if its
1377+
* access method is. Do this only for relation and materialized views.
1378+
*
1379+
* No need to add an explicit dependency for the toast table, as the
1380+
* main table depends on it.
1381+
*/
1382+
if (relkind == RELKIND_RELATION ||
1383+
relkind == RELKIND_MATVIEW)
1384+
{
1385+
referenced.classId = AccessMethodRelationId;
1386+
referenced.objectId = accessmtd;
1387+
referenced.objectSubId = 0;
1388+
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
1389+
}
13691390
}
13701391

13711392
/* Post creation hook for new relation */

src/backend/catalog/index.c

+1
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,7 @@ index_create(Relation heapRelation,
907907
tableSpaceId,
908908
indexRelationId,
909909
relFileNode,
910+
accessMethodObjectId,
910911
indexTupDesc,
911912
relkind,
912913
relpersistence,

src/backend/catalog/toasting.c

+1
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
267267
toast_typid,
268268
InvalidOid,
269269
rel->rd_rel->relowner,
270+
rel->rd_rel->relam,
270271
tupdesc,
271272
NIL,
272273
RELKIND_TOASTVALUE,

0 commit comments

Comments
 (0)