Russian Qt Forum

Qt => Базы данных => Тема начата: -QT- от Апрель 27, 2009, 13:39



Название: SQLite & transaction()
Отправлено: -QT- от Апрель 27, 2009, 13:39
Доброго времени суток !

Использую в программе:
Код
C++ (Qt)
db.transaction();
...
if(!q.exec())
  db.rollbak();
else
  db.commit();
 

В итоге получаю, что db.commit() равно FALSE и
соответственно не закрывается транзакция.
Что это может быть? Это баг в драйвере ?

QT 4.5.0 static


Название: Re: SQLite & transaction()
Отправлено: Rcus от Апрель 27, 2009, 13:42
Цитировать
bool QSqlDatabase::commit ()

Commits a transaction to the database if the driver supports transactions and a transaction() has been started. Returns true if the operation succeeded. Otherwise it returns false.

Note: For some databases, the commit will fail and return false if there is an active query using the database for a SELECT. Make the query inactive before doing the commit.

Call lastError() to get information about errors.


Название: Re: SQLite & transaction()
Отправлено: -QT- от Апрель 27, 2009, 14:08
Простите за назойливость.

А
Цитировать
Make the query inactive before doing the commit.
это нужно сделать так:
q.clear();
Если так то это не отрабатывает.


Название: Re: SQLite & transaction()
Отправлено: spirit от Апрель 27, 2009, 14:14
а так?
Код
C++ (Qt)
...
q = QSqlQuery();
...
 


Название: Re: SQLite & transaction()
Отправлено: -QT- от Апрель 27, 2009, 14:21
а так?
Код
C++ (Qt)
...
q = QSqlQuery();
...
 

так тоже не отрабатывает.


Название: Re: SQLite & transaction()
Отправлено: -QT- от Апрель 27, 2009, 14:36
Заметил что и в другом месте косяк.
Код
C++ (Qt)
QSqlDatabase db_import = QSqlDatabase::database("DBF_IMPORT");
QSqlQuery query(db_import);
query.exec("...")
...
query.clear();
db_import.close();
QSqlDatabase::removeDatabase("DBF_IMPORT");

QSqlDatabasePrivate::removeDatabase: connection 'DBF_IMPORT' is still in use, all queries will cease to work.

но я же все закрыл и очистил.


Название: Re: SQLite & transaction()
Отправлено: -QT- от Апрель 27, 2009, 15:01
Решение для первой части вопроса:
http://www.qtcentre.org/forum/f-qt-programming-2/t-unable-to-commit-transaction-20290.html/?highlight=transaction
Ну и муторно же наф... так делать то ёёёёё.
У мну 4 представления и каждый раз нуно все чистить .... :o
А так Всем спасибо за помощь.


Название: Re: SQLite & transaction()
Отправлено: -QT- от Апрель 27, 2009, 16:42
Заметил что и в другом месте косяк.
Код
C++ (Qt)
QSqlDatabase db_import = QSqlDatabase::database("DBF_IMPORT");
QSqlQuery query(db_import);
query.exec("...")
...
query.clear();
db_import.close();
QSqlDatabase::removeDatabase("DBF_IMPORT");

QSqlDatabasePrivate::removeDatabase: connection 'DBF_IMPORT' is still in use, all queries will cease to work.

но я же все закрыл и очистил.

А вот это видимо баг. Так как removeDatabase работать без вышеуказанного варнинга небудет.
http://lists.trolltech.com/qt-interest/2006-02/thread01434-0.html


Название: Re: SQLite & transaction()
Отправлено: Krow от Октябрь 17, 2009, 11:42
Код:
DB_Tovar = QSqlDatabase::database("tovar");
if (!DB_Tovar.open())
{
QMessageBox::critical(0, qApp->tr("Ошибка"),
             qApp->tr("Не удалось открыть базу данных"), QMessageBox::Cancel);
}
model = new QSqlTableModel(this, DB_Tovar);
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->setTable("tovar");
...
if (!DB_Tovar.open())
{
QMessageBox::critical(0, qApp->tr("Ошибка"),
             qApp->tr("Не удалось открыть базу данных"), QMessageBox::Cancel);
}
if (!model->database().transaction())
QMessageBox::warning(0, "", "Not work transaction");
if (!model->query().exec(tr("UPDATE tovar SET kolvo='0'%1").arg(search)))
QMessageBox::warning(0, "", "Not work query");
if (!model->database().commit())
{
QMessageBox::warning(0, "", "Not work submit");
QMessageBox::warning(0, "", model->database().lastError().text());
}
DB_Tovar.close();
ошибка коммита: database is locked Unable to commit transaction.
не могу понять где косяк...


