Fix propagation of persistence to sequences in ALTER TABLE / ADD COLUMN
authorPeter Eisentraut <peter@eisentraut.org>
Fri, 9 Feb 2024 06:57:31 +0000 (07:57 +0100)
committerPeter Eisentraut <peter@eisentraut.org>
Fri, 9 Feb 2024 07:09:22 +0000 (08:09 +0100)
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

src/backend/parser/parse_utilcmd.c
src/test/regress/expected/identity.out
src/test/regress/sql/identity.sql

index 56ac4f516ea09c0df5d8b668b3a54049cf6cf320..c7efd8d8cee13016fe588cf8f0266197111719f6 100644 (file)
@@ -459,7 +459,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;
 
        /*
index 08f95674ca8f148b7adff1cc2b4105411508e336..f357b9b63b10c24378a2ba7056dda96922b3e94a 100644 (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,
index 9f35214751cf7f31b2dbc7cf20e46ea991f9f018..7b0800226ca0ac3066cd067232e9bdaa64bead5f 100644 (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,