пятница, 1 июля 2011 г.

Qt: сборка плагина QIBASE. Qt + FireBird Embedded.

     Задумал я тут в недавнем прошлом переписать на Qt программу ранее созданную в Visual Basic 6.0. Попутно решил заменить "классический" сервер БД MySQL, используемый сейчас, каким-либо встраиваемым решением. Основная идея задумки - получить кросс-платформенное и портативное приложение. Исключая хранилища данных основанных на файлах, функционал Qt предложил на выбор, по-сути, три возможных решения: 1) SQLite, 2) MySQL Embedded, 3) FireBird Embedded.
     Первым делом, конечно же, было решено задействовать MySQL Embedded. Следуя инструкции, описанной в справочной системе Qt, собрал плагин QMYSQL слинкованный с MySQL Embedded библиотекой. Сборка прошла успешно, тестовое приложение плагин находило, а вот работать категорически отказывалось. Перелопатив десяток "веток" форумов по теме "Qt + MySQL Embedded" вышел на один сайт с подробным описанием манипуляций, необходимых что бы эту связку заставить работать. Правда, почитав представленную информацию, пришлось отказаться от идеи, т.к. один из ключевых моментов - статическая линковка библиотеки MySQL Embedded (что мне категорически не подходит). Не знаю справедливо ли это для пользователей Linux, но то, что и них есть свои проблемы с ее работой это факт (хотя, возможно, им просто не хватало терпения или библиотеки hands.so ;-)). По некоторым слухам, в Qt 4.8 обещают включить отдельно плагин для MySQL Embedded (на момент написания этого очерка в snapshot Qt 4.8 все оставалось как и прежде - один плагин), пока же этого не произошло, для себя я решил "забыть туда дорогу" :-).
     Следующая на очереди была СУБД SQLite. Сразу порадовала ее поддержка Qt прямо "из коробки", а так же внутренняя кодировка данных - UTF-8/UTF-16. Но радоваться долго не пришлось, как оказалось, SQLite регистронезависимый поиск поддерживает только для символов входящих в кодировку ASCII. Для всех остальных предлагается писать свои функции сравнения, либо использовать связку со сторонней библиотекой ICU. Перспектива собирать библиотеку ICU и перекомпилировать SQLite с ее участием ... меня не впечатлила и я решил, предварительно, ознакомиться с FireBird Embedded. Сделал я это точно не зря - и "головняка" меньше и возможностей больше ;-).
     Тем, кто не знаком с "Огнептицей", рекомендую, как минимум, посетить страницу Википедии - дабы знать, откуда у нее "крылья растут". Не лишним будет ознакомиться с материалами и на сайте IBprovider - разработчика программных продуктов для работы с  InterBase/FireBird. А самых страждущих и напористых ждут на официальном сайте www.firebirdsql.org :-).
     Итак, для работы с этой замечательной СУБД в Qt, необходимо собрать соответствующий плагин - QIBASE. Поскольку моя основная ОС - Windows, отпишусь вкратце как это сделать с помощью MinGW:

  1. скачать с официального сайта FireBird версии сервера Superclassic/Classic и Embedded (если не понимаете о чем идет речь... все-таки стоит сначала почитать Википедию :-)).
  2. установить Superclassic/Classic (либо распаковать архив, если вы скачали не установочную версию) в любую директорию, желательно не содержащую пробелов. Например, "C:\firebird25".
  3. внести в переменную PATH путь до директории "bin" сервера, в нашем случае это "C:\firebird25\bin".
  4. перейти в директорию "%QtDir%\src\plugins\sqldrivers\ibase" и выполнить команду:
    qmake "INCLUDEPATH+=C:/firebird25/include" "LIBS+=C:/firebird25/lib/fbclient_ms.lib" ibase.pro
    Конечно же заменяя пути на свои :-). Обратите внимание, что путь до нужных директорий указывается с использованием прямых слешей, а не обратных.

    Примечание 1: если вы используете QtSDK, то должны знать, что пути немного изменились. Теперь исходные тексты хранятся по адресу: "%QtSDKDir%\QtSources\{версия_Qt}". И, кстати, учитывая новый "механизм" установки - не забудьте их вообще "установить" :-). В offline инсталляторе, их, к примеру, совсем нет.
    Примечание 2: если не получается - вы можете воспользоваться способом сборки плагина описанном в WiKi форума www.prog.org.ru.
  5. выполнить команду:
    mingw32-make.exe all
    В итоге у вас появятся 2 директории с debug и release версиями плагина. Библиотечные файлы из этих каталогов (с расширением *.a  и *.dll) необходимо скопировать в директорию "%QtDir%\plugins\sqldrivers" (для пользователей QtSDK: "%QtSDKDir%\Desktop\Qt\{версия_Qt}\mingw\plugins\sqldrivers").

    Примечание: если mingw32-make.exe завершается с ошибкой об отсутствии файла qsqlcashedresult_p.h (актуально для пользователей QtSDK) - можно пойти двумя путями:
    1) отредактировать файл qsql_ibase.h и вместо:
    #include <QtSql/private/qsqlcachedresult_p.h>
    указать конкретное местоположение файла (с помощью поиска, я думаю найти его труда не составит :-));
    2) скопировать директорию "kernel" из каталога "%QtSDKDir%\QtSources\{версия_Qt}\src\sql" в каталог "%QtSDKDir%\Desktop\Qt\{версия_Qt}\mingw\include\QtSql" и переименовать ее в "private".
  6. заварить кофе/чай и радоваться, что все получилось :-).
     Как подключаться к СУБД и что с ней делать... тема отдельного разговора и, я полагаю, вы не сильно обидитесь, если я ее не затрону :-). Однако, тем, кто только начинает свое знакомство с FireBird, я хотел бы порекомендовать неплохую программу для администрирования СУБД - FlameRobin. ПО бесплатно и постоянно развивается, что является его неоспоримым преимуществом. Подробнее с программой вы всегда можете ознакомиться посетив официальный сайт.
     Далее же в нашей программе - использование встраиваемого решения от FireBird. И тут я вас готов обрадовать - делать, практически, ничего не придется - все необходимое мы уже проделали выше. В отличии от MySQL, FireBird использует одну библиотеку и для "классических" серверов и для "встраиваемого", поэтому плагин QIBASE одинаково успешно работает со всеми видами серверов FireBird. Что позволяет на стадии разработки приложения использовать "классический" сервер, а в момент релиза заменить его на Embedded.
     Для того, чтобы ваше приложение имело возможность работать со встраиваемым сервером FireBird, необходимо, в директорию с запускаемым файлом, поместить следующие файлы и директории из архива с Embedded версией Firebird (помните, мы его скачивали вместе с Superclassic/Classic сервером? ;-)):
  • fbembed.dll, переименовав в fbclient.dll или в gds32.dll (у меня, к примеру, замечательно работает с fbclient.dll);
  • firebird.msg;
  • ib_util.dll;
  • все файлы начинающиеся с icu*;
  • каталог intl;
  • каталог udf;
  • если вы планируете использовать псевдонимы для доступа к БД, вам так же потребуется файл aliases.conf;
  • если же вам потребуется указать специфичные настройки БД (например, местоположение БД), то не забудьте добавить и файл firebird.conf;
     Собственно на этом можно было бы поставить точку и заняться разработкой супер программы с использованием FireBird Embedded, но чувствую обязанность проинформировать начинающих о специфике работы этой версии СУБД FireBird:

  1. поскольку уровень доступа не проверяется, к БД может подключаться любой, кто имеет физический доступ к файлу БД.
  2. доступ к БД осуществляется по локальному протоколу, т.е. вместо указания имени хоста (localhost etc.) необходимо указывать местоположение файла БД.
  3. подключенный клиент блокирует файл БД, т.е. одновременно с БД может работать только один пользователь (правда встраиваемые решения редко разрабатываются как многопользовательские).
     Если все это вас еще не отпугнуло - смело "в бой" :-). Тем же, кто испытывает трудности непосредственно с работой самой FireBird (например, с синтаксисом команд) советую свой взор обратить в сторону парочки ресурсов: www.ibase.ru и www.firebirdsql.su.
     Теперь точно все - всем спасибо за внимание :-). Конструктивные комментарии и замечания всегда приветствуются - пишите, не стесняйтесь ;-).

