Thread: tsvector_update_trigger throws error "column is not of tsvector type"
Hi! I am in the process of migrating a PostgreSQL 8.2.4 database to 8.3. So far, everything has worked fine, even tsearch2-searchingan indexed table. There's something severely wrong with the trigger-function I use to keep the tsvector-column updated. Here's my table definition: CREATE TABLE public.ct_com_board_message ( board_id integer DEFAULT 0, thread_id integer DEFAULT 0, father_id integer DEFAULT 0, message_id integer NOT NULL DEFAULT 0, user_id integer DEFAULT 0, title text, signature text, follow_up text, count_reply integer DEFAULT 0, last_reply timestamptz, created timestamptz DEFAULT now(), article_id integer DEFAULT 0, logged_ip text, state_id smallint DEFAULT 0, text text, deleted_date timestamptz, deleted_login text, poll_id integer DEFAULT 0, last_updated timestamptz DEFAULT now(), idxfti tsvector, CONSTRAINT "pk_ct_com_board_message" PRIMARY KEY (message_id) ); And there's this trigger definition: CREATE TRIGGER "tsvectorupdate" BEFORE INSERT OR UPDATE ON "public"."ct_com_board_message" FOR EACH ROW EXECUTE PROCEDURE pg_catalog.tsvector_update_trigger(idxfti,pg_catalog.german,title,text,user_login); Now when I do anything that fires the trigger like UPDATE ct_com_board_message set count_reply = 1 where message_id = 12345; I get an error ERROR: column "idxfti" is not of tsvector type I didn't touch the tsvector_update_trigger-function at all, it still reads CREATE or REPLACE FUNCTION "pg_catalog"."tsvector_update_trigger"() RETURNS "pg_catalog"."trigger" AS $BODY$ tsvector_update_trigger_byid $BODY$ LANGUAGE 'internal' VOLATILE; So what's happening here? Kind regards Markus Computec Media AG Sitz der Gesellschaft und Registergericht: Fürth (HRB 8818) Vorstandsmitglieder: Johannes S. Gözalan (Vorsitzender) und Rainer Rosenbusch Vorsitzender des Aufsichtsrates: Jürg Marquard Umsatzsteuer-Identifikationsnummer: DE 812 575 276
"Markus Wollny" <Markus.Wollny@computec.de> writes: > Now when I do anything that fires the trigger like > UPDATE ct_com_board_message set count_reply = 1 where message_id = 12345; > I get an error > ERROR: column "idxfti" is not of tsvector type This is leaping to conclusions, but what I suspect is that you've got two types "tsvector" in your database and the column is the wrong one. This situation is not too hard to get into if you try to restore a dump from an old database that used contrib/tsearch2 --- the dump may create a partially broken type "public.tsvector" while the built-in pg_catalog.tsvector still remains. There's some hints in the manual about safe migration from tsearch2 to built-in tsearch: http://www.postgresql.org/docs/8.3/static/textsearch-migration.html The whole thing is a bit of a mess :-(, and has certainly helped make it clear that we need to invent some better-defined module concept to help with major upgrades/replacements of add-on modules. regards, tom lane
Re: tsvector_update_trigger throws error "column is not of tsvector type"
From
"Markus Wollny"
Date:
Hi! Tom Lane wrote: > This is leaping to conclusions, but what I suspect is that you've got > two types "tsvector" in your database and the column is the wrong > one. > This situation is not too hard to get into if you try to restore a > dump from an old database that used contrib/tsearch2 --- the dump may > create a partially broken type "public.tsvector" while the built-in > pg_catalog.tsvector still remains. It's a fair suspicion, but I have been in the fortunate situation to have tsearch2 installed to it's own schema in 8.2.4;so I dumped the old db without the tsearch2-schema like this, using 8.3.1's pg_dump on the new machine: pg_dump -h123.123.123.123 -U postgres -N tsearch2 -s community > community.schema.sql pg_dump -h123.123.123.123 -U postgres -N tsearch2 -a community -Fc > community.data.pg Then I edited community.schema.sql, doing these two sed's: sed -e 's/tsearch2\.tsvector/tsvector/g' community.schema.sq | \ sed -e 's/idxfti tsearch2\.gist_tsvector_ops/idxfti/g' - > community.schema.sql.83.tmp Afterwards I replaced all the old trigger-declarations for the update-trigger with the new style, using tsvector_update_trigger. Then I created a new 8.3-DB, imported the tsearch2-compatibility-script like this: psql -U postgres community < /opt/pgsql/share/contrib/tsearch2.sql And only then did I import the edited schema. Afterwards I restored the dump like this: pg_restore --disable-triggers -U postgres -v -Fc -d community community.data.pg There haven't been any errors during the import, everything went fine. The restored database doesn't have a tsearch2-schemaany more. I scanned through the edited schema-definiton which I imported and theres's no CREATE TYPE in thereat all. I checked the public schema and there's no tsvector there either. So it must be the builtin-tsvector type alright- it seems to be there and work perfectly: community=# select 'foo'::tsvector; tsvector ---------- 'foo' (1 row) community=# select to_tsvector('foo'); to_tsvector ------------- 'foo':1 (1 row) community=# SELECT message_id FROM ct_com_board_message WHERE idxfti @@ to_tsquery('Starcraft') LIMIT 3; message_id ------------ 5669043 5671762 5670197 (3 rows) I can even update that idxfti-column manually like so: community=# UPDATE ct_com_board_message SET idxfti = to_tsvector(coalesce(title,'')) || to_tsvector(coalesce(text,'')) || to_tsvector(coalesce(user_login,'')) WHERE message_id = 6575830; UPDATE 1 And when I use a custom-trigger-function, there's no problem either: CREATE FUNCTION board_message_trigger() RETURNS trigger AS $$ begin new.idxfti := to_tsvector(coalesce(new.title,'')) || to_tsvector(coalesce(new.text,'')) || to_tsvector(coalesce(new.user_login,'')); return new; end $$ LANGUAGE plpgsql; CREATE TRIGGER "tsvectorupdate" BEFORE INSERT OR UPDATE ON "public"."ct_com_board_message" FOR EACH ROW EXECUTE PROCEDURE board_message_trigger(); community=# UPDATE ct_com_board_message set count_reply = count_reply where message_id = 6575830; UPDATE 1 community=# SELECT message_id FROM ct_com_board_message WHERE idxfti @@ to_tsquery('markus') AND message_id = 6575830 LIMIT3; message_id ------------ 6575830 (1 row) So everything's working as expected apart from that built-in trigger function. > There's some hints in the manual about safe migration from tsearch2 > to built-in tsearch: > http://www.postgresql.org/docs/8.3/static/textsearch-migration.html I read that carefully before I went on that journey (that's why I did load that new contrib/tsearch2 module), but I didn'tfind anything helpful regarding this situation. This is very puzzling. I'll resort to writing custom trigger-functions for the time being. Kind regards Markus Computec Media AG Sitz der Gesellschaft und Registergericht: Fürth (HRB 8818) Vorstandsmitglieder: Johannes S. Gözalan (Vorsitzender) und Rainer Rosenbusch Vorsitzender des Aufsichtsrates: Jürg Marquard Umsatzsteuer-Identifikationsnummer: DE 812 575 276
"Markus Wollny" <Markus.Wollny@computec.de> writes: > So everything's working as expected apart from that built-in trigger function. Well, that's just strange. I tried to duplicate your example without any success (ie, it worked fine) --- although it seemed you hadn't shown the trigger definition exactly. I got a syntax error because 'pg_catalog.german' wasn't quoted, and after that an error about column user_login not existing. But I assume these are just typos in your message. Would you confirm that select atttypid from pg_attribute where attrelid = 'public.ct_com_board_message'::regclass and attname = 'idxfti'; gives 3614 (the preassigned OID for pg_catalog.tsvector)? regards, tom lane
I wrote: > Would you confirm that > select atttypid from pg_attribute where attrelid = 'public.ct_com_board_message'::regclass and attname = 'idxfti'; > gives 3614 (the preassigned OID for pg_catalog.tsvector)? Actually, I'll bet a nickel that you'll find it doesn't, but rather returns the OID of the domain over tsvector that the new contrib/tsearch2 module creates. It's clearly a bug that the built-in trigger doesn't allow the domain alias to be used --- will fix. regards, tom lane
Re: tsvector_update_trigger throws error "column is not of tsvector type"
From
"Markus Wollny"
Date:
Hi! Tom Lane wrote: > I wrote: >> Would you confirm that >> select atttypid from pg_attribute where attrelid = >> 'public.ct_com_board_message'::regclass and attname = 'idxfti'; >> gives 3614 (the preassigned OID for pg_catalog.tsvector)? > > Actually, I'll bet a nickel that you'll find it doesn't, but rather > returns the OID of the domain over tsvector that the new > contrib/tsearch2 module creates. It's clearly a bug that the > built-in trigger doesn't allow the domain alias to be used --- will > fix. > > regards, tom lane That nickel would be yours to keep :) community=# select atttypid from pg_attribute where attrelid = 'public.ct_com_board_message'::regclass and attname = 'idxfti'; atttypid ---------- 33991259 (1 row) Concerning the table definition - sorry, I edited out a couple of fields too many, which I assumed were not relevant to thiscase. Here is the full table definition: CREATE TABLE public.ct_com_board_message ( board_id integer DEFAULT 0, thread_id integer DEFAULT 0, father_id integer DEFAULT 0, message_id integer NOT NULL DEFAULT 0, user_id integer DEFAULT 0, title text, signature text, follow_up text, count_reply integer DEFAULT 0, last_reply timestamptz, created timestamptz DEFAULT now(), article_id integer DEFAULT 0, logged_ip text, state_id smallint DEFAULT 0, user_login text, user_status smallint DEFAULT 5, user_rights text, text text, deleted_user_id integer DEFAULT -1, user_rank text, user_rank_description text, user_rank_picture text, deleted_date timestamptz, deleted_login text, user_created timestamptz, poll_id integer DEFAULT 0, last_updated timestamptz DEFAULT now(), idxfti tsvector, CONSTRAINT "pk_ct_com_board_message" PRIMARY KEY (message_id) ); The trigger definition: CREATE TRIGGER "tsvectorupdate" BEFORE INSERT OR UPDATE ON "public"."ct_com_board_message" FOR EACH ROW EXECUTE PROCEDURE pg_catalog.tsvector_update_trigger(idxfti,'pg_catalog.german',title,text,user_login); And the error message from the log: <2008-04-09 13:42:48 CEST - 8820: 192.168.222.132(52319)@community>ERROR: column "idxfti" is not of tsvector type <2008-04-09 13:42:48 CEST - 8820: 192.168.222.132(52319)@community>STATEMENT: insert into PUBLIC.CT_COM_BOARD_MESSAGE ( BOARD_ID , THREAD_ID , FATHER_ID , MESSAGE_ID , USER_ID , TITLE , TEXT , SIGNATURE , LOGGED_IP , USER_LOGIN , USER_STATUS , USER_RIGHTS , USER_CREATED , LAST_REPLY ) values ( 1 , 6579073 , 0 , 6579073 , 39 , 'Test TSearch2 tsvector_update_trigger' , 'tsvector_update_trigger test test test' , '' , '123.123.123.123' , 'Markus_Wollny' , 100 , 'yp' , '2001-03-22 16:54:53.0' , CURRENT_TIMESTAMP ) Now I have a custom trigger function: CREATE or REPLACE FUNCTION "public"."board_message_trigger"() RETURNS "pg_catalog"."trigger" AS $BODY$ begin new.idxfti := to_tsvector(coalesce(new.title,'')) || to_tsvector(coalesce(new.text,'')) || to_tsvector(coalesce(new.user_login,'')); return new; end $BODY$ LANGUAGE 'plpgsql' VOLATILE; And this trigger: CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE ON ct_com_board_message FOR EACH ROW EXECUTE PROCEDURE board_message_trigger(); Everything works fine. It's sort of less elegant though than having just the one generic trigger function and configuringthe needed fields in the trigger itself. Kind regards Markus Computec Media AG Sitz der Gesellschaft und Registergericht: Fürth (HRB 8818) Vorstandsmitglieder: Johannes S. Gözalan (Vorsitzender) und Rainer Rosenbusch Vorsitzender des Aufsichtsrates: Jürg Marquard Umsatzsteuer-Identifikationsnummer: DE 812 575 276
"Markus Wollny" <Markus.Wollny@computec.de> writes: > Everything works fine. It's sort of less elegant though than having just the one generic trigger function and configuringthe needed fields in the trigger itself. It should work if you explicitly change the column's type to pg_catalog.tsvector. (There's a fix in place for 8.3.2, also.) regards, tom lane
Re: tsvector_update_trigger throws error "column is not of tsvector type"
From
"Markus Wollny"
Date:
Tom Lane wrote: > It should work if you explicitly change the column's type to > pg_catalog.tsvector. (There's a fix in place for 8.3.2, also.) Which would probably be not such a good idea to try on a 7GB table in production, I think. Or is there some way hacking thesystem catalog to correct the type instead of an ALTER TABLE ... ALTER COLUMN TYPE? Kind regards Markus Computec Media AG Sitz der Gesellschaft und Registergericht: Fürth (HRB 8818) Vorstandsmitglieder: Johannes S. Gözalan (Vorsitzender) und Rainer Rosenbusch Vorsitzender des Aufsichtsrates: Jürg Marquard Umsatzsteuer-Identifikationsnummer: DE 812 575 276
"Markus Wollny" <Markus.Wollny@computec.de> writes: > Tom Lane wrote: >> It should work if you explicitly change the column's type to >> pg_catalog.tsvector. (There's a fix in place for 8.3.2, also.) > Which would probably be not such a good idea to try on a 7GB table in production, I think. Or is there some way hackingthe system catalog to correct the type instead of an ALTER TABLE ... ALTER COLUMN TYPE? Well, you could probably get away with an "update pg_attribute set atttypid ..." but it might be safer to just wait for 8.3.2. regards, tom lane
Re: tsvector_update_trigger throws error "column is not of tsvector type"
From
"Markus Wollny"
Date:
Hi! Tom Lane wrote: > > Well, you could probably get away with an "update pg_attribute set > atttypid ..." but it might be safer to just wait for 8.3.2. I like it safe :) Thanks for the advice! Kind regards Markus Computec Media AG Sitz der Gesellschaft und Registergericht: Fürth (HRB 8818) Vorstandsmitglieder: Johannes S. Gözalan (Vorsitzender) und Rainer Rosenbusch Vorsitzender des Aufsichtsrates: Jürg Marquard Umsatzsteuer-Identifikationsnummer: DE 812 575 276