mirror of
https://github.com/QuasarApp/Heart.git
synced 2025-05-14 10:29:43 +00:00
added db patches functionality
This commit is contained in:
parent
5c4d954a45
commit
e217aadd48
Heart
AbstractSpace
DataBaseSpace
HeartTests/DataBaseSpace
@ -34,6 +34,14 @@ public:
|
||||
*/
|
||||
using Job = std::function<bool()>;
|
||||
|
||||
/**
|
||||
* @brief asyncLauncher This method invoke a job on the thread (using the asyncHandler method) of this object.
|
||||
* @param job This is function with needed job.
|
||||
* @param await This is boolean option for enable or disable wait for finish of the job function.
|
||||
* @return true if the job function started correctly. If the await option is true then
|
||||
* this method return result of job function.
|
||||
*/
|
||||
bool asyncLauncher(const Job &job, bool await = false) const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
@ -66,14 +74,6 @@ protected:
|
||||
*/
|
||||
bool waitFor(const Job &condition, int timeout = WAIT_TIME) const;
|
||||
|
||||
/**
|
||||
* @brief asyncLauncher This method invoke a job on the thread (using the asyncHandler method) of this object.
|
||||
* @param job This is function with needed job.
|
||||
* @param await This is boolean option for enable or disable wait for finish of the job function.
|
||||
* @return true if the job function started correctly. If the await option is true then
|
||||
* this method return result of job function.
|
||||
*/
|
||||
bool asyncLauncher(const Job &job, bool await = false) const;
|
||||
private slots:
|
||||
|
||||
/**
|
||||
|
@ -31,3 +31,11 @@ CREATE TABLE IF NOT EXISTS DefaultPermissions (
|
||||
ON DELETE CASCADE
|
||||
)
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DataBaseAttributes (
|
||||
name TEXT NOT NULL PRIMARY KEY,
|
||||
value INT NOT NULL UNIQUE
|
||||
)
|
||||
|
||||
INSERT INTO "DataBaseAttributes" VALUES ("version", 0);
|
||||
|
||||
|
||||
|
@ -32,3 +32,10 @@ CREATE TABLE IF NOT EXISTS DefaultPermissions (
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS DataBaseAttributes (
|
||||
name TEXT NOT NULL PRIMARY KEY,
|
||||
value INT NOT NULL UNIQUE
|
||||
)
|
||||
|
||||
INSERT INTO "DataBaseAttributes" VALUES ("version", 0);
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include <sqlitedbcache.h>
|
||||
#include <sqldb.h>
|
||||
#include <QCryptographicHash>
|
||||
#include "getsinglevalue.h"
|
||||
#include "setsinglevalue.h"
|
||||
|
||||
#define THIS_NODE "this_node_key"
|
||||
namespace QH {
|
||||
@ -71,6 +73,12 @@ bool DataBaseNode::initSqlDb(QString DBparamsFile,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!upgradeDataBase()) {
|
||||
QuasarAppUtils::Params::log("Failed to upgrade database",
|
||||
QuasarAppUtils::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -180,6 +188,11 @@ void DataBaseNode::objectChanged(const QSharedPointer<DBObject> &) {
|
||||
|
||||
}
|
||||
|
||||
QMap<int, std::function<bool (const iObjectProvider *)> >
|
||||
DataBaseNode::dbPatches() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
void DataBaseNode::handleObjectChanged(const QSharedPointer<DBObject> &item) {
|
||||
notifyObjectChanged(item.staticCast<PKG::ISubscribableData>());
|
||||
objectChanged(item);
|
||||
@ -371,6 +384,60 @@ bool DataBaseNode::isForbidenTable(const QString &table) {
|
||||
return systemTables().contains(table);
|
||||
}
|
||||
|
||||
bool DataBaseNode::upgradeDataBase() {
|
||||
auto patches = dbPatches();
|
||||
int actyalyVersion = patches.cend().key();
|
||||
int currentVersion = 0;
|
||||
|
||||
PKG::GetSingleValue request({"DataBaseAttributes", "name"}, "value");
|
||||
auto responce = _db->getObject(request);
|
||||
if (!responce) {
|
||||
|
||||
QuasarAppUtils::Params::log("The data base of application do not support soft upgrade. "
|
||||
"Please remove database monyaly and restart application.",
|
||||
QuasarAppUtils::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
currentVersion = responce->value().toInt();
|
||||
|
||||
do {
|
||||
currentVersion++;
|
||||
|
||||
auto patch = patches.value(currentVersion);
|
||||
|
||||
QString message;
|
||||
if (currentVersion == 0) {
|
||||
message = "Initialize data base!";
|
||||
} else {
|
||||
message = "Upgrade data base!. from %0 to %1 versions";
|
||||
}
|
||||
|
||||
QuasarAppUtils::Params::log(message,
|
||||
QuasarAppUtils::Info);
|
||||
|
||||
if (!patch(db())) {
|
||||
message = message.arg(currentVersion).arg(currentVersion);
|
||||
QuasarAppUtils::Params::log("Failed to " + message,
|
||||
QuasarAppUtils::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto request = QSharedPointer<PKG::SetSingleValue>::create(
|
||||
DbAddress{"DataBaseAttributes", "name"},
|
||||
"value", currentVersion);
|
||||
|
||||
if (!_db->updateObject(request, true)) {
|
||||
message = message.arg(currentVersion).arg(currentVersion);
|
||||
QuasarAppUtils::Params::log("Failed to update version attribute",
|
||||
QuasarAppUtils::Error);
|
||||
}
|
||||
}
|
||||
while ( currentVersion < actyalyVersion);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DataBaseNode::setLocalNodeName(const QString &newLocalNodeName) {
|
||||
_localNodeName = newLocalNodeName;
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ class SqlDBWriter;
|
||||
class WebSocketController;
|
||||
class DbAddress;
|
||||
class NodeId;
|
||||
class iObjectProvider;
|
||||
|
||||
|
||||
/**
|
||||
@ -395,6 +396,21 @@ protected:
|
||||
*/
|
||||
virtual void objectChanged(const QSharedPointer<PKG::DBObject>& obj);
|
||||
|
||||
/**
|
||||
* @brief dbPatches This method should be return map with functions that upgrade production data base.
|
||||
* Eeach function shoul be can upgrade databae from preview version to own version.
|
||||
* **Example**:
|
||||
*
|
||||
* We have 3 version of data base {0, 1, 2} each version should be contains own function for upgrade data base.
|
||||
*
|
||||
*
|
||||
* @code{cpp}
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
virtual QMap<int, std::function<bool(const iObjectProvider*)>> dbPatches() const;
|
||||
|
||||
private slots:
|
||||
void handleObjectChanged(const QSharedPointer<PKG::DBObject> &item);
|
||||
@ -415,6 +431,13 @@ private:
|
||||
|
||||
bool isForbidenTable(const QString& table);
|
||||
|
||||
/**
|
||||
* @brief upgradeDataBase This method upgrade data base to actyaly database version.
|
||||
* @note The last version of dbPatches is actyaly version.
|
||||
* @return true if operation finished successful
|
||||
*/
|
||||
bool upgradeDataBase();
|
||||
|
||||
ISqlDBCache *_db = nullptr;
|
||||
QString _localNodeName;
|
||||
WebSocketController *_webSocketWorker = nullptr;
|
||||
|
@ -121,6 +121,14 @@ public:
|
||||
bool wait = true);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief doQuery This method execute a @a query in this database.
|
||||
* @param query This is query that will be executed.
|
||||
* @return true if the query finished successful
|
||||
*/
|
||||
virtual bool doQuery(const QString& query, bool wait = false) const = 0;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -214,6 +214,15 @@ bool ISqlDBCache::insertObject(const QSharedPointer<DBObject> &saveObject, bool
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ISqlDBCache::doQuery(const QString &query, bool wait) const {
|
||||
|
||||
if (!_writer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _writer->doQuery(query, wait);
|
||||
}
|
||||
|
||||
bool ISqlDBCache::init(const QString &initDbParams) {
|
||||
|
||||
if (!_writer) {
|
||||
|
@ -107,6 +107,8 @@ public:
|
||||
bool insertObject(const QSharedPointer<QH::PKG::DBObject>& saveObject,
|
||||
bool wait = false) override;
|
||||
|
||||
bool doQuery(const QString &query, bool wait) const override;
|
||||
|
||||
/**
|
||||
* @brief changeObjects This method change object of the database.
|
||||
* @param templateObject This is template for get objects from database.
|
||||
@ -258,6 +260,7 @@ signals:
|
||||
*/
|
||||
void sigItemDeleted(const DbAddress& obj);
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -131,6 +131,22 @@ bool SqlDBWriter::initDbPrivate(const QVariantMap ¶ms) {
|
||||
return initSuccessful;
|
||||
}
|
||||
|
||||
bool SqlDBWriter::doQueryPrivate(const QString &query) const {
|
||||
if (!db()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QSqlQuery q(query, *db());
|
||||
|
||||
if (!q.exec()) {
|
||||
QuasarAppUtils::Params::log("request error : " + q.lastError().text());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool SqlDBWriter::enableFK() {
|
||||
if (!db()) {
|
||||
return false;
|
||||
@ -317,6 +333,17 @@ bool SqlDBWriter::insertQuery(const QSharedPointer<DBObject> &ptr) const {
|
||||
return workWithQuery(q, prepare, cb, ptr->printError());
|
||||
}
|
||||
|
||||
bool SqlDBWriter::doQuery(const QString &query,
|
||||
bool wait) const {
|
||||
|
||||
|
||||
Async::Job job = [this, query]() {
|
||||
return doQueryPrivate(query);
|
||||
};
|
||||
|
||||
return asyncLauncher(job, wait);
|
||||
}
|
||||
|
||||
bool SqlDBWriter::selectQuery(const DBObject& requestObject,
|
||||
QList<QSharedPointer<QH::PKG::DBObject>> &result) {
|
||||
|
||||
|
@ -69,6 +69,7 @@ public:
|
||||
bool deleteObject(const QSharedPointer<PKG::DBObject> &ptr, bool wait = false) override;
|
||||
bool insertObject(const QSharedPointer<PKG::DBObject> &ptr, bool wait = false) override;
|
||||
void setSQLSources(const QStringList &list) override;
|
||||
bool doQuery(const QString& query, bool wait = false) const override;
|
||||
|
||||
/**
|
||||
* @brief databaseLocation This method return location of database.
|
||||
@ -213,6 +214,13 @@ private:
|
||||
*/
|
||||
bool initDbPrivate(const QVariantMap ¶ms);
|
||||
|
||||
/**
|
||||
* @brief doQueryPrivate This method execute a @a query in this database.
|
||||
* @param query This is query that will be executed.
|
||||
* @return true if the query finished successful
|
||||
*/
|
||||
bool doQueryPrivate(const QString& query) const;
|
||||
|
||||
bool initSuccessful = false;
|
||||
QVariantMap _config;
|
||||
QStringList _SQLSources;
|
||||
|
@ -36,8 +36,14 @@ protected:
|
||||
_ping.setAnsver(ping->ansver());
|
||||
}
|
||||
|
||||
QMap<int, std::function<bool (const QH::iObjectProvider *)> > dbPatches() const override{
|
||||
return {};
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
QH::PKG::Ping _ping;
|
||||
|
||||
};
|
||||
|
||||
class BadTstClient: public QH::DataBaseNode {
|
||||
|
Loading…
x
Reference in New Issue
Block a user