Russian Qt Forum

Qt => Базы данных => Тема начата: GraninDm от Август 29, 2012, 14:55



Название: query.lastError().isValid() не работает
Отправлено: GraninDm от Август 29, 2012, 14:55
Добрый день!

Решил я проверить что будет с программой, если во время ее работы погасить postgresql, с которым она работает.

Код банальный
Код:
query.exec("select ...");
queryError = query.lastError().isValid();
далее проверяется queryError


Запустил программу, погасил сервер, и получил queryError = false
Удивился, и переделал код

Код:
queryError = !query.exec("select ...");
queryError = queryError || query.lastError().isValid();

exec() установил queryError в true, а query.lastError().isValid() вернула false;

Хотя при подключенном сервере query.lastError().isValid() работало.

Я что-то упустил?


Название: Re: query.lastError().isValid() не работает
Отправлено: GraninDm от Сентябрь 03, 2012, 14:54
Решил еще проверить...

qqqwwa = db->isValid();
qqqwwa = db->isOpen();

Вываливается Seg fault то на первой строке, то на второй.

Объясните мне, что я не так делаю?

Qt 4.7.4 32bit WinXP


Название: Re: query.lastError().isValid() не работает
Отправлено: andrew.k от Сентябрь 03, 2012, 15:24
Решил еще проверить...

qqqwwa = db->isValid();
qqqwwa = db->isOpen();

Вываливается Seg fault то на первой строке, то на второй.

Объясните мне, что я не так делаю?
Решил проверить то же самое.
То на первой, то на второй строке Seg fault не вываливается.

Объясните мне, что я не так делаю?


Название: Re: query.lastError().isValid() не работает
Отправлено: GraninDm от Сентябрь 03, 2012, 15:56
Ок.

Нашел http://www.sql.ru/forum/actualthread.aspx?tid=426962 (http://www.sql.ru/forum/actualthread.aspx?tid=426962) вот это
Вот этот момент мне в QT очень не нравится, но увы. При объявлении объекта типа QSqlDatabase в любом месте кроме стека появлется большое количество очень странных глюков.

Объясните, почему нельзя ее создавать в куче?


Название: Re: query.lastError().isValid() не работает
Отправлено: andrew.k от Сентябрь 03, 2012, 15:58
Объясните, почему нельзя ее создавать в куче?
А зачем её создавать в куче?


Название: Re: query.lastError().isValid() не работает
Отправлено: GraninDm от Сентябрь 03, 2012, 16:03
Т.е. вот так в классе нельзя делать?

private:
    QSqlDatabase    *db;


Название: Re: query.lastError().isValid() не работает
Отправлено: andrew.k от Сентябрь 03, 2012, 17:30
Т.е. вот так в классе нельзя делать?

private:
    QSqlDatabase    *db;
еще раз, зачем так делать?
Ты в любой момент можешь получить нужный экземпляр класса QSqlDataBase


Название: Re: query.lastError().isValid() не работает
Отправлено: andrew.k от Сентябрь 03, 2012, 17:35
Нигде в QtSql не используется динамический экземпляр, зачем тебе это нужно?


Название: Re: query.lastError().isValid() не работает
Отправлено: GraninDm от Сентябрь 03, 2012, 21:21
Спасибо, натолкнули на правильный путь.
Понял, что с самого начала неправильно сделал.

Буду переделывать.


Название: Re: query.lastError().isValid() не работает
Отправлено: GraninDm от Сентябрь 04, 2012, 09:40
А по первому сообщению, может кто подскажет, как в моем случае получить код и текст ошибки?

сервер postgres погашен, но подключение к базе было установлено ранее
Код:
        QSqlDatabase db = QSqlDatabase::database();
        qqqwwa = db.isValid();                         qqqwwa = true;
        qqqwwa = db.isOpen();                        qqqwwa = true;  
        QSqlQuery query;
        query...
        queryError = !query.exec();                   queryError = true;
        queryError = query.lastError().isValid();    queryError = false;
        qDebug() <<  query.lastError();              QSqlError(-1, "", "")
        qqqwwa = db.isValid();                         qqqwwa = true;
        qqqwwa = db.isOpen();                         qqqwwa = true;


Посмотрел в исходниках qsqlquery и qsql_psql
Код:
  Note that the last error for this query is reset when exec() is
  called.

