aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/parser/parse_utilcmd.c24
-rw-r--r--src/test/regress/expected/create_table_like.out103
-rw-r--r--src/test/regress/sql/create_table_like.sql42
3 files changed, 158 insertions, 11 deletions
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index eb7716cd84c..abbe1bb45a3 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -1131,6 +1131,10 @@ transformTableConstraint(CreateStmtContext *cxt, Constraint *constraint)
* process at this point, add the TableLikeClause to cxt->likeclauses, which
* will cause utility.c to call expandTableLikeClause() after the new
* table has been created.
+ *
+ * Some options are ignored. For example, as foreign tables have no storage,
+ * these INCLUDING options have no effect: STORAGE, COMPRESSION, IDENTITY
+ * and INDEXES. Similarly, INCLUDING INDEXES is ignored from a view.
*/
static void
transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_clause)
@@ -1145,12 +1149,6 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
setup_parser_errposition_callback(&pcbstate, cxt->pstate,
table_like_clause->relation->location);
- /* we could support LIKE in many cases, but worry about it another day */
- if (cxt->isforeign)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("LIKE is not supported for creating foreign tables")));
-
/* Open the relation referenced by the LIKE clause */
relation = relation_openrv(table_like_clause->relation, AccessShareLock);
@@ -1231,7 +1229,8 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
* Copy identity if requested
*/
if (attribute->attidentity &&
- (table_like_clause->options & CREATE_TABLE_LIKE_IDENTITY))
+ (table_like_clause->options & CREATE_TABLE_LIKE_IDENTITY) &&
+ !cxt->isforeign)
{
Oid seq_relid;
List *seq_options;
@@ -1250,14 +1249,16 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
}
/* Likewise, copy storage if requested */
- if (table_like_clause->options & CREATE_TABLE_LIKE_STORAGE)
+ if ((table_like_clause->options & CREATE_TABLE_LIKE_STORAGE) &&
+ !cxt->isforeign)
def->storage = attribute->attstorage;
else
def->storage = 0;
/* Likewise, copy compression if requested */
- if ((table_like_clause->options & CREATE_TABLE_LIKE_COMPRESSION) != 0
- && CompressionMethodIsValid(attribute->attcompression))
+ if ((table_like_clause->options & CREATE_TABLE_LIKE_COMPRESSION) != 0 &&
+ CompressionMethodIsValid(attribute->attcompression) &&
+ !cxt->isforeign)
def->compression =
pstrdup(GetCompressionMethodName(attribute->attcompression));
else
@@ -1536,7 +1537,8 @@ expandTableLikeClause(RangeVar *heapRel, TableLikeClause *table_like_clause)
* Process indexes if required.
*/
if ((table_like_clause->options & CREATE_TABLE_LIKE_INDEXES) &&
- relation->rd_rel->relhasindex)
+ relation->rd_rel->relhasindex &&
+ childrel->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
{
List *parent_indexes;
ListCell *l;
diff --git a/src/test/regress/expected/create_table_like.out b/src/test/regress/expected/create_table_like.out
index 2cebe382432..bf34289e984 100644
--- a/src/test/regress/expected/create_table_like.out
+++ b/src/test/regress/expected/create_table_like.out
@@ -566,3 +566,106 @@ DROP TYPE ctlty1;
DROP VIEW ctlv1;
DROP TABLE IF EXISTS ctlt4, ctlt10, ctlt11, ctlt11a, ctlt12;
NOTICE: table "ctlt10" does not exist, skipping
+--
+-- CREATE FOREIGN TABLE LIKE
+--
+CREATE FOREIGN DATA WRAPPER ctl_dummy;
+CREATE SERVER ctl_s0 FOREIGN DATA WRAPPER ctl_dummy;
+CREATE TABLE ctl_table(a int PRIMARY KEY,
+ b varchar COMPRESSION pglz,
+ c int GENERATED ALWAYS AS (a * 2) STORED,
+ d bigint GENERATED ALWAYS AS IDENTITY,
+ e int DEFAULT 1);
+CREATE INDEX ctl_table_a_key ON ctl_table(a);
+COMMENT ON COLUMN ctl_table.b IS 'Column b';
+CREATE STATISTICS ctl_table_stat ON a,b FROM ctl_table;
+ALTER TABLE ctl_table ADD CONSTRAINT foo CHECK (b = 'text');
+ALTER TABLE ctl_table ALTER COLUMN b SET STORAGE MAIN;
+\d+ ctl_table
+ Table "public.ctl_table"
+ Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
+--------+-------------------+-----------+----------+------------------------------------+---------+--------------+-------------
+ a | integer | | not null | | plain | |
+ b | character varying | | | | main | | Column b
+ c | integer | | | generated always as (a * 2) stored | plain | |
+ d | bigint | | not null | generated always as identity | plain | |
+ e | integer | | | 1 | plain | |
+Indexes:
+ "ctl_table_pkey" PRIMARY KEY, btree (a)
+ "ctl_table_a_key" btree (a)
+Check constraints:
+ "foo" CHECK (b::text = 'text'::text)
+Statistics objects:
+ "public.ctl_table_stat" ON a, b FROM ctl_table
+Not-null constraints:
+ "ctl_table_a_not_null" NOT NULL "a"
+ "ctl_table_d_not_null" NOT NULL "d"
+
+-- Test EXCLUDING ALL
+CREATE FOREIGN TABLE ctl_foreign_table1(LIKE ctl_table EXCLUDING ALL) SERVER ctl_s0;
+\d+ ctl_foreign_table1
+ Foreign table "public.ctl_foreign_table1"
+ Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description
+--------+-------------------+-----------+----------+---------+-------------+----------+--------------+-------------
+ a | integer | | not null | | | plain | |
+ b | character varying | | | | | extended | |
+ c | integer | | | | | plain | |
+ d | bigint | | not null | | | plain | |
+ e | integer | | | | | plain | |
+Not-null constraints:
+ "ctl_table_a_not_null" NOT NULL "a"
+ "ctl_table_d_not_null" NOT NULL "d"
+Server: ctl_s0
+
+-- \d+ does not report the value of attcompression for a foreign table, so
+-- check separately.
+SELECT attname, attcompression FROM pg_attribute
+ WHERE attrelid = 'ctl_foreign_table1'::regclass and attnum > 0 ORDER BY attnum;
+ attname | attcompression
+---------+----------------
+ a |
+ b |
+ c |
+ d |
+ e |
+(5 rows)
+
+-- Test INCLUDING ALL
+-- INDEXES, IDENTITY, COMPRESSION, STORAGE are not copied.
+CREATE FOREIGN TABLE ctl_foreign_table2(LIKE ctl_table INCLUDING ALL) SERVER ctl_s0;
+\d+ ctl_foreign_table2
+ Foreign table "public.ctl_foreign_table2"
+ Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description
+--------+-------------------+-----------+----------+------------------------------------+-------------+----------+--------------+-------------
+ a | integer | | not null | | | plain | |
+ b | character varying | | | | | extended | | Column b
+ c | integer | | | generated always as (a * 2) stored | | plain | |
+ d | bigint | | not null | | | plain | |
+ e | integer | | | 1 | | plain | |
+Check constraints:
+ "foo" CHECK (b::text = 'text'::text)
+Statistics objects:
+ "public.ctl_foreign_table2_a_b_stat" ON a, b FROM ctl_foreign_table2
+Not-null constraints:
+ "ctl_table_a_not_null" NOT NULL "a"
+ "ctl_table_d_not_null" NOT NULL "d"
+Server: ctl_s0
+
+-- \d+ does not report the value of attcompression for a foreign table, so
+-- check separately.
+SELECT attname, attcompression FROM pg_attribute
+ WHERE attrelid = 'ctl_foreign_table2'::regclass and attnum > 0 ORDER BY attnum;
+ attname | attcompression
+---------+----------------
+ a |
+ b |
+ c |
+ d |
+ e |
+(5 rows)
+
+DROP TABLE ctl_table;
+DROP FOREIGN TABLE ctl_foreign_table1;
+DROP FOREIGN TABLE ctl_foreign_table2;
+DROP FOREIGN DATA WRAPPER ctl_dummy CASCADE;
+NOTICE: drop cascades to server ctl_s0
diff --git a/src/test/regress/sql/create_table_like.sql b/src/test/regress/sql/create_table_like.sql
index 63a60303659..6e21722aaeb 100644
--- a/src/test/regress/sql/create_table_like.sql
+++ b/src/test/regress/sql/create_table_like.sql
@@ -225,3 +225,45 @@ DROP SEQUENCE ctlseq1;
DROP TYPE ctlty1;
DROP VIEW ctlv1;
DROP TABLE IF EXISTS ctlt4, ctlt10, ctlt11, ctlt11a, ctlt12;
+
+--
+-- CREATE FOREIGN TABLE LIKE
+--
+CREATE FOREIGN DATA WRAPPER ctl_dummy;
+CREATE SERVER ctl_s0 FOREIGN DATA WRAPPER ctl_dummy;
+
+CREATE TABLE ctl_table(a int PRIMARY KEY,
+ b varchar COMPRESSION pglz,
+ c int GENERATED ALWAYS AS (a * 2) STORED,
+ d bigint GENERATED ALWAYS AS IDENTITY,
+ e int DEFAULT 1);
+
+CREATE INDEX ctl_table_a_key ON ctl_table(a);
+COMMENT ON COLUMN ctl_table.b IS 'Column b';
+CREATE STATISTICS ctl_table_stat ON a,b FROM ctl_table;
+ALTER TABLE ctl_table ADD CONSTRAINT foo CHECK (b = 'text');
+ALTER TABLE ctl_table ALTER COLUMN b SET STORAGE MAIN;
+
+\d+ ctl_table
+
+-- Test EXCLUDING ALL
+CREATE FOREIGN TABLE ctl_foreign_table1(LIKE ctl_table EXCLUDING ALL) SERVER ctl_s0;
+\d+ ctl_foreign_table1
+-- \d+ does not report the value of attcompression for a foreign table, so
+-- check separately.
+SELECT attname, attcompression FROM pg_attribute
+ WHERE attrelid = 'ctl_foreign_table1'::regclass and attnum > 0 ORDER BY attnum;
+
+-- Test INCLUDING ALL
+-- INDEXES, IDENTITY, COMPRESSION, STORAGE are not copied.
+CREATE FOREIGN TABLE ctl_foreign_table2(LIKE ctl_table INCLUDING ALL) SERVER ctl_s0;
+\d+ ctl_foreign_table2
+-- \d+ does not report the value of attcompression for a foreign table, so
+-- check separately.
+SELECT attname, attcompression FROM pg_attribute
+ WHERE attrelid = 'ctl_foreign_table2'::regclass and attnum > 0 ORDER BY attnum;
+
+DROP TABLE ctl_table;
+DROP FOREIGN TABLE ctl_foreign_table1;
+DROP FOREIGN TABLE ctl_foreign_table2;
+DROP FOREIGN DATA WRAPPER ctl_dummy CASCADE;