Поиск в SQLite без учета регистра, для русского языка

August 14th, 2010 Begemot Posted in Использование

Не смотрю на всю свою юникодность, SQLite все-таки юникодна не до конца:( При поиске типа WHERE description LIKE “%STRING%” поиск идет без учета регистра для латинских букв, но к сожалению, он регистрозависимый для всех остальных символов. Корни этого уходят в виндовую функцию tolower(), которая правильно обрабатывает символы только текущей локали. И это весьма плохо, для целого ряда задач, например для поиска ранее скопированного текста в истории буфера обмена (извините, не удержался:))

Но к счастию способ есть. Оригинал и файлы для загрузки тут – SQLite and native UNICODE LIKE support in C/C++ . А я раскажу о том как это интегрировать и скрестить с wxDatabaselayer’om.

  1. Берем файлы sqlite3_unicode.h/c с архива по ссылке выше и добавляем в проект.
  2. Вызываем свойства sqlite3_unicode.c  и добавляем SQLITE_ENABLE_UNICODE; SQLITE_CORE в определения препроцессора c++/preprocessor/preprocessor definitions
  3. Если используете precompiled header в проекте, надо в свойствах обоих файлов отключить его использование.
  4. в с файле есть строчка #include “sqlite3.h” заменить ее на свой путь к sqlite3.h, если он у вас отличается
  5. Включить sqlite3.h в sqlite3_unicode.h, без этого у меня не компилилось.
  6. Дальше вызываете sqlite3_unicode_load();  \  sqlite3_unicode_free();  –  в начале/конце программы
  7. После открытия базы данных вызываем для нее sqlite3_unicode_init(db);

Проблема тут в том что sqlite3_unicode_init(db); хочет db типа sqlite3 *, а у нас есть только указатель на обьект датабайслаера. Тут придется править код самого wxDatabaselayer’a и заново компилить. Идем в databaselayer\include\SqliteDatabaseLayer.h, пишем:

// Added by Begemot – for using with  sqlite3_unicode
void * GetSQLiteDatabase()  { return m_pDatabase; } 

компиляем, и в нашей программе вместо строчки sqlite3_unicode_init(db); используем вот такую вот страшную конструкцию

sqlite3_unicode_init(static_cast<sqlite3*>(static_cast<SqliteDatabaseLayer*>(db)->GetSQLiteDatabase()));

Все. Теперь Like % прекрасно ищет по русским или любым другим символам без учета регистра.

Related:

8 Responses to “Поиск в SQLite без учета регистра, для русского языка”

  1. Я правда не знаком с SQLite но в других БД можно выкрутиться конструкцией типа WHERE UPPER(description) LIKE ‘%STRING%’

  2. дык UPPER(description) наверняка же будет делатся той же виндовой toupper, зависящей от локали…

  3. с ICU люди еще собирают я слышал, но там и с апи тогда нужно добавлять sqlite3_enable_load_extension
    вот обсуждение
    http://habrahabr.ru/blogs/sql/57915/

    я лично FireBird пользую

  4. Спасибо, полезная ссылка буду иметь ввиду. Вдруг я полезну под другие платформы все-таки 🙂

    Хотя вроде бы ICU сильно утяжеляет библиотеку…

  5. Яблоков Says:

    Извините, а скомпилированную sqlite3_unicode (win) могли бы выложить?

  6. Это просто файлы добавляемые в ваш проект…

  7. Яблоков Says:

    Ай, а если проект на другом языке? 🙂 А превратить это в dll есть возможность? (Если не сложно конечно, если нет, буду сам разбираться).

  8. нет, незнаю, тут к сожалению ничем не помогу 🙂