crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> QIBASE + транзакции, не возможно выполнить более одного раза
Litkevich Yuriy
  опции профиля:
сообщение 18.3.2010, 20:42
Сообщение #1


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Тут порешал для работы с Firebird'ом воспользоваться драйвером QIBASE, до этого работал через QODBC.
Наткнулся на проблему, более одного раза (!) не могу воспользоваться транзакцией. Выжимка из кода:
model->database().transaction();
model->submitAll();
model->database().commit();
такой код почему-то срабатывает только один раз, если его вызвать повторно, то на model->submitAll() возникает ошибка.
В Qt 4.4.3:
"QSqlError(-901, "Unable to execute query", "Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements")"

В Qt 4.6.0:
"QSqlError(-901, "Unable to execute query", "invalid transaction handle (expecting explicit transaction start)")"

Без транзакций всё работает как в аптеке, а также с транзакциями через QODBC.
Пробовал какую-то не свежую версию QFirebird, которую выкладывал один человек на прогорге, они просто падает на первой же транзакции (model->submitAll())

Может кто-нибудь просветить в чём проблема?

Окружение
Firebird - 2.1.2.18118
Windows 2000 SP4
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 19.3.2010, 13:12
Сообщение #2


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Собрал свежий драйвер QFIREBIRD, транзакция тоже выполняется только один раз. Я уже начинаю подозревать, что я где-то делаю через одно место, но в упор не вижу где. Вот тестовый код:
(вставляет 10 строк)
#include <QCoreApplication>
#include <QSqlTableModel>
#include <QSettings>
#include <QSqlDatabase>
#include <QDebug>
#include <QSqlError>

bool connectToDatabse(QSettings &s)
{
    QSqlDatabase database;
    
    QString key;
    s.beginGroup("Database");
    key = "Driver";
    if (s.contains(key)){
        database = QSqlDatabase::addDatabase(s.value(key).toString());
    }else{
        qDebug() << "Key" << key << "is absent";
        return false;
    }
    key = "DbName";
    if (s.contains(key)){
        database.setDatabaseName(s.value(key).toString());
    }else{
        qDebug() << "Key" << key << "is absent";
        return false;
    }
    key = "UserName";
    if (s.contains(key)){
        database.setUserName(s.value(key).toString());
    }else{
        qDebug() << "Key" << key << "is absent";
        return false;
    }
    key = "UserPassword";
    if (s.contains(key)){
        database.setPassword(s.value(key).toString());
    }else{
        qDebug() << "Key" << key << "is absent";
        return false;
    }
    s.endGroup();


    
    if (!database.open())
    {
        QString qerr = database.lastError().text();
        qDebug() << "Error on open DB, reson:"
                 << qerr;
        return false;
    }
    qDebug() << database;
    return true;
}

