Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

228 строки
8.4 KiB

  1. #pragma once
  2. #include <cpphibernate/driver/mariadb/schema/field.h>
  3. #include <cpphibernate/driver/mariadb/impl/create_update.h>
  4. beg_namespace_cpphibernate_driver_mariadb
  5. {
  6. /* simple_field_t */
  7. template<typename T_field>
  8. void simple_field_t<T_field>
  9. ::update()
  10. {
  11. base_type::update();
  12. id = misc::get_type_id(hana::type_c<field_type>);
  13. dataset_id = misc::get_type_id(hana::type_c<dataset_type>);
  14. real_dataset_id = misc::get_type_id(hana::type_c<real_dataset_type>);
  15. value_id = misc::get_type_id(hana::type_c<value_type>);
  16. real_value_id = misc::get_type_id(hana::type_c<real_value_type>);
  17. value_is_nullable = misc::is_nullable<value_type>::value;
  18. value_is_pointer = misc::is_pointer<value_type>::value;
  19. value_is_container = misc::is_container<value_type>::value;
  20. value_is_ordered = misc::is_ordered<value_type>::value;
  21. }
  22. /* value_field_t */
  23. template<typename T_field>
  24. void value_field_t<T_field>
  25. ::update()
  26. {
  27. base_type::update();
  28. this->type = type_props::type();
  29. if (type_props::convert_to_open())
  30. this->convert_to_open = this->convert_to_open + type_props::convert_to_open();
  31. if (type_props::convert_to_close())
  32. this->convert_to_close = type_props::convert_to_close() + this->convert_to_close;
  33. if (type_props::convert_from_open())
  34. this->convert_from_open = this->convert_from_open + type_props::convert_from_open();
  35. if (type_props::convert_from_close())
  36. this->convert_from_close = type_props::convert_from_close() + this->convert_from_close;
  37. }
  38. template<typename T_field>
  39. value_t value_field_t<T_field>
  40. ::get(const data_context& context) const
  41. {
  42. auto& dataset = context.get<dataset_type>();
  43. return type_props::convert_from(this->field.getter(dataset));
  44. }
  45. template<typename T_field>
  46. void value_field_t<T_field>
  47. ::set(const data_context& context, const value_t& value) const
  48. {
  49. auto& dataset = context.get<dataset_type>();
  50. this->field.setter(dataset, type_props::convert_to(value));
  51. }
  52. /* primary_key_field_t */
  53. template<typename T_field>
  54. void primary_key_field_t<T_field>
  55. ::update()
  56. {
  57. base_type::update();
  58. this->value_is_auto_incremented = key_props::auto_generated::value;
  59. }
  60. template<typename T_field>
  61. bool primary_key_field_t<T_field>
  62. ::is_default(const data_context& context) const
  63. {
  64. auto& dataset = context.get<dataset_type>();
  65. return key_props::is_default(this->field.getter(dataset));
  66. }
  67. template<typename T_field>
  68. std::string primary_key_field_t<T_field>
  69. ::generate_value(::cppmariadb::connection& connection) const
  70. {
  71. auto ret = connection.execute_used(key_props::create_key_query);
  72. if (!ret || !ret->next())
  73. throw misc::hibernate_exception("unable to generate key value!");
  74. return ret->current()->at(0).template get<std::string>();
  75. }
  76. /* foreign_table_field_t */
  77. template<typename T_field>
  78. value_t foreign_table_field_t<T_field>
  79. ::foreign_create_update(const create_update_context& context) const
  80. {
  81. auto& dataset = context.get<dataset_type>();
  82. auto& foreign = this->field.getter(dataset);
  83. auto next_context = change_context(context, foreign);
  84. using foreign_dataset_type = mp::decay_t<decltype(foreign)>;
  85. return create_update_impl_t<foreign_dataset_type>::apply(
  86. next_context,
  87. false);
  88. }
  89. template<typename T_field>
  90. read_context_ptr foreign_table_field_t<T_field>
  91. ::foreign_read(const read_context& context, bool fake_context) const
  92. {
  93. if (!fake_context)
  94. {
  95. auto& dataset = context.get<dataset_type>();
  96. auto& member = this->field.getter(dataset);
  97. auto new_context = make_read_context(member, context.schema, context.connection, context.filter);
  98. using context_type = mp::decay_t<decltype(new_context)>;
  99. return std::make_unique<context_type>(new_context);
  100. }
  101. else
  102. {
  103. auto new_context = make_fake_context(hana::type_c<value_type>, context.schema, context.connection, context.filter);
  104. using context_type = mp::decay_t<decltype(new_context)>;
  105. return std::make_unique<context_type>(new_context);
  106. }
  107. }
  108. template<typename T_field>
  109. ::cppmariadb::statement& foreign_table_field_t<T_field>
  110. ::get_statement_foreign_one_delete(bool key_known) const
  111. {
  112. return base_type::get_statement_foreign_one_delete_impl(
  113. key_known,
  114. _statement_foreign_one_delete_key_known,
  115. _statement_foreign_one_delete_key_unknown);
  116. }
  117. template<typename T_field>
  118. ::cppmariadb::statement& foreign_table_field_t<T_field>
  119. ::get_statement_foreign_many_update() const
  120. { return base_type::get_statement_foreign_many_update_impl(_statement_foreign_many_update); }
  121. namespace __impl
  122. {
  123. /* is_primary_key_field */
  124. template<typename T_field>
  125. struct is_primary_key_field
  126. : public mp::decay_t<decltype(
  127. hana::contains(
  128. std::declval<T_field>().attributes,
  129. schema::attribute::primary_key))>
  130. { };
  131. /* is_foreign_table_field */
  132. template<typename T_schema, typename T_field>
  133. struct is_foreign_table_field
  134. : public mp::decay_t<decltype(
  135. hana::contains(
  136. hana::transform(
  137. std::declval<T_schema>().tables,
  138. schema::table::get_wrapped_dataset),
  139. hana::type_c<misc::real_dataset_t<typename T_field::getter_type::value_type>>))>
  140. { };
  141. /* field_type */
  142. template<typename T_schema, typename T_field, typename = void>
  143. struct field_type
  144. { using type = data_field_t<T_field>; };
  145. template<typename T_schema, typename T_field>
  146. struct field_type<T_schema, T_field, mp::enable_if<is_primary_key_field<T_field>>>
  147. { using type = primary_key_field_t<T_field>; };
  148. template<typename T_schema, typename T_field>
  149. struct field_type<T_schema, T_field, mp::enable_if<is_foreign_table_field<T_schema, T_field>>>
  150. { using type = foreign_table_field_t<T_field>; };
  151. template<typename T_schema, typename T_field>
  152. using field_type_t = typename field_type<T_schema, T_field>::type;
  153. /* make_field_impl */
  154. template<typename T, typename>
  155. struct make_field_impl
  156. {
  157. template<typename... T_args>
  158. static constexpr decltype(auto) apply(T_args&&... args)
  159. { static_assert(sizeof...(args) == -1, "Invalid parameters for mariadb::make_field(...)!"); }
  160. };
  161. template<typename T_schema, typename T_table, typename T_field>
  162. struct make_field_impl<
  163. mp::list<T_schema, T_table, T_field>,
  164. mp::enable_if_c<
  165. schema::is_schema<mp::decay_t<T_schema>>::value
  166. && schema::is_table <mp::decay_t<T_table >>::value
  167. && schema::is_field <mp::decay_t<T_field >>::value>>
  168. {
  169. static constexpr decltype(auto) apply(const T_schema& schema, const T_table& table, const T_field& field)
  170. {
  171. using schema_type = mp::decay_t<T_schema>;
  172. using field_type = mp::decay_t<T_field>;
  173. using return_type = field_type_t<schema_type, field_type>;
  174. using primary_key_type = primary_key_field_t<field_type>;
  175. return_type ret(field);
  176. ret.schema_name = schema.name;
  177. ret.table_name = table.name;
  178. ret.field_name = field.name;
  179. ret.attributes = make_attributes(field.attributes);
  180. hana::eval_if(
  181. hana::equal(hana::type_c<return_type>, hana::type_c<primary_key_type>),
  182. [&ret](){
  183. ret.field_name = ret.table_name + "_" + ret.field_name;
  184. }, [](){ });
  185. return ret;
  186. }
  187. };
  188. }
  189. }
  190. end_namespace_cpphibernate_driver_mariadb