PostgreSQL ERROR: функция to_tsvector (символ меняется, неизвестен) не существует

Этот фрагмент сеанса psql должен быть самоочевидным:

psql (9.1.7)
Type "help" for help.
=> CREATE TABLE languages(language VARCHAR NOT NULL);
CREATE TABLE
=> INSERT INTO languages VALUES ('english'),('french'),('turkish');
INSERT 0 3
=> SELECT language, to_tsvector('english', 'hello world') FROM languages;
 language|     to_tsvector     
---------+---------------------
 english | 'hello':1 'world':2
 french  | 'hello':1 'world':2
 turkish | 'hello':1 'world':2
(3 rows)

=> SELECT language, to_tsvector(language, 'hello world') FROM languages;
ERROR:  function to_tsvector(character varying, unknown) does not exist
LINE 1: select language, to_tsvector(language, 'hello world')...
                         ^
HINT:  No function matches the given name and argument types.  
You might need to add explicit type casts.

Проблема в том, что функция Postgres to_tsvector не любит тип поля varchar, но этот вызов должен быть совершенно корректным в соответствии с документацией?

Ответ 1

Используйте явный тип приведения:

SELECT language, to_tsvector(language::regconfig, 'hello world') FROM languages;

Или измените столбец languages.language на тип regconfig. См. ответ @Swav.

Почему?

Postgres позволяет перегрузку функций. Функциональные сигнатуры определяются их (необязательно, с помощью схемы) имени плюс (список) типов входных параметров. 2-параметрическая форма to_tsvector() ожидает тип regconfig в качестве первого параметра:

SELECT proname, pg_get_function_arguments(oid)
FROM   pg_catalog.pg_proc
WHERE  proname = 'to_tsvector'

   proname   | pg_get_function_arguments
-------------+---------------------------
 to_tsvector | text
 to_tsvector | regconfig, text             -- you are here

Если никакая существующая функция не соответствует точно, правила Тип функции Разрешение определяют наилучшее совпадение - если таковые имеются. Это успешно для to_tsvector('english', 'hello world'), причем 'english' является нетипизированным строковым литералом. Но с параметром напечатано varchar, но не имеет зарегистрированного неявного перевода из varchar в regconfig. Руководство:

Отменить функции кандидата, для которых типы ввода не совпадают и не могут быть преобразованы (с использованием преобразования неявного) для соответствия. неизвестно литералы считаются конвертируемыми для чего-либо для этой цели.

Смелый акцент мой.
Зарегистрированные броски для regconfig:

SELECT castsource::regtype, casttarget::regtype, castcontext
FROM   pg_catalog.pg_cast
WHERE  casttarget = 'regconfig'::regtype;

 castsource | casttarget | castcontext
------------+------------+-------------
 oid        | regconfig  | i
 bigint     | regconfig  | i
 smallint   | regconfig  | i
 integer    | regconfig  | i

Объяснение для castcontext:

castcontext char
Указывает, какие контексты могут быть задействованы in. e означает только как явное приведение (используя синтаксис CAST или ::). aподразумевает неявное присвоение целевому столбцу, а также в явном виде. i означает неявно в выражениях, а также в других случаях.

Подробнее о трех разных типах присваивания в главе CREATE CAST.

Ответ 2

Альтернативный подход к ответу Эрвина Брандстретера

Вы можете определить свой столбец языка типа regconfig, который сделает ваш запрос немного менее подробным. i.e.:

CREATE TABLE languages(language regconfig NOT NULL DEFAULT 'english'::regconfig)

Я установил английский по умолчанию выше, но это не требуется. Впоследствии ваш исходный запрос

SELECT language, to_tsvector(language, 'hello world') FROM languages;

будет работать нормально.