Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > [Qt4]сборка драйвера для PostgreSQL


Автор: LazyVoid 1.3.2008, 01:38
Доброго здравия.
Вот уже 5 дней пытаюсь собрать драйвер для постгрес, но никакого толка не выходит.
Не справившись с проблемой самостоятельно, надеюсь на вашу помощь, господа форумчане.
О компонентах:

1) WindowsXP SP2;
2) qt-win-opensource-src-4.3.3.zip
3) postgresql-8.3.0-1.zip
4) MinGW-3.4.2.exe
5) mingw-utils-0.3.tar.gz

Переменные среды:
PATH = C:\MinGW\bin;C:\Qt\4.3.3\bin;C:\PostgreSQL\bin
INCLUDE = C:\PostgreSQL\include
LIB = C:\PostgreSQL\lib
QTDIR = C:\Qt\4.3.3
QMAKESPECS = win32-g++

configure.bat:
Код

set PATH=c:\mingw\bin;c:\qt\4.3.3\bin;%PATH%
set QTDIR=c:\qt\4.3.3
set QMAKESPEC=win32-g++
c:
cd c:\Qt\4.3.3\
configure -fast -release -shared -rtti -exceptions -accessibility -stl -qt-zlib -no-gif -qt-libpng -qt-libmng -qt-libjpeg -qmake -process -qt-sql-psql -no-qt3support
mingw32-make


Действия:
Руководствуясь
http://projects.org.ua/forum.phpbb2ru/viewtopic.php?p=4381&sid=5f92228ea8c9fc0fe7467ce0265480b7
переделал libpq.lib в lib.a следующим образом:

reimp -d libpq.lib
скопировал из директории PostgreSQL\bin в ..\lib libpq.dll
убрал подчеркивания в LIBPQ.DEF
dlltool --input-def libpq.def --dllname libpq.dll --output-lib libpq.a --kill-at

Далее собрал Qt приведенным выше батником, все прошло успешно, но:
1) Драйвер не отображается для приложений
2) Не запускается sqlbrowser через qdemo
3) При запуске вручную из папки вылетает следующая ошибка:
    Порядковый номер 284 не найден в библиотеке DLL SSLEAY32.dll

При проверке Dependency Walker'ом sqlbrowser.exe получены следующие сообщения:
Error: At least one module has an unresolved import due to a missing export function in an implicitly dependent module.
Warning: At least one module has an unresolved import due to a missing export function in a delay-load dependent module.

В общем дело сводится к тому что он ругается на MPR.dll, WNetRestoreConnectionA помечена красным.
Но я где то читал что на это не надо обращать внимания т.к. это вроде dw гонит.

Надеюсь проблему изложил верно, жду комментариев и помощи, заранее благодарен всем.

