diff --git a/include/cpphibernate.h b/include/cpphibernate.h index 3dbc55a..e895d5b 100644 --- a/include/cpphibernate.h +++ b/include/cpphibernate.h @@ -1,5 +1,6 @@ #pragma once +#include "cpphibernate/context.h" #include "cpphibernate/misc.h" #include "cpphibernate/modifier.h" #include "cpphibernate/schema.h" diff --git a/include/cpphibernate/context.h b/include/cpphibernate/context.h new file mode 100644 index 0000000..e3e2b6c --- /dev/null +++ b/include/cpphibernate/context.h @@ -0,0 +1,3 @@ +#pragma once + +#include "context/context.h" diff --git a/include/cpphibernate/context/context.h b/include/cpphibernate/context/context.h new file mode 100644 index 0000000..ef2c7e9 --- /dev/null +++ b/include/cpphibernate/context/context.h @@ -0,0 +1,106 @@ +#pragma once + +#include + +namespace cpphibernate +{ + + /** + * @brief Context class for cpphibernate. + */ + template + struct context + : public T_driver + { + public: + using base_type = T_driver; + using driver_type = T_driver; + using schema_type = T_schema; + + private: + const schema_type& _schema; + + public: + /** + * @brief Value constructor. Create a new context object. + * + * @param p_schema Database schema to use. + * @param p_args Arguments to pass to underlying driver. + */ + template + constexpr context(const schema_type& p_schema, T_args&&... p_args); + + /** + * @brief Nove constructor. + */ + constexpr context(context&&) = default; + + /** + * @brief Copy constrcutor. + */ + constexpr context(const context&) = default; + + /** + * @brief Initialize the database. This will create all non exsitsing tables. + */ + template + constexpr decltype(auto) init(T_args&&... args); + + /** + * @brief Create the passed object in the database. + */ + template + constexpr decltype(auto) create(T_args&&... args); + + /** + * @brief Read an object from the database. + */ + template + constexpr decltype(auto) read(T_args&&... args); + + /** + * @brief Update the passed object in the database. + */ + template + constexpr decltype(auto) update(T_args&&... args); + + /** + * @brief Destroy the passed object in the database. + */ + template + constexpr decltype(auto) destroy(T_args&&... args); + }; + + /** + * @brief Create a new cpphibernate context. + * + * @tparam T_driver Hibernate driver to use. + * @tparam T_schema Database schema to use. + * @tparam T_args Arguments to pass to underlying driver implementation. + * + * @param schema Database schema to use. + * @param args Arguments to pass to underlying driver implementation. + * + * @return Created hibernate context. + */ + template + constexpr decltype(auto) make_context(T_schema&& schema, T_args&&... args); + + /** + * @brief Create a new cpphibernate context as a unique pointer. + * + * @tparam T_driver Hibernate driver to use. + * @tparam T_schema Database schema to use. + * @tparam T_args Arguments to pass to underlying driver implementation. + * + * @param schema Database schema to use. + * @param args Arguments to pass to underlying driver implementation. + * + * @return Unique pointer of the created hibernate context. + */ + template + constexpr decltype(auto) make_context_ptr(T_schema&& schema, T_args&&... args); + +} + +#include "context.inl" diff --git a/include/cpphibernate/context/context.inl b/include/cpphibernate/context/context.inl new file mode 100644 index 0000000..290ea4d --- /dev/null +++ b/include/cpphibernate/context/context.inl @@ -0,0 +1,203 @@ +#pragma once + +#include "context.h" + +namespace cpphibernate +{ + + namespace __impl + { + + /* init_builder */ + + template + struct init_builder + { + template + static constexpr decltype(auto) apply(T_args&&...) + { static_assert(sizeof...(T_args) == -1, "Invalid parameters for context::init(...)!"); } + }; + + constexpr decltype(auto) init = mp::generic_predicate { }; +#if 0 + template + struct init_builder, void> + { + static constexpr decltype(auto) apply(T_impl& impl, bool recreate) + { return impl.init(recreate); } + }; +#endif + /* create_builder */ + + template + struct create_builder + { + template + static constexpr decltype(auto) apply(T_args&&...) + { static_assert(sizeof...(T_args) == -1, "Invalid parameters for context::create(...)!"); } + }; + + constexpr decltype(auto) create = mp::generic_predicate { }; +#if 0 + template + struct create_impl, void> + { + static constexpr decltype(auto) apply(T_impl& impl, T_dataset& dataset) + { return impl.create(dataset); } + }; +#endif + /* read_builder */ + + template + struct read_builder + { + template + static constexpr decltype(auto) apply(T_args&&...) + { static_assert(sizeof...(T_args) == -1, "Invalid parameters for context::read(...)!"); } + }; + + constexpr decltype(auto) read = mp::generic_predicate { }; +#if 0 + template + struct create_impl< + mp::list, + mp::enable_if_t>...>>> + { + static constexpr decltype(auto) apply(T_impl& impl, T_dataset& dataset, T_modifiers&&... modifiers) + { return impl.read(dataset, make_modifiers(std::forward(modifiers)...)); } + }; +#endif + /* update_builder */ + + template + struct update_builder + { + template + static constexpr decltype(auto) apply(T_args&&...) + { static_assert(sizeof...(T_args) == -1, "Invalid parameters for context::update(...)!"); } + }; + + constexpr decltype(auto) update = mp::generic_predicate { }; +#if 0 + template + struct update_impl, void> + { + static constexpr decltype(auto) apply(T_impl& impl, T_dataset& dataset) + { return impl.update(dataset); } + }; +#endif + /* destroy_builder */ + + template + struct destroy_builder + { + template + static constexpr decltype(auto) apply(T_args&&...) + { static_assert(sizeof...(T_args) == -1, "Invalid parameters for context::destroy(...)!"); } + }; + + constexpr decltype(auto) destroy = mp::generic_predicate { }; +#if 0 + template + struct destroy_impl, void> + { + static constexpr decltype(auto) apply(T_impl& impl, T_dataset& dataset) + { return impl.create(dataset); } + }; +#endif + + } + + /* context */ + + template + template + constexpr context::context(const schema_type& p_schema, T_args&&... p_args) + : base_type (p_schema, std::forward(p_args)...) + , _schema (p_schema) + { } + + template + template + constexpr decltype(auto) context::init(T_args&&... args) + { return __impl::init(*this, std::forward(args)...); } + + template + template + constexpr decltype(auto) context::create(T_args&&... args) + { return __impl::create(*this, std::forward(args)...); } + + template + template + constexpr decltype(auto) context::read(T_args&&... args) + { return __impl::read(*this, std::forward(args)...); } + + template + template + constexpr decltype(auto) context::update(T_args&&... args) + { return __impl::update(*this, std::forward(args)...); } + + template + template + constexpr decltype(auto) context::destroy(T_args&&... args) + { return __impl::destroy(*this, std::forward(args)...); } + + +#if 0 + template + constexpr auto read(T_dataset& dataset, T_modifiers&&... modifiers) + -> mp::enable_if< + modifier::all_are_modifiers...>> + { + using namespace modifier; + using real_dataset_type = misc::real_dataset_t>; + schema::tables::find(_schema.tables, hana::type_c); + this->read_impl(dataset, modifier::make_list(std::forward(modifiers)...)); + } + + template + constexpr auto read(T_dataset& dataset) + -> mp::enable_if_c< + !misc::is_container>::value + && !misc::is_nullable>::value> + { + using namespace modifier; + using real_dataset_type = misc::real_dataset_t>; + auto& table = schema::tables::find(_schema.tables, hana::type_c); + auto& primary_key = schema::table::get_primary_key_field(table); + this->read_impl(dataset, modifier::make_list(where(equal(primary_key, primary_key.getter(dataset))))); + } + + template + constexpr auto read(T_dataset& dataset) + -> mp::enable_if_c< + misc::is_container>::value + || misc::is_nullable>::value> + { + using namespace modifier; + using real_dataset_type = misc::real_dataset_t>; + schema::tables::find(_schema.tables, hana::type_c); + this->read_impl(dataset, modifier::make_list()); + } +#endif + + /* make_context */ + + template + constexpr decltype(auto) make_context(T_schema&& schema, T_args&&... args) + { + using context_type = context; + return context_type(std::forward(schema), std::forward(args)...); + } + + /* make_context_ptr */ + + template + constexpr decltype(auto) make_context_ptr(T_schema&& schema, T_args&&... args) + { + using context_type = context; + using pointer_type = std::unique_ptr; + return pointer_type(new context_type(std::forward(schema), std::forward(args)...)); + } + +} diff --git a/include/cpphibernate/driver/mariadb.h b/include/cpphibernate/driver/mariadb.h index 3eb45e9..c7b6840 100644 --- a/include/cpphibernate/driver/mariadb.h +++ b/include/cpphibernate/driver/mariadb.h @@ -1,12 +1,8 @@ #pragma once -#include -#include +#include -beg_namespace_cpphibernate_driver +namespace cpphibernate { - - using mariadb = mariadb_impl::mariadb_driver_t; - + using mariadb_driver = ::cpphibernate::mariadb::driver_t; } -end_namespace_cpphibernate_driver \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/classes.h b/include/cpphibernate/driver/mariadb/classes.h new file mode 100644 index 0000000..b04b907 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes.h @@ -0,0 +1,6 @@ +#pragma once + +#include "classes/attributes.h" +#include "classes/fields.h" +#include "classes/tables.h" +#include "classes/schema.h" diff --git a/include/cpphibernate/driver/mariadb/classes/attributes.h b/include/cpphibernate/driver/mariadb/classes/attributes.h new file mode 100644 index 0000000..997d436 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/attributes.h @@ -0,0 +1,3 @@ +#pragma once + +#include "attributes/attributes.h" diff --git a/include/cpphibernate/driver/mariadb/classes/attributes/attributes.h b/include/cpphibernate/driver/mariadb/classes/attributes/attributes.h new file mode 100644 index 0000000..20e2341 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/attributes/attributes.h @@ -0,0 +1,43 @@ +#pragma once + +#include + +#include "../forward.h" + +namespace cpphibernate { +namespace mariadb { + + namespace __impl + { + + /** + * @brief Helper class to create attributes type. + */ + template + struct attributes_builder; + + } + + /** + * @brief Attributes enumeration + */ + enum class attribute_t + { + hex, //!< The field is stored hex encoded. + compress, //!< The field is stored compressed. + primary_key, //!< The field is the primary key. + }; + + /** + * @brief Set of attributes. + */ + struct attributes_t; + + /** + * @brief Predicate to create attributes set from attributes schema. + */ + constexpr decltype(auto) make_attributes = mp::generic_predicate<__impl::attributes_builder> { }; + +} } + +#include "attributes.inl" diff --git a/include/cpphibernate/driver/mariadb/schema/attributes.inl b/include/cpphibernate/driver/mariadb/classes/attributes/attributes.inl similarity index 75% rename from include/cpphibernate/driver/mariadb/schema/attributes.inl rename to include/cpphibernate/driver/mariadb/classes/attributes/attributes.inl index 87a7ae0..ff7179c 100644 --- a/include/cpphibernate/driver/mariadb/schema/attributes.inl +++ b/include/cpphibernate/driver/mariadb/classes/attributes/attributes.inl @@ -1,9 +1,14 @@ #pragma once -#include +#include -beg_namespace_cpphibernate_driver_mariadb -{ +#include +#include + +#include "attributes.h" + +namespace cpphibernate { +namespace mariadb { namespace __impl { @@ -25,10 +30,10 @@ beg_namespace_cpphibernate_driver_mariadb struct attribute_converter { static constexpr decltype(auto) value = attribute_t::primary_key; }; - /* make_attributes_impl */ + /* attributes_builder */ template - struct make_attributes_impl + struct attributes_builder { template static constexpr decltype(auto) apply(T_args&&... args) @@ -36,10 +41,9 @@ beg_namespace_cpphibernate_driver_mariadb }; template - struct make_attributes_impl< + struct attributes_builder< mp::list, - mp::enable_if_c< - schema::is_attributes>::value>> + mp::enable_if_t>>> { template static constexpr decltype(auto) helper(T_attributes&&, const std::index_sequence&) @@ -58,5 +62,13 @@ beg_namespace_cpphibernate_driver_mariadb } -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file + /* attributes_t */ + + struct attributes_t : + public std::set + { + using base_type = std::set; + using base_type::base_type; + }; + +} } diff --git a/include/cpphibernate/driver/mariadb/classes/fields.h b/include/cpphibernate/driver/mariadb/classes/fields.h new file mode 100644 index 0000000..69c000a --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/fields.h @@ -0,0 +1,4 @@ +#pragma once + +#include "fields/field.h" +#include "fields/fields.h" diff --git a/include/cpphibernate/driver/mariadb/classes/fields/field.h b/include/cpphibernate/driver/mariadb/classes/fields/field.h new file mode 100644 index 0000000..0205dc8 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/fields/field.h @@ -0,0 +1,106 @@ +#pragma once + +#include +#include + +#include "../forward.h" +#include "../attributes.h" + +namespace cpphibernate { +namespace mariadb { + + /** + * @brief Abstract field class. + */ + struct field_t + { + public: + size_t id { 0 }; //!< unique id of the field + size_t value_id { 0 }; //!< unique id of the value type + size_t real_value_id { 0 }; //!< unique id of the real/unwrapped value type + + bool value_is_nullable { false }; //!< value is stored in a nullable container + bool value_is_pointer { false }; //!< value is stored in a pointer container + bool value_is_container { false }; //!< value is stored in a container + bool value_is_ordered { false }; //!< value is stored in a ordered container (vector, list, ...) + bool value_is_auto_incremented { false }; //!< value is a auto incremented field + + const table_t& table; //!< table this field belongs to + const table_t* referenced_table { nullptr }; //!< table that belongs to the value (if exists) + + std::string name; //!< name of the SQL field + std::string type; //!< SQL type name + std::string create_arguments; //!< additional arguments for CREATE TABLE command + + std::string convert_to_open; //!< SQL code to open the "convert to" operation + std::string convert_to_close; //!< SQL code to close the "convert to" operation + std::string convert_from_open; //!< SQL code to open the "convert from" operation + std::string convert_from_close; //!< SQL code to close the "convert from" operation + + attributes_t attributes; //!< attributes for the field + + public: + /** + * @brief Value constructor. Creates a mariadb field from the cpphibernate field. + * + * @param[in] p_owner Owner of the field. + * @param[in] p_schema Cpphibernate schema the mariadb field belongs to. + * @param[in] p_table Cpphibernate table the mariadb field belongs to. + * @param[in] p_field Cpphibernate field to create mariadb field for. + */ + template< + typename T_schema, + typename T_table, + typename T_field> + inline field_t( + const table_t& p_owner, + const T_schema& p_schema, + const T_table& p_table, + const T_field& p_field); + + /** + * @brief Move constructor. + */ + inline field_t(field_t&& other) = delete; + + /** + * @brief Copy constructor. + */ + inline field_t(const field_t&) = delete; + + /** + * @brief Destructor. + */ + virtual ~field_t() = 0; + + /** + * @brief Print the field values to the passed stream. + */ + std::ostream& print(std::ostream& os) const; + + private: + /** + * @brief Initialize the field. + */ + void init(); + }; + + namespace __impl + { + + /** + * @brief Helper type to build table. + */ + template + struct field_builder; + + } + + /** + * @brief Predicate to create mariadb table class. + */ + constexpr decltype(auto) make_field = mp::generic_predicate<__impl::field_builder> { }; + +} } + +#include "field.inl" diff --git a/include/cpphibernate/driver/mariadb/classes/fields/field.inl b/include/cpphibernate/driver/mariadb/classes/fields/field.inl new file mode 100644 index 0000000..264b173 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/fields/field.inl @@ -0,0 +1,126 @@ +#pragma once + +#include +#include +#include + +#include "field.h" +#include "field_data.h" +#include "field_primary_key.h" +#include "field_foreign_table.h" + +namespace cpphibernate { +namespace mariadb { + + template< + typename T_schema, + typename T_table, + typename T_field> + field_t::field_t( + const table_t& p_owner, + const T_schema& p_schema, + const T_table& p_table, + const T_field& p_field) + : id (get_type_id(hana::type_c>)) + , value_id (get_type_id(hana::type_c)) + , real_value_id (get_type_id(hana::type_c>)) + , value_is_nullable (is_nullable_v ) + , value_is_pointer (is_pointer_v ) + , value_is_container (is_container_v) + , value_is_ordered (is_ordered_v ) + , value_is_auto_incremented (false) + , table (p_owner) + , referenced_table (nullptr) + , name (p_field.name) + , type () + , create_arguments () + , convert_to_open () + , convert_to_close () + , convert_from_open () + , convert_from_close () + , attributes (make_attributes(p_field.attributes)) + { } + + namespace __impl + { + + /* field_builder */ + + template + struct field_builder + { + template + static constexpr decltype(auto) apply(T_args&&... args) + { static_assert(sizeof...(args) == 0, "Invalid parameters for mariadb::make_field(...)!"); } + }; + + template + struct field_builder< + mp::list, + mp::enable_if_t< + mp::is_base_of_v> + && schema::is_schema_v> + && schema::is_table_v> + && schema::is_field_v>>> + { + + /* is_primary_key_field */ + + template + struct is_primary_key_field + : public decltype( + hana::contains( + std::declval>().attributes, + schema::attribute::primary_key)) + { }; + + /* is_foreign_table_field */ + + template + struct is_foreign_table_field + : public decltype( + hana::contains( + hana::transform( + std::declval().tables, + schema::get_wrapped_dataset), + std::declval().wrapped_real_value_type)) + { }; + + /* field_type */ + + template + struct field_type + { using type = field_data_t; }; + + template + struct field_type< + X_schema, + X_field, + mp::enable_if_t::value>> + { using type = field_primary_key_t; }; + + template + struct field_type< + X_schema, + X_field, + mp::enable_if_t::value>> + { using type = field_foreign_table_t; }; + + template + using field_type_t = typename field_type::type; + + /* apply */ + + static constexpr decltype(auto) apply(const table_t& owner, const T_schema& schema, const T_table& table, const T_field& field) + { + using schema_type = mp::decay_t; + using field_type = mp::decay_t; + using return_type = field_type_t; + + return std::make_unique(owner, schema, table, field); + } + }; + + } + +} } diff --git a/include/cpphibernate/driver/mariadb/classes/fields/field_data.h b/include/cpphibernate/driver/mariadb/classes/fields/field_data.h new file mode 100644 index 0000000..540fa22 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/fields/field_data.h @@ -0,0 +1,39 @@ +#pragma once + +#include "field_value.h" + +namespace cpphibernate { +namespace mariadb { + + /** + * @brief Field that represents a data field. + */ + template + struct field_data_t + : public field_value_t + { + private: + using base_type = field_value_t; + + public: + /** + * @brief Value constructor. Creates a mariadb field from the cpphibernate field. + * + * @param[in] p_owner Owner of the field. + * @param[in] p_schema Cpphibernate schema the mariadb field belongs to. + * @param[in] p_table Cpphibernate table the mariadb field belongs to. + * @param[in] p_field Cpphibernate field to create mariadb field for. + */ + template< + typename T_schema, + typename T_table> + inline field_data_t( + const table_t& p_owner, + const T_schema& p_schema, + const T_table& p_table, + const T_field& p_field); + }; + +} } + +#include "field_data.inl" diff --git a/include/cpphibernate/driver/mariadb/classes/fields/field_data.inl b/include/cpphibernate/driver/mariadb/classes/fields/field_data.inl new file mode 100644 index 0000000..8c90bb0 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/fields/field_data.inl @@ -0,0 +1,27 @@ +#pragma once + +#include "field_data.h" + +namespace cpphibernate { +namespace mariadb { + + /* field_data_t */ + + template< + typename T_field> + template< + typename T_schema, + typename T_table> + field_data_t::field_data_t( + const table_t& p_owner, + const T_schema& p_schema, + const T_table& p_table, + const T_field& p_field) + : field_value_t::field_value_t( + p_owner, + p_schema, + p_table, + p_field) + { } + +} } diff --git a/include/cpphibernate/driver/mariadb/classes/fields/field_foreign_table.h b/include/cpphibernate/driver/mariadb/classes/fields/field_foreign_table.h new file mode 100644 index 0000000..e73ebbc --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/fields/field_foreign_table.h @@ -0,0 +1,39 @@ +#pragma once + +#include "field_simple.h" + +namespace cpphibernate { +namespace mariadb { + + /** + * @brief Field that represents a foreign table. + */ + template + struct field_foreign_table_t + : public field_simple_t + { + private: + using base_type = field_simple_t; + + public: + /** + * @brief Value constructor. Creates a mariadb field from the cpphibernate field. + * + * @param[in] p_owner Owner of the field. + * @param[in] p_schema Cpphibernate schema the mariadb field belongs to. + * @param[in] p_table Cpphibernate table the mariadb field belongs to. + * @param[in] p_field Cpphibernate field to create mariadb field for. + */ + template< + typename T_schema, + typename T_table> + inline field_foreign_table_t( + const table_t& p_owner, + const T_schema& p_schema, + const T_table& p_table, + const T_field& p_field); + }; + +} } + +#include "field_foreign_table.inl" diff --git a/include/cpphibernate/driver/mariadb/classes/fields/field_foreign_table.inl b/include/cpphibernate/driver/mariadb/classes/fields/field_foreign_table.inl new file mode 100644 index 0000000..c734586 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/fields/field_foreign_table.inl @@ -0,0 +1,27 @@ +#pragma once + +#include "field_foreign_table.h" + +namespace cpphibernate { +namespace mariadb { + + /* field_foreign_table_t */ + + template< + typename T_field> + template< + typename T_schema, + typename T_table> + field_foreign_table_t::field_foreign_table_t( + const table_t& p_owner, + const T_schema& p_schema, + const T_table& p_table, + const T_field& p_field) + : field_simple_t::field_simple_t( + p_owner, + p_schema, + p_table, + p_field) + { } + +} } diff --git a/include/cpphibernate/driver/mariadb/classes/fields/field_primary_key.h b/include/cpphibernate/driver/mariadb/classes/fields/field_primary_key.h new file mode 100644 index 0000000..fc5d364 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/fields/field_primary_key.h @@ -0,0 +1,44 @@ +#pragma once + +#include "field_value.h" +#include "../../helper/key_properties.h" + +namespace cpphibernate { +namespace mariadb { + + /** + * @brief Field that represents a primary key field. + */ + template + struct field_primary_key_t + : public field_value_t + { + private: + using base_type = field_value_t; + + public: + static constexpr decltype(auto) key_props = + key_properties { }; + + public: + /** + * @brief Value constructor. Creates a mariadb field from the cpphibernate field. + * + * @param[in] p_owner Owner of the field. + * @param[in] p_schema Cpphibernate schema the mariadb field belongs to. + * @param[in] p_table Cpphibernate table the mariadb field belongs to. + * @param[in] p_field Cpphibernate field to create mariadb field for. + */ + template< + typename T_schema, + typename T_table> + inline field_primary_key_t( + const table_t& p_owner, + const T_schema& p_schema, + const T_table& p_table, + const T_field& p_field); + }; + +} } + +#include "field_primary_key.inl" diff --git a/include/cpphibernate/driver/mariadb/classes/fields/field_primary_key.inl b/include/cpphibernate/driver/mariadb/classes/fields/field_primary_key.inl new file mode 100644 index 0000000..c1e9377 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/fields/field_primary_key.inl @@ -0,0 +1,33 @@ +#pragma once + +#include "field_primary_key.h" + +namespace cpphibernate { +namespace mariadb { + + /* field_primary_key_t */ + + template< + typename T_field> + template< + typename T_schema, + typename T_table> + field_primary_key_t::field_primary_key_t( + const table_t& p_owner, + const T_schema& p_schema, + const T_table& p_table, + const T_field& p_field) + : field_value_t::field_value_t( + p_owner, + p_schema, + p_table, + p_field) + { + this->value_is_auto_incremented = key_props.is_auto_generated(); + auto args = key_props.create_table_argument(); + if (args) + this->create_arguments = args; + this->name = this->table.name + '_' + this->name; + } + +} } diff --git a/include/cpphibernate/driver/mariadb/classes/fields/field_simple.h b/include/cpphibernate/driver/mariadb/classes/fields/field_simple.h new file mode 100644 index 0000000..58ca545 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/fields/field_simple.h @@ -0,0 +1,39 @@ +#pragma once + +#include "field.h" + +namespace cpphibernate { +namespace mariadb { + + /** + * @brief Field that completely implementes the abstract field_t + */ + template + struct field_simple_t + : public field_t + { + private: + using base_type = field_t; + + public: + /** + * @brief Value constructor. Creates a mariadb field from the cpphibernate field. + * + * @param[in] p_owner Owner of the field. + * @param[in] p_schema Cpphibernate schema the mariadb field belongs to. + * @param[in] p_table Cpphibernate table the mariadb field belongs to. + * @param[in] p_field Cpphibernate field to create mariadb field for. + */ + template< + typename T_schema, + typename T_table> + inline field_simple_t( + const table_t& p_owner, + const T_schema& p_schema, + const T_table& p_table, + const T_field& p_field); + }; + +} } + +#include "field_simple.inl" diff --git a/include/cpphibernate/driver/mariadb/classes/fields/field_simple.inl b/include/cpphibernate/driver/mariadb/classes/fields/field_simple.inl new file mode 100644 index 0000000..fa54378 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/fields/field_simple.inl @@ -0,0 +1,27 @@ +#pragma once + +#include "field_simple.h" + +namespace cpphibernate { +namespace mariadb { + + /* field_simple_t */ + + template< + typename T_field> + template< + typename T_schema, + typename T_table> + field_simple_t::field_simple_t( + const table_t& p_owner, + const T_schema& p_schema, + const T_table& p_table, + const T_field& p_field) + : field_t::field_t( + p_owner, + p_schema, + p_table, + p_field) + { } + +} } diff --git a/include/cpphibernate/driver/mariadb/classes/fields/field_value.h b/include/cpphibernate/driver/mariadb/classes/fields/field_value.h new file mode 100644 index 0000000..ed11729 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/fields/field_value.h @@ -0,0 +1,48 @@ +#pragma once + +#include "field_simple.h" +#include "../../helper/type_properties.h" + +namespace cpphibernate { +namespace mariadb { + + /** + * @brief Field that represents a simple value. + */ + template + struct field_value_t + : public field_simple_t + { + private: + using base_type = field_simple_t; + + public: + static constexpr decltype(auto) field_type = + hana::type_c>; + static constexpr decltype(auto) value_type = + hana::type_c; + static constexpr decltype(auto) value_props = + type_properties { }; + + public: + /** + * @brief Value constructor. Creates a mariadb field from the cpphibernate field. + * + * @param[in] p_owner Owner of the field. + * @param[in] p_schema Cpphibernate schema the mariadb field belongs to. + * @param[in] p_table Cpphibernate table the mariadb field belongs to. + * @param[in] p_field Cpphibernate field to create mariadb field for. + */ + template< + typename T_schema, + typename T_table> + inline field_value_t( + const table_t& p_owner, + const T_schema& p_schema, + const T_table& p_table, + const T_field& p_field); + }; + +} } + +#include "field_value.inl" diff --git a/include/cpphibernate/driver/mariadb/classes/fields/field_value.inl b/include/cpphibernate/driver/mariadb/classes/fields/field_value.inl new file mode 100644 index 0000000..f958c40 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/fields/field_value.inl @@ -0,0 +1,37 @@ +#pragma once + +#include "field_value.h" + +namespace cpphibernate { +namespace mariadb { + + /* field_value_t */ + + template< + typename T_field> + template< + typename T_schema, + typename T_table> + field_value_t::field_value_t( + const table_t& p_owner, + const T_schema& p_schema, + const T_table& p_table, + const T_field& p_field) + : field_simple_t::field_simple_t( + p_owner, + p_schema, + p_table, + p_field) + { + this->type = value_props.type(); + if (value_props.convert_to_open()) + this->convert_to_open = this->convert_to_open + value_props.convert_to_open(); + if (value_props.convert_to_close()) + this->convert_to_close = value_props.convert_to_close() + this->convert_to_close; + if (value_props.convert_from_open()) + this->convert_from_open = this->convert_from_open + value_props.convert_from_open(); + if (value_props.convert_from_close()) + this->convert_from_close = value_props.convert_from_close() + this->convert_from_close; + } + +} } diff --git a/include/cpphibernate/driver/mariadb/classes/fields/fields.h b/include/cpphibernate/driver/mariadb/classes/fields/fields.h new file mode 100644 index 0000000..1d86301 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/fields/fields.h @@ -0,0 +1,39 @@ +#pragma once + +#include + +#include "../forward.h" +#include "field.h" + +namespace cpphibernate { +namespace mariadb { + + /** + * @brief Vector of fields. + */ + struct fields_t + : public std::vector + { + using base_type = std::vector; + using base_type::base_type; + }; + + namespace __impl + { + + /** + * @brief Helper class to create table vector. + */ + template + struct fields_builder; + + } + + /** + * @brief Predicate to create table vector. + */ + constexpr decltype(auto) make_fields = mp::generic_predicate<__impl::fields_builder> { }; + +} } + +#include "fields.inl" diff --git a/include/cpphibernate/driver/mariadb/classes/fields/fields.inl b/include/cpphibernate/driver/mariadb/classes/fields/fields.inl new file mode 100644 index 0000000..f33b772 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/fields/fields.inl @@ -0,0 +1,67 @@ +#pragma once + +#include +#include + +#include "field.h" +#include "fields.h" + +namespace cpphibernate { +namespace mariadb { + + namespace __impl + { + + /* fields_builder */ + + template + struct fields_builder + { + template + static constexpr decltype(auto) apply(T_args&&... args) + { static_assert(sizeof...(args) == -1, "Invalid parameters for mariadb::make_fields(...)!"); } + }; + + template + struct fields_builder< + mp::list, + mp::enable_if_t< + mp::is_same_v> + && schema::is_schema_v> + && schema::is_table_v>>> + { + template + static constexpr void emplace( + fields_t& result, + const table_t& owner, + const T_schema& schema, + const T_table& table, + T_index&& index) + { + result.emplace_back(make_field(owner, schema, table, table.fields[index])); + } + + template + static auto helper( + const table_t& owner, + const T_schema& schema, + const T_table& table, + std::index_sequence&&) + { + fields_t ret; + int dummy[] = { 0, (emplace(ret, owner, schema, table, hana::size_c), void(), 0)... }; + (void) dummy; + return ret; + } + + static constexpr decltype(auto) apply( + const table_t& owner, const T_schema& schema, const T_table& table) + { + using size = decltype(hana::size(table.fields)); + return helper(owner, schema, table, std::make_index_sequence { }); + } + }; + + } + +} } diff --git a/include/cpphibernate/driver/mariadb/classes/forward.h b/include/cpphibernate/driver/mariadb/classes/forward.h new file mode 100644 index 0000000..c5b7a8d --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/forward.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +namespace cpphibernate { +namespace mariadb { + + enum class attribute_t; + struct attributes_t; + struct field_t; + struct fields_t; + struct table_t; + struct tables_t; + struct schema_t; + + using field_ptr_u = std::unique_ptr; + using table_ptr_u = std::unique_ptr; + using schema_ptr_u = std::unique_ptr; + +} } diff --git a/include/cpphibernate/driver/mariadb/classes/schema.h b/include/cpphibernate/driver/mariadb/classes/schema.h new file mode 100644 index 0000000..b5e715e --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/schema.h @@ -0,0 +1,3 @@ +#pragma once + +#include "schema/schema.h" diff --git a/include/cpphibernate/driver/mariadb/classes/schema/schema.h b/include/cpphibernate/driver/mariadb/classes/schema/schema.h new file mode 100644 index 0000000..c70a5fe --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/schema/schema.h @@ -0,0 +1,80 @@ +#pragma once + +#include + +#include "../forward.h" +#include "../tables/tables.h" + +namespace cpphibernate { +namespace mariadb { + + /** + * @brief Class to wrapp all values needed by the maraidb schema. + */ + struct schema_t + { + public: + using table_map = std::map; + + private: + table_map _lookup; //!< dataset id to table pointer map + + public: + std::string name; //!< name of the schema + tables_t tables; //!< tables that are managed by this schema. + + public: + /** + * @brief Default constructor. + */ + inline schema_t() = default; + + /** + * @brief Value constructor. + * + * @param[in] p_schema Cpphibernate schema to create mariadb schema from. + */ + template + inline schema_t(const T_schema& p_schema); + + /** + * @brief Move constructor. + */ + inline schema_t(schema_t&&) = delete; + + /** + * @brief Copy constructor. + */ + inline schema_t(const schema_t&) = delete; + + /** + * @brief Print the schema to the passed stream. + */ + std::ostream& print(std::ostream& os) const; + + private: + /** + * @brief Initialize the field. + */ + void init(); + }; + + namespace __impl + { + + /** + * @brief Helper type to build schema. + */ + template + struct schema_builder; + + } + + /** + * @brief Predicate to create mariadb schema class. + */ + constexpr decltype(auto) make_schema = mp::generic_predicate<__impl::schema_builder> { }; + +} } + +#include "schema.inl" diff --git a/include/cpphibernate/driver/mariadb/classes/schema/schema.inl b/include/cpphibernate/driver/mariadb/classes/schema/schema.inl new file mode 100644 index 0000000..e6c016f --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/schema/schema.inl @@ -0,0 +1,43 @@ +#pragma once + +#include + +#include "schema.h" + +namespace cpphibernate { +namespace mariadb { + + /* schema_t */ + + template + schema_t::schema_t(const T_schema& p_schema) + : name (p_schema.name) + , tables(make_tables(*this, p_schema)) + { init(); } + + namespace __impl + { + + /* schema_builder */ + + template + struct schema_builder + { + template + static constexpr decltype(auto) apply(T_args&&... args) + { static_assert(sizeof...(args) == -1, "Invalid parameters for mariadb::make_schema(...)!"); } + }; + + template + struct schema_builder< + mp::list, + mp::enable_if_t< + schema::is_schema_v>>> + { + static decltype(auto) apply(const T_schema& p_schema) + { return std::make_unique(p_schema); } + }; + + } + +} } diff --git a/include/cpphibernate/driver/mariadb/classes/tables.h b/include/cpphibernate/driver/mariadb/classes/tables.h new file mode 100644 index 0000000..411f73b --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/tables.h @@ -0,0 +1,4 @@ +#pragma once + +#include "tables/table.h" +#include "tables/tables.h" diff --git a/include/cpphibernate/driver/mariadb/classes/tables/table.h b/include/cpphibernate/driver/mariadb/classes/tables/table.h new file mode 100644 index 0000000..48f0879 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/tables/table.h @@ -0,0 +1,115 @@ +#pragma once + +#include +#include +#include + +#include "../forward.h" +#include "../fields/fields.h" + +namespace cpphibernate { +namespace mariadb { + + /** + * @brief Abstract table class. + */ + struct table_t + { + public: + using size_vector = std::vector; //!< vector of size_t + using table_vector = std::vector; //!< vector of constant field pointers + using field_vector = std::vector; //!< vector of constant field pointers + using field_map = std::map; //!< map of field id to field + + private: + field_map _lookup; //!< field id to field pointer map + + 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; + + private: + /** + * @brief Initialize the field. + */ + void init(); + }; + + namespace __impl + { + + /** + * @brief Helper type to build table. + */ + template + struct table_builder; + + } + + /** + * @brief Predicate to create mariadb table class. + */ + constexpr decltype(auto) make_table = mp::generic_predicate<__impl::table_builder> { }; + +} } + +#include "table.inl" diff --git a/include/cpphibernate/driver/mariadb/classes/tables/table.inl b/include/cpphibernate/driver/mariadb/classes/tables/table.inl new file mode 100644 index 0000000..bf0b37d --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/tables/table.inl @@ -0,0 +1,99 @@ +#pragma once + +#include +#include + +#include "table.h" +#include "table_simple.h" +#include "table_polymorphic.h" + +namespace cpphibernate { +namespace mariadb { + + /* table_t */ + + template< + typename T_schema, + typename T_table> + table_t::table_t( + const schema_t& p_owner, + const T_schema& p_schema, + const T_table& p_table) + : id (hana::value(p_table.table_id)) + , dataset_id(get_type_id(p_table.wrapped_dataset)) + , name (p_table.name) + , schema (p_owner) + , fields (make_fields(*this, p_schema, p_table)) + { init(); } + + namespace __impl + { + + /* table_builder */ + + template + struct table_builder + { + template + static constexpr decltype(auto) apply(T_args&&... args) + { static_assert(sizeof...(args) == 0, "Invalid parameters for mariadb::make_table(...)!"); } + }; + + template + struct table_builder< + mp::list, + mp::enable_if_t< + mp::is_same_v> + && schema::is_schema_v> + && schema::is_table_v>>> + { + + /* table_type */ + + template< + typename T_dataset, + typename T_base_dataset, + typename T_derived_datasets, + typename = void> + struct table_type + { using type = table_simple_t /* table_simple_t, mp::decay_t, T_base_dataset> */; }; + + template< + typename T_dataset, + typename T_base_dataset, + typename T_derived_datasets> + struct table_type< + T_dataset, + T_base_dataset, + T_derived_datasets, + mp::enable_if_t< + decltype(hana::size(std::declval()) != hana::size_c<0>)::value + || decltype(hana::not_equal(std::declval(), hana::type_c))::value>> + { using type = table_polymorphic_t /* table_polymorphic_t, mp::decay_t, T_base_dataset> */; }; + + template< + typename T_dataset, + typename T_base_dataset, + typename T_derived_datasets> + using table_type_t = typename table_type::type; + + /* apply */ + + static decltype(auto) apply(const schema_t& owner, const T_schema& schema, const T_table& table) + { + using dataset_type = decltype(+table.wrapped_dataset); + using base_dataset_type = mp::decay_t; + using derived_datasets_type = mp::decay_t; + using table_type = table_type_t; + + return std::make_unique( + owner, schema, table, + base_dataset_type { }, derived_datasets_type { }); + } + + }; + + + } + +} } diff --git a/include/cpphibernate/driver/mariadb/classes/tables/table_polymorphic.h b/include/cpphibernate/driver/mariadb/classes/tables/table_polymorphic.h new file mode 100644 index 0000000..39a2b90 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/tables/table_polymorphic.h @@ -0,0 +1,39 @@ +#pragma once + +#include + +#include "table.h" + +namespace cpphibernate { +namespace mariadb { + + /** + * @brief Table for polymorphic data types. + */ + struct table_polymorphic_t + : public table_t + { + public: + /** + * @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, + typename T_base_dataset, + typename T_derived_datasets> + inline table_polymorphic_t( + const schema_t& p_owner, + const T_schema& p_schema, + const T_table& p_table, + const T_base_dataset&&, + const T_derived_datasets&&); + }; + +} } + +#include "table_polymorphic.inl" diff --git a/include/cpphibernate/driver/mariadb/classes/tables/table_polymorphic.inl b/include/cpphibernate/driver/mariadb/classes/tables/table_polymorphic.inl new file mode 100644 index 0000000..afd1653 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/tables/table_polymorphic.inl @@ -0,0 +1,60 @@ +#pragma once + +#include "table_polymorphic.h" + +namespace cpphibernate { +namespace mariadb { + + namespace __impl + { + + /* make_dataset_id_vector */ + + struct make_dataset_id_vector_impl + { + template + static constexpr decltype(auto) helper(const T_datasets& datasets, std::index_sequence) + { + return std::vector({ + get_type_id(datasets[hana::size_c])... + }); + } + + template + constexpr decltype(auto) operator()(const T_datasets& datasets) const + { + using size = mp::decay_t; + return helper(datasets, std::make_index_sequence { }); + } + }; + + static constexpr decltype(auto) make_dataset_id_vector = make_dataset_id_vector_impl { }; + + } + + /* table_polymorphic_t */ + + template< + typename T_schema, + typename T_table, + typename T_base_dataset, + typename T_derived_datasets> + table_polymorphic_t::table_polymorphic_t( + const schema_t& p_owner, + const T_schema& p_schema, + const T_table& p_table, + const T_base_dataset&&, + const T_derived_datasets&&) + : table_t( + p_owner, + p_schema, + p_table) + { + this->base_dataset_id = hana::if_( + hana::equal(T_base_dataset { }, hana::type_c), + static_cast(0), + get_type_id(T_base_dataset { })); + this->derived_dataset_ids = __impl::make_dataset_id_vector(T_derived_datasets { }); + } + +} } diff --git a/include/cpphibernate/driver/mariadb/classes/tables/table_simple.h b/include/cpphibernate/driver/mariadb/classes/tables/table_simple.h new file mode 100644 index 0000000..abd138a --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/tables/table_simple.h @@ -0,0 +1,39 @@ +#pragma once + +#include + +#include "table.h" + +namespace cpphibernate { +namespace mariadb { + + /** + * @brief Table for non polymorphic datatypes. + */ + struct table_simple_t + : public table_t + { + public: + /** + * @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, + typename T_base_dataset, + typename T_derived_datasets> + inline table_simple_t( + const schema_t& p_owner, + const T_schema& p_schema, + const T_table& p_table, + const T_base_dataset&&, + const T_derived_datasets&&); + }; + +} } + +#include "table_simple.inl" diff --git a/include/cpphibernate/driver/mariadb/classes/tables/table_simple.inl b/include/cpphibernate/driver/mariadb/classes/tables/table_simple.inl new file mode 100644 index 0000000..d03f4c1 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/tables/table_simple.inl @@ -0,0 +1,27 @@ +#pragma once + +#include "table_simple.h" + +namespace cpphibernate { +namespace mariadb { + + /* table_simple_t */ + + template< + typename T_schema, + typename T_table, + typename T_base_dataset, + typename T_derived_datasets> + table_simple_t::table_simple_t( + const schema_t& p_owner, + const T_schema& p_schema, + const T_table& p_table, + const T_base_dataset&&, + const T_derived_datasets&&) + : table_t( + p_owner, + p_schema, + p_table) + { } + +} } diff --git a/include/cpphibernate/driver/mariadb/classes/tables/tables.h b/include/cpphibernate/driver/mariadb/classes/tables/tables.h new file mode 100644 index 0000000..066b658 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/tables/tables.h @@ -0,0 +1,38 @@ +#pragma once + +#include + +#include "table.h" + +namespace cpphibernate { +namespace mariadb { + + /** + * @brief Vector of tables. + */ + struct tables_t + : public std::vector + { + using base_type = std::vector; + using base_type::base_type; + }; + + namespace __impl + { + + /** + * @brief Helper class to create table vector. + */ + template + struct tables_builder; + + } + + /** + * @brief Predicate to create table vector. + */ + constexpr decltype(auto) make_tables = mp::generic_predicate<__impl::tables_builder> { }; + +} } + +#include "tables.inl" diff --git a/include/cpphibernate/driver/mariadb/classes/tables/tables.inl b/include/cpphibernate/driver/mariadb/classes/tables/tables.inl new file mode 100644 index 0000000..d49bf94 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/classes/tables/tables.inl @@ -0,0 +1,67 @@ +#pragma once + +#include +#include + +#include "tables.h" + +namespace cpphibernate { +namespace mariadb { + + namespace __impl + { + + /* tables_builder */ + + template + struct tables_builder + { + template + static constexpr decltype(auto) apply(T_args&&... args) + { static_assert(sizeof...(args) == -1, "Invalid parameters for mariadb::make_tables(...)!"); } + }; + + template< + typename T_owner, + typename T_schema> + struct tables_builder< + mp::list, + mp::enable_if_t< + mp::is_same_v> + && schema::is_schema_v>>> + { + template + static constexpr void emplace( + tables_t& result, + const schema_t& owner, + const T_schema& schema, + T_index&& index) + { + result.emplace_back(make_table(owner, schema, schema.tables[index])); + } + + template + static decltype(auto) helper( + const schema_t& owner, + const T_schema& schema, + std::index_sequence seq) + { + tables_t ret; + ret.reserve(sizeof...(I)); + int dummy[] = { 0, (emplace(ret, owner, schema, hana::size_c), void(), 0)... }; + (void) dummy; + return ret; + } + + static constexpr decltype(auto) apply( + const schema_t& owner, + const T_schema& schema) + { + using size = decltype(hana::size(schema.tables)); + return helper(owner, schema, std::make_index_sequence { }); + } + }; + + } + +} } diff --git a/include/cpphibernate/driver/mariadb/mariadb.h b/include/cpphibernate/driver/mariadb/driver.h similarity index 81% rename from include/cpphibernate/driver/mariadb/mariadb.h rename to include/cpphibernate/driver/mariadb/driver.h index 8b95bd5..4eaf625 100644 --- a/include/cpphibernate/driver/mariadb/mariadb.h +++ b/include/cpphibernate/driver/mariadb/driver.h @@ -1,16 +1,37 @@ #pragma once #include -#include -#include -#include -#include -beg_namespace_cpphibernate_driver_mariadb -{ +#include "classes.h" +// #include +// #include +// #include +// #include - struct mariadb_driver_t +namespace cpphibernate { +namespace mariadb { + + /** + * @brief Mariadb driver. + */ + struct driver_t { + private: + schema_ptr_u _schema; + + public: + /** + * @brief Constructor. Initializes the driver with the passed schema. + */ + template + inline driver_t(T_schema&& p_schema); + + /** + * @brief Print the schema of the driver to the passed stream. + */ + inline std::ostream& print(std::ostream& os) const; + +/* public: using lock_type = std::unique_ptr; @@ -21,9 +42,8 @@ beg_namespace_cpphibernate_driver_mariadb public: template - mariadb_driver_t(T_schema&& p_schema, ::cppmariadb::connection& p_connection) - : _connection (&p_connection) - , _schema (make_schema(std::forward(p_schema))) + mariadb_driver_t(T_schema&& p_schema) + : _schema(make_schema(std::forward(p_schema))) { } cpphibernate_copyable(mariadb_driver_t, delete); @@ -114,7 +134,9 @@ beg_namespace_cpphibernate_driver_mariadb destroy_impl_t::apply(context); } +*/ }; -} -end_namespace_cpphibernate_driver_mariadb +} } + +#include "driver.inl" diff --git a/include/cpphibernate/driver/mariadb/driver.inl b/include/cpphibernate/driver/mariadb/driver.inl new file mode 100644 index 0000000..157def4 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/driver.inl @@ -0,0 +1,16 @@ +#pragma once + +#include "driver.h" + +namespace cpphibernate { +namespace mariadb { + + template + driver_t::driver_t(T_schema&& p_schema) + : _schema(make_schema(std::forward(p_schema))) + { } + + std::ostream& driver_t::print(std::ostream& os) const + { return _schema->print(os); } + +} } diff --git a/include/cpphibernate/driver/mariadb/helper.h b/include/cpphibernate/driver/mariadb/helper.h index 322dbe8..f737456 100644 --- a/include/cpphibernate/driver/mariadb/helper.h +++ b/include/cpphibernate/driver/mariadb/helper.h @@ -1,6 +1,7 @@ #pragma once -#include -#include -#include -#include \ No newline at end of file +#include "helper/key_properties.h" +#include "helper/type_properties.h" +#include "helper/key_properties.h" +#include "helper/transaction_lock.h" +#include "helper/type_properties.h" diff --git a/include/cpphibernate/driver/mariadb/helper/key_properties.h b/include/cpphibernate/driver/mariadb/helper/key_properties.h index 6a800ea..4238978 100644 --- a/include/cpphibernate/driver/mariadb/helper/key_properties.h +++ b/include/cpphibernate/driver/mariadb/helper/key_properties.h @@ -1,42 +1,41 @@ #pragma once -#include #include -#include -beg_namespace_cpphibernate_driver_mariadb -{ - - /* key_properties */ +namespace cpphibernate { +namespace mariadb { + /** + * @brief Key type properties for the passed type. + * + * @tparam T_key Type to get key properties for. + */ template - struct key_properties; - - template<> - struct key_properties + struct key_properties { - using auto_generated = mp::c_false_t; - using key_type = uuid; - - static constexpr decltype(auto) create_table_argument = ""; - static constexpr decltype(auto) create_key_query = "SELECT Uuid()"; - - static bool is_default(const key_type& key) - { return key == key_type(); } + using key_type = T_key; + + /** + * @brief Check if the passed key value is the default value. + */ + static bool is_default(const key_type& key) = delete; + + /** + * @brief Returns true if the key type is auto generated, false otherwise. + */ + static constexpr bool is_auto_generated() = delete; + + /** + * @brief Returns extra arguments to use for creating the table. + */ + static constexpr const char * create_table_argument() = delete; + + /** + * @brief Return the query to create a new key value. + */ + static constexpr const char * create_key_query() = delete; }; - template - struct key_properties>> - { - using auto_generated = mp::c_true_t; - using key_type = T_key; - - static constexpr decltype(auto) create_table_argument = "AUTO_INCREMENT"; - static constexpr decltype(auto) create_key_query = ""; - - static bool is_default(const key_type& key) - { return key == key_type(); } - }; +} } -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file +#include "key_properties.inl" diff --git a/include/cpphibernate/driver/mariadb/helper/key_properties.inl b/include/cpphibernate/driver/mariadb/helper/key_properties.inl new file mode 100644 index 0000000..6a22500 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/helper/key_properties.inl @@ -0,0 +1,50 @@ +#pragma once + +#include "key_properties.h" + +#include + +namespace cpphibernate { +namespace mariadb { + + /* key_properties */ + + template<> + struct key_properties + { + using key_type = uuid; + + static bool is_default(const key_type& key) + { return key == key_type(); } + + static constexpr bool is_auto_generated() + { return false; } + + static constexpr const char * create_table_argument() + { return nullptr; } + + static constexpr const char * create_key_query() + { return "SELECT Uuid()"; } + }; + + template + struct key_properties< + T_key, + mp::enable_if_t>>> + { + using key_type = mp::decay_t; + + static bool is_default(const key_type& key) + { return key == key_type(); } + + static constexpr bool is_auto_generated() + { return true; } + + static constexpr const char * create_table_argument() + { return "AUTO_INCREMENT"; } + + static constexpr const char * create_key_query() + { return nullptr; } + }; + +} } diff --git a/include/cpphibernate/driver/mariadb/helper/nullable_helper.h b/include/cpphibernate/driver/mariadb/helper/nullable_helper.h new file mode 100644 index 0000000..3d74c1c --- /dev/null +++ b/include/cpphibernate/driver/mariadb/helper/nullable_helper.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +namespace cpphibernate { +namespace mariadb { + + /** + * @brief Helper class to manage operations on nullable types. + */ + template + struct nullable_helper + { + using nullable_type = T_nullable; + using value_type = real_dataset_t; + + /** + * @brief Get a pointer to the stored value of the nullable object. + */ + static value_type* get(const nullable_type&) = delete; + + /** + * @brief Set the new value of the nullable object. + */ + static value_type& set(nullable_type&, const value_type&) = delete; + + /** + * @brief Destroy the stored value of a nullable objec (clear the nullable object). + */ + static void clear(nullable_type&) = delete; + }; + +} } + +#include "nullable_helper.inl" diff --git a/include/cpphibernate/driver/mariadb/helper/nullable_helper.inl b/include/cpphibernate/driver/mariadb/helper/nullable_helper.inl new file mode 100644 index 0000000..60a7164 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/helper/nullable_helper.inl @@ -0,0 +1,75 @@ +#include "nullable_helper.h" + +#include + +#include + +namespace cpphibernate { +namespace mariadb { + + + /* nullable_helper - cppcore::nullable */ + + template + struct nullable_helper, void> + { + using nullable_type = cppcore::nullable; + using value_type = T_value; + + static inline value_type* get(nullable_type& x) + { return x.has_value() ? &x.value() : nullptr; } + + static inline const value_type* get(const nullable_type& x) + { return x.has_value() ? &x.value() : nullptr; } + + static inline value_type& set(nullable_type& x, const value_type* value) + { return *(x = *value); } + + static inline value_type& set(nullable_type& x, const value_type& value) + { return *(x = value); } + + static inline value_type& set(nullable_type& x, value_type&& value) + { return *(x = std::move(value)); } + + static void clear(nullable_type& x) + { x.reset(); } + }; + + /* nullable_helper - std::unique_ptr/std::shared_ptr */ + + template + struct nullable_helper< + T, + mp::enable_if_t< + mp::is_specialization_of_v + || mp::is_specialization_of_v>> + { + using nullable_type = T; + using value_type = typename nullable_type::element_type; + + static inline value_type* get(const nullable_type& x) + { return x.get(); } + + static inline value_type& set(nullable_type& x, value_type* value) + { + x.reset(value); + return *x; + } + + static inline value_type& set(nullable_type& x, const value_type& value) + { + x.reset(new value_type(value)); + return *x; + } + + static inline value_type& set(nullable_type& x, value_type&& value) + { + x.reset(new value_type(std::move(value))); + return *x; + } + + static void clear(nullable_type& x) + { return x.reset(); } + }; + +} } diff --git a/include/cpphibernate/driver/mariadb/helper/type_properties.h b/include/cpphibernate/driver/mariadb/helper/type_properties.h index ddb211a..a982bf1 100644 --- a/include/cpphibernate/driver/mariadb/helper/type_properties.h +++ b/include/cpphibernate/driver/mariadb/helper/type_properties.h @@ -1,583 +1,60 @@ #pragma once -#include -#include -#include - -#include -#include #include -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - /* value_t */ +#include - using value_t = utl::nullable; +namespace cpphibernate { +namespace mariadb { - /* type_properties */ + /** + * @brief Value received from the database. + */ + using value_t = cppcore::nullable; + /** + * @brief Type properties for the passed type. + * + * @tparam T Type to get properties for. + */ template struct type_properties { - static constexpr void type () = delete; - static T convert_to (const value_t&) = delete; - static value_t convert_from (const T&) = delete; - static constexpr const char* convert_to_open () = delete; - static constexpr const char* convert_to_close () = delete; - static constexpr const char* convert_from_open () = delete; - static constexpr const char* convert_from_close() = delete; - }; - - template<> - struct type_properties - { - static constexpr decltype(auto) type() - { return "BOOLEAN"; } - - static inline bool convert_to(const value_t& value) - { return utl::from_string(*value); } - - static inline value_t convert_from(const bool& value) - { return utl::to_string(static_cast(value)); } - - static constexpr const char* convert_to_open() - { return nullptr; } - - static constexpr const char* convert_to_close() - { return nullptr; } - - static constexpr const char* convert_from_open() - { return nullptr; } - - static constexpr const char* convert_from_close() - { return nullptr; } - }; - - template<> - struct type_properties - { - static constexpr decltype(auto) type() - { return "TINYINT UNSIGNED"; } - - static inline uint8_t convert_to(const value_t& value) - { return static_cast(utl::from_string(*value)); } - - static inline value_t convert_from(const uint8_t& value) - { return utl::to_string(static_cast(value)); } - - static constexpr const char* convert_to_open() - { return nullptr; } - - static constexpr const char* convert_to_close() - { return nullptr; } - - static constexpr const char* convert_from_open() - { return nullptr; } - - static constexpr const char* convert_from_close() - { return nullptr; } - }; - - template<> - struct type_properties - { - static constexpr decltype(auto) type() - { return "TINYINT"; } - - static inline int8_t convert_to(const value_t& value) - { return static_cast(utl::from_string(*value)); } - - static inline value_t convert_from(const int8_t& value) - { return utl::to_string(static_cast(value)); } - - static constexpr const char* convert_to_open() - { return nullptr; } - - static constexpr const char* convert_to_close() - { return nullptr; } - - static constexpr const char* convert_from_open() - { return nullptr; } - - static constexpr const char* convert_from_close() - { return nullptr; } - }; - - template<> - struct type_properties - { - static constexpr decltype(auto) type() - { return "SMALLINT UNSIGNED"; } - - static inline uint16_t convert_to(const value_t& value) - { return utl::from_string(*value); } - - static inline value_t convert_from(const uint16_t& value) - { return utl::to_string(value); } - - static constexpr const char* convert_to_open() - { return nullptr; } - - static constexpr const char* convert_to_close() - { return nullptr; } - - static constexpr const char* convert_from_open() - { return nullptr; } - - static constexpr const char* convert_from_close() - { return nullptr; } - }; - - template<> - struct type_properties - { - static constexpr decltype(auto) type() - { return "SMALLINT"; } - - static inline int16_t convert_to(const value_t& value) - { return utl::from_string(*value); } - - static inline value_t convert_from(const int16_t& value) - { return utl::to_string(value); } - - static constexpr const char* convert_to_open() - { return nullptr; } - - static constexpr const char* convert_to_close() - { return nullptr; } - - static constexpr const char* convert_from_open() - { return nullptr; } - - static constexpr const char* convert_from_close() - { return nullptr; } - }; - - template<> - struct type_properties - { - static constexpr decltype(auto) type() - { return "INT UNSIGNED"; } - - static inline uint32_t convert_to(const value_t& value) - { return utl::from_string(*value); } - - static inline value_t convert_from(const uint32_t& value) - { return utl::to_string(value); } - - static constexpr const char* convert_to_open() - { return nullptr; } - - static constexpr const char* convert_to_close() - { return nullptr; } - - static constexpr const char* convert_from_open() - { return nullptr; } - - static constexpr const char* convert_from_close() - { return nullptr; } - }; - - template<> - struct type_properties - { - static constexpr decltype(auto) type() - { return "INT"; } - - static inline int32_t convert_to(const value_t& value) - { return utl::from_string(*value); } - - static inline value_t convert_from(const int32_t& value) - { return utl::to_string(value); } - - static constexpr const char* convert_to_open() - { return nullptr; } - - static constexpr const char* convert_to_close() - { return nullptr; } - - static constexpr const char* convert_from_open() - { return nullptr; } - - static constexpr const char* convert_from_close() - { return nullptr; } - }; - - template<> - struct type_properties - { - static constexpr decltype(auto) type() - { return "BIGINT UNSIGNED"; } - - static inline uint64_t convert_to(const value_t& value) - { return utl::from_string(*value); } - - static inline value_t convert_from(const uint64_t& value) - { return utl::to_string(value); } - - static constexpr const char* convert_to_open() - { return nullptr; } - - static constexpr const char* convert_to_close() - { return nullptr; } - - static constexpr const char* convert_from_open() - { return nullptr; } - - static constexpr const char* convert_from_close() - { return nullptr; } - }; - - template<> - struct type_properties - { - static constexpr decltype(auto) type() - { return "BIGINT"; } - - static inline int64_t convert_to(const value_t& value) - { return utl::from_string(*value); } - - static inline value_t convert_from(const int64_t& value) - { return utl::to_string(value); } - - static constexpr const char* convert_to_open() - { return nullptr; } - - static constexpr const char* convert_to_close() - { return nullptr; } - - static constexpr const char* convert_from_open() - { return nullptr; } - - static constexpr const char* convert_from_close() - { return nullptr; } - }; - - template<> - struct type_properties - { - static constexpr decltype(auto) type() - { return "FLOAT"; } - - static inline float convert_to(const value_t& value) - { return utl::from_string(*value); } - - static inline value_t convert_from(const float& value) - { return utl::to_string(value); } - - static constexpr const char* convert_to_open() - { return nullptr; } - - static constexpr const char* convert_to_close() - { return nullptr; } - - static constexpr const char* convert_from_open() - { return nullptr; } - - static constexpr const char* convert_from_close() - { return nullptr; } - }; - - template<> - struct type_properties - { - static constexpr decltype(auto) type() - { return "DOUBLE"; } - - static inline double convert_to(const value_t& value) - { return utl::from_string(*value); } - - static inline value_t convert_from(const double& value) - { return utl::to_string(value); } - - static constexpr const char* convert_to_open() - { return nullptr; } - - static constexpr const char* convert_to_close() - { return nullptr; } - - static constexpr const char* convert_from_open() - { return nullptr; } - - static constexpr const char* convert_from_close() - { return nullptr; } - }; - - template<> - struct type_properties - { - static constexpr decltype(auto) type() - { return "BINARY(16)"; } - - static inline uuid convert_to(const value_t& value) - { return utl::from_string(*value); } - - static inline value_t convert_from(const uuid& value) - { return utl::to_string(value); } - - static constexpr const char* convert_to_open() - { return "UuidToBin("; } - - static constexpr const char* convert_to_close() - { return ")"; } - - static constexpr const char* convert_from_open() - { return "BinToUuid("; } - - static constexpr const char* convert_from_close() - { return ")"; } - }; - - template<> - struct type_properties - { - static constexpr decltype(auto) type() - { return "BIGINT"; } - - static inline timestamp convert_to(const value_t& value) - { return timestamp(utl::from_string(*value)); } - - static inline value_t convert_from(const timestamp& value) - { return utl::to_string(static_cast(value)); } - - static constexpr const char* convert_to_open() - { return nullptr; } - - static constexpr const char* convert_to_close() - { return nullptr; } - - static constexpr const char* convert_from_open() - { return nullptr; } - - static constexpr const char* convert_from_close() - { return nullptr; } - }; - - template<> - struct type_properties - { - static constexpr decltype(auto) type() - { return "VARCHAR(100)"; } + /** + * @brief Get the mariadb type. + */ + static constexpr const char * type() = delete; - static inline std::string convert_to(const value_t& value) - { return *value; } + /** + * @brief Convert a value from the database to its actual type. + */ + static T convert_to(const value_t&) = delete; - static inline value_t convert_from(const std::string& value) - { return value; } + /** + * @brief Convert the actual value to a database value. + */ + static value_t convert_from(const T&) = delete; - static constexpr const char* convert_to_open() - { return nullptr; } + /** + * @brief Get the string to start the "convert to" operation. + */ + static constexpr const char * convert_to_open() = delete; - static constexpr const char* convert_to_close() - { return nullptr; } + /** + * @brief Get the string to end the "convert to" operation. + */ + static constexpr const char * convert_to_close() = delete; - static constexpr const char* convert_from_open() - { return nullptr; } + /** + * @brief Get the string to start the "convert from" operation. + */ + static constexpr const char * convert_from_open() = delete; - static constexpr const char* convert_from_close() - { return nullptr; } + /** + * @brief Get the string to end the "convert from" operation. + */ + static constexpr const char * convert_from_close() = delete; }; - template - struct type_properties, void> - { - static inline std::string make_type() - { return std::string("VARCHAR(") + utl::to_string(N) + ")"; } - - static inline decltype(auto) type() - { - static const std::string v = make_type(); - return v; - } - - static inline std::string convert_to(const value_t& value) - { return *value; } - - static inline value_t convert_from(const std::string& value) - { return value; } - - static constexpr const char* convert_to_open() - { return nullptr; } - - static constexpr const char* convert_to_close() - { return nullptr; } - - static constexpr const char* convert_from_open() - { return nullptr; } - - static constexpr const char* convert_from_close() - { return nullptr; } - }; - - template - struct type_properties>>> - { - using nullable_type = T; - using nullable_helper_type = misc::nullable_helper; - using value_type = typename nullable_helper_type::value_type; - using value_type_props = type_properties; - - static constexpr decltype(auto) type() - { return value_type_props::type(); } - - static inline nullable_type convert_to(const value_t& value) - { - nullable_type ret; - if (value.has_value()) - nullable_helper_type::set(ret, value_type_props::convert_to(value)); - return ret; - } - - static inline value_t convert_from(const nullable_type& value) - { - value_t ret; - auto v = nullable_helper_type::get(value); - if (v) - ret = value_type_props::convert_from(*v); - return ret; - } - - static constexpr const char* convert_to_open() - { return nullptr; } - - static constexpr const char* convert_to_close() - { return nullptr; } - - static constexpr const char* convert_from_open() - { return nullptr; } - - static constexpr const char* convert_from_close() - { return nullptr; } - }; - - template - struct type_properties>>> - { - using enum_type = T; - using base_type = typename std::underlying_type::type; - - static std::string make_type() - { - std::ostringstream os; - os << "ENUM ( "; - auto e = enum_type::first; - while (e <= enum_type::last) - { - if (e != enum_type::first) - os << ", "; - os << "'" << utl::enum_conversion::to_string(e, false) << "'"; - e = static_cast(static_cast(e) + 1); - } - os << " )"; - return os.str(); - } - - static inline decltype(auto) type() - { - static const std::string v = make_type(); - return v; - } - - static inline enum_type convert_to(const value_t& value) - { - enum_type ret; - if (!utl::enum_conversion::try_to_enum(*value, ret, false)) - throw misc::hibernate_exception("unable to convert enum value!"); - return ret; - } - - static inline value_t convert_from(const enum_type& value) - { return utl::enum_conversion::to_string(value, false); } - - static constexpr const char* convert_to_open() - { return nullptr; } - - static constexpr const char* convert_to_close() - { return nullptr; } - - static constexpr const char* convert_from_open() - { return nullptr; } - - static constexpr const char* convert_from_close() - { return nullptr; } - }; - - template - struct type_properties, utl::flags>>> - { - using flags_type = T; - using enum_type = typename flags_type::enum_type; - using base_type = typename std::underlying_type::type; - - static inline std::string make_type() - { - std::ostringstream os; - os << "SET ( "; - auto e = enum_type::first; - while (e <= enum_type::last) - { - if (e != enum_type::first) - os << ", "; - os << "'" << utl::to_string(e) << "'"; - e = static_cast(static_cast(e) + 1); - } - os << " )"; - return os.str(); - } - - static inline decltype(auto) type() - { - static const std::string v = make_type(); - return v; - } - - static inline flags_type convert_to(const value_t& value) - { - auto s = *value; - auto c = s.c_str(); - auto e = c + s.size(); - auto p = c; - flags_type ret; - while (c <= e) - { - if (c == e || *c == ',') - { - if (c - p > 0) - ret.set(utl::enum_conversion::to_enum(std::string(p, static_cast(c - p)), true)); - p = c + 1; - } - ++c; - } - return ret; - } - - static inline value_t convert_from(const flags_type& value) - { - std::ostringstream os; - bool first = true; - for (auto e : value) - { - if (first) first = false; - else os << ","; - os << utl::enum_conversion::to_string(e, false); - } - return os.str(); - } - - static constexpr const char* convert_to_open() - { return nullptr; } - - static constexpr const char* convert_to_close() - { return nullptr; } - - static constexpr const char* convert_from_open() - { return nullptr; } - - static constexpr const char* convert_from_close() - { return nullptr; } - }; +} } -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file +#include "type_properties.inl" diff --git a/include/cpphibernate/driver/mariadb/helper/type_properties.inl b/include/cpphibernate/driver/mariadb/helper/type_properties.inl new file mode 100644 index 0000000..e687358 --- /dev/null +++ b/include/cpphibernate/driver/mariadb/helper/type_properties.inl @@ -0,0 +1,563 @@ +#pragma once + +#include +#include + +#include "type_properties.h" +#include "nullable_helper.h" + +namespace cpphibernate { +namespace mariadb { + + template<> + struct type_properties + { + static constexpr decltype(auto) type() + { return "BOOLEAN"; } + + static inline bool convert_to(const value_t& value) + { return cppcore::from_string(*value); } + + static inline value_t convert_from(const bool& value) + { return cppcore::to_string(static_cast(value)); } + + static constexpr const char* convert_to_open() + { return nullptr; } + + static constexpr const char* convert_to_close() + { return nullptr; } + + static constexpr const char* convert_from_open() + { return nullptr; } + + static constexpr const char* convert_from_close() + { return nullptr; } + }; + + template<> + struct type_properties + { + static constexpr decltype(auto) type() + { return "TINYINT UNSIGNED"; } + + static inline uint8_t convert_to(const value_t& value) + { return static_cast(cppcore::from_string(*value)); } + + static inline value_t convert_from(const uint8_t& value) + { return cppcore::to_string(static_cast(value)); } + + static constexpr const char* convert_to_open() + { return nullptr; } + + static constexpr const char* convert_to_close() + { return nullptr; } + + static constexpr const char* convert_from_open() + { return nullptr; } + + static constexpr const char* convert_from_close() + { return nullptr; } + }; + + template<> + struct type_properties + { + static constexpr decltype(auto) type() + { return "TINYINT"; } + + static inline int8_t convert_to(const value_t& value) + { return static_cast(cppcore::from_string(*value)); } + + static inline value_t convert_from(const int8_t& value) + { return cppcore::to_string(static_cast(value)); } + + static constexpr const char* convert_to_open() + { return nullptr; } + + static constexpr const char* convert_to_close() + { return nullptr; } + + static constexpr const char* convert_from_open() + { return nullptr; } + + static constexpr const char* convert_from_close() + { return nullptr; } + }; + + template<> + struct type_properties + { + static constexpr decltype(auto) type() + { return "SMALLINT UNSIGNED"; } + + static inline uint16_t convert_to(const value_t& value) + { return cppcore::from_string(*value); } + + static inline value_t convert_from(const uint16_t& value) + { return cppcore::to_string(value); } + + static constexpr const char* convert_to_open() + { return nullptr; } + + static constexpr const char* convert_to_close() + { return nullptr; } + + static constexpr const char* convert_from_open() + { return nullptr; } + + static constexpr const char* convert_from_close() + { return nullptr; } + }; + + template<> + struct type_properties + { + static constexpr decltype(auto) type() + { return "SMALLINT"; } + + static inline int16_t convert_to(const value_t& value) + { return cppcore::from_string(*value); } + + static inline value_t convert_from(const int16_t& value) + { return cppcore::to_string(value); } + + static constexpr const char* convert_to_open() + { return nullptr; } + + static constexpr const char* convert_to_close() + { return nullptr; } + + static constexpr const char* convert_from_open() + { return nullptr; } + + static constexpr const char* convert_from_close() + { return nullptr; } + }; + + template<> + struct type_properties + { + static constexpr decltype(auto) type() + { return "INT UNSIGNED"; } + + static inline uint32_t convert_to(const value_t& value) + { return cppcore::from_string(*value); } + + static inline value_t convert_from(const uint32_t& value) + { return cppcore::to_string(value); } + + static constexpr const char* convert_to_open() + { return nullptr; } + + static constexpr const char* convert_to_close() + { return nullptr; } + + static constexpr const char* convert_from_open() + { return nullptr; } + + static constexpr const char* convert_from_close() + { return nullptr; } + }; + + template<> + struct type_properties + { + static constexpr decltype(auto) type() + { return "INT"; } + + static inline int32_t convert_to(const value_t& value) + { return cppcore::from_string(*value); } + + static inline value_t convert_from(const int32_t& value) + { return cppcore::to_string(value); } + + static constexpr const char* convert_to_open() + { return nullptr; } + + static constexpr const char* convert_to_close() + { return nullptr; } + + static constexpr const char* convert_from_open() + { return nullptr; } + + static constexpr const char* convert_from_close() + { return nullptr; } + }; + + template<> + struct type_properties + { + static constexpr decltype(auto) type() + { return "BIGINT UNSIGNED"; } + + static inline uint64_t convert_to(const value_t& value) + { return cppcore::from_string(*value); } + + static inline value_t convert_from(const uint64_t& value) + { return cppcore::to_string(value); } + + static constexpr const char* convert_to_open() + { return nullptr; } + + static constexpr const char* convert_to_close() + { return nullptr; } + + static constexpr const char* convert_from_open() + { return nullptr; } + + static constexpr const char* convert_from_close() + { return nullptr; } + }; + + template<> + struct type_properties + { + static constexpr decltype(auto) type() + { return "BIGINT"; } + + static inline int64_t convert_to(const value_t& value) + { return cppcore::from_string(*value); } + + static inline value_t convert_from(const int64_t& value) + { return cppcore::to_string(value); } + + static constexpr const char* convert_to_open() + { return nullptr; } + + static constexpr const char* convert_to_close() + { return nullptr; } + + static constexpr const char* convert_from_open() + { return nullptr; } + + static constexpr const char* convert_from_close() + { return nullptr; } + }; + + template<> + struct type_properties + { + static constexpr decltype(auto) type() + { return "FLOAT"; } + + static inline float convert_to(const value_t& value) + { return cppcore::from_string(*value); } + + static inline value_t convert_from(const float& value) + { return cppcore::to_string(value); } + + static constexpr const char* convert_to_open() + { return nullptr; } + + static constexpr const char* convert_to_close() + { return nullptr; } + + static constexpr const char* convert_from_open() + { return nullptr; } + + static constexpr const char* convert_from_close() + { return nullptr; } + }; + + template<> + struct type_properties + { + static constexpr decltype(auto) type() + { return "DOUBLE"; } + + static inline double convert_to(const value_t& value) + { return cppcore::from_string(*value); } + + static inline value_t convert_from(const double& value) + { return cppcore::to_string(value); } + + static constexpr const char* convert_to_open() + { return nullptr; } + + static constexpr const char* convert_to_close() + { return nullptr; } + + static constexpr const char* convert_from_open() + { return nullptr; } + + static constexpr const char* convert_from_close() + { return nullptr; } + }; + + template<> + struct type_properties + { + static constexpr decltype(auto) type() + { return "BINARY(16)"; } + + static inline uuid convert_to(const value_t& value) + { return cppcore::from_string(*value); } + + static inline value_t convert_from(const uuid& value) + { return cppcore::to_string(value); } + + static constexpr const char* convert_to_open() + { return "UuidToBin("; } + + static constexpr const char* convert_to_close() + { return ")"; } + + static constexpr const char* convert_from_open() + { return "BinToUuid("; } + + static constexpr const char* convert_from_close() + { return ")"; } + }; + + template<> + struct type_properties + { + static constexpr decltype(auto) type() + { return "BIGINT"; } + + static inline timestamp convert_to(const value_t& value) + { return timestamp(cppcore::from_string(*value)); } + + static inline value_t convert_from(const timestamp& value) + { return cppcore::to_string(static_cast(value)); } + + static constexpr const char* convert_to_open() + { return nullptr; } + + static constexpr const char* convert_to_close() + { return nullptr; } + + static constexpr const char* convert_from_open() + { return nullptr; } + + static constexpr const char* convert_from_close() + { return nullptr; } + }; + + template<> + struct type_properties + { + static constexpr decltype(auto) type() + { return "VARCHAR(100)"; } + + static inline std::string convert_to(const value_t& value) + { return *value; } + + static inline value_t convert_from(const std::string& value) + { return value; } + + static constexpr const char* convert_to_open() + { return nullptr; } + + static constexpr const char* convert_to_close() + { return nullptr; } + + static constexpr const char* convert_from_open() + { return nullptr; } + + static constexpr const char* convert_from_close() + { return nullptr; } + }; + + template + struct type_properties, void> + { + static inline std::string make_type() + { return std::string("VARCHAR(") + cppcore::to_string(N) + ")"; } + + static inline decltype(auto) type() + { + static const std::string v = make_type(); + return v; + } + + static inline std::string convert_to(const value_t& value) + { return *value; } + + static inline value_t convert_from(const std::string& value) + { return value; } + + static constexpr const char* convert_to_open() + { return nullptr; } + + static constexpr const char* convert_to_close() + { return nullptr; } + + static constexpr const char* convert_from_open() + { return nullptr; } + + static constexpr const char* convert_from_close() + { return nullptr; } + }; + + template + struct type_properties>>> + { + using nullable_type = T; + using nullable_helper_type = nullable_helper; + using value_type = typename nullable_helper_type::value_type; + + static constexpr decltype(auto) nullable = nullable_helper_type { }; + static constexpr decltype(auto) value_props = type_properties { }; + + static constexpr decltype(auto) type() + { return value_props.type(); } + + static inline decltype(auto) convert_to(const value_t& value) + { + nullable_type ret; + if (value.has_value()) + nullable.set(ret, value_props.convert_to(value)); + return ret; + } + + static inline value_t convert_from(const nullable_type& value) + { + value_t ret; + auto v = nullable.get(value); + if (v) + ret = value_props.convert_from(*v); + return ret; + } + + static constexpr const char* convert_to_open() + { return value_props.convert_to_open(); } + + static constexpr const char* convert_to_close() + { return value_props.convert_to_close(); } + + static constexpr const char* convert_from_open() + { return value_props.convert_from_open(); } + + static constexpr const char* convert_from_close() + { return value_props.convert_from_close(); } + }; + + template + struct type_properties>>> + { + using enum_type = T; + using base_type = typename std::underlying_type::type; + + static std::string make_type() + { + std::ostringstream os; + os << "ENUM ( "; + auto e = enum_type::first; + while (e <= enum_type::last) + { + if (e != enum_type::first) + os << ", "; + os << "'" << cppcore::enum_conversion::to_string(e, false) << "'"; + e = static_cast(static_cast(e) + 1); + } + os << " )"; + return os.str(); + } + + static inline decltype(auto) type() + { + static const std::string v = make_type(); + return v; + } + + static inline enum_type convert_to(const value_t& value) + { + enum_type ret; + if (!cppcore::enum_conversion::try_to_enum(*value, ret, false)) + throw exception("unable to convert enum value!"); + return ret; + } + + static inline value_t convert_from(const enum_type& value) + { return cppcore::enum_conversion::to_string(value, false); } + + static constexpr const char* convert_to_open() + { return nullptr; } + + static constexpr const char* convert_to_close() + { return nullptr; } + + static constexpr const char* convert_from_open() + { return nullptr; } + + static constexpr const char* convert_from_close() + { return nullptr; } + }; + + template + struct type_properties, cppcore::flags>>> + { + using flags_type = T; + using enum_type = typename flags_type::enum_type; + using base_type = typename std::underlying_type::type; + + static inline std::string make_type() + { + std::ostringstream os; + os << "SET ( "; + auto e = enum_type::first; + while (e <= enum_type::last) + { + if (e != enum_type::first) + os << ", "; + os << "'" << cppcore::to_string(e) << "'"; + e = static_cast(static_cast(e) + 1); + } + os << " )"; + return os.str(); + } + + static inline decltype(auto) type() + { + static const std::string v = make_type(); + return v; + } + + static inline flags_type convert_to(const value_t& value) + { + auto s = *value; + auto c = s.c_str(); + auto e = c + s.size(); + auto p = c; + flags_type ret; + while (c <= e) + { + if (c == e || *c == ',') + { + if (c - p > 0) + ret.set(cppcore::enum_conversion::to_enum(std::string(p, static_cast(c - p)), true)); + p = c + 1; + } + ++c; + } + return ret; + } + + static inline value_t convert_from(const flags_type& value) + { + std::ostringstream os; + bool first = true; + for (auto e : value) + { + if (first) first = false; + else os << ","; + os << cppcore::enum_conversion::to_string(e, false); + } + return os.str(); + } + + static constexpr const char* convert_to_open() + { return nullptr; } + + static constexpr const char* convert_to_close() + { return nullptr; } + + static constexpr const char* convert_from_open() + { return nullptr; } + + static constexpr const char* convert_from_close() + { return nullptr; } + }; + +} } diff --git a/include/cpphibernate/driver/mariadb/schema.h b/include/cpphibernate/driver/mariadb/schema.h deleted file mode 100644 index f3fa522..0000000 --- a/include/cpphibernate/driver/mariadb/schema.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/attributes.fwd.h b/include/cpphibernate/driver/mariadb/schema/attributes.fwd.h deleted file mode 100644 index 259a091..0000000 --- a/include/cpphibernate/driver/mariadb/schema/attributes.fwd.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - /* attribute_t */ - - enum class attribute_t - { - hex, - compress, - primary_key, - }; - - /* attributes_t */ - - struct attributes_t; - - /* make_attributes */ - - namespace __impl - { - - template - struct make_attributes_impl; - - } - - constexpr decltype(auto) make_attributes = misc::make_generic_predicate<__impl::make_attributes_impl> { }; - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/attributes.h b/include/cpphibernate/driver/mariadb/schema/attributes.h deleted file mode 100644 index 3b1ca22..0000000 --- a/include/cpphibernate/driver/mariadb/schema/attributes.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - /* attributes_t */ - - struct attributes_t : - public std::set - { - using base_type = std::set; - using base_type::base_type; - }; - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/field.fwd.h b/include/cpphibernate/driver/mariadb/schema/field.fwd.h deleted file mode 100644 index 275ffc8..0000000 --- a/include/cpphibernate/driver/mariadb/schema/field.fwd.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include -#include -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - /* field_t */ - - struct field_t; - - /* field_ptr_t */ - - using field_ptr_t = std::unique_ptr; - - /* make_field */ - - namespace __impl - { - - template - struct make_field_impl; - - } - - constexpr decltype(auto) make_field = misc::make_generic_predicate<__impl::make_field_impl> { }; - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/field.h b/include/cpphibernate/driver/mariadb/schema/field.h deleted file mode 100644 index 8d037cf..0000000 --- a/include/cpphibernate/driver/mariadb/schema/field.h +++ /dev/null @@ -1,213 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - /* field_t */ - - struct field_t - { - public: - size_t id { 0 }; // unique id of the field - size_t dataset_id { 0 }; // unique id of the dataset type - size_t real_dataset_id { 0 }; // unique id of the real/unwrapped dataset type - size_t value_id { 0 }; // unique id of the value type - size_t real_value_id { 0 }; // unique id of the real/unwrapped value type - - bool value_is_nullable { false }; // value is stored in a nullable container - bool value_is_pointer { false }; // value is stored in a pointer container - bool value_is_container { false }; // value is stored in a container - bool value_is_ordered { false }; // value is stored in a ordered container (vector, list, ...) - bool value_is_auto_incremented { false }; // value is a auto incremented field - - table_t* table { nullptr }; // table this field belongs to - table_t* referenced_table { nullptr }; // table that belongs to the value (if exists) - - std::string schema_name; // name of the SQL schema - std::string table_name; // name of the SQL table - std::string field_name; // name of the SQL field - std::string type; // SQL type name - std::string create_arguments; // additional arguments for CREATE TABLE command - - std::string convert_to_open; // SQL code to open the "convert to" operation - std::string convert_to_close; // SQL code to close the "convert to" operation - std::string convert_from_open; // SQL code to open the "convert from" operation - std::string convert_from_close; // SQL code to close the "convert from" operation - - attributes_t attributes; // attributes for the field - - inline field_t() = default; - inline field_t(const field_t&) = delete; - inline field_t(field_t&& other) - : id (std::move(other).id) - , dataset_id (std::move(other).dataset_id) - , real_dataset_id (std::move(other).real_dataset_id) - , value_id (std::move(other).value_id) - , real_value_id (std::move(other).real_value_id) - , value_is_nullable (std::move(other).value_is_nullable) - , value_is_pointer (std::move(other).value_is_pointer) - , value_is_container (std::move(other).value_is_container) - , value_is_auto_incremented (std::move(other).value_is_auto_incremented) - , table (nullptr) - , referenced_table (nullptr) - , schema_name (std::move(other).schema_name) - , table_name (std::move(other).table_name) - , field_name (std::move(other).field_name) - , type (std::move(other).type) - , create_arguments (std::move(other).create_arguments) - , convert_to_open (std::move(other).convert_to_open) - , convert_to_close (std::move(other).convert_to_close) - , convert_from_open (std::move(other).convert_from_open) - , convert_from_close (std::move(other).convert_from_close) - , attributes (std::move(other).attributes) - { } - virtual ~field_t() { }; - - void print (std::ostream& os) const; - virtual void update (); - - /* CRUD */ - using read_context_ptr = std::unique_ptr; - - virtual value_t foreign_create_update (const create_update_context& context) const; - virtual read_context_ptr foreign_read (const read_context& context, bool fake_context) const; - - /* properties */ - virtual value_t get (const data_context& context) const; - virtual void set (const data_context& context, const value_t&) const; - virtual bool is_default (const data_context& context) const; - virtual std::string generate_value (::cppmariadb::connection& connection) const; - - /* statements */ - virtual ::cppmariadb::statement& get_statement_foreign_one_delete(bool key_known) const; - virtual ::cppmariadb::statement& get_statement_foreign_many_update() const; - - protected: - using statement_ptr = std::unique_ptr<::cppmariadb::statement>; - - ::cppmariadb::statement& get_statement_foreign_one_delete_impl(bool key_known, statement_ptr& known, statement_ptr& unknown) const; - ::cppmariadb::statement& get_statement_foreign_many_update_impl(statement_ptr& statement) const; - }; - - /* simple_field_t */ - - template - struct simple_field_t - : public field_t - { - using base_type = field_t; - using field_type = mp::decay_t; - using getter_type = typename field_type::getter_type; - using dataset_type = mp::decay_t; - using real_dataset_type = misc::real_dataset_t; - using value_type = mp::decay_t; - using real_value_type = misc::real_dataset_t; - using type_props = type_properties; - - const field_type& field; - - inline simple_field_t(const field_type& p_field) - : field_t () - , field (p_field) - { } - - virtual void update() override; - }; - - /* value_field_t */ - - template - struct value_field_t - : public simple_field_t - { - using base_type = simple_field_t; - using field_type = typename base_type::field_type; - using getter_type = typename base_type::getter_type; - using dataset_type = typename base_type::dataset_type; - using real_dataset_type = typename base_type::dataset_type; - using value_type = typename base_type::value_type; - using real_value_type = typename base_type::real_value_type; - using type_props = typename base_type::type_props; - - using base_type::base_type; - - static_assert(mp::is_same::value, "internal error: dataset type mismatch!"); - - virtual void update () override; - virtual value_t get (const data_context& context) const override; - virtual void set (const data_context& context, const value_t& value) const override; - }; - - /* primary_key_field_t */ - - template - struct primary_key_field_t - : public value_field_t - { - using base_type = value_field_t; - using field_type = typename base_type::field_type; - using dataset_type = typename base_type::dataset_type; - using value_type = typename base_type::value_type; - using key_props = key_properties; - - using base_type::base_type; - - virtual void update () override; - virtual bool is_default (const data_context& context) const override; - virtual std::string generate_value(::cppmariadb::connection& connection) const override; - }; - - /* data_field_t */ - - template - struct data_field_t - : public value_field_t - { - using base_type = value_field_t; - - using base_type::base_type; - }; - - /* foreign_table_field_t */ - - template - struct foreign_table_field_t - : public simple_field_t - { - public: - using base_type = simple_field_t; - using value_type = typename base_type::value_type; - using real_value_type = typename base_type::real_value_type; - using dataset_type = typename base_type::dataset_type; - - using base_type::base_type; - - public: - /* CRUD */ - virtual value_t foreign_create_update(const create_update_context& context) const override; - virtual read_context_ptr foreign_read (const read_context& context, bool fake_context) const override; - - /* statements */ - virtual ::cppmariadb::statement& get_statement_foreign_one_delete(bool key_known) const override; - virtual ::cppmariadb::statement& get_statement_foreign_many_update() const override; - - private: - using statement_ptr = std::unique_ptr<::cppmariadb::statement>; - - mutable statement_ptr _statement_foreign_one_delete_key_known; - mutable statement_ptr _statement_foreign_one_delete_key_unknown; - mutable statement_ptr _statement_foreign_many_update; - }; - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/field.inl b/include/cpphibernate/driver/mariadb/schema/field.inl deleted file mode 100644 index fef4450..0000000 --- a/include/cpphibernate/driver/mariadb/schema/field.inl +++ /dev/null @@ -1,228 +0,0 @@ -#pragma once - -#include -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - /* simple_field_t */ - - template - void simple_field_t - ::update() - { - base_type::update(); - - id = misc::get_type_id(hana::type_c); - dataset_id = misc::get_type_id(hana::type_c); - real_dataset_id = misc::get_type_id(hana::type_c); - value_id = misc::get_type_id(hana::type_c); - real_value_id = misc::get_type_id(hana::type_c); - - value_is_nullable = misc::is_nullable::value; - value_is_pointer = misc::is_pointer::value; - value_is_container = misc::is_container::value; - value_is_ordered = misc::is_ordered::value; - } - - /* value_field_t */ - - template - void value_field_t - ::update() - { - base_type::update(); - - this->type = type_props::type(); - - if (type_props::convert_to_open()) - this->convert_to_open = this->convert_to_open + type_props::convert_to_open(); - if (type_props::convert_to_close()) - this->convert_to_close = type_props::convert_to_close() + this->convert_to_close; - if (type_props::convert_from_open()) - this->convert_from_open = this->convert_from_open + type_props::convert_from_open(); - if (type_props::convert_from_close()) - this->convert_from_close = type_props::convert_from_close() + this->convert_from_close; - } - - template - value_t value_field_t - ::get(const data_context& context) const - { - auto& dataset = context.get(); - return type_props::convert_from(this->field.getter(dataset)); - } - - template - void value_field_t - ::set(const data_context& context, const value_t& value) const - { - auto& dataset = context.get(); - this->field.setter(dataset, type_props::convert_to(value)); - } - - /* primary_key_field_t */ - - template - void primary_key_field_t - ::update() - { - base_type::update(); - - this->value_is_auto_incremented = key_props::auto_generated::value; - } - - template - bool primary_key_field_t - ::is_default(const data_context& context) const - { - auto& dataset = context.get(); - return key_props::is_default(this->field.getter(dataset)); - } - - template - std::string primary_key_field_t - ::generate_value(::cppmariadb::connection& connection) const - { - auto ret = connection.execute_used(key_props::create_key_query); - if (!ret || !ret->next()) - throw misc::hibernate_exception("unable to generate key value!"); - return ret->current()->at(0).template get(); - } - - /* foreign_table_field_t */ - - template - value_t foreign_table_field_t - ::foreign_create_update(const create_update_context& context) const - { - auto& dataset = context.get(); - auto& foreign = this->field.getter(dataset); - auto next_context = change_context(context, foreign); - - using foreign_dataset_type = mp::decay_t; - return create_update_impl_t::apply( - next_context, - false); - } - - template - read_context_ptr foreign_table_field_t - ::foreign_read(const read_context& context, bool fake_context) const - { - if (!fake_context) - { - auto& dataset = context.get(); - auto& member = this->field.getter(dataset); - auto new_context = make_read_context(member, context.schema, context.connection, context.filter); - using context_type = mp::decay_t; - return std::make_unique(new_context); - } - else - { - auto new_context = make_fake_context(hana::type_c, context.schema, context.connection, context.filter); - using context_type = mp::decay_t; - return std::make_unique(new_context); - } - } - - template - ::cppmariadb::statement& foreign_table_field_t - ::get_statement_foreign_one_delete(bool key_known) const - { - return base_type::get_statement_foreign_one_delete_impl( - key_known, - _statement_foreign_one_delete_key_known, - _statement_foreign_one_delete_key_unknown); - } - - template - ::cppmariadb::statement& foreign_table_field_t - ::get_statement_foreign_many_update() const - { return base_type::get_statement_foreign_many_update_impl(_statement_foreign_many_update); } - - namespace __impl - { - - /* is_primary_key_field */ - - template - struct is_primary_key_field - : public mp::decay_t().attributes, - schema::attribute::primary_key))> - { }; - - /* is_foreign_table_field */ - - template - struct is_foreign_table_field - : public mp::decay_t().tables, - schema::table::get_wrapped_dataset), - hana::type_c>))> - { }; - - /* field_type */ - - template - struct field_type - { using type = data_field_t; }; - - template - struct field_type>> - { using type = primary_key_field_t; }; - - template - struct field_type>> - { using type = foreign_table_field_t; }; - - template - using field_type_t = typename field_type::type; - - /* make_field_impl */ - - template - struct make_field_impl - { - template - static constexpr decltype(auto) apply(T_args&&... args) - { static_assert(sizeof...(args) == -1, "Invalid parameters for mariadb::make_field(...)!"); } - }; - - template - struct make_field_impl< - mp::list, - mp::enable_if_c< - schema::is_schema>::value - && schema::is_table >::value - && schema::is_field >::value>> - { - static constexpr decltype(auto) apply(const T_schema& schema, const T_table& table, const T_field& field) - { - using schema_type = mp::decay_t; - using field_type = mp::decay_t; - using return_type = field_type_t; - using primary_key_type = primary_key_field_t; - return_type ret(field); - ret.schema_name = schema.name; - ret.table_name = table.name; - ret.field_name = field.name; - ret.attributes = make_attributes(field.attributes); - hana::eval_if( - hana::equal(hana::type_c, hana::type_c), - [&ret](){ - ret.field_name = ret.table_name + "_" + ret.field_name; - }, [](){ }); - return ret; - } - }; - - } - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/fields.fwd.h b/include/cpphibernate/driver/mariadb/schema/fields.fwd.h deleted file mode 100644 index f2411a8..0000000 --- a/include/cpphibernate/driver/mariadb/schema/fields.fwd.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -#include -#include -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - /* fields_t */ - - struct fields_t; - - /* make_fields */ - - namespace __impl - { - - template - struct make_fields_impl; - - } - - constexpr decltype(auto) make_fields = misc::make_generic_predicate<__impl::make_fields_impl> { }; - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/fields.h b/include/cpphibernate/driver/mariadb/schema/fields.h deleted file mode 100644 index 8eb5400..0000000 --- a/include/cpphibernate/driver/mariadb/schema/fields.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include -#include -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - /* fields_t */ - - struct fields_t - : public std::vector - { - using base_type = std::vector; - using base_type::base_type; - }; - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/fields.inl b/include/cpphibernate/driver/mariadb/schema/fields.inl deleted file mode 100644 index e5b044a..0000000 --- a/include/cpphibernate/driver/mariadb/schema/fields.inl +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - namespace __impl - { - - /* make_fields_impl */ - - template - struct make_fields_impl - { - template - static constexpr decltype(auto) apply(T_args&&... args) - { static_assert(sizeof...(args) == -1, "Invalid parameters for mariadb::make_fields(...)!"); } - }; - - template - struct make_fields_impl< - mp::list, - mp::enable_if_c< - schema::is_schema>::value - && schema::is_table >::value>> - { - template - static constexpr void emplace(fields_t& fields, const T_schema& schema, const T_table& table, T_index&& index) - { - decltype(auto) field = make_field(schema, table, table.fields[index]); - using field_type = mp::decay_t; - fields.emplace_back(new field_type(std::move(field))); - } - - template - static auto helper(const T_schema& schema, const T_table& table, std::index_sequence&&) - { - fields_t fields; - int dummy[] = {0, (emplace(fields, schema, table, hana::size_c), void(), 0)...}; - (void) dummy; - return fields; - } - - static constexpr decltype(auto) apply(const T_schema& schema, const T_table& table) - { - using size = decltype(hana::size(table.fields)); - return helper(schema, table, std::make_index_sequence { }); - } - }; - - } - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/filter.fwd.h b/include/cpphibernate/driver/mariadb/schema/filter.fwd.h deleted file mode 100644 index 24e3510..0000000 --- a/include/cpphibernate/driver/mariadb/schema/filter.fwd.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - /* filter_t */ - - struct filter_t; - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/filter.h b/include/cpphibernate/driver/mariadb/schema/filter.h deleted file mode 100644 index c1cc432..0000000 --- a/include/cpphibernate/driver/mariadb/schema/filter.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - namespace __impl - { - - /* filter_add_element */ - - template - struct filter_add_element_impl; - - constexpr decltype(auto) filter_add_element = misc::make_generic_predicate<__impl::filter_add_element_impl> { }; - - } - - /* filter_t */ - - struct filter_t - { - public: - using field_set_type = std::set; - using table_set_type = std::set; - - size_t cache_id { 0 }; - bool exclusive { true }; - field_set_type fields; - table_set_type tables; - - inline bool is_excluded(const table_t& table) const; - inline bool is_excluded(const field_t& field) const; - - template - inline void set_inclusive(const schema_t& schema, T_args&&... args); - - template - inline void set_exclusive(const schema_t& schema, T_args&&... args); - - inline void clear(); - - private: - void update_tables(); - }; - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/filter.inl b/include/cpphibernate/driver/mariadb/schema/filter.inl deleted file mode 100644 index fd251bf..0000000 --- a/include/cpphibernate/driver/mariadb/schema/filter.inl +++ /dev/null @@ -1,122 +0,0 @@ -#pragma once - -#include -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - namespace __impl - { - - /* filter_add_element_impl */ - - template - struct filter_add_element_impl - { - template - static constexpr decltype(auto) apply(T_args&&... args) - { static_assert(sizeof...(args) == -1, "Invalid parameters for mariadb::filter_add_element(...)!"); } - }; - - template - struct filter_add_element_impl< - mp::list, - mp::enable_if_c< - schema::is_table>::value>> - { - static constexpr decltype(auto) apply(filter_t& filter, const schema_t& schema, const T_table& table) - { - auto dataset_id = misc::get_type_id(table.wrapped_dataset); - auto& t = schema.table(dataset_id); - filter.tables.emplace(&t); - for (auto& ptr : t.fields) - { - filter.fields.emplace(ptr.get()); - } - } - }; - - template - struct filter_add_element_impl< - mp::list, - mp::enable_if_c< - schema::is_field>::value>> - { - static constexpr decltype(auto) apply(filter_t& filter, const schema_t& schema, const T_field& field) - { - auto field_id = misc::get_type_id(hana::type_c>); - auto& f = schema.field(field_id); - filter.fields.emplace(&f); - filter.tables.emplace(f.table); - } - }; - - } - - /* filter_t */ - - bool filter_t::is_excluded(const table_t& table) const - { - auto ret = static_cast(tables.count(&table)); - if (!exclusive) - ret = !ret; - return ret; - } - - bool filter_t::is_excluded(const field_t& field) const - { - auto ret = static_cast(fields.count(&field)); - if (!exclusive) - ret = !ret; - return ret; - } - - template - void filter_t::set_inclusive(const schema_t& schema, T_args&&... args) - { - clear(); - exclusive = false; - cache_id = static_cast(utl::get_unique_id...>()); - int dummy[] = { 0, (__impl::filter_add_element(*this, schema, std::forward(args)), void(), 0)... }; - (void)dummy; - } - - template - void filter_t::set_exclusive(const schema_t& schema, T_args&&... args) - { - clear(); - exclusive = true; - cache_id = static_cast(utl::get_unique_id...>()); - int dummy[] = { 0, (__impl::filter_add_element(*this, schema, std::forward(args)), void(), 0)... }; - (void)dummy; - - // remove excluded tables if not all fields are excluded - auto it = tables.begin(); - while (it != tables.end()) - { - bool removed = false; - for (auto& field : (*it)->fields) - { - if (fields.count(field.get())) - { - it = tables.erase(it); - removed = true; - break; - } - } - if (!removed) - ++it; - } - } - - void filter_t::clear() - { - cache_id = 0; - exclusive = true; - fields.clear(); - tables.clear(); - } - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/schema.fwd.h b/include/cpphibernate/driver/mariadb/schema/schema.fwd.h deleted file mode 100644 index 87217aa..0000000 --- a/include/cpphibernate/driver/mariadb/schema/schema.fwd.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include -#include -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - /* schema_t */ - - struct schema_t; - - /* make_schema */ - - namespace __impl - { - - template - struct make_schema_impl; - - } - - constexpr decltype(auto) make_schema = misc::make_generic_predicate<__impl::make_schema_impl> { }; - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/schema.h b/include/cpphibernate/driver/mariadb/schema/schema.h deleted file mode 100644 index 2b3498b..0000000 --- a/include/cpphibernate/driver/mariadb/schema/schema.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - /* schema_t */ - - struct schema_t - { - std::string schema_name; - tables_t tables; - - inline schema_t() = default; - inline schema_t(const schema_t&) = delete; - inline schema_t(schema_t&& other) - : schema_name(std::move(other).schema_name) - , tables (std::move(other).tables) - { update(); } - - void update (); - void print (std::ostream& os) const; - - const table_t& table(size_t dataset_id) const; - const field_t& field(size_t field_id) const; - - /* CRUD */ - void init(const init_context& context) const; - }; - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/schema.inl b/include/cpphibernate/driver/mariadb/schema/schema.inl deleted file mode 100644 index 8c1b6ed..0000000 --- a/include/cpphibernate/driver/mariadb/schema/schema.inl +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - namespace __impl - { - - /* make_schema_impl */ - - template - struct make_schema_impl - { - template - static constexpr decltype(auto) apply(T_args&&... args) - { static_assert(sizeof...(args) == -1, "Invalid parameters for mariadb::make_schema(...)!"); } - }; - - template - struct make_schema_impl< - mp::list, - mp::enable_if_c< - schema::is_schema>::value>> - { - static decltype(auto) apply(const T_schema& schema) - { - schema_t ret; - ret.schema_name = schema.name; - ret.tables = make_tables(schema); - ret.update(); - return ret; - } - }; - - } - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/table.fwd.h b/include/cpphibernate/driver/mariadb/schema/table.fwd.h deleted file mode 100644 index d63f620..0000000 --- a/include/cpphibernate/driver/mariadb/schema/table.fwd.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include -#include -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - /* table_t */ - - struct table_t; - - /* table_ptr_t */ - - using table_ptr_t = std::unique_ptr; - - /* make_table */ - - namespace __impl - { - - template - struct make_table_impl; - - } - - constexpr decltype(auto) make_table = misc::make_generic_predicate<__impl::make_table_impl> { }; - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/table.h b/include/cpphibernate/driver/mariadb/schema/table.h deleted file mode 100644 index 198077c..0000000 --- a/include/cpphibernate/driver/mariadb/schema/table.h +++ /dev/null @@ -1,208 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - /* table_t */ - - struct table_t - { - public: - size_t dataset_id { 0 }; - size_t base_dataset_id { 0 }; - size_t table_id { 0 }; - bool is_used_in_container { false }; - - std::vector derived_dataset_ids; - std::string table_name; - std::string schema_name; - - fields_t fields; - - const table_t* base_table { nullptr }; - std::vector derived_tables; - - const field_t* primary_key_field { nullptr }; - std::vector foreign_key_fields; - std::vector foreign_table_fields; - std::vector foreign_table_one_fields; - std::vector foreign_table_many_fields; - std::vector data_fields; - - inline table_t() = default; - inline table_t(const table_t&) = delete; - inline table_t(table_t&& other) - : dataset_id (std::move(other).dataset_id) - , base_dataset_id (std::move(other).base_dataset_id) - , table_id (std::move(other).table_id) - , derived_dataset_ids (std::move(other).derived_dataset_ids) - , table_name (std::move(other).table_name) - , schema_name (std::move(other).schema_name) - , fields (std::move(other).fields) - , base_table (nullptr) - , derived_tables () - , primary_key_field (nullptr) - , foreign_key_fields () - , foreign_table_fields () - , foreign_table_one_fields () - , foreign_table_many_fields () - , data_fields () - { } - virtual ~table_t() { }; - - void print(std::ostream& os) const; - - const table_t* get_derived_by_table_id(size_t id) const; - const table_t* get_derived_by_dataset_id(size_t id) const; - - virtual void emplace (const read_context& context) const; - std::string get_where_primary_key(const data_context& context) const; - std::string build_delete_query (const std::string* where) const; - - /* CRUD */ - inline void init_stage1(const init_context& context) const - { return init_stage1_exec(context); } - - inline void init_stage2(const init_context& context) const - { return init_stage2_exec(context); } - - inline decltype(auto) create_update(const create_update_context& context) const - { return create_update_intern(context); } - - inline void read(const read_context& context) const - { return read_exec(context); } - - inline void destroy(const destroy_context& context) const - { return destroy_intern(context); } - - private: - template - friend struct table_simple_t; - - template - friend struct table_polymorphic_t; - - using statement_ptr = std::unique_ptr<::cppmariadb::statement>; - using map_key = std::tuple; - using statement_map = std::map; - - mutable statement_ptr _statement_key_from_base; - mutable statement_ptr _statement_create_table; - mutable statement_ptr _statement_alter_table; - mutable statement_ptr _statement_insert_into; - mutable statement_map _statement_select_static; - mutable statement_map _statement_select_dynamic; - mutable statement_map _statement_update; - mutable statement_ptr _statement_foreign_many_delete; - mutable statement_ptr _statement_delete; - - ::cppmariadb::statement& get_statement_key_from_base() const; - ::cppmariadb::statement& get_statement_create_table() const; - ::cppmariadb::statement* get_statement_alter_table() const; - ::cppmariadb::statement* get_statement_insert_into() const; - ::cppmariadb::statement& get_statement_select(const read_context& context) const; - ::cppmariadb::statement* get_statement_update(const filter_t& filter, const field_t* owner) const; - ::cppmariadb::statement& get_statement_foreign_many_delete() const; - ::cppmariadb::statement& get_statement_delete() const; - - void execute_foreign_many_delete(const base_context& context) const; - - std::string execute_create_update( - const create_update_context& context, - ::cppmariadb::statement* statement) const; - - std::string get_primary_key(const data_context& context) const; - std::string get_key_from_base(const data_context& context) const; - - virtual std::string create_update_base(const create_update_context& context) const; - - protected: - using table_set = std::set; - - void init_stage1_exec (const init_context& context) const; - void init_stage2_exec (const init_context& context) const; - - virtual std::string create_update_intern(const create_update_context& context) const; - std::string create_update_exec (const create_update_context& context) const; - - void read_exec (const read_context& context) const; - - virtual void destroy_intern (const destroy_context& context) const; - void destroy_exec (const destroy_context& context) const; - void destroy_cleanup (const base_context& context, table_set& processed, bool check_derived, bool check_base) const; - }; - - /* table_simple_t */ - - template - struct table_simple_t - : public table_t - { - public: - using schema_type = T_schema; - using table_type = T_table; - using base_dataset_type = T_base_dataset; - using dataset_type = typename table_type::dataset_type; - - const schema_type& schema; - const table_type& table; - - inline table_simple_t(const schema_type& p_schema, const table_type& p_table) - : schema(p_schema) - , table (p_table) - { } - - inline table_simple_t(const table_simple_t&) = delete; - - inline table_simple_t(table_simple_t&& other) - : table_t(std::move(other)) - , schema (std::move(other).schema) - , table (std::move(other).table) - { } - }; - - /* table_polymorphic_t */ - - template - struct table_polymorphic_t - : public table_simple_t - { - public: - using base_type = table_simple_t; - using schema_type = typename base_type::schema_type; - using table_type = typename base_type::table_type; - using base_dataset_type = typename base_type::base_dataset_type; - using dataset_type = typename table_type::dataset_type; - using real_dataset_type = misc::real_dataset_t; - - using base_type::base_type; - - virtual void emplace(const read_context& context) const override; - - private: - template - constexpr void for_each_derived(T_dataset& dataset, const T_include_self& include_self, const T_pred& pred) const; - - protected: - virtual std::string create_update_intern(const create_update_context& context) const override; - virtual void destroy_intern (const destroy_context& context) const override; - - private: - virtual std::string create_update_base(const create_update_context& context) const override; - }; - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/table.inl b/include/cpphibernate/driver/mariadb/schema/table.inl deleted file mode 100644 index 9191096..0000000 --- a/include/cpphibernate/driver/mariadb/schema/table.inl +++ /dev/null @@ -1,218 +0,0 @@ -#pragma once - -#include -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - /* table_polymorphic_t */ - - template - void table_polymorphic_t - ::emplace(const read_context& context) const - { - hana::eval_if( - std::is_abstract { }, - [](){ - throw misc::hibernate_exception(std::string("can not create dataset of abstract type: ") - + utl::type_helper::name()); - }, - [&context, this](auto _){ - _(context).template emplace(this); - }); - } - - template - template - constexpr void table_polymorphic_t - ::for_each_derived(T_dataset& dataset, const T_include_self& include_self, const T_pred& pred) const - { - auto derived_types = hana::filter( - schema::get_all_derived_types(this->schema, hana::type_c), - [&](auto type){ - return hana::and_( - hana::not_(hana::trait(type)), - hana::or_( - type != hana::type_c, - include_self)); - }); - - hana::for_each(derived_types, [&](auto& type){ - using derived_type = misc::decay_unwrap_t; - auto* derived = dynamic_cast(&dataset); - if (derived) - pred(*derived); - }); - } - - template - std::string table_polymorphic_t - ::create_update_intern(const create_update_context& context) const - { - bool done = false; - auto& dataset = context.get(); - for_each_derived(dataset, hana::false_c, [&](auto& derived_dataset){ - if (!done) - { - using derived_dataset_type = mp::decay_t; - auto derived_dataset_id = misc::get_type_id(hana::type_c); - auto derived_table = this->get_derived_by_dataset_id(derived_dataset_id); - if (!derived_table) - { - throw misc::hibernate_exception(static_cast(std::ostringstream { } - << "unable to find derived table info for dataset '" - << utl::type_helper::name() << "'!").str()); - } - derived_table->create_update(change_context(context, derived_dataset)); - done = true; - } - }); - - return done - ? *this->primary_key_field->get(context) - : this->create_update_exec(context); - } - - template - void table_polymorphic_t - ::destroy_intern(const destroy_context& context) const - { - bool done = false; - auto& dataset = context.get(); - for_each_derived(dataset, hana::false_c, [&](auto& derived_dataset){ - if (!done) - { - using derived_dataset_type = mp::decay_t; - auto derived_dataset_id = misc::get_type_id(hana::type_c); - auto derived_table = this->get_derived_by_dataset_id(derived_dataset_id); - if (!derived_table) - { - throw misc::hibernate_exception(static_cast(std::ostringstream { } - << "unable to find derived table info for dataset '" - << utl::type_helper::name() << "'!").str()); - } - auto new_context = change_context(context, derived_dataset); - derived_table->destroy(new_context); - done = true; - } - }); - - if (!done) - { - this->destroy_exec(context); - } - } - - template - std::string table_polymorphic_t - ::create_update_base(const create_update_context& context) const - { - return hana::eval_if( - mp::is_same { }, - [this]()->std::string { - throw misc::hibernate_exception(static_cast(std::ostringstream { } - << "'" << this->table_name << "' does not have a base table").str()); - }, - [this, &context](auto _)->std::string { - using tmp_type = misc::decay_unwrap_t))>; - assert(this->base_table); - auto& dataset = context.get(); - auto& base = static_cast(dataset); - return this->base_table->create_update_exec(change_context(context, base)); - }); - } - - namespace __impl - { - - /* make_dataset_id_vector */ - - struct make_dataset_id_vector_impl - { - template - static constexpr decltype(auto) helper(const T_wrapped_datasets& wrapped_datasets, std::index_sequence) - { - return std::vector({ - misc::get_type_id(wrapped_datasets[hana::size_c])... - }); - } - - template - constexpr decltype(auto) operator()(T_wrapped_datasets&& wrapped_datasets) const - { - using size = mp::decay_t; - return helper(std::forward(wrapped_datasets), std::make_index_sequence { }); - } - }; - - static constexpr decltype(auto) make_dataset_id_vector = make_dataset_id_vector_impl { }; - - /* make_table_impl */ - - template - struct make_table_impl - { - template - static constexpr decltype(auto) apply(T_args&&... args) - { static_assert(sizeof...(args) == 0, "Invalid parameters for mariadb::make_table(...)!"); } - }; - - template - struct make_table_impl< - mp::list, - mp::enable_if_c< - schema::is_schema>::value - && schema::is_table >::value>> - { - - /* table_type */ - - template - struct table_type - { using type = table_simple_t, mp::decay_t, T_base_dataset>; }; - - template - struct table_type::value>> - { using type = table_polymorphic_t, mp::decay_t, T_base_dataset>; }; - - template - using table_type_t = typename table_type::type; - - /* apply */ - - static decltype(auto) apply(const T_schema& schema, const T_table& table) - { - using wrapped_base_type = mp::decay_t(), - std::declval().wrapped_dataset))>; - using base_type = misc::unwrap_t; - using derived_wrapped_types_type = mp::decay_t(), - std::declval().wrapped_dataset))>; - using wrapped_dataset_type = typename mp::decay_t::wrapped_dataset_type; - using dataset_type = misc::unwrap_t; - using real_dataset_type = misc::real_dataset_t; - using table_type = table_type_t; - - static_assert(mp::is_same::value, "table cn only be created for simple dataset types (not for containers)!"); - - table_type ret(schema, table); - ret.dataset_id = misc::get_type_id(table.wrapped_dataset); - ret.base_dataset_id = misc::get_type_id(wrapped_base_type { }); - ret.derived_dataset_ids = make_dataset_id_vector(derived_wrapped_types_type { }); - ret.table_id = hana::value(table.table_id); - ret.schema_name = schema.name; - ret.table_name = table.name; - ret.fields = make_fields(schema, table); - return ret; - } - }; - - } - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/tables.fwd.h b/include/cpphibernate/driver/mariadb/schema/tables.fwd.h deleted file mode 100644 index 78e0ebd..0000000 --- a/include/cpphibernate/driver/mariadb/schema/tables.fwd.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -#include -#include -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - /* tables_t */ - - struct tables_t; - - /* make_tables */ - - namespace __impl - { - - template - struct make_tables_impl; - - } - - constexpr decltype(auto) make_tables = misc::make_generic_predicate<__impl::make_tables_impl> { }; - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/tables.h b/include/cpphibernate/driver/mariadb/schema/tables.h deleted file mode 100644 index c127cfb..0000000 --- a/include/cpphibernate/driver/mariadb/schema/tables.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - /* tables_t */ - - struct tables_t - : public std::map - { - using base_type = std::map; - using base_type::base_type; - }; - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/driver/mariadb/schema/tables.inl b/include/cpphibernate/driver/mariadb/schema/tables.inl deleted file mode 100644 index acabb9e..0000000 --- a/include/cpphibernate/driver/mariadb/schema/tables.inl +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include - -beg_namespace_cpphibernate_driver_mariadb -{ - - namespace __impl - { - - /* make_tables_impl */ - - template - struct make_tables_impl - { - template - static constexpr decltype(auto) apply(T_args&&... args) - { static_assert(sizeof...(args) == -1, "Invalid parameters for mariadb::make_tables(...)!"); } - }; - - template - struct make_tables_impl< - mp::list, - mp::enable_if_c< - schema::is_schema>::value>> - { - template - static constexpr void emplace(tables_t& tables, const T_schema& schema, T_index&& index) - { - decltype(auto) table = make_table(schema, schema.tables[index]); - using table_type = mp::clean_type; - auto key = table.dataset_id; - tables.emplace(key, std::make_unique(std::move(table))); - } - - template - static decltype(auto) helper(const T_schema& schema, std::index_sequence) - { - tables_t tables; - int dummy[] = {0, (emplace(tables, schema, hana::size_c), void(), 0)...}; - (void) dummy; - return tables; - } - - static constexpr decltype(auto) apply(const T_schema& schema) - { - using size = decltype(hana::size(schema.tables)); - return helper(schema, std::make_index_sequence { }); - } - }; - - } - -} -end_namespace_cpphibernate_driver_mariadb \ No newline at end of file diff --git a/include/cpphibernate/misc/equality_compare.h b/include/cpphibernate/misc/equality_compare.h index 0c19134..033f005 100644 --- a/include/cpphibernate/misc/equality_compare.h +++ b/include/cpphibernate/misc/equality_compare.h @@ -5,26 +5,58 @@ namespace cpphibernate { + namespace __impl + { + + template + using equality_compare_equal = mp::bool_t>, + hana::type_c>))>; + + template + using equality_compare_not_equal = mp::bool_t>, + hana::type_c>))>; + + } + /** * @brief Tag all objects that are equality comparable to each other. * * @tparam T_group Type used for groupig different types. */ template - struct tag_equality_comparable; + struct tag_equality_comparable + { + static constexpr decltype(auto) equality_compare_group = hana::type_c; + }; /** * @brief Equality compare for all objects that has the quality compare tag */ template - constexpr decltype(auto) operator == (T_lhs&& lhs, T_rhs&& rhs); + constexpr auto operator == (T_lhs&&, T_rhs&&) + -> mp::enable_if_t< + mp::is_valid_v().equality_compare_group)> + && mp::is_valid_v().equality_compare_group)> + && mp::is_same_v< + typename decltype(+std::declval().equality_compare_group)::type, + typename decltype(+std::declval().equality_compare_group)::type>, + __impl::equality_compare_equal> + { return __impl::equality_compare_equal { }; } /** * @brief Equality compare for all objects that has the quality compare tag */ template - constexpr decltype(auto) operator != (T_lhs&& lhs, T_rhs&& rhs); + constexpr auto operator != (T_lhs&&, T_rhs&&) + -> mp::enable_if_t< + mp::is_valid_v().equality_compare_group)> + && mp::is_valid_v().equality_compare_group)> + && mp::is_same_v< + typename decltype(+std::declval().equality_compare_group)::type, + typename decltype(+std::declval().equality_compare_group)::type>, + __impl::equality_compare_not_equal> + { return __impl::equality_compare_not_equal { }; } } - -#include "equality_compare.inl" diff --git a/include/cpphibernate/misc/equality_compare.inl b/include/cpphibernate/misc/equality_compare.inl deleted file mode 100644 index 56d24f3..0000000 --- a/include/cpphibernate/misc/equality_compare.inl +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once - -#include "equality_compare.h" - -namespace cpphibernate -{ - - namespace __impl - { - - template - struct equality_compare_impl - { - static constexpr decltype(auto) equal(T_lhs&&, T_rhs&&) - { static_assert(sizeof(T_lhs) == -1, "Unable to equality compare these two types."); } - - static constexpr decltype(auto) not_equal(T_lhs&&, T_rhs&&) - { static_assert(sizeof(T_lhs) == -1, "Unable to equality compare these two types."); } - }; - - template - struct equality_compare_impl< - T_lhs, - T_rhs, - mp::enable_if_t< - mp::is_valid_v - && mp::is_valid_v - && mp::is_same_v< - typename T_lhs::equality_compare_group_type, - typename T_rhs::equality_compare_group_type>>> - { - static constexpr decltype(auto) equal(T_lhs&&, T_rhs&&) - { return hana::type_c> == hana::type_c>; } - - static constexpr decltype(auto) not_equal(T_lhs&&, T_rhs&&) - { return hana::type_c> != hana::type_c>; } - }; - - }; - - template - struct tag_equality_comparable - { - using equality_compare_group_type = T_group; - }; - - template - constexpr decltype(auto) operator == (T_lhs&& lhs, T_rhs&& rhs) - { - using equality_compare_type = __impl::equality_compare_impl; - return equality_compare_type::equal(std::forward(lhs), std::forward(rhs)); - } - - template - constexpr decltype(auto) operator != (T_lhs&& lhs, T_rhs&& rhs) - { - using equality_compare_type = __impl::equality_compare_impl; - return equality_compare_type::not_equal(std::forward(lhs), std::forward(rhs)); - } - -} diff --git a/include/cpphibernate/misc/print_container.inl b/include/cpphibernate/misc/print_container.inl index 5706dc1..eef7839 100644 --- a/include/cpphibernate/misc/print_container.inl +++ b/include/cpphibernate/misc/print_container.inl @@ -1,6 +1,7 @@ #pragma once #include +#include #include "print_container.h" @@ -77,8 +78,10 @@ namespace cpphibernate { static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_print_container(...)!"); } }; - template - struct print_container_builder, void> + template + struct print_container_builder< + mp::list, + mp::enable_if_t>>> { static constexpr decltype(auto) apply(T_container&& container, bool do_indent, T_func&& func) { @@ -91,14 +94,16 @@ namespace cpphibernate } }; - template - struct print_container_builder, void> + template + struct print_container_builder< + mp::list, + mp::enable_if_t>>> { static constexpr decltype(auto) apply(T_container&& container, bool do_indent) { using namespace ::cppcore; - make_print_container( + return make_print_container( std::forward(container), do_indent, [do_indent](auto& os, auto& value) @@ -114,3 +119,26 @@ namespace cpphibernate } } + +namespace std +{ + + template< + typename T_print_container, + typename T_char, + typename T_traits> + inline auto + operator << ( + basic_ostream& os, + const T_print_container& ctnr) + -> ::cppmp::enable_if_t< + ::cppmp::is_specialization_of_v< + ::cppmp::decay_t, + ::cpphibernate::__impl::print_container>, + basic_ostream&> + { + ctnr.print(os); + return os; + } + +} diff --git a/include/cpphibernate/misc/type_helper.h b/include/cpphibernate/misc/type_helper.h index fd551e5..2f8a0b7 100644 --- a/include/cpphibernate/misc/type_helper.h +++ b/include/cpphibernate/misc/type_helper.h @@ -29,6 +29,67 @@ namespace cpphibernate template using decay_unwrap_t = typename mp::decay_t::type; + /** + * @brief Unwrap the passed hana::type and return an object of the inner type. + */ + template + constexpr decltype(auto) unwrap(T&& t) + { return typename decltype(+t)::type { }; } + + /** + * @brief Get a unique ID for the passed type + */ + template + constexpr decltype(auto) get_type_id(T_type&&); + + /** + * @brief Evaluates to true_t if the passed type is a container, false_t otherwise. + */ + template + struct is_container; + + /** + * @brief Is true if the passed type is a container, false otherwise. + */ + template + constexpr decltype(auto) is_container_v = is_container::value; + + /** + * @brief Evaluates to true_t if the passed type is an ordered container type, false_t otherwise. + */ + template + struct is_ordered; + + /** + * @brief Is true if the passed type is an ordered container type, false otherwise. + */ + template + constexpr decltype(auto) is_ordered_v = is_ordered::value; + + /** + * @brief Evaluates to true_t if the passed type is a nullable type, false_t otherwise. + */ + template + struct is_pointer; + + /** + * @brief Is true if the passed type is a pointer type, false otherwise. + */ + template + constexpr decltype(auto) is_pointer_v = is_pointer::value; + + /** + * @brief Evaluates to true_t if the passed type is a pointer type, false_t otherwise. + */ + template + struct is_nullable; + + /** + * @brief Is true if the passed type is a nullable type, false otherwise. + */ + template + constexpr decltype(auto) is_nullable_v = is_nullable::value; + } #include "type_helper.inl" diff --git a/include/cpphibernate/misc/type_helper.inl b/include/cpphibernate/misc/type_helper.inl index 734ee24..9ba5c22 100644 --- a/include/cpphibernate/misc/type_helper.inl +++ b/include/cpphibernate/misc/type_helper.inl @@ -50,4 +50,79 @@ namespace cpphibernate : public __impl::real_dataset_impl { }; + /* get_dataset_id */ + + namespace __impl + { + struct counter_type_id + { }; + } + + template + constexpr decltype(auto) get_type_id(T_type&&) + { return cppcore::get_unique_id<__impl::counter_type_id, mp::decay_t>(); } + + /* is_container */ + + template + struct is_container + : public mp::false_t + { }; + + template + struct is_container> + : public mp::true_t + { }; + + template + struct is_container> + : public mp::true_t + { }; + + /* is_ordered */ + + template + struct is_ordered + : public mp::false_t + { }; + + template + struct is_ordered> + : public mp::true_t + { }; + + template + struct is_ordered> + : public mp::true_t + { }; + + /* is_pointer */ + + template + struct is_pointer + : public mp::false_t + { }; + + template + struct is_pointer> + : public mp::true_t + { }; + + template + struct is_pointer> + : public mp::true_t + { }; + + /* is_nullable */ + + template + struct is_nullable + : public is_pointer + { }; + + template + struct is_nullable> + : public mp::true_t + { }; + } diff --git a/include/cpphibernate/schema/attribute.h b/include/cpphibernate/schema/attribute.h index bdcd27e..18b83d2 100644 --- a/include/cpphibernate/schema/attribute.h +++ b/include/cpphibernate/schema/attribute.h @@ -26,6 +26,22 @@ namespace schema { { using inner_type = T_inner; using this_type = attribute_t; + +/* + template + constexpr decltype(auto) operator==(T_other&&) const + { + return ::boost::hana::type> { } == + ::boost::hana::type> { }; + } + + template + constexpr decltype(auto) operator!=(T_other&&) const + { + return ::boost::hana::type> { } != + ::boost::hana::type> { }; + } +*/ }; struct hex_t { static constexpr decltype(auto) name = "hex"; }; diff --git a/include/cpphibernate/schema/field.h b/include/cpphibernate/schema/field.h index 950e99d..b3b85e5 100644 --- a/include/cpphibernate/schema/field.h +++ b/include/cpphibernate/schema/field.h @@ -1,6 +1,7 @@ #pragma once #include +#include namespace cpphibernate { namespace schema { @@ -8,6 +9,85 @@ namespace schema { namespace __impl { + /** + * @brief Tag class to mark field types. + */ + struct tag_field + { }; + + /** + * @brief Represents a data field in the schema. + * + * @tparam T_name Type of the name of the field. + * @tparam T_getter Type of the getter of the field. + * @tparam T_setter Type of the setter of the field. + * @tparam T_attributes Type of the attributes of the field. + */ + template + struct field_t + : public tag_field + , public tag_equality_comparable + { + using name_type = T_name; + using getter_type = T_getter; + using setter_type = T_setter; + using dataset_type = typename mp::decay_t::object_type; + using real_dataset_type = real_dataset_t; + using value_type = typename mp::decay_t::value_type; + using real_value_type = real_dataset_t; + using attributes_type = T_attributes; + using this_type = field_t; + + name_type name; //!< Name of the field. + getter_type getter; //!< Getter of the field, to get values from the dataset. + setter_type setter; //!< Setter of the field, to set values of the dataset. + attributes_type attributes; //!< List of attributes for this field. + + hana::type wrapped_value_type; //!< Type of the stoed value. + hana::type wrapped_dataset_type; //!< Type of the real stored value (containers are removed). + hana::type wrapped_real_value_type; //!< Type of the dataset this fields uses. + hana::type wrapped_real_dataset_type; //!< Type of the read dataset (contaiers are removed). + + /** + * @brief Constrcutor. + * + * @param[in] p_name Name of the field. + * @param[in] p_getter Getter to receive the represented value from the dataset. + * @param[in] p_setter Setter to set the represented value at the dataset. + * @param[in] p_attributes List of attributes of the field. + */ + constexpr field_t( + T_name&& p_name, + T_getter&& p_getter, + T_setter&& p_setter, + T_attributes&& p_attributes); + + /** + * @brief Move constructor. + */ + constexpr field_t(field_t&&) = default; + + /** + * @brief Copy constructor. + */ + constexpr field_t(const field_t&) = delete; + + /** + * @brief Move assignment constructor. + */ + constexpr field_t& operator = (field_t&&) = default; + + /** + * @brief Copy assignment constructor. + */ + constexpr field_t& operator = (const field_t&) = delete; + + /** + * @brief Print the field to the passed stream. + */ + inline void print(std::ostream& os) const; + }; + /** * @brief Helper type to build field objects. */ diff --git a/include/cpphibernate/schema/field.inl b/include/cpphibernate/schema/field.inl index 57f072a..32c76bc 100644 --- a/include/cpphibernate/schema/field.inl +++ b/include/cpphibernate/schema/field.inl @@ -3,9 +3,8 @@ #include #include -#include - #include "field.h" +#include "attributes.h" namespace cpphibernate { namespace schema { @@ -13,30 +12,11 @@ namespace schema { namespace __impl { - /* tag_field */ - - struct tag_field - { }; - /* field_t */ template - struct field_t - : public tag_field - , public tag_equality_comparable - { - using name_type = T_name; - using getter_type = T_getter; - using setter_type = T_setter; - using attributes_type = T_attributes; - using this_type = field_t; - - name_type name; - getter_type getter; - setter_type setter; - attributes_type attributes; - - constexpr field_t( + constexpr field_t + ::field_t( T_name&& p_name, T_getter&& p_getter, T_setter&& p_setter, @@ -47,38 +27,30 @@ namespace schema { , attributes (std::forward(p_attributes)) { } - constexpr field_t(field_t&&) = default; - constexpr field_t(const field_t&) = delete; - - constexpr field_t& operator = (field_t&&) = default; - constexpr field_t& operator = (const field_t&) = delete; - - inline void print(std::ostream& os) const - { - using namespace ::cppcore; - - using value_type = typename mp::decay_t::value_type; - using dataset_type = real_dataset_t; - - size_t index = 0; - os << indent << '{' - << incindent - << indent << "\"name\": \"" << name << "\"," - << indent << "\"value_type\": \"" << type_helper::name() << "\"" - << indent << "\"dataset_type\": \"" << type_helper::name() << "\"" - << indent << "\"attributes\": " - << indent << '[' - << incindent; - hana::for_each(attributes, [&](auto& attrib){ - if (index++ > 0) os << ","; - os << indent << '"' << attrib.name << '"'; - }); - os << decindent - << indent << ']' - << decindent - << indent << '}'; - } - }; + template + void field_t + ::print(std::ostream& os) const + { + using namespace ::cppcore; + + size_t index = 0; + os << indent << '{' + << incindent + << indent << "\"name\": \"" << name << "\"," + << indent << "\"value_type\": \"" << type_helper::name() << "\"" + << indent << "\"dataset_type\": \"" << type_helper::name() << "\"" + << indent << "\"attributes\": " + << indent << '[' + << incindent; + hana::for_each(attributes, [&](auto& attrib){ + if (index++ > 0) os << ","; + os << indent << '"' << attrib.name << '"'; + }); + os << decindent + << indent << ']' + << decindent + << indent << '}'; + } /* field_builder */ @@ -95,10 +67,9 @@ namespace schema { mp::list, mp::enable_if_t< true - // && mp::is_getter_v> - // && mp::is_setter_v> - // && is_attributes_v> - >> + && mp::is_getter_v> + && mp::is_setter_v> + && is_attributes_v>>> { using name_type = T_name; using getter_type = T_getter; diff --git a/include/cpphibernate/schema/schema.h b/include/cpphibernate/schema/schema.h index e661183..6dbff82 100644 --- a/include/cpphibernate/schema/schema.h +++ b/include/cpphibernate/schema/schema.h @@ -8,12 +8,83 @@ namespace schema { namespace __impl { + /** + * @brief Tag class to mark schema objects. + */ + struct tag_schema + { }; + + /** + * @brief Schema type with all tables and fields for a database layout. + * + * @tparam T_name Name of the schema. + * @tparam T_tables List of all tables that belong to this schema. + */ + template + struct schema_t + : public tag_schema + , public tag_equality_comparable + { + using name_type = T_name; + using tables_type = T_tables; + + name_type name; //!< Name of the schema. + tables_type tables; //!< List of all tables that belongs to the schema. + + /** + * @brief Constructor. + * + * @param[in] p_name Name of the schema. + * @param[in] p_tables List of all tables that belongs to the schema. + */ + constexpr schema_t( + name_type&& p_name, + tables_type&& p_tables); + + /** + * @brief Move constructor. + */ + constexpr schema_t(schema_t&&) = default; + + /** + * @brief Copy constructor. + */ + constexpr schema_t(const schema_t&) = delete; + + /** + * @brief Move assignment constructor. + */ + constexpr schema_t& operator = (schema_t&&) = default; + + /** + * @brief Copy assignment constructor. + */ + constexpr schema_t& operator = (const schema_t&) = delete; + + /** + * @brief Print the whole schema to the passed stream. + */ + inline void print(std::ostream& os) const; + }; + /** * @brief Helper type to build schema objects. */ template struct schema_builder; + /** + * @brief Helper type to get the base type of the passed dataset type. + */ + template + struct get_base_type_builder; + + /** + * @brief Helper type to get the derived types of the passed dataset type. + */ + template + struct get_derived_types_builder; + } /** @@ -33,6 +104,16 @@ namespace schema { */ constexpr decltype(auto) make_schema = mp::generic_predicate<__impl::schema_builder> { }; + /** + * @brief Predicate to get the base type of the passed dataset type. + */ + constexpr decltype(auto) get_base_type = mp::generic_predicate<__impl::get_base_type_builder> { }; + + /** + * @brief Predicate to get the derived types of the passed dataset type. + */ + constexpr decltype(auto) get_derived_types = mp::generic_predicate<__impl::get_derived_types_builder> { }; + } } #include "schema.inl" diff --git a/include/cpphibernate/schema/schema.inl b/include/cpphibernate/schema/schema.inl index 4293a61..26113d7 100644 --- a/include/cpphibernate/schema/schema.inl +++ b/include/cpphibernate/schema/schema.inl @@ -1,5 +1,8 @@ #pragma once +#include + +#include "tables.h" #include "schema.h" namespace cpphibernate { @@ -8,57 +11,39 @@ namespace schema { namespace __impl { - /* tag_schema */ - - struct tag_schema - { }; - /* schema_t */ template - struct schema_t - : public tag_schema - , public tag_equality_comparable - { - using name_type = T_name; - using tables_type = T_tables; - - name_type name; - tables_type tables; - - constexpr schema_t( + constexpr schema_t + ::schema_t( name_type&& p_name, tables_type&& p_tables) : name (std::forward (p_name)) , tables(std::forward(p_tables)) { } - constexpr schema_t(schema_t&&) = default; - constexpr schema_t(const schema_t&) = delete; - - constexpr schema_t& operator = (schema_t&&) = default; - constexpr schema_t& operator = (const schema_t&) = delete; - - inline void print(std::ostream& os) const - { - using namespace ::cppcore; - size_t index = 0; - os << indent << '{' - << incindent - << indent << "\"name\": \"" << name << "\"," - << indent << "\"tables\": " - << indent << '[' - << incindent; - hana::for_each(tables, [&](auto& table){ - if (index++ > 0) os << ","; - table.print(os); - }); - os << decindent - << indent << ']' - << decindent - << indent << '}'; - } - }; + template + void schema_t + ::print(std::ostream& os) const + { + using namespace ::cppcore; + + size_t index = 0; + os << indent << '{' + << incindent + << indent << "\"name\": \"" << name << "\"," + << indent << "\"tables\": " + << indent << '[' + << incindent; + hana::for_each(tables, [&](auto& table){ + if (index++ > 0) os << ","; + table.print(os); + }); + os << decindent + << indent << ']' + << decindent + << indent << '}'; + } /* schema_builder */ @@ -90,6 +75,115 @@ namespace schema { } }; + /* get_base_type_builder */ + + template + struct get_base_type_builder + { + template + static constexpr decltype(auto) apply(T_args&&...) + { static_assert(sizeof...(T_args) == -1, "Invalid parameters for get_base_type(...)!"); } + }; + + template + struct get_base_type_builder< + mp::list, + mp::enable_if_t>>> + { + + /* is_base_of */ + + static constexpr decltype(auto) is_base_of = hana::integral(hana::metafunction); + + /* do_fold */ + + struct do_fold_impl + { + template + constexpr decltype(auto) operator()(T_type_1&& type_1, T_type_2&& type_2) const + { + auto check = hana::or_(is_base_of(type_1, type_2), is_base_of(type_2, type_1)); + static_assert(decltype(check)::value, "A dataset must not have more than one base class!"); + return hana::if_(is_base_of(type_1, type_2), type_2, type_1); + } + }; + + static constexpr decltype(auto) do_fold = do_fold_impl { }; + + /* get_base_types */ + + template + static constexpr decltype(auto) get_base_types(T_datasets datasets, T_dataset dataset) + { + return hana::filter( + datasets, + [&](auto type){ + return hana::and_( + is_base_of(type, dataset), + hana::not_equal(type, dataset)); + }); + } + + /* apply */ + + static constexpr decltype(auto) apply( + const T_schema& schema, + const T_wrapped_dataset& wrapped_dataset) + { + decltype(auto) wrapped_datasets = hana::transform( + schema.tables, + schema::get_wrapped_dataset); + decltype(auto) base_types = get_base_types(wrapped_datasets, wrapped_dataset); + return hana::eval_if( + hana::size(base_types) <= hana::size_c<0>, + [&](auto _){ return hana::type_c; }, + [&](auto _){ return hana::fold(_(base_types), do_fold); }); + } + }; + + /* get_derived_types_builder */ + + template + struct get_derived_types_builder + { + template + static constexpr decltype(auto) apply(T_args&&...) + { static_assert(sizeof...(T_args) == -1, "Invalid parameters for get_derived_types(...)!"); } + }; + + template + struct get_derived_types_builder< + mp::list, + mp::enable_if_t< + schema::is_schema_v> + && mp::is_same_v> + >> + { + struct has_base_impl + { + template + constexpr decltype(auto) operator()(T_type&&) const + { + return decltype(hana::equal( + get_base_type( + std::declval(), + std::declval()), + std::declval())) { }; + } + }; + + static constexpr decltype(auto) has_base = has_base_impl { }; + + static constexpr decltype(auto) apply(T_schema&& schema, T_dataset&& dataset) + { + constexpr decltype(auto) dataset_types = + decltype(hana::transform(schema.tables, schema::get_wrapped_dataset)) { }; + constexpr decltype(auto) derived_types = + decltype(hana::filter(dataset_types, has_base)) { }; + return derived_types; + } + }; + } /* is_schema */ diff --git a/include/cpphibernate/schema/table.h b/include/cpphibernate/schema/table.h index 325a1ba..9a53bf9 100644 --- a/include/cpphibernate/schema/table.h +++ b/include/cpphibernate/schema/table.h @@ -8,12 +8,93 @@ namespace schema { namespace __impl { + /** + * @brief Tag class to mark table objects. + */ + struct tag_table + { }; + + /** + * @brief Represents a data field in the schema. + * + * @tparam T_name Name of the table. + * @tparam T_wrapped_dataset Dataset type the table represents. + * @tparam T_table_id Unique ID assigned by the user. + * @tparam T_fields List of field that belongs to the table. + */ + template< + typename T_name, + typename T_wrapped_dataset, + typename T_table_id, + typename T_fields> + struct table_t + : public tag_table + , public tag_equality_comparable + { + using name_type = T_name; + using wrapped_dataset_type = mp::decay_t; + using dataset_type = decay_unwrap_t; + using table_id_type = T_table_id; + using fields_type = T_fields; + using this_type = table_t; + + name_type name; //!< Name of the table. + wrapped_dataset_type wrapped_dataset; //!< Dataset type this table represents. + table_id_type table_id; //!< Unique ID of the table, assigned by the user. + fields_type fields; //!< List of fields that belongs to the table. + + /** + * @brief Constructor. + * + * @param[in] p_name Name of the table. + * @param[in] p_wrapped_dataset Dataset type this table represents. + * @param[in] p_table_id Unique ID of the table assigned by the user. + * @param[in] p_fields List of fields that belongs to the table. + */ + constexpr table_t( + name_type p_name, + wrapped_dataset_type p_wrapped_dataset, + table_id_type p_table_id, + fields_type p_fields); + + /** + * @brief Move constructor. + */ + constexpr table_t(table_t&&) = default; + + /** + * @brief Copy constructor. + */ + constexpr table_t(const table_t&) = delete; + + /** + * @brief Move assignment constructor. + */ + constexpr table_t& operator = (table_t&&) = default; + + /** + * @brief Copy assignment constructor. + */ + constexpr table_t& operator = (const table_t&) = delete; + + /** + * @brief Print the table to the passed stream. + */ + inline void print(std::ostream& os) const; + }; + /** * @brief Helper type to build table objects. */ template struct table_builder; + /** + * @brief Helper type to get the wrapped dataset of the passed table. + */ + template + struct table_get_wrapped_dataset; + } /** @@ -33,6 +114,11 @@ namespace schema { */ constexpr decltype(auto) make_table = mp::generic_predicate<__impl::table_builder> { }; + /** + * @brief Predicate to get the wrapped dataset of the passed table. + */ + constexpr decltype(auto) get_wrapped_dataset = mp::generic_predicate<__impl::table_get_wrapped_dataset> { }; + } } #include "table.inl" diff --git a/include/cpphibernate/schema/table.inl b/include/cpphibernate/schema/table.inl index 0a8b703..bf0ef7b 100644 --- a/include/cpphibernate/schema/table.inl +++ b/include/cpphibernate/schema/table.inl @@ -1,5 +1,8 @@ #pragma once +#include + +#include "fields.h" #include "table.h" namespace cpphibernate { @@ -8,35 +11,11 @@ namespace schema { namespace __impl { - /* tag_table */ - - struct tag_table - { }; - /* table_t */ - template< - typename T_name, - typename T_wrapped_dataset, - typename T_table_id, - typename T_fields> - struct table_t - : public tag_table - , public tag_equality_comparable - { - using name_type = T_name; - using wrapped_dataset_type = mp::decay_t; - using dataset_type = decay_unwrap_t; - using table_id_type = T_table_id; - using fields_type = T_fields; - using this_type = table_t; - - name_type name; - wrapped_dataset_type wrapped_dataset; - table_id_type table_id; - fields_type fields; - - constexpr table_t( + template + constexpr table_t + ::table_t( name_type p_name, wrapped_dataset_type p_wrapped_dataset, table_id_type p_table_id, @@ -47,34 +26,29 @@ namespace schema { , fields (std::forward (p_fields)) { } - constexpr table_t(table_t&&) = default; - constexpr table_t(const table_t&) = delete; - - constexpr table_t& operator = (table_t&&) = default; - constexpr table_t& operator = (const table_t&) = delete; - - inline void print(std::ostream& os) const - { - using namespace ::cppcore; - size_t index = 0; - os << indent << '{' - << incindent - << indent << "\"name\": \"" << name << "\"," - << indent << "\"wrapped_dataset\": \"" << type_helper::name() << "\"" - << indent << "\"table_id\": \"" << hana::value(table_id) << "\"" - << indent << "\"fields\": " - << indent << '[' - << incindent; - hana::for_each(fields, [&](auto& table){ - if (index++ > 0) os << ","; - table.print(os); - }); - os << decindent - << indent << ']' - << decindent - << indent << '}'; - } - }; + template + void table_t + ::print(std::ostream& os) const + { + using namespace ::cppcore; + size_t index = 0; + os << indent << '{' + << incindent + << indent << "\"name\": \"" << name << "\"," + << indent << "\"wrapped_dataset\": \"" << type_helper::name() << "\"" + << indent << "\"table_id\": \"" << hana::value(table_id) << "\"" + << indent << "\"fields\": " + << indent << '[' + << incindent; + hana::for_each(fields, [&](auto& table){ + if (index++ > 0) os << ","; + table.print(os); + }); + os << decindent + << indent << ']' + << decindent + << indent << '}'; + } /* table_builder */ @@ -117,6 +91,25 @@ namespace schema { } }; + /* table_get_wrapped_dataset */ + + template + struct table_get_wrapped_dataset + { + template + static constexpr decltype(auto) apply(T_args&&...) + { static_assert(sizeof...(T_args) == -1, "Invalid parameters for get_wrapped_dataset(...)!"); } + }; + + template + struct table_get_wrapped_dataset< + mp::list, + mp::enable_if_t>>> + { + static constexpr decltype(auto) apply(T_table&& table) + { return std::forward(table).wrapped_dataset; } + }; + } /* is_table */ diff --git a/include/cpphibernate/types.h b/include/cpphibernate/types.h index 6841219..5e29d80 100644 --- a/include/cpphibernate/types.h +++ b/include/cpphibernate/types.h @@ -5,10 +5,20 @@ #include #include +#include namespace cpphibernate { + /** + * @brief Hibernate exception class. + */ + struct exception + : public cppcore::exception + { + using cppcore::exception::exception; + }; + /** * @brief Represents a string with an fixed length. */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 741f40d..4e69ee0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,6 +7,10 @@ Include ( strip_symbols OPTIONAL RESULT_VARIABLE HAS_STRIP_S Find_Package ( Hana REQUIRED ) Find_Package ( cppmp REQUIRED ) Find_Package ( cppcore REQUIRED ) +Find_Package ( cppmariadb REQUIRED ) +If ( cppmariadb_FOUND ) + Set ( CPPHIBERNATE_HAS_CPPMARIADB true ) +EndIf ( ) # Object Library ################################################################################## @@ -29,6 +33,11 @@ Target_Link_Libraries ( cpphibernate-objects hana cppmp::cppmp cppcore::cppcore ) +If ( CPPHIBERNATE_HAS_CPPMARIADB ) + Target_Link_Libraries ( cpphibernate-objects + PUBLIC + cppmariadb::cppmariadb-shared ) +EndIf ( ) # Static Library ################################################################################## @@ -41,6 +50,11 @@ Target_Include_Directories ( cpphibernate-static PUBLIC $ $ ) +If ( CPPHIBERNATE_HAS_CPPMARIADB ) + Target_Link_Libraries ( cpphibernate-static + PUBLIC + cppmariadb::cppmariadb-static ) +EndIf ( ) # Shared Library ################################################################################## @@ -54,6 +68,11 @@ Target_Include_Directories ( cpphibernate-shared PUBLIC $ $ ) +If ( CPPHIBERNATE_HAS_CPPMARIADB ) + Target_Link_Libraries ( cpphibernate-shared + PUBLIC + cppmariadb::cppmariadb-shared ) +EndIf ( ) # Optimization #################################################################################### diff --git a/src/cpphibernate/driver/mariadb/schema/field.xcpp b/src/cpphibernate/driver/mariadb/classes/field.xcpp similarity index 100% rename from src/cpphibernate/driver/mariadb/schema/field.xcpp rename to src/cpphibernate/driver/mariadb/classes/field.xcpp diff --git a/src/cpphibernate/driver/mariadb/classes/fields/field.cpp b/src/cpphibernate/driver/mariadb/classes/fields/field.cpp new file mode 100644 index 0000000..663621b --- /dev/null +++ b/src/cpphibernate/driver/mariadb/classes/fields/field.cpp @@ -0,0 +1,135 @@ +#include +#include +#include + +#include + +using namespace ::cpphibernate; +using namespace ::cpphibernate::mariadb; + +/* field_t */ + +field_t::~field_t() + { } + +std::ostream& field_t::print(std::ostream& os) const +{ + using namespace ::cppcore; + + os << indent << '{' + << incindent + + << indent << "\"id\": " << id << "," + // TODO + // << indent << "\"dataset_id\": " << dataset_id << "," + // << indent << "\"real_dataset_id\": " << real_dataset_id << "," + << indent << "\"value_id\": " << value_id << "," + << indent << "\"real_value_id\": " << real_value_id << "," + << indent << "\"value_is_nullable\": " << (value_is_nullable ? "true" : "false") << "," + << indent << "\"value_is_pointer\": " << (value_is_pointer ? "true" : "false") << "," + << indent << "\"value_is_container\": " << (value_is_container ? "true" : "false") << "," + << indent << "\"value_is_auto_incremented\": " << (value_is_auto_incremented ? "true" : "false") << "," + << indent << "\"table\": " << '"' << table.name << "\"," + << indent << "\"referenced_table\": " << (referenced_table + ? std::string("\"") + referenced_table->name + "\"" + : "null") << "," + + // TODO + // << indent << "\"schema_name\": \"" << schema_name << "\"," + // << indent << "\"table_name\": \"" << table_name << "\"," + // << indent << "\"field_name\": \"" << field_name << "\"," + << indent << "\"name\": \"" << name << "\"," + << indent << "\"type\": \"" << type << "\"," + << indent << "\"create_arguments\": \"" << create_arguments << "\"," + + << indent << "\"convert_to_open\": \"" << convert_to_open << "\"," + << indent << "\"convert_to_close\": \"" << convert_to_close << "\"," + << indent << "\"convert_from_open\": \"" << convert_from_open << "\"," + << indent << "\"convert_from_close\": \"" << convert_from_close << "\"," + + << indent << "\"attributes\": " << make_print_container(attributes, false) + + << decindent + << indent << '}'; + + return os; +} + +void field_t::init() +{ + /* conver_to_open */ + { + std::ostringstream ss; + for (auto& attrib : attributes) + { + switch(attrib) + { + case attribute_t::hex: + ss << "HEX("; + break; + case attribute_t::compress: + ss << "COMPRESS("; + break; + default: + break; + } + } + convert_to_open = ss.str(); + } + + /* convert_to_close */ + { + std::ostringstream ss; + for (auto& attrib : attributes) + { + switch(attrib) + { + case attribute_t::hex: + case attribute_t::compress: + ss << ')'; + break; + default: + break; + } + } + convert_to_close = ss.str(); + } + + /* convert_from_open */ + { + std::ostringstream ss; + for (auto& attrib : attributes) + { + switch(attrib) + { + case attribute_t::hex: + ss << "UNHEX("; + break; + case attribute_t::compress: + ss << "UNCOMPRESS("; + break; + default: + break; + } + } + convert_from_open = ss.str(); + } + + /* convert_from_close */ + { + std::ostringstream ss; + for (auto& attrib : attributes) + { + switch(attrib) + { + case attribute_t::hex: + case attribute_t::compress: + ss << ')'; + break; + default: + break; + } + } + convert_from_close = ss.str(); + } +} diff --git a/src/cpphibernate/driver/mariadb/schema/schema.xcpp b/src/cpphibernate/driver/mariadb/classes/schema.xcpp similarity index 100% rename from src/cpphibernate/driver/mariadb/schema/schema.xcpp rename to src/cpphibernate/driver/mariadb/classes/schema.xcpp diff --git a/src/cpphibernate/driver/mariadb/classes/schema/schema.cpp b/src/cpphibernate/driver/mariadb/classes/schema/schema.cpp new file mode 100644 index 0000000..f89729e --- /dev/null +++ b/src/cpphibernate/driver/mariadb/classes/schema/schema.cpp @@ -0,0 +1,127 @@ +#include +#include + +#include + +using namespace ::cpphibernate; +using namespace ::cpphibernate::mariadb; + +/* schema_t */ + +std::ostream& schema_t::print(std::ostream& os) const +{ + using namespace ::cppcore; + + os << indent << '{' + << incindent + << indent << "\"schema_name\": \"" << name << "\"," + << indent << "\"tables\": " << make_print_container(tables, true, [](auto& s, auto& table) { + table->print(s); + }) + << decindent + << indent << '}'; + + return os; +} + +void schema_t::init() +{ + /* build lookup */ + for (auto& t : tables) + { + assert(static_cast(t)); + _lookup.emplace(t->dataset_id, t.get()); + } + + /* update table referencs */ + for (auto& t : tables) + { + assert(static_cast(t)); + auto& table = const_cast(*t); + + /* get base table */ + auto it = _lookup.find(table.base_dataset_id); + table.base_table = (it != _lookup.end() + ? it->second + : nullptr); + + /* dereived tables */ + for (auto& id : table.derived_dataset_ids) + { + it = _lookup.find(id); + if (it == _lookup.end()) + throw exception(std::string("unable to find derived table for dataset id ") + std::to_string(id)); + table.derived_tables.emplace_back(it->second); + } + + /* update fields */ + for (auto& f : table.fields) + { + assert(static_cast(f)); + auto& field = const_cast(*f); + + /* referenced_table */ + it = _lookup.find(field.real_value_id); + auto * referenced_table = (it != _lookup.end() + ? const_cast(it->second) + : nullptr); + field.referenced_table = referenced_table; + + /* primary key field */ + if (field.attributes.count(attribute_t::primary_key)) + { + if (static_cast(table.primary_key_field)) + throw exception(std::string("Table '") + table.name + "' can not have more then one primary key!"); + table.primary_key_field = &field; + } + + /* foreign table field */ + else if (static_cast(referenced_table)) + { + table.foreign_table_fields.emplace_back(&field); + if (field.value_is_container) + { + referenced_table->is_used_in_container = true; + } + } + + /* normal data field */ + else + { + table.data_fields.emplace_back(&field); + } + } + if (!static_cast(table.primary_key_field)) + throw exception(std::string("Table '") + table.name + "' does not have a primary key!"); + } + + /* update foreign fields (one, many, key) */ + for (auto& t : tables) + { + assert(static_cast(t)); + auto& table = const_cast(*t); + + for (auto& f : table.foreign_table_fields) + { + assert(static_cast(f)); + assert(static_cast(f->referenced_table)); + + auto& field = *f; + auto& referenced_table = const_cast(*field.referenced_table); + + if (field.value_is_container) + { + table.foreign_table_many_fields.emplace_back(&field); + referenced_table.foreign_key_fields.emplace_back(&field); + } + else + { + table.foreign_table_one_fields.emplace_back(&field); + if (referenced_table.is_used_in_container) + { + referenced_table.foreign_key_fields.push_back(&field); + } + } + } + } +} diff --git a/src/cpphibernate/driver/mariadb/schema/table.xcpp b/src/cpphibernate/driver/mariadb/classes/table.xcpp similarity index 100% rename from src/cpphibernate/driver/mariadb/schema/table.xcpp rename to src/cpphibernate/driver/mariadb/classes/table.xcpp diff --git a/src/cpphibernate/driver/mariadb/classes/tables/table.cpp b/src/cpphibernate/driver/mariadb/classes/tables/table.cpp new file mode 100644 index 0000000..80d7e03 --- /dev/null +++ b/src/cpphibernate/driver/mariadb/classes/tables/table.cpp @@ -0,0 +1,66 @@ +#include +#include + +#include + +using namespace ::cpphibernate; +using namespace ::cpphibernate::mariadb; + +/* table_t */ + +table_t::~table_t() + { } + +std::ostream& table_t::print(std::ostream& os) const +{ + using namespace ::cppcore; + + os << indent << '{' + << incindent + << indent << "\"id\": " << id << "," + // TODO + << indent << "\"dataset_id\": " << dataset_id << "," + << indent << "\"base_dataset_id\": " << base_dataset_id << "," + << indent << "\"derived_dataset_ids\": " << make_print_container(derived_dataset_ids, false) << "," + // TODO + // << indent << "\"schema_name\": \"" << schema_name << "\"," + // << indent << "\"table_name\": \"" << table_name << "\"," + << indent << "\"name\": \"" << name << "\"," + << indent << "\"base_table\": " << (base_table ? std::string("\"") + base_table->name + "\"" : "null") << "," + << indent << "\"derived_tables\":" << make_print_container(derived_tables, true, [](auto& s, auto& ptr){ + s << indent << '"' << ptr->name << '"'; + }) << "," + << indent << "\"primary_key_field\": " << (primary_key_field ? std::string("\"") + primary_key_field->name + "\"" : "null") << "," + << indent << "\"foreign_key_fields\": " << make_print_container(foreign_key_fields, true, [](auto& s, auto& ptr){ + s << indent << '"' << ptr->name << '.' << ptr->name << '"'; + }) << "," + << indent << "\"foreign_table_fields\": " << make_print_container(foreign_table_fields, true, [](auto& s, auto& ptr){ + s << indent << '"' << ptr->name << '"'; + }) << "," + << indent << "\"foreign_table_one_fields\": " << make_print_container(foreign_table_one_fields, true, [](auto& s, auto& ptr){ + s << indent << '"' << ptr->name << '"'; + }) << "," + << indent << "\"foreign_table_many_fields\": " << make_print_container(foreign_table_many_fields, true, [](auto& s, auto& ptr){ + s << indent << '"' << ptr->name << '"'; + }) << "," + << indent << "\"data_fields\": " << make_print_container(data_fields, true, [](auto& s, auto& ptr){ + s << indent << '"' << ptr->name << '"'; + }) << "," + << indent << "\"fields\":" << make_print_container(fields, true, [](auto& s, auto& field) { + field->print(s); + }) + << decindent + << indent << '}'; + + return os; +} + +void table_t::init() +{ + /* build field lookup */ + for (auto& f : fields) + { + assert(static_cast(f)); + _lookup.emplace(f->id, f.get()); + } +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0074a00..ef708be 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -23,7 +23,7 @@ Add_Executable ( cpphibernate-test Target_Link_Libraries ( cpphibernate-test PUBLIC cpphibernate-objects - GTest::Main ) + GMock::Main ) # pedantic If ( HAS_PEDANTIC ) diff --git a/test/cpphibernate/cpphibernate_init.xcpp b/test/cpphibernate/cpphibernate_init.cpp similarity index 98% rename from test/cpphibernate/cpphibernate_init.xcpp rename to test/cpphibernate/cpphibernate_init.cpp index 72c88a0..ec0722e 100644 --- a/test/cpphibernate/cpphibernate_init.xcpp +++ b/test/cpphibernate/cpphibernate_init.cpp @@ -7,8 +7,11 @@ using namespace ::testing; using namespace ::cpphibernate; +namespace hana = ::boost::hana; + TEST(CppHibernateTests, init) { +/* StrictMock mock; expect_query(mock, "START TRANSACTION"); @@ -293,8 +296,11 @@ TEST(CppHibernateTests, init) mock, mysql_close( reinterpret_cast(0x1111))); - +*/ ::cppmariadb::connection connection(reinterpret_cast(0x1111)); - auto context = make_context(test_schema, connection); - context.init(true); + auto context = make_context(test_schema); + (void)context; + context.print(std::cout) << std::endl << std::endl; + + // context.init(true); } diff --git a/test/cpphibernate/cpphibernate_tests.cpp b/test/cpphibernate/cpphibernate_tests.cpp deleted file mode 100644 index a6c2e50..0000000 --- a/test/cpphibernate/cpphibernate_tests.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include - -#include - -#include "test_schema.h" - -using namespace ::testing; -using namespace ::cpphibernate; -using namespace ::cpphibernate::schema; - -using namespace hana::literals; - -constexpr decltype(auto) tmp_table = test_schema.tables[0_c]; -constexpr decltype(auto) tmp_field = tmp_table.fields[0_c]; -constexpr decltype(auto) mod = make_modifiers( - limit(5_c), - offset(3_c), - order_by( - ascending(tmp_field), - descending(tmp_field)), - where( - or_( - negation(equal(tmp_field, 1)), - negation(equal(tmp_field, 1))))); - -TEST(cpphibernate_tests, dummy) -{ - (void)mod; -} diff --git a/test/cpphibernate/mariadb_mock.xcpp b/test/cpphibernate/mariadb_mock.cpp similarity index 100% rename from test/cpphibernate/mariadb_mock.xcpp rename to test/cpphibernate/mariadb_mock.cpp diff --git a/test/cpphibernate/test_helper.h b/test/cpphibernate/test_helper.h index 18b2360..2e38c5e 100644 --- a/test/cpphibernate/test_helper.h +++ b/test/cpphibernate/test_helper.h @@ -180,4 +180,4 @@ inline void expect_query(T_mock& mock, const std::string& query, T_result&& resu template inline void expect_query(T_mock& mock, const std::string& query) - { expect_query(mock, query, result_stored()); } \ No newline at end of file + { expect_query(mock, query, result_stored()); }