bool QSqlQuery::exec(const QString& query)
{
    if (d->ref != 1) {
        bool fo = isForwardOnly();
        *this = QSqlQuery(driver()->createResult());
        d->sqlResult->setNumericalPrecisionPolicy(d->sqlResult->numericalPrecisionPolicy());
        setForwardOnly(fo);
    } else {
        d->sqlResult->clear();
        d->sqlResult->setActive(false);
        d->sqlResult->setLastError(QSqlError());
        d->sqlResult->setAt(QSql::BeforeFirstRow);
        d->sqlResult->setNumericalPrecisionPolicy(d->sqlResult->numericalPrecisionPolicy());
    }
    d->sqlResult->setQuery(query.trimmed());
    if (!driver()->isOpen() || driver()->isOpenError()) {
        qWarning("QSqlQuery::exec: database not open");
        return false;
    }
    if (query.isEmpty()) {
        qWarning("QSqlQuery::exec: empty query");
        return false;
    }
#ifdef QT_DEBUG_SQL
    qDebug("\n QSqlQuery: %s", query.toLocal8Bit().constData());
#endif
    return d->sqlResult->reset(query);
}

bool QPSQLResult::reset (const QString& query)
{
    cleanup();
    if (!driver())
        return false;
    if (!driver()->isOpen() || driver()->isOpenError())
        return false;
    d->result = PQexec(d->driver->connection,
                       d->driver->isUtf8 ? query.toUtf8().constData()
                                         : query.toLocal8Bit().constData());
    return d->processResults();
}


bool QPSQLResultPrivate::processResults()
{
    if (!result)
        return false; Вот тут ошибка не обрабатывается?????

    int status = PQresultStatus(result);
    if (status == PGRES_TUPLES_OK) {
        q->setSelect(true);
        q->setActive(true);
        currentSize = PQntuples(result);
        return true;
    } else if (status == PGRES_COMMAND_OK) {
        q->setSelect(false);
        q->setActive(true);
        currentSize = -1;
        return true;
    }
    q->setLastError(qMakeError(QCoreApplication::translate("QPSQLResult",
                    "Unable to create query"), QSqlError::StatementError, driver));
    return false;
}
Т.е. получается, что проверяется только открыт драйвер и была ли при открытии ошибка
В противном случае ошибка сбрасывается
Так получается?


Название: Re: query.lastError().isValid() не работает
Отправлено: GraninDm от Сентябрь 04, 2012, 12:40
Короче, подправил драйвер psql

Код:
bool QPSQLResultPrivate::processResults()
{
    if (!result){
        q->setLastError(qMakeError(QCoreApplication::translate("QPSQLResult",
                        "Unable to execute query"), QSqlError::StatementError, driver));
       return false;
    }
...

Мой код
Код:
        queryError = !query.exec();
        queryError = query.lastError().isValid();
        qDebug() << queryError;
        qDebug() << query.lastError();

Так работает
Код:
Подключение установлено, сервер работает
false
QSqlError(-1, "", "")
Подключение установлено, сервер не работает
true
QSqlError(-1, "QPSQL: Unable to execute query", "no connection to the server
")

Может я не прав?

Добавил
Оказывается для mysql зарегистрирован bug
https://bugreports.qt-project.org/browse/QTBUG-4926 (https://bugreports.qt-project.org/browse/QTBUG-4926)
Для psql похоже то же самое.


Название: Re: query.lastError().isValid() не работает
Отправлено: fte от Сентябрь 04, 2012, 14:05
А что будет?
query("select 1 where 0!=0")
qDebug() << query.lastError().text();


Название: Re: query.lastError().isValid() не работает
Отправлено: GraninDm от Сентябрь 04, 2012, 14:19
А что будет?
query("select 1 where 0!=0")
qDebug() << query.lastError().text();

Код:
QSqlQuery queryTemp("select 1 where 0!=0");
        qDebug() << queryTemp.lastError().isValid();
        qDebug() << queryTemp.lastError().text();

Драйвер с моими исправлениями

При работающем сервере
false
" "
При неработающем
true
"server closed the connection unexpectedly
   This probably means the server terminated abnormally
   before or while processing the request.

А вот так с родным соответственно
false
" "
false
" "


Название: Re: query.lastError().isValid() не работает
Отправлено: andrew.k от Сентябрь 04, 2012, 14:25
Выложил бы, что исправил в драйвере.
Вдруг кому пригодится.


Название: Re: query.lastError().isValid() не работает
Отправлено: GraninDm от Сентябрь 04, 2012, 14:35
Так я же выложил
Было
Код:
bool QPSQLResultPrivate::processResults()
{
    if (!result)
       return false;
...

Стало
Код:
bool QPSQLResultPrivate::processResults()
{
    if (!result){
        q->setLastError(qMakeError(QCoreApplication::translate("QPSQLResult",
                        "Unable to execute query"), QSqlError::StatementError, driver));
       return false;
    }
...



Название: Re: query.lastError().isValid() не работает
Отправлено: andrew.k от Сентябрь 04, 2012, 14:43
Так я же выложил
извини, забыл просто.