LeechCraft 0.6.70-18450-gabe19ee3b0
Modular cross-platform feature rich live environment.
Loading...
Searching...
No Matches
oraltest_simplerecord.cpp
Go to the documentation of this file.
1/**********************************************************************
2 * LeechCraft - modular cross-platform feature rich internet client.
3 * Copyright (C) 2006-2014 Georg Rudoy
4 *
5 * Distributed under the Boost Software License, Version 1.0.
6 * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
7 **********************************************************************/
8
10#include "common.h"
11#include "simplerecord.h"
12
13QTEST_GUILESS_MAIN (LC::Util::OralTest_SimpleRecord)
14
15using LC::operator""_ct;
16
17// Models the pagination scenario: messages with a timestamp (TS) and an
18// auto-generated primary key (Id) that don't necessarily correlate.
19// After history sync, a message from the past gets a high Id.
21{
23 int TS_;
24 QString Body_;
25
26 constexpr static auto ClassName = "MessageLikeRecord"_ct;
27
28 auto AsTuple () const
29 {
30 return std::tuple (Id_, TS_, Body_);
31 }
32};
33
35 Id_,
36 TS_,
37 Body_)
38
40
41namespace LC
42{
43namespace Util
44{
45 namespace sph = oral::sph;
46
47 void OralTest_SimpleRecord::testSimpleRecordInsertSelect ()
48 {
50 const auto& list = adapted->Select ();
51 QCOMPARE (list, (QList<SimpleRecord> { { 0, "0" }, { 1, "1" }, { 2, "2" } }));
52 }
53
54 void OralTest_SimpleRecord::testSimpleRecordInsertReplaceSelect ()
55 {
56 auto db = MakeDatabase ();
57
59 for (int i = 0; i < 3; ++i)
60 adapted->Insert (OralFactory {}, { 0, QString::number (i) }, lco::InsertAction::Replace::Whole);
61
62 const auto& list = adapted->Select ();
63 QCOMPARE (list, (QList<SimpleRecord> { { 0, "2" } }));
64 }
65
66 void OralTest_SimpleRecord::testSimpleRecordInsertIgnoreSelect ()
67 {
68 auto db = MakeDatabase ();
69
71 for (int i = 0; i < 3; ++i)
72 adapted->Insert (OralFactory {}, { 0, QString::number (i) }, lco::InsertAction::Ignore);
73
74 const auto& list = adapted->Select ();
75 QCOMPARE (list, (QList<SimpleRecord> { { 0, "0" } }));
76 }
77
78 void OralTest_SimpleRecord::testSimpleRecordInsertSelectByPos ()
79 {
81 const auto& list = adapted->Select (sph::f<&SimpleRecord::ID_> == 1);
82 QCOMPARE (list, (QList<SimpleRecord> { { 1, "1" } }));
83 }
84
85 void OralTest_SimpleRecord::testSimpleRecordInsertSelectByPos2 ()
86 {
88 const auto& list = adapted->Select (sph::f<&SimpleRecord::ID_> < 2);
89 QCOMPARE (list, (QList<SimpleRecord> { { 0, "0" }, { 1, "1" } }));
90 }
91
92 void OralTest_SimpleRecord::testSimpleRecordInsertSelectByPos3 ()
93 {
95 const auto& list = adapted->Select (sph::f<&SimpleRecord::ID_> < 2 && sph::f<&SimpleRecord::Value_> == QString { "1" });
96 QCOMPARE (list, (QList<SimpleRecord> { { 1, "1" } }));
97 }
98
99 void OralTest_SimpleRecord::testSimpleRecordInsertSelectOneByPos ()
100 {
101 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
102 const auto& single = adapted->SelectOne (sph::f<&SimpleRecord::ID_> == 1);
103 QCOMPARE (single, (std::optional<SimpleRecord> { { 1, "1" } }));
104 }
105
106 void OralTest_SimpleRecord::testSimpleRecordInsertSelectByFields ()
107 {
108 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
109 const auto& list = adapted->Select (sph::f<&SimpleRecord::ID_> == 1);
110 QCOMPARE (list, (QList<SimpleRecord> { { 1, "1" } }));
111 }
112
113 void OralTest_SimpleRecord::testSimpleRecordInsertSelectByFields2 ()
114 {
115 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
116 const auto& list = adapted->Select (sph::f<&SimpleRecord::ID_> < 2);
117 QCOMPARE (list, (QList<SimpleRecord> { { 0, "0" }, { 1, "1" } }));
118 }
119
120 void OralTest_SimpleRecord::testSimpleRecordInsertSelectByFields3 ()
121 {
122 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
123 const auto& list = adapted->Select (sph::f<&SimpleRecord::ID_> < 2 && sph::f<&SimpleRecord::Value_> == QString { "1" });
124 QCOMPARE (list, (QList<SimpleRecord> { { 1, "1" } }));
125 }
126
127 void OralTest_SimpleRecord::testSimpleRecordInsertSelectOneByFields ()
128 {
129 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
130 const auto& single = adapted->SelectOne (sph::f<&SimpleRecord::ID_> == 1);
131 QCOMPARE (single, (std::optional<SimpleRecord> { { 1, "1" } }));
132 }
133
134 void OralTest_SimpleRecord::testSimpleRecordInsertSelectSingleFieldByFields ()
135 {
136 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
137 const auto& list = adapted->Select (sph::fields<&SimpleRecord::Value_>, sph::f<&SimpleRecord::ID_> < 2);
138 QCOMPARE (list, (QList<QString> { "0", "1" }));
139 }
140
141 void OralTest_SimpleRecord::testSimpleRecordInsertSelectFieldsByFields ()
142 {
143 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
144 const auto& list = adapted->Select (sph::fields<&SimpleRecord::ID_, &SimpleRecord::Value_>, sph::f<&SimpleRecord::ID_> < 2);
145 QCOMPARE (list, (QList<std::tuple<int, QString>> { { 0, "0" }, { 1, "1" } }));
146 }
147
148 void OralTest_SimpleRecord::testSimpleRecordInsertSelectFieldsByFieldsOrderAsc ()
149 {
150 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
151 const auto& list = adapted->Select (sph::fields<&SimpleRecord::ID_, &SimpleRecord::Value_>,
152 sph::f<&SimpleRecord::ID_> < 2,
153 oral::OrderBy<sph::asc<&SimpleRecord::Value_>>);
154 QCOMPARE (list, (QList<std::tuple<int, QString>> { { 0, "0" }, { 1, "1" } }));
155 }
156
157 void OralTest_SimpleRecord::testSimpleRecordInsertSelectFieldsByFieldsOrderDesc ()
158 {
159 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
160 const auto& list = adapted->Select (sph::fields<&SimpleRecord::ID_, &SimpleRecord::Value_>,
161 sph::f<&SimpleRecord::ID_> < 2,
162 oral::OrderBy<sph::desc<&SimpleRecord::Value_>>);
163 QCOMPARE (list, (QList<std::tuple<int, QString>> { { 1, "1" }, { 0, "0" } }));
164 }
165
166 void OralTest_SimpleRecord::testSimpleRecordInsertSelectFieldsByFieldsOrderManyAsc ()
167 {
168 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
169 const auto& list = adapted->Select (sph::fields<&SimpleRecord::ID_, &SimpleRecord::Value_>,
170 sph::f<&SimpleRecord::ID_> < 2,
171 oral::OrderBy<sph::asc<&SimpleRecord::Value_>, sph::desc<&SimpleRecord::ID_>>);
172 QCOMPARE (list, (QList<std::tuple<int, QString>> { { 0, "0" }, { 1, "1" } }));
173 }
174
175 void OralTest_SimpleRecord::testSimpleRecordInsertSelectFieldsByFieldsOrderManyDesc ()
176 {
177 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
178 const auto& list = adapted->Select (sph::fields<&SimpleRecord::ID_, &SimpleRecord::Value_>,
179 sph::f<&SimpleRecord::ID_> < 2,
180 oral::OrderBy<sph::desc<&SimpleRecord::Value_>, sph::asc<&SimpleRecord::ID_>>);
181 QCOMPARE (list, (QList<std::tuple<int, QString>> { { 1, "1" }, { 0, "0" } }));
182 }
183
184 void OralTest_SimpleRecord::testSimpleRecordInsertSelectNoOffsetLimit ()
185 {
186 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase (), 10);
187 const auto& list = adapted->Select.Build ().Limit (2) ();
188 QCOMPARE (list, (QList<SimpleRecord> { { 0, "0" }, { 1, "1" } }));
189 }
190
191 /*
192 void OralTest_SimpleRecord::testSimpleRecordInsertSelectOffsetNoLimit ()
193 {
194 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase (), 10);
195 const auto& list = adapted->Select.Build ().Offset ({ 8 }) ();
196 QCOMPARE (list, (QList<SimpleRecord> { { 8, "8" }, { 9, "9" } }));
197 }
198 */
199
200 void OralTest_SimpleRecord::testSimpleRecordInsertSelectOffsetLimit ()
201 {
202 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase (), 10);
203 const auto& list = adapted->Select.Build ().Offset (5).Limit (2) ();
204 QCOMPARE (list, (QList<SimpleRecord> { { 5, "5" }, { 6, "6" } }));
205 }
206
207 void OralTest_SimpleRecord::testSimpleRecordInsertSelectBuilderAndWhere ()
208 {
209 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
210 const auto& list = adapted->Select.Build ()
211 .Where (sph::f<&SimpleRecord::ID_> < 2)
212 .AndWhere (sph::f<&SimpleRecord::Value_> == QString { "1" })
213 ();
214 QCOMPARE (list, (QList<SimpleRecord> { { 1, "1" } }));
215 }
216
217 void OralTest_SimpleRecord::testSimpleRecordInsertSelectBuilderAndWhereMultiple ()
218 {
219 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase (), 10);
220 const auto& list = adapted->Select.Build ()
221 .Where (sph::f<&SimpleRecord::ID_> < 8)
222 .AndWhere (sph::f<&SimpleRecord::ID_> >= 2)
223 .AndWhere (sph::f<&SimpleRecord::Value_> == QString { "5" })
224 ();
225 QCOMPARE (list, (QList<SimpleRecord> { { 5, "5" } }));
226 }
227
228 void OralTest_SimpleRecord::testSimpleRecordInsertSelectCount ()
229 {
230 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
231 const auto count = adapted->Select (sph::count<>);
232 QCOMPARE (count, 3);
233 }
234
235 void OralTest_SimpleRecord::testSimpleRecordInsertSelectCountByFields ()
236 {
237 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
238 const auto count = adapted->Select (sph::count<>, sph::f<&SimpleRecord::ID_> < 2);
239 QCOMPARE (count, 2);
240 }
241
242 void OralTest_SimpleRecord::testSimpleRecordInsertSelectMin ()
243 {
244 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
245 const auto min = adapted->Select (sph::min<&SimpleRecord::ID_>);
246 QCOMPARE (min, 0);
247 }
248
249 void OralTest_SimpleRecord::testSimpleRecordInsertSelectMax ()
250 {
251 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
252 const auto max = adapted->Select (sph::max<&SimpleRecord::ID_>);
253 QCOMPARE (max, 2);
254 }
255
256 void OralTest_SimpleRecord::testSimpleRecordInsertSelectMinPlusMax ()
257 {
258 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
259 const auto minMax = adapted->Select (sph::min<&SimpleRecord::ID_> + sph::max<&SimpleRecord::ID_>);
260 QCOMPARE (minMax, (std::tuple { 0, 2 }));
261 }
262
263 void OralTest_SimpleRecord::testSimpleRecordInsertSelectMinPlusMaxEmpty ()
264 {
266 const auto minMax = adapted->Select (sph::min<&SimpleRecord::ID_> + sph::max<&SimpleRecord::ID_>);
267 QCOMPARE (minMax, (std::tuple { std::nullopt, std::nullopt }));
268 }
269
270 void OralTest_SimpleRecord::testSimpleRecordInsertSelectValuePlusMinPlusMax ()
271 {
273 for (int i = 0; i < 3; ++i)
274 adapted->Insert ({ i, "0" });
275 for (int i = 3; i < 6; ++i)
276 adapted->Insert ({ i, "1" });
277
278 const auto allMinMax = adapted->Select.Build ()
279 .Select (sph::fields<&SimpleRecord::Value_> + sph::min<&SimpleRecord::ID_> + sph::max<&SimpleRecord::ID_>)
281 ();
282 QCOMPARE (allMinMax, (QList<std::tuple<QString, std::optional<int>, std::optional<int>>>
283 {
284 { { "0" }, 0, 2 },
285 { { "1" }, 3, 5 }
286 }));
287 }
288
289 void OralTest_SimpleRecord::testSimpleRecordInsertSelectAllPlusMinPlusMax ()
290 {
291 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase (), 2);
292 const auto allMinMax = adapted->Select.Build ()
293 .Select (sph::all + sph::min<&SimpleRecord::ID_> + sph::max<&SimpleRecord::ID_>)
295 ();
296 QCOMPARE (allMinMax, (QList<std::tuple<SimpleRecord, std::optional<int>, std::optional<int>>>
297 {
298 { { 0, "0" }, 0, 0 }, { { 1, "1" }, 1, 1 }
299 }));
300 }
301
302 void OralTest_SimpleRecord::testSimpleRecordInsertSelectLike ()
303 {
304 using namespace oral::infix;
305
307 adapted->Insert ({ 0, "foo" });
308 adapted->Insert ({ 1, "bar" });
309 adapted->Insert ({ 2, "foobar" });
310 const auto& list = adapted->Select (sph::f<&SimpleRecord::Value_> |like| QString { "%oo%" });
311 QCOMPARE (list, (QList<SimpleRecord> { { 0, "foo" }, { 2, "foobar" } }));
312 }
313
314 void OralTest_SimpleRecord::testSimpleRecordUpdate ()
315 {
316 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
317 adapted->Update ({ 0, "meh" });
318 const auto updated = adapted->Select (sph::f<&SimpleRecord::ID_> == 0);
319 QCOMPARE (updated, (QList<SimpleRecord> { { 0, "meh" } }));
320 }
321
322 void OralTest_SimpleRecord::testSimpleRecordUpdateExprTree ()
323 {
324 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
325 adapted->Update (sph::f<&SimpleRecord::Value_> = QString { "meh" }, sph::f<&SimpleRecord::ID_> == 0);
326 const auto updated = adapted->Select (sph::f<&SimpleRecord::ID_> == 0);
327 QCOMPARE (updated, (QList<SimpleRecord> { { 0, "meh" } }));
328 }
329
330 void OralTest_SimpleRecord::testSimpleRecordUpdateMultiExprTree ()
331 {
332 auto adapted = PrepareRecords<SimpleRecord> (MakeDatabase ());
333 adapted->Update ((sph::f<&SimpleRecord::Value_> = QString { "meh" }, sph::f<&SimpleRecord::ID_> = 10),
334 sph::f<&SimpleRecord::ID_> == 0);
335 const auto updated = adapted->Select (sph::f<&SimpleRecord::ID_> == 10);
336 QCOMPARE (updated, (QList<SimpleRecord> { { 10, "meh" } }));
337 }
338
339 auto PrepareMessageLikeRecords (QSqlDatabase db)
340 {
341 using Rec = MessageLikeRecord;
342 auto adapted = oral::AdaptPtr<Rec, OralFactory> (db);
343 adapted->Insert ({ {}, 300, "c" });
344 adapted->Insert ({ {}, 400, "d" });
345 adapted->Insert ({ {}, 500, "e" });
346 adapted->Insert ({ {}, 100, "a" });
347 adapted->Insert ({ {}, 200, "b" });
348 return adapted;
349 }
350
351 void OralTest_SimpleRecord::testTupleCompareEq ()
352 {
353 using Rec = MessageLikeRecord;
354 auto adapted = PrepareMessageLikeRecords (MakeDatabase ());
355 const auto& list = adapted->Select (sph::tuple<&Rec::TS_, &Rec::Id_> == std::tuple (300, 1));
356 QCOMPARE (list, (QList<Rec> { { 1, 300, "c" } }));
357 }
358
359 void OralTest_SimpleRecord::testTupleCompareLt ()
360 {
361 using Rec = MessageLikeRecord;
362 auto adapted = PrepareMessageLikeRecords (MakeDatabase ());
363 const auto& list = adapted->Select.Build ()
364 .Where (sph::tuple<&Rec::TS_, &Rec::Id_> < std::tuple (300, 1))
365 .Order (oral::OrderBy<sph::asc<&Rec::TS_>, sph::asc<&Rec::Id_>>)
366 ();
367 QCOMPARE (list, (QList<Rec> { { 4, 100, "a" }, { 5, 200, "b" } }));
368 }
369
370 void OralTest_SimpleRecord::testTupleCompareGt ()
371 {
372 using Rec = MessageLikeRecord;
373 auto adapted = PrepareMessageLikeRecords (MakeDatabase ());
374 const auto& list = adapted->Select.Build ()
375 .Where (sph::tuple<&Rec::TS_, &Rec::Id_> > std::tuple (300, 1))
376 .Order (oral::OrderBy<sph::asc<&Rec::TS_>, sph::asc<&Rec::Id_>>)
377 ();
378 QCOMPARE (list, (QList<Rec> { { 2, 400, "d" }, { 3, 500, "e" } }));
379 }
380
381 void OralTest_SimpleRecord::testTupleCompareLte ()
382 {
383 using Rec = MessageLikeRecord;
384 auto adapted = PrepareMessageLikeRecords (MakeDatabase ());
385 const auto& list = adapted->Select.Build ()
386 .Where (sph::tuple<&Rec::TS_, &Rec::Id_> <= std::tuple (300, 1))
387 .Order (oral::OrderBy<sph::asc<&Rec::TS_>, sph::asc<&Rec::Id_>>)
388 ();
389 QCOMPARE (list, (QList<Rec> { { 4, 100, "a" }, { 5, 200, "b" }, { 1, 300, "c" } }));
390 }
391
392 void OralTest_SimpleRecord::testTupleCompareGte ()
393 {
394 using Rec = MessageLikeRecord;
395 auto adapted = PrepareMessageLikeRecords (MakeDatabase ());
396 const auto& list = adapted->Select.Build ()
397 .Where (sph::tuple<&Rec::TS_, &Rec::Id_> >= std::tuple (300, 1))
398 .Order (oral::OrderBy<sph::asc<&Rec::TS_>, sph::asc<&Rec::Id_>>)
399 ();
400 QCOMPARE (list, (QList<Rec> { { 1, 300, "c" }, { 2, 400, "d" }, { 3, 500, "e" } }));
401 }
402
403 void OralTest_SimpleRecord::testTupleCompareIsNotComponentwise ()
404 {
405 using Rec = MessageLikeRecord;
406 auto adapted = PrepareMessageLikeRecords (MakeDatabase ());
407 const auto& before = adapted->Select (sph::tuple<&Rec::TS_, &Rec::Id_> < std::tuple (200, 5));
408 QCOMPARE (before, (QList<Rec> { { 4, 100, "a" } }));
409
410 const auto& after = adapted->Select.Build ()
411 .Where (sph::tuple<&Rec::TS_, &Rec::Id_> > std::tuple (200, 5))
412 .Order (oral::OrderBy<sph::asc<&Rec::TS_>, sph::asc<&Rec::Id_>>)
413 ();
414 QCOMPARE (after, (QList<Rec> { { 1, 300, "c" }, { 2, 400, "d" }, { 3, 500, "e" } }));
415 }
416
417 void OralTest_SimpleRecord::testTupleCompareInBuilder ()
418 {
419 using Rec = MessageLikeRecord;
420 auto adapted = PrepareMessageLikeRecords (MakeDatabase ());
421 auto page = adapted->Select.Build ()
422 .Where (sph::tuple<&Rec::TS_, &Rec::Id_> < std::tuple (400, 2))
423 .Order (oral::OrderBy<sph::desc<&Rec::TS_>, sph::desc<&Rec::Id_>>)
424 .Limit (2)
425 ();
426 QCOMPARE (page, (QList<Rec> { { 1, 300, "c" }, { 5, 200, "b" } }));
427 }
428}
429}
#define TOSTRING(n)
Definition common.h:35
lco::SQLiteImplFactory OralFactory
Definition common.h:18
ObjectInfo_ptr< T > AdaptPtr(const QSqlDatabase &db)
Definition oral.h:1836
constexpr detail::OrderBy< Orders... > OrderBy
Definition oral.h:1117
constexpr detail::GroupBy< Ptrs... > GroupBy
Definition oral.h:1120
auto PrepareRecords(QSqlDatabase db, int count=3)
Definition common.h:69
QSqlDatabase MakeDatabase(const QString &name=":memory:")
Definition common.h:56
Definition constants.h:15
#define ORAL_ADAPT_STRUCT(sname,...)
Definition oral.h:44
static constexpr struct LC::Util::oral::InsertAction::Replace::WholeType Whole
static constexpr struct LC::Util::oral::InsertAction::IgnoreTag Ignore
static constexpr auto ClassName
lco::PKey< int, lco::NoAutogen > ID_
QString Value_