Heart 1.3.842.34c2ab5
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-2024 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 QuasarAppUtils::Params::log("The variantMap method return an empty map.",
67 QuasarAppUtils::Error);
68
70 }
71
72 QString queryString = (replace)?
73 "REPLACE INTO %0(%1) VALUES (%2) " :
74 "INSERT INTO %0(%1) VALUES (%2) ";
75
76
77 queryString = queryString.arg(table());
78 QString tableInsertHeader = "";
79 QString tableInsertValues = "";
80
81 for (auto it = map.begin(); it != map.end(); ++it) {
82
83 if (!static_cast<bool>(it.value().type & MemberType::Insert)) {
84 continue;
85 }
86
87 if (static_cast<bool>(it.value().type & MemberType::Autoincement) && !replace) {
88 continue;
89 }
90
91 tableInsertHeader += it.key();
92 tableInsertValues += ":" + it.key();
93 if (std::next(it, 1) != map.end()) {
94 tableInsertHeader += ", ";
95 tableInsertValues += ", ";
96 }
97
98 }
99
100 queryString = queryString.arg(tableInsertHeader);
101 queryString = queryString.arg(tableInsertValues);
102
103 if (q.prepare(queryString)) {
104
105 for (auto it = map.begin(); it != map.end(); ++it) {
106 if (!static_cast<bool>(it.value().type & MemberType::Insert)) {
107 continue;
108 }
109
110 if (static_cast<bool>(it.value().type & MemberType::Autoincement) && !replace) {
111 continue;
112 }
113
114 q.bindValue(":" + it.key(), it.value().value);
115 }
116
118 }
119
120 return PrepareResult::Fail;
121}
122
124
125 DBVariantMap map = variantMap();
126
127 if (!map.size()) {
128 QuasarAppUtils::Params::log("The variantMap method return an empty map.",
129 QuasarAppUtils::Error);
130
131 return PrepareResult::Fail;
132 }
133
134 auto [conditionQueryString, conditionBindingMap] = condition();
135
136 if (conditionQueryString.isEmpty()) {
137 QuasarAppUtils::Params::log("The object soue not have condition for update object.",
138 QuasarAppUtils::Error);
139 return PrepareResult::Fail;
140 }
141
142 QString queryString = "UPDATE %0 SET %1 WHERE " + conditionQueryString;
143
144 queryString = queryString.arg(table());
145 QString tableUpdateValues = "";
146
147 for (auto it = map.begin(); it != map.end(); ++it) {
148 if (!bool(it.value().type & MemberType::Update)) {
149 continue;
150 }
151
152 if (tableUpdateValues.size()) {
153 tableUpdateValues += ", ";
154 }
155
156 tableUpdateValues += QString("%0= :%0").arg(it.key());
157
158 }
159
160 if (tableUpdateValues.isEmpty()) {
161 QuasarAppUtils::Params::log("Fail to generate condition for object: " + toString() +
162 ". The object do not have valid update fields.",
163 QuasarAppUtils::Error);
164 return PrepareResult::Fail;
165 }
166
167 queryString = queryString.arg(tableUpdateValues);
168
169 if (q.prepare(queryString)) {
170
171 for (auto it = map.begin(); it != map.end(); ++it) {
172 if (!bool(it.value().type & MemberType::Update)) {
173 continue;
174 }
175
176 q.bindValue(":" + it.key(), it.value().value);
177 }
178
179 for (auto it = conditionBindingMap.begin(); it != conditionBindingMap.end(); ++it) {
180#ifdef QT_DEBUG
181 if (bool(map.value(it.key()).type & MemberType::Update)) {
182 QuasarAppUtils::Params::log(QString("Bad object configuration: "
183 "The %0 field using in the condition and has MemberType::Update configuration."
184 " All condition fields should not use the MemberType::Update. \n %1").
185 arg(it.key(), toString()),
186 QuasarAppUtils::Warning);
187 }
188#endif
189 q.bindValue(it.key(), it.value());
190 }
191
192
193
195 }
196
197 return PrepareResult::Fail;
198}
199
200bool DBObject::isCached() const {
201#ifdef HEART_DB_CACHE
202 return isHaveAPrimaryKey();
203#else
204 return false;
205#endif
206}
207
208bool DBObject::isBundle() const {
209 return false;
210}
211
212std::pair<QString, QMap<QString, QVariant>> DBObject::condition() const {
213
214 // if object have a primaryKey then return primary key
215 auto primaryVal = primaryValue();
216 if (!primaryVal.isNull()) {
217 return {QString("%0 = :%0").arg(primaryKey()),
218 {{QString(":%0").arg(primaryKey()), {primaryVal}}}};
219 }
220
221
222 QuasarAppUtils::Params::log("Fail to generate condition for object: " + toString() +
223 ". Object do not have valid unique fields or valid database address.",
224 QuasarAppUtils::Error);
225
226
227 return {};
228}
229
230QString DBObject::primaryKey() const {
231 return "";
232}
233
234QVariant DBObject::primaryValue() const {
235 return {};
236}
237
239 return bool(variantMap().value(primaryKey()).type & MemberType::Insert);
240}
241
243 return {table(), primaryValue()};
244}
245
246QString DBObject::toString() const {
247 return AbstractData::toString() +
248 QString(" %0").arg(dbAddress().toString());
249}
250
251QDataStream &DBObject::fromStream(QDataStream &stream) {
252 QuasarAppUtils::Params::log("This object not support stream operator."
253 " Please Override the fromStream method for this object. " + toString(),
254 QuasarAppUtils::Warning);
255
256 return stream;
257}
258
259QDataStream &DBObject::toStream(QDataStream &stream) const {
260
261 QuasarAppUtils::Params::log("This object not support stream operator."
262 " Please Override the toStream method for this object. " + toString(),
263 QuasarAppUtils::Warning);
264 return stream;
265}
266
268
269 QString queryString = "DELETE FROM %0 ";
270 queryString = queryString.arg(table());
271
272 auto [conditionQueryString, conditionBindingMap] = condition();
273
274 if (conditionQueryString.size()) {
275
276 queryString += " WHERE " + conditionQueryString;
277 if (!q.prepare(queryString)) {
278 return PrepareResult::Fail;
279 }
280
281 for (auto it = conditionBindingMap.begin(); it != conditionBindingMap.end(); ++it) {
282 q.bindValue(it.key(), it.value());
283 }
284
286 }
287
288 if (!q.prepare(queryString)) {
289 return PrepareResult::Fail;
290 }
291
293}
294
296 if (isHaveAPrimaryKey()) {
298 }
299
300 return {};
301}
302
303bool DBObject::isValid() const {
305 return false;
306
307 if (isInsertPrimaryKey()) {
308 return primaryValue().isValid();
309 }
310
311 return table().size();
312}
313
315 return primaryKey().size();
316}
317
319
323
324DBVariant::DBVariant(const QVariant &value, MemberType type) {
325 this->value = value;
326 this->type = type;
327}
328
329}
330}
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:242
bool isHaveAPrimaryKey() const
isHaveAPrimaryKey This method return true if this object has a primary key. If you want to cache this...
Definition dbobject.cpp:314
virtual PrepareResult prepareRemoveQuery(QSqlQuery &q) const
prepareRemoveQuery This method should be prepare a query for remove this object from a database....
Definition dbobject.cpp:267
~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:212
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:259
bool isInsertPrimaryKey() const
isInsertPrimaryKey This method check primaryKeys type. If the primary key have a type MemberType::Ins...
Definition dbobject.cpp:238
virtual DBVariantMap variantMap() const
variantMap This method should be create a DBVariantMap implementation of this database object.
Definition dbobject.cpp:295
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:251
virtual void clear()
clear This method clear all data of database object. Override This method for remove or reset your ow...
Definition dbobject.cpp:318
virtual QString primaryKey() const
primaryKey This method must be return the name of primary key of this object table....
Definition dbobject.cpp:230
QString toString() const override
Definition dbobject.cpp:246
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:123
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:200
virtual bool isBundle() const
isBundle This method definef determines whether the object will be abstract (composite objects) or si...
Definition dbobject.cpp:208
bool isValid() const override
isValid This method check current object to valid.
Definition dbobject.cpp:303
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:234
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