23 сентября Heikki Linnakangas применил патч, который написал Radek Strnad (на самом деле была применена его доработанная версия).
Что он делает? Патч позволяет добавлять (действительно!) разные collation order и character categories для разных БД.
До этого надо было устанавливать LC_COLLATE и LC_CTYPE при инициализации кластера (initdb), и в дальнейшем эти параметры невозможно было изменить. БД инициализированная с LATIN2 не будет корректно работать с данными в UTF-8.
Теперь всё меняется:
Делает LC_COLLATE и LC_CTYPE параметрами уровня БД. ПорядокЧто мы получаем?
сортировки (collation) и класс символов (ctype) сейчас, подобно
кодировке, хранятся в новых колонках datcollate и datctype
таблицы database.
Это доработанная мной версия патча Radek Strnad'а.
Например, предположим, что есть инстанс PostgreSQL инициализированный с локалью "C":
# \lТ.к. "C" ничего не знает, например, о польских символах, не возможно будет корректно сделать сортировку по польскому тексту. Это же касается работы upper():
List of databases
Name | Owner | Encoding | Collation | Ctype | Access Privileges
-----------+--------+-----------+-----------+-------+----------------------------
depesz | depesz | SQL_ASCII | C | C |
postgres | pgdba | SQL_ASCII | C | C |
template0 | pgdba | SQL_ASCII | C | C | {=c/pgdba,pgdba=CTc/pgdba}
template1 | pgdba | SQL_ASCII | C | C | {=c/pgdba,pgdba=CTc/pgdba}
(4 rows)
# set client_encoding = 'UTF-8';(Если вы не знакомы с польским алфавитом, просто поверьте мне. Сейчас я покажу как это должно выглядеть правильно.).
SET
# select c, upper(c) from (values ('a'), ('ć'), ('e'), ('ź'), ('x'), ('ł'), ('ś'), ('w')) as x (c) order by c;
c | upper
---+-------
a | A
e | E
w | W
x | X
ć | ć
ł | ł
ś | ś
ź | ź
(8 rows)
С версией postgres <= 8.3 мне бы потребовалось переинициализировать кластер (reinitdb), и, соответственно, сконвертировать все базы для новых языковых параметров, что немного проблематично.
К счастью, с версии 8.4 я смогу просто добавить новую базу с другими параметрами:
# CREATE DATABASE depesz_pl with encoding 'utf8' collate 'pl_PL.UTF-8' ctype 'pl_PL.UTF-8' template template0;Единственная проблема в необходимости использования template0. Иначе я получу:
CREATE DATABASE
# CREATE DATABASE depesz_pl with encoding 'utf8' collate 'pl_PL.UTF-8' ctype 'pl_PL.UTF-8';(конечно же я мог бы сделать template1_pl, но не сейчас - как-нибудь в следующий раз :)
ERROR: new collation is incompatible with the collation of the template database (C)
HINT: Use the same collation as in the template database, or use template0 as template
И так, теперь у нас есть новая БД, попробуем на ней наш тестовый запрос:
# \c depesz_plДА! Заработало!
You are now connected to database "depesz_pl".
# show client_encoding ;
client_encoding
-----------------
UTF8
(1 row)
# select c, upper(c) from (values ('a'), ('ć'), ('e'), ('ź'), ('x'), ('ł'), ('ś'), ('w')) as x (c) order by c;
c | upper
---+-------
a | A
ć | Ć
e | E
ł | Ł
ś | Ś
w | W
x | X
ź | Ź
(8 rows)
Также, команда \l выдаст новую информацию:
# \lОдна вещь, которую надо принять - нельзя изменить collation/ctype существующей базы. Причина тому очень проста: индексы зависят от collation (и могут зависеть от ctype). Т.о. изменение collation/ctype потребуют переиндексации всех данных. Если это технически возможно, вы сможете сделать это с помошью дампа базы, создания новой с желаемой локалью и загрузки этого дампа.
List of databases
Name | Owner | Encoding | Collation | Ctype | Access Privileges
-----------+--------+-----------+-------------+-------------+----------------------------
depesz | depesz | SQL_ASCII | C | C |
depesz_pl | depesz | UTF8 | pl_PL.UTF-8 | pl_PL.UTF-8 |
postgres | pgdba | SQL_ASCII | C | C |
template0 | pgdba | SQL_ASCII | C | C | {=c/pgdba,pgdba=CTc/pgdba}
template1 | pgdba | SQL_ASCII | C | C | {=c/pgdba,pgdba=CTc/pgdba}
(5 rows)
Конечно же, ещё далеко до полноценного функционирования PostgreSQL в мультиязычном окружении, но по крайней мере это шаг в правильном направлении. Долгожданный и важный шаг.
Комментарии
Steve, 29 сентября 2008 в 06:43
Вы упомянули "ещё далеко до полноценного функционирования PostgreSQL в мультиязычном окружении". Не могли бы вы рассказать в чём нехватка полноценного функционирования и где могут быть проблемы?
depesz, 29 сентября 2008 в 09:55
@Steve:
Для того чтобы сделать это полнофункциональным, необходима поддержка collation/ctype на более мелких объектах, чем база данных: таблицы или колонки.
Например, для сортировки по тексту на нескольких языках. Конечно, можно везде использовать utf8, но это приводит к дополнительным затратам на конвертацию текста при использовании различных кодировок.
3 comments:
Не получается так и на 4 версии:
ts=# CREATE DATABASE depesz_pl with encoding 'utf8' collate 'pl_PL.UTF-8' ctype 'pl_PL.UTF-8' template template0;
ERROR: syntax error at or near "collate"
ts=# select version();
version
----------------------------------------------------------------------------------------------------------
PostgreSQL 8.4.2 on amd64-portbld-freebsd7.1, compiled by GCC cc (GCC) 4.2.1 20070719 [FreeBSD], 64-bit
Видимо в к релизу поменяли COLLATE/CTYPE на LC_COLLATE/LC_CTYPE.
http://www.postgresql.org/docs/8.4/interactive/sql-createdatabase.html
ага, спасибо, так работает :)
Post a Comment