On Wed, Dec 30, 2020 at 12:33:56PM +0000, Simon Riggs wrote: > There are no tests for the new functionality, please could you add some?
Did you look at the most recent patch? +CREATE ACCESS METHOD heapdup TYPE TABLE HANDLER heap_tableam_handler; +CREATE TABLE likeam() USING heapdup; +CREATE TABLE likeamlike(LIKE likeam INCLUDING ALL); Also, I just realized that Dilip's toast compression patch adds "INCLUDING COMPRESSION", which is stored in pg_am. That's an implementation detail of that patch, but it's not intuitive that "including access method" wouldn't include the compression stored there. So I think this should use "INCLUDING TABLE ACCESS METHOD" not just ACCESS METHOD. -- Justin
>From f27fd6291aa10af1ca0be4bc72a656811c8e0c9f Mon Sep 17 00:00:00 2001 From: Justin Pryzby <pryz...@telsasoft.com> Date: Sun, 15 Nov 2020 16:54:53 -0600 Subject: [PATCH v3] create table (like .. including ACCESS METHOD) --- doc/src/sgml/ref/create_table.sgml | 12 +++++++++++- src/backend/parser/gram.y | 1 + src/backend/parser/parse_utilcmd.c | 10 ++++++++++ src/include/nodes/parsenodes.h | 1 + src/test/regress/expected/create_table_like.out | 12 ++++++++++++ src/test/regress/sql/create_table_like.sql | 8 ++++++++ 6 files changed, 43 insertions(+), 1 deletion(-) diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml index 569f4c9da7..e3c607f6b1 100644 --- a/doc/src/sgml/ref/create_table.sgml +++ b/doc/src/sgml/ref/create_table.sgml @@ -87,7 +87,7 @@ class="parameter">referential_action</replaceable> ] [ ON UPDATE <replaceable cl <phrase>and <replaceable class="parameter">like_option</replaceable> is:</phrase> -{ INCLUDING | EXCLUDING } { COMMENTS | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | ALL } +{ INCLUDING | EXCLUDING } { COMMENTS | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | TABLE ACCESS METHOD | ALL } <phrase>and <replaceable class="parameter">partition_bound_spec</replaceable> is:</phrase> @@ -689,6 +689,16 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM </listitem> </varlistentry> + <varlistentry> + <term><literal>INCLUDING TABLE ACCESS METHOD</literal></term> + <listitem> + <para> + The table's access method will be copied. By default, the + <literal>default_table_access_method</literal> is used. + </para> + </listitem> + </varlistentry> + <varlistentry> <term><literal>INCLUDING ALL</literal></term> <listitem> diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 31c95443a5..719ac838e3 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -3708,6 +3708,7 @@ TableLikeOption: | INDEXES { $$ = CREATE_TABLE_LIKE_INDEXES; } | STATISTICS { $$ = CREATE_TABLE_LIKE_STATISTICS; } | STORAGE { $$ = CREATE_TABLE_LIKE_STORAGE; } + | TABLE ACCESS METHOD { $$ = CREATE_TABLE_LIKE_TABLE_ACCESS_METHOD; } | ALL { $$ = CREATE_TABLE_LIKE_ALL; } ; diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index b31f3afa03..f34f42aae3 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -96,6 +96,7 @@ typedef struct bool ispartitioned; /* true if table is partitioned */ PartitionBoundSpec *partbound; /* transformed FOR VALUES */ bool ofType; /* true if statement contains OF typename */ + char *accessMethod; /* table access method */ } CreateStmtContext; /* State shared by transformCreateSchemaStmt and its subroutines */ @@ -252,6 +253,7 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString) cxt.ispartitioned = stmt->partspec != NULL; cxt.partbound = stmt->partbound; cxt.ofType = (stmt->ofTypename != NULL); + cxt.accessMethod = NULL; Assert(!stmt->ofTypename || !stmt->inhRelations); /* grammar enforces */ @@ -346,6 +348,9 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString) stmt->tableElts = cxt.columns; stmt->constraints = cxt.ckconstraints; + if (cxt.accessMethod != NULL) + stmt->accessMethod = cxt.accessMethod; + result = lappend(cxt.blist, stmt); result = list_concat(result, cxt.alist); result = list_concat(result, save_alist); @@ -1118,6 +1123,11 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla cxt->likeclauses = lappend(cxt->likeclauses, table_like_clause); } + /* ACCESS METHOD doesn't apply and isn't copied for partitioned tables */ + if ((table_like_clause->options & CREATE_TABLE_LIKE_TABLE_ACCESS_METHOD) != 0 && + !cxt->ispartitioned) + cxt->accessMethod = get_am_name(relation->rd_rel->relam); + /* * We may copy extended statistics if requested, since the representation * of CreateStatsStmt doesn't depend on column numbers. diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index dc2bb40926..600856c229 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -685,6 +685,7 @@ typedef enum TableLikeOption CREATE_TABLE_LIKE_INDEXES = 1 << 5, CREATE_TABLE_LIKE_STATISTICS = 1 << 6, CREATE_TABLE_LIKE_STORAGE = 1 << 7, + CREATE_TABLE_LIKE_TABLE_ACCESS_METHOD = 1 << 8, CREATE_TABLE_LIKE_ALL = PG_INT32_MAX } TableLikeOption; diff --git a/src/test/regress/expected/create_table_like.out b/src/test/regress/expected/create_table_like.out index 10d17be23c..a09cd48ed0 100644 --- a/src/test/regress/expected/create_table_like.out +++ b/src/test/regress/expected/create_table_like.out @@ -429,6 +429,18 @@ SELECT s.stxname, objsubid, description FROM pg_description, pg_statistic_ext s ctlt_all_a_b_stat | 0 | ab stats (1 row) +CREATE ACCESS METHOD heapdup TYPE TABLE HANDLER heap_tableam_handler; +CREATE TABLE likeam() USING heapdup; +CREATE TABLE likeamlike(LIKE likeam INCLUDING ALL); +-- pg_regress helpfully hides the Access Method output, which we need: +SELECT a.amname FROM pg_class c JOIN pg_am a ON c.relam=a.oid WHERE c.oid='likeamlike'::regclass; + amname +--------- + heapdup +(1 row) + +DROP TABLE likeam, likeamlike; +DROP ACCESS METHOD heapdup; CREATE TABLE inh_error1 () INHERITS (ctlt1, ctlt4); NOTICE: merging multiple inherited definitions of column "a" ERROR: inherited column "a" has a storage parameter conflict diff --git a/src/test/regress/sql/create_table_like.sql b/src/test/regress/sql/create_table_like.sql index 06b76f949d..ee6c464851 100644 --- a/src/test/regress/sql/create_table_like.sql +++ b/src/test/regress/sql/create_table_like.sql @@ -165,6 +165,14 @@ CREATE TABLE ctlt_all (LIKE ctlt1 INCLUDING ALL); SELECT c.relname, objsubid, description FROM pg_description, pg_index i, pg_class c WHERE classoid = 'pg_class'::regclass AND objoid = i.indexrelid AND c.oid = i.indexrelid AND i.indrelid = 'ctlt_all'::regclass ORDER BY c.relname, objsubid; SELECT s.stxname, objsubid, description FROM pg_description, pg_statistic_ext s WHERE classoid = 'pg_statistic_ext'::regclass AND objoid = s.oid AND s.stxrelid = 'ctlt_all'::regclass ORDER BY s.stxname, objsubid; +CREATE ACCESS METHOD heapdup TYPE TABLE HANDLER heap_tableam_handler; +CREATE TABLE likeam() USING heapdup; +CREATE TABLE likeamlike(LIKE likeam INCLUDING ALL); +-- pg_regress helpfully hides the Access Method output, which we need: +SELECT a.amname FROM pg_class c JOIN pg_am a ON c.relam=a.oid WHERE c.oid='likeamlike'::regclass; +DROP TABLE likeam, likeamlike; +DROP ACCESS METHOD heapdup; + CREATE TABLE inh_error1 () INHERITS (ctlt1, ctlt4); CREATE TABLE inh_error2 (LIKE ctlt4 INCLUDING STORAGE) INHERITS (ctlt1); -- 2.17.0