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.
 
 
 

277 lines
9.5 KiB

  1. #include <string>
  2. #include <iostream>
  3. #include <cpputils/misc/enum.h>
  4. #include <cpputils/misc/string.h>
  5. #include <cpputils/misc/indent.h>
  6. #include <cpphibernate/misc.h>
  7. #include <cpphibernate/driver/mariadb/schema/field.h>
  8. #include <cpphibernate/driver/mariadb/schema/table.h>
  9. using namespace ::std;
  10. using namespace ::utl;
  11. using namespace ::cpphibernate::driver::mariadb_impl;
  12. void field_t::print(std::ostream& os) const
  13. {
  14. os << indent << '{'
  15. << incindent
  16. << indent << "\"id\": " << id << ","
  17. << indent << "\"dataset_id\": " << dataset_id << ","
  18. << indent << "\"real_dataset_id\": " << real_dataset_id << ","
  19. << indent << "\"value_id\": " << value_id << ","
  20. << indent << "\"real_value_id\": " << real_value_id << ","
  21. << indent << "\"value_is_nullable\": " << (value_is_nullable ? "true" : "false") << ","
  22. << indent << "\"value_is_pointer\": " << (value_is_pointer ? "true" : "false") << ","
  23. << indent << "\"value_is_container\": " << (value_is_container ? "true" : "false") << ","
  24. << indent << "\"value_is_auto_incremented\": " << (value_is_auto_incremented ? "true" : "false") << ","
  25. << indent << "\"table\": " << (table ? std::string("\"") + table->table_name + "\"" : "null") << ","
  26. << indent << "\"referenced_table\": " << (referenced_table ? std::string("\"") + referenced_table->table_name + "\"" : "null") << ","
  27. << indent << "\"schema_name\": \"" << schema_name << "\","
  28. << indent << "\"table_name\": \"" << table_name << "\","
  29. << indent << "\"field_name\": \"" << field_name << "\","
  30. << indent << "\"type\": \"" << type << "\","
  31. << indent << "\"create_arguments\": \"" << create_arguments << "\","
  32. << indent << "\"convert_to_open\": \"" << convert_to_open << "\","
  33. << indent << "\"convert_to_close\": \"" << convert_to_close << "\","
  34. << indent << "\"convert_from_open\": \"" << convert_from_open << "\","
  35. << indent << "\"convert_from_close\": \"" << convert_from_close << "\","
  36. << indent << "\"attributes\": " << misc::print_container(attributes, false)
  37. << decindent
  38. << indent << '}';
  39. }
  40. void field_t::update()
  41. {
  42. id = 0;
  43. dataset_id = 0;
  44. real_dataset_id = 0;
  45. value_id = 0;
  46. real_value_id = 0;
  47. value_is_nullable = false;
  48. value_is_container = false;
  49. value_is_auto_incremented = false;
  50. table = nullptr;
  51. referenced_table = nullptr;
  52. type.clear();
  53. create_arguments.clear();
  54. /* conver_to_open */
  55. {
  56. std::ostringstream ss;
  57. for (auto it = this->attributes.begin(); it != this->attributes.end(); ++it)
  58. {
  59. switch(*it)
  60. {
  61. case attribute_t::hex:
  62. ss << "HEX(";
  63. break;
  64. case attribute_t::compress:
  65. ss << "COMPRESS(";
  66. break;
  67. case attribute_t::primary_key:
  68. ss << "UuidToBin(";
  69. break;
  70. }
  71. }
  72. convert_to_open = ss.str();
  73. }
  74. /* convert_to_close */
  75. {
  76. std::ostringstream ss;
  77. for (auto it = this->attributes.begin(); it != this->attributes.end(); ++it)
  78. {
  79. switch(*it)
  80. {
  81. case attribute_t::hex:
  82. case attribute_t::compress:
  83. case attribute_t::primary_key:
  84. ss << ')';
  85. break;
  86. }
  87. }
  88. convert_to_close = ss.str();
  89. }
  90. /* convert_from_open */
  91. {
  92. std::ostringstream ss;
  93. for (auto it = this->attributes.rbegin(); it != this->attributes.rend(); ++it)
  94. {
  95. switch(*it)
  96. {
  97. case attribute_t::hex:
  98. ss << "UNHEX(";
  99. break;
  100. case attribute_t::compress:
  101. ss << "UNCOMPRESS(";
  102. break;
  103. case attribute_t::primary_key:
  104. ss << "BinToUuid(";
  105. break;
  106. }
  107. }
  108. convert_from_open = ss.str();
  109. }
  110. /* convert_from_close */
  111. {
  112. std::ostringstream ss;
  113. for (auto it = this->attributes.rbegin(); it != this->attributes.rend(); ++it)
  114. {
  115. switch(*it)
  116. {
  117. case attribute_t::hex:
  118. case attribute_t::compress:
  119. case attribute_t::primary_key:
  120. ss << ')';
  121. break;
  122. }
  123. }
  124. convert_from_close = ss.str();
  125. }
  126. }
  127. #define throw_not_implemented(p_ret, p_name, ...) \
  128. p_ret field_t::p_name(__VA_ARGS__) const \
  129. { \
  130. throw misc::hibernate_exception( \
  131. std::string("'") + table_name + "." + field_name + \
  132. "' does not implement the " #p_name "() method!"); \
  133. }
  134. /* CRUD */
  135. throw_not_implemented(value_t, foreign_create_update, const create_update_context&)
  136. throw_not_implemented(read_context_ptr, foreign_read, const read_context&, bool fake_context)
  137. /* properties */
  138. throw_not_implemented(bool, is_default, const data_context& context)
  139. throw_not_implemented(string, generate_value, ::cppmariadb::connection&)
  140. throw_not_implemented(value_t, get, const data_context& context)
  141. throw_not_implemented(void, set, const data_context& context, const value_t&)
  142. /* statements */
  143. throw_not_implemented(::cppmariadb::statement&, get_statement_foreign_one_delete, bool)
  144. throw_not_implemented(::cppmariadb::statement&, get_statement_foreign_many_update)
  145. ::cppmariadb::statement& field_t::get_statement_foreign_one_delete_impl(bool key_known, statement_ptr& known, statement_ptr& unknown) const
  146. {
  147. assert(table);
  148. assert(table->primary_key_field);
  149. assert(referenced_table);
  150. assert(referenced_table->primary_key_field);
  151. if (key_known)
  152. {
  153. if (!known)
  154. {
  155. auto& ref_table = *referenced_table;
  156. auto& key_info = *table->primary_key_field;
  157. auto& ref_key_info = *ref_table.primary_key_field;
  158. std::ostringstream os;
  159. os << "WHERE `"
  160. << ref_key_info.field_name
  161. << "` IN (SELECT `"
  162. << ref_key_info.table_name
  163. << "_id_"
  164. << field_name
  165. << "` FROM `"
  166. << key_info.table_name
  167. << "` WHERE `"
  168. << key_info.field_name
  169. << "`="
  170. << key_info.convert_to_open
  171. << "?\?"
  172. << key_info.convert_to_close
  173. << " AND `"
  174. << ref_key_info.table_name
  175. << "_id_"
  176. << field_name
  177. << "`!= "
  178. << ref_key_info.convert_to_open
  179. << "?\?"
  180. << ref_key_info.convert_to_close
  181. << ")";
  182. auto where = os.str();
  183. auto query = ref_table.build_delete_query(&where);
  184. known.reset(new ::cppmariadb::statement(query));
  185. }
  186. return *known;
  187. }
  188. else
  189. {
  190. if (!unknown)
  191. {
  192. auto& ref_table = *referenced_table;
  193. auto& key_info = *table->primary_key_field;
  194. auto& ref_key_info = *ref_table.primary_key_field;
  195. std::ostringstream os;
  196. os << "WHERE `"
  197. << ref_key_info.field_name
  198. << "` IN (SELECT `"
  199. << ref_key_info.table_name
  200. << "_id_"
  201. << field_name
  202. << "` FROM `"
  203. << key_info.table_name
  204. << "` WHERE `"
  205. << key_info.field_name
  206. << "`="
  207. << key_info.convert_to_open
  208. << "?\?"
  209. << key_info.convert_to_close
  210. << ")";
  211. auto where = os.str();
  212. auto query = ref_table.build_delete_query(&where);
  213. unknown.reset(new ::cppmariadb::statement(query));
  214. }
  215. return *unknown;
  216. }
  217. }
  218. ::cppmariadb::statement& field_t::get_statement_foreign_many_update_impl(statement_ptr& statement) const
  219. {
  220. assert(referenced_table);
  221. assert(referenced_table->primary_key_field);
  222. if (!statement)
  223. {
  224. auto& ref_key_info = *referenced_table->primary_key_field;
  225. std::ostringstream os;
  226. os << "UPDATE `"
  227. << ref_key_info.table_name
  228. << "` SET `"
  229. << ref_key_info.table_name
  230. << "_id_"
  231. << field_name
  232. << "`=NULL, `"
  233. << ref_key_info.table_name
  234. << "_index_"
  235. << field_name
  236. << "`=0 WHERE `"
  237. << ref_key_info.table_name
  238. << "_id_"
  239. << field_name
  240. << "`="
  241. << ref_key_info.convert_to_open
  242. << "?\?"
  243. << ref_key_info.convert_to_close;
  244. statement.reset(new ::cppmariadb::statement(os.str()));
  245. }
  246. return *statement;
  247. }