Больно ударился об UTF-8

Уже много лет я насаждаю UTF-8 как кодировку хранения всяких текстов. С переменным успехом, но большинство баз данных в округе - вроде перевел. На третий день Зоркому Глазу подсказали, что в доме нету пары стен.

Берем русские тексты с буквой ё. Да, их немного, но они есть. Заливаем в Postgresql, начинаем сортировать и делать всякие прочие upper/lower преобразования. Видим... плохое видим:

lexa=# SELECT * from aa order by bb;
 bb
----
 еа
 ее
 ея
 её
(4 rows)

При этом, если база в кодировке KOI8 (попробовал) или cp1251 (не пробовал, но должно быть так же), то все отлично.

Причина выяснилась, оказалась банальной:

$ uname -v
FreeBSD 6.2-RELEASE-p9
$ ls -l /usr/share/locale/ru_RU.UTF-8/LC_COLLATE
lrwxr-xr-x  1 root  wheel  28 Dec  3 23:30 /usr/share/locale/ru_RU.UTF-8/
LC_COLLATE -> ../la_LN.US-ASCII/LC_COLLATE

Надо сказать, что такого свинства в 21-м веке я как-то не ожидал.

Да, чтобы два раза не вставать. В Леопарде локаль такая же

Comments

Дык, Федя Сигаев про это сто лет назад говорил, так как у него на лаптопе фря и локаль там неправильная всю жизнь была. Только теги к посту нужно поменять: не "postgresql, уроды", а "freebsd, уроды"; не вводите в заблуждение читателей: PostgreSQL тут не виноват.

Э.. а я правильно понимаю, что если вдруг поправить системную локаль (взяв линуксовую, например), то все начнет магически работать ? И upper/lower тоже ?

А теги - через запятую

правильно понимаете
спросите Федю (http://sigaev.ru), он об этом все знает
думаю, и патч у него для фри тоже должен быть

что касается использования utf8 в СУБД, то в настоящее время это просто необходимо даже для одноязычных проектов. нормальные пользователи хотят нормальные кавычки и остальные символы, а не убогие пережитки прошлого. а так как СУБД является сердцем многих систем, то перекодировать впоследствии данные будет слишком дорого. так что ниша байтовых кодировок действительно есть: проекты, написанные в прошлом тысячелетии.

Кстати, под FreeBSD вообще ни в одной из UTF-8 локалей нет своего LC_COLLATE, все ведут на US-ASCII.

Ага, нету. Я посмотрел как оно там делается и ужаснулся.

Нужно бы попробовать взять линуксовую локаль и скормить colldef-у.

Правда сортировки я добился путем initdb -E UTF8 --locale=ru_RU.CP1251
меня обругали страшными словами, но сортирует правильно.

Но upper/lower от этого работать правильно не стали.
Вполне возможно, впрочем, что нужны разные collate и ctype.

Если поискать googl'ом про collate во FreeBSD, то можно найти много смешного.

Во-первых, твой блог уже на первом месте по запросу "UTF-8 LC_COLLATE FreeBSD US-ASCII".

Во-вторых, в 2005-м году некий несчастный немец уже задавался вопросом "PostgreSQL, UTF-8 and Mac OS X" ( http://qaix.com/postgresql-database-development/445-468-postgresql-utf-8... )

В третьих, в 2006-м году люди удивлялись скорости сортировки UTF-ных строк во FreeBSD ( http://lists.freebsd.org/pipermail/freebsd-stable/2006-March/023725.html )

В общем, что-то мне подсказывает, что простого решения проблемы сортировки нет, иначе оно уже было бы общеизвестно, а то и подперто. Вполне вероятно, что правильная сортировка и работа с UTF-8 во FreeBSD должна быть поддержана и еще где-нибуде, кроме каталога locale.

Там, к сожалению, не мелкая недоделка: типа нужный LC_COLLATE не сделали. FreeBSD'ишная libc вообще не умеет многобайтные символы по локальным правилам сортировать.

наши разработчики наблюдали странности и на win32 с postgresql.
В итоге выкатили рекомендацию - инициализировать кластер данных нужно только в 1251, и базы хранить в 1251.
Там тоже локаль странная.

А нефиг насаждать ненасаждаемое. utf8 хорошо там где оно хорошо. Байтовые кодировки хороши там где они хороши. Тот кто насильно все упихивает в utf8, не понимает дао, и обречен огребать ;)

В каком смысле "упихивает" ?

Казалось бы, туда все упихивается и еще место остается.

В том смысле что всегда останется ниша где utf8 неоптимален.

Естественно, если вход строго однобайтовый (одноязыковый), то можно без UTF.

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

Диски сейчас дешевые, а обработку utf можно сделать довольно быстрой.

sapa=# show client_encoding;
client_encoding
-----------------
UTF8
(1 запись)

sapa=# VALUES ('ea'),('ee'),('ёe'),('eё'),('ae'),('aё') ORDER BY 1;
column1
---------
ae

ea
ee

ёe
(6 rows)

sapa=# SELECT upper(column1) FROM (VALUES ('ea'),('ee'),('ёe'),('eё'),('ae'),('aё')) s ORDER BY 1;
upper
-------
AE

EA
EE

ЁE
(6 rows)

Линукс спасёт, ага.

Насколько я помню вся проблема банально во фре. Линухи в массе своей этим не страдают.
И не правильно тут прозвучало, что не надо насаждать utf-8. Опять же, на мой взгляд это единственно верная кодировка. Кто против этого пусть представит например мультиязычный сайт для русских, поляков и американцев.

http://www.freebsd.org/cgi/query-pr.cgi?pr=misc/109367

PR cегодня исполнился ровно год.

О, я же помню, что что-то такое было

http://people.freebsd.org/~girgen/postgresql-icu/README.html

Правда только для 8.1 (причем страничка живая, последний апдейт - вчера).

будет время - попробую накатить это на 8.3.0

напишешь потом о результатах сам-знаешь-куда ?

Напишу. И сюда и туда. Опер велел всюду писать.

Но раньше выходных скорее всего не сяду с этим разбираться.

проблемы с такой кодировой и у меня иногда бывают, а че длать?

никогда не любил эту кодировку

Турецкий попробуйте...