Heart 1.4.918.d927d9c
Heart is base back end library for your c++ Qt projects.
Loading...
Searching...
No Matches
database.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2018-2025 QuasarApp.
3 * Distributed under the lgplv3 software license, see the accompanying
4 * Everyone is permitted to copy and distribute verbatim copies
5 * of this license document, but changing it is not allowed.
6*/
7
8#include "database.h"
9#include "sqldbwriter.h"
10#include "asyncsqldbwriter.h"
11
12#include <quasarapp.h>
13#include <QCoreApplication>
14#include <deleteobject.h>
15#include <QSet>
16#include <itoken.h>
17#include <sqlitedbcache.h>
18#include <sqldb.h>
19#include "getsinglevalue.h"
20#include "setsinglevalue.h"
21#include <qaglobalutils.h>
22
23namespace QH {
24using namespace PKG;
25
26DataBase::DataBase(QObject *ptr): QObject(ptr) {
27 qRegisterMetaType<QSharedPointer<QH::PKG::DBObject>>();
28}
29
30bool DataBase::initSqlDb(QString DBparamsFile,
31 ISqlDB *cache,
32 SqlDBWriter *writer) {
33
34 initDefaultDbObjects(cache, writer);
35
36 QVariantMap params;
37 _db->setSQLSources(SQLSources());
38
39 if (DBparamsFile.isEmpty()) {
40 params = defaultDbParams();
41
42 if (!_db->init(params)) {
43 return false;
44 }
45
46 } else {
47
48 if (!_db->init(DBparamsFile)) {
49 return false;
50 }
51
52 }
53
54 if (!upgradeDataBase()) {
55 qCritical() << "Failed to upgrade database";
56 return false;
57 }
58
59 qDebug() << "Database loaded from: " << dbLocation();
60
61 connect(_db, &ISqlDB::sigItemChanged,
63 Qt::DirectConnection);
64
65 connect(_db, &ISqlDB::sigItemDeleted,
67 Qt::DirectConnection);
68
69 return true;
70}
71
73 return _db;
74}
75
77 if (!isSqlInited() && !initSqlDb()) {
78 return false;
79 }
80 return true;
81}
82
83bool DataBase::run(const QString &localNodeName) {
84
85 if (localNodeName.isEmpty())
86 return false;
87
89
90 if (!isSqlInited() && !initSqlDb()) {
91 return false;
92 }
93
94 return true;
95}
96
98
99 if (db()) {
100 auto writer = _db->writer();
101 _db->softDelete();
102 _db = nullptr;
103 delete writer;
104 }
105}
106
108 stop();
109}
110
112 SqlDBWriter *writer) {
113 if (!writer) {
114 writer = new AsyncSqlDBWriter();
115 }
116
117 if (!cache) {
118 cache = new SqlDB();
119 }
120
121 cache->setWriter(writer);
122 _db = cache;
123}
124
125
127 return true;
128}
129
130QStringList DataBase::SQLSources() const{
131 return {
133 };
134}
135
136QSet<QString> DataBase::systemTables() const {
137 return {"NetworkMembers", "MemberPermisions"};
138}
139
141
142}
143
144void DataBase::objectChanged(const QSharedPointer<DBObject> &) {
145
146}
147
149 return _dbPatches;
150}
151
152void DataBase::addDBPatch(const DBPatch &patch) {
153 debug_assert(patch.isValid(),
154 "Failed to initialise a Data base patch!"
155 " Patch object is invalid");
156
157
158 debug_assert(!_dbPatches[patch.versionFrom].contains(patch.versionTo),
159 "Failed to initialise a Data base patch!");
160
161 _dbPatches[patch.versionFrom][patch.versionTo] = patch;
162
163 _targetDBVersion = std::max(_targetDBVersion, patch.versionTo);
164}
165
166QString DataBase::dbLocation() const {
167 if (db() && db()->writer()) {
168 return db()->writer()->databaseLocation();
169 }
170
171 return "";
172}
173
174QString DataBase::backUp(int version) const {
175 auto&& params = defaultDbParams();
176
177 if (params.value(QH_DB_DRIVER) != "QSQLITE")
178 return {};
179
180 QString&& path = params.value(QH_DB_BACKUP_PATH).toString();
181 if (path.isEmpty()) {
182 return {};
183 }
184
185 auto file = path + "/DBv%0_" + QDateTime::currentDateTimeUtc().toString("hh:mm:ss_dd_MM_yyyy") + ".db";
186 file = file.arg(version);
187 if (db() && db()->writer() &&
188 QFile::exists(db()->writer()->databaseLocation())) {
189
190 QDir().mkpath(path);
191
192 if (!QFile::copy(db()->writer()->databaseLocation(), file)) {
193 return {};
194 }
195 }
196
197 return file;
198}
199
201 return _db;
202}
203
204bool DataBase::isForbidenTable(const QString &table) {
205 return systemTables().contains(table);
206}
207
209 if (!db())
210 return false;
211
212 DBPatchMap patchesPack = dbPatches();
213 if (!patchesPack.size()) {
214 return true;
215 }
216
217 int currentVersion = 0;
218
219 bool fsupportUpgrade = db()->doQuery("SELECT COUNT(*) FROM DataBaseAttributes", {}, true);
220
221 if (!fsupportUpgrade) {
222
223 qCritical() << "The data base of application do not support soft upgrade. "
224 "Please remove database monyaly and restart application."
225 "You can disable upgrade functions for this override the upgradeDataBase method. ";
226 return false;
227 }
228
229 currentVersion = getDBAttribute("version", 0).toInt();
230
231 if (currentVersion < _targetDBVersion)
232 onBeforeDBUpgrade(currentVersion, _targetDBVersion);
233
234 while (currentVersion < _targetDBVersion) {
235
236 QString message;
237 message = "Upgrade data base from %0 to %1 versions. %2";
238 message = message.arg(currentVersion);
239
240 auto patches = patchesPack.value(currentVersion, {});
241
242 if (!patches.size()) {
243 qCritical() << "Failed to " + message.arg("Unknown", "Required patch not found!");
244 return false;
245 }
246
247 auto patch = patches.last();
248 message = message.arg(patch.versionTo);
249
250 qInfo() << message.arg("(Begin)");
251
252 if (!patch.action(db())) {
253 qCritical() << "Failed to " + message.arg("Patch finished with error code!");
254 return false;
255 }
256
257 currentVersion = patch.versionTo;
258 if (!setDBAttribute("version", currentVersion)) {
259 return false;
260 }
261 }
262
263 return true;
264}
265
266void DataBase::onBeforeDBUpgrade(int currentVerion, int ) const {
267 backUp(currentVerion);
268}
269
270const QString &DataBase::localNodeName() const {
271 return _localNodeName;
272}
273
274void DataBase::setLocalNodeName(const QString &newLocalNodeName) {
275 _localNodeName = newLocalNodeName;
276}
277
278QVariantMap DataBase::defaultDbParams() const {
279
280 return {
281 {QH_DB_DRIVER, "QSQLITE"},
282 {QH_DB_FILE_PATH, DEFAULT_DB_PATH + "/" + localNodeName() + "/" + QCoreApplication::applicationName() + "_" + DEFAULT_DB_NAME},
283 {QH_DB_BACKUP_PATH, DEFAULT_DB_PATH + "/" + localNodeName() + "/BackUp"}
284 };
285}
286
287QVariant DataBase::getDBAttribute(const QString& key, const QVariant& defaultVal) {
288 if (!_db)
289 return defaultVal;
290
291 PKG::GetSingleValue request({"DataBaseAttributes", key}, "value", "name");
292
293 if (auto&& responce = _db->getObject(request)) {
294 if (!responce->value().isNull())
295 return responce->value();
296
297 }
298
299 return defaultVal;
300}
301
302bool DataBase::setDBAttribute(const QString& key, const QVariant& newValue) {
303 auto updateVersionRequest = QSharedPointer<PKG::SetSingleValue>::create(
304 DbAddress{"DataBaseAttributes", key},
305 "value", newValue, "name");
306
307 if (!_db->replaceObject(updateVersionRequest, true)) {
308
309 qCritical() << "Failed to update " << key << " attribute";
310 return false;
311 }
312
313 return true;
314}
315
316}
317
The AbstractNodeInfo class contains information about client or server connection and tcp socket of n...
void sigObjectChanged(const QSharedPointer< QH::PKG::DBObject > &obj)
sigItemChanged This signal emitted when database object is changed.
bool isSqlInited() const
isSqlInited This method return true if database initialized successful.
Definition database.cpp:72
void stop()
stop This method stop and diskonnect the database.
Definition database.cpp:97
virtual bool upgradeDataBase()
upgradeDataBase This method upgrade data base to actyaly database version.
Definition database.cpp:208
void setLocalNodeName(const QString &newLocalNodeName)
setLocalNodeName This method sets new local name of database file.
Definition database.cpp:274
DataBase(QObject *ptr=nullptr)
Definition database.cpp:26
bool run()
run This method start and initialize the data base connection.
Definition database.cpp:76
QVariant getDBAttribute(const QString &key, const QVariant &defaultVal)
getDBAttribute This method gets value from the default of QH DB table "DataBaseAttributes".
Definition database.cpp:287
virtual void initDefaultDbObjects(ISqlDB *cache, SqlDBWriter *writer)
initDefaultDbObjects This method create a default cache and database writer objects if the input poin...
Definition database.cpp:111
bool setDBAttribute(const QString &key, const QVariant &newValue)
setDBAttribute This method sets value for the default of QH DB table "DataBaseAttributes".
Definition database.cpp:302
virtual const DBPatchMap dbPatches() const
dbPatches This method should be return map with functions that upgrade production data base....
Definition database.cpp:148
virtual QVariantMap defaultDbParams() const
defaultDbParams This method return default database parameters for this node. Override this method fo...
Definition database.cpp:278
void sigObjectDeleted(const QH::DbAddress &obj)
sigItemDeleted This signal emitted when database object is deleted.
virtual QStringList SQLSources() const
SQLSources This method contains list of sqldatabase sources. This method will be invoked into initial...
Definition database.cpp:130
virtual bool welcomeAddress(AbstractNodeInfo *node)
welcomeAddress This method send to the node information about self. Override this method if you want ...
Definition database.cpp:126
const QString & localNodeName() const
localNodeName This method return local node name.
Definition database.cpp:270
virtual void objectRemoved(const DbAddress &address)
objectRemoved This method invoked when object with address removed from database. Oberride this metho...
Definition database.cpp:140
QString dbLocation() const
dbLocation This method return location of nodes or clients database.
Definition database.cpp:166
void addDBPatch(const DBPatch &patch)
addDBPatch This method add database patch to the data base object.
Definition database.cpp:152
virtual QSet< QString > systemTables() const
systemTables This method return the set of tables that forbidden for users. By default is NetworkMemb...
Definition database.cpp:136
ISqlDB * db() const
db This node return pointer to database object.
Definition database.cpp:200
virtual void objectChanged(const QSharedPointer< PKG::DBObject > &obj)
objectChanged This method invoked when object with address changed in database. Override this method ...
Definition database.cpp:144
virtual void onBeforeDBUpgrade(int currentVerion, int tergetVersion) const
onBeforeDBUpgrade This method will be invoked before upgrade database.
Definition database.cpp:266
QString backUp(int version) const
backUp This method make a backup of database.
Definition database.cpp:174
virtual bool initSqlDb(QString DBparamsFile="", ISqlDB *cache=nullptr, SqlDBWriter *writer=nullptr)
intSqlDb This method initalize database of this node or server.
Definition database.cpp:30
The DbAddress class use to work with database addresses. Database Address it is structure with 2 valu...
Definition dbaddress.h:24
The ISqlDB class it is db cache and bridge for DbWriters. Work Scheme of the database cache:
Definition isqldb.h:73
void setWriter(SqlDBWriter *writer)
setWriter This method set new writer for this cache.
Definition isqldb.cpp:154
SqlDBWriter * writer() const
writer This method return is database writer object. For more inforamation about writer see the SqlDB...
Definition isqldb.cpp:150
bool doQuery(const QString &query, const QVariantMap &bindValues, bool wait=false, QSqlQuery *result=nullptr) const override
doQuery This method execute a query in this database.
Definition isqldb.cpp:247
void sigItemChanged(const QSharedPointer< QH::PKG::DBObject > &obj)
sigItemChanged This signal emitted when database object is changed.
void sigItemDeleted(const QH::DbAddress &obj)
sigItemDeleted This signal emitted when database object is deleted.
The GetSingleValue class is intended for get a single value from database. The value is selected by p...
The SqlDBWriter class. This class write and read objects from database (hard level)....
Definition sqldbwriter.h:36
QString databaseLocation() const
databaseLocation This method return location of database. If it is sqlite then return path to db file...
#define DEFAULT_DB_PATH
Definition config.h:27
#define QH_DB_DRIVER
Definition config.h:32
#define DEFAULT_DB_NAME
Definition config.h:26
#define QH_DB_BACKUP_PATH
Definition config.h:39
#define DEFAULT_DB_INIT_FILE_PATH
Definition config.h:28
#define QH_DB_FILE_PATH
Definition config.h:33
The PKG namesapce - this namespace contains all default packages of the Heart library....
Definition heart.h:211
The QH namespace - QuasarApp Heart namespace. This namespace contains all classes of the Heart librar...
Definition heart.cpp:13
QMap< unsigned short, QMap< unsigned short, DBPatch > > DBPatchMap
DBPatchMap This is 2 depch map of the DBPatch structure when the first key it is version (from) and s...
Definition dbpatch.h:49
DBPatch This is function that should be upgrade database.
Definition dbpatch.h:25
unsigned short versionFrom
Definition dbpatch.h:28
bool isValid() const
isValid This method check this oject to valid.
Definition dbpatch.cpp:12
unsigned short versionTo
Definition dbpatch.h:32