2012-10-31 38 views
5

Tôi hiện đang làm việc trên một ứng dụng IOS sẽ có tìm kiếm toàn văn. Việc tìm kiếm được thực hiện bằng cách thực hiện câu lệnh chọn trên cơ sở dữ liệu sqlite, nhưng vấn đề là nhiều giá trị trong cơ sở dữ liệu chứa chữ cái Scandinavia (Æ, Ö, Á vv) và tôi gặp sự cố khi chuyển đổi câu lệnh mà không nhận giá trị hex cho các chữ cái.Cách mã hóa NSString chính xác cho SQLite trong khi vẫn giữ các chữ cái Scandinavia

Đây là những gì tôi đang thực hiện:

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]; 

Bây giờ kCustomerSelect là một hằng số chứa các cột tôi muốn chọn, và searchString chứa đầu vào người dùng.

Điều này hoạt động như một nét duyên dáng cho các chữ cái La-tinh bình thường, nhưng nếu tôi ví dụ truyền theo Ö, dưới dạng một chuỗi tìm kiếm, tôi nhận được lệnh \ xc3 \ xb6. Tôi biết rằng chỉ cần đăng xuất một chuỗi được mã hóa UTF8 sẽ không cung cấp biểu diễn chính xác của chuỗi, nhưng vấn đề là câu lệnh chọn của tôi không cho tôi bất kỳ kết quả nào.

Tôi đang gọi sqlite3_open() trước khi thực hiện truy vấn và từ tài liệu SQLite * "Mã hóa mặc định cho cơ sở dữ liệu sẽ là UTF-8 nếu sqlite3_open() hoặc sqlite3_open_v2() được gọi và UTF-16 ở gốc thứ tự byte nếu sqlite3_open16() được sử dụng. "*.

Tôi đã thử sử dụng các mã hóa khác nhau bằng cách thay thế UTF8String bằng cStringUsingEncoding: và thử các mã hóa khác nhau. Không ai trong số họ đã làm việc (không phải là tôi đã mong đợi họ, nhưng ít nhất là muốn thử).

Bất kỳ và tất cả trợ giúp hoặc mẹo đều được đánh giá cao.

Chỉnh sửa Tôi hiện đã thử sử dụng Trình duyệt cơ sở dữ liệu SQLite để chạy cùng một câu lệnh chọn trên cơ sở dữ liệu và không nhận được bất kỳ kết quả nào. Điều này khiến tôi tin rằng điều này có thể liên quan đến tôi bằng cách sử dụng FTS3 để tạo bảng Customer_Metadata của tôi.

MrDresden

Trả lời

0

Nếu bạn đang sử dụng FTS3, trình mã thông báo mặc định sẽ không thực hiện những gì bạn muốn.

Trừ một tokenizer cụ thể được quy định như một phần của CREATE TABLE VIRTUAL sử dụng để tạo ra các bảng FTS, các tokenizer mặc định, "đơn giản", được sử dụng.Trình mã thông báo đơn giản trích xuất các mã thông báo từ tài liệu hoặc truy vấn toàn văn bản FTS cơ bản theo các quy tắc sau:

Thuật ngữ là một chuỗi ký tự đủ điều kiện, tất cả các ký tự có giá trị codepoint Unicode lớn hơn lớn hơn hoặc bằng 128. Tất cả các ký tự khác sẽ bị hủy khi tách tài liệu thành các thuật ngữ. Đóng góp duy nhất của họ là tách biệt các thuật ngữ liền kề.

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

Bạn sẽ cần phải sử dụng một tokenizer tùy chỉnh, hoặc xem nếu ICU hoặc tokenizers unicode61 sẽ làm việc cho bạn. Thông tin về những người trong tài liệu được liên kết ở trên.

+0

Đáng buồn thay, sau khi thử cả ICU và Unicode61, tôi vẫn không nhận được kết quả. Tôi có thể cần phải tạo một tokenizer tùy chỉnh như bạn nói. – Hrafn

0

Viết truy vấn của bạn như thế này:

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]; 

Sau khi bạn chuẩn bị báo cáo kết quả, ràng buộc searchString:

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

Chừng nào cơ sở dữ liệu là UTF-8, sau đó bạn có thể nhập văn bản bằng tiếng Hy Lạp, tiếng Nga, tiếng Nhật và tất nhiên bằng cách sử dụng các ký tự Scandinavia khác nhau.

Chỉnh sửa: Tôi vừa xem bản chỉnh sửa của bạn. Nếu dữ liệu không được tạo đúng cách, điều đó chắc chắn sẽ là một vấn đề.

+0

Cảm ơn sự giúp đỡ. Tôi đã thử đề xuất của bạn nhưng vẫn không nhận được kết quả cho các chữ "đặc biệt". Tôi thực sự bắt đầu nghĩ rằng tôi cần phải tìm một tokanizer đặc biệt cho các bảng FTS3 của tôi. – Hrafn

+0

Chỉ cần một lưu ý phụ (bỏ qua vấn đề ngay lập tức cho thời điểm này) - lý do bạn nên sử dụng 'sqlite_bind_xxx' trên các định dạng chuỗi là vì' sqlite_bind_xxx' xử lý đúng các trường hợp như giá trị chuỗi chứa dấu ngoặc kép. Cũng có thể giải quyết các cuộc tấn công SQL injection. Chúc may mắn với vấn đề FTS. – rmaddy

Các vấn đề liên quan