Skip to content

Commit b81a9c2

Browse files
committed
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
1 parent bffe1bd commit b81a9c2

File tree

3 files changed

+100
-6
lines changed

3 files changed

+100
-6
lines changed

src/backend/parser/parse_utilcmd.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,11 +1023,13 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
10231023
attmap[parent_attno - 1] = list_length(cxt->columns);
10241024

10251025
/*
1026-
* Copy default, if present and the default has been requested
1026+
* Copy default, if present and it should be copied. We have separate
1027+
* options for plain default expressions and GENERATED defaults.
10271028
*/
10281029
if (attribute->atthasdef &&
1029-
(table_like_clause->options & CREATE_TABLE_LIKE_DEFAULTS ||
1030-
table_like_clause->options & CREATE_TABLE_LIKE_GENERATED))
1030+
(attribute->attgenerated ?
1031+
(table_like_clause->options & CREATE_TABLE_LIKE_GENERATED) :
1032+
(table_like_clause->options & CREATE_TABLE_LIKE_DEFAULTS)))
10311033
{
10321034
Node *this_default = NULL;
10331035
AttrDefault *attrdef;
@@ -1065,9 +1067,7 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
10651067
attributeName,
10661068
RelationGetRelationName(relation))));
10671069

1068-
if (attribute->attgenerated &&
1069-
(table_like_clause->options & CREATE_TABLE_LIKE_GENERATED))
1070-
def->generated = attribute->attgenerated;
1070+
def->generated = attribute->attgenerated;
10711071
}
10721072

10731073
/*

src/test/regress/expected/create_table_like.out

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,80 @@ SELECT * FROM test_like_gen_3;
159159
(1 row)
160160

161161
DROP TABLE test_like_gen_1, test_like_gen_2, test_like_gen_3;
162+
CREATE TABLE test_like_4 (a int, b int DEFAULT 42, c int GENERATED ALWAYS AS (a * 2) STORED);
163+
\d test_like_4
164+
Table "public.test_like_4"
165+
Column | Type | Collation | Nullable | Default
166+
--------+---------+-----------+----------+------------------------------------
167+
a | integer | | |
168+
b | integer | | | 42
169+
c | integer | | | generated always as (a * 2) stored
170+
171+
CREATE TABLE test_like_4a (LIKE test_like_4);
172+
CREATE TABLE test_like_4b (LIKE test_like_4 INCLUDING DEFAULTS);
173+
CREATE TABLE test_like_4c (LIKE test_like_4 INCLUDING GENERATED);
174+
CREATE TABLE test_like_4d (LIKE test_like_4 INCLUDING DEFAULTS INCLUDING GENERATED);
175+
\d test_like_4a
176+
Table "public.test_like_4a"
177+
Column | Type | Collation | Nullable | Default
178+
--------+---------+-----------+----------+---------
179+
a | integer | | |
180+
b | integer | | |
181+
c | integer | | |
182+
183+
INSERT INTO test_like_4a VALUES(11);
184+
TABLE test_like_4a;
185+
a | b | c
186+
----+---+---
187+
11 | |
188+
(1 row)
189+
190+
\d test_like_4b
191+
Table "public.test_like_4b"
192+
Column | Type | Collation | Nullable | Default
193+
--------+---------+-----------+----------+---------
194+
a | integer | | |
195+
b | integer | | | 42
196+
c | integer | | |
197+
198+
INSERT INTO test_like_4b VALUES(11);
199+
TABLE test_like_4b;
200+
a | b | c
201+
----+----+---
202+
11 | 42 |
203+
(1 row)
204+
205+
\d test_like_4c
206+
Table "public.test_like_4c"
207+
Column | Type | Collation | Nullable | Default
208+
--------+---------+-----------+----------+------------------------------------
209+
a | integer | | |
210+
b | integer | | |
211+
c | integer | | | generated always as (a * 2) stored
212+
213+
INSERT INTO test_like_4c VALUES(11);
214+
TABLE test_like_4c;
215+
a | b | c
216+
----+---+----
217+
11 | | 22
218+
(1 row)
219+
220+
\d test_like_4d
221+
Table "public.test_like_4d"
222+
Column | Type | Collation | Nullable | Default
223+
--------+---------+-----------+----------+------------------------------------
224+
a | integer | | |
225+
b | integer | | | 42
226+
c | integer | | | generated always as (a * 2) stored
227+
228+
INSERT INTO test_like_4d VALUES(11);
229+
TABLE test_like_4d;
230+
a | b | c
231+
----+----+----
232+
11 | 42 | 22
233+
(1 row)
234+
235+
DROP TABLE test_like_4, test_like_4a, test_like_4b, test_like_4c, test_like_4d;
162236
CREATE TABLE inhg (x text, LIKE inhx INCLUDING INDEXES, y text); /* copies indexes */
163237
INSERT INTO inhg VALUES (5, 10);
164238
INSERT INTO inhg VALUES (20, 10); -- should fail

src/test/regress/sql/create_table_like.sql

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,26 @@ INSERT INTO test_like_gen_3 (a) VALUES (1);
6565
SELECT * FROM test_like_gen_3;
6666
DROP TABLE test_like_gen_1, test_like_gen_2, test_like_gen_3;
6767

68+
CREATE TABLE test_like_4 (a int, b int DEFAULT 42, c int GENERATED ALWAYS AS (a * 2) STORED);
69+
\d test_like_4
70+
CREATE TABLE test_like_4a (LIKE test_like_4);
71+
CREATE TABLE test_like_4b (LIKE test_like_4 INCLUDING DEFAULTS);
72+
CREATE TABLE test_like_4c (LIKE test_like_4 INCLUDING GENERATED);
73+
CREATE TABLE test_like_4d (LIKE test_like_4 INCLUDING DEFAULTS INCLUDING GENERATED);
74+
\d test_like_4a
75+
INSERT INTO test_like_4a VALUES(11);
76+
TABLE test_like_4a;
77+
\d test_like_4b
78+
INSERT INTO test_like_4b VALUES(11);
79+
TABLE test_like_4b;
80+
\d test_like_4c
81+
INSERT INTO test_like_4c VALUES(11);
82+
TABLE test_like_4c;
83+
\d test_like_4d
84+
INSERT INTO test_like_4d VALUES(11);
85+
TABLE test_like_4d;
86+
DROP TABLE test_like_4, test_like_4a, test_like_4b, test_like_4c, test_like_4d;
87+
6888
CREATE TABLE inhg (x text, LIKE inhx INCLUDING INDEXES, y text); /* copies indexes */
6989
INSERT INTO inhg VALUES (5, 10);
7090
INSERT INTO inhg VALUES (20, 10); -- should fail

0 commit comments

Comments
 (0)