You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

236 lines
9.3 KiB

  1. #pragma once
  2. #include <cpphibernate/modifier.h>
  3. #include "context.h"
  4. namespace cpphibernate
  5. {
  6. namespace __impl
  7. {
  8. /* init_builder */
  9. template<typename X, typename = void>
  10. struct init_builder
  11. {
  12. template<typename... T_args>
  13. static constexpr decltype(auto) apply(T_args&&...)
  14. { static_assert(sizeof...(T_args) == -1, "Invalid parameters for context::init(...)!"); }
  15. };
  16. constexpr decltype(auto) init = mp::generic_predicate<init_builder> { };
  17. template<typename T_impl, typename T_bool>
  18. struct init_builder<
  19. mp::list<T_impl, T_bool>,
  20. mp::enable_if_t<
  21. mp::is_valid_v<decltype(std::declval<T_impl>().init(std::declval<bool>()))>
  22. && mp::is_same_v<bool, mp::decay_t<T_bool>>
  23. >>
  24. {
  25. static constexpr decltype(auto) apply(T_impl& impl, bool recreate)
  26. { return impl.init(recreate); }
  27. };
  28. /* create_builder */
  29. template<typename X, typename = void>
  30. struct create_builder
  31. {
  32. template<typename... T_args>
  33. static constexpr decltype(auto) apply(T_args&&...)
  34. { static_assert(sizeof...(T_args) == -1, "Invalid parameters for context::create(...)!"); }
  35. };
  36. constexpr decltype(auto) create = mp::generic_predicate<create_builder> { };
  37. template<typename T_impl, typename T_dataset>
  38. struct create_builder<
  39. mp::list<T_impl, T_dataset>,
  40. mp::enable_if_t<
  41. mp::is_valid_v<decltype(std::declval<T_impl>().create(std::declval<T_dataset&>()))>
  42. >>
  43. {
  44. static constexpr decltype(auto) apply(T_impl& impl, T_dataset& dataset)
  45. { return impl.create(dataset); }
  46. };
  47. /* read_builder */
  48. template<typename X, typename = void>
  49. struct read_builder
  50. {
  51. template<typename... T_args>
  52. static constexpr decltype(auto) apply(T_args&&...)
  53. { static_assert(sizeof...(T_args) == -1, "Invalid parameters for context::read(...)!"); }
  54. };
  55. constexpr decltype(auto) read = mp::generic_predicate<read_builder> { };
  56. template<typename T_schema, typename T_impl, typename T_dataset, typename T_modifiers>
  57. struct read_builder<
  58. mp::list<T_schema, T_impl, T_dataset, T_modifiers>,
  59. mp::enable_if_t<
  60. schema::is_schema_v<mp::decay_t<T_schema>>
  61. && is_modifiers_v<mp::decay_t<T_modifiers>>
  62. && mp::is_valid_v<decltype(std::declval<T_impl>().read(
  63. std::declval<T_dataset&>(),
  64. std::declval<T_modifiers>()))>
  65. >>
  66. {
  67. static constexpr decltype(auto) apply(const T_schema& schema, T_impl& impl, T_dataset& dataset, T_modifiers&& modifiers)
  68. { return impl.read(dataset, std::forward<T_modifiers>(modifiers)); }
  69. };
  70. template<typename T_schema, typename T_impl, typename T_dataset>
  71. struct read_builder<
  72. mp::list<T_schema, T_impl, T_dataset>,
  73. mp::enable_if_t<
  74. schema::is_schema_v<mp::decay_t<T_schema>>
  75. && !is_container_v<mp::decay_t<T_dataset>>
  76. && !is_nullable_v<mp::decay_t<T_dataset>>
  77. >>
  78. {
  79. static constexpr decltype(auto) apply(const T_schema& schema, T_impl& impl, T_dataset& dataset)
  80. {
  81. using real_dataset_type = real_dataset_t<mp::decay_t<T_dataset>>;
  82. auto& table = schema::find_table(schema.tables, hana::type_c<real_dataset_type>);
  83. auto& primary_key = schema::get_primary_key_field(table);
  84. return impl.read(dataset, make_modifiers(where(equal(primary_key, primary_key.getter(dataset)))));
  85. }
  86. };
  87. template<typename T_schema, typename T_impl, typename T_dataset, typename... T_modifier>
  88. struct read_builder<
  89. mp::list<T_schema, T_impl, T_dataset, T_modifier...>,
  90. mp::enable_if_t<
  91. schema::is_schema_v<mp::decay_t<T_schema>>
  92. && mp::is_true_v<is_modifier_v<T_modifier>...>
  93. && ( is_container_v<mp::decay_t<T_dataset>>
  94. || is_nullable_v<mp::decay_t<T_dataset>>)
  95. >>
  96. {
  97. static constexpr decltype(auto) apply(const T_schema& schema, T_impl& impl, T_dataset& dataset, T_modifier&&... modifier)
  98. { return impl.read(dataset, make_modifiers(std::forward<T_modifier>(modifier)...)); }
  99. };
  100. template<typename T_schema, typename T_impl, typename T_dataset, typename... T_modifier>
  101. struct read_builder<
  102. mp::list<T_schema, T_impl, T_dataset, T_modifier...>,
  103. mp::enable_if_t<
  104. schema::is_schema_v<mp::decay_t<T_schema>>
  105. && mp::is_true_v<is_modifier_v<T_modifier>...>
  106. && !is_container_v<mp::decay_t<T_dataset>>
  107. && !is_nullable_v<mp::decay_t<T_dataset>>
  108. && sizeof...(T_modifier)
  109. >>
  110. {
  111. static constexpr decltype(auto) apply(const T_schema& schema, T_impl& impl, T_dataset& dataset, T_modifier&&... modifier)
  112. { return impl.read(dataset, make_modifiers(std::forward<T_modifier>(modifier)...)); }
  113. };
  114. /* update_builder */
  115. template<typename X, typename = void>
  116. struct update_builder
  117. {
  118. template<typename... T_args>
  119. static constexpr decltype(auto) apply(T_args&&...)
  120. { static_assert(sizeof...(T_args) == -1, "Invalid parameters for context::update(...)!"); }
  121. };
  122. constexpr decltype(auto) update = mp::generic_predicate<update_builder> { };
  123. template<typename T_impl, typename T_dataset>
  124. struct update_builder<
  125. mp::list<T_impl, T_dataset>,
  126. mp::enable_if_t<
  127. mp::is_valid_v<decltype(std::declval<T_impl>().update(std::declval<T_dataset&>()))>>>
  128. {
  129. static constexpr decltype(auto) apply(T_impl& impl, T_dataset& dataset)
  130. { return impl.update(dataset); }
  131. };
  132. /* destroy_builder */
  133. template<typename X, typename = void>
  134. struct destroy_builder
  135. {
  136. template<typename... T_args>
  137. static constexpr decltype(auto) apply(T_args&&...)
  138. { static_assert(sizeof...(T_args) == -1, "Invalid parameters for context::destroy(...)!"); }
  139. };
  140. constexpr decltype(auto) destroy = mp::generic_predicate<destroy_builder> { };
  141. template<typename T_impl, typename T_dataset>
  142. struct destroy_builder<
  143. mp::list<T_impl, T_dataset>,
  144. mp::enable_if_t<
  145. mp::is_valid_v<decltype(std::declval<T_impl>().destroy(std::declval<T_dataset&>()))>>>
  146. {
  147. static constexpr decltype(auto) apply(T_impl& impl, T_dataset& dataset)
  148. { return impl.destroy(dataset); }
  149. };
  150. }
  151. /* context */
  152. template<typename T_driver, typename T_schema>
  153. template<typename... T_args>
  154. constexpr context<T_driver, T_schema>::context(const schema_type& p_schema, T_args&&... p_args)
  155. : base_type (p_schema, std::forward<T_args>(p_args)...)
  156. , _schema (p_schema)
  157. { }
  158. template<typename T_driver, typename T_schema>
  159. template<typename... T_args>
  160. constexpr decltype(auto) context<T_driver, T_schema>::init(T_args&&... args)
  161. { return __impl::init(this->impl(), std::forward<T_args>(args)...); }
  162. template<typename T_driver, typename T_schema>
  163. template<typename... T_args>
  164. constexpr decltype(auto) context<T_driver, T_schema>::create(T_args&&... args)
  165. { return __impl::create(this->impl(), std::forward<T_args>(args)...); }
  166. template<typename T_driver, typename T_schema>
  167. template<typename... T_args>
  168. constexpr decltype(auto) context<T_driver, T_schema>::read(T_args&&... args)
  169. { return __impl::read(_schema, this->impl(), std::forward<T_args>(args)...); }
  170. template<typename T_driver, typename T_schema>
  171. template<typename... T_args>
  172. constexpr decltype(auto) context<T_driver, T_schema>::update(T_args&&... args)
  173. { return __impl::update(this->impl(), std::forward<T_args>(args)...); }
  174. template<typename T_driver, typename T_schema>
  175. template<typename... T_args>
  176. constexpr decltype(auto) context<T_driver, T_schema>::destroy(T_args&&... args)
  177. { return __impl::destroy(this->impl(), std::forward<T_args>(args)...); }
  178. /* make_context */
  179. template<typename T_driver, typename T_schema, typename... T_args>
  180. constexpr decltype(auto) make_context(T_schema&& schema, T_args&&... args)
  181. {
  182. using context_type = context<T_driver, T_schema>;
  183. return context_type(std::forward<T_schema>(schema), std::forward<T_args>(args)...);
  184. }
  185. /* make_context_ptr */
  186. template<typename T_driver, typename T_schema, typename... T_args>
  187. constexpr decltype(auto) make_context_ptr(T_schema&& schema, T_args&&... args)
  188. {
  189. using context_type = context<T_driver, T_schema>;
  190. using pointer_type = std::unique_ptr<context_type>;
  191. return pointer_type(new context_type(std::forward<T_schema>(schema), std::forward<T_args>(args)...));
  192. }
  193. }