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.
 
 
 

266 lines
10 KiB

  1. #pragma once
  2. beg_namespace_cpphibernate_driver_mariadb
  3. {
  4. namespace __impl
  5. {
  6. /* declaration */
  7. template<typename T, typename = void>
  8. struct make_read_context_impl
  9. {
  10. template<typename... T_args>
  11. static constexpr decltype(auto) apply(T_args&&... args)
  12. { static_assert(sizeof...(args) == -1, "Invalid parameters for mariadb::make_read_context(...)!"); }
  13. };
  14. /* normal datasets */
  15. template<typename T_dataset, typename... T_args>
  16. struct make_read_context_impl<
  17. mp::list<T_dataset, T_args...>,
  18. mp::enable_if_c<
  19. !misc::is_container<mp::decay_t<T_dataset>>::value
  20. && !misc::is_nullable<mp::decay_t<T_dataset>>::value>>
  21. {
  22. using dataset_type = mp::decay_t<T_dataset>;
  23. struct context_impl
  24. : public read_context
  25. {
  26. private:
  27. mutable size_t _count;
  28. dataset_type& _dataset;
  29. public:
  30. template<typename... X_args>
  31. context_impl(dataset_type& dataset, X_args&&... args)
  32. : read_context (std::forward<X_args>(args)...)
  33. , _count (0)
  34. , _dataset (dataset)
  35. {
  36. is_dynamic = false;
  37. base_dataset_id = misc::get_type_id(hana::type_c<dataset_type>);
  38. }
  39. private:
  40. virtual void* emplace_intern(void* data, size_t dataset_id) const override
  41. {
  42. if (data || dataset_id != 0)
  43. throw misc::hibernate_exception("Static datasets can not be assigned!");
  44. ++_count;
  45. if (_count > 1)
  46. throw misc::hibernate_exception("Expected exactly one dataset, but received more!");
  47. return set(_dataset);
  48. }
  49. virtual void finish_intern() const override
  50. {
  51. if (_count < 1)
  52. throw misc::hibernate_exception("Expected exactly one dataset, but received none!");
  53. }
  54. };
  55. static constexpr decltype(auto) apply(dataset_type& dataset, T_args&&... args)
  56. { return context_impl(dataset, std::forward<T_args>(args)...); }
  57. };
  58. /* nullable datasets */
  59. template<typename T_dataset, typename... T_args>
  60. struct make_read_context_impl<
  61. mp::list<T_dataset, T_args...>,
  62. mp::enable_if_c<
  63. !misc::is_container<mp::decay_t<T_dataset>>::value
  64. && misc::is_nullable<mp::decay_t<T_dataset>>::value>>
  65. {
  66. using dataset_type = mp::decay_t<T_dataset>;
  67. using nullable_helper_type = misc::nullable_helper<dataset_type>;
  68. using value_type = typename nullable_helper_type::value_type;
  69. struct context_impl
  70. : public read_context
  71. {
  72. private:
  73. dataset_type& _dataset;
  74. mutable size_t _count;
  75. public:
  76. template<typename... X_args>
  77. context_impl(dataset_type& dataset, X_args&&... args)
  78. : read_context (std::forward<X_args>(args)...)
  79. , _dataset (dataset)
  80. , _count (0)
  81. {
  82. is_dynamic = misc::is_pointer<dataset_type>::value;
  83. base_dataset_id = misc::get_type_id(hana::type_c<value_type>);
  84. nullable_helper_type::clear(_dataset);
  85. }
  86. private:
  87. virtual void* emplace_intern(void* data, size_t dataset_id) const override
  88. {
  89. if (data && !misc::is_pointer<dataset_type>::value)
  90. throw misc::hibernate_exception("None pointer type can not be assigned!");
  91. ++_count;
  92. if (_count > 1)
  93. throw misc::hibernate_exception("Expected exactly one dataset, but received more!");
  94. if (data)
  95. {
  96. auto* cast = static_cast<value_type*>(data);
  97. auto& value = nullable_helper_type::set(_dataset, cast);
  98. if (cast != &value)
  99. throw misc::hibernate_exception("Nullable pointer value has changed!");
  100. return set(value, dataset_id);
  101. }
  102. else
  103. {
  104. auto& value = nullable_helper_type::set(_dataset, value_type { });
  105. return set(value);
  106. }
  107. }
  108. virtual void finish_intern() const override
  109. { }
  110. };
  111. static constexpr decltype(auto) apply(dataset_type& dataset, T_args&&... args)
  112. { return context_impl(dataset, std::forward<T_args>(args)...); }
  113. };
  114. /* container datasets */
  115. template<typename T_dataset, typename... T_args>
  116. struct make_read_context_impl<
  117. mp::list<T_dataset, T_args...>,
  118. mp::enable_if_c<
  119. misc::is_container<mp::decay_t<T_dataset>>::value
  120. && !misc::is_nullable<mp::decay_t<T_dataset>>::value>>
  121. {
  122. using dataset_type = mp::decay_t<T_dataset>;
  123. using real_dataset_type = misc::real_dataset_t<dataset_type>;
  124. using container_helper_type = misc::container_helper<dataset_type>;
  125. using value_type = typename container_helper_type::value_type;
  126. struct context_impl
  127. : public read_context
  128. {
  129. private:
  130. dataset_type& _dataset;
  131. mutable size_t _count;
  132. public:
  133. template<typename... X_args>
  134. context_impl(dataset_type& dataset, X_args&&... args)
  135. : read_context (std::forward<X_args>(args)...)
  136. , _dataset (dataset)
  137. , _count (0)
  138. {
  139. is_dynamic = misc::is_pointer<value_type>::value;
  140. base_dataset_id = misc::get_type_id(hana::type_c<real_dataset_type>);
  141. container_helper_type::clear(_dataset);
  142. }
  143. private:
  144. virtual void* emplace_intern(void* data, size_t dataset_id) const override
  145. {
  146. return hana::eval_if(
  147. misc::is_nullable<value_type> { },
  148. [this, &data, &dataset_id](auto _){
  149. using nullable_type = typename mp::decay_t<decltype(_(hana::type_c<value_type>))>::type;
  150. using nullable_helper_type = misc::nullable_helper<nullable_type>;
  151. using inner_value_type = typename nullable_helper_type::value_type;
  152. if (!data)
  153. throw misc::hibernate_exception("Expected dynamic data for pointer type!");
  154. if (!misc::is_pointer<nullable_type>::value)
  155. throw misc::hibernate_exception("None pointer type can not be assigned!");
  156. auto& nullable = container_helper_type::emplace(this->_dataset);
  157. auto* cast = static_cast<inner_value_type*>(data);
  158. auto& value = nullable_helper_type::set(nullable, cast);
  159. if (cast != &value)
  160. throw misc::hibernate_exception("Nullable pointer value has changed!");
  161. return set(value, dataset_id);
  162. },
  163. [this, &data, &dataset_id](){
  164. if (data || dataset_id != 0)
  165. throw misc::hibernate_exception("Static datasets can not be assigned!");
  166. auto& value = container_helper_type::emplace(this->_dataset);
  167. return this->set(value);
  168. });
  169. }
  170. virtual void finish_intern() const override
  171. { }
  172. };
  173. static constexpr decltype(auto) apply(dataset_type& dataset, T_args&&... args)
  174. { return context_impl(dataset, std::forward<T_args>(args)...); }
  175. };
  176. }
  177. constexpr decltype(auto) make_read_context = misc::make_generic_predicate<__impl::make_read_context_impl> { };
  178. namespace __impl
  179. {
  180. template<typename T, typename = void>
  181. struct make_fake_context_impl
  182. {
  183. template<typename... T_args>
  184. static constexpr decltype(auto) apply(T_args&&... args)
  185. { static_assert(sizeof...(args) == -1, "Invalid parameters for mariadb::make_fake_context(...)!"); }
  186. };
  187. template<typename T_wrapped_dataset, typename... T_args>
  188. struct make_fake_context_impl<
  189. mp::list<T_wrapped_dataset, T_args...>,
  190. mp::enable_if_c<
  191. hana::is_a_t<hana::type_tag, T_wrapped_dataset>::value>>
  192. {
  193. using wrapped_dataset_type = mp::decay_t<T_wrapped_dataset>;
  194. using dataset_type = misc::unwrap_t<wrapped_dataset_type>;
  195. using real_dataset_type = misc::real_dataset_t<dataset_type>;
  196. struct context_impl
  197. : public read_context
  198. {
  199. public:
  200. template<typename... X_args>
  201. context_impl(X_args&&... args)
  202. : read_context (std::forward<X_args>(args)...)
  203. {
  204. is_dynamic = misc::is_pointer<dataset_type>::value;
  205. base_dataset_id = misc::get_type_id(hana::type_c<real_dataset_type>);
  206. }
  207. private:
  208. virtual void* emplace_intern(void* data, size_t dataset_id) const override
  209. { return nullptr; }
  210. virtual void finish_intern() const override
  211. { }
  212. };
  213. static constexpr decltype(auto) apply(T_wrapped_dataset&&, T_args&&... args)
  214. { return context_impl(std::forward<T_args>(args)...); }
  215. };
  216. }
  217. constexpr decltype(auto) make_fake_context = misc::make_generic_predicate<__impl::make_fake_context_impl> { };
  218. }
  219. end_namespace_cpphibernate_driver_mariadb