From b698f200d91e4aa24433a928ad6cbd63fcef960f Mon Sep 17 00:00:00 2001 From: EndrII Date: Tue, 7 Nov 2023 21:07:29 +0100 Subject: [PATCH 1/3] added support of the autoincerement fields of db --- src/public/database.h | 23 +++++++++++++++++++++ src/public/iobjectprovider.h | 8 ++++++-- src/public/isqldb.cpp | 40 +++++++++++++++++++----------------- src/public/isqldb.h | 16 ++++++++------- src/public/sqldbwriter.cpp | 36 ++++++++++++++++++++++++-------- src/public/sqldbwriter.h | 8 ++++++-- 6 files changed, 92 insertions(+), 39 deletions(-) diff --git a/src/public/database.h b/src/public/database.h index 1af787d9..935c48f1 100644 --- a/src/public/database.h +++ b/src/public/database.h @@ -402,6 +402,29 @@ class HEARTSHARED_EXPORT DataBase: public QObject return false; }; + /** + * @brief insert a new value into database, and save into @a resultId autoincremented id of inserted object. + * + * @tparam Object The type of object to save. + * @param obj The object to save. + * @return true if the object is successfully saved, false otherwise. + * + * Example: + * + * @code{cpp} + * auto&& id = QSharedPointe:: create(); + insertObj(role.dynamicCast(), id.toWeekRef()); + * @endcode + */ + template + bool insertObj(const Object& obj, const QWeakPointer& resultId = {}) { + if (auto&& database = db()) { + return database->insertObject(obj, resultId.isNull(), resultId); + } + + return false; + }; + /** * @brief Get a list of all objects from a specified table. * diff --git a/src/public/iobjectprovider.h b/src/public/iobjectprovider.h index 4416eed9..37bb9b52 100644 --- a/src/public/iobjectprovider.h +++ b/src/public/iobjectprovider.h @@ -98,9 +98,13 @@ class HEARTSHARED_EXPORT iObjectProvider * @note This method insert object into database only. IF object is exits in the database then this method return false. * @param saveObject This is object for inserting. * @param wait This arguments force current thread wait for the function finishing. - * @return true if objects is saved successful else false. + * @param autoincrementIdResult is id of the insert query to the Table with autoincrement id field. + * @return true if objects is saved successful else false. Note return two value. First is boolean result, second is id of inserted value. + * @note id will be returned only for the autoincement records. */ - virtual bool insertObject(const QSharedPointer& saveObject, bool wait) = 0; + virtual bool insertObject(const QSharedPointer& saveObject, + bool wait, + const QWeakPointer& autoincrementIdResult) = 0; /** * @brief deleteObject This method execute a delete method of obj and remove current object from database. diff --git a/src/public/isqldb.cpp b/src/public/isqldb.cpp index ec5e87f1..7cb31144 100644 --- a/src/public/isqldb.cpp +++ b/src/public/isqldb.cpp @@ -23,7 +23,7 @@ void ISqlDB::globalUpdateDataBase(SqlDBCasheWriteMode mode) { qint64 currentTime = QDateTime::currentMSecsSinceEpoch(); if (currentTime - lastUpdateTime > updateInterval || - static_cast(mode & SqlDBCasheWriteMode::Force)) { + static_cast(mode & SqlDBCasheWriteMode::Force)) { if (static_cast(mode & SqlDBCasheWriteMode::On_New_Thread)) { @@ -48,13 +48,13 @@ void ISqlDB::globalUpdateDataBase(SqlDBCasheWriteMode mode) { } bool ISqlDB::updateObjectP(const QSharedPointer &saveObject, - bool wait) { + bool wait) { if (updateCache(saveObject)) { if (getMode() == SqlDBCasheWriteMode::Force) { return _writer && _writer->isValid() && - _writer->updateObject(saveObject, wait); + _writer->updateObject(saveObject, wait); } pushToQueue(saveObject, CacheAction::Update); @@ -64,11 +64,11 @@ bool ISqlDB::updateObjectP(const QSharedPointer &saveObject, } return _writer && _writer->isValid() && - _writer->updateObject(saveObject, wait); + _writer->updateObject(saveObject, wait); } bool ISqlDB::deleteObjectP(const QSharedPointer &delObj, - bool wait) { + bool wait) { deleteFromCache(delObj); pushToQueue(delObj, CacheAction::Delete); @@ -81,14 +81,15 @@ bool ISqlDB::deleteObjectP(const QSharedPointer &delObj, } bool ISqlDB::insertObjectP(const QSharedPointer &saveObject, - bool wait) { + bool wait, + const QWeakPointer& autoincrementIdResult) { if (insertToCache(saveObject)) { if (getMode() == SqlDBCasheWriteMode::Force) { return _writer && _writer->isValid() && - _writer->insertObject(saveObject, wait); + _writer->insertObject(saveObject, wait, autoincrementIdResult); } pushToQueue(saveObject, CacheAction::Update); @@ -98,7 +99,7 @@ bool ISqlDB::insertObjectP(const QSharedPointer &saveObject, } return _writer && _writer->isValid() && - _writer->insertObject(saveObject, wait); + _writer->insertObject(saveObject, wait, autoincrementIdResult); } bool ISqlDB::replaceObjectP(const QSharedPointer &saveObject, bool wait) { @@ -129,7 +130,7 @@ void ISqlDB::setLastUpdateTime(const qint64 &value) { } void ISqlDB::pushToQueue(const QSharedPointer &obj, - CacheAction type) { + CacheAction type) { _saveLaterMutex.lock(); _changes.insert(type, obj); _saveLaterMutex.unlock(); @@ -155,7 +156,7 @@ void ISqlDB::setWriter(SqlDBWriter *writer) { } bool ISqlDB::getAllObjects(const DBObject &templateObject, - QList> &result) { + QList> &result) { result = getFromCache(&templateObject); if(result.size()) { @@ -170,7 +171,7 @@ bool ISqlDB::getAllObjects(const DBObject &templateObject, 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(), + object->toString(), QuasarAppUtils::Warning); } } @@ -182,7 +183,7 @@ bool ISqlDB::getAllObjects(const DBObject &templateObject, } bool ISqlDB::deleteObject(const QSharedPointer &delObj, - bool wait) { + bool wait) { if (!delObj) return false; @@ -201,7 +202,7 @@ bool ISqlDB::deleteObject(const QSharedPointer &delObj, } bool ISqlDB::updateObject(const QSharedPointer &saveObject, - bool wait) { + bool wait) { if (!saveObject || !saveObject->isValid()) { return false; @@ -216,12 +217,13 @@ bool ISqlDB::updateObject(const QSharedPointer &saveObject, return true; } -bool ISqlDB::insertObject(const QSharedPointer &saveObject, bool wait) { +bool ISqlDB::insertObject(const QSharedPointer &saveObject, bool wait, + const QWeakPointer& autoincrementIdResult) { if (!saveObject || !saveObject->isValid()) { return false; } - if (!insertObjectP(saveObject, wait)) { + if (!insertObjectP(saveObject, wait, autoincrementIdResult)) { return false; } @@ -291,7 +293,7 @@ void ISqlDB::prepareForDelete() { } bool ISqlDB::changeObjects(const DBObject &templateObject, - const std::function&)> &changeAction) { + const std::function&)> &changeAction) { QList> list; if (!getAllObjects(templateObject, list)) { @@ -337,7 +339,7 @@ void ISqlDB::globalUpdateDataBasePrivate(qint64 currentTime) { QuasarAppUtils::Params::log("writeUpdateItemIntoDB failed when" " db object is not valid! obj=" + - obj->toString(), + obj->toString(), QuasarAppUtils::VerboseLvl::Error); continue; } @@ -359,7 +361,7 @@ void ISqlDB::globalUpdateDataBasePrivate(qint64 currentTime) { } default: { QuasarAppUtils::Params::log("The Object of the cache have wrong type " + - obj->toString(), + obj->toString(), QuasarAppUtils::VerboseLvl::Warning); continue; @@ -369,7 +371,7 @@ void ISqlDB::globalUpdateDataBasePrivate(qint64 currentTime) { if (!saveResult ) { QuasarAppUtils::Params::log("writeUpdateItemIntoDB failed when" " work globalUpdateDataRelease!!! obj=" + - obj->toString(), + obj->toString(), QuasarAppUtils::VerboseLvl::Error); } } else { diff --git a/src/public/isqldb.h b/src/public/isqldb.h index ea41ad96..bc168a57 100644 --- a/src/public/isqldb.h +++ b/src/public/isqldb.h @@ -80,7 +80,7 @@ class HEARTSHARED_EXPORT ISqlDB: public QObject, public iObjectProvider, public * @param mode See the SqlDBCache::setMode method for more information. */ ISqlDB(qint64 updateInterval = DEFAULT_UPDATE_INTERVAL, - SqlDBCasheWriteMode mode = SqlDBCasheWriteMode::Default); + SqlDBCasheWriteMode mode = SqlDBCasheWriteMode::Default); ~ISqlDB() override; /** @@ -103,10 +103,11 @@ class HEARTSHARED_EXPORT ISqlDB: public QObject, public iObjectProvider, public bool deleteObject(const QSharedPointer& delObj, bool wait = false) override; bool insertObject(const QSharedPointer& saveObject, - bool wait = false) override; + bool wait = false, + const QWeakPointer& autoincrementIdResult = {}) override; bool replaceObject(const QSharedPointer& saveObject, - bool wait = false) override; + bool wait = false) override; bool doQuery(const QString &query, const QVariantMap& bindValues, bool wait = false, QSqlQuery* result = nullptr) const override; @@ -231,13 +232,14 @@ class HEARTSHARED_EXPORT ISqlDB: public QObject, public iObjectProvider, public private: bool updateObjectP(const QSharedPointer& saveObject, - bool wait = false); + bool wait = false); bool deleteObjectP(const QSharedPointer& delObj, - bool wait = false); + bool wait = false); bool insertObjectP(const QSharedPointer& saveObject, - bool wait = false); + bool wait, + const QWeakPointer& autoincrementIdResult); bool replaceObjectP(const QSharedPointer& saveObject, - bool wait = false); + bool wait = false); qint64 lastUpdateTime = 0; qint64 updateInterval = DEFAULT_UPDATE_INTERVAL; diff --git a/src/public/sqldbwriter.cpp b/src/public/sqldbwriter.cpp index 90552630..7967ec28 100644 --- a/src/public/sqldbwriter.cpp +++ b/src/public/sqldbwriter.cpp @@ -77,7 +77,7 @@ bool SqlDBWriter::initDbPrivate(const QVariantMap ¶ms) { delete _db; _db = new QSqlDatabase(initSqlDataBasse(_config["DBDriver"].toString(), - _config["DBFilePath"].toString())); + _config["DBFilePath"].toString())); if (_config.contains("DBFilePath")) { @@ -311,14 +311,24 @@ bool SqlDBWriter::deleteObject(const QSharedPointer &ptr, bool wait) { return asyncLauncher(job, wait); } -bool SqlDBWriter::insertObject(const QSharedPointer &ptr, bool wait) { +bool SqlDBWriter::insertObject(const QSharedPointer &ptr, + bool wait, + const QWeakPointer& autoincrementIdResult) { - Async::Job job = [this, ptr]() { - return insertQuery(ptr); - }; + if (wait) { + auto resultId = QSharedPointer::create(); + Async::Job job = [this, ptr, autoincrementIdResult]() { + return insertQuery(ptr, autoincrementIdResult); + }; - return asyncLauncher(job, wait); + return asyncLauncher(job, wait); + } else { + Async::Job job = [this, ptr]() { + return insertQuery(ptr); + }; + return asyncLauncher(job, wait); + } } bool SqlDBWriter::replaceObject(const QSharedPointer &ptr, bool wait) { @@ -354,7 +364,8 @@ SqlDBWriter::~SqlDBWriter() { } -bool SqlDBWriter::insertQuery(const QSharedPointer &ptr) const { +bool SqlDBWriter::insertQuery(const QSharedPointer &ptr, + const QWeakPointer& autoincrementIdResult) const { if (!ptr) return false; @@ -368,7 +379,14 @@ bool SqlDBWriter::insertQuery(const QSharedPointer &ptr) const { return ptr->prepareInsertQuery(q, false); }; - auto cb = [](){return true;}; + auto cb = [&q, autoincrementIdResult]() { + + if (auto&& ptr = autoincrementIdResult.lock()) { + *ptr = q.lastInsertId().toInt(); + } + + return true; + }; return workWithQuery(q, prepare, cb); } @@ -438,7 +456,7 @@ bool SqlDBWriter::selectQuery(const DBObject& requestObject, if (!newObject->fromSqlRecord(q.record())) { QuasarAppUtils::Params::log("Select query finished successful but, " "the fromSqlRecord method return false." + - newObject->toString(), + newObject->toString(), QuasarAppUtils::Error); return false; } diff --git a/src/public/sqldbwriter.h b/src/public/sqldbwriter.h index b4510b70..faa83a50 100644 --- a/src/public/sqldbwriter.h +++ b/src/public/sqldbwriter.h @@ -67,7 +67,8 @@ class HEARTSHARED_EXPORT SqlDBWriter : public Async, public iObjectProvider QList> &result) override; bool updateObject(const QSharedPointer &ptr, bool wait = false) override; bool deleteObject(const QSharedPointer &ptr, bool wait = false) override; - bool insertObject(const QSharedPointer &ptr, bool wait = false) override; + bool insertObject(const QSharedPointer &ptr, bool wait = false, + const QWeakPointer& autoincrementIdResult = {}) override; bool replaceObject(const QSharedPointer &ptr, bool wait = false) override; void setSQLSources(const QStringList &list) override; @@ -110,9 +111,12 @@ class HEARTSHARED_EXPORT SqlDBWriter : public Async, public iObjectProvider /** * @brief insertQuery This method prepare the insert object query. * @param insertObject This is strong pointer of object for generate the insert query. + * @param autoIncrementID Week pointer to result id of new inserteed record. * @return true if query generated successful. + * @note Works only of the int autoincrement ids... */ - virtual bool insertQuery(const QSharedPointer& insertObject) const; + virtual bool insertQuery(const QSharedPointer& insertObject, + const QWeakPointer& autoIncrementID = {}) const; /** * @brief replaceQuery This method prepare the replce object query. From b8048a880af59fcca3230a92cbc5eec3066a0730 Mon Sep 17 00:00:00 2001 From: EndrII Date: Wed, 8 Nov 2023 21:59:11 +0100 Subject: [PATCH 2/3] fix autoincerement replace requests --- src/public/packages/dbobject.cpp | 12 ++++++++++-- src/public/packages/dbobject.h | 5 ++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/public/packages/dbobject.cpp b/src/public/packages/dbobject.cpp index 5cfc054b..7d466760 100644 --- a/src/public/packages/dbobject.cpp +++ b/src/public/packages/dbobject.cpp @@ -80,7 +80,11 @@ PrepareResult DBObject::prepareInsertQuery(QSqlQuery &q, bool replace) const { for (auto it = map.begin(); it != map.end(); ++it) { - if (!bool(it.value().type & MemberType::Insert)) { + if (!static_cast(it.value().type & MemberType::Insert)) { + continue; + } + + if (static_cast(it.value().type & MemberType::Autoincement) && !replace) { continue; } @@ -99,7 +103,11 @@ PrepareResult DBObject::prepareInsertQuery(QSqlQuery &q, bool replace) const { if (q.prepare(queryString)) { for (auto it = map.begin(); it != map.end(); ++it) { - if (!bool(it.value().type & MemberType::Insert)) { + if (!static_cast(it.value().type & MemberType::Insert)) { + continue; + } + + if (static_cast(it.value().type & MemberType::Autoincement) && !replace) { continue; } diff --git a/src/public/packages/dbobject.h b/src/public/packages/dbobject.h index 3e8d4c34..8c78ab30 100644 --- a/src/public/packages/dbobject.h +++ b/src/public/packages/dbobject.h @@ -47,6 +47,9 @@ enum class MemberType { /// The Field with this type can not be duplicate on a table. If a Database object do not have a primary key then default implementation for select query try get object by fields with unique type. Unique = 0x4, + /// The field with this atribute automaticaly incemented into database, and will not to added into insert reqests, but it can be used with replace request as a key. + Autoincement = 0x8, + /// The Field With This type can be inserted and updated. InsertUpdate = Insert | Update, @@ -54,7 +57,7 @@ enum class MemberType { PrimaryKey = Insert | Unique, //// The primary key field with autoincrement. - PrimaryKeyAutoIncrement = Unique + PrimaryKeyAutoIncrement = PrimaryKey | Autoincement }; constexpr inline uint qHash(MemberType type) { From dbb59b007836e320411f3455380a741ae41533f2 Mon Sep 17 00:00:00 2001 From: EndrII Date: Sat, 18 Nov 2023 17:49:20 +0100 Subject: [PATCH 3/3] fix insertObj functions --- src/public/database.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/public/database.h b/src/public/database.h index 935c48f1..a049efc1 100644 --- a/src/public/database.h +++ b/src/public/database.h @@ -419,7 +419,7 @@ class HEARTSHARED_EXPORT DataBase: public QObject template bool insertObj(const Object& obj, const QWeakPointer& resultId = {}) { if (auto&& database = db()) { - return database->insertObject(obj, resultId.isNull(), resultId); + return database->insertObject(obj, !resultId.isNull(), resultId); } return false;