On PostgreSQL 13, I have a table define as such :
create table my_table (
id serial8 primary key,
title varchar(50),
description varchar(512),
french_vector_text tsvector generated always as (to_tsvector('french', coalesce(title, '') || ' ' || coalesce(description, ''))) stored
);
create index IDX_FULL_TEXT on my_table using GIN(french_vector_text);
It works fine. However, when I try to alter a column used to generate the vector, like this
alter table my_table
alter column title type varchar(100);
I get an error telling me I can't alter a column used to calculate another, which is fair. I made it work by dropping the vector column with the index, altering the title column, and then recreating the column and index.
alter table my_table
drop column french_vector_text;
alter table my_table
alter column title
type varchar(100);
alter table my_table
add column french_vector_text tsvector generated always as (to_tsvector('french', coalesce(title, '') || ' ' || coalesce(description, ''))) stored;
create index IDX_FULL_TEXT on my_table using GIN(french_vector_text);
Once again it worked fine, but in reality, the column is the aggregation of 7 columns, some with fairly large text, and the table may contain a couple ten thousand of records. So the operation took some time to complete.
Even if altering the schema isn't an everyday operation, I'm wondering if there is a more efficient solution that doesn't require dropping the column and fully recreates the index.
I thought about a trigger, but i would rather keep the generated column. So i tried creating an IMMUTABLE function as such :
create function my_french_vector(text_to_transform varchar) returns tsvector as $$
BEGIN
return to_tsvector('french', text_to_transform);
end
$$ LANGUAGE plpgsql
immutable;
And use it instead of the plain to_tsvector. But obviously, it doesn't work either as the column is still referenced.
As for my question, is there a way to alter a column used in a generated value, without having to drop it and recreate the whole thing after?