rewrite db adapter to use single execute() method

This commit is contained in:
Evgenii Alekseev 2018-12-10 03:09:00 +03:00
parent 57fdb62a5c
commit 62700f65e1
3 changed files with 102 additions and 121 deletions

@ -1 +1 @@
Subproject commit fafc01123d53370f7744596fadd4e77212bc55fa Subproject commit f1247cd01093f90dd57f581a4b0d778bf82020cd

View File

@ -81,6 +81,17 @@ public:
* table name * table name
*/ */
void createTable(const QString &_table); void createTable(const QString &_table);
/**
* @brief execute arbitrary query
* @throw QueuedDatabaseException
* in case if error occurs
* @param _query
* sql query
* @param _params
* sql query parameters
* @return query result
*/
QList<QVariantHash> execute(const QString &_query, const QVariantHash &_params);
/** /**
* @brief get all records from table * @brief get all records from table
* @param _table * @param _table
@ -191,7 +202,7 @@ private:
* table name * table name
* @return last insertion id from table * @return last insertion id from table
*/ */
long long lastInsertionId(const QString &_table) const; long long lastInsertionId(const QString &_table);
/** /**
* @brief additional function to get payload for query * @brief additional function to get payload for query
* @param _table * @param _table

View File

@ -64,10 +64,8 @@ void QueuedDatabase::checkDatabase()
QStringList schemaTables = QueuedDB::DBSchema.keys(); QStringList schemaTables = QueuedDB::DBSchema.keys();
for (auto &table : schemaTables) { for (auto &table : schemaTables) {
// create table if does not exist // create table if does not exist
if (!tables.contains(table)) { if (!tables.contains(table))
qDebug() << table;
createTable(table); createTable(table);
}
// update schema // update schema
createSchema(table); createSchema(table);
} }
@ -90,16 +88,8 @@ void QueuedDatabase::createAdministrator(const QString &_user, const QString &_p
{ {
qCDebug(LOG_LIB) << "Check for user" << _user; qCDebug(LOG_LIB) << "Check for user" << _user;
QSqlQuery query(m_database); auto current = get(QueuedDB::USERS_TABLE, "WHERE name=:username", {{"username", _user}});
query.prepare(QString("SELECT * FROM %1 WHERE name=:username").arg(QueuedDB::USERS_TABLE)); if (!current.isEmpty())
query.bindValue(":username", _user);
query.exec();
QSqlError error = query.lastError();
if (error.isValid())
qCWarning(LOG_LIB) << "Could not get record" << _user << "from" << QueuedDB::USERS_TABLE
<< "message" << error.text();
else if (query.next())
return; return;
qCInfo(LOG_LIB) << "Create administrator user" << _user; qCInfo(LOG_LIB) << "Create administrator user" << _user;
@ -107,7 +97,7 @@ void QueuedDatabase::createAdministrator(const QString &_user, const QString &_p
{"password", _password}, {"password", _password},
{"permissions", static_cast<int>(QueuedEnums::Permission::SuperAdmin)}}; {"permissions", static_cast<int>(QueuedEnums::Permission::SuperAdmin)}};
if (!add(QueuedDB::USERS_TABLE, payload)) if (add(QueuedDB::USERS_TABLE, payload) <= 0)
qCCritical(LOG_LIB) << "Could not create administrator"; qCCritical(LOG_LIB) << "Could not create administrator";
} }
@ -131,17 +121,11 @@ void QueuedDatabase::createSchema(const QString &_table)
if (columns.contains(column)) if (columns.contains(column))
continue; continue;
QueuedDB::QueuedDBField field = QueuedDB::DBSchema[_table][column]; QueuedDB::QueuedDBField field = QueuedDB::DBSchema[_table][column];
QSqlQuery query(m_database); auto queryString = QString("ALTER TABLE %1 ADD `%2` %3")
query.prepare(QString("ALTER TABLE %1 ADD `%2` %3") .arg(_table)
.arg(_table) .arg(column)
.arg(column) .arg(field.sqlDescription);
.arg(field.sqlDescription)); execute(queryString, QVariantHash());
query.exec();
QSqlError error = query.lastError();
if (error.isValid())
qCCritical(LOG_LIB) << "Could not insert column" << column << "to table" << _table
<< "error:" << error.text();
} }
} }
@ -153,37 +137,33 @@ void QueuedDatabase::createTable(const QString &_table)
{ {
qCDebug(LOG_LIB) << "Create table" << _table; qCDebug(LOG_LIB) << "Create table" << _table;
QSqlQuery query(m_database); auto queryString
query.prepare(QString("CREATE TABLE %1 (`_id` INTEGER PRIMARY KEY AUTOINCREMENT)").arg(_table)); = QString("CREATE TABLE %1 (`_id` INTEGER PRIMARY KEY AUTOINCREMENT)").arg(_table);
query.exec(); execute(queryString, QVariantHash());
QSqlError error = query.lastError();
if (error.isValid())
qCCritical(LOG_LIB) << "Could not create table" << _table << "error:" << error.text();
} }
/** /**
* @fn get * @fn execute
*/ */
QList<QVariantHash> QueuedDatabase::get(const QString &_table, const QString &_condition, QList<QVariantHash> QueuedDatabase::execute(const QString &_query, const QVariantHash &_params)
const QVariantHash &_params)
{ {
qCDebug(LOG_LIB) << "Get records in table" << _table; qCDebug(LOG_LIB) << "Execute query" << _query << "with parameters" << _params;
QList<QVariantHash> output; QList<QVariantHash> output;
QSqlQuery query(m_database); QSqlQuery query(m_database);
query.prepare(QString("SELECT * FROM %1 %2 ORDER BY _id ASC").arg(_table).arg(_condition)); query.prepare(_query);
for (auto &key : _params.keys()) for (auto &key : _params.keys())
query.bindValue(QString(":%1").arg(key), _params[key]); query.bindValue(QString(":%1").arg(key), _params[key]);
query.exec(); query.exec();
QSqlError error = query.lastError(); auto error = query.lastError();
if (error.isValid()) { if (error.isValid()) {
qCWarning(LOG_LIB) << "Could not get records from" << _table << "message" << error.text(); qCWarning(LOG_LIB) << "Could not get records using query" << _query << "message"
return output; << error.text();
throw QueuedDatabaseException(error.text());
} }
QSqlRecord record = query.record(); auto record = query.record();
auto columns = getColumnsInRecord(record); auto columns = getColumnsInRecord(record);
while (query.next()) { while (query.next()) {
@ -197,6 +177,24 @@ QList<QVariantHash> QueuedDatabase::get(const QString &_table, const QString &_c
} }
/**
* @fn get
*/
QList<QVariantHash> QueuedDatabase::get(const QString &_table, const QString &_condition,
const QVariantHash &_params)
{
qCDebug(LOG_LIB) << "Get records in table" << _table;
auto queryString = QString("SELECT * FROM %1 %2 ORDER BY _id ASC").arg(_table).arg(_condition);
try {
return execute(queryString, _params);
} catch (QueuedDatabaseException &) {
return QList<QVariantHash>();
}
}
/** /**
* @fn get * @fn get
*/ */
@ -205,14 +203,15 @@ QVariantHash QueuedDatabase::get(const QString &_table, const long long _id)
qCDebug(LOG_LIB) << "Get record" << _id << "in table" << _table; qCDebug(LOG_LIB) << "Get record" << _id << "in table" << _table;
auto output = get(_table, "WHERE _id=:_id", {{"_id", _id}}); auto output = get(_table, "WHERE _id=:_id", {{"_id", _id}});
if (output.count() == 0) { switch (output.count()) {
case 0:
qCWarning(LOG_LIB) << "Could not find records for" << _id; qCWarning(LOG_LIB) << "Could not find records for" << _id;
return QVariantHash(); return QVariantHash();
} else if (output.count() == 1) { case 1:
return output.at(0); return output.first();
} else { default:
qCWarning(LOG_LIB) << "Too many records found for" << _id; qCWarning(LOG_LIB) << "Too many records found for" << _id;
return output.at(0); return output.first();
} }
} }
@ -255,20 +254,14 @@ long long QueuedDatabase::add(const QString &_table, const QVariantHash &_value)
qCDebug(LOG_LIB) << "Add record" << _value << "to table" << _table; qCDebug(LOG_LIB) << "Add record" << _value << "to table" << _table;
auto payload = getQueryPayload(_table, _value); auto payload = getQueryPayload(_table, _value);
// build query auto queryString = QString("INSERT INTO %1 (%2) VALUES (%3)")
QSqlQuery query(m_database); .arg(_table)
query.prepare(QString("INSERT INTO %1 (%2) VALUES (%3)") .arg(payload.keys().join(','))
.arg(_table) .arg(payload.values().join(','));
.arg(payload.keys().join(','))
.arg(payload.values().join(',')));
for (auto &key : _value.keys())
query.bindValue(QString(":%1").arg(key), _value[key]);
query.exec();
QSqlError error = query.lastError(); try {
if (error.isValid()) { execute(queryString, _value);
qCCritical(LOG_LIB) << "Could not add record" << _value << "to table" << _table << "message" } catch (QueuedDatabaseException &) {
<< error.text();
return -1; return -1;
} }
@ -288,18 +281,12 @@ bool QueuedDatabase::modify(const QString &_table, const long long _id, const QV
for (auto &key : payload.keys()) for (auto &key : payload.keys())
stringPayload.append(QString("%1=:%1").arg(key)); stringPayload.append(QString("%1=:%1").arg(key));
// build query // build query
QSqlQuery query(m_database); auto queryString
query.prepare( = QString("UPDATE %1 SET %2 WHERE _id=:_id").arg(_table).arg(stringPayload.join(','));
QString("UPDATE %1 SET %2 WHERE _id=:_id").arg(_table).arg(stringPayload.join(',')));
query.bindValue(":_id", _id);
for (auto &key : _value.keys())
query.bindValue(QString(":%1").arg(key), _value[key]);
query.exec();
QSqlError error = query.lastError(); try {
if (error.isValid()) { execute(queryString, _value);
qCCritical(LOG_LIB) << "Could not modify record" << _value << "in table" << _table } catch (QueuedDatabaseException &) {
<< "message" << error.text();
return false; return false;
} }
@ -314,15 +301,11 @@ bool QueuedDatabase::remove(const QString &_table, const long long _id)
{ {
qCDebug(LOG_LIB) << "Remove row" << _id << "from" << _table; qCDebug(LOG_LIB) << "Remove row" << _id << "from" << _table;
QSqlQuery query(m_database); auto queryString = QString("DELETE FROM %1 WHERE _id=:_id").arg(_table);
query.prepare(QString("DELETE FROM %1 WHERE _id=:_id").arg(_table));
query.bindValue(":_id", _id);
query.exec();
QSqlError error = query.lastError(); try {
if (error.isValid()) { execute(queryString, {{"_id", _id}});
qCCritical(LOG_LIB) << "Could not remove record" << _id << "in table" << _table << "message" } catch (QueuedDatabaseException &) {
<< error.text();
return false; return false;
} }
@ -337,16 +320,13 @@ void QueuedDatabase::removeTasks(const QDateTime &_endTime)
{ {
qCDebug(LOG_LIB) << "Remove all tasks which are older than" << _endTime; qCDebug(LOG_LIB) << "Remove all tasks which are older than" << _endTime;
QSqlQuery query(m_database); auto queryString = QString("DELETE FROM %1 WHERE datetime(endTime) < datetime(:time)")
query.prepare(QString("DELETE FROM %1 WHERE datetime(endTime) < datetime(:time)") .arg(QueuedDB::TASKS_TABLE);
.arg(QueuedDB::TASKS_TABLE));
query.bindValue(":time", _endTime.toString(Qt::ISODateWithMs));
query.exec();
QSqlError error = query.lastError(); try {
if (error.isValid()) execute(queryString, {{"time", _endTime}});
qCCritical(LOG_LIB) << "Could not remove tasks in table" } catch (QueuedDatabaseException &) {
<< "message" << error.text(); }
} }
@ -355,17 +335,14 @@ void QueuedDatabase::removeTasks(const QDateTime &_endTime)
*/ */
void QueuedDatabase::removeTokens() void QueuedDatabase::removeTokens()
{ {
QString now = QDateTime::currentDateTimeUtc().toString(Qt::ISODateWithMs); auto now = QDateTime::currentDateTimeUtc().toString(Qt::ISODateWithMs);
QSqlQuery query(m_database); auto queryString = QString("DELETE FROM %1 WHERE datetime(validUntil) < datetime(:time)")
query.prepare(QString("DELETE FROM %1 WHERE datetime(validUntil) < datetime(:time)") .arg(QueuedDB::TOKENS_TABLE);
.arg(QueuedDB::TOKENS_TABLE));
query.bindValue(":time", now);
query.exec();
QSqlError error = query.lastError(); try {
if (error.isValid()) execute(queryString, {{"time", now}});
qCCritical(LOG_LIB) << "Could not remove tokens in table" } catch (QueuedDatabaseException &) {
<< "message" << error.text(); }
} }
@ -376,16 +353,13 @@ void QueuedDatabase::removeUsers(const QDateTime &_lastLogin)
{ {
qCDebug(LOG_LIB) << "Remove all users which logged older than" << _lastLogin; qCDebug(LOG_LIB) << "Remove all users which logged older than" << _lastLogin;
QSqlQuery query(m_database); auto queryString = QString("DELETE FROM %1 WHERE datetime(lastLogin) < datetime(:time)")
query.prepare(QString("DELETE FROM %1 WHERE datetime(lastLogin) < datetime(:time)") .arg(QueuedDB::USERS_TABLE);
.arg(QueuedDB::USERS_TABLE));
query.bindValue(":time", _lastLogin.toString(Qt::ISODateWithMs));
query.exec();
QSqlError error = query.lastError(); try {
if (error.isValid()) execute(queryString, {{"time", _lastLogin}});
qCCritical(LOG_LIB) << "Could not remove users in table" } catch (QueuedDatabaseException &) {
<< "message" << error.text(); }
} }
@ -407,25 +381,21 @@ QStringList QueuedDatabase::getColumnsInRecord(const QSqlRecord &_record) const
/** /**
* @fn lastInsertionId * @fn lastInsertionId
*/ */
long long QueuedDatabase::lastInsertionId(const QString &_table) const long long QueuedDatabase::lastInsertionId(const QString &_table)
{ {
qCDebug(LOG_LIB) << "Get last row ID from" << _table; qCDebug(LOG_LIB) << "Get last row ID from" << _table;
QSqlQuery query(m_database); QList<QVariantHash> result;
query.prepare(QString("SELECT max(_id) FROM %1").arg(_table)); try {
query.exec(); result = execute(QString("SELECT max(_id) FROM %1").arg(_table), QVariantHash());
} catch (QueuedDatabaseException &) {
QSqlError error = query.lastError();
if (error.isValid()) {
qCCritical(LOG_LIB) << "Could not get last insertion ID";
return -1; return -1;
} }
long long id = -1; if (result.isEmpty())
while (query.next()) return -1;
id = query.value(0).toLongLong();
return id; return result.first()["max(_id)"].toLongLong();
} }
@ -435,7 +405,7 @@ long long QueuedDatabase::lastInsertionId(const QString &_table) const
QHash<QString, QString> QueuedDatabase::getQueryPayload(const QString &_table, QHash<QString, QString> QueuedDatabase::getQueryPayload(const QString &_table,
const QVariantHash &_value) const const QVariantHash &_value) const
{ {
qCDebug(LOG_LIB) << "Add record" << _value << "to table" << _table; qCDebug(LOG_LIB) << "Get payload from" << _value << "to table" << _table;
QHash<QString, QString> output; QHash<QString, QString> output;
auto schemaColumns = QueuedDB::DBSchema[_table].keys(); auto schemaColumns = QueuedDB::DBSchema[_table].keys();