Название: Re: SQLite & transaction()
Отправлено: break от Октябрь 17, 2009, 21:46
Цитировать
А вот это видимо баг. Так как removeDatabase работать без вышеуказанного варнинга небудет.
это вы видимо не читаете документацию - QSqlDatabase value class и надо ограничить область видимости его - сто раз было на форуме и есть в ассистенте - например

http://www.prog.org.ru/index.php?topic=10014.msg61002#msg61002


по поводу коммита в SQLite - а вообще то SQLite поддерживает работу с транзакциями - я не работал с этой БД - и поддерживает ли работу с транзакциями драйвер QT для SQLite - а то может вы зря мучаетесь?


Название: Re: SQLite & transaction()
Отправлено: Krow от Октябрь 18, 2009, 06:23
насколько помню то поддерживает...
вот я представил кусок кода.. query отрабатывает нормально.. только вот после перезапуска программы изменение внесенные query возвращаются так как было до запроса...


Название: Re: SQLite & transaction()
Отправлено: Kagami от Октябрь 18, 2009, 08:44
Попробуй лучше это:
Цитировать
void QSqlQuery::finish ()


Название: Re: SQLite & transaction()
Отправлено: Krow от Октябрь 18, 2009, 15:58
пасибо. попытаюсь сегодня-завтра.. и отпишусь!


