Fix propagation of persistence to sequences in ALTER TABLE / ADD COLUMN

Fix for 344d62fb9a9: That commit introduced unlogged sequences and
made it so that identity/serial sequences automatically get the
persistence level of their owning table.  But this works only for
CREATE TABLE and not for ALTER TABLE / ADD COLUMN.  The latter would
always create the sequence as logged (default), independent of the
persistence setting of the table.  This is fixed here.

Note: It is allowed to change the persistence of identity sequences
directly using ALTER SEQUENCE.  So mistakes in existing databases can
be fixed manually.

Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/c4b6e2ed-bcdf-4ea7-965f-e49761094827%40eisentraut.org
This commit is contained in:
Peter Eisentraut 2024-02-09 07:57:31 +01:00
parent 27c3a41f3c
commit d17a3a4c6a
3 changed files with 100 additions and 1 deletions

View File

@ -456,7 +456,16 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
seqstmt = makeNode(CreateSeqStmt);
seqstmt->for_identity = for_identity;
seqstmt->sequence = makeRangeVar(snamespace, sname, -1);
seqstmt->sequence->relpersistence = cxt->relation->relpersistence;
/*
* Copy the persistence of the table. For CREATE TABLE, we get the
* persistence from cxt->relation, which comes from the CreateStmt in
* progress. For ALTER TABLE, the parser won't set
* cxt->relation->relpersistence, but we have cxt->rel as the existing
* table, so we copy the persistence from there.
*/
seqstmt->sequence->relpersistence = cxt->rel ? cxt->rel->rd_rel->relpersistence : cxt->relation->relpersistence;
seqstmt->options = seqoptions;
/*

View File

@ -365,6 +365,78 @@ SELECT seqtypid::regtype FROM pg_sequence WHERE seqrelid = 'itest3_a_seq'::regcl
ALTER TABLE itest3 ALTER COLUMN a TYPE text; -- error
ERROR: identity column type must be smallint, integer, or bigint
-- check that unlogged propagates to sequence
CREATE UNLOGGED TABLE itest17 (a int NOT NULL, b text);
ALTER TABLE itest17 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;
ALTER TABLE itest17 ADD COLUMN c int GENERATED ALWAYS AS IDENTITY;
\d itest17
Unlogged table "public.itest17"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+------------------------------
a | integer | | not null | generated always as identity
b | text | | |
c | integer | | not null | generated always as identity
\d itest17_a_seq
Unlogged sequence "public.itest17_a_seq"
Type | Start | Minimum | Maximum | Increment | Cycles? | Cache
---------+-------+---------+------------+-----------+---------+-------
integer | 1 | 1 | 2147483647 | 1 | no | 1
Sequence for identity column: public.itest17.a
\d itest17_c_seq
Unlogged sequence "public.itest17_c_seq"
Type | Start | Minimum | Maximum | Increment | Cycles? | Cache
---------+-------+---------+------------+-----------+---------+-------
integer | 1 | 1 | 2147483647 | 1 | no | 1
Sequence for identity column: public.itest17.c
CREATE TABLE itest18 (a int NOT NULL, b text);
ALTER TABLE itest18 SET UNLOGGED, ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;
\d itest18
Unlogged table "public.itest18"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+------------------------------
a | integer | | not null | generated always as identity
b | text | | |
\d itest18_a_seq
Unlogged sequence "public.itest18_a_seq"
Type | Start | Minimum | Maximum | Increment | Cycles? | Cache
---------+-------+---------+------------+-----------+---------+-------
integer | 1 | 1 | 2147483647 | 1 | no | 1
Sequence for identity column: public.itest18.a
ALTER TABLE itest18 SET LOGGED;
\d itest18
Table "public.itest18"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+------------------------------
a | integer | | not null | generated always as identity
b | text | | |
\d itest18_a_seq
Sequence "public.itest18_a_seq"
Type | Start | Minimum | Maximum | Increment | Cycles? | Cache
---------+-------+---------+------------+-----------+---------+-------
integer | 1 | 1 | 2147483647 | 1 | no | 1
Sequence for identity column: public.itest18.a
ALTER TABLE itest18 SET UNLOGGED;
\d itest18
Unlogged table "public.itest18"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+------------------------------
a | integer | | not null | generated always as identity
b | text | | |
\d itest18_a_seq
Unlogged sequence "public.itest18_a_seq"
Type | Start | Minimum | Maximum | Increment | Cycles? | Cache
---------+-------+---------+------------+-----------+---------+-------
integer | 1 | 1 | 2147483647 | 1 | no | 1
Sequence for identity column: public.itest18.a
-- kinda silly to change property in the same command, but it should work
ALTER TABLE itest3
ADD COLUMN c int GENERATED BY DEFAULT AS IDENTITY,

View File

@ -214,6 +214,24 @@ SELECT seqtypid::regtype FROM pg_sequence WHERE seqrelid = 'itest3_a_seq'::regcl
ALTER TABLE itest3 ALTER COLUMN a TYPE text; -- error
-- check that unlogged propagates to sequence
CREATE UNLOGGED TABLE itest17 (a int NOT NULL, b text);
ALTER TABLE itest17 ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;
ALTER TABLE itest17 ADD COLUMN c int GENERATED ALWAYS AS IDENTITY;
\d itest17
\d itest17_a_seq
\d itest17_c_seq
CREATE TABLE itest18 (a int NOT NULL, b text);
ALTER TABLE itest18 SET UNLOGGED, ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;
\d itest18
\d itest18_a_seq
ALTER TABLE itest18 SET LOGGED;
\d itest18
\d itest18_a_seq
ALTER TABLE itest18 SET UNLOGGED;
\d itest18
\d itest18_a_seq
-- kinda silly to change property in the same command, but it should work
ALTER TABLE itest3
ADD COLUMN c int GENERATED BY DEFAULT AS IDENTITY,