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

212 строки
8.2 KiB

  1. #pragma once
  2. #include <string>
  3. #include <vector>
  4. #include <cppmariadb.h>
  5. #include "../fields/field.h"
  6. #include "../fields/fields.h"
  7. namespace cpphibernate {
  8. namespace mariadb {
  9. struct filter_t;
  10. struct schema_t;
  11. struct init_context;
  12. struct create_update_context;
  13. enum init_stage
  14. {
  15. unknown = 0,
  16. stage1,
  17. stage2,
  18. };
  19. /**
  20. * @brief Abstract table class.
  21. */
  22. struct table_t
  23. {
  24. public:
  25. using size_vector = std::vector<size_t>; //!< vector of size_t
  26. using table_vector = std::vector<const table_t *>; //!< vector of constant field pointers
  27. using field_vector = std::vector<const field_t *>; //!< vector of constant field pointers
  28. public:
  29. size_t id { 0 }; //!< unique id of the table assigned by the user
  30. size_t dataset_id { 0 }; //!< unique id of the dataset type
  31. size_t base_dataset_id { 0 }; //!< unique id of the dataset type
  32. size_vector derived_dataset_ids; //!< vector of ids of all derived dataset
  33. bool is_used_in_container { false }; //!< indicates if this table is used inside a container
  34. std::string name; //!< name of the table
  35. const schema_t& schema; //!< schema this table is owned by
  36. fields_t fields; //!< vector of fields managed by this table
  37. const table_t * base_table { nullptr }; //!< base table (if has one)
  38. table_vector derived_tables; //!< vector of pointers of all derived tables
  39. const field_t * primary_key_field { nullptr }; //!< primary key field
  40. field_vector foreign_key_fields; //!< vector of pointers of all foreign key fields
  41. field_vector foreign_table_fields; //!< vector of pointers of all foreign table fields
  42. field_vector foreign_table_one_fields; //!< vector of pointers of all foreign table one fields
  43. field_vector foreign_table_many_fields; //!< vector of pointers of all foreign table many fields
  44. field_vector data_fields; //!< vector of pointers of all normal data fields
  45. public:
  46. /**
  47. * @brief Default constructor.
  48. */
  49. inline table_t() = default;
  50. /**
  51. * @brief Value constructor. Creates a mariadb table from the cpphibernate table.
  52. *
  53. * @param[in] p_owner Owner of the table.
  54. * @param[in] p_schema Cpphibernate schema the table belongs to.
  55. * @param[in] p_table Cpphibernate table to create mariadb table for.
  56. */
  57. template<
  58. typename T_schema,
  59. typename T_table>
  60. inline table_t(
  61. const schema_t& p_owner,
  62. const T_schema& p_schema,
  63. const T_table& p_table);
  64. /**
  65. * @brief Move constructor.
  66. */
  67. inline table_t(table_t&& other) = delete;
  68. /**
  69. * @brief Copy constructor.
  70. */
  71. inline table_t(const table_t&) = delete;
  72. /**
  73. * @brief Destructor.
  74. */
  75. virtual ~table_t() = 0;
  76. /**
  77. * @brief Print the table to the passed stream.
  78. */
  79. std::ostream& print(std::ostream& os) const;
  80. public:
  81. /**
  82. * @brief Initialize the table using the passed context.
  83. *
  84. * The initialization is splitted into two stages. In the first stage the
  85. * table is created. In the second stage the table contraints are added.
  86. * The first stage must be completed for all tables before stage two of
  87. * any table is executed.
  88. *
  89. * @param[in] context Context that stores the needed data for the operation.
  90. * @param[in] stage Stage to execute.
  91. */
  92. void init(const init_context& context, init_stage stage) const;
  93. /**
  94. * @brief Execute a create/update operation on the current table.
  95. *
  96. * For a polymorphic type this will check the derived tables before executing the actual opertion.
  97. * If the dataset matches one of the dericed tables, the operation is executed on this table.
  98. * This operation also updates the base table if the dataset has one.
  99. *
  100. * @param[in] context Context that stores the needed data for the operation.
  101. *
  102. * @return Returns the key of the created/updated dataset in it's string representation.
  103. */
  104. virtual std::string create_update(const create_update_context& context) const;
  105. public:
  106. /**
  107. * @brief Get the value of the primary key of this table.
  108. *
  109. * @param[in] context Data context to get the dataset from.
  110. *
  111. * @return Value of the primary key.
  112. */
  113. std::string get_primary_key(const data_context& context) const;
  114. /**
  115. * @brief Get the value of the primary key of this table,
  116. * by fetching it from the base table.
  117. *
  118. * @param[in] context Data context to get the dataset from.
  119. *
  120. * @return Value of the primary key.
  121. */
  122. std::string get_key_from_base(const data_context& context) const;
  123. /**
  124. * @brief Execute the actual create/update operation.
  125. *
  126. * Other than create_update this will not check the derived tables. It will execute the query
  127. * and forward the operation to the base table if the dataset has one.
  128. */
  129. std::string create_update_exec(const create_update_context& context) const;
  130. private:
  131. using statement_ptr_u = std::unique_ptr<::cppmariadb::statement>;
  132. using statement_key = std::tuple<size_t, const field_t*>;
  133. using statement_map = std::map<statement_key, ::cppmariadb::statement>;
  134. mutable statement_ptr_u _statement_key_from_base; //!< Statement to fetch the key of this table from the base table.
  135. mutable statement_ptr_u _statement_init_stage1; //!< Statement for init stage 1 (create table).
  136. mutable statement_ptr_u _statement_init_stage2; //!< Statement for init stage 2 (alter table).
  137. mutable statement_ptr_u _statement_insert_into; //!< Statement for create operation (inser into)
  138. mutable statement_map _statement_update; //!< Map of all update statements
  139. /**
  140. * @brief Get the statement to fetch the key of this table from the base table.
  141. */
  142. ::cppmariadb::statement& get_statement_key_from_base() const;
  143. /**
  144. * @brief Get or create the mariadb statement for init stage 1.
  145. */
  146. ::cppmariadb::statement& get_statement_init_stage1() const;
  147. /**
  148. * @brief Get or create the mariadb statement for init stage 2.
  149. */
  150. ::cppmariadb::statement* get_statement_init_stage2() const;
  151. /**
  152. * Get the statement for the create operation. If the statement is empty nullptr is returned;
  153. */
  154. ::cppmariadb::statement* get_statement_insert_into() const;
  155. /**
  156. * Get the statement for the update operation. If the statement is empty nullptr is returned;
  157. *
  158. * @param[in] filter Filter to use for the update statement.
  159. * @param[in] owner Field the current dataset is owned by (if this table is used in a foreign field).
  160. */
  161. ::cppmariadb::statement* get_statement_update(const filter_t& filter, const field_t * owner) const;
  162. };
  163. using table_ptr_u = std::unique_ptr<const table_t>;
  164. namespace __impl
  165. {
  166. /**
  167. * @brief Helper type to build table.
  168. */
  169. template<typename X, typename = void>
  170. struct table_builder;
  171. }
  172. /**
  173. * @brief Predicate to create mariadb table class.
  174. */
  175. constexpr decltype(auto) make_table = mp::generic_predicate<__impl::table_builder> { };
  176. } }