Название: Re: SQLite & transaction()
Отправлено: Krow от Октябрь 19, 2009, 10:59
не помогает.... в пределах модели работает.. и ничего больше.. ( т.е не сохраняет изменения в базу..


Название: Re: SQLite & transaction()
Отправлено: Kagami от Октябрь 19, 2009, 13:25
Может у тебя где-нибудь еще есть активные запросы к базе данных? Нигде не создавал на куче QSqlQuery?


Название: Re: SQLite & transaction()
Отправлено: Krow от Октябрь 19, 2009, 15:20
нет, я специально для того чтобы проверить насколько оно работае. закрывал все открытые БД. переоткрывал нужную БД, и запускал чисто этот кусок кода.. одна фигня.. но ничего... буду мучать код сегодня ночью ещё.. авось найду то место где программист из программиста стал дураком...


Название: Re: SQLite & transaction()
Отправлено: break от Октябрь 19, 2009, 16:49
не мучайся - скинь свой код(рабочий тестовый пример) и болванку базы - мы совместно быстрее разберемся


Название: Re: SQLite & transaction()
Отправлено: Krow от Октябрь 19, 2009, 17:28
в mainWindow добавляется БД.
вот так:
Код:
bool mainWindow::createConnectionTovar()
{
QSqlDatabase db_tovar = QSqlDatabase::addDatabase("QSQLITE", "tovar");
QString file;
if (!flagSklad)
file=tr("bd")+QDir::separator()+dirCount+QDir::separator()+"tovar.db";
else
file=tr("bd")+QDir::separator()+dirCountSklad+QDir::separator()+"tovar.db";
db_tovar.setDatabaseName(file);
}

и чуть ниже приведены основные процедуры в чайлде.
Код:
void fTovCat::showModel()
{
model = new QSqlTableModel(this, DB_Tovar);
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->setTable("tovar");
...
showTovar();
             ...
}

void fTovCat::showTovar()
{
QString filter;
if (firmFilter != "")
filter = firmFilter;
if (searchFilter != "")
if (filter != "")
filter += " AND "+searchFilter;
else
filter = searchFilter;
if (ostatokFilter != "")
if (filter != "")
filter += " AND "+ostatokFilter;
else
filter = ostatokFilter;
model->setFilter(filter);
model->select();
ui.tableView->resizeColumnsToContents();
ui.tableView->resizeRowsToContents();
}
fTovCat::fTovCat()
{
ui.setupUi(this);
...
//Подключаем БД
DB_Tovar = QSqlDatabase::database("tovar");
if (!DB_Tovar.open())
{
QMessageBox::critical(0, qApp->tr("Ошибка"),
      qApp->tr("Не удалось открыть базу данных"), QMessageBox::Cancel);
}

}

void fTovCat::pbNullRecordClicked()
{
/*QStringList listDB = QSqlDatabase::connectionNames();
for (int k=0; k<listDB.count(); k++)
{
QMessageBox::information(0, "", listDB[k]);
}*/
QMessageBox::StandardButton ret;
ret = QMessageBox::warning(this, tr("Предупреждение"),
                      tr("Вы действительно хотите обнулить значения всех записей?"),
  QMessageBox::Yes | QMessageBox::No);
if (ret == QMessageBox::No)
return;
QString search;
if (itemColumn->text(columnItem).trimmed() != "")
{
if (columnItem == 0)
search = "";
else
search = tr(" WHERE firm = '%1'").arg(itemColumn->text(columnItem).trimmed());

/*DB_Tovar.close();
if (!DB_Tovar.open())
{
QMessageBox::critical(0, qApp->tr("Ошибка"),
      qApp->tr("Не удалось открыть базу данных"), QMessageBox::Cancel);
}*/
//if (DB_Tovar.transaction())
//if (!model->database().transaction())
//QMessageBox::warning(0, "", "Not work transaction");
//model->database().transaction();
//model->query().prepare(tr("UPDATE tovar SET kolvo='0'%1").arg(search));
model->query().exec(tr("UPDATE tovar SET kolvo='0'%1").arg(search));
//QMessageBox::warning(0, "", model->);
//QSqlQuery *query = new QSqlQuery(DB_Tovar);
//query->exec(tr("UPDATE tovar SET kolvo='0'%1").arg(search));
//query->finish();
//query->exec(tr("UPDATE tovar SET kolvo='0'%1").arg(search));
model->submitAll();
delete model;
/*DB_Tovar.close();
if (!DB_Tovar.open())
{
QMessageBox::critical(0, qApp->tr("Ошибка"),
      qApp->tr("Не удалось открыть базу данных"), QMessageBox::Cancel);
}*/
showModel();
rbCenaClicked();
QMessageBox::information(0, tr("Информация"), tr("Количество товаров в фирме %1 обнулены!").arg(itemColumn->text(columnItem)));
}
}
в последней процедуре я ппц уже замучался... не знал как поступить.. куча проверок и комментов, за них меня не надо сильно карать.
шаблон создания БД
query->exec("create table tovar (id, code_firm, firm, name, cena_zakup, cena_kr_opt, cena_opt, cena_rozn, percent_kr_opt, percent_opt, precent_rozn, kolvo, prim)");


Название: Re: SQLite & transaction()
Отправлено: break от Октябрь 19, 2009, 18:59
Не знаю что у вас не получается - код некрасивый разбираться не хочется, но я потратил 20 мин - создал SQLite базу с 1 таблицей и маленькое приложение QT кот. изменяет существующие строки - у меня все работает - скидываю вам для теста и сравнения, в конструкторе формы поправьте имя базы - я указал для своенго компьютера полный путь, проект и БД во вложении.


Название: Re: SQLite & transaction()
Отправлено: Krow от Октябрь 20, 2009, 03:25
спасибо. как окончательно проснусь гляну ваш пример..


Название: Re: SQLite & transaction()
Отправлено: break от Октябрь 20, 2009, 04:09
я думаю понял --- так делать нельзя

Цитировать
model->query().exec(tr("UPDATE tovar SET kolvo='0'%1").arg(search));

попробуйте использовать отдельную QSqlQuery для своих целей не трогая query модели - и все заработает
кстати зачем там tr и 0 перед %1


Название: Re: SQLite & transaction()
Отправлено: Krow от Октябрь 20, 2009, 08:43
я пытался использовать и отдельный sql запрос... запрос то проходит, а вот данные не фиксируются в БД.
что на счёт запроса переменная search может быть пустой, а может принимать значение  "WHERE firm = '%1'" где вместо %1 подставляется фирма подлежащая обнулению..


Название: Re: SQLite & transaction()
Отправлено: Krow от Октябрь 20, 2009, 08:55
вот жешь блин.... всего ничего нужно было... перенести строчку
Код:
model = new QSqlTableModel(this, DB_Tovar);
из процедуры showModel в конструктор...
но чувстую что это не последний вопрос мой заданный в этой теме..