P/S
Кому нужен собранный плагин для Qt 4.8 - можете взять тут.

6 комментариев:

  1. а собранное есть чего?

    ОтветитьУдалить
  2. trdm

    А что конкретно интересует? Если сам плагин, то могу разместить его на файлообменнике.

    ОтветитьУдалить
  3. не могу собрать для винды никак.
    вот что в консоли

    C:\QtSDK\QtSources\4.8.0\src\plugins\sqldrivers\ibase>qmake -o Makefile "INCLUDEPATH+=C:/Firebird_2_5/include" "LIBS+=C:/Firebird_2_5/lib/fbclient_ms.lib" ibase.pro
    ...
    C:\QtSDK\QtSources\4.8.0\src\plugins\sqldrivers\ibase>mingw32-make -f Makefile.Release
    ...
    collect2: ld returned 1 exit status
    mingw32-make: *** [release\qsqlibase4.dll] Error 1

    после мингв32 следует куча сообщений о undefined reference to

    Помогите что делать?
    Спасибо

    ОтветитьУдалить
    Ответы
    1. inbush

      Перво-наперво,хотел спросить - а как вы "установили" Qt 4.8 в QtSDK? Исходя из блога Qt - 4.8 появиться только в SDK 1.2, которая еще не вышла, да и установленная ранее у меня не предлагала обновиться до 4.8 :-).

      Ну и хотелось бы увидеть полный вывод ошибок mingw32.

      К слову - плагин для 4.8 у меня собрался без проблем (не в версии SDK, а отдельно скачанном бинарнике) - так что если интересует только он - можете забрать его тут. Собран штатным MinGW.

      Удалить
  4. Если еще остался плагин, то выложи пожалуйста!

    ОтветитьУдалить
    Ответы
    1. Да не вопрос, выложить то мне не сложно. Только сейчас он у меня собран на версии 5.0.1 с GCC 4.7.2 win32. Если он подойдет - то выложу :-).

      Удалить