4
1
mirror of https://github.com/QuasarApp/Heart.git synced 2025-05-05 22:19:41 +00:00
2024-12-30 22:44:47 +01:00

399 lines
10 KiB
C++

/*
* Copyright (C) 2018-2025 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 "isqldb.h"
#include "sqldbwriter.h"
#include <dbobject.h>
#include <asyncsqldbwriter.h>
#include <QDateTime>
#include <QtConcurrent/QtConcurrent>
#include <qaglobalutils.h>
namespace QH {
using namespace PKG;
void ISqlDB::globalUpdateDataBase(SqlDBCasheWriteMode mode) {
qint64 currentTime = QDateTime::currentMSecsSinceEpoch();
if (currentTime - lastUpdateTime > updateInterval ||
static_cast<bool>(mode & SqlDBCasheWriteMode::Force)) {
if (static_cast<bool>(mode & SqlDBCasheWriteMode::On_New_Thread)) {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QtConcurrent::run([currentTime, this]() {
globalUpdateDataBasePrivate(currentTime);
});
#else
auto future = QtConcurrent::run([currentTime, this]() {
globalUpdateDataBasePrivate(currentTime);
});
if (!future.isValid()) {
QuasarAppUtils::Params::log("Failde to start update database thread");
}
#endif
} else {
globalUpdateDataBasePrivate(currentTime);
}
}
}
bool ISqlDB::updateObjectP(const QSharedPointer<DBObject> &saveObject,
bool wait) {
if (updateCache(saveObject)) {
if (getMode() == SqlDBCasheWriteMode::Force) {
return _writer && _writer->isValid() &&
_writer->updateObject(saveObject, wait);
}
pushToQueue(saveObject, CacheAction::Update);
globalUpdateDataBase(getMode());
return true;
}
return _writer && _writer->isValid() &&
_writer->updateObject(saveObject, wait);
}
bool ISqlDB::deleteObjectP(const QSharedPointer<DBObject> &delObj,
bool wait) {
deleteFromCache(delObj);
pushToQueue(delObj, CacheAction::Delete);
if (_writer && _writer->isValid()) {
return _writer->deleteObject(delObj, wait);
}
return false;
}
bool ISqlDB::insertObjectP(const QSharedPointer<DBObject> &saveObject,
bool wait,
const QWeakPointer<unsigned int>& autoincrementIdResult) {
if (insertToCache(saveObject)) {
if (getMode() == SqlDBCasheWriteMode::Force) {
return _writer && _writer->isValid() &&
_writer->insertObject(saveObject, wait, autoincrementIdResult);
}
pushToQueue(saveObject, CacheAction::Update);
globalUpdateDataBase(getMode());
return true;
}
return _writer && _writer->isValid() &&
_writer->insertObject(saveObject, wait, autoincrementIdResult);
}
bool ISqlDB::replaceObjectP(const QSharedPointer<PKG::DBObject> &saveObject, bool wait) {
if (updateCache(saveObject)) {
if (getMode() == SqlDBCasheWriteMode::Force) {
return _writer && _writer->isValid() &&
_writer->replaceObject(saveObject, wait);
}
pushToQueue(saveObject, CacheAction::Update);
globalUpdateDataBase(getMode());
return true;
}
return _writer && _writer->isValid() &&
_writer->replaceObject(saveObject, wait);
}
qint64 ISqlDB::getLastUpdateTime() const {
return lastUpdateTime;
}
void ISqlDB::setLastUpdateTime(const qint64 &value) {
lastUpdateTime = value;
}
void ISqlDB::pushToQueue(const QSharedPointer<DBObject> &obj,
CacheAction type) {
_saveLaterMutex.lock();
_changes.insert(type, obj);
_saveLaterMutex.unlock();
}
ISqlDB::ISqlDB(qint64 updateInterval, SqlDBCasheWriteMode mode) {
lastUpdateTime = QDateTime::currentMSecsSinceEpoch();
this->updateInterval = updateInterval;
setMode(mode);
}
ISqlDB::~ISqlDB() {
}
SqlDBWriter *ISqlDB::writer() const {
return _writer;
}
void ISqlDB::setWriter(SqlDBWriter *writer) {
_writer = writer;
}
bool ISqlDB::getAllObjects(const DBObject &templateObject,
QList<QSharedPointer<QH::PKG::DBObject>> &result) {
result = getFromCache(&templateObject);
if(result.size()) {
return true;
}
if (_writer && _writer->isValid()) {
if (!_writer->getAllObjects(templateObject, result)) {
return false;
}
for (const auto &object: std::as_const(result)) {
if (object->isCached() && !insertToCache(object)) {
QuasarAppUtils::Params::log("Selected object from database can not be saved into database cache. " +
object->toString(),
QuasarAppUtils::Warning);
}
}
return true;
}
return false;
}
bool ISqlDB::deleteObject(const QSharedPointer<DBObject> &delObj,
bool wait) {
if (!delObj)
return false;
auto id = delObj->dbAddress();
if (!deleteObjectP(delObj, wait)) {
return false;
}
if (id.isValid())
emit sigItemDeleted(id);
return true;
}
bool ISqlDB::updateObject(const QSharedPointer<DBObject> &saveObject,
bool wait) {
if (!saveObject || !saveObject->isValid()) {
return false;
}
if (!updateObjectP(saveObject, wait)) {
return false;
}
emit sigItemChanged(saveObject);
return true;
}
bool ISqlDB::insertObject(const QSharedPointer<DBObject> &saveObject, bool wait,
const QWeakPointer<unsigned int>& autoincrementIdResult) {
if (!saveObject || !saveObject->isValid()) {
return false;
}
if (!insertObjectP(saveObject, wait, autoincrementIdResult)) {
return false;
}
emit sigItemChanged(saveObject);
return true;
}
bool ISqlDB::replaceObject(const QSharedPointer<PKG::DBObject> &saveObject, bool wait) {
if (!saveObject || !saveObject->isValid()) {
return false;
}
if (!replaceObjectP(saveObject, wait)) {
return false;
}
emit sigItemChanged(saveObject);
return true;
}
bool ISqlDB::doQuery(const QString &query, const QVariantMap& toBind,
bool wait, QSqlQuery *result) const {
if (!_writer) {
return false;
}
return _writer->doQuery(query, toBind, wait, result);
}
bool ISqlDB::doSql(const QString &sqlFile, bool wait) const {
if (!_writer) {
return false;
}
return _writer->doSql(sqlFile, wait);
}
bool ISqlDB::init(const QString &initDbParams) {
if (!_writer) {
return false;
}
return _writer->initDb(initDbParams);
}
bool ISqlDB::init(const QVariantMap &params) {
if (!_writer) {
return false;
}
return _writer->initDb(params);
}
void ISqlDB::setSQLSources(const QStringList &list) {
auto db = writer();
if (db)
db->setSQLSources(list);
}
void ISqlDB::prepareForDelete() {
globalUpdateDataBase(SqlDBCasheWriteMode::Force);
}
bool ISqlDB::changeObjects(const DBObject &templateObject,
const std::function<bool (const QSharedPointer<QH::PKG::DBObject>&)> &changeAction) {
QList<QSharedPointer<DBObject>> list;
if (!getAllObjects(templateObject, list)) {
return false;
}
if (!list.size())
return false;
for (const auto& obj :std::as_const(list)) {
if (!changeAction(obj)) {
return false;
};
if (!updateObject(obj)) {
return false;
};
}
return true;
}
SqlDBCasheWriteMode ISqlDB::getMode() const {
return _mode;
}
void ISqlDB::setMode(const SqlDBCasheWriteMode &mode) {
_mode = mode;
}
void ISqlDB::globalUpdateDataBasePrivate(qint64 currentTime) {
QMutexLocker lock(&_saveLaterMutex);
for (auto it = _changes.begin(); it != _changes.end(); ++it) {
if (writer() && writer()->isValid()) {
auto obj = it.value();
if (!obj || !obj->isValid()) {
deleteFromCache(obj);
QuasarAppUtils::Params::log("writeUpdateItemIntoDB failed when"
" db object is not valid! obj=" +
obj->toString(),
QuasarAppUtils::VerboseLvl::Error);
continue;
}
bool saveResult = false;
switch (it.key()) {
case CacheAction::Insert: {
saveResult = writer()->insertObject(obj, true);
break;
}
case CacheAction::Update: {
saveResult = writer()->updateObject(obj, true);
break;
}
case CacheAction::Delete: {
saveResult = writer()->deleteObject(obj, true);
break;
}
default: {
QuasarAppUtils::Params::log("The Object of the cache have wrong type " +
obj->toString(),
QuasarAppUtils::VerboseLvl::Warning);
continue;
}
}
if (!saveResult ) {
QuasarAppUtils::Params::log("writeUpdateItemIntoDB failed when"
" work globalUpdateDataRelease!!! obj=" +
obj->toString(),
QuasarAppUtils::VerboseLvl::Error);
}
} else {
QuasarAppUtils::Params::log("writeUpdateItemIntoDB failed when"
" db writer is npt inited! ",
QuasarAppUtils::VerboseLvl::Error);
return;
}
}
_changes.clear();
setLastUpdateTime(currentTime);
}
qint64 ISqlDB::getUpdateInterval() const {
return updateInterval;
}
void ISqlDB::setUpdateInterval(const qint64 &value) {
updateInterval = value;
}
}