From 64c9c5ccabc6489e8b3d6c47f27fb71313bae86a Mon Sep 17 00:00:00 2001 From: Christian Hohnstaedt Date: Sun, 18 Mar 2018 16:42:35 +0100 Subject: [PATCH] Add table prefix to be prepended to each table This allows multiple independent xca databases in one database --- lib/sql.cpp | 46 +++++++++++++++++++++++++++++++++---- lib/sql.h | 13 ++++++++++- ui/OpenDb.ui | 15 ++++++++---- widgets/MW_database.cpp | 20 +++++++--------- widgets/OpenDb.cpp | 33 ++++++++++++++++++-------- widgets/OpenDb.h | 1 + widgets/database_schema.cpp | 4 ++++ 7 files changed, 100 insertions(+), 32 deletions(-) diff --git a/lib/sql.cpp b/lib/sql.cpp index 731a68b5..f3535e38 100644 --- a/lib/sql.cpp +++ b/lib/sql.cpp @@ -9,6 +9,7 @@ #include #include "base.h" #include "sql.h" +#include "settings.h" int DbTransaction::mutex; int DbTransaction::error; @@ -99,12 +100,48 @@ bool DbTransaction::done(QSqlError e, const char *file, int line) return e.isValid() ? rollback(file, line) : commit(file, line); } +QString XSqlQuery::table_prefix; + +int XSqlQuery::schemaVersion() +{ + qDebug() << "table_prefix:" << table_prefix;; + return QSqlDatabase::database().tables() + .contains(table_prefix + "settings") ? + Settings["schema"] : 0; +} + +QString XSqlQuery::rewriteQuery(QString _q) +{ + QStringList tables; tables << + "items" << "crls" << "private_keys" << "public_keys" << + "tokens" << "token_mechanism" << "templates" << "certs" << + "authority" << "revocations" << "requests" << "x509super" << + "settings" << "revocations" << + + "view_public_keys" << "view_certs" << "view_requests" << + "view_crls" << "view_templates" << "view_private" ; + + lastq = query = _q; + if (table_prefix.isEmpty()) + return query; + + QString m = tables.join("|") + "|i_" + tables.join("|i_"); + m = QString("\\b(%1)").arg(m); + query = query.replace(QRegExp(m), table_prefix + "\\1"); + + return query; +} QString XSqlQuery::query_details() { QString lq = lastq; QList list = boundValues().values(); QStringList sl; + + if (query != lastq) { + lq = QString("%1 (PREFIX[%2]: %3)").arg(lastq) + .arg(table_prefix).arg(query); + } for (int i = 0; i < list.size(); ++i) sl << list.at(i).toString(); if (sl.size()) @@ -126,15 +163,14 @@ XSqlQuery::XSqlQuery() : QSqlQuery() { } -XSqlQuery::XSqlQuery(QString q) : QSqlQuery(q) +XSqlQuery::XSqlQuery(QString q) : QSqlQuery() { - file = ""; line = 0; - lastq = q; + exec(q); } bool XSqlQuery::exec(QString q) { - lastq = q; + q = rewriteQuery(q); file = ""; line = 0; return QSqlQuery::exec(q); } @@ -159,7 +195,7 @@ bool XSqlQuery::exec() bool XSqlQuery::prepare(QString q) { - lastq = q; + q = rewriteQuery(q); setForwardOnly(true); return QSqlQuery::prepare(q); } diff --git a/lib/sql.h b/lib/sql.h index 19dfaa93..3e26a2f3 100644 --- a/lib/sql.h +++ b/lib/sql.h @@ -56,13 +56,24 @@ class DbTransaction class XSqlQuery: public QSqlQuery { private: - QString lastq; + QString lastq, query; const char *file; int line; + QString rewriteQuery(QString query); + static QString table_prefix; public: XSqlQuery(); XSqlQuery(QString q); + static int schemaVersion(); + static void setTablePrefix(QString p) + { + table_prefix = p; + } + static void clearTablePrefix() + { + table_prefix.clear(); + } QString query_details(); QSqlError lastError(); bool exec(QString q); diff --git a/ui/OpenDb.ui b/ui/OpenDb.ui index 5eb34905..d509d2ee 100644 --- a/ui/OpenDb.ui +++ b/ui/OpenDb.ui @@ -7,12 +7,9 @@ 0 0 441 - 325 + 292 - - Dialog - @@ -149,6 +146,16 @@ + + + + Table prefix + + + + + + diff --git a/widgets/MW_database.cpp b/widgets/MW_database.cpp index e846667e..5a3c3414 100644 --- a/widgets/MW_database.cpp +++ b/widgets/MW_database.cpp @@ -32,24 +32,18 @@ QSqlError MainWindow::initSqlDB() XSqlQuery q; QSqlDatabase db = QSqlDatabase::database(); QStringList tables; - unsigned i = 0; - + unsigned int i; if (!db.isOpen()) return QSqlError(); - tables = db.tables(); - - if (tables.contains("settings")) { - i = Settings["schema"]; - } Transaction; if (!TransBegin()) return db.lastError(); - for (; i < ARRAY_SIZE(schemas); i++) { + for (i = XSqlQuery::schemaVersion(); i < ARRAY_SIZE(schemas); i++) { foreach(QString sql, schemas[i]) { qDebug("EXEC[%d]: '%s'", i, CCHAR(sql)); - if (!q.exec(sql)) { + if (!q.exec(sql) || q.lastError().isValid()) { TransRollback(); return q.lastError(); } @@ -66,13 +60,14 @@ QString MainWindow::openSqlDB(QString dbName) close_database(); opendb->openDatabase(); QSqlError e = initSqlDB(); - qDebug() << "DB-DESC:" << opendb->getDescriptor(); if (e.isValid()) { - dbSqlError(); + dbSqlError(e); + QSqlDatabase::database().close(); dbName = QString(); } else { dbName = opendb->getDescriptor(); } + qDebug() << "DB-DESC:" << opendb->getDescriptor() << dbName << e; } delete opendb; return dbName; @@ -258,7 +253,7 @@ int MainWindow::init_database(QString dbName) } Entropy::seed_rng(); dbName = openSqlDB(dbName); - if (!QSqlDatabase::database().isOpen()) { + if (!QSqlDatabase::database().isOpen() || dbName.isEmpty()) { /* Error already printed */ return 1; } @@ -513,6 +508,7 @@ void MainWindow::close_database() QSqlDatabase::removeDatabase(connName); currentDB.clear(); Settings.clear(); + XSqlQuery::clearTablePrefix(); } void MainWindow::load_history() diff --git a/widgets/OpenDb.cpp b/widgets/OpenDb.cpp index 92fc9b91..e3d0bfc6 100644 --- a/widgets/OpenDb.cpp +++ b/widgets/OpenDb.cpp @@ -15,6 +15,9 @@ #include "PwDialog.h" #include "lib/base.h" +#define NUM_PARAM 6 +#define NUM_PARAM_LEAST 5 + DbMap OpenDb::getDatabases() { QStringList list = QSqlDatabase::drivers(); @@ -46,17 +49,21 @@ bool OpenDb::hasRemoteDrivers() DbMap OpenDb::splitRemoteDbName(QString db) { - static const char * const names[] = - { "all", "user", "host", "type", "dbname" }; + static const char * const names[NUM_PARAM] = + { "all", "user", "host", "type", "dbname", "prefix" }; DbMap map; - QRegExp rx("(.*)@(.*)/(.*):(.*)"); + QRegExp rx("(.*)@(.*)/(.*):([^#]*)#?([^#]*)"); int i, pos = rx.indexIn(db); QStringList list = rx.capturedTexts(); - if (pos != -1 && list.size() == 5) { - for (i=0; i<5; i++) { + if (pos != -1 && list.size() >= NUM_PARAM_LEAST) { + if (list.size() == NUM_PARAM_LEAST) + list[NUM_PARAM_LEAST] = ""; + list[NUM_PARAM_LEAST] = list[NUM_PARAM_LEAST].toLower(); + for (i=0; i < NUM_PARAM; i++) { map[names[i]] = list[i]; } + qDebug() << "SPLIT DB:" << map; } return map; } @@ -64,7 +71,7 @@ DbMap OpenDb::splitRemoteDbName(QString db) bool OpenDb::isRemoteDB(QString db) { DbMap remote_param = splitRemoteDbName(db); - return remote_param.size() == 5; + return remote_param.size() == NUM_PARAM; } OpenDb::OpenDb(QWidget *parent, QString db) @@ -77,11 +84,12 @@ OpenDb::OpenDb(QWidget *parent, QString db) setWindowTitle(XCA_TITLE); remote_param = splitRemoteDbName(db); - if (remote_param.size() == 5) { + if (remote_param.size() == NUM_PARAM) { userName->setText(remote_param["user"]); hostName->setText(remote_param["host"]); dbTypeName = remote_param["type"]; dbName->setText(remote_param["dbname"]); + prefix->setText(remote_param["prefix"]); sqlite = false; show_connection_settings = false; } else if (hasSqLite() && !db.isEmpty()) { @@ -183,26 +191,31 @@ bool OpenDb::_openDatabase(QString connName, QString pass) const db.setPort(hostport[1].toInt()); db.setUserName(userName->text()); db.setPassword(pass); + XSqlQuery::setTablePrefix(prefix->text().toLower()); db.open(); QSqlError e = db.lastError(); if (!e.isValid() || e.type() != QSqlError::ConnectionError || db.isOpen()) return true; - + XSqlQuery::clearTablePrefix(); db.close(); return false; }; QString OpenDb::getDescriptor() const { + QString pref = prefix->text(); + if (!pref.isEmpty()) + pref = QString("#%1").arg(pref.toLower()); return sqlite ? dbName->text() : - QString("%1@%2/%3:%4") + QString("%1@%2/%3:%4%5") .arg(userName->text()) .arg(hostName->text()) .arg(getDbType()) - .arg(dbName->text()); + .arg(dbName->text()) + .arg(pref); } int OpenDb::exec() diff --git a/widgets/OpenDb.h b/widgets/OpenDb.h index 3c11bbd6..6a15f3cc 100644 --- a/widgets/OpenDb.h +++ b/widgets/OpenDb.h @@ -9,6 +9,7 @@ #define __OPENDB_H #include "ui_OpenDb.h" +#include #include typedef QMap DbMap; diff --git a/widgets/database_schema.cpp b/widgets/database_schema.cpp index ff35de87..b687aee9 100644 --- a/widgets/database_schema.cpp +++ b/widgets/database_schema.cpp @@ -294,3 +294,7 @@ << "CREATE INDEX i_items_stamp ON items (stamp)" << "UPDATE settings SET value='5' WHERE key_='schema'" ; + +/* When adding new tables or views, also add them to the list + * in XSqlQuery::rewriteQuery(QString) in lib/sql.cpp + */