agora inbox for [email protected]
help / color / mirror / Atom feed[PATCH v4] create table (like .. including ACCESS METHOD)
28+ messages / 3 participants
[nested] [flat]
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v4] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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 c6c248f1e9..dd92fd0e9a 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 } { ACCESS METHOD | COMMENTS | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | ALL }
<phrase>and <replaceable class="parameter">partition_bound_spec</replaceable> is:</phrase>
@@ -613,6 +613,16 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
available options are:
<variablelist>
+ <varlistentry>
+ <term><literal>INCLUDING 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 COMMENTS</literal></term>
<listitem>
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index bc43641ffe..383e0671af 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -3741,6 +3741,7 @@ TableLikeOption:
| STATISTICS { $$ = CREATE_TABLE_LIKE_STATISTICS; }
| STORAGE { $$ = CREATE_TABLE_LIKE_STORAGE; }
| COMPRESSION { $$ = CREATE_TABLE_LIKE_COMPRESSION; }
+ | ACCESS METHOD { $$ = CREATE_TABLE_LIKE_ACCESS_METHOD; }
| ALL { $$ = CREATE_TABLE_LIKE_ALL; }
;
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index aa6c19adad..07e18fa62f 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -97,6 +97,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 */
@@ -253,6 +254,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 */
@@ -347,6 +349,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);
@@ -1137,6 +1142,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_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 68425eb2c0..5e2fc9baca 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -696,6 +696,7 @@ typedef enum TableLikeOption
CREATE_TABLE_LIKE_STATISTICS = 1 << 6,
CREATE_TABLE_LIKE_STORAGE = 1 << 7,
CREATE_TABLE_LIKE_COMPRESSION = 1 << 8,
+ CREATE_TABLE_LIKE_ACCESS_METHOD = 1 << 9,
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
--UnaWdueM1EBWVRzC--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v5] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
doc/src/sgml/ref/create_table.sgml | 22 ++++++++++++++++++-
src/backend/parser/gram.y | 3 ++-
src/backend/parser/parse_utilcmd.c | 10 +++++++++
src/include/nodes/parsenodes.h | 19 ++++++++--------
.../regress/expected/create_table_like.out | 12 ++++++++++
src/test/regress/sql/create_table_like.sql | 8 +++++++
6 files changed, 63 insertions(+), 11 deletions(-)
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index c6d0a35e50..ab84ca8718 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 | COMPRESSION | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | ALL }
+{ INCLUDING | EXCLUDING } { ACCESS METHOD | COMMENTS | COMPRESSION | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | ALL }
<phrase>and <replaceable class="parameter">partition_bound_spec</replaceable> is:</phrase>
@@ -618,6 +618,16 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
available options are:
<variablelist>
+ <varlistentry>
+ <term><literal>INCLUDING 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 COMMENTS</literal></term>
<listitem>
@@ -725,6 +735,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 9ee90e3f13..c8991cead9 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -3754,7 +3754,8 @@ TableLikeOptionList:
;
TableLikeOption:
- COMMENTS { $$ = CREATE_TABLE_LIKE_COMMENTS; }
+ ACCESS METHOD { $$ = CREATE_TABLE_LIKE_ACCESS_METHOD; }
+ | COMMENTS { $$ = CREATE_TABLE_LIKE_COMMENTS; }
| COMPRESSION { $$ = CREATE_TABLE_LIKE_COMPRESSION; }
| CONSTRAINTS { $$ = CREATE_TABLE_LIKE_CONSTRAINTS; }
| DEFAULTS { $$ = CREATE_TABLE_LIKE_DEFAULTS; }
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index d5b67d48cf..0cdea516ac 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -97,6 +97,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 */
@@ -349,6 +351,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);
@@ -1139,6 +1144,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_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 ef73342019..726f15f78a 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -689,15 +689,16 @@ typedef struct TableLikeClause
typedef enum TableLikeOption
{
- CREATE_TABLE_LIKE_COMMENTS = 1 << 0,
- CREATE_TABLE_LIKE_COMPRESSION = 1 << 1,
- CREATE_TABLE_LIKE_CONSTRAINTS = 1 << 2,
- CREATE_TABLE_LIKE_DEFAULTS = 1 << 3,
- CREATE_TABLE_LIKE_GENERATED = 1 << 4,
- CREATE_TABLE_LIKE_IDENTITY = 1 << 5,
- CREATE_TABLE_LIKE_INDEXES = 1 << 6,
- CREATE_TABLE_LIKE_STATISTICS = 1 << 7,
- CREATE_TABLE_LIKE_STORAGE = 1 << 8,
+ CREATE_TABLE_LIKE_ACCESS_METHOD = 1 << 0,
+ CREATE_TABLE_LIKE_COMMENTS = 1 << 1,
+ CREATE_TABLE_LIKE_COMPRESSION = 1 << 2,
+ CREATE_TABLE_LIKE_CONSTRAINTS = 1 << 3,
+ CREATE_TABLE_LIKE_DEFAULTS = 1 << 4,
+ CREATE_TABLE_LIKE_GENERATED = 1 << 5,
+ CREATE_TABLE_LIKE_IDENTITY = 1 << 6,
+ CREATE_TABLE_LIKE_INDEXES = 1 << 7,
+ CREATE_TABLE_LIKE_STATISTICS = 1 << 8,
+ CREATE_TABLE_LIKE_STORAGE = 1 << 9,
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 4dc5e6aa5f..68411e3a84 100644
--- a/src/test/regress/expected/create_table_like.out
+++ b/src/test/regress/expected/create_table_like.out
@@ -433,6 +433,18 @@ SELECT s.stxname, objsubid, description FROM pg_description, pg_statistic_ext s
ctlt_all_expr_stat | 0 | ab expr stats
(2 rows)
+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 4929d373a2..1845b9adb5 100644
--- a/src/test/regress/sql/create_table_like.sql
+++ b/src/test/regress/sql/create_table_like.sql
@@ -167,6 +167,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
--azLHFNyN32YCQGCU--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v1] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
doc/src/sgml/ref/create_table.sgml | 12 +++++++++++-
src/backend/parser/gram.y | 3 ++-
src/backend/parser/parse_utilcmd.c | 7 +++++++
src/include/nodes/parsenodes.h | 17 +++++++++--------
src/test/regress/expected/create_table_like.out | 2 +-
src/test/regress/sql/create_table_like.sql | 2 +-
6 files changed, 31 insertions(+), 12 deletions(-)
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index 569f4c9da7..cb95177e92 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 } { ACCESS METHOD | COMMENTS | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | ALL }
<phrase>and <replaceable class="parameter">partition_bound_spec</replaceable> is:</phrase>
@@ -593,6 +593,16 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
available options are:
<variablelist>
+ <varlistentry>
+ <term><literal>INCLUDING 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 COMMENTS</literal></term>
<listitem>
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 8f341ac006..b32861a04e 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -3651,7 +3651,8 @@ TableLikeOptionList:
;
TableLikeOption:
- COMMENTS { $$ = CREATE_TABLE_LIKE_COMMENTS; }
+ ACCESS METHOD { $$ = CREATE_TABLE_LIKE_ACCESSMETHOD; }
+ | COMMENTS { $$ = CREATE_TABLE_LIKE_COMMENTS; }
| CONSTRAINTS { $$ = CREATE_TABLE_LIKE_CONSTRAINTS; }
| DEFAULTS { $$ = CREATE_TABLE_LIKE_DEFAULTS; }
| IDENTITY_P { $$ = CREATE_TABLE_LIKE_IDENTITY; }
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 89ee990599..3507fd4738 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 */
@@ -345,6 +347,8 @@ 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);
@@ -1118,6 +1122,9 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
cxt->likeclauses = lappend(cxt->likeclauses, table_like_clause);
}
+ if (table_like_clause->options & CREATE_TABLE_LIKE_ACCESSMETHOD)
+ 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 48a79a7657..589fd0cab0 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -677,14 +677,15 @@ typedef struct TableLikeClause
typedef enum TableLikeOption
{
- CREATE_TABLE_LIKE_COMMENTS = 1 << 0,
- CREATE_TABLE_LIKE_CONSTRAINTS = 1 << 1,
- CREATE_TABLE_LIKE_DEFAULTS = 1 << 2,
- CREATE_TABLE_LIKE_GENERATED = 1 << 3,
- CREATE_TABLE_LIKE_IDENTITY = 1 << 4,
- CREATE_TABLE_LIKE_INDEXES = 1 << 5,
- CREATE_TABLE_LIKE_STATISTICS = 1 << 6,
- CREATE_TABLE_LIKE_STORAGE = 1 << 7,
+ CREATE_TABLE_LIKE_ACCESSMETHOD = 1 << 0,
+ CREATE_TABLE_LIKE_COMMENTS = 1 << 1,
+ CREATE_TABLE_LIKE_CONSTRAINTS = 1 << 2,
+ CREATE_TABLE_LIKE_DEFAULTS = 1 << 3,
+ CREATE_TABLE_LIKE_GENERATED = 1 << 4,
+ CREATE_TABLE_LIKE_IDENTITY = 1 << 5,
+ CREATE_TABLE_LIKE_INDEXES = 1 << 6,
+ CREATE_TABLE_LIKE_STATISTICS = 1 << 7,
+ CREATE_TABLE_LIKE_STORAGE = 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..cac3c57c76 100644
--- a/src/test/regress/expected/create_table_like.out
+++ b/src/test/regress/expected/create_table_like.out
@@ -490,7 +490,7 @@ Check constraints:
"noinh_con_copy_a_check" CHECK (a > 0) NO INHERIT
-- fail, as partitioned tables don't allow NO INHERIT constraints
-CREATE TABLE noinh_con_copy1_parted (LIKE noinh_con_copy INCLUDING ALL)
+CREATE TABLE noinh_con_copy1_parted (LIKE noinh_con_copy INCLUDING ALL EXCLUDING ACCESS METHOD)
PARTITION BY LIST (a);
ERROR: cannot add NO INHERIT constraint to partitioned table "noinh_con_copy1_parted"
DROP TABLE noinh_con_copy, noinh_con_copy1;
diff --git a/src/test/regress/sql/create_table_like.sql b/src/test/regress/sql/create_table_like.sql
index 06b76f949d..eda9f39078 100644
--- a/src/test/regress/sql/create_table_like.sql
+++ b/src/test/regress/sql/create_table_like.sql
@@ -189,7 +189,7 @@ CREATE TABLE noinh_con_copy1 (LIKE noinh_con_copy INCLUDING CONSTRAINTS);
\d noinh_con_copy1
-- fail, as partitioned tables don't allow NO INHERIT constraints
-CREATE TABLE noinh_con_copy1_parted (LIKE noinh_con_copy INCLUDING ALL)
+CREATE TABLE noinh_con_copy1_parted (LIKE noinh_con_copy INCLUDING ALL EXCLUDING ACCESS METHOD)
PARTITION BY LIST (a);
DROP TABLE noinh_con_copy, noinh_con_copy1;
--
2.17.0
--ClNI7qcIuZbdM87U--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v2] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
doc/src/sgml/ref/create_table.sgml | 12 +++++++++++-
src/backend/parser/gram.y | 3 ++-
src/backend/parser/parse_utilcmd.c | 10 ++++++++++
src/include/nodes/parsenodes.h | 17 +++++++++--------
src/test/regress/expected/create_table_like.out | 12 ++++++++++++
src/test/regress/sql/create_table_like.sql | 8 ++++++++
6 files changed, 52 insertions(+), 10 deletions(-)
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index 569f4c9da7..cb95177e92 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 } { ACCESS METHOD | COMMENTS | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | STORAGE | ALL }
<phrase>and <replaceable class="parameter">partition_bound_spec</replaceable> is:</phrase>
@@ -593,6 +593,16 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
available options are:
<variablelist>
+ <varlistentry>
+ <term><literal>INCLUDING 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 COMMENTS</literal></term>
<listitem>
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 8f341ac006..fee0aceb65 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -3651,7 +3651,8 @@ TableLikeOptionList:
;
TableLikeOption:
- COMMENTS { $$ = CREATE_TABLE_LIKE_COMMENTS; }
+ ACCESS METHOD { $$ = CREATE_TABLE_LIKE_ACCESS_METHOD; }
+ | COMMENTS { $$ = CREATE_TABLE_LIKE_COMMENTS; }
| CONSTRAINTS { $$ = CREATE_TABLE_LIKE_CONSTRAINTS; }
| DEFAULTS { $$ = CREATE_TABLE_LIKE_DEFAULTS; }
| IDENTITY_P { $$ = CREATE_TABLE_LIKE_IDENTITY; }
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 89ee990599..4eed7e3ea2 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);
}
+ /* CREATE TABLE LIKE ACCESS METHOD is not copied for partitioned table */
+ if ((table_like_clause->options & CREATE_TABLE_LIKE_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 48a79a7657..2d5dfe487e 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -677,14 +677,15 @@ typedef struct TableLikeClause
typedef enum TableLikeOption
{
- CREATE_TABLE_LIKE_COMMENTS = 1 << 0,
- CREATE_TABLE_LIKE_CONSTRAINTS = 1 << 1,
- CREATE_TABLE_LIKE_DEFAULTS = 1 << 2,
- CREATE_TABLE_LIKE_GENERATED = 1 << 3,
- CREATE_TABLE_LIKE_IDENTITY = 1 << 4,
- CREATE_TABLE_LIKE_INDEXES = 1 << 5,
- CREATE_TABLE_LIKE_STATISTICS = 1 << 6,
- CREATE_TABLE_LIKE_STORAGE = 1 << 7,
+ CREATE_TABLE_LIKE_ACCESS_METHOD = 1 << 0,
+ CREATE_TABLE_LIKE_COMMENTS = 1 << 1,
+ CREATE_TABLE_LIKE_CONSTRAINTS = 1 << 2,
+ CREATE_TABLE_LIKE_DEFAULTS = 1 << 3,
+ CREATE_TABLE_LIKE_GENERATED = 1 << 4,
+ CREATE_TABLE_LIKE_IDENTITY = 1 << 5,
+ CREATE_TABLE_LIKE_INDEXES = 1 << 6,
+ CREATE_TABLE_LIKE_STATISTICS = 1 << 7,
+ CREATE_TABLE_LIKE_STORAGE = 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
--3V7upXqbjpZ4EhLz--
^ permalink raw reply [nested|flat] 28+ messages in thread
* [PATCH v3] create table (like .. including ACCESS METHOD)
@ 2020-11-15 22:54 Justin Pryzby <[email protected]>
0 siblings, 0 replies; 28+ messages in thread
From: Justin Pryzby @ 2020-11-15 22:54 UTC (permalink / raw)
---
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
--T6xhMxlHU34Bk0ad--
^ permalink raw reply [nested|flat] 28+ messages in thread
* Crash on UNION with PG 17
@ 2024-03-27 15:33 Regina Obe <[email protected]>
2024-03-27 23:46 ` Re: Crash on UNION with PG 17 David Rowley <[email protected]>
2024-04-01 23:25 ` Re: Crash on UNION with PG 17 David Rowley <[email protected]>
0 siblings, 2 replies; 28+ messages in thread
From: Regina Obe @ 2024-03-27 15:33 UTC (permalink / raw)
To: 'Postgres hackers' <[email protected]>
Our PostGIS bot that follows master branch has been crashing for past couple
of days on one of our tests
https://trac.osgeo.org/postgis/ticket/5701
I traced the issue down to this commit:
https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=66c0185a3d14b
bbf51d0fc9d267093ffec735231
The issue can be exercised without postgis installed as follows:
CREATE TABLE edge_data AS
SELECT i AS edge_id, i + 1 AS start_node, i + 2 As end_node
FROM generate_series(1,10) AS i;
WITH edge AS (
SELECT start_node, end_node
FROM edge_data
WHERE edge_id = 1
)
SELECT start_node id FROM edge UNION
SELECT end_node FROM edge;
If I run using UNION ALL, this works fine:
WITH edge AS (
SELECT start_node, end_node
FROM edge_data
WHERE edge_id = 1
)
SELECT start_node id FROM edge UNION ALL
SELECT end_node FROM edge;
Thanks,
Regina
^ permalink raw reply [nested|flat] 28+ messages in thread
* Re: Crash on UNION with PG 17
2024-03-27 15:33 Crash on UNION with PG 17 Regina Obe <[email protected]>
@ 2024-03-27 23:46 ` David Rowley <[email protected]>
1 sibling, 0 replies; 28+ messages in thread
From: David Rowley @ 2024-03-27 23:46 UTC (permalink / raw)
To: Regina Obe <[email protected]>; +Cc: Postgres hackers <[email protected]>
On Thu, 28 Mar 2024 at 04:34, Regina Obe <[email protected]> wrote:
> The issue can be exercised without postgis installed as follows:
>
>
> CREATE TABLE edge_data AS
> SELECT i AS edge_id, i + 1 AS start_node, i + 2 As end_node
> FROM generate_series(1,10) AS i;
>
> WITH edge AS (
> SELECT start_node, end_node
> FROM edge_data
> WHERE edge_id = 1
> )
> SELECT start_node id FROM edge UNION
> SELECT end_node FROM edge;
Thanks for the report.
There's some discussion about this in [1] along with a proposed way to
fix it. The proposed fix does alter the function signature of an
important and externally visible planner function, so will be waiting
for some feedback on that before moving ahead with fixing.
[1] https://www.postgresql.org/message-id/[email protected]
David
^ permalink raw reply [nested|flat] 28+ messages in thread
* Re: Crash on UNION with PG 17
2024-03-27 15:33 Crash on UNION with PG 17 Regina Obe <[email protected]>
@ 2024-04-01 23:25 ` David Rowley <[email protected]>
1 sibling, 0 replies; 28+ messages in thread
From: David Rowley @ 2024-04-01 23:25 UTC (permalink / raw)
To: Regina Obe <[email protected]>; +Cc: Postgres hackers <[email protected]>
On Thu, 28 Mar 2024 at 04:34, Regina Obe <[email protected]> wrote:
> CREATE TABLE edge_data AS
> SELECT i AS edge_id, i + 1 AS start_node, i + 2 As end_node
> FROM generate_series(1,10) AS i;
>
> WITH edge AS (
> SELECT start_node, end_node
> FROM edge_data
> WHERE edge_id = 1
> )
> SELECT start_node id FROM edge UNION
> SELECT end_node FROM edge;
As of d5d2205c8, this query should work as expected.
Thank you for letting us know about this.
David
^ permalink raw reply [nested|flat] 28+ messages in thread
end of thread, other threads:[~2024-04-01 23:25 UTC | newest]
Thread overview: 28+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v4] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v5] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v1] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v2] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2020-11-15 22:54 [PATCH v3] create table (like .. including ACCESS METHOD) Justin Pryzby <[email protected]>
2024-03-27 15:33 Crash on UNION with PG 17 Regina Obe <[email protected]>
2024-03-27 23:46 ` Re: Crash on UNION with PG 17 David Rowley <[email protected]>
2024-04-01 23:25 ` Re: Crash on UNION with PG 17 David Rowley <[email protected]>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox