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.
 
 
 

183 line
6.2 KiB

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