mirror of
https://github.com/QuasarApp/Heart.git
synced 2025-04-29 03:04:39 +00:00
276 lines
6.7 KiB
C++
276 lines
6.7 KiB
C++
/*
|
|
* Copyright (C) 2018-2023 QuasarApp.
|
|
* Distributed under the lgplv3 software license, see the accompanying
|
|
* Everyone is permitted to copy and distribute verbatim copies
|
|
* of this license document, but changing it is not allowed.
|
|
*/
|
|
|
|
#include "database.h"
|
|
#include "sqldbwriter.h"
|
|
#include "asyncsqldbwriter.h"
|
|
|
|
#include <quasarapp.h>
|
|
#include <QCoreApplication>
|
|
#include <deleteobject.h>
|
|
#include <QSet>
|
|
#include <itoken.h>
|
|
#include <sqlitedbcache.h>
|
|
#include <sqldb.h>
|
|
#include "getsinglevalue.h"
|
|
#include "setsinglevalue.h"
|
|
#include <qaglobalutils.h>
|
|
|
|
namespace QH {
|
|
using namespace PKG;
|
|
|
|
DataBase::DataBase(QObject *ptr): QObject(ptr) {
|
|
qRegisterMetaType<QSharedPointer<QH::PKG::DBObject>>();
|
|
}
|
|
|
|
bool DataBase::initSqlDb(QString DBparamsFile,
|
|
ISqlDB *cache,
|
|
SqlDBWriter *writer) {
|
|
|
|
initDefaultDbObjects(cache, writer);
|
|
|
|
QVariantMap params;
|
|
_db->setSQLSources(SQLSources());
|
|
|
|
if (DBparamsFile.isEmpty()) {
|
|
params = defaultDbParams();
|
|
|
|
if (!_db->init(params)) {
|
|
return false;
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!_db->init(DBparamsFile)) {
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
if (!upgradeDataBase()) {
|
|
QuasarAppUtils::Params::log("Failed to upgrade database",
|
|
QuasarAppUtils::Error);
|
|
return false;
|
|
}
|
|
|
|
QuasarAppUtils::Params::log(QString("Database loaded from: %0").arg(dbLocation()),
|
|
QuasarAppUtils::Debug);
|
|
|
|
connect(_db, &ISqlDB::sigItemChanged,
|
|
this, &DataBase::sigObjectChanged,
|
|
Qt::DirectConnection);
|
|
|
|
connect(_db, &ISqlDB::sigItemDeleted,
|
|
this, &DataBase::sigObjectDeleted,
|
|
Qt::DirectConnection);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool DataBase::isSqlInited() const {
|
|
return _db;
|
|
}
|
|
|
|
bool DataBase::run() {
|
|
if (!isSqlInited() && !initSqlDb()) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool DataBase::run(const QString &localNodeName) {
|
|
|
|
if (localNodeName.isEmpty())
|
|
return false;
|
|
|
|
setLocalNodeName(localNodeName);
|
|
|
|
if (!isSqlInited() && !initSqlDb()) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void DataBase::stop() {
|
|
|
|
if (db()) {
|
|
auto writer = _db->writer();
|
|
_db->softDelete();
|
|
_db = nullptr;
|
|
delete writer;
|
|
}
|
|
}
|
|
|
|
DataBase::~DataBase() {
|
|
stop();
|
|
}
|
|
|
|
void DataBase::initDefaultDbObjects(ISqlDB *cache,
|
|
SqlDBWriter *writer) {
|
|
if (!writer) {
|
|
writer = new AsyncSqlDBWriter();
|
|
}
|
|
|
|
if (!cache) {
|
|
cache = new SqlDB();
|
|
}
|
|
|
|
cache->setWriter(writer);
|
|
_db = cache;
|
|
}
|
|
|
|
|
|
bool DataBase::welcomeAddress(AbstractNodeInfo *) {
|
|
return true;
|
|
}
|
|
|
|
QStringList DataBase::SQLSources() const{
|
|
return {
|
|
DEFAULT_DB_INIT_FILE_PATH
|
|
};
|
|
}
|
|
|
|
QSet<QString> DataBase::systemTables() const {
|
|
return {"NetworkMembers", "MemberPermisions"};
|
|
}
|
|
|
|
void DataBase::objectRemoved(const DbAddress &) {
|
|
|
|
}
|
|
|
|
void DataBase::objectChanged(const QSharedPointer<DBObject> &) {
|
|
|
|
}
|
|
|
|
const DBPatchMap DataBase::dbPatches() const {
|
|
return _dbPatches;
|
|
}
|
|
|
|
void DataBase::addDBPatch(const DBPatch &patch) {
|
|
debug_assert(patch.isValid(),
|
|
"Failed to initialise a Data base patch!"
|
|
" Patch object is invalid");
|
|
|
|
|
|
debug_assert(!_dbPatches[patch.versionFrom].contains(patch.versionTo),
|
|
"Failed to initialise a Data base patch!");
|
|
|
|
_dbPatches[patch.versionFrom][patch.versionTo] = patch;
|
|
|
|
_targetDBVersion = std::max(_targetDBVersion, patch.versionTo);
|
|
}
|
|
|
|
QString DataBase::dbLocation() const {
|
|
if (db() && db()->writer()) {
|
|
return db()->writer()->databaseLocation();
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
ISqlDB *DataBase::db() const {
|
|
return _db;
|
|
}
|
|
|
|
bool DataBase::isForbidenTable(const QString &table) {
|
|
return systemTables().contains(table);
|
|
}
|
|
|
|
bool DataBase::upgradeDataBase() {
|
|
if (!db())
|
|
return false;
|
|
|
|
DBPatchMap patchesPack = dbPatches();
|
|
if (!patchesPack.size()) {
|
|
return true;
|
|
}
|
|
|
|
int currentVersion = 0;
|
|
|
|
bool fsupportUpgrade = db()->doQuery("SELECT COUNT(*) FROM DataBaseAttributes", {}, true);
|
|
|
|
if (!fsupportUpgrade) {
|
|
|
|
QuasarAppUtils::Params::log("The data base of application do not support soft upgrade. "
|
|
"Please remove database monyaly and restart application."
|
|
"You can disable upgrade functions for this override the upgradeDataBase method. ",
|
|
QuasarAppUtils::Error);
|
|
return false;
|
|
}
|
|
|
|
PKG::GetSingleValue request({"DataBaseAttributes", "version"}, "value", "name");
|
|
|
|
if (auto responce = _db->getObject(request)) {
|
|
currentVersion = responce->value().toInt();
|
|
}
|
|
|
|
if (currentVersion < _targetDBVersion)
|
|
onBeforeDBUpgrade(currentVersion, _targetDBVersion);
|
|
|
|
while (currentVersion < _targetDBVersion) {
|
|
|
|
QString message;
|
|
message = "Upgrade data base from %0 to %1 versions. %2";
|
|
message = message.arg(currentVersion);
|
|
|
|
auto patches = patchesPack.value(currentVersion, {});
|
|
|
|
if (!patches.size()) {
|
|
QuasarAppUtils::Params::log("Failed to " + message.arg("Unknown", "Required patch not found!"),
|
|
QuasarAppUtils::Error);
|
|
return false;
|
|
}
|
|
|
|
auto patch = patches.last();
|
|
message = message.arg(patch.versionTo);
|
|
|
|
QuasarAppUtils::Params::log(message.arg("(Begin)"),
|
|
QuasarAppUtils::Info);
|
|
|
|
if (!patch.action(db())) {
|
|
QuasarAppUtils::Params::log("Failed to " + message.arg("Patch finished with error code!"),
|
|
QuasarAppUtils::Error);
|
|
return false;
|
|
}
|
|
|
|
currentVersion = patch.versionTo;
|
|
|
|
auto updateVersionRequest = QSharedPointer<PKG::SetSingleValue>::create(
|
|
DbAddress{"DataBaseAttributes", "version"},
|
|
"value", currentVersion, "name");
|
|
|
|
if (!_db->replaceObject(updateVersionRequest, true)) {
|
|
QuasarAppUtils::Params::log("Failed to update version attribute",
|
|
QuasarAppUtils::Error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void DataBase::onBeforeDBUpgrade(int , int ) const { }
|
|
|
|
const QString &DataBase::localNodeName() const {
|
|
return _localNodeName;
|
|
}
|
|
|
|
void DataBase::setLocalNodeName(const QString &newLocalNodeName) {
|
|
_localNodeName = newLocalNodeName;
|
|
}
|
|
|
|
QVariantMap DataBase::defaultDbParams() const {
|
|
|
|
return {
|
|
{"DBDriver", "QSQLITE"},
|
|
{"DBFilePath", DEFAULT_DB_PATH + "/" + localNodeName() + "/" + localNodeName() + "_" + DEFAULT_DB_NAME},
|
|
};
|
|
}
|
|
}
|
|
|