Дано: PostgreSQL 8.3.1.
Задача: реализовать поиск по тексту независимым от латышских диакритических символов. Т.е. по запросу «ē», должны быть найдены и «e», и «ē» и наоборот.
Латышский язык содержит следующие диакритические знаки (wikipedia):
- гарумзиме: ā ē ī ū,
- гачек: č š ž,
- седиль: ģ ķ ļ,
и всем этим буквам соотвествуют обычные латинские, без дополнений.
Сначала, для тех кто ищет просто решение - функция, которая заменяет буквы с диакритическими знаками на обычные:
CREATE OR REPLACE FUNCTION unaccent_string(text)
RETURNS text
LANGUAGE SQL
IMMUTABLE
STRICT
AS $$
SELECT replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
(
SELECT replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace($1, \'ā\', \'a\'),
\'ž\', \'z\'),
\'ū\', \'u\'),
\'š\', \'s\'),
\'ņ\', \'n\'),
\'ļ\', \'l\'),
\'ķ\', \'k\'),
\'ī\', \'i\'),
\'ģ\', \'g\'),
\'ē\', \'e\'),
\'č\', \'c\') AS "text")
, \'Ā\', \'A\'),
\'Ž\', \'Z\'),
\'Ū\', \'U\'),
\'Š\', \'S\'),
\'Ņ\', \'N\'),
\'Ļ\', \'L\'),
\'Ķ\', \'K\'),
\'Ī\', \'I\'),
\'Ģ\', \'G\'),
\'Ē\', \'E\'),
\'Č\', \'C\') AS "text";
$$;
Не имея понятия с чего начать, я попытался найти какое-то готовое решение. Мне попалась идея замены букв на обычные с помощью функции translate(). Отсюда и начал:
~~
SELECT translate('Cātozzo', 't', 'a2') AS "res"
res: Cāaozzo
~~
простой символ заменяется как и ожидалось, но:
~~
SELECT translate('Cātozzo', 'ā', 'a2') AS "res"
res: Ca2tozzo
~~
utf-символ воспринимается функцией translate как два, и каждая половинка заменяется отдельно (таков принцип работы функции). Первая часть utf-символа повторяется у разных букв, поэтому вариант с translate() не работает или сильно усложняется.
Тогда я решил попробовать replace, что и дало мне функцию указанную вначале статьи. Тест:
~~
SELECT unaccent_string(\'glāžšķūņu rūķīši\') AS "res"
res: glazskunu rukisi
SELECT unaccent_string(\'GLĀŽŠĶŪŅU RŪĶĪŠI\') AS "res"
res: GLAZSKUNU RUKISI
~~