//---------------------------------------------------------------------
int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    
    // Читаем настройки БД из INI-файла
    QSettings s("settings.ini", QSettings::IniFormat);
    if (!connectToDatabse(s))
        return 1;
    
    // Информация о таблице
    QString table("entities");
    table = table.toUpper();
    const int columnForInsert = 2;    

    QSqlTableModel *model = new QSqlTableModel();

    model->setTable(table);
    model->setEditStrategy(QSqlTableModel::OnManualSubmit);
    model->select();
    
    const int rowForInsert = 10;
    int cnt = 0;
    
    while (cnt < rowForInsert){
        QString value = QString("testInsert-%1").arg(cnt);
        qDebug() << value;
        cnt++;
        //-- вставляем пустую строку в модель
        int row = model->rowCount();
        if (!model->insertRow(row)){
            qDebug() << "\t" << "Insert to model - ERROR, reson:" << model->lastError();
            return 1;
        }
        //-- вставляем данные в модель
        QModelIndex insertIndex = model->index(row, columnForInsert);
        model->setData(insertIndex, value);
        
        //-- фиксируем данные в БД
        if (model->database().transaction()){
            qDebug() << "\t" << "transaction - START";
        }else{
            qDebug() << "\t" << "transaction -" << model->database().lastError();
        }
        //
        if (model->submitAll()){
            qDebug() << "\t" << "submit - Ok";
        }else{
            qDebug() << "\t" << "submit - " << model->lastError();
        }
        //
        if (model->database().commit()){
            qDebug() << "\t" << "transaction - COMMIT";
        }else{
            qDebug() << "\t" << "transaction -" << model->lastError();
        }
    }
    return 0;
}
Может кто-то ткнёт носом?
Вот вывод:
для QODBC/Qt 4.4.3
QSqlDatabase(driver=""QODBC"", database=""UNITEST"", host="""", port=-1, user=""NNN"", open=true)
"testInsert-0"
         transaction - START
         submit - Ok
         transaction - COMMIT
"testInsert-1"
         transaction - START
         submit - Ok
         transaction - COMMIT
"testInsert-2"
         transaction - START
         submit - Ok
         transaction - COMMIT
"testInsert-3"
         transaction - START
         submit - Ok
         transaction - COMMIT
"testInsert-4"
         transaction - START
         submit - Ok
         transaction - COMMIT
"testInsert-5"
         transaction - START
         submit - Ok
         transaction - COMMIT
"testInsert-6"
         transaction - START
         submit - Ok
         transaction - COMMIT
"testInsert-7"
         transaction - START
         submit - Ok
         transaction - COMMIT
"testInsert-8"
         transaction - START
         submit - Ok
         transaction - COMMIT
"testInsert-9"
         transaction - START
         submit - Ok
         transaction - COMMIT

D:\tempData\Qt-test-18>
реально вставляются в БД все 10 записей
для QIBASE/Qt 4.4.3
D:\tempData\Qt-test-18>ee.d
QSqlDatabase(driver=""QIBASE"", database=""L:/Repository/universalDB/db/UNIVERSALDB_1_test.FDB"", host="""", port=-1, user=""NNN"", open=true)
"testInsert-0"
         transaction - START
         submit - Ok
         transaction - COMMIT
"testInsert-1"
         transaction - START
         submit -  QSqlError(-901, "Unable to execute query", "Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements")
         transaction - COMMIT
"testInsert-2"
         transaction - START
         submit -  QSqlError(-901, "Unable to execute query", "Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements")
         transaction - COMMIT
"testInsert-3"
         transaction - START
         submit -  QSqlError(-901, "Unable to execute query", "Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements")
         transaction - COMMIT
"testInsert-4"
         transaction - START
         submit -  QSqlError(-901, "Unable to execute query", "Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements")
         transaction - COMMIT
"testInsert-5"
         transaction - START
         submit -  QSqlError(-901, "Unable to execute query", "Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements")
         transaction - COMMIT
"testInsert-6"
         transaction - START
         submit -  QSqlError(-901, "Unable to execute query", "Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements")
         transaction - COMMIT
"testInsert-7"
         transaction - START
         submit -  QSqlError(-901, "Unable to execute query", "Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements")
         transaction - COMMIT
"testInsert-8"
         transaction - START
         submit -  QSqlError(-901, "Unable to execute query", "Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements")
         transaction - COMMIT
"testInsert-9"
         transaction - START
         submit -  QSqlError(-901, "Unable to execute query", "Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements")
         transaction - COMMIT
QSqlDatabasePrivate::removeDatabase: connection 'qt_sql_default_connection' is still in use, all queries will cease to work.

D:\tempData\Qt-test-18>
реально вставляется в БД толкько 1 запись
для qtfirebirdibppsqldriver trunk@9
QSqlDatabase(driver=""QFIREBIRD"", database=""L:/Repository/universalDB/db/UNIVERSALDB_1_test.FDB"", host="""", port=-1, user=""NNN"", open=true)
"testInsert-0"
         transaction - START
         submit - Ok
         transaction - COMMIT
"testInsert-1"
         transaction - START
*** IBPP::LogicException ***
Context: Statement::Execute
Message: No statement has been prepared.


         submit -  QSqlError(-1, "Unable execute statement", "*** IBPP::LogicException ***
Context: Statement::Execute
Message: No statement has been prepared.

")
         transaction - COMMIT
"testInsert-2"
         transaction - START
*** IBPP::LogicException ***
Context: Statement::Execute
Message: No statement has been prepared.


         submit -  QSqlError(-1, "Unable execute statement", "*** IBPP::LogicException ***
Context: Statement::Execute
Message: No statement has been prepared.

")
         transaction - COMMIT
"testInsert-3"
         transaction - START
*** IBPP::LogicException ***
Context: Statement::Execute
Message: No statement has been prepared.


         submit -  QSqlError(-1, "Unable execute statement", "*** IBPP::LogicException ***
Context: Statement::Execute
Message: No statement has been prepared.

")
         transaction - COMMIT
"testInsert-4"
         transaction - START
*** IBPP::LogicException ***
Context: Statement::Execute
Message: No statement has been prepared.


         submit -  QSqlError(-1, "Unable execute statement", "*** IBPP::LogicException ***
Context: Statement::Execute
Message: No statement has been prepared.

")
         transaction - COMMIT
"testInsert-5"
         transaction - START
*** IBPP::LogicException ***
Context: Statement::Execute
Message: No statement has been prepared.


         submit -  QSqlError(-1, "Unable execute statement", "*** IBPP::LogicException ***
Context: Statement::Execute
Message: No statement has been prepared.

")
         transaction - COMMIT
"testInsert-6"
         transaction - START
*** IBPP::LogicException ***
Context: Statement::Execute
Message: No statement has been prepared.


         submit -  QSqlError(-1, "Unable execute statement", "*** IBPP::LogicException ***
Context: Statement::Execute
Message: No statement has been prepared.

")
         transaction - COMMIT
"testInsert-7"
         transaction - START
*** IBPP::LogicException ***
Context: Statement::Execute
Message: No statement has been prepared.


         submit -  QSqlError(-1, "Unable execute statement", "*** IBPP::LogicException ***
Context: Statement::Execute
Message: No statement has been prepared.

")
         transaction - COMMIT
"testInsert-8"
         transaction - START
*** IBPP::LogicException ***
Context: Statement::Execute
Message: No statement has been prepared.


         submit -  QSqlError(-1, "Unable execute statement", "*** IBPP::LogicException ***
Context: Statement::Execute
Message: No statement has been prepared.

")
         transaction - COMMIT
"testInsert-9"
         transaction - START
*** IBPP::LogicException ***
Context: Statement::Execute
Message: No statement has been prepared.


         submit -  QSqlError(-1, "Unable execute statement", "*** IBPP::LogicException ***
Context: Statement::Execute
Message: No statement has been prepared.

")
         transaction - COMMIT
QSqlDatabasePrivate::removeDatabase: connection 'qt_sql_default_connection' is still in use, all queries will cease to work.

D:\tempData\Qt-test-18>

реально вставляется в БД толкько 1 запись
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 21.3.2010, 0:52
Сообщение #3


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Продолжаю раскопки проблемы.
--1--
Заменил QSqlTableModel, на простой QSqlQuery. Все работает в любом окружении, при любой версии Qt для компиляции. Стало быть проблема именно с QSqlTableModel + Драйвер Interbse/Firebird

--2--
сегодня наткнулся на странную ситуацию.
Поставил на свой нетбук, с Вин ХП домашней, Qt SDK 2010.02 (Qt 4.6.2), запустил эту тестовую прогу уже скомпиленную с помощью Qt 4.4.3
И она работает! т.е. все десять транзакций выполняются.
Я обрадовался, скомпилил, в консоли, ту прогу в окружении Qt 4.6.2.
И она опять НЕ работает!

Этого я вообще не понял.

П.С. обновил первое сообщение, добавив полное описание окружения.

--3--
Засунув в драйвер QIBASE кучу отладки, на сегодня, выяснил только одну вещь:
Старт транзакции происходит всякий раз, с новым номером транзакции. Но, почему-то сама запись в базу (второй и последующие разы) происходит с номером транзакции, который был у первой транзакции
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 27.3.2010, 1:41
Сообщение #4


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(Litkevich Yuriy @ 19.3.2010, 16:12) *
для qtfirebirdibppsqldriver trunk@9
пробовал и с последней версией, исключений уже нет, ошибки как и при QIBASE
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
mishabard
  опции профиля:
сообщение 4.7.2011, 17:55
Сообщение #5


Студент
*

Группа: Участник
Сообщений: 31
Регистрация: 13.6.2011
Из: Киев
Пользователь №: 2741

Спасибо сказали: 0 раз(а)




Репутация:   0  


Здравствуйте! Решил не создавать новую тему! Вы занимались ей год назад.
Столкнулся с той же проблемой. При удалении строки из базы данных, дает выполнить только одну транзакцию. после этого приходится только полностью делать disconect к базе, чтоб еще одну транзакцию выполнить.
У меня ubuntu 11.4 QT 4.7 Firebird 2.1 использую стандартный драйвер IBASE.
Скажите Вы нашли решение? Дело в том что если использовать QSqlQuery, то все работает, можно делать неограниченное количестов транзакций. а если использовать QSQLTableModel - то выполняет только одну транзацию и пишет
invalid transaction handle (expecting explicit transaction start) Unable to execute query. Вот код удаления строки(упрощенный):
QSqlTableModel * kassaModel;
QModelIndex index = kassaView->currentIndex();

if (!index.isValid())
return;
if (!db.transaction())
qDebug()<<db.lastError().text();

if (!kassaModel->removeRow(index.row()))
qDebug()<<" "+kassaModel->lastError().text();
invalid transaction handle (expecting explicit transaction start) Unable to execute query
kassaModel->submitAll()

db.commit()

kassaModel->select();
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 4.7.2011, 19:43
Сообщение #6


Мастер
******

Группа: Модератор
Сообщений: 3296
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


1. Нужно разбираться с моделью, почему при удалении происходит ошибка.
2. Если происходит ошибка нужно делать не commit, а rollback!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 4.7.2011, 19:55
Сообщение #7


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(mishabard @ 4.7.2011, 20:55) *
Скажите Вы нашли решение?
нет.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
mishabard
  опции профиля:
сообщение 6.7.2011, 15:12
Сообщение #8


Студент
*

Группа: Участник
Сообщений: 31
Регистрация: 13.6.2011
Из: Киев
Пользователь №: 2741

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(Litkevich Yuriy @ 4.7.2011, 19:55) *
Цитата(mishabard @ 4.7.2011, 20:55) *
Скажите Вы нашли решение?
нет.

Спасибо!
Пока вышел из положения следующим образом: использую QSQLQuery не связанный с моделью TableView, Открываю транзакцию, выполняю запрос на удаление. закрываю транзакцию. после чего обновляю TableView. Может каряво и просто, но надежно работает.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lvlad
  опции профиля:
сообщение 18.6.2012, 14:35
Сообщение #9


Новичок


Группа: Новичок
Сообщений: 1
Регистрация: 18.6.2012
Пользователь №: 3427

Спасибо сказали: 0 раз(а)




Репутация:   0  


чтобы исправить проблему необходимо в файле qsqltablemodel.cpp
в методе QSqlTableModelPrivate::exec закомментировать строку:
if (editQuery.driver() != db.driver())


bool QSqlTableModelPrivate::exec(const QString &stmt, bool prepStatement,
const QSqlRecord &rec, const QSqlRecord &whereValues)
{
if (stmt.isEmpty())
return false;

// lazy initialization of editQuery
//-->> if (editQuery.driver() != db.driver()) <<--
editQuery = QSqlQuery(db);


После этого придется перекомпировать Qt или модуль QtSql
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 28.11.2024, 3:13