33 #include <type_traits> 36 #include <boost/fusion/include/for_each.hpp> 37 #include <boost/fusion/include/fold.hpp> 38 #include <boost/fusion/include/filter_if.hpp> 39 #include <boost/fusion/container/vector.hpp> 40 #include <boost/fusion/include/vector.hpp> 41 #include <boost/fusion/include/transform.hpp> 42 #include <boost/fusion/include/zip.hpp> 43 #include <boost/fusion/container/generation/make_vector.hpp> 44 #include <QStringList> 80 :
std::runtime_error (str)
106 if constexpr (IsDetected_v<MorpherDetector, T>)
107 return T::FieldNameMorpher (str);
110 if (str.endsWith (
'_'))
116 template<
typename Seq,
int Idx>
119 return MorphFieldName<Seq> (boost::fusion::extension::struct_member_name<Seq, Idx>::call ());
123 constexpr
auto SeqSize = boost::fusion::result_of::size<S>::type::value;
126 constexpr
auto SeqIndices = std::make_index_sequence<SeqSize<S>> {};
133 return Run (SeqIndices<S>);
136 template<
size_t... Vals>
137 QStringList Run (std::index_sequence<Vals...>)
const noexcept
139 return { GetFieldName<S, Vals> ()... };
149 static constexpr
auto Ptr () noexcept
155 static constexpr
auto Index () noexcept
157 return &boost::fusion::at_c<Idx> (
Obj_);
161 template<auto Ptr,
size_t Idx = 0>
166 if constexpr (Idx == SeqSize<S>)
172 if constexpr (std::is_same_v<decltype (direct), decltype (indexed)>)
174 if (indexed == direct)
178 return FieldIndex<Ptr, Idx + 1> ();
186 return GetFieldName<S, FieldIndex<Ptr> ()> ();
193 return S::ClassName () +
"." + GetFieldName<S, FieldIndex<Ptr> ()> ();
209 template<
typename ImplFactory,
typename T,
typename =
void>
216 else if constexpr (std::is_same_v<T, double>)
218 else if constexpr (std::is_same_v<T, QString> || std::is_same_v<T, QDateTime> || std::is_same_v<T, QUrl>)
220 else if constexpr (std::is_same_v<T, QByteArray>)
221 return ImplFactory::TypeLits::Binary;
222 else if constexpr (detail::TypeNameCustomized<T>)
224 else if constexpr (detail::BaseTypeCustomized<T>)
227 static_assert (std::is_same_v<T, struct Dummy>,
"Unsupported type");
231 template<
typename ImplFactory,
typename T>
237 template<
typename ImplFactory,
typename T>
243 template<
typename ImplFactory,
typename T,
typename... Tags>
249 template<
typename ImplFactory,
typename... Tags>
252 QString
operator() () const noexcept {
return ImplFactory::TypeLits::IntAutoincrement; }
255 template<
typename ImplFactory, auto Ptr>
262 " REFERENCES " + className +
" (" + detail::GetFieldNamePtr<Ptr> () +
") ON DELETE CASCADE";
266 template<
typename T,
typename =
void>
271 if constexpr (std::is_same_v<T, QDateTime>)
272 return t.toString (Qt::ISODate);
273 else if constexpr (std::is_enum_v<T>)
274 return static_cast<qint64
> (t);
277 else if constexpr (detail::TypeNameCustomized<T>)
278 return t.ToVariant ();
279 else if constexpr (detail::BaseTypeCustomized<T>)
286 template<
typename T,
typename =
void>
291 if constexpr (std::is_same_v<T, QDateTime>)
292 return QDateTime::fromString (var.toString (), Qt::ISODate);
293 else if constexpr (std::is_enum_v<T>)
294 return static_cast<T
> (var.value<qint64> ());
297 else if constexpr (detail::TypeNameCustomized<T>)
298 return T::FromVariant (var);
299 else if constexpr (detail::BaseTypeCustomized<T>)
302 return var.value<T> ();
311 template<
typename U,
typename... Tags>
323 return [data, insertQuery, bindPrimaryKey] (
const T& t)
325 boost::fusion::fold (t, data.BoundFields_.begin (),
326 [&] (
auto pos,
const auto& elem)
328 using Elem = std::decay_t<decltype (elem)>;
330 insertQuery->bindValue (*pos++,
ToVariantF (elem));
334 if (!insertQuery->exec ())
337 throw QueryException (
"insert query execution failed", insertQuery);
342 template<
typename Seq,
int Idx>
343 using ValueAtC_t =
typename boost::fusion::result_of::value_at_c<Seq, Idx>::type;
345 template<
typename Seq,
typename Idx>
346 using ValueAt_t =
typename boost::fusion::result_of::value_at<Seq, Idx>::type;
348 template<
typename Seq,
typename MemberIdx = boost::mpl::
int_<0>>
351 static_assert ((boost::fusion::result_of::size<Seq>::value) != (MemberIdx::value),
352 "Primary key not found");
367 template<
typename Seq>
370 template<
typename Seq>
371 constexpr
auto HasPKey = IsDetected_v<FindPKeyDetector, Seq>;
373 template<
typename Seq>
376 if constexpr (HasPKey<Seq>)
386 const auto& qualified =
Util::Map (
fields, [&table] (
const QString& field) {
return table +
"." + field; });
387 const auto& boundFields =
Util::Map (
fields, [] (
const QString& str) {
return ':' + str; });
389 return { table,
fields, qualified, boundFields };
395 static CachedFieldsData result = BuildCachedFieldsData<T> (T::ClassName ());
399 template<
typename Seq>
402 const QSqlDatabase DB_;
405 constexpr
static bool HasAutogen_ = HasAutogenPKey<Seq> ();
409 template<
typename ImplFactory>
411 : Data_ { RemovePKey (data) }
412 , QueryBuilder_ { factory.MakeInsertQueryBuilder (db, Data_) }
418 return Run<true> (t, action);
423 return Run<false> (t, action);
426 template<
bool UpdatePKey,
typename Val>
429 const auto query = QueryBuilder_->GetQuery (action);
431 MakeInserter<Seq> (Data_, query, !HasAutogen_) (t);
433 if constexpr (HasAutogen_)
438 if constexpr (UpdatePKey)
439 boost::fusion::at_c<index> (t) = lastId;
445 static CachedFieldsData RemovePKey (CachedFieldsData data) noexcept
447 if constexpr (HasAutogen_)
449 constexpr
auto index = FindPKey<Seq>::result_type::value;
450 data.Fields_.removeAt (index);
451 data.BoundFields_.removeAt (index);
457 template<
typename Seq,
bool HasPKey = HasPKey<Seq>>
462 template<
bool B = HasPKey>
468 const auto& del =
"DELETE FROM " + data.
Table_ +
469 " WHERE " + data.
Fields_.at (index) +
" = " + boundName;
471 const auto deleteQuery = std::make_shared<QSqlQuery> (db);
472 deleteQuery->prepare (del);
474 Deleter_ = [deleteQuery, boundName] (
const Seq& t)
477 deleteQuery->bindValue (boundName,
ToVariantF (boost::fusion::at_c<index> (t)));
478 if (!deleteQuery->exec ())
479 throw QueryException (
"delete query execution failed", deleteQuery);
483 template<
bool B = HasPKey>
488 template<
bool B = HasPKey>
495 template<
typename T,
typename... Args>
498 template<
typename T,
size_t...
Indices>
506 const auto dummy = std::initializer_list<int>
561 return "invalid type";
596 template<
typename Seq,
typename L,
typename R>
600 template<
typename Seq,
typename L,
typename R>
601 constexpr
auto AreComparableTypes = IsDetected_v<ComparableDetector, Seq, L, R> || IsDetected_v<ComparableDetector, Seq, R, L>;
603 template<
typename Seq,
typename L,
typename R,
typename =
void>
606 template<
typename Seq,
typename L,
typename R>
609 template<ExprType Type,
typename Seq,
typename L,
typename R,
typename =
void>
612 template<ExprType Type,
typename Seq,
typename L,
typename R>
615 template<ExprType Type,
typename L =
void,
typename R =
void>
621 template<ExprType Type,
typename L,
typename R>
624 template<
typename L,
typename R>
640 return Left_.GetFieldName () +
" = " + Right_.ToSql (state);
642 return Left_.ToSql (state) +
", " + Right_.ToSql (state);
645 template<
typename OL,
typename OR>
652 template<ExprType Type,
typename L,
typename R>
668 "Incompatible types passed to a relational operator.");
670 return Left_.ToSql (state) +
" " +
TypeToSql (
Type) +
" " + Right_.ToSql (state);
676 return Left_.template AdditionalTables<T> () + Right_.template AdditionalTables<T> ();
682 return L::template HasAdditionalTables<T> () || R::template HasAdditionalTables<T> ();
699 template<
typename ObjT>
702 const auto& name =
":bound_" + QString::number (++state.LastID_);
703 state.BoundMembers_ [name] =
ToVariantF (Data_);
729 template<
auto... Ptr>
748 return detail::GetFieldNamePtr<Ptr> ();
755 if constexpr (std::is_same_v<Seq, T>)
758 return { Seq::ClassName () };
764 return !std::is_same_v<MemberPtrStruct_t<Ptr>, T>;
767 auto operator= (
const ExpectedType_t& r)
const noexcept
778 template<ExprType Type,
typename L,
typename R>
786 template<
typename L,
typename R>
796 template<
typename L,
typename R>
799 template<
typename L,
typename R,
typename = EnableRelOp_t<L, R>>
802 return MakeExprTree<ExprType::Less> (left, right);
805 template<
typename L,
typename R,
typename = EnableRelOp_t<L, R>>
808 return MakeExprTree<ExprType::Greater> (left, right);
811 template<
typename L,
typename R,
typename = EnableRelOp_t<L, R>>
814 return MakeExprTree<ExprType::Equal> (left, right);
817 template<
typename L,
typename R,
typename = EnableRelOp_t<L, R>>
820 return MakeExprTree<ExprType::Neq> (left, right);
823 template<ExprType Op>
834 template<
typename L, ExprType Op>
840 template<
typename L, ExprType Op>
846 template<
typename L, ExprType Op,
typename R>
849 return MakeExprTree<Op> (left.Left_, right);
852 template<
typename L,
typename R,
typename = EnableRelOp_t<L, R>>
855 return MakeExprTree<ExprType::And> (left, right);
858 template<
typename L,
typename R,
typename = EnableRelOp_t<L, R>>
861 return MakeExprTree<ExprType::Or> (left, right);
873 ,
Binder_ { std::move (binder) }
885 template<
typename Seq,
typename Tree,
886 typename = decltype (std::declval<Tree> ().ToSql (std::declval<ToSqlState<Seq>&> ()))>
891 const auto& sql = tree.ToSql (state);
896 [state] (QSqlQuery& query)
898 for (
const auto& pair :
Stlize (state.BoundMembers_))
899 query.bindValue (pair.first, pair.second);
912 template<AggregateFunction, auto Ptr>
919 template<
typename... MemberDirectionList>
922 template<
auto... Ptrs>
927 template<
typename L,
typename R>
936 template<AggregateFunction Fun, auto Ptr>
939 template<
auto... Ptrs>
942 template<
typename L,
typename R>
945 template<
typename L,
typename R,
typename = std::enable_if_t<IsSelector<L> {} && IsSelector<R> {}>>
957 template<
auto... Ptrs>
962 template<
auto... Ptrs>
965 template<
auto... Ptrs>
968 template<auto Ptr = detail::CountAllPtr>
978 template<
typename... Orders>
981 template<
auto... Ptrs>
1006 template<
auto... Ptrs,
size_t... Idxs>
1009 return [] (
const QSqlQuery& q,
int startIdx = 0) noexcept
1011 if constexpr (
sizeof... (Ptrs) == 1)
1021 return [] (
const QSqlQuery& q,
int startIdx = 0) noexcept
1027 template<
auto... Ptrs>
1030 return { BuildCachedFieldsData<MemberPtrStruct_t<Ptrs>> ().QualifiedFields_.value (FieldIndex<Ptrs> ())... };
1040 template<
size_t RepIdx,
size_t TupIdx,
typename Tuple,
typename NewType>
1043 if constexpr (RepIdx == TupIdx)
1044 return std::forward<NewType> (arg);
1046 return std::get<TupIdx> (tuple);
1049 template<
size_t RepIdx,
typename NewType,
typename Tuple,
size_t... TupIdxs>
1054 GetReplaceTupleElem<RepIdx, TupIdxs> (std::forward<Tuple> (tuple), std::forward<NewType> (arg))...
1058 template<
size_t RepIdx,
typename NewType,
typename... TupleArgs>
1061 return ReplaceTupleElemImpl<RepIdx> (std::move (tuple),
1062 std::forward<NewType> (arg),
1063 std::index_sequence_for<TupleArgs...> {});
1066 template<
typename Seq,
typename T>
1072 template<
typename Seq,
typename... Args>
1078 template<
typename Seq>
1081 constexpr
static int Value = SeqSize<Seq>;
1084 template<
typename... LArgs,
typename... RArgs>
1085 auto Combine (std::tuple<LArgs...>&& left, std::tuple<RArgs...>&& right) noexcept
1087 return std::tuple_cat (std::move (left), std::move (right));
1090 template<
typename... LArgs,
typename R>
1091 auto Combine (std::tuple<LArgs...>&& left,
const R& right) noexcept
1093 return std::tuple_cat (std::move (left), std::tuple { right });
1096 template<
typename L,
typename... RArgs>
1097 auto Combine (
const L& left, std::tuple<RArgs...>&& right) noexcept
1099 return std::tuple_cat (std::tuple { left }, std::move (right));
1102 template<
typename L,
typename R>
1103 auto Combine (
const L& left,
const R& right) noexcept
1105 return std::tuple { left, right };
1114 template<
typename L,
typename R>
1117 if constexpr (std::is_same_v<L, ResultBehaviour::First> && std::is_same_v<R, ResultBehaviour::First>)
1123 template<
typename ResList>
1126 return std::forward<ResList> (list);
1129 template<
typename ResList>
1132 return list.value (0);
1135 template<
typename F,
typename R>
1143 template<
typename F,
typename R>
1159 QString where, std::function<
void (QSqlQuery&)>&& binder,
1160 const QString& orderStr,
1161 const QString& groupStr,
1162 const QString& limitOffsetStr)
const 1164 if (!where.isEmpty ())
1165 where.prepend (
" WHERE ");
1167 const auto& queryStr =
"SELECT " +
fields +
1174 QSqlQuery query {
DB_ };
1175 query.prepare (queryStr);
1182 throw QueryException (
"fetch query execution failed", std::make_shared<QSqlQuery> (query));
1195 return " LIMIT " + QString::number (limit.Count);
1198 template<
typename L>
1202 if constexpr (std::is_same_v<std::decay_t<L>,
LimitNone>)
1207 else if constexpr (std::is_integral_v<L>)
1208 limitStr = QString::number (limit);
1210 limitStr = QString::number (limit.Count);
1211 return " LIMIT " + limitStr +
1212 " OFFSET " + QString::number (offset.Count);
1216 template<
typename T, SelectBehaviour SelectBehaviour>
1221 template<
typename ParamsTuple>
1225 ParamsTuple Params_;
1227 template<
typename NewTuple>
1228 constexpr
auto RepTuple (NewTuple&& tuple) noexcept
1230 return Builder<NewTuple> { W_, tuple };
1233 template<
typename U>
1234 constexpr
auto Select (U&& selector) && noexcept
1236 return RepTuple (ReplaceTupleElem<0> (std::move (Params_), std::forward<U> (selector)));
1239 template<
typename U>
1240 constexpr
auto Where (U&& tree) && noexcept
1242 return RepTuple (ReplaceTupleElem<1> (std::move (Params_), std::forward<U> (tree)));
1245 template<
typename U>
1246 constexpr
auto Order (U&& order) && noexcept
1248 return RepTuple (ReplaceTupleElem<2> (std::move (Params_), std::forward<U> (order)));
1251 template<
typename U>
1252 constexpr
auto Group (U&& group) && noexcept
1254 return RepTuple (ReplaceTupleElem<3> (std::move (Params_), std::forward<U> (group)));
1257 template<
typename U = Limit>
1258 constexpr
auto Limit (U&& limit) && noexcept
1260 return RepTuple (ReplaceTupleElem<4> (std::move (Params_), std::forward<U> (limit)));
1263 template<
typename U = Offset>
1264 constexpr
auto Offset (U&& offset) && noexcept
1266 return RepTuple (ReplaceTupleElem<5> (std::move (Params_), std::forward<U> (offset)));
1271 return std::apply (W_, Params_);
1274 template<
auto... Ptrs>
1275 constexpr
auto Group () && noexcept
1281 template<
typename ImplFactory>
1290 std::tuple defParams
1299 return Builder<decltype (defParams)> { *
this, defParams };
1307 template<
typename Single>
1310 if constexpr (
IsExprTree<std::decay_t<Single>> {})
1311 return (*
this) (
SelectWhole {}, std::forward<Single> (single));
1328 Limit limit = LimitNone {},
1329 Offset offset = OffsetNone {})
const 1331 const auto& [where, binder, _] = HandleExprTree<T> (tree);
1333 const auto& [
fields, initializer, resultBehaviour] = HandleSelector (std::forward<Selector> (selector));
1335 Select (
fields, BuildFromClause (tree),
1338 HandleOrder (std::forward<Order> (order)),
1339 HandleGroup (std::forward<Group> (group)),
1340 HandleLimitOffset (std::forward<Limit> (limit), std::forward<Offset> (offset))));
1343 template<
typename Binder,
typename Initializer>
1344 auto Select (
const QString&
fields,
const QString& from,
1345 const QString& where, Binder&& binder,
1346 Initializer&& initializer,
1347 const QString& orderStr,
1348 const QString& groupStr,
1349 const QString& limitOffsetStr)
const 1351 std::function<void (QSqlQuery&)> binderFunc;
1352 if constexpr (!std::is_same_v<Void, std::decay_t<Binder>>)
1353 binderFunc = binder;
1354 auto query =
RunQuery (
fields, from, where,
std::move (binderFunc), orderStr, groupStr, limitOffsetStr);
1359 while (query.next ())
1360 result << initializer (query);
1365 using RetType_t = std::optional<std::result_of_t<Initializer (QSqlQuery)>>;
1366 return query.next () ?
1372 template<ExprType Type,
typename L,
typename R>
1373 QString BuildFromClause (
const ExprTree<Type, L, R>& tree)
const noexcept
1377 auto result = Cached_.
Table_;
1378 for (
const auto& item : tree.template AdditionalTables<T> ())
1379 result +=
", " + item;
1386 auto HandleSelector (SelectWhole)
const noexcept
1391 [] (
const QSqlQuery& q,
int startIdx = 0)
1393 return InitializeFromQuery<T> (q, SeqIndices<T>, startIdx);
1395 ResultBehaviour::All {}
1399 template<
auto... Ptrs>
1400 auto HandleSelector (MemberPtrs<Ptrs...> ptrs)
const noexcept
1406 ResultBehaviour::All {}
1410 auto HandleSelector (AggregateType<AggregateFunction::Count, CountAllPtr>)
const noexcept
1415 [] (
const QSqlQuery& q,
int startIdx = 0) {
return q.value (startIdx).toLongLong (); },
1421 auto HandleSelector (AggregateType<AggregateFunction::Count, Ptr>)
const noexcept
1425 "count(" + GetQualifiedFieldNamePtr<Ptr> () +
")",
1426 [] (
const QSqlQuery& q,
int startIdx = 0) {
return q.value (startIdx).toLongLong (); },
1432 auto HandleSelector (AggregateType<AggregateFunction::Min, Ptr>)
const noexcept
1436 "min(" + GetQualifiedFieldNamePtr<Ptr> () +
")",
1437 MakeIndexedQueryHandler<Ptr> (),
1443 auto HandleSelector (AggregateType<AggregateFunction::Max, Ptr>)
const noexcept
1447 "max(" + GetQualifiedFieldNamePtr<Ptr> () +
")",
1448 MakeIndexedQueryHandler<Ptr> (),
1453 template<
typename L,
typename R>
1454 auto HandleSelector (SelectorUnion<L, R>)
const noexcept
1456 const auto& lSel = HandleSelector (L {});
1457 const auto& rSel = HandleSelector (R {});
1459 const auto& lHandler = lSel.Initializer_;
1460 const auto& rHandler = rSel.Initializer_;
1464 lSel.Fields_ +
", " + rSel.Fields_,
1465 [lHandler, rHandler] (
const QSqlQuery& q,
int startIdx = 0)
1468 return Combine (lHandler (q, startIdx), rHandler (q, startIdx + shift));
1474 QString HandleOrder (OrderNone)
const noexcept
1479 template<
auto... Ptrs>
1482 return { (GetQualifiedFieldNamePtr<Ptrs> () +
" ASC")... };
1485 template<
auto... Ptrs>
1486 QList<QString> HandleSuborder (sph::desc<Ptrs...>)
const noexcept
1488 return { (GetQualifiedFieldNamePtr<Ptrs> () +
" DESC")... };
1491 template<
typename... Suborders>
1492 QString HandleOrder (OrderBy<Suborders...>)
const noexcept
1494 return " ORDER BY " + QStringList {
Concat (
QList { HandleSuborder (Suborders {})... }) }.join (
", ");
1497 QString HandleGroup (GroupNone)
const noexcept
1502 template<
auto... Ptrs>
1503 QString HandleGroup (GroupBy<Ptrs...>)
const noexcept
1505 return " GROUP BY " + QStringList { GetQualifiedFieldNamePtr<Ptrs> ()... }.join (
", ");
1509 template<
typename T>
1512 const QSqlDatabase DB_;
1513 const QString Table_;
1517 , Table_ (data.Table_)
1521 template<ExprType Type,
typename L,
typename R>
1524 const auto& [where, binder, _] = HandleExprTree<T> (tree);
1527 const auto& selectAll =
"DELETE FROM " + Table_ +
1530 QSqlQuery query { DB_ };
1531 query.prepare (selectAll);
1537 template<
typename T,
bool HasPKey = HasPKey<T>>
1540 const QSqlDatabase DB_;
1541 const QString Table_;
1543 std::function<void (T)> Updater_;
1547 , Table_ { data.Table_ }
1551 constexpr
auto index = FindPKey<T>::result_type::value;
1553 auto statements = Util::ZipWith<QList> (data.Fields_, data.BoundFields_,
1554 [] (
const QString& s1,
const QString& s2) {
return s1 +
" = " + s2; });
1555 auto wherePart = statements.takeAt (index);
1556 const auto& update =
"UPDATE " + data.Table_ +
1557 " SET " + statements.join (
", ") +
1558 " WHERE " + wherePart;
1560 const auto updateQuery = std::make_shared<QSqlQuery> (db);
1561 updateQuery->prepare (update);
1562 Updater_ = MakeInserter<T> (data, updateQuery,
true);
1566 template<
bool B = HasPKey>
1572 template<
typename SL,
typename SR, ExprType WType,
typename WL,
typename WR>
1576 "joins in update statements are not supported by SQL");
1578 const auto& [setClause, setBinder, setLast] = HandleExprTree<T> (
set);
1579 const auto& [whereClause, whereBinder, _] = HandleExprTree<T> (where, setLast);
1581 const auto& update =
"UPDATE " + Table_ +
1582 " SET " + setClause +
1583 " WHERE " + whereClause;
1585 QSqlQuery query { DB_ };
1586 query.prepare (update);
1588 whereBinder (query);
1592 throw QueryException (
"update query execution failed", std::make_shared<QSqlQuery> (query));
1595 return query.numRowsAffected ();
1599 template<
typename T>
1602 template<
typename T>
1605 template<
typename T>
1608 template<
int... Fields>
1613 return "UNIQUE (" + QStringList { data.Fields_.value (Fields)... }.join (
", ") +
")";
1617 template<
int... Fields>
1622 return "PRIMARY KEY (" + QStringList { data.Fields_.value (Fields)... }.join (
", ") +
")";
1626 template<
typename... Args>
1632 template<
typename ImplFactory,
typename T,
size_t...
Indices>
1638 template<
typename ImplFactory,
typename T>
1641 const auto& types = GetTypes<ImplFactory, T> (SeqIndices<T>);
1644 const auto& constraintsStr = constraints.isEmpty () ?
1646 (
", " + constraints.join (
", "));
1648 const auto& statements = Util::ZipWith<QList> (types, data.Fields_,
1649 [] (
const QString& type,
const QString& field) {
return field +
" " + type; });
1650 return "CREATE TABLE " +
1653 statements.join (
", ") +
1659 template<
auto... Ptrs>
1662 return { { detail::BuildCachedFieldsData<MemberPtrStruct_t<Ptrs>> ().
Fields_.value (detail::FieldIndex<Ptrs> ())... } };
1665 template<
typename Seq>
1668 static_assert (detail::HasPKey<Seq>,
"Sequence does not have any primary keys");
1669 return { { detail::GetFieldName<Seq, detail::FindPKey<Seq>::result_type::value> () } };
1672 template<
typename T>
1686 template<
typename T,
typename ImplFactory = detail::SQLite::ImplFactory>
1689 const auto& cachedData = detail::BuildCachedFieldsData<T> ();
1691 if (!db.tables ().contains (cachedData.Table_, Qt::CaseInsensitive))
1692 RunTextQuery (db, detail::AdaptCreateTable<ImplFactory, T> (cachedData));
1694 ImplFactory factory;
1698 { db, cachedData, factory },
1702 { db, cachedData, factory },
1703 { db, cachedData, factory },
1708 template<
typename T>
1711 template<
typename T,
typename ImplFactory = SQLiteImplFactory>
1714 return std::make_shared<ObjectInfo<T>> (Adapt<T, ImplFactory> (db));
1719 template<
size_t Idx,
typename Tuple>
1720 using UnderlyingObject_t =
typename std::decay_t<std::tuple_element_t<Idx, Tuple>>::element_type::ObjectType_t;
1722 template<
typename ImplFactory,
typename Tuple,
size_t... Idxs>
1723 void AdaptPtrs (
const QSqlDatabase& db, Tuple& tuple, std::index_sequence<Idxs...>)
1729 template<
typename ImplFactory,
typename Tuple>
1732 detail::AdaptPtrs<ImplFactory> (db, tuple, std::make_index_sequence<std::tuple_size_v<Tuple>> {});
typename std::decay_t< std::tuple_element_t< Idx, Tuple > >::element_type::ObjectType_t UnderlyingObject_t
decltype(std::declval< UnwrapIndirect_t< typename L::template ValueType_t< Seq > >>()==std::declval< UnwrapIndirect_t< typename R::template ValueType_t< Seq > >>()) ComparableDetector
constexpr bool IsRelational(ExprType type) noexcept
constexpr detail::AggregateType< detail::AggregateFunction::Count, Ptr > count
detail::DeleteByFieldsWrapper< T > DeleteBy
auto Stlize(Assoc &&assoc)
Converts an Qt's associative sequence assoc to an STL-like iteratable range.
constexpr size_t FieldIndex() noexcept
QString GetFieldName() noexcept
constexpr detail::OrderBy< Orders... > OrderBy
typename boost::fusion::result_of::value_at_c< Seq, Idx >::type ValueAtC_t
typename T::Constraints ConstraintsDetector
constexpr auto HasAutogenPKey() noexcept
AdaptDelete(const QSqlDatabase &, const CachedFieldsData &, std::enable_if_t<!B > *=nullptr) noexcept
std::enable_if_t< B > operator()(const T &seq)
decltype(T::TypeName) TypeNameDetector
constexpr bool TypeNameCustomized
constexpr CountAll * CountAllPtr
QString MorphFieldName(QString str) noexcept
QSet< QString > AdditionalTables() const noexcept
Container< T > Concat(const Container< Container< T >> &containers)
QString operator()() const noexcept
QStringList QualifiedFields_
constexpr detail::AggregateType< detail::AggregateFunction::Max, Ptr > max
AssignList(const L &l, const R &r) noexcept
QStringList operator()() const noexcept
QString HandleLimitOffset(LimitNone, OffsetNone) const noexcept
constexpr auto AreComparableTypes
constexpr detail::GroupBy< Ptrs... > GroupBy
boost::mpl::int_< FindPKey< Seq >::result_type::value > FindPKeyDetector
typename std::conditional_t< IsPKey< ValueAt_t< Seq, MemberIdx > >::value, Lazy< MemberIdx >, Lazy< FindPKey< Seq, typename boost::mpl::next< MemberIdx >::type > > >::type result_type
SelectWrapperCommon(const QSqlDatabase &db, const QString &limitNone)
ExprTreeHandler(const QString &sql, F &&binder, int lastId) noexcept
static UTIL_DB_API void DumpError(const QSqlError &error)
Dumps the error to the qWarning() stream.
CachedFieldsData BuildCachedFieldsData(const QString &table) noexcept
SelectorUnion< L, R > operator+(L, R) noexcept
T operator()(const QVariant &var) const noexcept
AdaptInsert(const QSqlDatabase &db, CachedFieldsData data, ImplFactory &&factory) noexcept
HandleSelectorResult(QString, F, R) -> HandleSelectorResult< F, R >
typename detail::IsDetected< Type, void, Op, Args... >::type IsDetected_t
QVariant operator()(const T &t) const noexcept
auto Build() const noexcept
auto HandleExprTree(const ExprTree< ExprType::ConstTrue > &, int lastId=0) noexcept
static constexpr auto Index() noexcept
auto operator,(const AssignList< OL, OR > &tail) noexcept
MemberTypeType_t< decltype(Ptr)> MemberPtrType_t
~QueryException() noexcept=default
constexpr bool IsDetected_v
static constexpr auto Ptr() noexcept
T InitializeFromQuery(const QSqlQuery &q, std::index_sequence< Indices... >, int startIdx) noexcept
static constexpr bool HasAdditionalTables() noexcept
QString ToSql(ToSqlState< ObjT > &state) const noexcept
auto operator<(const L &left, const R &right) noexcept
constexpr bool BaseTypeCustomized
DeleteByFieldsWrapper(const QSqlDatabase &db, const CachedFieldsData &data) noexcept
QueryException(const std::string &str, const QSqlQuery_ptr &q)
std::shared_ptr< QSqlQuery > QSqlQuery_ptr
decltype(auto) HandleResultBehaviour(ResultBehaviour::All, ResList &&list) noexcept
auto operator!=(const L &left, const R &right) noexcept
auto RunQuery(const QString &fields, const QString &from, QString where, std::function< void(QSqlQuery &)> &&binder, const QString &orderStr, const QString &groupStr, const QString &limitOffsetStr) const
auto MakeExprTree(const L &left, const R &right) noexcept
QList< QString > GetTypes(std::index_sequence< Indices... >) noexcept
constexpr detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, detail::MemberPtrs< Ptr > > f
QString ToSql(ToSqlState< T > &state) const noexcept
constexpr auto ReplaceTupleElemImpl(Tuple &&tuple, NewType &&arg, std::index_sequence< TupIdxs... >) noexcept
void operator()(const ExprTree< Type, L, R > &tree) const noexcept
void AdaptPtrs(const QSqlDatabase &db, Tuple &tuple, std::index_sequence< Idxs... >)
auto operator &&(const L &left, const R &right) noexcept
Type
Describes the various types of XDG .desktop files.
QVariantMap BoundMembers_
constexpr auto SeqIndices
QString AdaptCreateTable(const CachedFieldsData &data) noexcept
void AdaptPtrs(const QSqlDatabase &db, Tuple &tuple)
constexpr bool EitherIsExprTree() noexcept
detail::AdaptUpdate< T > Update
AdaptDelete(const QSqlDatabase &db, const CachedFieldsData &data, std::enable_if_t< B > *=nullptr) noexcept
QStringList BuildFieldNames() noexcept
auto MakeInserter(const CachedFieldsData &data, const QSqlQuery_ptr &insertQuery, bool bindPrimaryKey) noexcept
QString ToSql(ToSqlState< T > &state) const noexcept
auto Map(Container &&c, F f)
static constexpr bool HasAdditionalTables() noexcept
auto operator==(const L &left, const R &right) noexcept
std::unique_ptr< IInsertQueryBuilder > IInsertQueryBuilder_ptr
decltype(new T { std::declval< Args >()... }) AggregateDetector_t
QString GetQualifiedFieldNamePtr() noexcept
ObjectInfo_ptr< T > AdaptPtr(const QSqlDatabase &db)
static struct LC::Util::oral::InsertAction::DefaultTag Default
A somewhat "strong" typedef.
ExprTree(const T &t) noexcept
typename AsTypelist< T >::Result_t AsTypelist_t
QSet< QString > AdditionalTables() const noexcept
auto operator>(const L &left, const R &right) noexcept
detail::AdaptInsert< T > Insert
std::conditional_t< std::is_same_v< detail::RetTypeRaw_t< F >, detail::ReturnsVoid >, void, detail::RetTypeRaw_t< F > > RetType_t
typename boost::fusion::result_of::value_at< Seq, Idx >::type ValueAt_t
const QSqlQuery_ptr & GetQueryPtr() const
static constexpr int Value
QStringList GetConstraintsStringList(Constraints< Args... >, const CachedFieldsData &data) noexcept
std::enable_if_t< B > operator()(const Seq &seq)
const QSqlQuery & GetQuery() const
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
SelectWrapper(const QSqlDatabase &db, const CachedFieldsData &data, ImplFactory &&factory) noexcept
ExprTree(const L &l, const R &r) noexcept
constexpr detail::MemberPtrs< Ptrs... > fields
typename T::BaseType BaseTypeDetector
QSqlQuery RunTextQuery(const QSqlDatabase &db, const QString &text)
Runs the given query text on the given db.
constexpr detail::AggregateType< detail::AggregateFunction::Min, Ptr > min
constexpr auto CombineBehaviour(L, R) noexcept
auto operator()(Seq &t, InsertAction action=InsertAction::Default) const
constexpr auto AsLeafData(const T &node) noexcept
AdaptUpdate(const QSqlDatabase &db, const CachedFieldsData &data) noexcept
typename std::conditional_t< IsIndirect< T > {}, T, WrapDirect< T > >::value_type UnwrapIndirect_t
MemberTypeStruct_t< decltype(Ptr)> MemberPtrStruct_t
Util::IsDetected_t< Constraints<>, ConstraintsDetector, T > ConstraintsType
QString HandleLimitOffset(L limit, Offset offset) const noexcept
ExpectedType_t ValueType_t
ObjectInfo< T > Adapt(const QSqlDatabase &db)
decltype(auto) constexpr GetReplaceTupleElem(Tuple &&tuple, NewType &&arg) noexcept
decltype(std::declval< U >().FieldNameMorpher(QString {})) MorpherDetector
detail::SelectWrapper< T, detail::SelectBehaviour::One > SelectOne
constexpr detail::SelectWhole all
QString HandleLimitOffset(Limit limit, OffsetNone) const noexcept
auto MakeIndexedQueryHandler(MemberPtrs< Ptrs... >, std::index_sequence< Idxs... >) noexcept
Typelist< Args... > Constraints
std::enable_if_t< EitherIsExprTree< L, R >()> EnableRelOp_t
QSet< QString > AdditionalTables() const noexcept
auto operator||(const L &left, const R &right) noexcept
detail::AdaptDelete< T > Delete
auto operator|(const L &left, InfixBinary< Op >) noexcept
QString TypeToSql(ExprType type) noexcept
QString ToSql(ToSqlState< T > &) const noexcept
QString GetFieldName() const noexcept
static constexpr bool HasAdditionalTables() noexcept
Offset(uint64_t count) noexcept
Limit(uint64_t count) noexcept
QVariant ToVariantF(const T &t) noexcept
std::shared_ptr< ObjectInfo< T > > ObjectInfo_ptr
QString GetFieldNamePtr() noexcept
constexpr auto ConstTrueTree_v
std::function< void(Seq)> Deleter_