diff --git a/lib/db_base.cpp b/lib/db_base.cpp index dfabb260..bce72298 100644 --- a/lib/db_base.cpp +++ b/lib/db_base.cpp @@ -509,6 +509,9 @@ void db_base::updateItem(pki_base *pki, QString name, QString comment) XSqlQuery q; QSqlError e; + Transaction; + TransThrow(); + SQL_PREPARE(q, "UPDATE items SET name=?, comment=? WHERE id=?"); q.bindValue(0, name); q.bindValue(1, comment); @@ -518,6 +521,7 @@ void db_base::updateItem(pki_base *pki, QString name, QString comment) mainwin->dbSqlError(e); if (e.isValid()) return; + TransDone(e); pki->setIntName(name); pki->setComment(comment); diff --git a/lib/db_x509.cpp b/lib/db_x509.cpp index 856eea13..bd393cfe 100644 --- a/lib/db_x509.cpp +++ b/lib/db_x509.cpp @@ -497,6 +497,8 @@ pki_x509 *db_x509::newCert(NewX509 *dlg) subject = req->getSubject(); intname = req->getIntName(); } + TransThrow(); + if (clientkey == NULL) throw errorEx(tr("Invalid public key")); // initially create cert @@ -559,11 +561,6 @@ pki_x509 *db_x509::newCert(NewX509 *dlg) // and finally sign the request cert->sign(signkey, hashAlgo); - if (!TransBegin()) { - delete cert; - throw errorEx("Database trnasaction failed"); - } - // set the comment field cert->setComment(dlg->comment->toPlainText()); cert->pkiSource = dlg->getPkiSource(); @@ -1086,6 +1083,7 @@ void db_x509::caProperties(QModelIndex idx) ui.subjectManager->initCols(sl); sl.clear(); + sl << "*"; foreach(int nid, *MainWindow::dn_nid) sl << QString(OBJ_nid2ln(nid)); ui.subjectManager->setKeys(sl, 0); @@ -1102,7 +1100,10 @@ void db_x509::caProperties(QModelIndex idx) if (l.size() != 2) continue; qDebug() << "Option:" << l[1].toInt(); - polKV << QString(OBJ_nid2ln(OBJ_sn2nid(CCHAR(l[0])))); + if (l[0] == "*") + polKV << "*"; + else + polKV << QString(OBJ_nid2ln(OBJ_sn2nid(CCHAR(l[0])))); polKV << actions[l[1].toInt()]; ui.subjectManager->addRow(polKV); } @@ -1112,6 +1113,9 @@ void db_x509::caProperties(QModelIndex idx) int rows = ui.subjectManager->rowCount(); XSqlQuery q; QSqlError e; + Transaction; + TransThrow(); + templ = ui.temp->currentPkiItem(); tmplId = templ ? templ->getSqlItemId() : QVariant(); @@ -1121,9 +1125,10 @@ void db_x509::caProperties(QModelIndex idx) int idx = actions.indexOf(l[1]); if (idx == -1) continue; - sl << QString("%1:%2") - .arg(OBJ_nid2sn(OBJ_ln2nid(CCHAR(l[0])))) - .arg(idx); + QString first = l[0]; + if (first != "*") + first = OBJ_nid2sn(OBJ_ln2nid(CCHAR(l[0]))); + sl << QString("%1:%2").arg(first).arg(idx); } policy = sl.join(","); cert->setTemplateSqlId(tmplId); @@ -1138,6 +1143,7 @@ void db_x509::caProperties(QModelIndex idx) q.bindValue(2, tmplId); q.bindValue(3, cert->getSqlItemId()); q.exec(); + TransDone(q.lastError()); mainwin->dbSqlError(q.lastError()); } delete dlg; diff --git a/lib/sql.cpp b/lib/sql.cpp index 2d4cd31e..37fd9d70 100644 --- a/lib/sql.cpp +++ b/lib/sql.cpp @@ -54,9 +54,17 @@ bool DbTransaction::finish(const char *oper, const char *file, int line) return true; QSqlDatabase db = QSqlDatabase::database(); - int e = error; - error = 0; - return e ? db.rollback() : db.commit(); + if (error) { + error = 0; + return db.rollback(); + } + XSqlQuery q; + if (db.driverName() == "QPSQL7") + SQL_PREPARE(q, "UPDATE settings SET value = CAST (value AS INTEGER) +1 WHERE key_ = 'counter'"); + else + SQL_PREPARE(q, "UPDATE settings SET value = value +1 WHERE key_ = 'counter'"); + q.exec(); + return db.commit(); } bool DbTransaction::commit(const char *file, int line) @@ -120,10 +128,15 @@ bool XSqlQuery::exec() QString res; setForwardOnly(true); bool r = QSqlQuery::exec(); - if (isSelect()) + if (isSelect()) { res = QString("Rows selected: %1").arg(size()); - else + } else { res = QString("Rows affected: %1").arg(numRowsAffected()); + if (!DbTransaction::active()) { + qCritical("########## MISSING Transaction in %s(%d)", + file, line); + } + } qDebug() << QString("QUERY: %1 - %2").arg(query_details()).arg(res); return r; } diff --git a/lib/sql.h b/lib/sql.h index e067f824..15c1246b 100644 --- a/lib/sql.h +++ b/lib/sql.h @@ -31,10 +31,16 @@ class DbTransaction bool commit(const char *file, int line); bool rollback(const char *file, int line); bool done(QSqlError e, const char *file, int line); + static bool active() + { + return mutex > 0; + } }; #define Transaction DbTransaction __trans #define TransBegin() __trans.begin(__FILE__, __LINE__) +#define TransThrow() if (!__trans.begin(__FILE__, __LINE__)) { \ + throw errorEx(tr("Failed to start a database transaction")); } #define TransCommit() __trans.commit(__FILE__, __LINE__) #define TransRollback() __trans.rollback(__FILE__, __LINE__) #define TransDone(e) __trans.done(e, __FILE__, __LINE__); diff --git a/widgets/MW_database.cpp b/widgets/MW_database.cpp index 1a829b48..acefff12 100644 --- a/widgets/MW_database.cpp +++ b/widgets/MW_database.cpp @@ -25,7 +25,7 @@ QSqlError MainWindow::initSqlDB() { - QStringList schemas[4]; schemas[0] + QStringList schemas[5]; schemas[0] /* The "32bit hash" in public_keys, x509super, requests, certs and crls * is used to quickly find items in the DB by reference. @@ -316,6 +316,11 @@ QSqlError MainWindow::initSqlDB() << "UPDATE settings SET value='4' WHERE key_='schema'" ; + schemas[4] +<< "INSERT INTO settings (key_, value) VALUES ('counter', '1')" +<< "UPDATE settings SET value='5' WHERE key_='schema'" + ; + XSqlQuery q; QSqlDatabase db = QSqlDatabase::database(); QStringList tables;