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