42 return "SimpleRecord";
47 return std::tie (ID_, Value_);
57 struct AutogenPKeyRecord
62 static QString ClassName ()
64 return "AutogenPKeyRecord";
69 return std::tie (ID_, Value_);
84 static QString ClassName ()
86 return "NoPKeyRecord";
91 return std::tie (ID_, Value_);
101 struct NonInPlaceConstructibleRecord
106 NonInPlaceConstructibleRecord () =
default;
108 NonInPlaceConstructibleRecord (
int id,
const QString& value,
double someExtraArgument)
112 Q_UNUSED (someExtraArgument)
115 static QString ClassName ()
117 return "NonInPlaceConstructibleRecord";
120 auto AsTuple ()
const 122 return std::tie (ID_, Value_);
130 TOSTRING (NonInPlaceConstructibleRecord)
132 struct ComplexConstraintsRecord
139 static QString ClassName ()
141 return "ComplexConstraintsRecord";
144 auto AsTuple ()
const 146 return std::tie (ID_, Value_, Age_, Weight_);
170 auto PrepareRecords (QSqlDatabase db)
172 auto adapted = Util::oral::AdaptPtr<T, OralFactory> (db);
173 for (
int i = 0; i < 3; ++i)
174 adapted->Insert ({ i, QString::number (i) });
179 namespace sph = oral::sph;
181 void OralTest::testSimpleRecordInsertSelect ()
183 auto adapted = PrepareRecords<SimpleRecord> (
MakeDatabase ());
184 const auto& list = adapted->Select ();
188 void OralTest::testSimpleRecordInsertReplaceSelect ()
192 auto adapted = Util::oral::AdaptPtr<SimpleRecord, OralFactory> (db);
193 for (
int i = 0; i < 3; ++i)
194 adapted->Insert ({ 0, QString::number (i) }, lco::InsertAction::Replace::PKey<SimpleRecord>);
196 const auto& list = adapted->Select ();
200 void OralTest::testSimpleRecordInsertIgnoreSelect ()
204 auto adapted = Util::oral::AdaptPtr<SimpleRecord, OralFactory> (db);
205 for (
int i = 0; i < 3; ++i)
208 const auto& list = adapted->Select ();
212 void OralTest::testSimpleRecordInsertSelectByPos ()
214 auto adapted = PrepareRecords<SimpleRecord> (
MakeDatabase ());
215 const auto& list = adapted->Select (sph::_0 == 1);
219 void OralTest::testSimpleRecordInsertSelectByPos2 ()
221 auto adapted = PrepareRecords<SimpleRecord> (
MakeDatabase ());
222 const auto& list = adapted->Select (sph::_0 < 2);
226 void OralTest::testSimpleRecordInsertSelectByPos3 ()
228 auto adapted = PrepareRecords<SimpleRecord> (
MakeDatabase ());
229 const auto& list = adapted->Select (sph::_0 < 2 && sph::_1 == QString {
"1" });
233 void OralTest::testSimpleRecordInsertSelectOneByPos ()
235 auto adapted = PrepareRecords<SimpleRecord> (
MakeDatabase ());
236 const auto& single = adapted->SelectOne (sph::_0 == 1);
237 QCOMPARE (single, (boost::optional<SimpleRecord> { { 1,
"1" } }));
240 void OralTest::testSimpleRecordInsertSelectByFields ()
242 auto adapted = PrepareRecords<SimpleRecord> (
MakeDatabase ());
243 const auto& list = adapted->Select (sph::f<&SimpleRecord::ID_> == 1);
247 void OralTest::testSimpleRecordInsertSelectByFields2 ()
249 auto adapted = PrepareRecords<SimpleRecord> (
MakeDatabase ());
250 const auto& list = adapted->Select (sph::f<&SimpleRecord::ID_> < 2);
254 void OralTest::testSimpleRecordInsertSelectByFields3 ()
256 auto adapted = PrepareRecords<SimpleRecord> (
MakeDatabase ());
257 const auto& list = adapted->Select (sph::f<&SimpleRecord::ID_> < 2 && sph::f<&SimpleRecord::Value_> == QString {
"1" });
261 void OralTest::testSimpleRecordInsertSelectOneByFields ()
263 auto adapted = PrepareRecords<SimpleRecord> (
MakeDatabase ());
264 const auto& single = adapted->SelectOne (sph::f<&SimpleRecord::ID_> == 1);
265 QCOMPARE (single, (boost::optional<SimpleRecord> { { 1,
"1" } }));
268 void OralTest::testSimpleRecordInsertSelectSingleFieldByFields ()
270 auto adapted = PrepareRecords<SimpleRecord> (
MakeDatabase ());
271 const auto& list = adapted->Select (sph::fields<&SimpleRecord::Value_>, sph::f<&SimpleRecord::ID_> < 2);
275 void OralTest::testSimpleRecordInsertSelectFieldsByFields ()
277 auto adapted = PrepareRecords<SimpleRecord> (
MakeDatabase ());
278 const auto& list = adapted->Select (sph::fields<&SimpleRecord::ID_, &SimpleRecord::Value_>, sph::f<&SimpleRecord::ID_> < 2);
279 QCOMPARE (list, (
QList<std::tuple<int, QString>> { { 0,
"0" }, { 1,
"1" } }));
282 void OralTest::testSimpleRecordInsertSelectCount ()
284 auto adapted = PrepareRecords<SimpleRecord> (
MakeDatabase ());
289 void OralTest::testSimpleRecordInsertSelectCountByFields ()
291 auto adapted = PrepareRecords<SimpleRecord> (
MakeDatabase ());
292 const auto count = adapted->Select (
sph::count, sph::f<&SimpleRecord::ID_> < 2);
296 void OralTest::testSimpleRecordUpdate ()
298 auto adapted = PrepareRecords<SimpleRecord> (
MakeDatabase ());
299 adapted->Update ({ 0,
"meh" });
300 const auto updated = adapted->Select (sph::f<&SimpleRecord::ID_> == 0);
304 void OralTest::testSimpleRecordUpdateExprTree ()
306 auto adapted = PrepareRecords<SimpleRecord> (
MakeDatabase ());
307 adapted->Update (sph::f<&SimpleRecord::Value_> = QString {
"meh" }, sph::f<&SimpleRecord::ID_> == 0);
308 const auto updated = adapted->Select (sph::f<&SimpleRecord::ID_> == 0);
312 void OralTest::testSimpleRecordUpdateMultiExprTree ()
314 auto adapted = PrepareRecords<SimpleRecord> (
MakeDatabase ());
315 adapted->Update ((sph::f<&SimpleRecord::Value_> = QString {
"meh" }, sph::f<&SimpleRecord::ID_> = 10),
316 sph::f<&SimpleRecord::ID_> == 0);
317 const auto updated = adapted->Select (sph::f<&SimpleRecord::ID_> == 10);
321 void OralTest::testAutoPKeyRecordInsertSelect ()
323 auto adapted = PrepareRecords<AutogenPKeyRecord> (
MakeDatabase ());
324 const auto& list = adapted->Select ();
328 void OralTest::testAutoPKeyRecordInsertRvalueReturnsPKey ()
330 auto adapted = Util::oral::AdaptPtr<AutogenPKeyRecord, OralFactory> (
MakeDatabase ());
333 for (
int i = 0; i < 3; ++i)
334 ids << adapted->Insert ({ 0, QString::number (i) });
339 void OralTest::testAutoPKeyRecordInsertConstLvalueReturnsPKey ()
341 auto adapted = Util::oral::AdaptPtr<AutogenPKeyRecord, OralFactory> (
MakeDatabase ());
344 for (
int i = 0; i < 3; ++i)
345 records.push_back ({ 0, QString::number (i) });
348 for (
const auto& record : records)
349 ids << adapted->Insert (record);
354 void OralTest::testAutoPKeyRecordInsertSetsPKey ()
356 auto adapted = Util::oral::AdaptPtr<AutogenPKeyRecord, OralFactory> (
MakeDatabase ());
359 for (
int i = 0; i < 3; ++i)
360 records.push_back ({ 0, QString::number (i) });
362 for (
auto& record : records)
363 adapted->Insert (record);
368 void OralTest::testNoPKeyRecordInsertSelect ()
370 auto adapted = PrepareRecords<NoPKeyRecord> (
MakeDatabase ());
371 const auto& list = adapted->Select ();
375 void OralTest::testNonInPlaceConstructibleRecordInsertSelect ()
377 auto adapted = Util::oral::AdaptPtr<NonInPlaceConstructibleRecord, OralFactory> (
MakeDatabase ());
378 for (
int i = 0; i < 3; ++i)
379 adapted->Insert ({ i, QString::number (i), 0 });
381 const auto& list = adapted->Select ();
387 template<
typename Ex,
typename F>
388 void ShallThrow (F&&
f)
400 QCOMPARE (failed,
true);
404 void OralTest::testComplexConstraintsRecordInsertSelectDefault ()
406 auto adapted = Util::oral::AdaptPtr<ComplexConstraintsRecord, OralFactory> (
MakeDatabase ());
408 adapted->Insert ({ 0,
"first", 1, 2 });
409 ShallThrow<oral::QueryException> ([&] { adapted->Insert ({ 0,
"second", 1, 2 }); });
410 ShallThrow<oral::QueryException> ([&] { adapted->Insert ({ 0,
"first", 1, 3 }); });
411 adapted->Insert ({ 0,
"second", 1, 3 });
412 ShallThrow<oral::QueryException> ([&] { adapted->Insert ({ 0,
"first", 1, 3 }); });
414 const auto& list = adapted->Select ();
418 void OralTest::testComplexConstraintsRecordInsertSelectIgnore ()
420 auto adapted = Util::oral::AdaptPtr<ComplexConstraintsRecord, OralFactory> (
MakeDatabase ());
428 const auto& list = adapted->Select ();
432 void OralTest::testComplexConstraintsRecordInsertSelectReplace ()
434 auto adapted = Util::oral::AdaptPtr<ComplexConstraintsRecord, OralFactory> (
MakeDatabase ());
436 const auto idValueFields = lco::InsertAction::Replace::Fields<
437 &ComplexConstraintsRecord::ID_,
438 &ComplexConstraintsRecord::Value_
440 const auto weightAgeFields = lco::InsertAction::Replace::Fields<
441 &ComplexConstraintsRecord::Weight_,
442 &ComplexConstraintsRecord::Age_
444 adapted->Insert ({ 0,
"first", 1, 2 }, idValueFields);
445 adapted->Insert ({ 0,
"second", 1, 2 }, weightAgeFields);
446 adapted->Insert ({ 0,
"first", 1, 3 }, idValueFields);
447 adapted->Insert ({ 0,
"third", 1, 3 }, weightAgeFields);
448 adapted->Insert ({ 0,
"first", 1, 3 }, weightAgeFields);
450 const auto& list = adapted->Select ();
454 void OralTest::benchSimpleRecordAdapt ()
456 if constexpr (OralBench)
459 Util::oral::Adapt<SimpleRecord, OralFactory> (db);
461 QBENCHMARK { Util::oral::Adapt<SimpleRecord> (db); }
465 void OralTest::benchBaselineInsert ()
467 if constexpr (OralBench)
470 Util::oral::Adapt<SimpleRecord, OralFactory> (db);
472 QSqlQuery query { db };
473 query.prepare (
"INSERT OR IGNORE INTO SimpleRecord (ID, Value) VALUES (:id, :val);");
477 query.bindValue (
":id", 0);
478 query.bindValue (
":val",
"0");
484 void OralTest::benchSimpleRecordInsert ()
486 if constexpr (OralBench)
489 const auto& adapted = Util::oral::Adapt<SimpleRecord, OralFactory> (db);
495 void OralTest::benchBaselineUpdate ()
497 if constexpr (OralBench)
500 const auto& adapted = Util::oral::Adapt<SimpleRecord, OralFactory> (db);
501 adapted.Insert ({ 0,
"0" });
503 QSqlQuery query { db };
504 query.prepare (
"UPDATE SimpleRecord SET Value = :val WHERE Id = :id;");
508 query.bindValue (
":id", 0);
509 query.bindValue (
":val",
"1");
515 void OralTest::benchSimpleRecordUpdate ()
517 if constexpr (OralBench)
520 auto adapted = Util::oral::Adapt<SimpleRecord, OralFactory> (db);
521 adapted.Insert ({ 0,
"0" });
523 QBENCHMARK { adapted.Update ({ 0,
"1" }); }
lco::PKey< int, lco::NoAutogen > ID_
constexpr detail::AggregateType< detail::AggregateFunction::Count > count
constexpr detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, detail::MemberPtrs< Ptr > > f
Typelist< Args... > Constraints
static QString ClassName()
QSqlDatabase MakeDatabase(const QString &name=":memory:")
BOOST_FUSION_ADAPT_STRUCT(SimpleRecord, ID_, Value_) struct AutogenPKeyRecord
static struct LeechCraft::Util::oral::InsertAction::IgnoreTag Ignore