P.S. также компилил как плагин, пробовал на бинарной версии Qt но бестолку (:

Автор: SABROG 1.3.2008, 02:41
Цитата

SSLEAY32.dll


Это либа от OpenSSL. Нафиг делать reimp, когда Postgre прекрасно собирается мингвой не понимаю, если собирать отстоем в виде MSVC, то да.

Мой совет, хочешь Слона собирай и линкуй его к Qt своими силами, плюнь на плагины, как показывает опыт они бажные по самое не балуй. Взять хотябы последний WebKit, крашится хоть на Win2000, хоть на WinXP. И вообще чем больше вникаю в Qt, тем больше понимаю, что оно глючное, но это лучшая альтернатива.

Автор: LazyVoid 1.3.2008, 02:52
Цитата

Нафиг делать reimp, когда Postgre прекрасно собирается мингвой не понимаю, если собирать отстоем в виде MSVC, то да.

Может я плохо выразился.
Смысл в том что я поставил Постгрес из бинарника, а reimp делал для того чтобы мингв получил либу для сборики драйвера, т.к. он вроде как не понимает либы *.lib, вот и делал *.а
Цитата

хочешь Слона собирай и линкуй его к Qt своими силами

поподробнее бы расписали smile

Автор: SABROG 1.3.2008, 12:50
Цитата(LazyVoid @ 1.3.2008,  02:52)
поподробнее бы расписали smile

- качаем исходники слона
- качаем исходники openssl
- компилим openssl мингвой
- конфигурим исходники слона включая поддержку опенссл, прописываем директории до ходиреов и .a файлов
- компилим слона мингвой
- открываем .pro файл своего проекта и добавляем путь для поисков иклудов:
INCLUDEPATH += путь_до_инклудов_слона
LIBS += -Lпуть_где_искать_.a_файлы_слона -lимя_линкуемого.a_файла
- открываем исходники и прописываем иклуд:
#include "libpq-fe.h"
- пишем свой код для работы с базой данных:
Код

/*
 * testlibpq.c
 *
 *        Test the C version of libpq, the PostgreSQL frontend library.
 */
#include <stdio.h>
#include <stdlib.h>
#include "libpq-fe.h"

static void
exit_nicely(PGconn *conn)
{
    PQfinish(conn);
    exit(1);
}

int
main(int argc, char **argv)
{
    const char *conninfo;
    PGconn       *conn;
    PGresult   *res;
    int            nFields;
    int            i,
                j;

    /*
     * If the user supplies a parameter on the command line, use it as the
     * conninfo string; otherwise default to setting dbname=postgres and using
     * environment variables or defaults for all other connection parameters.
     */
    if (argc > 1)
        conninfo = argv[1];
    else
        conninfo = "dbname = postgres";

    /* Make a connection to the database */
    conn = PQconnectdb(conninfo);

    /* Check to see that the backend connection was successfully made */
    if (PQstatus(conn) != CONNECTION_OK)
    {
        fprintf(stderr, "Connection to database failed: %s",
                PQerrorMessage(conn));
        exit_nicely(conn);
    }

    /*
     * Our test case here involves using a cursor, for which we must be inside
     * a transaction block.  We could do the whole thing with a single
     * PQexec() of "select * from pg_database", but that's too trivial to make
     * a good example.
     */

    /* Start a transaction block */
    res = PQexec(conn, "BEGIN");
    if (PQresultStatus(res) != PGRES_COMMAND_OK)
    {
        fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(conn));
        PQclear(res);
        exit_nicely(conn);
    }

    /*
     * Should PQclear PGresult whenever it is no longer needed to avoid memory
     * leaks
     */
    PQclear(res);

    /*
     * Fetch rows from pg_database, the system catalog of databases
     */
    res = PQexec(conn, "DECLARE myportal CURSOR FOR select * from pg_database");
    if (PQresultStatus(res) != PGRES_COMMAND_OK)
    {
        fprintf(stderr, "DECLARE CURSOR failed: %s", PQerrorMessage(conn));
        PQclear(res);
        exit_nicely(conn);
    }
    PQclear(res);

    res = PQexec(conn, "FETCH ALL in myportal");
    if (PQresultStatus(res) != PGRES_TUPLES_OK)
    {
        fprintf(stderr, "FETCH ALL failed: %s", PQerrorMessage(conn));
        PQclear(res);
        exit_nicely(conn);
    }

    /* first, print out the attribute names */
    nFields = PQnfields(res);
    for (i = 0; i < nFields; i++)
        printf("%-15s", PQfname(res, i));
    printf("\n\n");

    /* next, print out the rows */
    for (i = 0; i < PQntuples(res); i++)
    {
        for (j = 0; j < nFields; j++)
            printf("%-15s", PQgetvalue(res, i, j));
        printf("\n");
    }

    PQclear(res);

    /* close the portal ... we don't bother to check for errors ... */
    res = PQexec(conn, "CLOSE myportal");
    PQclear(res);

    /* end the transaction */
    res = PQexec(conn, "END");
    PQclear(res);

    /* close the connection to the database and cleanup */
    PQfinish(conn);

    return 0;
}


И т.д., это уже в доки по слону.

Автор: JackYF 1.3.2008, 19:09
Цитата(SABROG @  1.3.2008,  01:41 Найти цитируемый пост)
Слона собирай и линкуй его к Qt своими силами, плюнь на плагины, как показывает опыт они бажные по самое не балуй.

 smile Как показывает опыт, это происходит под операционными системами, у которых структура динамических библиотек сделана через ж**у. Это я говорю как человек, лично работавший с плагином PostgreSQL под QT под линуксом. И не имевший ни одной проблемы с работой плагина, его линковкой и т.д.

Автор: Любитель 2.3.2008, 00:39
Да всё там как таковое работает нормально. И под виндой, и под линем. Конкретно с постгрисом - под виндой не собирал. Могу попробовать - думаю это возможно, причём без пересборки постгриса. Вообще, его бинарные виндовые дистры разве не через МинГВ собраны?

Автор: SABROG 2.3.2008, 01:47
Ага, настолько нормально, что сам Qt не может быть собран с оптимизацией -O3 и с поддержкой SSE2 без крашей приложений, а QWebKit крашится на ровном месте.
Стили отличные от стандартного windows лагают не по детски на сильной тачке. А при простом движении мышки над контролами Qt приложение в таскбаре при этом жрет 99% процессорного времени. Я понимаю, что ничто не идеально и тот же Delphi глюканутый по самые помидоры, но и плагины баз данных Qt не панацея, куда правильней писать независимый код, особенно, если проекты типа PostgreSQL кроссплатформенные и их можно использовать не только в Qt. Плагины баз данных Qt ограничивают возможность использовать другие функции, которые предоставляет библиотека. Например почти для всех баз данных есть функция экранирования запроса, чтобы избежать SQL Injection, в классе QSqlQuery этой функции нету, хотя и могла бы быть. И приходится писать свои аналоги, несмотря на то, что библиотеки уже имеют эту функцию и распространяются с твоей программой. В итоге имеем программу, где одни и те же функции реализованы по 100 раз только потому, что удобно привести все к одной схеме, под одну гребенку.

