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.
 
 
 

320 lines
13 KiB

  1. #pragma once
  2. #include <set>
  3. #include <string>
  4. #include <vector>
  5. #include <cppmariadb.h>
  6. #include "../fields/field.h"
  7. #include "../fields/fields.h"
  8. namespace cpphibernate {
  9. namespace mariadb {
  10. struct filter_t;
  11. struct schema_t;
  12. struct base_context;
  13. struct init_context;
  14. struct read_context;
  15. struct create_update_context;
  16. struct destroy_context;
  17. enum init_stage
  18. {
  19. unknown = 0,
  20. stage1,
  21. stage2,
  22. };
  23. /**
  24. * @brief Abstract table class.
  25. */
  26. struct table_t
  27. {
  28. public:
  29. using size_vector = std::vector<size_t>; //!< vector of size_t
  30. using table_vector = std::vector<const table_t *>; //!< vector of constant field pointers
  31. using field_vector = std::vector<const field_t *>; //!< vector of constant field pointers
  32. using table_set = std::set<const table_t *>; //!< set of tables
  33. public:
  34. size_t id { 0 }; //!< unique id of the table assigned by the user
  35. size_t dataset_id { 0 }; //!< unique id of the dataset type
  36. size_t base_dataset_id { 0 }; //!< unique id of the dataset type
  37. size_vector derived_dataset_ids; //!< vector of ids of all derived dataset
  38. bool is_used_in_container { false }; //!< indicates if this table is used inside a container
  39. std::string name; //!< name of the table
  40. const schema_t& schema; //!< schema this table is owned by
  41. fields_t fields; //!< vector of fields managed by this table
  42. const table_t * base_table { nullptr }; //!< base table (if has one)
  43. table_vector derived_tables; //!< vector of pointers of all derived tables
  44. const field_t * primary_key_field { nullptr }; //!< primary key field
  45. field_vector foreign_key_fields; //!< vector of pointers of all foreign key fields
  46. field_vector foreign_table_fields; //!< vector of pointers of all foreign table fields
  47. field_vector foreign_table_one_fields; //!< vector of pointers of all foreign table one fields
  48. field_vector foreign_table_many_fields; //!< vector of pointers of all foreign table many fields
  49. field_vector data_fields; //!< vector of pointers of all normal data fields
  50. public:
  51. /**
  52. * @brief Default constructor.
  53. */
  54. inline table_t() = default;
  55. /**
  56. * @brief Value constructor. Creates a mariadb table from the cpphibernate table.
  57. *
  58. * @param[in] p_owner Owner of the table.
  59. * @param[in] p_schema Cpphibernate schema the table belongs to.
  60. * @param[in] p_table Cpphibernate table to create mariadb table for.
  61. */
  62. template<
  63. typename T_schema,
  64. typename T_table>
  65. inline table_t(
  66. const schema_t& p_owner,
  67. const T_schema& p_schema,
  68. const T_table& p_table);
  69. /**
  70. * @brief Move constructor.
  71. */
  72. inline table_t(table_t&& other) = delete;
  73. /**
  74. * @brief Copy constructor.
  75. */
  76. inline table_t(const table_t&) = delete;
  77. /**
  78. * @brief Destructor.
  79. */
  80. virtual ~table_t() = 0;
  81. /**
  82. * @brief Print the table to the passed stream.
  83. */
  84. std::ostream& print(std::ostream& os) const;
  85. public:
  86. /**
  87. * @brief Initialize the table using the passed context.
  88. *
  89. * The initialization is splitted into two stages. In the first stage the
  90. * table is created. In the second stage the table contraints are added.
  91. * The first stage must be completed for all tables before stage two of
  92. * any table is executed.
  93. *
  94. * @param[in] context Context that stores the needed data for the operation.
  95. * @param[in] stage Stage to execute.
  96. */
  97. void init(const init_context& context, init_stage stage) const;
  98. /**
  99. * @brief Execute a read operation on the current table.
  100. *
  101. * @param[in] context Context that stores the needed data for the operation.
  102. */
  103. void read(const read_context& context) const;
  104. /**
  105. * @brief Execute a create/update operation on the current table.
  106. *
  107. * For a polymorphic type this will check the derived tables before executing the actual operation.
  108. * If the dataset matches one of the dericed tables, the operation is executed on this table.
  109. * This operation also updates the base table if the dataset has one.
  110. *
  111. * @param[in] context Context that stores the needed data for the operation.
  112. *
  113. * @return Returns the key of the created/updated dataset in it's string representation.
  114. */
  115. virtual std::string create_update(const create_update_context& context) const;
  116. /**
  117. * @brief Execute a destroy operation on the current table.
  118. *
  119. * For a polymorphic type this will check the derived tables before executing the actual operation.
  120. * If the dataset matches one of the dericed tables, the operation is executed on this table.
  121. * This operation also updates the base table if the dataset has one.
  122. *
  123. * @param[in] context Context that stores the needed data for the operation.
  124. */
  125. virtual void destroy(const destroy_context& context) const;
  126. /**
  127. * @brief Cleanup orphaned datasets beginning from this table.
  128. *
  129. * This operation will iterate through the different base, derived and foreign tables of this table
  130. * and delete all datasets that are not referenced at least by one other dataset.
  131. *
  132. * @param[in] context Context that stores the needed data for the operation.
  133. * @param[in] processed Contains all tables that are already cleared (to handle ring dependencies).
  134. * @param[in] check_derived Check the derived tables.
  135. * @param[in] check_base Check the base table.
  136. */
  137. void cleanup(const base_context& context, table_set& processed, bool check_derived, bool check_base) const;
  138. public:
  139. /**
  140. * @brief Get the value of the primary key of this table.
  141. *
  142. * @param[in] context Data context to get the dataset from.
  143. *
  144. * @return Value of the primary key.
  145. */
  146. std::string get_primary_key(const data_context& context) const;
  147. /**
  148. * @brief Get the value of the primary key of this table,
  149. * by fetching it from the base table.
  150. *
  151. * @param[in] context Data context to get the dataset from.
  152. *
  153. * @return Value of the primary key.
  154. */
  155. std::string get_key_from_base(const data_context& context) const;
  156. /**
  157. * @brief Execute the actual create/update operation.
  158. *
  159. * Other than the normal create_update method this will not check the derived tables.
  160. * It will execute the query and forward the operation to the base table if the dataset has one.
  161. */
  162. std::string create_update_exec(const create_update_context& context) const;
  163. /**
  164. * @brief Execute the actual destroy operation.
  165. *
  166. * Other than the normal destroy method this will not check the derived tables.
  167. * It will execute the query and forward the operation to the base table if the dataset has one.
  168. */
  169. void destroy_exec(const destroy_context& context) const;
  170. /**
  171. * @brief Delete all datasets from the table that foreign keys are all set to NULL.
  172. *
  173. * @param[in] context Context that stores the needed data for this operation.
  174. */
  175. void foreign_many_delete_exec(const base_context& context) const;
  176. /**
  177. * @brief Build the delete query for this table.
  178. *
  179. * @param[in] where Where expression to add to the delete query.
  180. *
  181. * @return The requested delete query.
  182. */
  183. std::string build_delete_query(const std::string* where) const;
  184. public:
  185. /**
  186. * @brief Emplace new dataset of the type the table represents.
  187. *
  188. * @param[in] context Context to emplace new dataset in.
  189. */
  190. virtual void emplace(const read_context& context) const;
  191. /**
  192. * @brief Get the derived table by it's dataset id
  193. *
  194. * @param[in] p_id Dataset id to get derived table for.
  195. *
  196. * @return Derived table or nullptr if table was not found.
  197. */
  198. inline const table_t* get_derived_by_dataset_id(size_t p_id) const;
  199. /**
  200. * @brief Get the derived table by it's table id
  201. *
  202. * @param[in] p_id Table id to get derived table for.
  203. *
  204. * @return Derived table or nullptr if table was not found.
  205. */
  206. inline const table_t* get_derived_by_table_id(size_t p_id) const;
  207. private:
  208. using statement_ptr_u = std::unique_ptr<::cppmariadb::statement>;
  209. using statement_key = std::tuple<size_t, const field_t*>;
  210. using statement_map = std::map<statement_key, ::cppmariadb::statement>;
  211. mutable statement_ptr_u _statement_key_from_base; //!< Statement to fetch the key of this table from the base table.
  212. mutable statement_ptr_u _statement_init_stage1; //!< Statement for init stage 1 (create table).
  213. mutable statement_ptr_u _statement_init_stage2; //!< Statement for init stage 2 (alter table).
  214. mutable statement_ptr_u _statement_insert_into; //!< Statement for create operation (inser into)
  215. mutable statement_map _statement_select_static; //!< Statement to select simple datasets from the database
  216. mutable statement_map _statement_select_dynamic; //!< Statement to select dynamic/polymorphic datasets from the database
  217. mutable statement_map _statement_update; //!< Map of all update statements
  218. mutable statement_ptr_u _statement_foreign_many_delete; //!< Statement to delete all datasets from the table that foreign keys are all set to NULL.
  219. mutable statement_ptr_u _statement_delete; //!< Statement to delete datasets from the database
  220. /**
  221. * @brief Get the statement to fetch the key of this table from the base table.
  222. */
  223. ::cppmariadb::statement& get_statement_key_from_base() const;
  224. /**
  225. * @brief Get or create the mariadb statement for init stage 1.
  226. */
  227. ::cppmariadb::statement& get_statement_init_stage1() const;
  228. /**
  229. * @brief Get or create the mariadb statement for init stage 2.
  230. */
  231. ::cppmariadb::statement* get_statement_init_stage2() const;
  232. /**
  233. * Get the statement for the create operation. If the statement is empty nullptr is returned.
  234. */
  235. ::cppmariadb::statement* get_statement_insert_into() const;
  236. /**
  237. * Get the statement for select operations.
  238. *
  239. * @param[in] filter Filter to apply to the statement.
  240. * @param[in] dynamic Get select statement for dynamic/polymorphic datasets, for simple datasets otherwise.
  241. */
  242. ::cppmariadb::statement& get_statement_select(const filter_t& filter, bool dynamic) const;
  243. /**
  244. * Get the statement for the update operation. If the statement is empty nullptr is returned;
  245. *
  246. * @param[in] filter Filter to use for the update statement.
  247. * @param[in] owner Field the current dataset is owned by (if this table is used in a foreign field).
  248. */
  249. ::cppmariadb::statement* get_statement_update(const filter_t& filter, const field_t * owner) const;
  250. /**
  251. * @brief Get the statement to delete all datasets from the table that foreign keys are all set to NULL.
  252. */
  253. ::cppmariadb::statement& get_statement_foreign_many_delete() const;
  254. /**
  255. * @brief Get statement to delete datasets from the database.
  256. */
  257. ::cppmariadb::statement& get_statement_delete() const;
  258. };
  259. using table_ptr_u = std::unique_ptr<const table_t>;
  260. namespace __impl
  261. {
  262. /**
  263. * @brief Helper type to build table.
  264. */
  265. template<typename X, typename = void>
  266. struct table_builder;
  267. }
  268. /**
  269. * @brief Predicate to create mariadb table class.
  270. */
  271. constexpr decltype(auto) make_table = mp::generic_predicate<__impl::table_builder> { };
  272. } }