Возникла проблема — хочу использовать sqlite для базы данных через QSql, но вот беда — в стандартной, а, стало быть и в Qt-шной поставке полноценная поддержка unicode в комплект не входит
Платформа — Windows, версия Qt — 4.6.0, версия sqlite в нём — 3.6.19. Собран sqlite как отдельный плагин (dll), причём ни одна из sqlite* ф-ций из таблицы экспорта не выглядывает (т.е. предлагаемый Qt Assistant трюк с:
QSqlDatabase db = ...;
QVariant v = db.driver()->handle();
if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*")==0) {
// v.data() returns a pointer to the handle
sqlite3 *handle = *static_cast<sqlite3 **>(v.data());
if (handle != 0) { // check that it is not NULL
...
}
}
бесполезен).
Решение проблемы вижу в том, чтобы подправить исходники qsql_sqlite.* (qt\src\sql\drivers\sqlite), в которых переопределить ф-ции upper, lower и collate NOCASE (кажется, так, но я могу ошибаться; Для like в sqlite достаточно NOCASE задать или лучше к uppercase обе строки перед сравнением приводить?). И пересобрать таким образом плагин. А т.к. это LGPL, с дистрибутивом программы положить архив с изменёнными исходниками (или для соблюдения лицензии надо что-то ещё?).
Пока искал по сети, встречал готовые DLL с поддержкой unicode, слинкованные с ICU. Стоит попробовать прикрутить их или зря время потрачу?
Вопрос — кто-нибудь добавлял поддержку unicode (конкретно для регистронезависимого поиска) в драйвер sqlite для Qt? Есть более красивое или даже готовое решение (гуглил — не нашёл )?
P.S. FTS3, case-insensitivity работающую с utf-8, замучаюсь прикручивать или тоже стоит попробовать?
(18) Case-insensitive matching of Unicode characters does not work.
The default configuration of SQLite only supports case-insensitive comparisons of ASCII characters. The reason for this is that doing full Unicode case-insensitive comparisons and case conversions requires tables and logic that would nearly double the size of the SQLite library. The SQLite developers reason that any application that needs full Unicode case support probably already has the necessary tables and functions and so SQLite should not take up space to duplicate this ability.
Instead of providing full Unicode case support by default, SQLite provides the ability to link against external Unicode comparison and conversion routines. The application can overload the built-in NOCASE collating sequence (using sqlite3_create_collation()) and the built-in like(), upper(), and lower() functions (using sqlite3_create_function()). The SQLite source code includes an "ICU" extension that does these overloads. Or, developers can write their own overloads based on their own Unicode-aware comparison routines already contained within their project.
Здравствуйте, Alexey F, Вы писали:
AF>Пока искал по сети, встречал готовые DLL с поддержкой unicode, слинкованные с ICU. Стоит попробовать прикрутить их или зря время потрачу?
А не проще взять субд поддерживающую юникод? Тот же firebird embedded по удобству не отличается от sqlite, зато вполне взрослая субд. Размер правда больше, но не фатально.
(18) Case-insensitive matching of Unicode characters does not work.
[]
В sqlite-вский FAQ я конечно же смотрел
Или это ответ на
Для like в sqlite достаточно NOCASE задать или лучше к uppercase обе строки перед сравнением приводить?
?
Каюсь, про строку "The application can overload the built-in NOCASE collating sequence (using sqlite3_create_collation()) and the built-in like(), upper(), and lower() functions (using sqlite3_create_function())." вчера перед сном забыл.
Ещё же в процессе гугления было упоминание о каких-то граблях со сборкой sqlite+ICU под windows, поэтому счёл нужным спросить RSDN.
Здравствуйте, Ziaw, Вы писали:
Z>А не проще взять субд поддерживающую юникод? Тот же firebird embedded по удобству не отличается от sqlite, зато вполне взрослая субд. Размер правда больше, но не фатально.
Не получится с sqlite — гляну firebird, спасибо за наводку.
Разницы мне действительно особенной нет, просто прикрутить регистронезависимый поиск к sqlite вчера показалось проще, чем взять другую БД.
Сегодня ещё немного попробую покопать в этом направлении.
Тот пост, что писал раньше, удалил, теперь по-нормальному.
По запросу в google "sqlite icu windows" выходим первой же ссылкой на: http://www.urban-eye.com/pagesqliteicu.html. Я взял версию 3.6.22. Кстати, там же, чуть ниже поищите по строке "icudt38.dll" и скачайте прилагающийся архив. Оттуда берём 3-хкилобайтовый файл icudt38.dll (он почему-то не был приложен в архиве с версией 3.6.22).
Договоримся, что в %QTDIR% у нас записан путь туда, где установлена Qt с папкой src внутри (в моём случае это "...\Qt\2009.05\qt").
В %QTDIR%/3rdparty создаём папку sqliteicu, туда распаковываем sqlite*.* из amalgamation-архива с sqlite.org. Там же поместим lib-файл к sqlite3.dll (для mingw-gcc описание этой процедуры здесь).
На всякий случай def-файл для sqlite3.dll:
Я назвал результат libsqlite3dll.a.
Далее в %QTDIR%\src\sql\drivers копируем папку sqlite в sqliteicu, все вхождения QSQLite заменяем на QSQLiteICU в файлах qsql_sqlite*.
Попутно в файле qsql_sqlite.cpp заменяем:
В %QTDIR%\src\plugins\sqldrivers копируем sqlite в sqliteicu. Я поменял имена *.rc-файлов, заменив sqlite на sqliteicu.
В файле %QTDIR%\src\plugins\sqldrivers\sqliteicu\smain.cpp делаем следующие изменения:
QSQLite меняем на QSQLiteICU, QLatin1String("QSQLITE") заменяем на QLatin1String("QSQLITEICU").
Компилируем так:
cd %QTDIR%\qt\src\plugins\sqldrivers\sqliteicu
qmake "INCLUDEPATH+=../../../3rdparty/sqliteicu" "LIBS+=-L../../../3rdparty/sqliteicu -lsqlite3dll"
В файле sqlite.pro (у меня он переименован в sqliteicu.pro), в папке %QTDIR%\src\plugins\sqldrivers\sqliteicu:
Все icu*.dll-файлы не забываем положить в одну из простреливаемых переменной окружения %PATH% папок
Проверял работу dll через %QTDIR%/demos/sqlbrowser, подключив там QSQLITEICU. upper, lower, like, order by работают правильно:
create table Test values ( content text );
insert into Test values ( 'Строка' );
insert into Test values ( 'СтРОка' );
insert into Test values ( 'строкА' );
select upper ( context ) from Test;
...
Правда, collate nocase от этого на unicode-строках не заработал . Только с lower/upper.
Re[2]: Нормальное решение
От:
Аноним
Дата:
14.10.11 07:41
Оценка:
Здравствуйте, Alexey F, Вы писали:
Тот пост, что писал раньше, удалил, теперь по-нормальному.
Делал по предложенному мануалу.
В результате получил длл-ки qsqliteicud4.dll и qsqliteicu4.dll, положил их в папку %QTDIR%\plugins\sqldrivers
Пытаюсь делать QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITEICU");
В ответ получаю:
QSqlDatabase: QSQLITEICU driver not loaded
QSqlDatabase: available drivers: QSQLITE QMYSQL3 QMYSQL
Здравствуйте, Аноним, Вы писали:
А>QSqlDatabase: QSQLITEICU driver not loaded А>QSqlDatabase: available drivers: QSQLITE QMYSQL3 QMYSQL
А>Подскажите пожалуйста, в чем я не прав?
DLL, от которых зависят эти две — т.е. целая пачка icu* лежат в %QTDIR%\plugins\sqldrivers?
Если попробовать загрузить DLL хоть через OllyDBG, она грузится или с исключением падает при загрузке?
Уже не помню, влияет ли это, но — компилятор тот же, которым собирался сам Qt?
Здравствуйте, Alexey F, Вы писали:
AF>Здравствуйте, Аноним, Вы писали:
А>>QSqlDatabase: QSQLITEICU driver not loaded А>>QSqlDatabase: available drivers: QSQLITE QMYSQL3 QMYSQL
А>>Подскажите пожалуйста, в чем я не прав? AF>DLL, от которых зависят эти две — т.е. целая пачка icu* лежат в %QTDIR%\plugins\sqldrivers? AF>Если попробовать загрузить DLL хоть через OllyDBG, она грузится или с исключением падает при загрузке? AF>Уже не помню, влияет ли это, но — компилятор тот же, которым собирался сам Qt?
dll-ли лежат.
Qt не собирался, устанавливал QtSDK.
Компилятор mingw.
OllyDBG при попытке открыть qsqliteicu4.dll говорит что не найдена точка входа в qtcore.dll, т.е. сама dll-ка вроде бы грузится.
Здравствуйте, WindAndRain, Вы писали:
WAR>OllyDBG при попытке открыть qsqliteicu4.dll говорит что не найдена точка входа в qtcore.dll, т.е. сама dll-ка вроде бы грузится.
Точнее наоборот.
OllyDBG подцепите к процессу, поставьте break на LoadLibraryW и посмотрите, прогружается она хоть или нет (код возврата LoadLibraryW + GetLastError; или он вообще плагин не видит и грузить не пытается).
Кстати, sqlbrowser тоже о новой sqlite не упоминает?
Свою версию уже давно не обновлял, смогу глубже копнуть когда она скачается/установится.
Здравствуйте, Alexey F, Вы писали:
AF>Здравствуйте, WindAndRain, Вы писали:
WAR>>OllyDBG при попытке открыть qsqliteicu4.dll говорит что не найдена точка входа в qtcore.dll, т.е. сама dll-ка вроде бы грузится. AF>Точнее наоборот. AF>OllyDBG подцепите к процессу, поставьте break на LoadLibraryW и посмотрите, прогружается она хоть или нет (код возврата LoadLibraryW + GetLastError; или он вообще плагин не видит и грузить не пытается). AF>Кстати, sqlbrowser тоже о новой sqlite не упоминает? AF>Свою версию уже давно не обновлял, смогу глубже копнуть когда она скачается/установится.
Собираю дистрибутив программы, кладу рядом с ней все нужные dll-ки, все запускается, like работает как надо, т.е. драйвер подцепился.
Из QtCreator программа не запускается, ругается на невалидный драйвер.
upd: положил icu* в папку куда делается сборка, программа запустилась. Видимо QTCreator не смог подхватить зависимости qsqliteicu из папки %QtDir%/plugins/sqldrivers