Автор: JackYF 2.3.2008, 14:40
Цитата(SABROG @  2.3.2008,  00:47 Найти цитируемый пост)
что сам Qt не может быть собран с оптимизацией -O3 и с поддержкой SSE2 без крашей приложений

Пруфлинк? И вообще, нет - ну и фиг с ним - мало что теряем.

Цитата(SABROG @  2.3.2008,  00:47 Найти цитируемый пост)
А при простом движении мышки над контролами Qt приложение в таскбаре при этом жрет 99% процессорного времени.

Омф, никогда такого не видел.

Цитата(SABROG @  2.3.2008,  00:47 Найти цитируемый пост)
Например почти для всех баз данных есть функция экранирования запроса, чтобы избежать SQL Injection, в классе QSqlQuery этой функции нету, хотя и могла бы быть

Согласен, недостаток. Напиши им в wishlist.
По информации от nickless QSqlQuery::bindValue делает то, что надо.

Автор: nickless 2.3.2008, 18:23
Цитата(SABROG @  1.3.2008,  23:47 Найти цитируемый пост)
Например почти для всех баз данных есть функция экранирования запроса, чтобы избежать SQL Injection, в классе QSqlQuery этой функции нету, хотя и могла бы быть

Даа? smile  А что тогда по-твоему делает http://doc.trolltech.com/4.2/qsqlquery.html#bindValue?

Долго пробовал заинжектить чего-нибудь в базу данных амарок-а, не получилось:
Код

    QSqlQuery query(db);
    query.prepare("SELECT * FROM amazon "
                  "WHERE locale = :loc ;");
    query.bindValue(":loc", "us'; "
                            "INSERT INTO amazon (asin, locale, filename, refetchdate) "
                            "VALUES ('0wn3d0wn3d', 'ru', '1234567890abcdef1234567890abcdef', '1234567890') ; --");
    query.exec();

Пишет -1 rows affected.

Вот так 
Код

    query.prepare("INSERT INTO amazon (asin, locale, filename, refetchdate) "
                    "VALUES (:test, 'ru', '1234567890abcdef1234567890abcdef', '1234567890')");
    query.bindValue(":test", "bla'; SELECT * FROM admin ; --");
    query.exec();

автоматически экранирует '

Даже вот так:
Код

    query.prepare("SELECT * FROM amazon "
                  "WHERE refetchdate = :da ;");
    query.bindValue(":da", "1234567890; "
                            "INSERT INTO amazon (asin, locale, filename, refetchdate) "
                            "VALUES ('0wn3d0wn3d', 'ru', '1234567890abcdef1234567890abcdef', '1111111111') ; --");
    query.exec();
    while (query.next()) {
        QString s = query.value(0).toString();
        qDebug() << s;
    }
    qDebug() << query.lastQuery();
    qDebug() << query.executedQuery();

Выдаёт
Код

"bla'; SELECT * FROM "
"SELECT * FROM amazon WHERE refetchdate = :da ;"
"SELECT * FROM amazon WHERE refetchdate = ? ;"


Цитата(SABROG @  1.3.2008,  23:47 Найти цитируемый пост)
Qt не может быть собран с оптимизацией -O3 и с поддержкой SSE2 без крашей приложений

А зачем использовать агрессивную оптимизацию? С ней вообще половина приложений падает, это и так известно. С -О2 у меня прекрасно работает, правда на винде не пробовал, там еще mingw и сама винда может проблемы создаёт.

Добавлено через 1 минуту и 17 секунд
ЗЫ, база данных = QMYSQL

Автор: LazyVoid 2.3.2008, 23:43
Всем принявшим участие спасибо!

Отдельное спасибо SABROG'у, который навел на решение проблемы.
Проблема была решена самостоятельной сборкой OpenSSL и PostgreSQL, после которых драйвер заработал сам.

P.S. тем не менее решил не юзать кутишные возможности для работы с базой, а делать через стандартные интерфейсы, опять же спасибо (или нет, время покажет ;) ) товарищу SABROG'у
P.P.S. +1 smile еслиб мог

Автор: JackYF 3.3.2008, 15:18
Цитата(LazyVoid @  2.3.2008,  22:43 Найти цитируемый пост)
P.P.S. +1 smile еслиб мог

выполнено.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)