選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

184 行
6.3 KiB

  1. #pragma once
  2. #include <sstream>
  3. #include <cpphibernate/config.h>
  4. #include <cpphibernate/modifier.h>
  5. #include <cpphibernate/driver/mariadb/schema/schema.h>
  6. beg_namespace_cpphibernate_driver_mariadb
  7. {
  8. /* where_builder */
  9. template<typename T_modifiers>
  10. struct where_builder
  11. {
  12. private:
  13. struct build_t
  14. {
  15. const schema_t& schema;
  16. const T_modifiers& modifiers;
  17. std::ostringstream os;
  18. inline build_t(const schema_t& p_schema, const T_modifiers& p_modifiers)
  19. : schema (p_schema)
  20. , modifiers (p_modifiers)
  21. { }
  22. template<typename T_clause>
  23. inline auto build_clause(T_clause&& clause)
  24. -> mp::enable_if<modifier::is_where_clause_and<mp::decay_t<T_clause>>>
  25. {
  26. os << "(";
  27. build_clause(os, clause.clauses[hana::size_c<0>]);
  28. os << ")";
  29. hana::for_each(
  30. hana::remove_at(clause.clauses, hana::size_c<0>),
  31. [&](auto& clause) {
  32. os << " AND (";
  33. build_clause(os, clause);
  34. os << ")";
  35. });
  36. }
  37. template<typename T_clause>
  38. inline auto build_clause(T_clause&& clause)
  39. -> mp::enable_if<modifier::is_where_clause_or<mp::decay_t<T_clause>>>
  40. {
  41. os << "(";
  42. build_clause(os, clause.clauses[hana::size_c<0>]);
  43. os << ")";
  44. hana::for_each(
  45. hana::remove_at(clause.clauses, hana::size_c<0>),
  46. [&](auto& clause) {
  47. os << " OR (";
  48. build_clause(os, clause);
  49. os << ")";
  50. });
  51. }
  52. template<typename T_clause>
  53. inline auto build_clause(T_clause&& clause)
  54. -> mp::enable_if<modifier::is_where_clause_not<mp::decay_t<T_clause>>>
  55. {
  56. os << "NOT (";
  57. build_clause(os, clause.clause);
  58. os << ")";
  59. }
  60. template<typename T_clause>
  61. inline auto build_clause(T_clause&& clause)
  62. -> mp::enable_if<modifier::is_where_clause_equal<mp::decay_t<T_clause>>>
  63. {
  64. auto field_id = misc::get_type_id(hana::type_c<mp::decay_t<decltype(clause.field)>>);
  65. auto& field = schema.field(field_id);
  66. os << "`"
  67. << field.table_name
  68. << "`.`"
  69. << field.field_name
  70. << "`="
  71. << field.convert_to_open
  72. << "?\?"
  73. << field.convert_to_close;
  74. }
  75. inline void build(::cppmariadb::statement& statement)
  76. {
  77. size_t index = 0;
  78. hana::for_each(modifiers, [&](auto& modifier){
  79. using modifier_type = mp::decay_t<decltype(modifier)>;
  80. using is_where_type = modifier::is_where_modifier<modifier_type>;
  81. hana::eval_if(
  82. is_where_type { },
  83. [&](auto _){
  84. if (index++ == 0) os << "WHERE (";
  85. else os << " AND (";
  86. build_clause(_(modifier).clause);
  87. os << ")";
  88. },
  89. []{ });
  90. });
  91. os << ")";
  92. statement.assign(os.str());
  93. }
  94. };
  95. struct assign_t
  96. {
  97. ::cppmariadb::statement& statement;
  98. const T_modifiers& modifiers;
  99. size_t index { 0 };
  100. inline assign_t(::cppmariadb::statement& p_statement, const T_modifiers& p_modifiers)
  101. : statement(p_statement)
  102. , modifiers(p_modifiers)
  103. { }
  104. template<typename T_clause>
  105. inline auto assign_clause(T_clause&& clause)
  106. -> mp::enable_if_c<
  107. modifier::is_where_clause_and<mp::decay_t<T_clause>>::value
  108. || modifier::is_where_clause_or <mp::decay_t<T_clause>>::value>
  109. {
  110. hana::for_each([&](auto& clause) {
  111. assign_clause(clause);
  112. });
  113. }
  114. template<typename T_clause>
  115. inline auto assign_clause(T_clause&& clause)
  116. -> mp::enable_if<modifier::is_where_clause_not<mp::decay_t<T_clause>>>
  117. {
  118. assign_clause(clause.clause);
  119. }
  120. template<typename T_clause>
  121. inline auto assign_clause(T_clause&& clause)
  122. -> mp::enable_if<modifier::is_where_clause_equal<mp::decay_t<T_clause>>>
  123. {
  124. statement.set(index, clause.value);
  125. ++index;
  126. }
  127. inline void assign()
  128. {
  129. hana::for_each(modifiers, [&](auto& modifier){
  130. using modifier_type = mp::decay_t<decltype(modifier)>;
  131. using is_where_type = modifier::is_where_modifier<modifier_type>;
  132. hana::eval_if(
  133. is_where_type { },
  134. [&](auto _){
  135. assign_clause(_(modifier).clause);
  136. },
  137. []{ });
  138. });
  139. }
  140. };
  141. private:
  142. const schema_t* _schema { nullptr };
  143. ::cppmariadb::statement _statement;
  144. public:
  145. inline ::cppmariadb::statement& assign(const schema_t& schema, const T_modifiers& modifiers)
  146. {
  147. if (_schema != &schema)
  148. {
  149. build_t(schema, modifiers).build(_statement);
  150. _schema = &schema;
  151. }
  152. assign_t(_statement, modifiers).assign();
  153. return _statement;
  154. }
  155. };
  156. template<typename T_modifiers>
  157. inline decltype(auto) build_where(const schema_t& schema, const T_modifiers& modifiers)
  158. {
  159. static where_builder<T_modifiers> builder;
  160. return builder.assign(schema, modifiers);
  161. }
  162. }
  163. end_namespace_cpphibernate_driver_mariadb