QEloquent 1.1.0
Qt most flexible ORM.
Loading...
Searching...
No Matches
modelhelpers.h
1#ifndef QELOQUENT_MODELHELPERS_H
2#define QELOQUENT_MODELHELPERS_H
3
4#include <QEloquent/model.h>
5#include <QEloquent/metaobject.h>
6#include <QEloquent/query.h>
7#include <QEloquent/error.h>
8#include <QEloquent/connection.h>
9#include <QEloquent/querybuilder.h>
10#include <QEloquent/queryrunner.h>
11
12#include <QSqlQuery>
13#include <QSqlRecord>
14#include <QJsonObject>
15
16#define QELOQUENT_HELPERS(Class) \
17public: \
18 using QEloquent::ModelHelpers<Class>::make; \
19 using QEloquent::ModelHelpers<Class>::find; \
20 using QEloquent::ModelHelpers<Class>::paginate; \
21 using QEloquent::ModelHelpers<Class>::all; \
22 using QEloquent::ModelHelpers<Class>::count; \
23 using QEloquent::ModelHelpers<Class>::create; \
24 using QEloquent::ModelHelpers<Class>::remove; \
25 using QEloquent::ModelHelpers<Class>::query; \
26 using QEloquent::ModelHelpers<Class>::fixQuery; \
27private:
28
29namespace QEloquent {
30
35template<typename Model>
37public:
39 static Model make() { return Model(); }
41 static MetaObject metaObject() { return MetaObject::fromQtMetaObject(Model::staticMetaObject); }
42};
43
55template<typename Model, typename Maker = ModelMaker<Model>>
57{
58public:
60 static Model make(const QJsonObject &object = QJsonObject());
62 static QList<Model> make(const QList<QJsonObject> &objects);
63
65 static Result<Model, Error> find(const QVariant &primary);
67 static Result<QList<Model>, Error> find(Query query);
68
70 static Result<QList<Model>, Error> paginate(int page = 1, int itemsPerPage = 20, Query query = Query());
71
73 static Result<QList<Model>, Error> all(Query query = Query());
74
76 static Result<int, Error> count(Query query = Query());
77
79 static Result<Model, Error> create(const QJsonObject &object);
81 static Result<QList<Model>, Error> create(const QList<QJsonObject> &objects);
82
84 static Result<int, Error> remove(Query query);
85
87 static Query query();
89 static Query &fixQuery(Query &query);
91 static Query &fixQuery(Query &query, const MetaObject &metaObject);
92};
93
94template<typename Model, typename Maker>
95inline Model ModelHelpers<Model, Maker>::make(const QJsonObject &object)
96{
97 Model m = Maker::make();
98 m.fill(object);
99 return m;
100}
101
102template<typename Model, typename Maker>
103inline QList<Model> ModelHelpers<Model, Maker>::make(const QList<QJsonObject> &objects)
104{
105 QList<Model> models;
106 for (const QJsonObject &object : objects) {
107 Model m = Maker::make();
108 m.fill(object);
109 models.append(m);
110 }
111 return models;
112}
113
114template<typename Model, typename Maker>
115inline Result<Model, Error> ModelHelpers<Model, Maker>::find(const QVariant &primary)
116{
117 Query query;
118 query.where(Maker::metaObject().primaryProperty().fieldName(), primary);
119 query.limit(1);
120
121 Result<QList<Model>, Error> result = find(query);
122 if (result) {
123 const QList<Model> models = result.value();
124 return (models.isEmpty() ? Maker::make() : models.first());
125 } else {
126 return failWith(result.error());
127 }
128}
129
130template<typename Model, typename Maker>
131inline Result<QList<Model>, Error> ModelHelpers<Model, Maker>::find(Query query)
132{
133 const MetaObject metaObject = Maker::metaObject();
134 const QString statement = QueryBuilder::selectStatement(fixQuery(query, metaObject));
135
136 auto result = QueryRunner::exec(statement, query.connectionName());
137 if (result) {
138 QList<Model> models;
139
140 QStringList relations = metaObject.relations() + query.relations();
141 relations.removeDuplicates();
142
143 while (result->next()) {
144 Model m = Maker::make();
145 m.fill(result->record());
146 if (m.load(relations))
147 models.append(m);
148 else
149 return failWith(m.lastError());
150 }
151
152 return models;
153 } else {
154 return failWith(Error::fromSqlError(result.error()));
155 }
156}
157
158template<typename Model, typename Maker>
159inline Result<QList<Model>, Error> ModelHelpers<Model, Maker>::paginate(int page, int itemsPerPage, Query query)
160{
161 return find(query.page(page, itemsPerPage));
162}
163
164template<typename Model, typename Maker>
165inline Result<QList<Model>, Error> ModelHelpers<Model, Maker>::all(Query query)
166{
167 return find(query);
168}
169
170template<typename Model, typename Maker>
171inline Result<int, Error> ModelHelpers<Model, Maker>::count(Query query)
172{
173 const QString statement = QueryBuilder::selectStatement("COUNT(1)", fixQuery(query));
174
175 auto result = QueryRunner::exec(statement, query.connectionName());
176 if (result)
177 return (result->next() ? result->value(0).toInt() : 0);
178 else
179 return failWith(Error::fromSqlError(result.error()));
180}
181
182template<typename Model, typename Maker>
183inline Result<Model, Error> ModelHelpers<Model, Maker>::create(const QJsonObject &object)
184{
185 Model model = Maker::make();
186 model.fill(object);
187 if (model.save())
188 return model;
189 else
190 return failWith(model.lastError());
191}
192
193template<typename Model, typename Maker>
194inline Result<QList<Model>, Error> ModelHelpers<Model, Maker>::create(const QList<QJsonObject> &objects)
195{
196 QList<Model> models;
197
198 for (const QJsonObject &object : objects) {
199 auto result = create(object);
200 if (result)
201 models.append(result.value());
202 else
203 return failWith(result.error());
204 }
205
206 return models;
207}
208
209template<typename Model, typename Maker>
210inline Result<int, Error> ModelHelpers<Model, Maker>::remove(Query query)
211{
212 const QString statement = QueryBuilder::deleteStatement(fixQuery(query));
213
214 auto result = QueryRunner::exec(statement, query.connectionName());
215 if (result)
216 return result->numRowsAffected();
217 else
218 return failWith(Error(Error::DatabaseError, QString(), result.error()));
219}
220
221template<typename Model, typename Maker>
223{
224 Query query;
225 return fixQuery(query, Maker::metaObject());
226}
227
228template<typename Model, typename Maker>
230{
231 return fixQuery(query, Maker::metaObject());
232}
233
234template<typename Model, typename Maker>
235inline Query &ModelHelpers<Model, Maker>::fixQuery(Query &query, const MetaObject &metaObject)
236{
237 return query
238 .table(metaObject.tableName())
239 .connection(metaObject.connectionName())
240 .raw(QString());
241}
242
243} // namespace QEloquent
244
245#endif // QELOQUENT_MODELHELPERS_H
Represents an error in a database operation.
Definition error.h:16
static Error fromSqlError(const QSqlError &error)
Creates an Error object from a QSqlError.
Definition error.cpp:128
Provides static CRUD and query helpers for Model types.
Definition modelhelpers.h:57
static Result< Model, Error > find(const QVariant &primary)
Finds a model by its primary key.
Definition modelhelpers.h:115
static Result< QList< Model >, Error > all(Query query=Query())
Finds all models, optionaly matching the given query.
Definition modelhelpers.h:165
static Result< int, Error > count(Query query=Query())
Returns the number of records matching the query.
Definition modelhelpers.h:171
static Model make(const QJsonObject &object=QJsonObject())
Creates a model instance with optional JSON data.
Definition modelhelpers.h:95
static Query & fixQuery(Query &query)
Configures a Query object for this model's table and connection.
Definition modelhelpers.h:229
static Result< Model, Error > create(const QJsonObject &object)
Creates and persists a new model from JSON data.
Definition modelhelpers.h:183
static Result< QList< Model >, Error > paginate(int page=1, int itemsPerPage=20, Query query=Query())
Finds models matching the given query and limit output using pagination.
Definition modelhelpers.h:159
static Query query()
Returns a new Query object initialized for this model's table.
Definition modelhelpers.h:222
static Result< int, Error > remove(Query query)
Deletes records matching the given query.
Definition modelhelpers.h:210
Internal helper to create model instances and access metadata.
Definition modelhelpers.h:36
static Model make()
Creates a default model instance.
Definition modelhelpers.h:39
static MetaObject metaObject()
Returns the MetaObject for the model type.
Definition modelhelpers.h:41
The Model class is the base class for all ORM models.
Definition model.h:31
Error lastError() const
Returns the last error encountered by this model.
Definition model.cpp:314
bool load(const QString &relation)
Eagerly loads a relationship.
Definition model.cpp:274
Fluent SQL query builder.
Definition query.h:15
Query & limit(int limit)
Adds a LIMIT clause.
Definition query.cpp:252
Query & page(int page, int countPerPage=20)
Configures pagination (LIMIT/OFFSET).
Definition query.cpp:238
QStringList relations() const
Returns the list of relations to be eager loaded.
Definition query.cpp:528
QString connectionName() const
Returns the name of the connection.
Definition query.cpp:296
Connection connection() const
Returns the connection used by this query.
Definition query.cpp:288
Query & table(const QString &tableName)
Configures the table name for the query.
Definition query.cpp:125