PostgreSQL

FreeBSD: UTF-8 russian collate (вторая попытка)

Несколько дней назад я опубликовал исходник LC_COLLATE для кодировки ru_RU.UTF-8 для использования в FreeBSD. Там же я обещал, что если понадобится не "универсальная" сортировка, а такая же, как в FreeBSD, то сделаю и ее, а обещания нужно выполнять.

Помимо этого, старый вариант не имел вообще никаких шансов попасть в FreeBSD (причины этого мне объяснил Андрей Чернов: нарушается FreeBSD-шное правило, что большие буквы отдельно, а маленькие - отдельно), а новый - такие шансы еще не потерял.

FreeBSD: ru_RU.UTF-8 LC_COLLATE

Несмотря на мой пессимизм относительно сортировки строк с многобайтными символами в FreeBSD, жизнь оказалась лучше, чем мне казалось.

Наш читатель, Александр Загребин, любезно поделился исходником locale LC_COLLATE для FreeBSD, который лечит проблему сортировок для ru_RU.UTF-8. Я немножко поправил Makefile, чтобы результат ставился прямо поверх системного файла, выкладываю (с согласия автора, естественно) это для всеобщего использования:

Update
Я сделал работу над ошибками, обновленный вариант (с тем же URL) и комментарии к нему берите здесь.

Лечение проблем LC_COLLATE при использовании UTF-8 в PostgreSQL под FreeBSD

Как я уже писал, при использовании UTF-8 в PostgreSQL под FreeBSD результат больно бъется: сортировка русских букв неправильная (касается это только буквы ё). Причина - в кривой locale под FreeBSD (и Mac OS X).

Естественно, на эти грабли уже много раз наступали и для PostgreSQL 8.1 существуют патчи имени Palle Girgensohn, позволяющие использовать IBM-овскую библиотеку ICU в которой все сделано правильно для безумного количества языков.

Больно ударился об 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-м веке я как-то не ожидал.

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

Postgresql 8.3b1 UTF conversion patch

Я уже писал (а потом писал еще), что, в силу многих причин, стандартное поведение PostgreSQL при конверсии из UTF-8 в однобайтовые русские кодировки меня не устраивает. Ну нельзя обижаться и ломаться в ситуации, когда мы, например, импортировали текст в кодировке windows-1251 с кавычками-лапками, а показать хотим его в KOI8-R, где кавычек-лапок нет.

Патч для версий 8.1.4-8.2 можно найти по ссылке выше. Для 8.3-beta1 он не подходит, поэтому пришлось сделать новый: postgres-8.3.b1-conversion.patch.gz

Это хак, правильность которого я обсуждать не желаю, ибо идеологически он неверен, но без него не работают старые приложения.

MT: перенос темплейтов (боремся с чужой жадностью)

Разработчики MovableType, судя по всему, предполагают, что вся работа с темплейтами должна происходить внутри интерфейса системы. В ряде сортов колбасы потребности, очевидно, нет. В частности, нет способов сделать:
  • backup/restore только темплейтов;
  • использование темплейтов одного блога для другого;
  • редактирование внешним редактором, а не встроенным уебибожеством.

Понятно, что разработчики плагинов в стороне не остались и Mark Carey предлагает готовое решение в виде плагинов Template Exporter и Template Installer. Есть правда одна закавыка, Installer бесплатен для некоммерческого использования, а вот за Exporter автор хочет $97.

Так как мне экспорт нужен однократно, перенести то что надевелопил дома на рабочий сервер, то за стобаксофф я удавлюсь. И комплект из двух плагинов мы заменяем вот такой вот командой:

<b>pg_dump -E UTF8 -F c -t mt_template movabletype | ssh server pg_restore -d movabletype -c </b>

Это, естественно, для инсталляции MT на PostgreSQL. C MySQL я практически не знаком, но уверен что средства побэкапить-поресторить табличку есть и там. Для переноса Archive Mapping нужно таскать табличку mt_templatemap. Конечно, мы неявно предполагаем что:
  • blog_id на двух инсталляциях совпадает
  • нужно перенести все темплейты всех блогов.

Естественно, для чуть более сложной задачи: экспортировать не все, а только для одного блога, экспортировать в файлы (и импортировать из них) придется попрограммировать. На первый взгляд, экспорт в формате, пригодном для импорта через Template Installer должен уложиться строчек в 20.

Postgresql 8.2, UTF8 и русские буквы

В отличие от PostgreSQL 8.1.x, табличка преобразования UTF8<—>CP1251 уже нормальная, € там имеется.

Однако сама идеология осталась порочной, мне не нужны ошибки при попытке конверсии, я хочу их маскировать. Впрочем патч от 8.1.5 вполне подходит и к 8.2

Postgresql 8.1.x и UTF-8

В PostgreSQL начиная с версии 8.1.4 ужесточили правила конверсии из UTF-8 в однобайтовые кодировки. Если раньше при неконвертируемом символе было предупреждение, которое попадало в лог (или в приложение, если оно читало Warnings) и все работало, то сейчас неправильный символ приводит к ошибке и запрос не выполняется.

Тут же выяснилось, что у этих криворуких уродов таблица преобразования из/в windows-1251 неверная, там пропущен символ €. Пришлось, как водится, править.

патч для таблиц перекодировки UTF8<->CP1251 PostgreSQL 8.1.4 и 8.1.5

Заметим, что введение такой безусловной функциональности в minor-версии &mdash это моветон. Разработчики нам обещают, что в пределах minor-а все будет работать без backup/restore базы, а это нифига не так, приложения просто перестали работать совсем. Впрочем, багу с конверсией посчитали vulnerability, что вполне верно если перекодировке подвергается пользовательский ввод. Но не во всех приложениях это впрямую пользовательский ввод, более того у нас правильность символов контролируется на этапе ввода, а значит нам такая неотключаемая проверка нафиг не нужна.

Пришлось делать патч, который ее относительно safe выключает: все неизвестные символы при преобразовании UTF8->однобайтная кодировка меняются на пробел. Вот этот патч: качать. Естественно, этот патч можно рекомендовать только тем, кто понимает что делает.

Pages

Subscribe to PostgreSQL