Re: Switching identity column to serial

From: Erik Wienhold <ewie(at)ewie(dot)name>
To: "pgsql-general(at)lists(dot)postgresql(dot)org" <pgsql-general(at)lists(dot)postgresql(dot)org>
Subject: Re: Switching identity column to serial
Date: 2023-02-04 01:05:02
Message-ID: 1478443868.15240.1675472702990@office.mailbox.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

> On 04/02/2023 01:54 CET Erik Wienhold <ewie(at)ewie(dot)name> wrote:
>
> I was wondering if it's possible to drop a column identity (not the column
> itself) while keeping the attached sequence. This would avoid recreating
> an identical sequence (especially with a correct start value and owner).
>
> Changing the sequence owner to NONE before dropping identity is not allowed.
> Also changing pg_class.relowner to some role did not help. The sequence is
> still dropped together with the column identity.
>
> But I managed it by clearing pg_attribute.attidentity. See the following
> psql session:

Forgot to mention: tested on 12.13 and 15.1.

>
> test=# create table t (id int generated always as identity, x char);
> CREATE TABLE
>
> test=# insert into t (x) values ('a'), ('b') returning *;
> id | x
> ----+---
> 1 | a
> 2 | b
> (2 rows)
>
> INSERT 0 2
>
> test=# select pg_get_serial_sequence('t', 'id');
> pg_get_serial_sequence
> ------------------------
> public.t_id_seq
> (1 row)
>
> test=# update pg_attribute set attidentity = '' where (attrelid, attname) = ('t'::regclass, 'id');
> UPDATE 1
>
> test=# alter table t alter id drop identity;
> psql:1.sql:6: ERROR: column "id" of relation "t" is not an identity column
>
> test=# select pg_get_serial_sequence('t', 'id');
> pg_get_serial_sequence
> ------------------------
> public.t_id_seq
> (1 row)
>
> test=# alter table t alter id set default nextval('t_id_seq');
> ALTER TABLE
>
> test=# insert into t (x) values ('c'), ('d') returning *;
> id | x
> ----+---
> 3 | c
> 4 | d
> (2 rows)
>
> INSERT 0 2
>
> test=# insert into t (id, x) values (-1, 'e') returning *;
> id | x
> ----+---
> -1 | e
> (1 row)
>
> INSERT 0 1
>
> test=# select * from t;
> id | x
> ----+---
> 1 | a
> 2 | b
> 3 | c
> 4 | d
> -1 | e
> (5 rows)
>
> Is this sufficient or am I missing some detail and messing around with
> pg_catalog is not enough (in addition to being risky)?
>
> Some context:
>
> I have to change identity columns to a form that resembles a definition as
> serial. Creating a new column and migrating the primary key constraint is
> not an option.
>
> Why is this change necessary?
>
> My team is importing data with QGIS which fails to properly handle identity
> columns. QGIS uses INSERT with OVERRIDING SYSTEM VALUE but tries to insert
> NULL although identity columns imply NOT NULL (also it's the primary key).
> QGIS tries to generate an ID with nextval but does not use the qualified
> sequence name although search_path does not contain the namespace. It's
> weird that QGIS thinks that it should generate the ID instead of delegating
> this to the database, yet it uses RETURNING id. Maybe it needs the ID in
> advance for reference. I don't know.
>
> The "serial" style with nextval as column default works as expected.
> Probably because QGIS just uses the column default expression which should
> reference the correct sequence. Oh, did I mention yet that QGIS generates
> the ID before issuing an INSERT with RETURNING id?
>
> I'll still open a bug ticket with QGIS but right now there's no other way
> than ditching identity columns.
>
> --
> Erik

In response to

Browse pgsql-general by date

  From Date Subject
Next Message Ron 2023-02-04 04:41:06 Re: Switching identity column to serial
Previous Message Erik Wienhold 2023-02-04 00:54:39 Switching identity column to serial