2013-02-24 16 views
5

Chcę porównać dwa ciągi w SQLite DB bez dbania o akcenty i sprawy. Mam na myśli "Événement" powinien być równy "evenment".Zlokalizowane COLLATE na porównywaniu ciągów SQLite

Na Debianie Wheezy, pakiet SQLite nie zapewnia OIOM. Dlatego skompilowałem oficjalny pakiet SQLite (wersja 3.7.15.2 2013-01-09 11:53:05) zawierający moduł ICU. Teraz mam lepszą obsługę Unicode (oryginalny lower() stosowany tylko do znaków ASCII, teraz działa na inne litery). Ale nie mogę zastosować porównania do porównania.

SELECT icu_load_collation('fr_FR', 'FRENCH'); 
SELECT 'événement' COLLATE FRENCH = 'evenement'; 
-- 0 (should be 1) 
SELECT 'Événement' COLLATE FRENCH = 'événement'; 
-- 0 (should be 1 if collation was case-insensitive) 
SELECT lower('Événement') = 'événement'; 
-- 1 (at least lower() works as expected with Unicode strings) 

Numer SQLite documentation potwierdza, że ​​jest to właściwy sposób zastosowania sortowania. Myślę, że documentation of this ICU extension jest trochę światła (kilka przykładów, nic na temat wielkości liter w przypadku sortowania). Nie mam pojęcia, dlaczego operator COLLATE nie ma żadnego efektu w powyższym przykładzie. Proszę pomóż.

Odpowiedz

5

Zajęło mi godziny, aby zrozumieć sytuację ... Sposób, w jaki sortowania ICU są zdefiniowane w SQLite ma (prawie) brak występowania w porównaniach. Wyjątkiem jest, według ICU, teksty hebrajskie ze znakami cantillation. Jest to domyślne zachowanie w kolekcjonowaniu biblioteki ICU. Z SQLite, LIKE staje się niewrażliwy na wielkość liter podczas ładowania ICU, ale normalizacja podkreślonych liter nie może zostać osiągnięta w ten sposób.

I w końcu zrozumiał, że to, co było potrzebne, aby ustawić strength z zestawień do primary level zamiast domyślnego poziomu wyższego.

Nie znalazłem sposobu, aby ustawić to przez ustawienia regionalne (np. Kilka wariantów SELECT icu_load_collation('fr_FR,strength=0', 'french') było bezużytecznych). Jedynym rozwiązaniem było naprawienie kodu SQLite. To było łatwe dzięki funkcji ucol_setStrength() w w ICU API.

Minimalna zmiana to poprawka jednoliniowa: dodaj linię ucol_setStrength(pUCollator, 0); po pUCollator = ucol_open(zLocale, &status); w funkcji icuLoadCollation(). W celu zmiany wstecznej dodałem opcjonalny trzeci parametr do icu_load_collation(), który ustawia siłę: 0 dla domyślnego ustawienia, 1 dla podstawowego itd. Do 4-czwartego. Zobacz diff.

W końcu mam co chciałem:

SELECT icu_load_collation('fr_FR', 'french_ci', 1); -- collation with strength=primary 
SELECT 'Événement' COLLATE french_ci = 'evenèment'; 
-- 1 
Powiązane problemy