Heart 1.3.848.aa44c26
Heart is base back end library for your c++ Qt projects.
dbobject.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 "dbobject.h"
9#include <QDataStream>
10#include <QDateTime>
11#include <QSqlQuery>
12#include <QHash>
13#include <QSqlRecord>
14#include <QVariantMap>
15#include <QSharedPointer>
16#include <quasarapp.h>
17#include <qaglobalutils.h>
18
19namespace QH {
20namespace PKG {
21
25
29
31
32 auto map = variantMap().keys();
33 QString queryString = "SELECT " + map.join(",") + " FROM %0 ";
34 queryString = queryString.arg(table());
35
36
37 auto [conditionQueryString, conditionBindingMap] = condition();
38
39 if (conditionQueryString.size()) {
40
41 queryString += " WHERE " + conditionQueryString;
42 if (!q.prepare(queryString)) {
44 }
45
46 for (auto it = conditionBindingMap.begin(); it != conditionBindingMap.end(); ++it) {
47 q.bindValue(it.key(), it.value());
48 }
49
51 }
52
53
54 if (!q.prepare(queryString)) {
56 }
57
59}
60
61PrepareResult DBObject::prepareInsertQuery(QSqlQuery &q, bool replace) const {
62
64
65 if (!map.size()) {
66 qCritical() << "The variantMap method return an empty map.";
67
69 }
70
71 QString queryString = (replace)?
72 "REPLACE INTO %0(%1) VALUES (%2) " :
73 "INSERT INTO %0(%1) VALUES (%2) ";
74
75
76 queryString = queryString.arg(table());
77 QString tableInsertHeader = "";
78 QString tableInsertValues = "";
79
80 for (auto it = map.begin(); it != map.end(); ++it) {
81
82 if (!static_cast<bool>(it.value().type & MemberType::Insert)) {
83 continue;
84 }
85
86 if (static_cast<bool>(it.value().type & MemberType::Autoincement) && !replace) {
87 continue;
88 }
89
90 tableInsertHeader += it.key();
91 tableInsertValues += ":" + it.key();
92 if (std::next(it, 1) != map.end()) {
93 tableInsertHeader += ", ";
94 tableInsertValues += ", ";
95 }
96
97 }
98
99 queryString = queryString.arg(tableInsertHeader);
100 queryString = queryString.arg(tableInsertValues);
101
102 if (q.prepare(queryString)) {
103
104 for (auto it = map.begin(); it != map.end(); ++it) {
105 if (!static_cast<bool>(it.value().type & MemberType::Insert)) {
106 continue;
107 }
108
109 if (static_cast<bool>(it.value().type & MemberType::Autoincement) && !replace) {
110 continue;
111 }
112
113 q.bindValue(":" + it.key(), it.value().value);
114 }
115
117 }
118
119 return PrepareResult::Fail;
120}
121
123
124 DBVariantMap map = variantMap();
125
126 if (!map.size()) {
127 qCritical() << "The variantMap method return an empty map.";
128
129 return PrepareResult::Fail;
130 }
131
132 auto [conditionQueryString, conditionBindingMap] = condition();
133
134 if (conditionQueryString.isEmpty()) {
135 qCritical() << "The object soue not have condition for update object.";
136 return PrepareResult::Fail;
137 }
138
139 QString queryString = "UPDATE %0 SET %1 WHERE " + conditionQueryString;
140
141 queryString = queryString.arg(table());
142 QString tableUpdateValues = "";
143
144 for (auto it = map.begin(); it != map.end(); ++it) {
145 if (!bool(it.value().type & MemberType::Update)) {
146 continue;
147 }
148
149 if (tableUpdateValues.size()) {
150 tableUpdateValues += ", ";
151 }
152
153 tableUpdateValues += QString("%0= :%0").arg(it.key());
154
155 }
156
157 if (tableUpdateValues.isEmpty()) {
158 qCritical() << "Fail to generate condition for object: " + toString() +
159 ". The object do not have valid update fields.";
160 return PrepareResult::Fail;
161 }
162
163 queryString = queryString.arg(tableUpdateValues);
164
165 if (q.prepare(queryString)) {
166
167 for (auto it = map.begin(); it != map.end(); ++it) {
168 if (!bool(it.value().type & MemberType::Update)) {
169 continue;
170 }
171
172 q.bindValue(":" + it.key(), it.value().value);
173 }
174
175 for (auto it = conditionBindingMap.begin(); it != conditionBindingMap.end(); ++it) {
176#ifdef QT_DEBUG
177 if (bool(map.value(it.key()).type & MemberType::Update)) {
178 qWarning() << "Bad object configuration: "
179 "The " << it.key() << " field using in the condition and has MemberType::Update configuration."
180 " All condition fields should not use the MemberType::Update. \n" << toString();
181 }
182#endif
183 q.bindValue(it.key(), it.value());
184 }
185
186
187
189 }
190
191 return PrepareResult::Fail;
192}
193
194bool DBObject::isCached() const {
195#ifdef HEART_DB_CACHE
196 return isHaveAPrimaryKey();
197#else
198 return false;
199#endif
200}
201
202bool DBObject::isBundle() const {
203 return false;
204}
205
206std::pair<QString, QMap<QString, QVariant>> DBObject::condition() const {
207
208 // if object have a primaryKey then return primary key
209 auto primaryVal = primaryValue();
210 if (!primaryVal.isNull()) {
211 return {QString("%0 = :%0").arg(primaryKey()),
212 {{QString(":%0").arg(primaryKey()), {primaryVal}}}};
213 }
214
215 qCritical() << "Fail to generate condition for object: " + toString() +
216 ". Object do not have valid unique fields or valid database address.";
217
218
219 return {};
220}
221
222QString DBObject::primaryKey() const {
223 return "";
224}
225
226QVariant DBObject::primaryValue() const {
227 return {};
228}
229
231 return bool(variantMap().value(primaryKey()).type & MemberType::Insert);
232}
233
235 return {table(), primaryValue()};
236}
237
238QString DBObject::toString() const {
239 return AbstractData::toString() +
240 QString(" %0").arg(dbAddress().toString());
241}
242
243QDataStream &DBObject::fromStream(QDataStream &stream) {
244
245 qWarning() << "This object not support stream operator."
246 " Please Override the fromStream method for this object. " + toString();
247
248 return stream;
249}
250
251QDataStream &DBObject::toStream(QDataStream &stream) const {
252
253 qWarning() << "This object not support stream operator."
254 " Please Override the toStream method for this object. " + toString();
255 return stream;
256}
257
259
260 QString queryString = "DELETE FROM %0 ";
261 queryString = queryString.arg(table());
262
263 auto [conditionQueryString, conditionBindingMap] = condition();
264
265 if (conditionQueryString.size()) {
266
267 queryString += " WHERE " + conditionQueryString;
268 if (!q.prepare(queryString)) {
269 return PrepareResult::Fail;
270 }
271
272 for (auto it = conditionBindingMap.begin(); it != conditionBindingMap.end(); ++it) {
273 q.bindValue(it.key(), it.value());
274 }
275
277 }
278
279 if (!q.prepare(queryString)) {
280 return PrepareResult::Fail;
281 }
282
284}
285
287 if (isHaveAPrimaryKey()) {
289 }
290
291 return {};
292}
293
294bool DBObject::isValid() const {
296 return false;
297
298 if (isInsertPrimaryKey()) {
299 return primaryValue().isValid();
300 }
301
302 return table().size();
303}
304
306 return primaryKey().size();
307}
308
310
314
315DBVariant::DBVariant(const QVariant &value, MemberType type) {
316 this->value = value;
317 this->type = type;
318}
319
320}
321}
The DbAddress class use to work with database addresses. Database Address it is structure with 2 valu...
Definition dbaddress.h:24
virtual bool isValid() const
isValid This method check current object to valid.
QString toString() const override
toString - Return a string implementation for this object.
DbAddress dbAddress() const
dbAddress This method return address of the database object. IF the object is not valid then this met...
Definition dbobject.cpp:234
bool isHaveAPrimaryKey() const
isHaveAPrimaryKey This method return true if this object has a primary key. If you want to cache this...
Definition dbobject.cpp:305
virtual PrepareResult prepareRemoveQuery(QSqlQuery &q) const
prepareRemoveQuery This method should be prepare a query for remove this object from a database....
Definition dbobject.cpp:258
~DBObject() override
Definition dbobject.cpp:26
virtual std::pair< QString, QMap< QString, QVariant > > condition() const
condition This method must to return a condition of the WHERE block of the sql query....
Definition dbobject.cpp:206
QDataStream & toStream(QDataStream &stream) const override
fromStream This method should be write all members of the current object to the stream object.
Definition dbobject.cpp:251
bool isInsertPrimaryKey() const
isInsertPrimaryKey This method check primaryKeys type. If the primary key have a type MemberType::Ins...
Definition dbobject.cpp:230
virtual DBVariantMap variantMap() const
variantMap This method should be create a DBVariantMap implementation of this database object.
Definition dbobject.cpp:286
QDataStream & fromStream(QDataStream &stream) override
fromStream This method should be read all bytes from the stream object and full the current object.
Definition dbobject.cpp:243
virtual void clear()
clear This method clear all data of database object. Override This method for remove or reset your ow...
Definition dbobject.cpp:309
virtual QString primaryKey() const
primaryKey This method must be return the name of primary key of this object table....
Definition dbobject.cpp:222
QString toString() const override
Definition dbobject.cpp:238
virtual PrepareResult prepareSelectQuery(QSqlQuery &q) const
prepareSelectQuery This method should be prepare a query for selected data. Override this method for ...
Definition dbobject.cpp:30
virtual PrepareResult prepareUpdateQuery(QSqlQuery &q) const
prepareUpdateQuery this method should be prepare a insert data query.
Definition dbobject.cpp:122
virtual PrepareResult prepareInsertQuery(QSqlQuery &q, bool replace) const
prepareInsertQuery This method should be prepare a query for insert object into database....
Definition dbobject.cpp:61
virtual bool isCached() const
isCached This method sholud be return status of object. If this method return true then this object c...
Definition dbobject.cpp:194
virtual bool isBundle() const
isBundle This method definef determines whether the object will be abstract (composite objects) or si...
Definition dbobject.cpp:202
bool isValid() const override
isValid This method check current object to valid.
Definition dbobject.cpp:294
virtual QString table() const =0
table This method should be return name of the database table that should be contains objects with th...
virtual QVariant primaryValue() const
primaryValue This method is wraper of DBAddress::id. If This object do not contains a id value then r...
Definition dbobject.cpp:226
PrepareResult
The PrepareResult enum is result of work prepare sql query of dbobjects.
Definition dbobject.h:24
@ Success
prepare finished successful.
@ Fail
prepare is failed.
QMap< QString, DBVariant > DBVariantMap
DBVariantMap this is Map with key, and value with data type.
Definition dbobject.h:84
MemberType
The MemberType enum. This enum contains types of members DBObjects classes. for more information see ...
Definition dbobject.h:37
@ Update
The Field With This type can be updated but not inserted.
@ PrimaryKey
The primary key field without autoincrement.
@ Autoincement
The field with this atribute automaticaly incemented into database, and will not to added into insert...
@ Insert
The Field With This type can be inserted but not updated.
The QH namespace - QuasarApp Heart namespace. This namespace contains all classes of the Heart librar...
Definition heart.cpp:13
MemberType type
Definition dbobject.h:75