I'm trying to modify the values of an enum in my schema (" feature
" in the below example).
I'm trying to do this by renaming the old enum and introducing a new one that has the values I want, and then altering the table definition to the new enum.
I'm following this blog post here: https://blog.yo1.dog/updating-enum-values-in-postgresql-the-safe-and-easy-way/ . But instead of the column being a simple column of the enum, my column is actually an array of the enum.
When I try to run the alter table
statement in the below statements, I get the error:
[42804] ERROR: column "features" is of type feature_old[] but expression is of type feature_v2[] Hint: You will need to rewrite or cast the expression.
alter type feature rename to feature_old;
create type feature_v2 as enum (
'enable_create_keyword',
'enable_make_payment',
'enable_test_data_flags'
);
-- ... cleanup of column array values to be compatible with new enum ...
alter table app_user alter column features type feature_v2
using features::feature_old[]::feature_v2[];
drop type feature_old;
But, I'm lost - what should the cast expression look like?
Postgres version is 9.6
EDIT
This is the relevant part of the previous version's schema DDL for the feature
enum and app_user
table that was requested by @VaoTsun.
-- feature enum and column
create type feature as enum ('enable_create_keyword', 'enable_make_payment');
comment on type feature is
'if default functionality is disabled feature name starts with enable_, if default is enabled starts with disable_'
;
alter table app_user add column
features feature[] not null default ARRAY[]::feature[];
-- feature data
update app_user
set features = ARRAY['enable_create_keyword', 'enable_make_payment']::feature[]
where email = 'test1@example.com';
update app_user
set features = ARRAY['enable_create_keyword']::feature[]
where email = 'test2@example.com';
Thanks to both Vao Tsun and Nick Barnes; this is the code that appears to work for me. I have marked Vao Tsun's answer as correct. Any answers that provide a more concise version would be gratefully upvoted.
alter type feature rename to feature_old;
create type feature_v2 as enum (
'enable_create_keyword',
'enable_make_payment',
'enable_test_data_flags'
);
alter table app_user alter column features drop default ;
alter table app_user alter column features type feature_v2[]
using features::feature_old[]::text[]::feature_v2[];
alter table app_user alter column features set default ARRAY[]::feature_v2[];
drop type feature_old;
with assumption that old enum has same values, but less, you should be able to simply cast it's value to text and then to a v2:
try this:
t=# create or replace function feature2v2(feature_old) returns feature_v2 as
$$
select $1::text::feature_v2;
$$
language sql strict;
CREATE FUNCTION
t=# create cast (feature_old AS feature_v2) WITH FUNCTION feature2v2(feature_old) AS ASSIGNMENT;
CREATE CAST
gives me:
t=# alter table app_user alter column features type feature_v2[]
using features::feature_v2[];
ALTER TABLE
t=# \d+ app_user
Table "postgres.app_user"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
----------+--------------+-----------+----------+------------------------+----------+--------------+-------------
email | text | | | | extended | |
features | feature_v2[] | | not null | ARRAY[]::feature_old[] | extended | |
t=# \dT+ feature_v2
List of data types
Schema | Name | Internal name | Size | Elements | Owner | Access privileges | Description
----------+------------+---------------+------+------------------------+----------+-------------------+-------------
postgres | feature_v2 | feature_v2 | 4 | enable_create_keyword +| postgres | |
| | | | enable_make_payment +| | |
| | | | enable_test_data_flags | | |
(1 row)
which looks like what you expect
UPDATE
catching up with Nick Barnes comments - creating a cast here is overhead and leaves bad defualt for column, the right approach her is:
alter table app_user alter column features drop default;
alter table app_user alter column features type feature_v2[] using features::feature_old[]::text[]::feature_v2[];
alter table app_user alter column features set default ARRAY[]::feature_v2[];
Leaving the previous version untouched to demonstrate the bad approach with hints how it is bad
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.