|
- #pragma once
-
- #include <set>
- #include <string>
- #include <vector>
- #include <cppmariadb.h>
-
- #include "../fields/field.h"
- #include "../fields/fields.h"
-
- namespace cpphibernate {
- namespace mariadb {
-
- struct filter_t;
- struct schema_t;
- struct base_context;
- struct init_context;
- struct read_context;
- struct create_update_context;
- struct destroy_context;
-
- enum init_stage
- {
- unknown = 0,
- stage1,
- stage2,
- };
-
- /**
- * @brief Abstract table class.
- */
- struct table_t
- {
- public:
- using size_vector = std::vector<size_t>; //!< vector of size_t
- using table_vector = std::vector<const table_t *>; //!< vector of constant field pointers
- using field_vector = std::vector<const field_t *>; //!< vector of constant field pointers
- using table_set = std::set<const table_t *>; //!< set of tables
-
- public:
- size_t id { 0 }; //!< unique id of the table assigned by the user
- size_t dataset_id { 0 }; //!< unique id of the dataset type
- size_t base_dataset_id { 0 }; //!< unique id of the dataset type
- size_vector derived_dataset_ids; //!< vector of ids of all derived dataset
-
- bool is_used_in_container { false }; //!< indicates if this table is used inside a container
-
- std::string name; //!< name of the table
- const schema_t& schema; //!< schema this table is owned by
- fields_t fields; //!< vector of fields managed by this table
-
- const table_t * base_table { nullptr }; //!< base table (if has one)
- table_vector derived_tables; //!< vector of pointers of all derived tables
-
- const field_t * primary_key_field { nullptr }; //!< primary key field
- field_vector foreign_key_fields; //!< vector of pointers of all foreign key fields
- field_vector foreign_table_fields; //!< vector of pointers of all foreign table fields
- field_vector foreign_table_one_fields; //!< vector of pointers of all foreign table one fields
- field_vector foreign_table_many_fields; //!< vector of pointers of all foreign table many fields
- field_vector data_fields; //!< vector of pointers of all normal data fields
-
- public:
- /**
- * @brief Default constructor.
- */
- inline table_t() = default;
-
- /**
- * @brief Value constructor. Creates a mariadb table from the cpphibernate table.
- *
- * @param[in] p_owner Owner of the table.
- * @param[in] p_schema Cpphibernate schema the table belongs to.
- * @param[in] p_table Cpphibernate table to create mariadb table for.
- */
- template<
- typename T_schema,
- typename T_table>
- inline table_t(
- const schema_t& p_owner,
- const T_schema& p_schema,
- const T_table& p_table);
-
- /**
- * @brief Move constructor.
- */
- inline table_t(table_t&& other) = delete;
-
- /**
- * @brief Copy constructor.
- */
- inline table_t(const table_t&) = delete;
-
- /**
- * @brief Destructor.
- */
- virtual ~table_t() = 0;
-
- /**
- * @brief Print the table to the passed stream.
- */
- std::ostream& print(std::ostream& os) const;
-
- public:
- /**
- * @brief Initialize the table using the passed context.
- *
- * The initialization is splitted into two stages. In the first stage the
- * table is created. In the second stage the table contraints are added.
- * The first stage must be completed for all tables before stage two of
- * any table is executed.
- *
- * @param[in] context Context that stores the needed data for the operation.
- * @param[in] stage Stage to execute.
- */
- void init(const init_context& context, init_stage stage) const;
-
- /**
- * @brief Execute a read operation on the current table.
- *
- * @param[in] context Context that stores the needed data for the operation.
- */
- void read(const read_context& context) const;
-
- /**
- * @brief Execute a create/update operation on the current table.
- *
- * For a polymorphic type this will check the derived tables before executing the actual operation.
- * If the dataset matches one of the dericed tables, the operation is executed on this table.
- * This operation also updates the base table if the dataset has one.
- *
- * @param[in] context Context that stores the needed data for the operation.
- *
- * @return Returns the key of the created/updated dataset in it's string representation.
- */
- virtual std::string create_update(const create_update_context& context) const;
-
- /**
- * @brief Execute a destroy operation on the current table.
- *
- * For a polymorphic type this will check the derived tables before executing the actual operation.
- * If the dataset matches one of the dericed tables, the operation is executed on this table.
- * This operation also updates the base table if the dataset has one.
- *
- * @param[in] context Context that stores the needed data for the operation.
- */
- virtual void destroy(const destroy_context& context) const;
-
- /**
- * @brief Cleanup orphaned datasets beginning from this table.
- *
- * This operation will iterate through the different base, derived and foreign tables of this table
- * and delete all datasets that are not referenced at least by one other dataset.
- *
- * @param[in] context Context that stores the needed data for the operation.
- * @param[in] processed Contains all tables that are already cleared (to handle ring dependencies).
- * @param[in] check_derived Check the derived tables.
- * @param[in] check_base Check the base table.
- */
- void cleanup(const base_context& context, table_set& processed, bool check_derived, bool check_base) const;
-
- public:
- /**
- * @brief Get the value of the primary key of this table.
- *
- * @param[in] context Data context to get the dataset from.
- *
- * @return Value of the primary key.
- */
- std::string get_primary_key(const data_context& context) const;
-
- /**
- * @brief Get the value of the primary key of this table,
- * by fetching it from the base table.
- *
- * @param[in] context Data context to get the dataset from.
- *
- * @return Value of the primary key.
- */
- std::string get_key_from_base(const data_context& context) const;
-
- /**
- * @brief Execute the actual create/update operation.
- *
- * Other than the normal create_update method this will not check the derived tables.
- * It will execute the query and forward the operation to the base table if the dataset has one.
- */
- std::string create_update_exec(const create_update_context& context) const;
-
- /**
- * @brief Execute the actual destroy operation.
- *
- * Other than the normal destroy method this will not check the derived tables.
- * It will execute the query and forward the operation to the base table if the dataset has one.
- */
- void destroy_exec(const destroy_context& context) const;
-
- /**
- * @brief Delete all datasets from the table that foreign keys are all set to NULL.
- *
- * @param[in] context Context that stores the needed data for this operation.
- */
- void foreign_many_delete_exec(const base_context& context) const;
-
- /**
- * @brief Build the delete query for this table.
- *
- * @param[in] where Where expression to add to the delete query.
- *
- * @return The requested delete query.
- */
- std::string build_delete_query(const std::string* where) const;
-
- public:
- /**
- * @brief Emplace new dataset of the type the table represents.
- *
- * @param[in] context Context to emplace new dataset in.
- */
- virtual void emplace(const read_context& context) const;
-
- /**
- * @brief Get the derived table by it's dataset id
- *
- * @param[in] p_id Dataset id to get derived table for.
- *
- * @return Derived table or nullptr if table was not found.
- */
- inline const table_t* get_derived_by_dataset_id(size_t p_id) const;
-
- /**
- * @brief Get the derived table by it's table id
- *
- * @param[in] p_id Table id to get derived table for.
- *
- * @return Derived table or nullptr if table was not found.
- */
- inline const table_t* get_derived_by_table_id(size_t p_id) const;
-
- private:
- using statement_ptr_u = std::unique_ptr<::cppmariadb::statement>;
- using statement_key = std::tuple<size_t, const field_t*>;
- using statement_map = std::map<statement_key, ::cppmariadb::statement>;
-
- mutable statement_ptr_u _statement_key_from_base; //!< Statement to fetch the key of this table from the base table.
- mutable statement_ptr_u _statement_init_stage1; //!< Statement for init stage 1 (create table).
- mutable statement_ptr_u _statement_init_stage2; //!< Statement for init stage 2 (alter table).
- mutable statement_ptr_u _statement_insert_into; //!< Statement for create operation (inser into)
- mutable statement_map _statement_select_static; //!< Statement to select simple datasets from the database
- mutable statement_map _statement_select_dynamic; //!< Statement to select dynamic/polymorphic datasets from the database
- mutable statement_map _statement_update; //!< Map of all update statements
- mutable statement_ptr_u _statement_foreign_many_delete; //!< Statement to delete all datasets from the table that foreign keys are all set to NULL.
- mutable statement_ptr_u _statement_delete; //!< Statement to delete datasets from the database
-
- /**
- * @brief Get the statement to fetch the key of this table from the base table.
- */
- ::cppmariadb::statement& get_statement_key_from_base() const;
-
- /**
- * @brief Get or create the mariadb statement for init stage 1.
- */
- ::cppmariadb::statement& get_statement_init_stage1() const;
-
- /**
- * @brief Get or create the mariadb statement for init stage 2.
- */
- ::cppmariadb::statement* get_statement_init_stage2() const;
-
- /**
- * Get the statement for the create operation. If the statement is empty nullptr is returned.
- */
- ::cppmariadb::statement* get_statement_insert_into() const;
-
- /**
- * Get the statement for select operations.
- *
- * @param[in] filter Filter to apply to the statement.
- * @param[in] dynamic Get select statement for dynamic/polymorphic datasets, for simple datasets otherwise.
- */
- ::cppmariadb::statement& get_statement_select(const filter_t& filter, bool dynamic) const;
-
- /**
- * Get the statement for the update operation. If the statement is empty nullptr is returned;
- *
- * @param[in] filter Filter to use for the update statement.
- * @param[in] owner Field the current dataset is owned by (if this table is used in a foreign field).
- */
- ::cppmariadb::statement* get_statement_update(const filter_t& filter, const field_t * owner) const;
-
- /**
- * @brief Get the statement to delete all datasets from the table that foreign keys are all set to NULL.
- */
- ::cppmariadb::statement& get_statement_foreign_many_delete() const;
-
- /**
- * @brief Get statement to delete datasets from the database.
- */
- ::cppmariadb::statement& get_statement_delete() const;
- };
-
- using table_ptr_u = std::unique_ptr<const table_t>;
-
- namespace __impl
- {
-
- /**
- * @brief Helper type to build table.
- */
- template<typename X, typename = void>
- struct table_builder;
-
- }
-
- /**
- * @brief Predicate to create mariadb table class.
- */
- constexpr decltype(auto) make_table = mp::generic_predicate<__impl::table_builder> { };
-
- } }
|