postgres - unikod

Adam Buraczewski adamb w polbox.pl
Wto, 23 Lip 2002, 23:25:00 CEST


On Tue, Jul 23, 2002 at 05:43:33PM +0200, Robert Święcki wrote:
> Jest sobie postgres i teraz, można w ma ustawione w /etc/sysconfig/postgresql 

Nie ujmując tej liście, może lepiej na temat PostgreSQLa zadawać
pytania na grupie usenetowej pl.comp.bazy-danych?  Jest tam kilka
osób, które tylko tym się zajmują.  Szczególnie polecam stronę:

	http://www.depesz.pl/pgsql.html

na której jest FAQ tej grupy w zakresie dot. PostgreSQLa.

> CHARSET=UNICODE
> i IMHO jest to nienajlepsze, ponieważ obecne klienckie oprogamowanie 

Wg mnie także nie najlepsze, ale trochę z innych powodów.  Po pierwsze
obsługa unikodu w PostgreSQL nie jest dokończona -- wiele funkcji
operujących na tekście (np. obsługa wyrażeń regularnych) po prostu nie
jest do unikodu przystosowana i daje nieprawidłowe, choć przewidywalne
wyniki.  Sporo z tych niedociągnięć poprawiono już w PostgreSQLu 7.3,
ale pojawi się on dopiero jesienią.  Dlatego, jeżeli nie jest to
jakimś specjalnym wymogiem, nie należy w PostgreSQL trzymać napisów
zakodowanych w unikodzie.

Z PostgreSQLem wiąże się też jeszcze jeden poważny problem, otóż do
obsługi znaków narodowych (zamiana liter małe <-> duże, sortowanie
itp.) wykorzystuje standardowy mechanizm "locale" z glibca.  Dodatkowo
działanie procedur obsługujących indeksy zależy od aktualnych ustawień
locale.  Dlatego autorzy PostgreSQLa (od wersji 7.1) zdecydowali się
na "zamrażanie" locale -- wartości zmiennych LC_CTYPE i LC_COLLATE są
zapamiętywane w chwili wykonania polecenia initdb (czyli zaraz po
instalacji PostgreSQLa) i każde kolejne uruchomienie postgresa używa
tylko tych wartości, pomijając chwilowe ustawienia zmiennych
środowiskowych.  Na dodatek, wartości te są narzucone dla wszystkich
baz danych obsługiwanych przez pojedyńczą instalację PostgreSQLa.

Żeby było ciekawiej, ustawienie kodowania bazy danych (np. za pomocą
opcji createdb -E) nie ma nic wspólnego z wykorzystaniem mechanizmu
locale.  Dlatego może dojść do sytuacji, że baza kodowana jest w
UNICODE a sortowana wg pl_PL.iso8859-2, albo kodowana w LATIN2 (czyli
ISO 8859-2), ale sortowana wg "C" locale (czyli US-ASCII), co jest
chyba najczęstszym źródłem frustracji początkujących administratorów
PostgreSQLa.  Próbują oni często zmieniać locale na pl_PL, co nie daje
efektu, bo przecież PostgreSQL nadal używa starych wartości,
zapamiętanych w chwili wykonania initdb.

Żeby PostgreSQL używał jako tako poprawnie bazy zakodowanej w
unikodzie, to nie tylko należy ustawić kodowanie bazy na UNICODE
(czyli np. wykonać "createdb -E unicode"), ale wcześniej, w chwili
wykonania initdb, locale musi być ustawione na pl_PL.utf-8 (no i takie
locale musi być w ogóle zdefiniowane w systemie, a standardowy glibc
tego nie oferuje).  Znacznie ciekawszym, a częściej stosowanym
rozwiązaniem jest ustawienie locale na pl_PL.iso_8859-2 (= pl_PL po
prostu) oraz kodowania baz danych na LATIN2.  Dzięki temu otrzymuje
się w miarę porządną obsługę polskich znaków (z sortowaniem włącznie),
kosztem może nadal trochę niedoskonałej obsługi wyrażeń regularnych.

Mam nadzieję, że wyjaśniłem w czym problem?

> SET CLIENT_ENCODING=LATIN1
> i.. zadziałało. są polskie literki, ale zapragnąłem miec je także bez tego 

Powinno być LATIN2, nieprawdaż? :)  

> wywołania, w koncu nie chcę o ty mcały czas pamiętać przy pisani czegokolwiek 
> co korzysta z bazy o ustawieniu odpowiedniego charsetu. Co za tem.. ustawiłem 
> CHRSET=LATIN1 
[...]
> unikodzie, podrapałem się w główkę i zajrzałem do 
> /var/lib/psql/postgresq.conf i tam dodałem linijkę 
> client_encoding = latin1
> 
> i.. dalej nie działa.. (postgres sie nie odpalił) tak więc chciałbym zapytać 

Szalejesz trochę z tymi plikami konfiguracyjnymi, zamiast trochę
pomyśleć.  Zmiana wpisu CHARSET w jakimś tam pliku na pewno nie
wpłynie na już działającą instalację PostgreSQLa.  Podejrzewam, że ten
wpis ma jedynie znaczenie dla skrytpu wywołującego initdb przy
pierwszym uruchomieniu PostgreSQLa na danym komputerze.  Żeby to
zrobić porządnie, musisz zrobić backup swoich baz danych, a następnie
zastopować PostgreSQLa i usunąć cały katalog $PGDATA (nie pamiętam w
tej chwili, gdzie on w PLD jest).  Potem zmień CHARSET na LATIN2,
upewnij się że locale będzie takie: LC_CTYPE=pl_PL i LC_COLLATE=pl_PL
i uruchom PostgreSQLa.  Sprytny skrypt w PLD pewnie zrobi na nowo
initdb, a Ty sobie zainstalujesz swoje bazy z powrotem.

Podejrzewam też, że w PLD to wszystko z powyższego akapitu jest już
zrobione.  Jeżeli tak, to wystarczy że tworząc bazę danych określisz
jej kodowanie jako LATIN2 (opcja -E w wywołaniu createdb) i wszystko
będzie działać poprawnie.  W tym przypadku wpis o UNICODE nie ma
znaczenia.

Poza tym, jeżeli PostgreSQL się "nie odpalił", to pierwszą rzeczą jest
zajrzenie do logów i zobaczenie dlaczego.  Uwierz mi, to tam będzie
dokładnie wyjaśnione.

> zgromadzonych tutaj w.czc. uzytkowników, czy ktoś już rozwiązał problem 
> unikodowego posgresa w pld w sposób inny niż wywoływanie SET z klienta?

Wywoływanie SET CLIENT_ENCODING to tylko życzenie klienta, w jakim
kodowaniu będzie się porozumiewał z serwerem.  Serwer wówczas
odpowiednio przekodowuje z/na kodowanie używane przez daną bazę.  I
zrezygnuj z unikodu w PostgreSQLu, prawie na pewno nie jest Ci to
potrzebne.

Uff, rozpisałem się :))  Jeżeli będziesz miał nadal wątpliwości, to
pisz do mnie.

Pozdrawiam!

-- 
Adam Buraczewski <adamb w polbox.pl> * Linux registered user #165585
GCS/TW d- s-:+>+:- a- C+++(++++) UL++++$ P++ L++++ E++ W+ N++ o? K? w--
O M- V- PS+ !PE Y PGP+ t+ 5 X+ R tv- b+ DI? D G++ e+++>++++ h r+>++ y?



Więcej informacji o liście dyskusyjnej pld-users-pl