summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2019-09-25 17:30:42 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2019-09-25 17:30:42 -0400
commit658d391d87c13a4b27425a2fd014f2162956ad4d (patch)
tree5dc2380f8989d9d75ad4094ba1d274a62c7ce6df
parent37ad1266147626bfe505b2c5b016497605915a8e (diff)
Fix handling of GENERATED columns in CREATE TABLE LIKE INCLUDING DEFAULTS.
LIKE INCLUDING DEFAULTS tried to copy the attrdef expression without copying the state of the attgenerated column. This is in fact wrong, because GENERATED and DEFAULT expressions are not the same kind of animal; one can contain Vars and the other not. We *must* copy attgenerated when we're copying the attrdef expression. Rearrange the if-tests so that the expression is copied only when the correct one of INCLUDING DEFAULTS and INCLUDING GENERATED has been specified. Per private report from Manuel Rigger. Tom Lane and Peter Eisentraut
-rw-r--r--src/backend/parser/parse_utilcmd.c12
-rw-r--r--src/test/regress/expected/create_table_like.out74
-rw-r--r--src/test/regress/sql/create_table_like.sql20
3 files changed, 100 insertions, 6 deletions
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 7450d74b7ac..2406ca7a5d0 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -1023,11 +1023,13 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
attmap[parent_attno - 1] = list_length(cxt->columns);
/*
- * Copy default, if present and the default has been requested
+ * Copy default, if present and it should be copied. We have separate
+ * options for plain default expressions and GENERATED defaults.
*/
if (attribute->atthasdef &&
- (table_like_clause->options & CREATE_TABLE_LIKE_DEFAULTS ||
- table_like_clause->options & CREATE_TABLE_LIKE_GENERATED))
+ (attribute->attgenerated ?
+ (table_like_clause->options & CREATE_TABLE_LIKE_GENERATED) :
+ (table_like_clause->options & CREATE_TABLE_LIKE_DEFAULTS)))
{
Node *this_default = NULL;
AttrDefault *attrdef;
@@ -1065,9 +1067,7 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
attributeName,
RelationGetRelationName(relation))));
- if (attribute->attgenerated &&
- (table_like_clause->options & CREATE_TABLE_LIKE_GENERATED))
- def->generated = attribute->attgenerated;
+ def->generated = attribute->attgenerated;
}
/*
diff --git a/src/test/regress/expected/create_table_like.out b/src/test/regress/expected/create_table_like.out
index b153d6adb1d..2a063a8369a 100644
--- a/src/test/regress/expected/create_table_like.out
+++ b/src/test/regress/expected/create_table_like.out
@@ -159,6 +159,80 @@ SELECT * FROM test_like_gen_3;
(1 row)
DROP TABLE test_like_gen_1, test_like_gen_2, test_like_gen_3;
+CREATE TABLE test_like_4 (a int, b int DEFAULT 42, c int GENERATED ALWAYS AS (a * 2) STORED);
+\d test_like_4
+ Table "public.test_like_4"
+ Column | Type | Collation | Nullable | Default
+--------+---------+-----------+----------+------------------------------------
+ a | integer | | |
+ b | integer | | | 42
+ c | integer | | | generated always as (a * 2) stored
+
+CREATE TABLE test_like_4a (LIKE test_like_4);
+CREATE TABLE test_like_4b (LIKE test_like_4 INCLUDING DEFAULTS);
+CREATE TABLE test_like_4c (LIKE test_like_4 INCLUDING GENERATED);
+CREATE TABLE test_like_4d (LIKE test_like_4 INCLUDING DEFAULTS INCLUDING GENERATED);
+\d test_like_4a
+ Table "public.test_like_4a"
+ Column | Type | Collation | Nullable | Default
+--------+---------+-----------+----------+---------
+ a | integer | | |
+ b | integer | | |
+ c | integer | | |
+
+INSERT INTO test_like_4a VALUES(11);
+TABLE test_like_4a;
+ a | b | c
+----+---+---
+ 11 | |
+(1 row)
+
+\d test_like_4b
+ Table "public.test_like_4b"
+ Column | Type | Collation | Nullable | Default
+--------+---------+-----------+----------+---------
+ a | integer | | |
+ b | integer | | | 42
+ c | integer | | |
+
+INSERT INTO test_like_4b VALUES(11);
+TABLE test_like_4b;
+ a | b | c
+----+----+---
+ 11 | 42 |
+(1 row)
+
+\d test_like_4c
+ Table "public.test_like_4c"
+ Column | Type | Collation | Nullable | Default
+--------+---------+-----------+----------+------------------------------------
+ a | integer | | |
+ b | integer | | |
+ c | integer | | | generated always as (a * 2) stored
+
+INSERT INTO test_like_4c VALUES(11);
+TABLE test_like_4c;
+ a | b | c
+----+---+----
+ 11 | | 22
+(1 row)
+
+\d test_like_4d
+ Table "public.test_like_4d"
+ Column | Type | Collation | Nullable | Default
+--------+---------+-----------+----------+------------------------------------
+ a | integer | | |
+ b | integer | | | 42
+ c | integer | | | generated always as (a * 2) stored
+
+INSERT INTO test_like_4d VALUES(11);
+TABLE test_like_4d;
+ a | b | c
+----+----+----
+ 11 | 42 | 22
+(1 row)
+
+DROP TABLE test_like_4, test_like_4a, test_like_4b, test_like_4c, test_like_4d;
CREATE TABLE inhg (x text, LIKE inhx INCLUDING INDEXES, y text); /* copies indexes */
INSERT INTO inhg VALUES (5, 10);
INSERT INTO inhg VALUES (20, 10); -- should fail
diff --git a/src/test/regress/sql/create_table_like.sql b/src/test/regress/sql/create_table_like.sql
index 9b19c680b50..589ee12ebcf 100644
--- a/src/test/regress/sql/create_table_like.sql
+++ b/src/test/regress/sql/create_table_like.sql
@@ -65,6 +65,26 @@ INSERT INTO test_like_gen_3 (a) VALUES (1);
SELECT * FROM test_like_gen_3;
DROP TABLE test_like_gen_1, test_like_gen_2, test_like_gen_3;
+CREATE TABLE test_like_4 (a int, b int DEFAULT 42, c int GENERATED ALWAYS AS (a * 2) STORED);
+\d test_like_4
+CREATE TABLE test_like_4a (LIKE test_like_4);
+CREATE TABLE test_like_4b (LIKE test_like_4 INCLUDING DEFAULTS);
+CREATE TABLE test_like_4c (LIKE test_like_4 INCLUDING GENERATED);
+CREATE TABLE test_like_4d (LIKE test_like_4 INCLUDING DEFAULTS INCLUDING GENERATED);
+\d test_like_4a
+INSERT INTO test_like_4a VALUES(11);
+TABLE test_like_4a;
+\d test_like_4b
+INSERT INTO test_like_4b VALUES(11);
+TABLE test_like_4b;
+\d test_like_4c
+INSERT INTO test_like_4c VALUES(11);
+TABLE test_like_4c;
+\d test_like_4d
+INSERT INTO test_like_4d VALUES(11);
+TABLE test_like_4d;
+DROP TABLE test_like_4, test_like_4a, test_like_4b, test_like_4c, test_like_4d;
+
CREATE TABLE inhg (x text, LIKE inhx INCLUDING INDEXES, y text); /* copies indexes */
INSERT INTO inhg VALUES (5, 10);
INSERT INTO inhg VALUES (20, 10); -- should fail