2013-02-24 2 views
5

ich zwei Strings in einer SQLite DB vergleichen will für die Akzente und den Fall ohne Pflege. Ich meine "Événement" sollte gleich "evenèment" sein.Lokalisierte COLLATE auf einem SQLite String-Vergleich

Auf Debian Wheezy, wird das SQLite-Paket ICU nicht bieten. Also habe ich das offizielle SQLite-Paket (Version 3.7.15.2 2013-01-09 11:53:05) mit einem ICU-Modul zusammengestellt. Nun, ich habe eine bessere Unicode-Unterstützung (das Original lower() gilt nur für ASCII-Zeichen, jetzt funktioniert es für andere Buchstaben). Aber ich kann es nicht schaffen, eine Vergleiche auf einen Vergleich anzuwenden.

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) 

The SQLite documentation bestätigt, dass dies der richtige Weg ist eine Sortierung anzuwenden. Ich denke, die documentation of this ICU extension ist ein bisschen Licht (einige Beispiele, nichts auf Groß-und Kleinschreibung für Kollatierungen).

Ich verstehe nicht, warum die COLLATE Betreiber keinen Einfluss in meinem Beispiel oben haben. Bitte helfen Sie.

Antwort

5

Ich habe Stunden um die Situation zu verstehen ... Die Art und Weise der ICU-Sortierungen in SQLite hat definiert sind (fast) keine Auswirkung auf Vergleiche. Eine Ausnahme sind laut der ICU hebräische Texte mit Krattierungszeichen. Dies ist das Standardverhalten der Sortierung der ICU-Bibliothek. Mit SQLite wird LIKE beim Laden der ICU nicht zwischen Groß- und Kleinschreibung unterschieden, aber die Normalisierung der akzentuierten Buchstaben kann auf diese Weise nicht erreicht werden.

ich endlich verstanden, dass das, was ich brauchte die strength des Vergleichs an die primary level anstelle der Standard-Tertiärstufe eingestellt war.

Ich habe keine Möglichkeit gefunden, dies über das Gebietsschema (z. B. mehrere Varianten von SELECT icu_load_collation('fr_FR,strength=0', 'french') waren nutzlos). So war die einzige Lösung, den Code von SQLite zu patchen. Es war einfach, dank der ucol_setStrength() Funktion im ICU API.

Die minimale Änderung ist ein einzeiliger Patch: Fügen Sie die Zeile ucol_setStrength(pUCollator, 0); nach in die Funktion icuLoadCollation() ein. Für eine abwärtskompatible Änderung habe ich einen optionalen dritten Parameter zu icu_load_collation() hinzugefügt, der die Stärke festlegt: 0 für Standard, 1 für Primär, usw. bis zu 4-quaternär. Siehe die diff.

Endlich Ich habe, was ich wollte:

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