PostgreSQL ОШИБКА: функция 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 тип поля, но этот вызов должен быть совершенно правильным в соответствии с документацией?

2 ответа

Решение

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

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

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

Зачем?

Postgres позволяет перегружать функции. Сигнатуры функций определяются их (необязательно определяемыми схемой) именем и типом входных параметров (списком). Двухпараметрическая форма 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
Указывает, в каких контекстах может быть задействован актерский состав. e означает только как явное приведение (используя CAST или же :: синтаксис). a означает неявно при присваивании целевому столбцу, а также явно. i означает неявно в выражениях, а также в других случаях.

Узнайте больше о трех различных типах назначения в главе CREATE CAST.

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

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

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

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

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

будет работать просто отлично.

Другие вопросы по тегам