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.
 
 
 

215 lines
8.6 KiB

  1. #pragma once
  2. #include <cppmariadb.h>
  3. #include "../../types.h"
  4. #include "../attributes/attributes.h"
  5. namespace cpphibernate {
  6. namespace mariadb {
  7. struct table_t;
  8. struct data_context;
  9. struct create_update_context;
  10. struct read_context;
  11. using read_context_ptr_u = std::unique_ptr<read_context>;
  12. /**
  13. * @brief Abstract field class.
  14. */
  15. struct field_t
  16. {
  17. public:
  18. size_t id { 0 }; //!< unique id of the field
  19. size_t value_id { 0 }; //!< unique id of the value type
  20. size_t real_value_id { 0 }; //!< unique id of the real/unwrapped value type
  21. bool value_is_nullable { false }; //!< value is stored in a nullable container
  22. bool value_is_pointer { false }; //!< value is stored in a pointer container
  23. bool value_is_container { false }; //!< value is stored in a container
  24. bool value_is_ordered { false }; //!< value is stored in a ordered container (vector, list, ...)
  25. bool value_is_auto_incremented { false }; //!< value is a auto incremented field
  26. const table_t& table; //!< table this field belongs to
  27. const table_t* referenced_table { nullptr }; //!< table that belongs to the value (if exists)
  28. std::string name; //!< name of the SQL field
  29. std::string type; //!< SQL type name
  30. std::string create_arguments; //!< additional arguments for CREATE TABLE command
  31. std::string convert_to_open; //!< SQL code to open the "convert to" operation
  32. std::string convert_to_close; //!< SQL code to close the "convert to" operation
  33. std::string convert_from_open; //!< SQL code to open the "convert from" operation
  34. std::string convert_from_close; //!< SQL code to close the "convert from" operation
  35. attributes_t attributes; //!< attributes for the field
  36. public:
  37. /**
  38. * @brief Value constructor. Creates a mariadb field from the cpphibernate field.
  39. *
  40. * @param[in] p_owner Owner of the field.
  41. * @param[in] p_schema Cpphibernate schema the mariadb field belongs to.
  42. * @param[in] p_table Cpphibernate table the mariadb field belongs to.
  43. * @param[in] p_field Cpphibernate field to create mariadb field for.
  44. */
  45. template<
  46. typename T_schema,
  47. typename T_table,
  48. typename T_field>
  49. inline field_t(
  50. const table_t& p_owner,
  51. const T_schema& p_schema,
  52. const T_table& p_table,
  53. const T_field& p_field);
  54. /**
  55. * @brief Move constructor.
  56. */
  57. inline field_t(field_t&& other) = delete;
  58. /**
  59. * @brief Copy constructor.
  60. */
  61. inline field_t(const field_t&) = delete;
  62. /**
  63. * @brief Destructor.
  64. */
  65. virtual ~field_t() = 0;
  66. /**
  67. * @brief Print the field values to the passed stream.
  68. */
  69. std::ostream& print(std::ostream& os) const;
  70. public:
  71. /**
  72. * @brief Get the value of this field from the current dataset.
  73. *
  74. * @param[in] context Data context to get the dataset from.
  75. *
  76. * @return Value of the field from the current dataset.
  77. */
  78. virtual value_t get(const data_context& context) const;
  79. /**
  80. * @brief Set a new value of this field in the current dataset.
  81. *
  82. * @param[in] context Data context to get the dataset from.
  83. * @param[in] value Value of the field to assign to the dataset.
  84. */
  85. virtual void set(const data_context& context, const value_t& value) const;
  86. /**
  87. * @brief Check if the value that is represented by this field has the default value.
  88. *
  89. * @param[in] context Data context to receive the value of the assigned dataset.
  90. *
  91. * @retval true If the dataset in the context is the default value for this field.
  92. * @retval false If the dataset in the context is not the default value for this field.
  93. */
  94. virtual bool is_default(const data_context& context) const;
  95. /**
  96. * @brief Create a new value that is represented by this field.
  97. *
  98. * @param[in] connection Connection to use to create the value.
  99. *
  100. * @return New created value for this field.
  101. */
  102. virtual std::string generate_value(::cppmariadb::connection& connection) const;
  103. public:
  104. /**
  105. * @brief Execute a create/update operation on the foreign table this field represents (if it is a foreign field)
  106. *
  107. * @param[in] context Create/Update context with the needed data for the operation.
  108. *
  109. * @return Key of the created/updated foreign dataset.
  110. */
  111. virtual value_t foreign_create_update(const create_update_context& context) const;
  112. /**
  113. * @brief Create a read context for the foreign key field.
  114. *
  115. * @param[in] context Read context to inherit new context from.
  116. * @param[in] create_fake Create a fake context (not data will be written).
  117. *
  118. * @return The created read context.
  119. */
  120. virtual read_context_ptr_u foreign_read(const read_context& context, bool create_fake) const;
  121. /**
  122. * @brief Delete all old datasets from the foreign table.
  123. *
  124. * If we update an exsisting foreign field with a new foreign dataset, the key of this dataset
  125. * changes. So we need to delete the old/exsisting foreign dataset from the database.
  126. *
  127. * @param[in] context Create/Update context with the needed data for the operation.
  128. * @param[in] primary_key Primary key of the current database.
  129. * @param[in] foreign_key Primary kes of the new foreign dataset.
  130. */
  131. void foreign_one_delete(
  132. const create_update_context& context,
  133. const std::string& primary_key,
  134. const value_t& foreign_key) const;
  135. /**
  136. * @brief Update the foreign dataset. Set the foreign key field to NULL if it matches the passed
  137. * primary key of the owner dataset.
  138. */
  139. void foreign_many_update(
  140. const create_update_context& context,
  141. const std::string& primary_key) const;
  142. private:
  143. /**
  144. * @brief Initialize the field.
  145. */
  146. void init();
  147. private:
  148. using statement_ptr_u = std::unique_ptr<::cppmariadb::statement>;
  149. mutable statement_ptr_u _statement_foreign_one_delete_key_known; //!< Statement to delete foreign datasets within an update operation (for known foreign keys)
  150. mutable statement_ptr_u _statement_foreign_one_delete_key_unknown; //!< Statement to delete foreign datasets within an update operation (for unknown foreign keys)
  151. mutable statement_ptr_u _statement_foreign_many_update; //!< Statement to update foreign many dataset (set foreign key to NULL if primary key of the owner matches)
  152. /**
  153. * @brief Get the statement to delete foreign datasets within an update operation (for known foreign keys).
  154. */
  155. ::cppmariadb::statement& get_statement_foreign_one_delete_key_known() const;
  156. /**
  157. * @brief Get the statement to delete foreign datasets within an update operation (for unknown foreign keys).
  158. */
  159. ::cppmariadb::statement& get_statement_foreign_one_delete_key_unknown() const;
  160. /**
  161. * @brief Get the statement to update foreign many dataset (set foreign key to NULL if primary key of the owner matches).
  162. */
  163. ::cppmariadb::statement& get_statement_foreign_many_update() const;
  164. };
  165. using field_ptr_u = std::unique_ptr<const field_t>;
  166. namespace __impl
  167. {
  168. /**
  169. * @brief Helper type to build table.
  170. */
  171. template<typename X, typename = void>
  172. struct field_builder;
  173. }
  174. /**
  175. * @brief Predicate to create mariadb table class.
  176. */
  177. constexpr decltype(auto) make_field = mp::generic_predicate<__impl::field_builder> { };
  178. } }