2012-10-31 6 views
5

Aktualnie pracuję nad aplikacją IOS, która będzie wyszukiwać pełnotekstowo. Wyszukiwanie jest wykonywane przez wykonanie instrukcji select w bazie danych sqlite, ale problem polega na tym, że wiele wartości w bazie danych zawiera skandynawskie litery (Æ, Ö, Á itp.) I mam problemy z konwersją instrukcji bez uzyskiwania wartości szesnastkowych dla liter.Jak poprawnie kodować NSString dla SQLite, cały czas zachowując skandynawskie litery

Oto co mam aktualnie robi:

const char *sql = [[NSString stringWithFormat: 
        @"SELECT %@\ 
        FROM Customer c\ 
        JOIN Customer_Metadata cm ON c.CustomerId = cm.CustomerId\ 
        WHERE cm.Name LIKE '%%%@%%'\ 
        ORDER BY cm.Name", kCustomerSelect, searchString] UTF8String]; 

Teraz kCustomerSelect jest stałą zawierającą kolumny chcę zaznaczyć, a searchString zawiera dane wprowadzone przez użytkownika.

Działa to jak czar dla normalnych łacińskich liter, ale jeśli na przykład przejdę wzdłuż Ö, jako searchString, otrzymam st \ xc3 \ xb6. Jestem świadomy, że zwyczajne wylogowanie się z łańcucha zakodowanego w UTF8 nie da prawidłowej reprezentacji ciągu znaków, ale problem polega na tym, że moja instrukcja select nie daje żadnych wyników.

Nazywam sqlite3_open() przed wykonaniem zapytania iz dokumentacji SQLite * "Domyślnym kodowaniem dla bazy danych będzie UTF-8, jeśli wywoływana jest metoda sqlite3_open() lub sqlite3_open_v2(), a kodowanie UTF-16 w wersji macierzystej kolejności bajtów, jeśli użyto sqlite3_open16(). "*.

Próbowałem używać różnych kodowań zastępując UTF8String z cStringUsingEncoding: i wypróbowując różne kodowania. Żaden z nich nie działał (nie, że oczekiwałem ich, ale przynajmniej chciałem spróbować).

Każda pomoc lub wskazówki byłyby mile widziane.

Edytuj Próbowałem już teraz użyć przeglądarki bazy danych SQLite do uruchomienia tej samej instrukcji select w bazie danych i nie otrzymuję żadnych wyników. To prowadzi mnie do przekonania, że ​​może to mieć coś wspólnego ze mną, używając FTS3 do utworzenia tabeli Customer_Metadata.

MrDresden

Odpowiedz

0

Jeśli używasz FTS3, domyślny tokenizer nie zrobi tego, co chcesz.

ile konkretny tokenizer jest określony jako część CREATE VIRTUAL TABLE używany do tworzenia tabeli FTS, domyślny tokenizera, "proste", jest wykorzystywana.Prosty tokenizer wyodrębnia tokeny z dokumentu lub podstawowej kwerendy pełnotekstowej FTS zgodnie z następującymi regułami:

Termin jest ciągłą sekwencją znaków spełniających kryteria, gdzie znakami kwalifikującymi się są wszystkie znaki alfanumeryczne, a wszystkie znaki z wartościami kodowymi w standardzie Unicode są większe równy lub równy 128. Wszystkie pozostałe znaki są odrzucane podczas dzielenia dokumentu na terminy. Ich jedynym wkładem jest oddzielenie sąsiednich terminów.

- http://www.sqlite.org/fts3.html#tokenizer

Musisz użyć niestandardowego tokenizera, lub sprawdzić, czy OIOM lub unicode61 tokenizers będzie pracować dla Ciebie. Informacje na ten temat znajdują się w powyższym dokumencie.

+0

Niestety, po wypróbowaniu zarówno ICU, jak i Unicode61, nadal nie otrzymuję wyników. Być może trzeba będzie utworzyć niestandardowy tokenizer, tak jak mówisz. – Hrafn

0

Napisz zapytanie tak:

const char *sql = [[NSString stringWithFormat: 
       @"SELECT %@\ 
       FROM Customer c\ 
       JOIN Customer_Metadata cm ON c.CustomerId = cm.CustomerId\ 
       WHERE cm.Name LIKE ?\ 
       ORDER BY cm.Name", kCustomerSelect] UTF8String]; 

Po przygotować oświadczenie, wiążą searchString:

sqlite3_bind_text(statement, 1, [[NSString stringWithFormat:@"%%%@%%", searchString] UTF8String], -1, SQLITE_TRANSIENT); 

Dopóki baza danych jest UTF-8, a następnie możesz wpisywać tekst w języku greckim, rosyjskim, japońskim i oczywiście używając różnych skandynawskich znaków.

Edytuj: Właśnie widziałem twoją edycję. Jeśli dane nie zostały utworzone prawidłowo, to z pewnością byłby problem.

+0

Dzięki za pomoc. Próbowałem Twojej sugestii, ale nadal nie otrzymuję wyników dla "specjalnych" listów. Naprawdę zaczynam myśleć, że muszę znaleźć specjalny tokanizer dla moich tabel FTS3. – Hrafn

+0

Wystarczy notatkę boczną (ignorując natychmiastowy problem w danym momencie) - powód, dla którego powinieneś używać 'sqlite_bind_xxx' przez formaty ciągów, jest tak, ponieważ' sqlite_bind_xxx' poprawnie obsługuje przypadki, takie jak wartość ciągu zawierającego cytaty. Rozwiązuje również ataki typu SQL-injection. Powodzenia w kwestii FTS. – rmaddy

Powiązane problemy