xca/lib/sql.cpp
Christian Hohnstaedt d36e6eb0cb Implement nested transactions.
The DbTransaction class automatically rolls back when the scope
is left (destructor) and no commit happenned.

Every transaction begin will increment the counter,
each commit/rollback will decrement it. Only if all transactions
finished with a commit, a final database commit will be performed.
2018-03-05 07:46:10 +01:00

147 lines
2.8 KiB
C++

/* vi: set sw=4 ts=4:
*
* Copyright (C) 2017 Christian Hohnstaedt.
*
* All rights reserved.
*/
#include <QString>
#include <QDebug>
#include "base.h"
#include "sql.h"
int DbTransaction::mutex;
int DbTransaction::error;
void DbTransaction::debug(const char *func, const char *file, int line)
{
QString f = file;
qDebug() << QString("%1(%2) Transaction: %3 Level %4, E:%5 ")
.arg(file + QString(file).lastIndexOf("/") +1)
.arg(line).arg(func).arg(mutex).arg(error);
}
DbTransaction::DbTransaction()
{
has_begun = false;
}
DbTransaction::~DbTransaction()
{
if (has_begun)
rollback("Destructor", 0);
}
bool DbTransaction::begin(const char *file, int line)
{
QSqlDatabase db = QSqlDatabase::database();
if (db.transaction()) {
has_begun = true;
if (mutex++ == 0)
error = 0;
debug("Begin", file, line);
return true;
}
return false;
}
bool DbTransaction::commit(const char *file, int line)
{
if (mutex > 0)
mutex--;
else
qCritical() << "Unbalanced DB Transaction (commit)";
debug("Commit", file, line);
has_begun = false;
if (mutex > 0)
return true;
QSqlDatabase db = QSqlDatabase::database();
return error ? db.rollback() : db.commit();
}
bool DbTransaction::rollback(const char *file, int line)
{
error++;
if (mutex > 0)
mutex--;
else
qCritical() << "Unbalanced DB Transaction (rollback)";
debug("Rollback", file, line);
has_begun = false;
if (mutex > 0)
return true;
QSqlDatabase db = QSqlDatabase::database();
return db.rollback();
}
bool DbTransaction::done(QSqlError e, const char *file, int line)
{
return e.isValid() ? rollback(file, line) : commit(file, line);
}
QString XSqlQuery::query_details()
{
QString lq = lastq;
QList<QVariant> list = boundValues().values();
QStringList sl;
for (int i = 0; i < list.size(); ++i)
sl << list.at(i).toString();
if (sl.size())
lq += QString("[%1]").arg(sl.join(", "));
return QString("%1:%2 (%3)").arg(file).arg(line).arg(lq);
}
QSqlError XSqlQuery::lastError()
{
QSqlError e = QSqlQuery::lastError();
if (!e.isValid())
return e;
QString dt = e.driverText();
e.setDriverText(QString("%1 - %2").arg(dt).arg(query_details()));
return e;
}
XSqlQuery::XSqlQuery() : QSqlQuery()
{
}
XSqlQuery::XSqlQuery(QString q) : QSqlQuery(q)
{
file = ""; line = 0;
lastq = q;
}
bool XSqlQuery::exec(QString q)
{
lastq = q;
file = ""; line = 0;
return QSqlQuery::exec(q);
}
bool XSqlQuery::exec()
{
QString res;
setForwardOnly(true);
bool r = QSqlQuery::exec();
if (isSelect())
res = QString("Rows selected: %1").arg(size());
else
res = QString("Rows affected: %1").arg(numRowsAffected());
qDebug() << QString("QUERY: %1 - %2").arg(query_details()).arg(res);
return r;
}
bool XSqlQuery::prepare(QString q)
{
lastq = q;
setForwardOnly(true);
return QSqlQuery::prepare(q);
}
void XSqlQuery::location(const char *f, int l)
{
file = f + QString(f).lastIndexOf("/") +1;
line = l;
}