12 #include <type_traits> 15 #include <boost/preprocessor/stringize.hpp> 16 #include <boost/preprocessor/tuple.hpp> 17 #include <QStringList> 35 #ifndef ORAL_ADAPT_STRUCT 37 #define ORAL_STRING_FIELD(_, index, tuple) \ 38 if constexpr (Idx == index) \ 39 return CtString { BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(index, tuple)) }; 41 #define ORAL_GET_FIELD(_, index, tuple) \ 42 if constexpr (Idx == index) \ 43 return s.BOOST_PP_TUPLE_ELEM(index, tuple); 45 #define ORAL_GET_FIELD_INDEX_IMPL(index, sname, field) \ 47 constexpr size_t FieldIndexAccess<sname>::FieldIndex<&sname::field> () { return index; } 49 #define ORAL_GET_FIELD_INDEX(_, index, args) \ 50 ORAL_GET_FIELD_INDEX_IMPL(index, BOOST_PP_TUPLE_ELEM(0, args), BOOST_PP_TUPLE_ELEM(index, BOOST_PP_TUPLE_ELEM(1, args))) 52 #define ORAL_ADAPT_STRUCT(sname, ...) \ 53 namespace LC::Util::oral \ 56 constexpr auto SeqSize<sname> = BOOST_PP_TUPLE_SIZE((__VA_ARGS__)); \ 59 struct MemberNames<sname> \ 61 template<size_t Idx> \ 62 constexpr static auto Get () \ 64 BOOST_PP_REPEAT(BOOST_PP_TUPLE_SIZE((__VA_ARGS__)), ORAL_STRING_FIELD, (__VA_ARGS__)) \ 69 struct FieldAccess<sname> \ 71 template<size_t Idx> \ 72 constexpr static const auto& Get (const sname& s) \ 74 BOOST_PP_REPEAT(BOOST_PP_TUPLE_SIZE((__VA_ARGS__)), ORAL_GET_FIELD, (__VA_ARGS__)) \ 77 template<size_t Idx> \ 78 constexpr static auto& Get (sname& s) \ 80 BOOST_PP_REPEAT(BOOST_PP_TUPLE_SIZE((__VA_ARGS__)), ORAL_GET_FIELD, (__VA_ARGS__)) \ 85 struct FieldIndexAccess<sname> \ 88 constexpr static size_t FieldIndex (); \ 91 BOOST_PP_REPEAT(BOOST_PP_TUPLE_SIZE((__VA_ARGS__)), ORAL_GET_FIELD_INDEX, (sname, (__VA_ARGS__))) \ 102 const QSqlQuery Query_;
110 :
std::runtime_error { str }
137 template<
size_t Idx,
typename Seq>
138 constexpr decltype (
auto)
Get (const Seq& seq)
143 template<
size_t Idx,
typename Seq>
144 constexpr decltype (
auto)
Get (Seq& seq)
149 template<
typename T, CtString str>
152 if constexpr (
requires { T::template FieldNameMorpher<str> (); })
153 return T::template FieldNameMorpher<str> ();
154 else if constexpr (str.EndsWith (
'_'))
155 return str.template Chop<1> ();
160 template<
typename Seq,
int Idx>
164 return MorphFieldName<Seq, str> ();
168 constexpr
auto SeqIndices = std::make_index_sequence<SeqSize<S>> {};
171 constexpr
auto FieldNames = []<
size_t... Ix> (std::index_sequence<Ix...>) constexpr
173 return std::tuple { GetFieldName<S, Ix> ()... };
177 constexpr
auto BoundFieldNames = []<
size_t... Ix> (std::index_sequence<Ix...>) constexpr
179 return std::tuple { (
":" + GetFieldName<S, Ix> ())... };
185 return std::tuple { (S::ClassName +
"." + GetFieldName<S, Ix> ())... };
199 return GetFieldName<S, FieldIndex<Ptr> ()> ();
206 return S::ClassName +
"." + GetFieldName<S, FieldIndex<Ptr> ()> ();
216 template<
typename ImplFactory,
typename T,
typename =
void>
223 else if constexpr (std::is_same_v<T, double>)
225 else if constexpr (std::is_same_v<T, QString> || std::is_same_v<T, QDateTime> || std::is_same_v<T, QUrl>)
227 else if constexpr (std::is_same_v<T, QByteArray>)
228 return ImplFactory::TypeLits::Binary;
229 else if constexpr (detail::TypeNameCustomized<T>)
231 else if constexpr (detail::BaseTypeCustomized<T>)
234 static_assert (std::is_same_v<T, struct Dummy>,
"Unsupported type");
238 template<
typename ImplFactory,
typename T>
244 template<
typename ImplFactory,
typename T>
250 template<
typename ImplFactory,
typename T,
typename...
Tags>
256 template<
typename ImplFactory,
typename...
Tags>
262 template<
typename ImplFactory, auto Ptr>
269 " REFERENCES " + className +
" (" + detail::GetFieldNamePtr<Ptr> () +
") ON DELETE CASCADE";
273 template<
typename T,
typename =
void>
278 if constexpr (std::is_same_v<T, QDateTime>)
279 return t.toString (Qt::ISODate);
280 else if constexpr (std::is_enum_v<T>)
281 return static_cast<qint64
> (t);
284 else if constexpr (detail::TypeNameCustomized<T>)
285 return t.ToVariant ();
286 else if constexpr (detail::BaseTypeCustomized<T>)
293 template<
typename T,
typename =
void>
298 if constexpr (std::is_same_v<T, QDateTime>)
299 return QDateTime::fromString (var.toString (), Qt::ISODate);
300 else if constexpr (std::is_enum_v<T>)
301 return static_cast<T
> (var.value<qint64> ());
304 else if constexpr (detail::TypeNameCustomized<T>)
305 return T::FromVariant (var);
306 else if constexpr (detail::BaseTypeCustomized<T>)
309 return var.value<T> ();
315 template<
typename Seq,
int Idx>
316 using ValueAtC_t = std::decay_t<decltype (Get<Idx> (std::declval<Seq> ()))>;
321 template<
typename U,
typename...
Tags>
330 template<
size_t Ix,
typename Seq>
331 void BindAtIndex (
const Seq& seq, QSqlQuery& query,
bool bindPrimaryKey)
334 query.bindValue (
ToString<std::get<Ix> (BoundFieldNames<Seq>)> (),
ToVariantF (Get<Ix> (seq)));
337 template<
typename Seq>
338 auto DoInsert (
const Seq& seq, QSqlQuery& insertQuery,
bool bindPrimaryKey)
340 [&]<
size_t... Ix> (std::index_sequence<Ix...>)
342 (BindAtIndex<Ix> (seq, insertQuery, bindPrimaryKey), ...);
345 if (!insertQuery.exec ())
347 qCritical () <<
"insert query execution failed";
349 throw QueryException (
"insert query execution failed", insertQuery);
353 template<
typename Seq>
356 auto run = []<
size_t... Idxes> (std::index_sequence<Idxes...>)
362 return run (SeqIndices<Seq>);
365 template<
typename Seq>
368 const auto idx = PKeyIndexUnsafe<Seq> ();
369 static_assert (idx >= 0);
373 template<
typename Seq>
376 template<
typename Seq>
377 concept
HasPKey = PKeyIndexUnsafe<Seq> () >= 0;
379 template<
typename Seq>
382 if constexpr (HasPKey<Seq>)
388 template<
typename Seq>
391 return std::tuple { detail::GetFieldName<Seq, PKeyIndex_v<Seq>> () };
394 template<
typename Seq,
auto... Ptrs>
397 return std::tuple { std::get<FieldIndex<Ptrs> ()> (FieldNames<Seq>)... };
400 template<
typename Seq>
403 const QSqlDatabase DB_;
404 constexpr
static bool HasAutogen_ = HasAutogenPKey<Seq> ();
411 template<
typename Action = InsertAction::DefaultTag>
414 return Run<SQLite::ImplFactory> (t, action);
417 template<
typename ImplFactory>
420 return Run<ImplFactory> (t, action);
423 template<
typename Action = InsertAction::DefaultTag>
426 return Run<SQLite::ImplFactory> (t, action);
429 template<
typename ImplFactory>
430 auto operator() (ImplFactory,
const Seq& t,
auto action)
const 432 return Run<ImplFactory> (t, action);
435 template<
typename ImplFactory,
typename Action>
436 constexpr
static auto MakeInsertSuffix (Action action)
438 if constexpr (std::is_same_v<Action, InsertAction::DefaultTag> || std::is_same_v<Action, InsertAction::IgnoreTag>)
439 return ImplFactory::GetInsertSuffix (action);
442 ExtractConflictingFields<Seq> (action),
446 template<
typename ImplFactory>
447 constexpr
static auto MakeQueryForAction (
auto action)
449 return ImplFactory::GetInsertPrefix (action) +
450 " INTO " + Seq::ClassName +
451 " (" +
JoinTup (FieldNames<Seq>,
", ") +
") " +
452 "VALUES (" +
JoinTup (BoundFieldNames<Seq>,
", ") +
") " +
453 MakeInsertSuffix<ImplFactory> (action);
456 template<
typename ImplFactory,
typename T>
457 auto Run (T& t,
auto action)
const 459 QSqlQuery query { DB_ };
460 constexpr
auto queryText = MakeQueryForAction<ImplFactory> (action);
461 query.prepare (ToString<queryText> ());
465 if constexpr (HasAutogen_)
467 constexpr
auto index = PKeyIndex_v<Seq>;
469 const auto& lastId = FromVariant<ValueAtC_t<Seq, index>> {} (query.lastInsertId ());
470 if constexpr (!std::is_const_v<T>)
471 Get<index> (t) = lastId;
478 template<
typename Seq>
486 if constexpr (HasPKey<Seq>)
488 constexpr
auto index = PKeyIndex_v<Seq>;
489 constexpr
auto del =
"DELETE FROM " + Seq::ClassName +
490 " WHERE " + std::get<index> (FieldNames<Seq>) +
" = ?";
497 constexpr
auto index = PKeyIndex_v<Seq>;
504 template<
typename T,
size_t...
Indices>
537 template<ExprType Type>
559 static_assert (std::is_same_v<struct D1, ExprType>,
"Invalid expression type");
584 template<ExprType Type,
typename Seq,
typename L,
typename R>
591 return requires (LReal l, RReal r) { l == r; };
597 template<ExprType Type,
typename L =
void,
typename R =
void>
603 template<ExprType Type,
typename L,
typename R>
606 template<
typename L,
typename R>
618 template<
typename Seq, CtString S>
624 return L::template
ToSql<Seq, S +
"l"> () +
", " + R::template ToSql<Seq, S + "r"> ();
627 template<
typename Seq, CtString S>
630 Left_.template
BindValues<Seq, S +
"l"> (query);
631 Right_.template
BindValues<Seq, S +
"r"> (query);
634 template<
typename OL,
typename OR>
641 template<ExprType Type,
typename L,
typename R>
653 template<
typename Seq, CtString S>
656 static_assert (Typecheck<Type, Seq, L, R> (),
657 "Incompatible types passed to a relational operator.");
659 return L::template
ToSql<Seq, S +
"l"> () +
" " + TypeToSql<Type> () +
" " + R::template
ToSql<Seq, S +
"r"> ();
662 template<
typename Seq, CtString S>
665 Left_.template
BindValues<Seq, S +
"l"> (query);
666 Right_.template
BindValues<Seq, S +
"r"> (query);
672 return std::tuple_cat (L::template AdditionalTables<T> (), R::template AdditionalTables<T> ());
678 return L::template HasAdditionalTables<T> () || R::template HasAdditionalTables<T> ();
695 template<
typename, CtString S>
698 return ":bound_" + S;
701 template<
typename Seq, CtString S>
704 constexpr
auto varName = ToSql<Seq, S> ();
705 query.bindValue (ToString<varName> (),
ToVariantF (Data_));
711 return std::tuple {};
730 template<
auto... Ptr>
741 template<
typename Seq, CtString S>
747 template<
typename Seq, CtString S>
754 return detail::GetFieldNamePtr<Ptr> ();
761 if constexpr (std::is_same_v<Seq, T>)
762 return std::tuple {};
764 return std::tuple { Seq::ClassName };
770 return !std::is_same_v<MemberPtrStruct_t<Ptr>, T>;
773 constexpr
auto operator= (
const ExpectedType_t& r)
const noexcept 783 template<
typename, CtString>
789 template<
typename, CtString>
803 template<ExprType Type,
typename L,
typename R>
811 template<
typename L,
typename R>
821 template<
typename L,
typename R>
824 template<
typename L,
typename R,
typename = EnableRelOp_t<L, R>>
827 return MakeExprTree<ExprType::Less> (left, right);
830 template<
typename L,
typename R,
typename = EnableRelOp_t<L, R>>
833 return MakeExprTree<ExprType::Greater> (left, right);
836 template<
typename L,
typename R,
typename = EnableRelOp_t<L, R>>
839 return MakeExprTree<ExprType::Equal> (left, right);
842 template<
typename L,
typename R,
typename = EnableRelOp_t<L, R>>
845 return MakeExprTree<ExprType::Neq> (left, right);
848 template<ExprType Op>
859 template<
typename L, ExprType Op>
865 template<
typename L, ExprType Op>
871 template<
typename L, ExprType Op,
typename R>
874 return MakeExprTree<Op> (left.Left_, right);
877 template<
typename L,
typename R,
typename = EnableRelOp_t<L, R>>
880 return MakeExprTree<ExprType::And> (left, right);
883 template<
typename L,
typename R,
typename = EnableRelOp_t<L, R>>
886 return MakeExprTree<ExprType::Or> (left, right);
889 template<CtString BindPrefix,
typename Seq,
typename Tree>
892 return Tree::template ToSql<Seq, BindPrefix> ();
895 template<CtString BindPrefix,
typename Seq,
typename Tree>
898 tree.template BindValues<Seq, BindPrefix> (query);
908 template<AggregateFunction, auto Ptr>
915 template<
typename... MemberDirectionList>
918 template<
auto... Ptrs>
923 template<
typename L,
typename R>
932 template<AggregateFunction Fun, auto Ptr>
935 template<
auto... Ptrs>
938 template<
typename L,
typename R>
941 template<
typename L,
typename R,
typename = std::enable_if_t<IsSelector<L> {} && IsSelector<R> {}>>
953 template<
auto... Ptrs>
958 template<
auto... Ptrs>
961 template<
auto... Ptrs>
964 template<auto Ptr = detail::CountAllPtr>
974 template<
typename... Orders>
977 template<
auto... Ptrs>
1001 return MemberFromVariant<Ptr> (q.value (startIdx));
1004 template<
auto... Ptrs>
1007 if constexpr (
sizeof... (Ptrs) == 1)
1010 return [&]<
size_t... Ix> (std::index_sequence<Ix...>)
1012 return std::tuple { MemberFromVariant<Ptrs> (q.value (startIdx + Ix))... };
1013 } (std::make_index_sequence<
sizeof... (Ptrs)> {});
1023 template<
size_t RepIdx,
size_t TupIdx,
typename Tuple,
typename NewType>
1026 if constexpr (RepIdx == TupIdx)
1027 return std::forward<NewType> (arg);
1029 return std::get<TupIdx> (tuple);
1032 template<
size_t RepIdx,
typename NewType,
typename Tuple,
size_t... TupIdxs>
1037 GetReplaceTupleElem<RepIdx, TupIdxs> (std::forward<Tuple> (tuple), std::forward<NewType> (arg))...
1041 template<
size_t RepIdx,
typename NewType,
typename... TupleArgs>
1044 return ReplaceTupleElemImpl<RepIdx> (std::move (tuple),
1045 std::forward<NewType> (arg),
1046 std::index_sequence_for<TupleArgs...> {});
1049 template<
typename Seq,
typename T>
1055 template<
typename Seq,
typename... Args>
1061 template<
typename Seq>
1064 constexpr
static int Value = SeqSize<Seq>;
1067 template<
typename... LArgs,
typename... RArgs>
1070 return std::tuple_cat (std::move (left), std::move (right));
1073 template<
typename... LArgs,
typename R>
1076 return std::tuple_cat (std::move (left), std::tuple { right });
1079 template<
typename L,
typename... RArgs>
1082 return std::tuple_cat (std::tuple { left }, std::move (right));
1085 template<
typename L,
typename R>
1088 return std::tuple { left, right };
1097 template<ResultBehaviour ResultBehaviour,
typename ResList>
1101 return std::forward<ResList> (list);
1103 return list.value (0);
1106 template<
typename F,
typename R>
1114 template<
typename F,
typename R>
1119 const QSqlDatabase DB_;
1127 auto&& binder)
const 1129 QSqlQuery query { DB_ };
1130 query.prepare (queryStr);
1135 qCritical () <<
"select query execution failed";
1137 throw QueryException (
"fetch query execution failed", std::make_shared<QSqlQuery> (query));
1144 template<
typename L,
typename O>
1147 if constexpr (std::is_same_v<L, LimitNone>)
1149 static_assert (std::is_same_v<O, OffsetNone>,
"LIMIT-less queries currently cannot have OFFSET");
1153 return " LIMIT :limit "_ct +
1156 if constexpr (std::is_same_v<O, OffsetNone>)
1159 return " OFFSET :offset"_ct;
1163 template<
typename L,
typename O>
1166 if constexpr (!std::is_same_v<std::decay_t<L>,
LimitNone>)
1167 query.bindValue (
":limit", qulonglong { limit.Count });
1168 if constexpr (!std::is_same_v<std::decay_t<O>,
OffsetNone>)
1169 query.bindValue (
":offset", qulonglong { offset.Count });
1172 template<
typename T,
typename Selector>
1179 template<
typename T>
1182 constexpr
inline static auto Fields =
JoinTup (QualifiedFieldNames<T>,
", "_ct);
1186 return InitializeFromQuery<T> (q, SeqIndices<T>, startIdx);
1190 template<
typename T,
auto... Ptrs>
1194 template<
size_t... Ixs>
1195 constexpr
static auto SelectFields ()
1197 return std::tuple { std::get<Ixs> (QualifiedFieldNames<T>)... };
1200 constexpr
inline static auto Fields =
JoinTup (SelectFields<FieldIndex<Ptrs> ()...> (),
", ");
1208 template<
typename T>
1211 constexpr
inline static auto Fields =
"count(1)"_ct;
1215 return q.value (startIdx).toLongLong ();
1219 template<
typename T, auto Ptr>
1222 constexpr
inline static auto Fields =
"count(" + GetQualifiedFieldNamePtr<Ptr> () +
")";
1226 return q.value (startIdx).toLongLong ();
1230 template<CtString Aggregate,
typename T, auto Ptr>
1233 constexpr
inline static auto Fields = Aggregate +
"(" + GetQualifiedFieldNamePtr<Ptr> () +
")";
1237 return MakeIndexedQueryHandler<Ptr> (q, startIdx);
1241 template<
typename T, auto Ptr>
1244 template<
typename T, auto Ptr>
1254 template<
typename T,
typename L,
typename R>
1260 constexpr
inline static auto ResultBehaviour_v =
CombineBehaviour (HL::ResultBehaviour_v, HR::ResultBehaviour_v);
1262 constexpr
inline static auto Fields = HL::Fields +
", " + HR::Fields;
1267 return Combine (HL::Initializer (q, startIdx), HR::Initializer (q, startIdx + shift));
1271 template<
typename T, SelectBehaviour SelectBehaviour>
1274 template<
typename ParamsTuple>
1278 ParamsTuple Params_;
1280 template<
typename NewTuple>
1281 constexpr
auto RepTuple (NewTuple&& tuple)
noexcept 1283 return Builder<NewTuple> { W_, tuple };
1286 template<
typename U>
1287 constexpr
auto Select (U&& selector) &&
noexcept 1289 return RepTuple (ReplaceTupleElem<0> (std::move (Params_), std::forward<U> (selector)));
1292 template<
typename U>
1293 constexpr
auto Where (U&& tree) &&
noexcept 1295 return RepTuple (ReplaceTupleElem<1> (std::move (Params_), std::forward<U> (tree)));
1298 template<
typename U>
1299 constexpr
auto Order (U&& order) &&
noexcept 1301 return RepTuple (ReplaceTupleElem<2> (std::move (Params_), std::forward<U> (order)));
1304 template<
typename U>
1305 constexpr
auto Group (U&& group) &&
noexcept 1307 return RepTuple (ReplaceTupleElem<3> (std::move (Params_), std::forward<U> (group)));
1312 return RepTuple (ReplaceTupleElem<4> (std::move (Params_), limit));
1317 return std::move (*this).Limit (
oral::Limit { limit });
1322 return RepTuple (ReplaceTupleElem<5> (std::move (Params_), offset));
1327 return std::move (*this).Offset (
oral::Offset { offset });
1332 return std::apply (W_, Params_);
1335 template<
auto... Ptrs>
1336 constexpr
auto Group () &&
noexcept 1346 std::tuple defParams
1355 return Builder<decltype (defParams)> { *
this, defParams };
1363 template<
typename Single>
1366 if constexpr (
IsExprTree<std::decay_t<Single>> {})
1367 return (*
this) (
SelectWhole {}, std::forward<Single> (single));
1384 Limit limit = LimitNone {},
1385 Offset offset = OffsetNone {})
const 1387 using TreeType_t = ExprTree<Type, L, R>;
1390 constexpr
auto wherePrefix = [where]
1392 if constexpr (where.IsEmpty ())
1395 return " WHERE "_ct;
1397 constexpr
auto from = BuildFromClause<TreeType_t> ();
1398 const auto binder = [&] (QSqlQuery& query)
1403 using HS = HandleSelector<T, Selector>;
1405 constexpr
auto query =
"SELECT " + HS::Fields +
1407 wherePrefix + where +
1408 HandleOrder (std::forward<Order> (order)) +
1409 HandleGroup (std::forward<Group> (group)) +
1410 LimitOffsetToString<Limit, Offset> ();
1411 auto selectResult = Select<HS> (ToString<query> (),
1413 return HandleResultBehaviour<HS::ResultBehaviour_v> (std::move (selectResult));
1416 template<
typename HS,
typename Binder>
1417 auto Select (
const QString& queryStr,
1418 Binder&& binder)
const 1420 auto query =
RunQuery (queryStr, binder);
1425 while (query.next ())
1426 result << HS::Initializer (query, 0);
1431 using RetType_t = std::optional<decltype (HS::Initializer (query, 0))>;
1432 return query.next () ?
1433 RetType_t { HS::Initializer (query, 0) } :
1438 template<
typename Tree>
1439 consteval
static auto BuildFromClause ()
noexcept 1441 if constexpr (Tree::template HasAdditionalTables<T> ())
1442 return T::ClassName + ", " +
JoinTup (
Nub<Tree::template AdditionalTables<T>> (), ", ");
1444 return T::ClassName;
1447 constexpr static auto HandleOrder (OrderNone)
noexcept 1452 template<
auto... Ptrs>
1453 constexpr
static auto HandleSuborder (sph::asc<Ptrs...>)
noexcept 1455 return std::tuple { (GetQualifiedFieldNamePtr<Ptrs> () +
" ASC")... };
1458 template<
auto... Ptrs>
1459 constexpr
static auto HandleSuborder (sph::desc<Ptrs...>)
noexcept 1461 return std::tuple { (GetQualifiedFieldNamePtr<Ptrs> () +
" DESC")... };
1464 template<
typename... Suborders>
1465 constexpr
static auto HandleOrder (OrderBy<Suborders...>)
noexcept 1467 return " ORDER BY " +
JoinTup (std::tuple_cat (HandleSuborder (Suborders {})...),
", ");
1470 constexpr
static auto HandleGroup (GroupNone)
noexcept 1475 template<
auto... Ptrs>
1476 constexpr
static auto HandleGroup (GroupBy<Ptrs...>)
noexcept 1478 return " GROUP BY " +
Join (
", ", GetQualifiedFieldNamePtr<Ptrs> ()...);
1482 template<
typename T>
1485 const QSqlDatabase DB_;
1492 template<ExprType Type,
typename L,
typename R>
1497 constexpr
auto selectAll =
"DELETE FROM " + T::ClassName +
" WHERE " + where;
1499 QSqlQuery query { DB_ };
1500 query.prepare (ToString<selectAll> ());
1506 template<
typename T>
1509 const QSqlDatabase DB_;
1512 QSqlQuery UpdateByPKey_ { DB_ };
1517 if constexpr (HasPKey<T>)
1519 constexpr
auto pkeyIdx = PKeyIndex_v<T>;
1520 constexpr
auto statements =
ZipWith (FieldNames<T>,
" = ", BoundFieldNames<T>);
1521 constexpr
auto update =
"UPDATE " + T::ClassName +
1522 " SET " +
JoinTup (statements,
", ") +
1523 " WHERE " + std::get<pkeyIdx> (statements);
1524 UpdateByPKey_.prepare (ToString<update> ());
1530 DoInsert (seq, UpdateByPKey_,
true);
1533 template<
typename SL,
typename SR, ExprType WType,
typename WL,
typename WR>
1537 "joins in update statements are not supported by SQL");
1542 constexpr
auto update =
"UPDATE " + T::ClassName +
1543 " SET " + setClause +
1544 " WHERE " + whereClause;
1546 QSqlQuery query { DB_ };
1547 query.prepare (ToString<update> ());
1552 qCritical () <<
"update query execution failed";
1554 throw QueryException (
"update query execution failed", std::make_shared<QSqlQuery> (query));
1557 return query.numRowsAffected ();
1561 template<
typename T,
size_t... Fields>
1564 return "UNIQUE (" +
Join (
", ", std::get<Fields> (FieldNames<T>)...) +
")";
1567 template<
typename T,
size_t... Fields>
1570 return "PRIMARY KEY (" +
Join (
", ", std::get<Fields> (FieldNames<T>)...) +
")";
1573 template<
typename T>
1578 return []<
typename... Args> (
Constraints<Args...>)
1580 return std::tuple { ExtractConstraintFields<T> (Args {})... };
1584 return std::tuple<> {};
1587 template<
typename ImplFactory,
typename T,
size_t...
Indices>
1593 template<auto Name,
typename ImplFactory,
typename T>
1596 constexpr
auto types = GetTypes<ImplFactory, T> (SeqIndices<T>);
1598 constexpr
auto constraints = GetConstraintsStrings<T> ();
1599 constexpr
auto constraintsStr = [&]
1601 if constexpr (!std::tuple_size_v<decltype (constraints)>)
1604 return ", " +
JoinTup (constraints,
", ");
1607 constexpr
auto statements =
ZipWith (FieldNames<T>,
" ", types);
1608 return "CREATE TABLE " +
1616 template<
typename ImplFactory,
typename T>
1619 return AdaptCreateTableNamed<T::ClassName, ImplFactory, T> ();
1623 template<
typename T>
1637 template<
typename T,
typename ImplFactory = detail::SQLite::ImplFactory>
1640 if (!db.tables ().contains (ToString<T::ClassName> (), Qt::CaseInsensitive))
1642 constexpr
auto query = detail::AdaptCreateTable<ImplFactory, T> ();
1658 template<
typename T>
1661 template<
typename T,
typename ImplFactory = SQLiteImplFactory>
1664 return std::make_unique<ObjectInfo<T>> (Adapt<T, ImplFactory> (db));
1667 template<
typename ImplFactory,
typename... Ts>
1670 ((objects = AdaptPtr<Ts, ImplFactory> (db)), ...);
DeleteByFieldsWrapper(const QSqlDatabase &db) noexcept
constexpr bool IsRelational(ExprType type) noexcept
constexpr detail::AggregateType< detail::AggregateFunction::Count, Ptr > count
detail::DeleteByFieldsWrapper< T > DeleteBy
void operator()(const Seq &seq) requires HasPKey< Seq >
constexpr detail::OrderBy< Orders... > OrderBy
constexpr auto HasAutogenPKey() noexcept
constexpr auto LimitOffsetToString() noexcept
constexpr CountAll * CountAllPtr
SelectWrapperCommon(const QSqlDatabase &db) noexcept
constexpr auto Join(auto &&) noexcept
static constexpr auto ToSql() noexcept
auto MemberFromVariant(const QVariant &var) noexcept
void AdaptPtrs(const QSqlDatabase &db, ObjectInfo_ptr< Ts > &... objects)
constexpr detail::AggregateType< detail::AggregateFunction::Max, Ptr > max
static auto Initializer(const QSqlQuery &q, int startIdx)
constexpr auto JoinTup(auto &&stringsTuple, auto &&sep) noexcept
constexpr detail::GroupBy< Ptrs... > GroupBy
constexpr auto ExprTreeToSql() noexcept
static auto Initializer(const QSqlQuery &q, int startIdx)
constexpr size_t FieldIndex() noexcept
static auto Initializer(const QSqlQuery &q, int startIdx)
void BindExprTree(const Tree &tree, QSqlQuery &query)
static UTIL_DB_API void DumpError(const QSqlError &error)
Dumps the error to the qWarning() stream.
SelectorUnion< L, R > operator+(L, R) noexcept
void BindLimitOffset(QSqlQuery &query, L limit, O offset) noexcept
static auto Initializer(const QSqlQuery &q, int startIdx) noexcept
T operator()(const QVariant &var) const noexcept
HandleSelectorResult(QString, F, R) -> HandleSelectorResult< F, R >
QVariant operator()(const T &t) const noexcept
constexpr auto GetQualifiedFieldNamePtr() noexcept
auto Build() const noexcept
constexpr auto operator()() const noexcept
Q_DECL_IMPORT const QString Count
The new total event count (int).
MemberTypeType_t< decltype(Ptr)> MemberPtrType_t
~QueryException() noexcept=default
T InitializeFromQuery(const QSqlQuery &q, std::index_sequence< Indices... >, int startIdx) noexcept
static constexpr bool HasAdditionalTables() noexcept
static constexpr auto Fields
auto operator<(const L &left, const R &right) noexcept
Q_DECL_IMPORT const QString Tags
consteval int PKeyIndex()
std::unique_ptr< ObjectInfo< T > > ObjectInfo_ptr
QueryException(const std::string &str, const QSqlQuery_ptr &q)
auto DoInsert(const Seq &seq, QSqlQuery &insertQuery, bool bindPrimaryKey)
constexpr auto TypeToSql() noexcept
std::shared_ptr< QSqlQuery > QSqlQuery_ptr
auto operator!=(const L &left, const R &right) noexcept
constexpr auto GetTypes(std::index_sequence< Indices... >) noexcept
auto MakeExprTree(const L &left, const R &right) noexcept
consteval auto GetFieldName()
constexpr auto ExtractConstraintFields(UniqueSubset< Fields... >)
constexpr detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, detail::MemberPtrs< Ptr > > f
constexpr auto ReplaceTupleElemImpl(Tuple &&tuple, NewType &&arg, std::index_sequence< TupIdxs... >) noexcept
void BindValues(QSqlQuery &query) const noexcept
static constexpr auto ToSql() noexcept
auto operator &&(const L &left, const R &right) noexcept
constexpr auto ExtractConflictingFields(InsertAction::Replace::PKeyType)
static constexpr bool HasAdditionalTables() noexcept
Type
Describes the various types of XDG .desktop files.
static constexpr auto ResultBehaviour_v
constexpr auto SeqIndices
constexpr bool EitherIsExprTree() noexcept
detail::AdaptUpdate< T > Update
constexpr auto GetFieldNamePtr() noexcept
constexpr auto AdaptCreateTableNamed() noexcept
requires(Tup1Size==Tup2Size) const expr auto ZipWith(Tup1 &&tup1
static auto Initializer(const QSqlQuery &q, int startIdx) noexcept
consteval auto MorphFieldName()
static constexpr bool HasAdditionalTables() noexcept
auto operator()(Seq &t, Action action={}) const
auto operator==(const L &left, const R &right) noexcept
constexpr int PKeyIndex_v
ObjectInfo_ptr< T > AdaptPtr(const QSqlDatabase &db)
static constexpr auto AdditionalTables() noexcept
consteval int PKeyIndexUnsafe()
A somewhat "strong" typedef.
typename AsTypelist< T >::Result_t AsTypelist_t
void BindAtIndex(const Seq &seq, QSqlQuery &query, bool bindPrimaryKey)
static constexpr auto ToSql() noexcept
auto operator>(const L &left, const R &right) noexcept
void BindValues(QSqlQuery &query) const noexcept
static constexpr auto ToSql() noexcept
AdaptUpdate(const QSqlDatabase &db) noexcept
detail::AdaptInsert< T > Insert
std::decay_t< decltype(Get< Idx >(std::declval< Seq >()))> ValueAtC_t
static constexpr auto AdditionalTables() noexcept
void BindValues(QSqlQuery &) const noexcept
static constexpr int Value
const QSqlQuery & GetQuery() const
decltype(auto) constexpr Get(const Seq &seq)
constexpr auto ReplaceTupleElem(std::tuple< TupleArgs... > &&tuple, NewType &&arg) noexcept
detail::SelectWrapper< T, detail::SelectBehaviour::Some > Select
auto Combine(std::tuple< LArgs... > &&left, std::tuple< RArgs... > &&right) noexcept
constexpr detail::InfixBinary< detail::ExprType::Like > like
auto Tup2 &&tup2 noexcept
decltype(auto) HandleResultBehaviour(ResList &&list) noexcept
concept TypeNameCustomized
constexpr detail::MemberPtrs< Ptrs... > fields
static constexpr auto ResultBehaviour_v
QSqlQuery RunTextQuery(const QSqlDatabase &db, const QString &text)
Runs the given query text on the given db.
constexpr auto operator,(const AssignList< OL, OR > &tail) noexcept
constexpr detail::AggregateType< detail::AggregateFunction::Min, Ptr > min
constexpr auto AsLeafData(const T &node) noexcept
typename std::conditional_t< IsIndirect< T > {}, T, WrapDirect< T > >::value_type UnwrapIndirect_t
MemberTypeStruct_t< decltype(Ptr)> MemberPtrStruct_t
static auto Initializer(const QSqlQuery &q, int startIdx) noexcept
constexpr ExprTree(const L &l, const R &r) noexcept
constexpr auto FieldNames
ExpectedType_t ValueType_t
ObjectInfo< T > Adapt(const QSqlDatabase &db)
decltype(auto) constexpr GetReplaceTupleElem(Tuple &&tuple, NewType &&arg) noexcept
detail::SelectWrapper< T, detail::SelectBehaviour::One > SelectOne
auto RunQuery(const QString &queryStr, auto &&binder) const
void BindValues(QSqlQuery &) const noexcept
constexpr detail::SelectWhole all
constexpr AssignList(const L &l, const R &r) noexcept
auto ZipWith(const Container< T1 > &c1, const Container< T2 > &c2, F f) -> WrapType_t< Container< std::decay_t< std::result_of_t< F(T1, T2)>>>>
Typelist< Args... > Constraints
std::enable_if_t< EitherIsExprTree< L, R >()> EnableRelOp_t
auto operator||(const L &left, const R &right) noexcept
constexpr auto GetConstraintsStrings() noexcept
constexpr ExprTree(const T &t) noexcept
detail::AdaptDelete< T > Delete
constexpr auto QualifiedFieldNames
QueryException(const std::string &str, const QSqlQuery &q)
auto operator|(const L &left, InfixBinary< Op >) noexcept
constexpr auto BoundFieldNames
static constexpr auto GetFieldName() noexcept
void BindValues(QSqlQuery &query) const noexcept
static constexpr auto ToSql() noexcept
static constexpr bool HasAdditionalTables() noexcept
constexpr auto CombineBehaviour(ResultBehaviour l, ResultBehaviour r) noexcept
auto MakeIndexedQueryHandler(const QSqlQuery &q, int startIdx=0) noexcept
constexpr auto AdaptCreateTable() noexcept
std::tuple_element_t< 0, detail::CallTypeGetter_t< F > > RetType_t
static constexpr auto AdditionalTables() noexcept
QVariant ToVariantF(const T &t) noexcept
concept BaseTypeCustomized
constexpr auto ConstTrueTree_v
AdaptDelete(const QSqlDatabase &db) noexcept
AdaptInsert(const QSqlDatabase &db) noexcept
constexpr bool Typecheck()