LeechCraft  0.6.70-6645-gcd10d7e
Modular cross-platform feature rich live environment.
oral.h
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  * Boost Software License - Version 1.0 - August 17th, 2003
6  *
7  * Permission is hereby granted, free of charge, to any person or organization
8  * obtaining a copy of the software and accompanying documentation covered by
9  * this license (the "Software") to use, reproduce, display, distribute,
10  * execute, and transmit the Software, and to prepare derivative works of the
11  * Software, and to permit third-parties to whom the Software is furnished to
12  * do so, all subject to the following:
13  *
14  * The copyright notices in the Software and this entire statement, including
15  * the above license grant, this restriction and the following disclaimer,
16  * must be included in all copies of the Software, in whole or in part, and
17  * all derivative works of the Software, unless such copies or derivative
18  * works are solely in the form of machine-executable object code generated by
19  * a source language processor.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
24  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
25  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
26  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  **********************************************************************/
29 
30 #pragma once
31 
32 #include <stdexcept>
33 #include <type_traits>
34 #include <memory>
35 #include <boost/fusion/include/for_each.hpp>
36 #include <boost/fusion/include/fold.hpp>
37 #include <boost/fusion/include/filter_if.hpp>
38 #include <boost/fusion/container/vector.hpp>
39 #include <boost/fusion/include/vector.hpp>
40 #include <boost/fusion/include/transform.hpp>
41 #include <boost/fusion/include/zip.hpp>
42 #include <boost/fusion/container/generation/make_vector.hpp>
43 #include <boost/variant/variant.hpp>
44 #include <boost/optional.hpp>
45 #include <QStringList>
46 #include <QDateTime>
47 #include <QPair>
48 #include <QSqlQuery>
49 #include <QSqlRecord>
50 #include <QVariant>
51 #include <QDateTime>
52 #include <QtDebug>
53 #include <util/sll/qtutil.h>
54 #include <util/sll/prelude.h>
55 #include <util/sll/typelist.h>
56 #include <util/sll/oldcppkludges.h>
57 #include <util/db/dblock.h>
58 #include <util/db/util.h>
59 #include "oraltypes.h"
60 
61 using QSqlQuery_ptr = std::shared_ptr<QSqlQuery>;
62 
63 namespace LeechCraft
64 {
65 namespace Util
66 {
67 namespace oral
68 {
69  class QueryException : public std::runtime_error
70  {
71  const QSqlQuery_ptr Query_;
72  public:
73  QueryException (const std::string& str, const QSqlQuery_ptr& q)
74  : std::runtime_error (str)
75  , Query_ (q)
76  {
77  }
78 
79  virtual ~QueryException () throw ()
80  {
81  }
82 
83  const QSqlQuery_ptr& GetQueryPtr () const
84  {
85  return Query_;
86  }
87 
88  const QSqlQuery& GetQuery () const
89  {
90  return *Query_;
91  }
92  };
93 
94  template<int... Fields>
95  struct UniqueSubset;
96 
97  template<typename... Args>
98  using Constraints = Typelist<Args...>;
99 
100  namespace detail
101  {
102  template<typename T>
103  QString MorphFieldNameImpl (const QString& str, int, decltype (&T::FieldNameMorpher)* = nullptr)
104  {
105  return T::FieldNameMorpher (str);
106  }
107 
108  template<typename T>
109  QString MorphFieldNameImpl (const QString& str, float)
110  {
111  return str;
112  }
113 
114  template<typename T>
115  QString MorphFieldName (const QString& str)
116  {
117  return MorphFieldNameImpl<T> (str, 0);
118  }
119 
120  template<typename Seq, int Idx>
122  {
123  static QString value ()
124  {
125  const QString rawName { boost::fusion::extension::struct_member_name<Seq, Idx>::call () };
126  return MorphFieldName<Seq> (rawName);
127  }
128  };
129 
130  template<typename S, typename N>
132  {
133  QStringList operator() () const
134  {
136  }
137  };
138 
139  template<typename S>
140  struct GetFieldsNames_<S, typename boost::fusion::result_of::size<S>::type>
141  {
142  QStringList operator() () const
143  {
144  return {};
145  }
146  };
147 
148  template<typename S>
149  struct GetFieldsNames : GetFieldsNames_<S, boost::mpl::int_<0>>
150  {
151  };
152 
153  template<typename Seq, int Idx>
155  {
156  static QString value () { return ':' + Seq::ClassName () + "_" + GetFieldName<Seq, Idx>::value (); }
157  };
158  }
159 
160  template<typename T>
161  struct Type2Name;
162 
163  template<>
164  struct Type2Name<int>
165  {
166  QString operator() () const { return "INTEGER"; }
167  };
168 
169  template<>
170  struct Type2Name<qulonglong>
171  {
172  QString operator() () const { return "INTEGER"; }
173  };
174 
175  template<>
176  struct Type2Name<double>
177  {
178  QString operator() () const { return "REAL"; }
179  };
180 
181  template<>
182  struct Type2Name<bool>
183  {
184  QString operator() () const { return "INTEGER"; }
185  };
186 
187  template<>
188  struct Type2Name<QString>
189  {
190  QString operator() () const { return "TEXT"; }
191  };
192 
193  template<>
194  struct Type2Name<QByteArray>
195  {
196  QString operator() () const { return "BLOB"; }
197  };
198 
199  template<>
200  struct Type2Name<QDateTime>
201  {
202  QString operator() () const { return "TEXT"; }
203  };
204 
205  template<typename T>
206  struct Type2Name<Unique<T>>
207  {
208  QString operator() () const { return Type2Name<T> () () + " UNIQUE"; }
209  };
210 
211  template<typename T, typename... Tags>
212  struct Type2Name<PKey<T, Tags...>>
213  {
214  QString operator() () const { return Type2Name<T> () () + " PRIMARY KEY"; }
215  };
216 
217  template<typename... Tags>
218  struct Type2Name<PKey<int, Tags...>>
219  {
220  QString operator() () const { return Type2Name<int> () () + " PRIMARY KEY AUTOINCREMENT"; }
221  };
222 
223  template<typename Seq, int Idx>
224  struct Type2Name<References<Seq, Idx>>
225  {
226  QString operator() () const
227  {
229  " REFERENCES " + Seq::ClassName () + " (" + detail::GetFieldName<Seq, Idx>::value () + ") ON DELETE CASCADE";
230  }
231  };
232 
233  template<typename T>
234  struct ToVariant
235  {
236  QVariant operator() (const T& t) const
237  {
238  return t;
239  }
240  };
241 
242  template<>
243  struct ToVariant<QDateTime>
244  {
245  QVariant operator() (const QDateTime& t) const
246  {
247  return t.toString (Qt::ISODate);
248  }
249  };
250 
251  template<typename T>
252  struct ToVariant<Unique<T>>
253  {
254  QVariant operator() (const Unique<T>& t) const
255  {
256  return static_cast<typename Unique<T>::value_type> (t);
257  }
258  };
259 
260  template<typename T, typename... Tags>
261  struct ToVariant<PKey<T, Tags...>>
262  {
263  QVariant operator() (const PKey<T, Tags...>& t) const
264  {
265  return static_cast<typename PKey<T, Tags...>::value_type> (t);
266  }
267  };
268 
269  template<typename Seq, int Idx>
270  struct ToVariant<References<Seq, Idx>>
271  {
272  QVariant operator() (const References<Seq, Idx>& t) const
273  {
274  return static_cast<typename References<Seq, Idx>::value_type> (t);
275  }
276  };
277 
278  template<typename T>
279  struct FromVariant
280  {
281  T operator() (const QVariant& var) const
282  {
283  return var.value<T> ();
284  }
285  };
286 
287  template<>
288  struct FromVariant<QDateTime>
289  {
290  QDateTime operator() (const QVariant& var) const
291  {
292  return QDateTime::fromString (var.toString (), Qt::ISODate);
293  }
294  };
295 
296  template<typename T>
297  struct FromVariant<Unique<T>>
298  {
299  T operator() (const QVariant& var) const
300  {
301  return var.value<T> ();
302  }
303  };
304 
305  template<typename T, typename... Tags>
306  struct FromVariant<PKey<T, Tags...>>
307  {
308  T operator() (const QVariant& var) const
309  {
310  return var.value<T> ();
311  }
312  };
313 
314  template<typename Seq, int Idx>
315  struct FromVariant<References<Seq, Idx>>
316  {
318 
319  value_type operator() (const QVariant& var) const
320  {
321  return var.value<value_type> ();
322  }
323  };
324 
325  enum class InsertAction
326  {
327  Default,
328  Ignore,
329  Replace
330  };
331 
332  namespace detail
333  {
334  struct Types
335  {
336  template<typename T>
337  QStringList operator() (const QStringList& init, const T&) const
338  {
339  return init + QStringList { Type2Name<T> () () };
340  }
341  };
342 
343  struct Inserter
344  {
349  const bool BindPrimaryKey_;
351 
352  template<typename T>
353  QStringList operator() (QStringList bounds, const T& t) const
354  {
355  if (BindPrimaryKey_ || !IsPKey<T>::value)
356  Q_->bindValue (bounds.takeFirst (), ToVariant<T> {} (t));
357  return bounds;
358  }
359  };
360 
361  struct Selector
362  {
364 
365  template<typename T>
366  int operator() (int index, T& t) const
367  {
368  t = FromVariant<T> {} (Q_->value (index));
369  return index + 1;
370  }
371  };
372 
374  {
375  QString Table_;
376  QSqlDatabase DB_;
377 
380  };
381 
382  template<typename T>
383  std::function<void (T)> MakeInserter (CachedFieldsData data, QSqlQuery_ptr insertQuery, bool bindPrimaryKey)
384  {
385  return [data, insertQuery, bindPrimaryKey] (const T& t)
386  {
387  boost::fusion::fold<T, QStringList, Inserter> (t, data.BoundFields_, Inserter { bindPrimaryKey, insertQuery });
388  if (!insertQuery->exec ())
389  {
390  DBLock::DumpError (*insertQuery);
391  throw QueryException ("insert query execution failed", insertQuery);
392  }
393  };
394  }
395 
396  template<typename T>
397  struct Lazy
398  {
399  using type = T;
400  };
401 
402  template<typename Seq, int Idx>
403  using ValueAtC_t = typename boost::fusion::result_of::value_at_c<Seq, Idx>::type;
404 
405  template<typename Seq, typename Idx>
406  using ValueAt_t = typename boost::fusion::result_of::value_at<Seq, Idx>::type;
407 
408  template<typename Seq, typename MemberIdx = boost::mpl::int_<0>>
409  struct FindPKey
410  {
411  static_assert ((boost::fusion::result_of::size<Seq>::value) != (MemberIdx::value),
412  "Primary key not found");
413 
414  using result_type = typename std::conditional<
418  >::type::type;
419  };
420 
421  template<typename Seq, int Idx = FindPKey<Seq>::result_type::value>
422  constexpr bool HasAutogenPKeyImpl (int)
423  {
424  return !HasType<NoAutogen> (AsTypelist_t<ValueAtC_t<Seq, Idx>> {});
425  }
426 
427  template<typename>
428  constexpr bool HasAutogenPKeyImpl (float)
429  {
430  return false;
431  }
432 
433  template<typename Seq>
434  constexpr bool HasAutogenPKey ()
435  {
436  return HasAutogenPKeyImpl<Seq> (0);
437  }
438 
439  QString GetInsertPrefix (InsertAction action)
440  {
441  switch (action)
442  {
444  return "INSERT";
446  return "INSERT OR IGNORE";
448  return "INSERT OR REPLACE";
449  }
450 
451  qWarning () << Q_FUNC_INFO
452  << "unknown action"
453  << static_cast<int> (action);
454  return "INSERT";
455  }
456 
457  template<typename Seq>
458  struct AdaptInsert
459  {
461  const QString InsertSuffix_;
462 
463  struct PrivateTag {};
464 
465  AdaptInsert (const CachedFieldsData& data, const PrivateTag&)
466  : Data_ (data)
467  , InsertSuffix_ (" INTO " + data.Table_ +
468  " (" + QStringList { data.Fields_ }.join (", ") + ") VALUES (" +
469  QStringList { data.BoundFields_ }.join (", ") + ");")
470  {
471  }
472  public:
473  template<bool Autogen = HasAutogenPKey<Seq> ()>
475  : AdaptInsert
476  {
477  {
478  [data] () mutable
479  {
480  constexpr auto index = FindPKey<Seq>::result_type::value;
481  data.Fields_.removeAt (index);
482  data.BoundFields_.removeAt (index);
483  return data;
484  } ()
485  },
486  PrivateTag {}
487  }
488  {
489  }
490 
491  template<bool Autogen = HasAutogenPKey<Seq> ()>
493  : AdaptInsert { data, PrivateTag {} }
494  {
495  }
496 
497  template<bool Autogen = HasAutogenPKey<Seq> ()>
498  EnableIf_t<Autogen> operator() (Seq& t, InsertAction action = InsertAction::Default) const
499  {
500  auto query = std::make_shared<QSqlQuery> (Data_.DB_);
501  query->prepare (GetInsertPrefix (action) + InsertSuffix_);
502  MakeInserter<Seq> (Data_, query, false) (t);
503 
504  constexpr auto index = FindPKey<Seq>::result_type::value;
505  boost::fusion::at_c<index> (t) = FromVariant<ValueAtC_t<Seq, index>> {} (query->lastInsertId ());
506  }
507 
508  template<bool Autogen = HasAutogenPKey<Seq> ()>
510  operator() (const Seq& t, InsertAction action = InsertAction::Default) const
511  {
512  auto query = std::make_shared<QSqlQuery> (Data_.DB_);
513  query->prepare (GetInsertPrefix (action) + InsertSuffix_);
514  MakeInserter<Seq> (Data_, query, false) (t);
515 
516  constexpr auto index = FindPKey<Seq>::result_type::value;
517  return FromVariant<ValueAtC_t<Seq, index>> {} (query->lastInsertId ());
518  }
519 
520  template<bool Autogen = HasAutogenPKey<Seq> ()>
521  EnableIf_t<!Autogen> operator() (const Seq& t, InsertAction action = InsertAction::Default) const
522  {
523  auto query = std::make_shared<QSqlQuery> (Data_.DB_);
524  query->prepare (GetInsertPrefix (action) + InsertSuffix_);
525  MakeInserter<Seq> (Data_, query, true) (t);
526  }
527  };
528 
529  template<typename T>
530  std::function<void (T)> AdaptUpdate (const CachedFieldsData& data)
531  {
532  const auto index = FindPKey<T>::result_type::value;
533 
534  auto removedFields = data.Fields_;
535  auto removedBoundFields = data.BoundFields_;
536 
537  const auto& fieldName = removedFields.takeAt (index);
538  const auto& boundName = removedBoundFields.takeAt (index);
539 
540  const auto& statements = Util::ZipWith (removedFields, removedBoundFields,
541  [] (const QString& s1, const QString& s2) -> QString
542  { return s1 + " = " + s2; });
543 
544  const auto& update = "UPDATE " + data.Table_ +
545  " SET " + QStringList { statements }.join (", ") +
546  " WHERE " + fieldName + " = " + boundName + ";";
547 
548  const auto updateQuery = std::make_shared<QSqlQuery> (data.DB_);
549  updateQuery->prepare (update);
550  return MakeInserter<T> (data, updateQuery, true);
551  }
552 
553  template<typename T>
554  std::function<void (T)> AdaptDelete (CachedFieldsData data)
555  {
556  const auto index = FindPKey<T>::result_type::value;
557 
558  const auto& boundName = data.BoundFields_.at (index);
559  const auto& del = "DELETE FROM " + data.Table_ +
560  " WHERE " + data.Fields_.at (index) + " = " + boundName + ";";
561 
562  const auto deleteQuery = std::make_shared<QSqlQuery> (data.DB_);
563  deleteQuery->prepare (del);
564 
565  return [deleteQuery, boundName] (const T& t)
566  {
567  constexpr auto index = FindPKey<T>::result_type::value;
568  deleteQuery->bindValue (boundName,
569  ToVariant<ValueAtC_t<T, index>> {} (boost::fusion::at_c<index> (t)));
570  if (!deleteQuery->exec ())
571  throw QueryException ("delete query execution failed", deleteQuery);
572  };
573  }
574 
575  template<typename T>
577  {
578  if (!q->exec ())
579  throw QueryException ("fetch query execution failed", q);
580 
581  QList<T> result;
582  while (q->next ())
583  {
584  T t;
585  boost::fusion::fold<T, int, Selector> (t, 0, Selector { q });
586  result << t;
587  }
588  q->finish ();
589  return result;
590  }
591 
592  template<typename T>
593  std::function<QList<T> ()> AdaptSelectAll (const CachedFieldsData& data)
594  {
595  const auto& selectAll = "SELECT " + QStringList { data.Fields_ }.join (", ") + " FROM " + data.Table_ + ";";
596  const auto selectQuery = std::make_shared<QSqlQuery> (data.DB_);
597  selectQuery->prepare (selectAll);
598  return [selectQuery] { return PerformSelect<T> (selectQuery); };
599  }
600 
601  template<int HeadT, int... TailT>
603  {
604  static const int Head = HeadT;
605  using Tail_t = FieldsUnpacker<TailT...>;
606  };
607 
608  template<int HeadT>
609  struct FieldsUnpacker<HeadT>
610  {
611  static const int Head = HeadT;
612  using Tail_t = std::false_type;
613  };
614 
615  template<typename FieldsUnpacker, typename HeadArg, typename... TailArgs>
616  struct ValueBinder
617  {
620 
621  void operator() (const HeadArg& arg, const TailArgs&... tail) const
622  {
623  Query_->bindValue (BoundFields_.at (FieldsUnpacker::Head), arg);
624 
625  ValueBinder<typename FieldsUnpacker::Tail_t, TailArgs...> { Query_, BoundFields_ } (tail...);
626  }
627  };
628 
629  template<typename FieldsUnpacker, typename HeadArg>
630  struct ValueBinder<FieldsUnpacker, HeadArg>
631  {
634 
635  void operator() (const HeadArg& arg) const
636  {
637  Query_->bindValue (BoundFields_.at (FieldsUnpacker::Head), arg);
638  }
639  };
640 
641  enum class ExprType
642  {
644  LeafData,
645 
646  Greater,
647  Less,
648  Equal,
649  Geq,
650  Leq,
651  Neq,
652 
653  And,
654  Or
655  };
656 
657  QString TypeToSql (ExprType type)
658  {
659  switch (type)
660  {
661  case ExprType::Greater:
662  return ">";
663  case ExprType::Less:
664  return "<";
665  case ExprType::Equal:
666  return "=";
667  case ExprType::Geq:
668  return ">=";
669  case ExprType::Leq:
670  return "<=";
671  case ExprType::Neq:
672  return "!=";
673  case ExprType::And:
674  return "AND";
675  case ExprType::Or:
676  return "OR";
677 
678  case ExprType::LeafStaticPlaceholder:
679  case ExprType::LeafData:
680  return "invalid type";
681  }
682 
683  qWarning () << Q_FUNC_INFO
684  << "unhandled type"
685  << static_cast<int> (type);
686  return {};
687  }
688 
689  template<ExprType Type>
690  struct IsLeaf : std::false_type {};
691 
692  template<>
693  struct IsLeaf<ExprType::LeafStaticPlaceholder> : std::true_type {};
694 
695  template<>
696  struct IsLeaf<ExprType::LeafData> : std::true_type {};
697 
698  template<ExprType Type1, ExprType Type2>
699  struct IsCompatible : std::false_type {};
700 
701  template<ExprType Type>
702  struct IsCompatible<Type, ExprType::And> : std::true_type {};
703 
704  template<ExprType Type>
705  struct IsCompatible<Type, ExprType::Or> : std::true_type {};
706 
707  template<ExprType Type>
708  struct IsCompatible<Type, ExprType::LeafStaticPlaceholder> : std::true_type {};
709 
710  template<ExprType Type>
711  struct IsCompatible<Type, ExprType::LeafData> : std::true_type {};
712 
713  template<typename T>
714  constexpr T Ctfy (T t)
715  {
716  return t;
717  }
718 
719  template<ExprType T1, ExprType T2>
720  constexpr bool CheckCompatible ()
721  {
723  }
724 
725  constexpr bool IsRelational (ExprType type)
726  {
727  return type == ExprType::Greater ||
728  type == ExprType::Less ||
729  type == ExprType::Equal ||
730  type == ExprType::Geq ||
731  type == ExprType::Leq ||
732  type == ExprType::Neq;
733  }
734 
735  template<typename T>
736  struct ToSqlState
737  {
738  int LastID_;
739  QVariantMap BoundMembers_;
740  };
741 
742  template<typename Seq, typename L, typename R>
743  constexpr bool AreComparableTypesImpl (int,
744  decltype (std::declval<typename L::template ValueType_t<Seq>> () == std::declval<typename R::template ValueType_t<Seq>> ())* = nullptr)
745  {
746  return true;
747  }
748 
749  template<typename Seq, typename L, typename R>
750  constexpr bool AreComparableTypesImpl (float)
751  {
752  return false;
753  }
754 
755  template<typename Seq, typename L, typename R>
756  constexpr bool AreComparableTypes ()
757  {
758  return AreComparableTypesImpl<Seq, L, R> (0) ||
759  AreComparableTypesImpl<Seq, R, L> (0);
760  }
761 
762  template<ExprType Type, typename Seq, typename L, typename R, typename = void>
763  struct RelationalTypesChecker : std::true_type {};
764 
765  template<typename Seq, typename L, typename R, typename = void>
766  struct RelationalTypesCheckerBase : std::false_type {};
767 
768  template<typename Seq, typename L, typename R>
769  struct RelationalTypesCheckerBase<Seq, L, R, EnableIf_t<AreComparableTypes<Seq, L, R> ()>> : std::true_type {};
770 
771  template<ExprType Type, typename Seq, typename L, typename R>
773 
774  template<ExprType Type, typename L = void, typename R = void>
775  class ExprTree
776  {
777  L Left_;
778  R Right_;
779  public:
780  ExprTree (const L& l, const R& r)
781  : Left_ (l)
782  , Right_ (r)
783  {
784  }
785 
786  template<typename T>
787  QString ToSql (ToSqlState<T>& state) const
788  {
790  "Incompatible types passed to a relational operator.");
791 
792  return Left_.ToSql (state) + " " + TypeToSql (Type) + " " + Right_.ToSql (state);
793  }
794  };
795 
796  template<int Idx>
797  class ExprTree<ExprType::LeafStaticPlaceholder, boost::mpl::int_<Idx>, void>
798  {
799  public:
800  template<typename T>
802 
803  template<typename T>
804  QString ToSql (ToSqlState<T>&) const
805  {
806  static_assert (Idx < boost::fusion::result_of::size<T>::type::value, "Index out of bounds.");
807  return detail::GetFieldsNames<T> {} ().at (Idx);
808  }
809  };
810 
811  template<typename T>
812  class ExprTree<ExprType::LeafData, T, void>
813  {
814  T Data_;
815  public:
816  template<typename>
817  using ValueType_t = T;
818 
819  ExprTree (const T& t)
820  : Data_ (t)
821  {
822  }
823 
824  template<typename ObjT>
825  QString ToSql (ToSqlState<ObjT>& state) const
826  {
827  const auto& name = ":bound_" + QString::number (++state.LastID_);
828  state.BoundMembers_ [name] = ToVariant<T> {} (Data_);
829  return name;
830  }
831  };
832 
833  template<typename T>
834  struct IsExprTree : std::false_type {};
835 
836  template<ExprType Type, typename L, typename R>
837  struct IsExprTree<ExprTree<Type, L, R>> : std::true_type {};
838 
839  template<ExprType LType, typename LL, typename LR, ExprType RType, typename RL, typename RR>
840  ExprTree<ExprType::Less, ExprTree<LType, LL, LR>, ExprTree<RType, RL, RR>> operator< (const ExprTree<LType, LL, LR>& left, const ExprTree<RType, RL, RR>& right)
841  {
842  static_assert (CheckCompatible<LType, RType> (), "comparing incompatible subexpressions");
843  return { left, right };
844  }
845 
846  template<ExprType LType, typename LL, typename LR, typename R>
847  ExprTree<ExprType::Less, ExprTree<LType, LL, LR>, ExprTree<ExprType::LeafData, R>> operator< (const ExprTree<LType, LL, LR>& left, const R& right)
848  {
849  return left < ExprTree<ExprType::LeafData, R> { right };
850  }
851 
852  template<ExprType RType, typename RL, typename RR, typename L>
853  ExprTree<ExprType::Less, ExprTree<ExprType::LeafData, L>, ExprTree<RType, RL, RR>> operator< (const L& left, const ExprTree<RType, RL, RR>& right)
854  {
855  return ExprTree<ExprType::LeafData, L> { left } < right;
856  }
857 
858  template<ExprType LType, typename LL, typename LR, ExprType RType, typename RL, typename RR>
860  {
861  static_assert (CheckCompatible<LType, RType> (), "comparing incompatible subexpressions");
862  return { left, right };
863  }
864 
865  template<ExprType LType, typename LL, typename LR, typename R>
867  {
868  return left == ExprTree<ExprType::LeafData, R> { right };
869  }
870 
871  template<ExprType RType, typename RL, typename RR, typename L>
873  {
874  return ExprTree<ExprType::LeafData, L> { left } == right;
875  }
876 
877  template<ExprType LType, typename LL, typename LR, ExprType RType, typename RL, typename RR>
879  {
880  return { left, right };
881  }
882 
883  template<ExprType LType, typename LL, typename LR, typename R>
885  {
886  return left && ExprTree<ExprType::LeafData, R> { right };
887  }
888 
889  template<ExprType RType, typename RL, typename RR, typename L>
891  {
892  return ExprTree<ExprType::LeafData, L> { left } && right;
893  }
894 
895  template<typename Seq, ExprType Type, typename L, typename R>
896  QPair<QString, std::function<void (QSqlQuery_ptr)>> HandleExprTree (const ExprTree<Type, L, R>& tree)
897  {
898  ToSqlState<Seq> state { 0, {} };
899 
900  const auto& sql = tree.ToSql (state);
901 
902  return
903  {
904  sql,
905  [state] (const QSqlQuery_ptr& query)
906  {
907  for (const auto& pair : Stlize (state.BoundMembers_))
908  query->bindValue (pair.first, pair.second);
909  }
910  };
911  }
912  }
913 
914  namespace sph
915  {
916  template<int Idx>
918 
919  static constexpr pos<0> _0 = {};
920  static constexpr pos<1> _1 = {};
921  static constexpr pos<2> _2 = {};
922  static constexpr pos<3> _3 = {};
923  static constexpr pos<4> _4 = {};
924 
925 #if __cpp_variable_templates >= 201304
926  template<int Idx>
927  static constexpr pos<Idx> _ = {};
928 #endif
929  };
930 
931  namespace detail
932  {
933  template<typename T>
935  {
936  const CachedFieldsData Cached_;
937  public:
939  : Cached_ (data)
940  {
941  }
942 
943  template<ExprType Type, typename L, typename R>
944  QList<T> operator() (const ExprTree<Type, L, R>& tree) const
945  {
946  const auto& treeResult = HandleExprTree<T> (tree);
947 
948  const auto& selectAll = "SELECT " + QStringList { Cached_.Fields_ }.join (", ") +
949  " FROM " + Cached_.Table_ +
950  " WHERE " + treeResult.first + ";";
951 
952  const auto query = std::make_shared<QSqlQuery> (Cached_.DB_);
953  query->prepare (selectAll);
954  treeResult.second (query);
955  return PerformSelect<T> (query);
956  }
957 
958  template<int Idx, ExprType Type, typename L, typename R>
960  {
961  const auto& treeResult = HandleExprTree<T> (tree);
962 
963  const auto& selectOne = "SELECT " + Cached_.Fields_.value (Idx) +
964  " FROM " + Cached_.Table_ +
965  " WHERE " + treeResult.first + ";";
966 
967  const auto query = std::make_shared<QSqlQuery> (Cached_.DB_);
968  query->prepare (selectOne);
969  treeResult.second (query);
970 
971  if (!query->exec ())
972  throw QueryException ("fetch query execution failed", query);
973 
974  using Type_t = ValueAtC_t<T, Idx>;
975 
976  QList<Type_t> result;
977  while (query->next ())
978  result << FromVariant<Type_t> {} (query->value (0));
979  query->finish ();
980  return result;
981  }
982  };
983 
984  template<typename T>
986  {
987  const SelectByFieldsWrapper<T> Select_;
988  public:
990  : Select_ { data }
991  {
992  }
993 
994  template<ExprType Type, typename L, typename R>
995  boost::optional<T> operator() (const ExprTree<Type, L, R>& tree) const
996  {
997  const auto& result = Select_ (tree);
998  if (result.isEmpty ())
999  return {};
1000 
1001  return result.value (0);
1002  }
1003 
1004  template<int Idx, ExprType Type, typename L, typename R>
1005  boost::optional<ValueAtC_t<T, Idx>> operator() (sph::pos<Idx> p, const ExprTree<Type, L, R>& tree) const
1006  {
1007  const auto& result = Select_ (p, tree);
1008  if (result.isEmpty ())
1009  return {};
1010 
1011  return result.value (0);
1012  }
1013  };
1014 
1015  template<typename T>
1017  {
1018  const CachedFieldsData Cached_;
1019  public:
1021  : Cached_ (data)
1022  {
1023  }
1024 
1025  template<ExprType Type, typename L, typename R>
1026  void operator() (const ExprTree<Type, L, R>& tree) const
1027  {
1028  const auto& treeResult = HandleExprTree<T> (tree);
1029 
1030  const auto& selectAll = "DELETE FROM " + Cached_.Table_ +
1031  " WHERE " + treeResult.first + ";";
1032 
1033  const auto query = std::make_shared<QSqlQuery> (Cached_.DB_);
1034  query->prepare (selectAll);
1035  treeResult.second (query);
1036  query->exec ();
1037  }
1038  };
1039 
1040  template<typename T>
1042  {
1043  return { data };
1044  }
1045 
1046  template<typename T>
1048  {
1049  return { data };
1050  }
1051 
1052  template<typename T>
1054  {
1055  return { data };
1056  }
1057 
1058  template<typename OrigSeq, typename OrigIdx, typename RefSeq, typename MemberIdx>
1059  struct FieldInfo
1060  {
1061  };
1062 
1063  template<typename To, typename OrigSeq, typename OrigIdx, typename T>
1065  {
1066  using value_type = To;
1067  };
1068 
1069  template<typename To, typename OrigSeq, typename OrigIdx, typename RefSeq, int RefIdx>
1070  struct FieldAppender<To, OrigSeq, OrigIdx, References<RefSeq, RefIdx>>
1071  {
1072  using value_type = typename boost::fusion::result_of::as_vector<
1073  typename boost::fusion::result_of::push_front<
1074  To,
1076  >::type
1077  >::type;
1078  };
1079 
1080  template<typename Seq, typename MemberIdx>
1082  {
1083  using type_list = typename FieldAppender<
1085  Seq,
1086  MemberIdx,
1087  typename std::decay<typename boost::fusion::result_of::at<Seq, MemberIdx>::type>::type
1088  >::value_type;
1089  };
1090 
1091  template<typename Seq>
1092  struct CollectRefs_<Seq, typename boost::fusion::result_of::size<Seq>::type>
1093  {
1094  using type_list = boost::fusion::vector<>;
1095  };
1096 
1097  template<typename Seq>
1098  struct CollectRefs : CollectRefs_<Seq, boost::mpl::int_<0>>
1099  {
1100  };
1101 
1102  struct Ref2Select
1103  {
1104  template<typename OrigSeq, typename OrigIdx, typename RefSeq, typename RefIdx>
1105  QStringList operator() (const QStringList& init, const FieldInfo<OrigSeq, OrigIdx, RefSeq, RefIdx>&) const
1106  {
1107  const auto& thisQualified = OrigSeq::ClassName () + "." + GetFieldName<OrigSeq, OrigIdx::value>::value ();
1108  return init + QStringList { thisQualified + " = " + GetBoundName<RefSeq, RefIdx::value>::value () };
1109  }
1110  };
1111 
1112  template<typename T>
1113  struct ExtrObj;
1114 
1115  template<typename OrigSeq, typename OrigIdx, typename RefSeq, typename MemberIdx>
1116  struct ExtrObj<FieldInfo<OrigSeq, OrigIdx, RefSeq, MemberIdx>>
1117  {
1118  using type = RefSeq;
1119  };
1120 
1121  struct SingleBind
1122  {
1124 
1125  template<typename ObjType, typename OrigSeq, typename OrigIdx, typename RefSeq, typename RefIdx>
1126  void operator() (const boost::fusion::vector2<ObjType, const FieldInfo<OrigSeq, OrigIdx, RefSeq, RefIdx>&>& pair) const
1127  {
1129  ToVariant<typename std::decay<typename boost::fusion::result_of::at<RefSeq, RefIdx>::type>::type> () (boost::fusion::at<RefIdx> (boost::fusion::at_c<0> (pair))));
1130  }
1131  };
1132 
1133  template<typename T, typename RefSeq>
1134  struct MakeBinder
1135  {
1136  using transform_view = typename boost::mpl::transform<RefSeq, ExtrObj<boost::mpl::_1>>;
1137  using objects_view = typename transform_view::type;
1138  using objects_vector = typename boost::fusion::result_of::as_vector<objects_view>::type;
1139 
1141 
1142  QList<T> operator() (const objects_vector& objs)
1143  {
1144  boost::fusion::for_each (boost::fusion::zip (objs, RefSeq {}), SingleBind { Q_ });
1145  return PerformSelect<T> (Q_);
1146  }
1147  };
1148 
1149  template<typename T, typename ObjInfo>
1150  typename std::enable_if<CollectRefs<T>::type_list::size::value == 1>::type AdaptSelectRef (const CachedFieldsData& data, ObjInfo& info)
1151  {
1152  using references_list = typename CollectRefs<T>::type_list;
1153  const auto& statements = boost::fusion::fold (references_list {}, QStringList {}, Ref2Select {});
1154 
1155  const auto& selectAll = "SELECT " + QStringList { data.Fields_ }.join (", ") +
1156  " FROM " + data.Table_ +
1157  (statements.isEmpty () ? "" : " WHERE ") + statements.join (" AND ") +
1158  ";";
1159  const auto selectQuery = std::make_shared<QSqlQuery> (data.DB_);
1160  selectQuery->prepare (selectAll);
1161 
1162  info.SelectByFKeysActor_ = MakeBinder<T, references_list> { selectQuery };
1163  }
1164 
1165  template<typename T, typename Ret>
1166  struct WrapAsFunc
1167  {
1168  using type = std::function<QList<Ret> (T)>;
1169  };
1170 
1171  template<typename T, typename Ret>
1173 
1174  template<typename T>
1176  {
1178 
1179  template<typename Vec, typename OrigObj, typename OrigIdx, typename RefObj, typename RefIdx>
1180  auto operator() (Vec vec, const FieldInfo<OrigObj, OrigIdx, RefObj, RefIdx>&) -> decltype (boost::fusion::push_back (vec, WrapAsFunc_t<RefObj, T> {}))
1181  {
1182  const auto& boundName = GetBoundName<OrigObj, OrigIdx::value>::value ();
1183  const auto& query = "SELECT " + QStringList { Data_.Fields_ }.join (", ") +
1184  " FROM " + Data_.Table_ +
1185  " WHERE " + GetFieldName<OrigObj, OrigIdx::value>::value () + " = " + boundName +
1186  ";";
1187  const auto selectQuery = std::make_shared<QSqlQuery> (Data_.DB_);
1188  selectQuery->prepare (query);
1189 
1190  auto inserter = [selectQuery, boundName] (const RefObj& obj)
1191  {
1192  selectQuery->bindValue (boundName,
1193  ToVariant<ValueAt_t<RefObj, RefIdx>> {} (boost::fusion::at<RefIdx> (obj)));
1194  return PerformSelect<T> (selectQuery);
1195  };
1196 
1197  return boost::fusion::push_back (vec, WrapAsFunc_t<RefObj, T> { inserter });
1198  }
1199  };
1200 
1201  template<typename T, typename ObjInfo>
1202  typename std::enable_if<CollectRefs<T>::type_list::size::value >= 2>::type AdaptSelectRef (const CachedFieldsData& data, ObjInfo& info)
1203  {
1204  using references_list = typename CollectRefs<T>::type_list;
1205  const auto& statements = boost::fusion::fold (references_list {}, QStringList {}, Ref2Select {});
1206 
1207  const auto& selectAll = "SELECT " + QStringList { data.Fields_ }.join (", ") +
1208  " FROM " + data.Table_ +
1209  (statements.isEmpty () ? "" : " WHERE ") + statements.join (" AND ") +
1210  ";";
1211  const auto selectQuery = std::make_shared<QSqlQuery> (data.DB_);
1212  selectQuery->prepare (selectAll);
1213 
1214  info.SelectByFKeysActor_ = MakeBinder<T, references_list> { selectQuery };
1215 
1216  auto singleSelectors = boost::fusion::fold (references_list {}, boost::fusion::vector<> {}, MakeSingleBinder<T> { data });
1217  info.SingleFKeySelectors_ = boost::fusion::as_vector (singleSelectors);
1218  }
1219 
1220  template<typename T, typename ObjInfo>
1221  typename std::enable_if<CollectRefs<T>::type_list::size::value <= 0>::type AdaptSelectRef (const CachedFieldsData&, ObjInfo&)
1222  {
1223  }
1224 
1225  template<typename T>
1226  typename T::Constraints GetConstraintsTypeImpl (int, typename T::Constraints* = nullptr)
1227  {
1228  return {};
1229  }
1230 
1231  template<typename T>
1232  Constraints<> GetConstraintsTypeImpl (float)
1233  {
1234  return {};
1235  }
1236 
1237  template<typename T>
1238  using ConstraintsType = decltype (GetConstraintsTypeImpl<T> (0));
1239 
1240  template<typename T>
1241  struct ConstraintToString;
1242 
1243  template<int... Fields>
1244  struct ConstraintToString<UniqueSubset<Fields...>>
1245  {
1246  QString operator() (const CachedFieldsData& data) const
1247  {
1248  return "UNIQUE (" + QStringList { data.Fields_.value (Fields)... }.join (", ") + ")";
1249  }
1250  };
1251 
1252  template<typename...>
1253  struct GetConstraintsStringList;
1254 
1255  template<>
1256  struct GetConstraintsStringList<Constraints<>>
1257  {
1258  QStringList operator() (const CachedFieldsData&) const
1259  {
1260  return {};
1261  }
1262  };
1263 
1264  template<typename Head, typename... Tail>
1265  struct GetConstraintsStringList<Constraints<Head, Tail...>>
1266  {
1267  QStringList operator() (const CachedFieldsData& data) const
1268  {
1269  return QStringList { ConstraintToString<Head> {} (data) } +
1270  GetConstraintsStringList<Constraints<Tail...>> {} (data);
1271  }
1272  };
1273 
1274  template<typename T>
1275  QString AdaptCreateTable (const CachedFieldsData& data)
1276  {
1277  const QList<QString> types = boost::fusion::fold (T {}, QStringList {}, Types {});
1278 
1279  const auto& constraints = GetConstraintsStringList<ConstraintsType<T>> {} (data);
1280  const auto& constraintsStr = constraints.isEmpty () ?
1281  QString {} :
1282  (", " + constraints.join (", "));
1283 
1284  const auto& statements = Util::ZipWith (types, data.Fields_,
1285  [] (const QString& type, const QString& field) { return field + " " + type; });
1286  return "CREATE TABLE " +
1287  data.Table_ +
1288  " (" +
1289  statements.join (", ") +
1290  constraintsStr +
1291  ");";
1292  }
1293 
1294  template<typename T, typename Enable = void>
1295  struct ObjectInfoFKeysHelper
1296  {
1297  };
1298 
1299  template<typename T>
1300  struct ObjectInfoFKeysHelper<T, typename std::enable_if<CollectRefs<T>::type_list::size::value == 1, void>::type>
1301  {
1302  std::function<QList<T> (typename MakeBinder<T, typename CollectRefs<T>::type_list>::objects_vector)> SelectByFKeysActor_;
1303  };
1304 
1305  template<typename T>
1306  struct ObjectInfoFKeysHelper<T, typename std::enable_if<CollectRefs<T>::type_list::size::value >= 2, void>::type>
1307  {
1308  using objects_vector = typename MakeBinder<T, typename CollectRefs<T>::type_list>::objects_vector;
1309  std::function<QList<T> (objects_vector)> SelectByFKeysActor_;
1310 
1311  using transform_view = typename boost::mpl::transform<objects_vector, WrapAsFunc<boost::mpl::_1, T>>::type;
1312  typename boost::fusion::result_of::as_vector<transform_view>::type SingleFKeySelectors_;
1313  };
1314  }
1315 
1316  template<typename T>
1317  struct ObjectInfo : detail::ObjectInfoFKeysHelper<T>
1318  {
1319  std::function<QList<T> ()> DoSelectAll_;
1321  std::function<void (T)> DoUpdate_;
1322  std::function<void (T)> DoDelete_;
1323 
1327 
1328  ObjectInfo (decltype (DoSelectAll_) doSel,
1329  decltype (DoInsert_) doIns,
1330  decltype (DoUpdate_) doUpdate,
1331  decltype (DoDelete_) doDelete,
1332  decltype (DoSelectByFields_) selectByFields,
1333  decltype (DoSelectOneByFields_) selectOneByFields,
1334  decltype (DoDeleteByFields_) deleteByFields)
1335  : DoSelectAll_ (doSel)
1336  , DoInsert_ (doIns)
1337  , DoUpdate_ (doUpdate)
1338  , DoDelete_ (doDelete)
1339  , DoSelectByFields_ (selectByFields)
1340  , DoSelectOneByFields_ (selectOneByFields)
1341  , DoDeleteByFields_ (deleteByFields)
1342  {
1343  }
1344  };
1345 
1346  template<typename T>
1347  ObjectInfo<T> Adapt (const QSqlDatabase& db)
1348  {
1349  const QList<QString> fields = detail::GetFieldsNames<T> {} ();
1350  const QList<QString> boundFields = Util::Map (fields, [] (const QString& str) { return ':' + str; });
1351 
1352  const auto& table = T::ClassName ();
1353 
1354  const detail::CachedFieldsData cachedData { table, db, fields, boundFields };
1355  if (db.record (table).isEmpty ())
1356  RunTextQuery (db, detail::AdaptCreateTable<T> (cachedData));
1357 
1358  const auto& selectr = detail::AdaptSelectAll<T> (cachedData);
1359  const auto& insertr = detail::AdaptInsert<T> (cachedData);
1360  const auto& updater = detail::AdaptUpdate<T> (cachedData);
1361  const auto& deleter = detail::AdaptDelete<T> (cachedData);
1362 
1363  const auto& selectByVal = detail::AdaptSelectFields<T> (cachedData);
1364  const auto& selectOneByVal = detail::AdaptSelectOneFields<T> (cachedData);
1365  const auto& deleteByVal = detail::AdaptDeleteFields<T> (cachedData);
1366 
1367  ObjectInfo<T> info
1368  {
1369  selectr,
1370  insertr,
1371  updater,
1372  deleter,
1373  selectByVal,
1374  selectOneByVal,
1375  deleteByVal
1376  };
1377 
1378  detail::AdaptSelectRef<T> (cachedData, info);
1379 
1380  return info;
1381  }
1382 
1383  template<typename T>
1384  using ObjectInfo_ptr = std::shared_ptr<ObjectInfo<T>>;
1385 
1386  template<typename T>
1387  ObjectInfo_ptr<T> AdaptPtr (const QSqlDatabase& db)
1388  {
1389  return std::make_shared<ObjectInfo<T>> (Adapt<T> (db));
1390  }
1391 }
1392 }
1393 }
QString MorphFieldName(const QString &str)
Definition: oral.h:115
std::function< void(T)> DoUpdate_
Definition: oral.h:1321
constexpr List< T... > Tail(List< H, T... >)
Definition: typelist.h:44
AdaptInsert(CachedFieldsData data, EnableIf_t< Autogen > *=nullptr)
Definition: oral.h:474
typename boost::mpl::transform< RefSeq, ExtrObj< boost::mpl::_1 >> transform_view
Definition: oral.h:1136
ExprTree< ExprType::And, ExprTree< ExprType::LeafData, L >, ExprTree< RType, RL, RR > > operator&&(const L &left, const ExprTree< RType, RL, RR > &right)
Definition: oral.h:890
boost::fusion::result_of::as_vector< transform_view >::type SingleFKeySelectors_
Definition: oral.h:1312
AdaptInsert(const CachedFieldsData &data, const PrivateTag &)
Definition: oral.h:465
const CachedFieldsData Data_
Definition: oral.h:460
typename boost::fusion::result_of::as_vector< objects_view >::type objects_vector
Definition: oral.h:1138
detail::SelectOneByFieldsWrapper< T > DoSelectOneByFields_
Definition: oral.h:1325
std::function< void(T)> AdaptDelete(CachedFieldsData data)
Definition: oral.h:554
QString TypeToSql(ExprType type)
Definition: oral.h:657
std::enable_if< CollectRefs< T >::type_list::size::value==1 >::type AdaptSelectRef(const CachedFieldsData &data, ObjInfo &info)
Definition: oral.h:1150
detail::SelectByFieldsWrapper< T > DoSelectByFields_
Definition: oral.h:1324
constexpr bool AreComparableTypes()
Definition: oral.h:756
constexpr bool CheckCompatible()
Definition: oral.h:720
typename boost::mpl::transform< objects_vector, WrapAsFunc< boost::mpl::_1, T >>::type transform_view
Definition: oral.h:1311
std::function< void(T)> MakeInserter(CachedFieldsData data, QSqlQuery_ptr insertQuery, bool bindPrimaryKey)
Definition: oral.h:383
auto ZipWith(const Container< T1 > &c1, const Container< T2 > &c2, F f) -> WrapType_t< Container< Decay_t< ResultOf_t< F(T1, T2)>>>>
Definition: prelude.h:59
STL namespace.
Typelist< Args... > Constraints
Definition: oral.h:98
constexpr bool HasAutogenPKey()
Definition: oral.h:434
QString MorphFieldNameImpl(const QString &str, float)
Definition: oral.h:109
typename std::conditional< IsPKey< ValueAt_t< Seq, MemberIdx >>::value, Lazy< MemberIdx >, Lazy< FindPKey< Seq, typename boost::mpl::next< MemberIdx >>> >::type::type result_type
Definition: oral.h:418
typename transform_view::type objects_view
Definition: oral.h:1137
const QSqlQuery & GetQuery() const
Definition: oral.h:88
QList< T > PerformSelect(QSqlQuery_ptr q)
Definition: oral.h:576
typename boost::fusion::result_of::as_vector< typename boost::fusion::result_of::push_front< To, FieldInfo< OrigSeq, OrigIdx, RefSeq, boost::mpl::int_< RefIdx >> >::type >::type value_type
Definition: oral.h:1077
bool operator==(const ModelIterator &left, const ModelIterator &right)
typename boost::fusion::result_of::value_at< Seq, Idx >::type ValueAt_t
Definition: oral.h:406
typename WrapAsFunc< T, Ret >::type WrapAsFunc_t
Definition: oral.h:1172
ObjectInfo< T > Adapt(const QSqlDatabase &db)
Definition: oral.h:1347
DeleteByFieldsWrapper< T > AdaptDeleteFields(const CachedFieldsData &data)
Definition: oral.h:1053
typename member_type::value_type value_type
Definition: oraltypes.h:124
SelectByFieldsWrapper< T > AdaptSelectFields(const CachedFieldsData &data)
Definition: oral.h:1041
typename std::enable_if< B, T >::type EnableIf_t
Definition: oldcppkludges.h:67
Type
Describes the various types of XDG .desktop files.
Definition: itemtypes.h:48
typename boost::fusion::result_of::value_at_c< Seq, Idx >::type ValueAtC_t
Definition: oral.h:403
ObjectInfo_ptr< T > AdaptPtr(const QSqlDatabase &db)
Definition: oral.h:1387
constexpr T Ctfy(T t)
Definition: oral.h:714
auto Stlize(Assoc &&assoc) -> detail::StlAssocRange< decltype(assoc.begin()), Assoc, PairType >
Converts an Qt&#39;s associative sequence assoc to an STL-like iteratable range.
Definition: qtutil.h:126
typename References< Seq, Idx >::value_type value_type
Definition: oral.h:317
SelectOneByFieldsWrapper(const CachedFieldsData &data)
Definition: oral.h:989
std::shared_ptr< ObjectInfo< T >> ObjectInfo_ptr
Definition: oral.h:1384
constexpr bool AreComparableTypesImpl(float)
Definition: oral.h:750
constexpr bool HasAutogenPKeyImpl(float)
Definition: oral.h:428
QString ToSql(ToSqlState< T > &state) const
Definition: oral.h:787
std::function< QList< Ret >(T)> type
Definition: oral.h:1168
constexpr bool IsRelational(ExprType type)
Definition: oral.h:725
const QSqlQuery_ptr & GetQueryPtr() const
Definition: oral.h:83
auto Map(const Container< T > &c, F f) -> typename std::enable_if<!std::is_same< void, decltype(Invoke(f,*c.begin()))>::value, WrapType_t< Container< typename std::decay< decltype(Invoke(f,*c.begin()))>::type >>>::type
Definition: prelude.h:129
std::function< QList< T >)> AdaptSelectAll(const CachedFieldsData &data)
Definition: oral.h:593
ExprTree(const L &l, const R &r)
Definition: oral.h:780
QString ToSql(ToSqlState< ObjT > &state) const
Definition: oral.h:825
static UTIL_DB_API void DumpError(const QSqlError &error)
Dumps the error to the qWarning() stream.
Definition: dblock.cpp:84
SelectOneByFieldsWrapper< T > AdaptSelectOneFields(const CachedFieldsData &data)
Definition: oral.h:1047
typename FieldAppender< typename CollectRefs_< Seq, typename boost::mpl::next< MemberIdx >::type >::type_list, Seq, MemberIdx, typename std::decay< typename boost::fusion::result_of::at< Seq, MemberIdx >::type >::type >::value_type type_list
Definition: oral.h:1088
std::shared_ptr< QSqlQuery > QSqlQuery_ptr
Definition: oral.h:61
DeleteByFieldsWrapper(const CachedFieldsData &data)
Definition: oral.h:1020
detail::AdaptInsert< T > DoInsert_
Definition: oral.h:1320
std::function< QList< T >objects_vector)> SelectByFKeysActor_
Definition: oral.h:1309
QueryException(const std::string &str, const QSqlQuery_ptr &q)
Definition: oral.h:73
typename AsTypelist< T >::Result_t AsTypelist_t
Definition: typelist.h:161
QString GetInsertPrefix(InsertAction action)
Definition: oral.h:439
void RunTextQuery(const QSqlDatabase &db, const QString &text)
Runs the given query text on the given db.
Definition: util.cpp:40
ObjectInfo(decltype(DoSelectAll_) doSel, decltype(DoInsert_) doIns, decltype(DoUpdate_) doUpdate, decltype(DoDelete_) doDelete, decltype(DoSelectByFields_) selectByFields, decltype(DoSelectOneByFields_) selectOneByFields, decltype(DoDeleteByFields_) deleteByFields)
Definition: oral.h:1328
SelectByFieldsWrapper(const CachedFieldsData &data)
Definition: oral.h:938
detail::DeleteByFieldsWrapper< T > DoDeleteByFields_
Definition: oral.h:1326
std::function< void(T)> AdaptUpdate(const CachedFieldsData &data)
Definition: oral.h:530
std::function< void(T)> DoDelete_
Definition: oral.h:1322
AdaptInsert(const CachedFieldsData &data, EnableIf_t<!Autogen > *=nullptr)
Definition: oral.h:492
QPair< QString, std::function< void(QSqlQuery_ptr)> > HandleExprTree(const ExprTree< Type, L, R > &tree)
Definition: oral.h:896