| @@ -1,6 +1,7 @@ | |||||
| #pragma once | #pragma once | ||||
| #include <cpphibernate/config.h> | #include <cpphibernate/config.h> | ||||
| #include <cpphibernate/context.h> | |||||
| #include <cpphibernate/misc.h> | #include <cpphibernate/misc.h> | ||||
| #include <cpphibernate/modifier.h> | #include <cpphibernate/modifier.h> | ||||
| #include <cpphibernate/schema.h> | #include <cpphibernate/schema.h> | ||||
| @@ -40,14 +40,20 @@ | |||||
| #define beg_namespace_cpphibernate namespace cpphibernate | #define beg_namespace_cpphibernate namespace cpphibernate | ||||
| #define end_namespace_cpphibernate | #define end_namespace_cpphibernate | ||||
| #define beg_namespace_cpphibernate_schema cpphibernate_define_namespace_beg(beg_namespace_cpphibernate, schema) | |||||
| #define end_namespace_cpphibernate_schema cpphibernate_define_namespace_end(end_namespace_cpphibernate) | |||||
| #define beg_namespace_cpphibernate_schema cpphibernate_define_namespace_beg(beg_namespace_cpphibernate, schema) | |||||
| #define end_namespace_cpphibernate_schema cpphibernate_define_namespace_end(end_namespace_cpphibernate) | |||||
| #define beg_namespace_cpphibernate_misc cpphibernate_define_namespace_beg(beg_namespace_cpphibernate, misc) | |||||
| #define end_namespace_cpphibernate_misc cpphibernate_define_namespace_end(end_namespace_cpphibernate) | |||||
| #define beg_namespace_cpphibernate_misc cpphibernate_define_namespace_beg(beg_namespace_cpphibernate, misc) | |||||
| #define end_namespace_cpphibernate_misc cpphibernate_define_namespace_end(end_namespace_cpphibernate) | |||||
| #define beg_namespace_cpphibernate_modifier cpphibernate_define_namespace_beg(beg_namespace_cpphibernate, modifier) | |||||
| #define end_namespace_cpphibernate_modifier cpphibernate_define_namespace_end(end_namespace_cpphibernate) | |||||
| #define beg_namespace_cpphibernate_modifier cpphibernate_define_namespace_beg(beg_namespace_cpphibernate, modifier) | |||||
| #define end_namespace_cpphibernate_modifier cpphibernate_define_namespace_end(end_namespace_cpphibernate) | |||||
| #define beg_namespace_cpphibernate_driver cpphibernate_define_namespace_beg(beg_namespace_cpphibernate, driver) | |||||
| #define end_namespace_cpphibernate_driver cpphibernate_define_namespace_end(end_namespace_cpphibernate) | |||||
| #define beg_namespace_cpphibernate_driver_mariadb cpphibernate_define_namespace_beg(beg_namespace_cpphibernate_driver, mariadb_impl) | |||||
| #define end_namespace_cpphibernate_driver_mariadb cpphibernate_define_namespace_end(end_namespace_cpphibernate_driver) | |||||
| beg_namespace_cpphibernate | beg_namespace_cpphibernate | ||||
| { | { | ||||
| @@ -0,0 +1,122 @@ | |||||
| #pragma once | |||||
| #include <memory> | |||||
| #include <cpphibernate/misc.h> | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/schema/table.h> | |||||
| #include <cpphibernate/schema/tables.h> | |||||
| #include <cpphibernate/modifier/where.h> | |||||
| #include <cpphibernate/modifier/modifier.h> | |||||
| beg_namespace_cpphibernate | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| template<typename T_driver, typename T_schema> | |||||
| struct context_t | |||||
| : 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: | |||||
| template<typename... T_args> | |||||
| constexpr context_t(const schema_type& p_schema, T_args&&... args) | |||||
| : base_type (p_schema, std::forward<T_args>(args)...) | |||||
| , _schema (p_schema) | |||||
| { } | |||||
| cpphibernate_copyable(context_t, delete); | |||||
| cpphibernate_moveable(context_t, default); | |||||
| /* init */ | |||||
| inline void init(bool recreate) | |||||
| { this->init_impl(recreate); } | |||||
| /* create */ | |||||
| template<typename T_dataset> | |||||
| constexpr void create(T_dataset& dataset) | |||||
| { this->create_impl(dataset); } | |||||
| /* read */ | |||||
| template<typename T_dataset, typename... T_modifiers> | |||||
| constexpr auto read(T_dataset& dataset, T_modifiers&&... modifiers) | |||||
| -> mp::enable_if< | |||||
| modifier::all_are_modifier<mp::decay_t<T_modifiers>...>> | |||||
| { | |||||
| using real_dataset_type = misc::real_dataset_t<mp::decay_t<T_dataset>>; | |||||
| schema::tables::find(_schema.tables, hana::type_c<real_dataset_type>); | |||||
| this->read_impl(dataset, hana::make_tuple(std::forward<T_modifiers>(modifiers)...)); | |||||
| } | |||||
| template<typename T_dataset> | |||||
| constexpr auto read(T_dataset& dataset) | |||||
| -> mp::enable_if_c< | |||||
| !misc::is_container<mp::decay_t<T_dataset>>::value | |||||
| && !misc::is_nullable<mp::decay_t<T_dataset>>::value> | |||||
| { | |||||
| using namespace modifier; | |||||
| using real_dataset_type = misc::real_dataset_t<mp::decay_t<T_dataset>>; | |||||
| auto& table = schema::tables::find(_schema.tables, hana::type_c<real_dataset_type>); | |||||
| auto& primary_key = schema::table::get_primary_key_field(table); | |||||
| this->read_impl(dataset, hana::make_tuple(where(equal(primary_key, primary_key.getter(dataset))))); | |||||
| } | |||||
| template<typename T_dataset> | |||||
| constexpr auto read(T_dataset& dataset) | |||||
| -> mp::enable_if_c< | |||||
| misc::is_container<mp::decay_t<T_dataset>>::value | |||||
| || misc::is_nullable<mp::decay_t<T_dataset>>::value> | |||||
| { | |||||
| using namespace modifier; | |||||
| using real_dataset_type = misc::real_dataset_t<mp::decay_t<T_dataset>>; | |||||
| schema::tables::find(_schema.tables, hana::type_c<real_dataset_type>); | |||||
| this->read_impl(dataset, hana::make_tuple()); | |||||
| } | |||||
| /* update */ | |||||
| template<typename T_dataset> | |||||
| constexpr void update(T_dataset& dataset) | |||||
| { this->update_impl(dataset); } | |||||
| /* destroy */ | |||||
| template<typename T_dataset> | |||||
| constexpr void destroy(T_dataset& dataset) | |||||
| { this->destroy_impl(dataset); } | |||||
| }; | |||||
| } | |||||
| /* make */ | |||||
| template<typename T_driver, typename T_schema, typename... T_args> | |||||
| constexpr decltype(auto) make_context(T_schema&& schema, T_args&&... args) | |||||
| { | |||||
| using context_type = __impl::context_t<T_driver, T_schema>; | |||||
| return context_type(std::forward<T_schema>(schema), std::forward<T_args>(args)...); | |||||
| } | |||||
| template<typename T_driver, typename T_schema, typename... T_args> | |||||
| constexpr decltype(auto) make_context_ptr(T_schema&& schema, T_args&&... args) | |||||
| { | |||||
| using context_type = __impl::context_t<T_driver, T_schema>; | |||||
| using pointer_type = std::unique_ptr<context_type>; | |||||
| return pointer_type(new context_type(std::forward<T_schema>(schema), std::forward<T_args>(args)...)); | |||||
| } | |||||
| } | |||||
| end_namespace_cpphibernate | |||||
| @@ -0,0 +1,12 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/driver/mariadb/mariadb.h> | |||||
| beg_namespace_cpphibernate_driver | |||||
| { | |||||
| using mariadb = mariadb_impl::mariadb_driver_t; | |||||
| } | |||||
| end_namespace_cpphibernate_driver | |||||
| @@ -0,0 +1,34 @@ | |||||
| #pragma once | |||||
| #include <cppmariadb.h> | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/driver/mariadb/schema.h> | |||||
| beg_namespace_cpphibernate_driver_mariadb | |||||
| { | |||||
| struct mariadb_driver_t | |||||
| { | |||||
| private: | |||||
| ::cppmariadb::connection& _connection; | |||||
| schema_t _schema; | |||||
| public: | |||||
| template<typename T_schema> | |||||
| mariadb_driver_t(T_schema&& p_schema, ::cppmariadb::connection& p_connection) | |||||
| : _connection (p_connection) | |||||
| , _schema (make_schema(std::forward<T_schema>(p_schema))) | |||||
| { } | |||||
| cpphibernate_copyable(mariadb_driver_t, delete); | |||||
| cpphibernate_moveable(mariadb_driver_t, default); | |||||
| inline decltype(auto) connection() | |||||
| { return _connection; } | |||||
| inline auto& schema() | |||||
| { return _schema; } | |||||
| }; | |||||
| } | |||||
| end_namespace_cpphibernate_driver_mariadb | |||||
| @@ -0,0 +1,15 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/driver/mariadb/schema/attributes.fwd.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/field.fwd.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/fields.fwd.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/schema.fwd.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/table.fwd.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/tables.fwd.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/attributes.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/field.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/fields.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/schema.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/table.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/tables.h> | |||||
| @@ -0,0 +1,34 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/config.h> | |||||
| 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<typename T, typename = void> | |||||
| struct make_attributes_impl; | |||||
| } | |||||
| constexpr decltype(auto) make_attributes = misc::make_generic_predicate<__impl::make_attributes_impl> { }; | |||||
| } | |||||
| end_namespace_cpphibernate_driver_mariadb | |||||
| @@ -0,0 +1,76 @@ | |||||
| #pragma once | |||||
| #include <set> | |||||
| #include <cpphibernate/misc.h> | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/schema/attributes.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/attributes.fwd.h> | |||||
| beg_namespace_cpphibernate_driver_mariadb | |||||
| { | |||||
| /* attributes_t */ | |||||
| struct attributes_t : | |||||
| public std::set<attribute_t> | |||||
| { | |||||
| using base_type = std::set<attribute_t>; | |||||
| using base_type::base_type; | |||||
| }; | |||||
| namespace __impl | |||||
| { | |||||
| /* attribute_converter */ | |||||
| template<typename T_attribute> | |||||
| struct attribute_converter; | |||||
| template<> | |||||
| struct attribute_converter<schema::attribute::hex_type> | |||||
| { static constexpr decltype(auto) value = attribute_t::hex; }; | |||||
| template<> | |||||
| struct attribute_converter<schema::attribute::compress_type> | |||||
| { static constexpr decltype(auto) value = attribute_t::compress; }; | |||||
| template<> | |||||
| struct attribute_converter<schema::attribute::primary_key_type> | |||||
| { static constexpr decltype(auto) value = attribute_t::primary_key; }; | |||||
| /* make_attributes_impl */ | |||||
| template<typename T, typename> | |||||
| struct make_attributes_impl | |||||
| { | |||||
| template<typename... T_args> | |||||
| static constexpr decltype(auto) apply(T_args&&... args) | |||||
| { static_assert(sizeof...(args) == 0, "Invalid parameters for mariadb::make_attributes(...)!"); } | |||||
| }; | |||||
| template<typename T_attributes> | |||||
| struct make_attributes_impl< | |||||
| mp::list<T_attributes>, | |||||
| mp::enable_if_c< | |||||
| schema::is_attributes<mp::decay_t<T_attributes>>::value>> | |||||
| { | |||||
| template<size_t... I> | |||||
| static constexpr decltype(auto) helper(T_attributes&&, const std::index_sequence<I...>&) | |||||
| { | |||||
| return attributes_t({ | |||||
| attribute_converter<mp::decay_t<decltype(std::declval<T_attributes>()[hana::size_c<I>])>>::value... | |||||
| }); | |||||
| } | |||||
| static constexpr decltype(auto) apply(const T_attributes& attributes) | |||||
| { | |||||
| using size = mp::decay_t<decltype(hana::size(attributes))>; | |||||
| return helper(attributes, std::make_index_sequence<size::value> { }); | |||||
| } | |||||
| }; | |||||
| } | |||||
| } | |||||
| end_namespace_cpphibernate_driver_mariadb | |||||
| @@ -0,0 +1,31 @@ | |||||
| #pragma once | |||||
| #include <memory> | |||||
| #include <cpphibernate/misc.h> | |||||
| #include <cpphibernate/config.h> | |||||
| beg_namespace_cpphibernate_driver_mariadb | |||||
| { | |||||
| /* field_t */ | |||||
| struct field_t; | |||||
| /* field_ptr_t */ | |||||
| using field_ptr_t = std::unique_ptr<field_t>; | |||||
| /* make_field */ | |||||
| namespace __impl | |||||
| { | |||||
| template<typename T, typename = void> | |||||
| struct make_field_impl; | |||||
| } | |||||
| constexpr decltype(auto) make_field = misc::make_generic_predicate<__impl::make_field_impl> { }; | |||||
| } | |||||
| end_namespace_cpphibernate_driver_mariadb | |||||
| @@ -0,0 +1,193 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/misc.h> | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/field.fwd.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/table.fwd.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/attributes.h> | |||||
| beg_namespace_cpphibernate_driver_mariadb | |||||
| { | |||||
| /* field_t */ | |||||
| struct field_t | |||||
| { | |||||
| size_t table_dataset_id { 0 }; | |||||
| size_t value_dataset_id { 0 }; | |||||
| bool value_is_nullable { false }; | |||||
| bool value_is_container { false }; | |||||
| std::string schema_name; | |||||
| std::string table_name; | |||||
| std::string field_name; | |||||
| attributes_t attributes; | |||||
| const table_t* table { nullptr }; | |||||
| const table_t* referenced_table { nullptr }; | |||||
| inline field_t() = default; | |||||
| inline field_t(const field_t&) = delete; | |||||
| inline field_t(field_t&& other) | |||||
| : table_dataset_id (std::move(other).table_dataset_id) | |||||
| , value_dataset_id (std::move(other).value_dataset_id) | |||||
| , value_is_nullable (std::move(other).value_is_nullable) | |||||
| , value_is_container(std::move(other).value_is_container) | |||||
| , schema_name (std::move(other).schema_name) | |||||
| , table_name (std::move(other).table_name) | |||||
| , field_name (std::move(other).field_name) | |||||
| , attributes (std::move(other).attributes) | |||||
| , table (nullptr) | |||||
| , referenced_table (nullptr) | |||||
| { } | |||||
| virtual ~field_t() = default; | |||||
| }; | |||||
| /* simple_field_t */ | |||||
| template<typename T_schema, typename T_field> | |||||
| struct simple_field_t | |||||
| : public field_t | |||||
| { | |||||
| using schema_type = T_schema; | |||||
| using field_type = T_field; | |||||
| const schema_type& schema; | |||||
| const field_type& field; | |||||
| inline simple_field_t(const schema_type& p_schema, const field_type& p_field) | |||||
| : field_t () | |||||
| , schema (p_schema) | |||||
| , field (p_field) | |||||
| { } | |||||
| }; | |||||
| /* value_field_t */ | |||||
| template<typename T_schema, typename T_field> | |||||
| struct value_field_t | |||||
| : public simple_field_t<T_schema, T_field> | |||||
| { | |||||
| using base_type = simple_field_t<T_schema, T_field>; | |||||
| using base_type::base_type; | |||||
| }; | |||||
| /* primary_key_field_t */ | |||||
| template<typename T_schema, typename T_field> | |||||
| struct primary_key_field_t | |||||
| : public value_field_t<T_schema, T_field> | |||||
| { | |||||
| using base_type = value_field_t<T_schema, T_field>; | |||||
| using base_type::base_type; | |||||
| }; | |||||
| /* data_field_t */ | |||||
| template<typename T_schema, typename T_field> | |||||
| struct data_field_t | |||||
| : public value_field_t<T_schema, T_field> | |||||
| { | |||||
| using base_type = value_field_t<T_schema, T_field>; | |||||
| using base_type::base_type; | |||||
| }; | |||||
| /* foreign_table_field_t */ | |||||
| template<typename T_schema, typename T_field> | |||||
| struct foreign_table_field_t | |||||
| : public simple_field_t<T_schema, T_field> | |||||
| { | |||||
| using base_type = simple_field_t<T_schema, T_field>; | |||||
| using base_type::base_type; | |||||
| }; | |||||
| namespace __impl | |||||
| { | |||||
| /* is_primary_key_field */ | |||||
| template<typename T_field> | |||||
| struct is_primary_key_field | |||||
| : public mp::decay_t<decltype( | |||||
| hana::contains( | |||||
| std::declval<T_field>().attributes, | |||||
| schema::attribute::primary_key))> | |||||
| { }; | |||||
| /* is_foreign_table_field */ | |||||
| template<typename T_schema, typename T_field> | |||||
| struct is_foreign_table_field | |||||
| : public mp::decay_t<decltype( | |||||
| hana::contains( | |||||
| hana::transform( | |||||
| std::declval<T_schema>().tables, | |||||
| schema::table::get_wrapped_dataset), | |||||
| hana::type_c<misc::real_dataset_t<typename T_field::getter_type::value_type>>))> | |||||
| { }; | |||||
| /* field_type */ | |||||
| template<typename T_schema, typename T_field, typename = void> | |||||
| struct field_type | |||||
| { using type = data_field_t<T_schema, T_field>; }; | |||||
| template<typename T_schema, typename T_field> | |||||
| struct field_type<T_schema, T_field, mp::enable_if<is_primary_key_field<T_field>>> | |||||
| { using type = primary_key_field_t<T_schema, T_field>; }; | |||||
| template<typename T_schema, typename T_field> | |||||
| struct field_type<T_schema, T_field, mp::enable_if<is_foreign_table_field<T_schema, T_field>>> | |||||
| { using type = foreign_table_field_t<T_schema, T_field>; }; | |||||
| template<typename T_schema, typename T_field> | |||||
| using field_type_t = typename field_type<T_schema, T_field>::type; | |||||
| /* make_field_impl */ | |||||
| template<typename T, typename> | |||||
| struct make_field_impl | |||||
| { | |||||
| template<typename... T_args> | |||||
| static constexpr decltype(auto) apply(T_args&&... args) | |||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for mariadb::make_field(...)!"); } | |||||
| }; | |||||
| template<typename T_schema, typename T_table, typename T_field> | |||||
| struct make_field_impl< | |||||
| mp::list<T_schema, T_table, T_field>, | |||||
| mp::enable_if_c< | |||||
| schema::is_schema<mp::decay_t<T_schema>>::value | |||||
| && schema::is_table <mp::decay_t<T_table >>::value | |||||
| && schema::is_field <mp::decay_t<T_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<T_schema>; | |||||
| using field_type = mp::decay_t<T_field>; | |||||
| using getter_type = mp::decay_t<typename field_type::getter_type>; | |||||
| using value_type = mp::decay_t<typename getter_type::value_type>; | |||||
| using dataset_type = mp::decay_t<typename getter_type::dataset_type>; | |||||
| using value_dataset_type = misc::real_dataset_t<value_type>; | |||||
| using return_type = field_type_t<schema_type, field_type>; | |||||
| return_type ret(schema, field); | |||||
| ret.table_dataset_id = misc::get_type_id(hana::type_c<dataset_type>), | |||||
| ret.value_dataset_id = misc::get_type_id(hana::type_c<value_dataset_type>), | |||||
| ret.value_is_nullable = misc::is_nullable<value_type>::value, | |||||
| ret.value_is_container = misc::is_container<value_type>::value, | |||||
| ret.schema_name = schema.name, | |||||
| ret.table_name = table.name, | |||||
| ret.field_name = field.name, | |||||
| ret.attributes = make_attributes(field.attributes); | |||||
| return ret; | |||||
| } | |||||
| }; | |||||
| } | |||||
| } | |||||
| end_namespace_cpphibernate_driver_mariadb | |||||
| @@ -0,0 +1,29 @@ | |||||
| #pragma once | |||||
| #include <vector> | |||||
| #include <cpphibernate/misc.h> | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/field.fwd.h> | |||||
| beg_namespace_cpphibernate_driver_mariadb | |||||
| { | |||||
| /* fields_t */ | |||||
| struct fields_t; | |||||
| /* make_fields */ | |||||
| namespace __impl | |||||
| { | |||||
| template<typename T, typename = void> | |||||
| struct make_fields_impl; | |||||
| } | |||||
| constexpr decltype(auto) make_fields = misc::make_generic_predicate<__impl::make_fields_impl> { }; | |||||
| } | |||||
| end_namespace_cpphibernate_driver_mariadb | |||||
| @@ -0,0 +1,71 @@ | |||||
| #pragma once | |||||
| #include <vector> | |||||
| #include <cpphibernate/misc.h> | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/schema/table.h> | |||||
| #include <cpphibernate/schema/schema.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/field.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/fields.fwd.h> | |||||
| beg_namespace_cpphibernate_driver_mariadb | |||||
| { | |||||
| /* fields_t */ | |||||
| struct fields_t | |||||
| : public std::vector<field_ptr_t> | |||||
| { | |||||
| using base_type = std::vector<field_ptr_t>; | |||||
| using base_type::base_type; | |||||
| }; | |||||
| namespace __impl | |||||
| { | |||||
| /* make_fields_impl */ | |||||
| template<typename T, typename> | |||||
| struct make_fields_impl | |||||
| { | |||||
| template<typename... T_args> | |||||
| static constexpr decltype(auto) apply(T_args&&... args) | |||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for mariadb::make_fields(...)!"); } | |||||
| }; | |||||
| template<typename T_schema, typename T_table> | |||||
| struct make_fields_impl< | |||||
| mp::list<T_schema, T_table>, | |||||
| mp::enable_if_c< | |||||
| schema::is_schema<mp::decay_t<T_schema>>::value | |||||
| && schema::is_table <mp::decay_t<T_table >>::value>> | |||||
| { | |||||
| template<typename T_index> | |||||
| 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<decltype(field)>; | |||||
| fields.emplace_back(new field_type(std::move(field))); | |||||
| } | |||||
| template<size_t... I> | |||||
| static auto helper(const T_schema& schema, const T_table& table, std::index_sequence<I...>&&) | |||||
| { | |||||
| fields_t fields; | |||||
| int dummy[] = {0, (emplace(fields, schema, table, hana::size_c<I>), 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<size::value> { }); | |||||
| } | |||||
| }; | |||||
| } | |||||
| } | |||||
| end_namespace_cpphibernate_driver_mariadb | |||||
| @@ -0,0 +1,27 @@ | |||||
| #pragma once | |||||
| #include <memory> | |||||
| #include <cpphibernate/misc.h> | |||||
| #include <cpphibernate/config.h> | |||||
| beg_namespace_cpphibernate_driver_mariadb | |||||
| { | |||||
| /* schema_t */ | |||||
| struct schema_t; | |||||
| /* make_schema */ | |||||
| namespace __impl | |||||
| { | |||||
| template<typename T, typename = void> | |||||
| struct make_schema_impl; | |||||
| } | |||||
| constexpr decltype(auto) make_schema = misc::make_generic_predicate<__impl::make_schema_impl> { }; | |||||
| } | |||||
| end_namespace_cpphibernate_driver_mariadb | |||||
| @@ -0,0 +1,61 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/misc.h> | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/tables.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/schema.fwd.h> | |||||
| 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; | |||||
| }; | |||||
| namespace __impl | |||||
| { | |||||
| /* make_schema_impl */ | |||||
| template<typename T, typename> | |||||
| struct make_schema_impl | |||||
| { | |||||
| template<typename... T_args> | |||||
| static constexpr decltype(auto) apply(T_args&&... args) | |||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for mariadb::make_schema(...)!"); } | |||||
| }; | |||||
| template<typename T_schema> | |||||
| struct make_schema_impl< | |||||
| mp::list<T_schema>, | |||||
| mp::enable_if_c< | |||||
| schema::is_schema<mp::decay_t<T_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 | |||||
| @@ -0,0 +1,31 @@ | |||||
| #pragma once | |||||
| #include <memory> | |||||
| #include <cpphibernate/misc.h> | |||||
| #include <cpphibernate/config.h> | |||||
| beg_namespace_cpphibernate_driver_mariadb | |||||
| { | |||||
| /* table_t */ | |||||
| struct table_t; | |||||
| /* table_ptr_t */ | |||||
| using table_ptr_t = std::unique_ptr<table_t>; | |||||
| /* make_table */ | |||||
| namespace __impl | |||||
| { | |||||
| template<typename T, typename = void> | |||||
| struct make_table_impl; | |||||
| } | |||||
| constexpr decltype(auto) make_table = misc::make_generic_predicate<__impl::make_table_impl> { }; | |||||
| } | |||||
| end_namespace_cpphibernate_driver_mariadb | |||||
| @@ -0,0 +1,194 @@ | |||||
| #pragma once | |||||
| #include <memory> | |||||
| #include <vector> | |||||
| #include <cpphibernate/misc.h> | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/schema/table.h> | |||||
| #include <cpphibernate/schema/schema.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/fields.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/table.fwd.h> | |||||
| beg_namespace_cpphibernate_driver_mariadb | |||||
| { | |||||
| /* table_t */ | |||||
| struct table_t | |||||
| { | |||||
| size_t dataset_id { 0 }; | |||||
| size_t base_dataset_id { 0 }; | |||||
| size_t table_id { 0 }; | |||||
| std::vector<size_t> derived_dataset_ids; | |||||
| std::string table_name; | |||||
| std::string schema_name; | |||||
| fields_t fields; | |||||
| const table_t* base_table { nullptr }; | |||||
| std::vector<const table_t*> derived_tables; | |||||
| const field_t* primary_key_field { nullptr }; | |||||
| std::vector<const field_t*> foreign_key_fields; | |||||
| std::vector<const field_t*> foreign_table_fields; | |||||
| std::vector<const field_t*> foreign_table_one_fields; | |||||
| std::vector<const field_t*> foreign_table_many_fields; | |||||
| std::vector<const field_t*> 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() = default; | |||||
| }; | |||||
| /* table_simple_t */ | |||||
| template<typename T_schema, typename T_table, typename T_base_dataset> | |||||
| struct table_simple_t | |||||
| : public table_t | |||||
| { | |||||
| using schema_type = T_schema; | |||||
| using table_type = T_table; | |||||
| using base_dataset_type = T_base_dataset; | |||||
| 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<typename T_schema, typename T_table, typename T_base_dataset> | |||||
| struct table_polymorphic_t | |||||
| : public table_simple_t<T_schema, T_table, T_base_dataset> | |||||
| { | |||||
| using base_type = table_simple_t<T_schema, T_table, T_base_dataset>; | |||||
| using schema_type = T_schema; | |||||
| using table_type = T_table; | |||||
| using base_dataset_type = T_base_dataset; | |||||
| using base_type::base_type; | |||||
| const schema_type& schema; | |||||
| const table_type& table; | |||||
| }; | |||||
| namespace __impl | |||||
| { | |||||
| /* make_dataset_id_vector */ | |||||
| struct make_dataset_id_vector_impl | |||||
| { | |||||
| template<typename T_wrapped_datasets, size_t... I> | |||||
| static constexpr decltype(auto) helper(const T_wrapped_datasets& wrapped_datasets, std::index_sequence<I...>) | |||||
| { | |||||
| return std::vector<size_t>({ | |||||
| misc::get_type_id(wrapped_datasets[hana::size_c<I>])... | |||||
| }); | |||||
| } | |||||
| template<typename T_wrapped_datasets> | |||||
| constexpr decltype(auto) operator()(T_wrapped_datasets&& wrapped_datasets) const | |||||
| { | |||||
| using size = mp::decay_t<decltype(hana::size(wrapped_datasets))>; | |||||
| return helper(std::forward<T_wrapped_datasets>(wrapped_datasets), std::make_index_sequence<size::value> { }); | |||||
| } | |||||
| }; | |||||
| static constexpr decltype(auto) make_dataset_id_vector = make_dataset_id_vector_impl { }; | |||||
| /* make_table_impl */ | |||||
| template<typename T, typename> | |||||
| struct make_table_impl | |||||
| { | |||||
| template<typename... T_args> | |||||
| static constexpr decltype(auto) apply(T_args&&... args) | |||||
| { static_assert(sizeof...(args) == 0, "Invalid parameters for mariadb::make_table(...)!"); } | |||||
| }; | |||||
| template<typename T_schema, typename T_table> | |||||
| struct make_table_impl< | |||||
| mp::list<T_schema, T_table>, | |||||
| mp::enable_if_c< | |||||
| schema::is_schema<mp::decay_t<T_schema>>::value | |||||
| && schema::is_table <mp::decay_t<T_table>>::value>> | |||||
| { | |||||
| /* table_type */ | |||||
| template<typename T_dataset, typename T_base_dataset, typename = void> | |||||
| struct table_type | |||||
| { using type = table_simple_t<mp::decay_t<T_schema>, mp::decay_t<T_table>, T_base_dataset>; }; | |||||
| template<typename T_dataset, typename T_base_dataset> | |||||
| struct table_type<T_dataset, T_base_dataset, mp::enable_if_c< | |||||
| std::is_polymorphic<T_dataset>::value>> | |||||
| { using type = table_polymorphic_t<mp::decay_t<T_schema>, mp::decay_t<T_table>, T_base_dataset>; }; | |||||
| template<typename T_dataset, typename T_base_dataset> | |||||
| using table_type_t = typename table_type<T_dataset, T_base_dataset>::type; | |||||
| /* apply */ | |||||
| static decltype(auto) apply(const T_schema& schema, const T_table& table) | |||||
| { | |||||
| using wrapped_base_type = mp::decay_t<decltype( | |||||
| schema::get_base_type( | |||||
| std::declval<T_schema>(), | |||||
| std::declval<T_table>().wrapped_dataset))>; | |||||
| using base_type = misc::unwrap_t<wrapped_base_type>; | |||||
| using derived_wrapped_types_type = mp::decay_t<decltype( | |||||
| schema::get_derived_types( | |||||
| std::declval<T_schema>(), | |||||
| std::declval<T_table>().wrapped_dataset))>; | |||||
| using wrapped_dataset_type = typename mp::decay_t<T_table>::wrapped_dataset_type; | |||||
| using dataset_type = misc::unwrap_t<wrapped_dataset_type>; | |||||
| using table_type = table_type_t<dataset_type, base_type>; | |||||
| 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 | |||||
| @@ -0,0 +1,29 @@ | |||||
| #pragma once | |||||
| #include <vector> | |||||
| #include <cpphibernate/misc.h> | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/field.fwd.h> | |||||
| beg_namespace_cpphibernate_driver_mariadb | |||||
| { | |||||
| /* tables_t */ | |||||
| struct tables_t; | |||||
| /* make_tables */ | |||||
| namespace __impl | |||||
| { | |||||
| template<typename T, typename = void> | |||||
| struct make_tables_impl; | |||||
| } | |||||
| constexpr decltype(auto) make_tables = misc::make_generic_predicate<__impl::make_tables_impl> { }; | |||||
| } | |||||
| end_namespace_cpphibernate_driver_mariadb | |||||
| @@ -0,0 +1,69 @@ | |||||
| #pragma once | |||||
| #include <map> | |||||
| #include <cpphibernate/misc.h> | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/schema/schema.h> | |||||
| #include <cpphibernate/driver/mariadb/schema/table.h> | |||||
| beg_namespace_cpphibernate_driver_mariadb | |||||
| { | |||||
| /* tables_t */ | |||||
| struct tables_t | |||||
| : public std::map<size_t, table_ptr_t> | |||||
| { | |||||
| using base_type = std::map<size_t, table_ptr_t>; | |||||
| using base_type::base_type; | |||||
| }; | |||||
| namespace __impl | |||||
| { | |||||
| /* make_tables_impl */ | |||||
| template<typename T, typename> | |||||
| struct make_tables_impl | |||||
| { | |||||
| template<typename... T_args> | |||||
| static constexpr decltype(auto) apply(T_args&&... args) | |||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for mariadb::make_tables(...)!"); } | |||||
| }; | |||||
| template<typename T_schema> | |||||
| struct make_tables_impl< | |||||
| mp::list<T_schema>, | |||||
| mp::enable_if_c< | |||||
| schema::is_schema<mp::decay_t<T_schema>>::value>> | |||||
| { | |||||
| template<typename T_index> | |||||
| 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<decltype(table)>; | |||||
| auto key = table.dataset_id; | |||||
| tables.emplace(key, std::make_unique<table_type>(std::move(table))); | |||||
| } | |||||
| template<size_t... I> | |||||
| static decltype(auto) helper(const T_schema& schema, std::index_sequence<I...>) | |||||
| { | |||||
| tables_t tables; | |||||
| int dummy[] = {0, (emplace(tables, schema, hana::size_c<I>), 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<size::value> { }); | |||||
| } | |||||
| }; | |||||
| } | |||||
| } | |||||
| end_namespace_cpphibernate_driver_mariadb | |||||
| @@ -1,6 +1,7 @@ | |||||
| #pragma once | #pragma once | ||||
| #include <cpphibernate/config.h> | #include <cpphibernate/config.h> | ||||
| #include <cpputils/misc/type_helper.h> | |||||
| beg_namespace_cpphibernate_misc | beg_namespace_cpphibernate_misc | ||||
| { | { | ||||
| @@ -15,5 +16,17 @@ beg_namespace_cpphibernate_misc | |||||
| { return T_builder<mp::list<T_args...>>::apply(std::forward<T_args>(args)...); } | { return T_builder<mp::list<T_args...>>::apply(std::forward<T_args>(args)...); } | ||||
| }; | }; | ||||
| /* get_dataset_id */ | |||||
| namespace __impl | |||||
| { | |||||
| struct counter_type_id | |||||
| { }; | |||||
| } | |||||
| template<typename T_type> | |||||
| constexpr decltype(auto) get_type_id(T_type&&) | |||||
| { return utl::get_unique_id<__impl::counter_type_id, mp::decay_t<T_type>>(); } | |||||
| } | } | ||||
| end_namespace_cpphibernate_misc | end_namespace_cpphibernate_misc | ||||
| @@ -96,14 +96,6 @@ beg_namespace_cpphibernate_misc | |||||
| struct real_dataset_impl<std::list<T>, void> | struct real_dataset_impl<std::list<T>, void> | ||||
| { using type = typename real_dataset_impl<T>::type; }; | { using type = typename real_dataset_impl<T>::type; }; | ||||
| template<typename T_from, typename T_to, typename = void> | |||||
| struct change_dataset_type_impl | |||||
| { using type = T_to; }; | |||||
| template<template<typename...> class X, typename T_from, typename T_to> | |||||
| struct change_dataset_type_impl<X<T_from>, T_to, void> | |||||
| { using type = X<T_to>; }; | |||||
| } | } | ||||
| /* meta */ | /* meta */ | ||||
| @@ -15,7 +15,7 @@ beg_namespace_cpphibernate_modifier | |||||
| struct where_clause_and_t | struct where_clause_and_t | ||||
| : public where_clause_t | : public where_clause_t | ||||
| { | { | ||||
| using clauses_type = hana::basic_tuple<T_clauses...>; | |||||
| using clauses_type = hana::tuple<T_clauses...>; | |||||
| clauses_type clauses; | clauses_type clauses; | ||||
| @@ -15,7 +15,7 @@ beg_namespace_cpphibernate_modifier | |||||
| struct where_clause_or_t | struct where_clause_or_t | ||||
| : public where_clause_t | : public where_clause_t | ||||
| { | { | ||||
| using clauses_type = hana::basic_tuple<T_clauses...>; | |||||
| using clauses_type = hana::tuple<T_clauses...>; | |||||
| clauses_type clauses; | clauses_type clauses; | ||||
| @@ -13,7 +13,7 @@ beg_namespace_cpphibernate_schema | |||||
| /* attributes_t */ | /* attributes_t */ | ||||
| template<typename... T_attributes> | template<typename... T_attributes> | ||||
| using attributes_t = hana::basic_tuple<T_attributes...>; | |||||
| using attributes_t = hana::tuple<T_attributes...>; | |||||
| /* is_attributes_impl */ | /* is_attributes_impl */ | ||||
| @@ -27,37 +27,47 @@ beg_namespace_cpphibernate_schema | |||||
| : mp::c_true_t | : mp::c_true_t | ||||
| { }; | { }; | ||||
| /* attributes_builder */ | |||||
| } | |||||
| /* meta */ | |||||
| template<typename T> | |||||
| struct is_attributes | |||||
| : public __impl::is_attributes_impl<T> | |||||
| { }; | |||||
| /* operations */ | |||||
| namespace __impl | |||||
| { | |||||
| /* attributes_make_impl */ | |||||
| template<typename T, typename = void> | template<typename T, typename = void> | ||||
| struct attributes_builder | |||||
| struct attributes_make_impl | |||||
| { | { | ||||
| template<typename... T_args> | template<typename... T_args> | ||||
| static constexpr decltype(auto) apply(T_args&&...) | static constexpr decltype(auto) apply(T_args&&...) | ||||
| { static_assert(sizeof...(T_args) == -1, "Invalid parameters for hibernate::schema::make_attributes(...)!"); } | |||||
| { static_assert(sizeof...(T_args) == -1, "Invalid parameters for hibernate::schema::attributes::make(...)!"); } | |||||
| }; | }; | ||||
| template<typename... T> | template<typename... T> | ||||
| struct attributes_builder<mp::list<T...>, mp::enable_if_c< | |||||
| struct attributes_make_impl<mp::list<T...>, mp::enable_if_c< | |||||
| all_are_attribures<mp::decay_t<T>...>::value>> | all_are_attribures<mp::decay_t<T>...>::value>> | ||||
| { | { | ||||
| template<typename... T_args> | template<typename... T_args> | ||||
| static constexpr decltype(auto) apply(T_args&&...) | static constexpr decltype(auto) apply(T_args&&...) | ||||
| { return attributes_t<mp::decay_t<T_args>...> { }; } | { return attributes_t<mp::decay_t<T_args>...> { }; } | ||||
| }; | |||||
| }; | |||||
| } | } | ||||
| /* meta */ | |||||
| template<typename T> | |||||
| struct is_attributes | |||||
| : public __impl::is_attributes_impl<T> | |||||
| { }; | |||||
| namespace attributes | |||||
| { | |||||
| /* make */ | |||||
| constexpr decltype(auto) make = misc::make_generic_predicate<__impl::attributes_make_impl> { }; | |||||
| constexpr decltype(auto) make_attributes = misc::make_generic_predicate<__impl::attributes_builder> { }; | |||||
| } | |||||
| } | } | ||||
| end_namespace_cpphibernate_schema | end_namespace_cpphibernate_schema | ||||
| @@ -72,18 +72,37 @@ beg_namespace_cpphibernate_schema | |||||
| } | } | ||||
| }; | }; | ||||
| /* field_builder */ | |||||
| } | |||||
| /* meta */ | |||||
| template<typename T> | |||||
| struct is_field | |||||
| : public mp::is_specialization_of<T, __impl::field_t> | |||||
| { }; | |||||
| template<typename... T> | |||||
| struct all_are_fields | |||||
| : public mp::all_true<is_field<T>::value...> | |||||
| { }; | |||||
| /* operations */ | |||||
| namespace __impl | |||||
| { | |||||
| /* field_make_impl */ | |||||
| template<typename X, typename = void> | template<typename X, typename = void> | ||||
| struct field_builder | |||||
| struct field_make_impl | |||||
| { | { | ||||
| template <typename ...T_args> | template <typename ...T_args> | ||||
| static constexpr decltype(auto) apply(T_args&&... args) | static constexpr decltype(auto) apply(T_args&&... args) | ||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::make_field(...)!"); } | |||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::field::make(...)!"); } | |||||
| }; | }; | ||||
| template<typename T_name, typename T_getter, typename T_setter, typename T_attributes> | template<typename T_name, typename T_getter, typename T_setter, typename T_attributes> | ||||
| struct field_builder<mp::list<T_name, T_getter, T_setter, T_attributes>, mp::enable_if_c< | |||||
| struct field_make_impl<mp::list<T_name, T_getter, T_setter, T_attributes>, mp::enable_if_c< | |||||
| is_getter<mp::decay_t<T_getter>>::value | is_getter<mp::decay_t<T_getter>>::value | ||||
| && is_setter<mp::decay_t<T_setter>>::value | && is_setter<mp::decay_t<T_setter>>::value | ||||
| && is_attributes<mp::decay_t<T_attributes>>::value>> | && is_attributes<mp::decay_t<T_attributes>>::value>> | ||||
| @@ -96,21 +115,12 @@ beg_namespace_cpphibernate_schema | |||||
| } | } | ||||
| /* meta */ | |||||
| template<typename T> | |||||
| struct is_field | |||||
| : public mp::is_specialization_of<T, __impl::field_t> | |||||
| { }; | |||||
| template<typename... T> | |||||
| struct all_are_fields | |||||
| : public mp::all_true<is_field<T>::value...> | |||||
| { }; | |||||
| namespace field | |||||
| { | |||||
| /* make */ | |||||
| constexpr decltype(auto) make = misc::make_generic_predicate<__impl::field_make_impl> { }; | |||||
| constexpr decltype(auto) make_field = misc::make_generic_predicate<__impl::field_builder> { }; | |||||
| } | |||||
| } | } | ||||
| end_namespace_cpphibernate_schema | end_namespace_cpphibernate_schema | ||||
| @@ -13,7 +13,7 @@ beg_namespace_cpphibernate_schema | |||||
| /* fields_t */ | /* fields_t */ | ||||
| template<typename... T_fields> | template<typename... T_fields> | ||||
| using fields_t = hana::basic_tuple<T_fields...>; | |||||
| using fields_t = hana::tuple<T_fields...>; | |||||
| /* is_fields_impl */ | /* is_fields_impl */ | ||||
| @@ -27,18 +27,32 @@ beg_namespace_cpphibernate_schema | |||||
| : public mp::c_true_t | : public mp::c_true_t | ||||
| { }; | { }; | ||||
| /* fields_builder */ | |||||
| } | |||||
| /* meta */ | |||||
| template<typename T> | |||||
| struct is_fields : | |||||
| public __impl::is_fields_impl<T> | |||||
| { }; | |||||
| /* operations */ | |||||
| namespace __impl | |||||
| { | |||||
| /* fields_make_impl */ | |||||
| template <typename T, typename = void> | template <typename T, typename = void> | ||||
| struct fields_builder | |||||
| struct fields_make_impl | |||||
| { | { | ||||
| template <typename ...T_args> | template <typename ...T_args> | ||||
| static constexpr decltype(auto) apply(T_args&&... args) | static constexpr decltype(auto) apply(T_args&&... args) | ||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::make_fields(...)!"); } | |||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::fields::make(...)!"); } | |||||
| }; | }; | ||||
| template<typename... T> | template<typename... T> | ||||
| struct fields_builder<mp::list<T...>, mp::enable_if<all_are_fields<T...>>> | |||||
| struct fields_make_impl<mp::list<T...>, mp::enable_if<all_are_fields<T...>>> | |||||
| { | { | ||||
| template <typename ...T_args> | template <typename ...T_args> | ||||
| static constexpr decltype(auto) apply(T_args&&... args) | static constexpr decltype(auto) apply(T_args&&... args) | ||||
| @@ -47,16 +61,12 @@ beg_namespace_cpphibernate_schema | |||||
| } | } | ||||
| /* meta */ | |||||
| template<typename T> | |||||
| struct is_fields : | |||||
| public __impl::is_fields_impl<T> | |||||
| { }; | |||||
| namespace fields | |||||
| { | |||||
| /* constructors */ | |||||
| constexpr decltype(auto) make = misc::make_generic_predicate<__impl::fields_make_impl> { }; | |||||
| constexpr decltype(auto) make_fields = misc::make_generic_predicate<__impl::fields_builder> { }; | |||||
| } | |||||
| } | } | ||||
| end_namespace_cpphibernate_schema | end_namespace_cpphibernate_schema | ||||
| @@ -11,35 +11,22 @@ beg_namespace_cpphibernate_schema | |||||
| /* getter_t */ | /* getter_t */ | ||||
| template<typename T_value> | |||||
| template<typename T_dataset, typename T_value> | |||||
| struct getter_t | struct getter_t | ||||
| { | { | ||||
| using value_type = T_value; | |||||
| }; | |||||
| /* getter_none_t */ | |||||
| struct getter_none_t | |||||
| : public getter_t<void> | |||||
| { | |||||
| using base_type = getter_t<void>; | |||||
| using value_type = typename base_type::value_type; | |||||
| cpphibernate_constructable(getter_none_t, default); | |||||
| cpphibernate_copyable (getter_none_t, delete); | |||||
| cpphibernate_moveable (getter_none_t, default); | |||||
| using dataset_type = T_dataset; | |||||
| using value_type = T_value; | |||||
| }; | }; | ||||
| /* getter_member_var_t */ | /* getter_member_var_t */ | ||||
| template<typename T_dataset, typename T_value, typename T_member> | template<typename T_dataset, typename T_value, typename T_member> | ||||
| struct getter_member_var_t | struct getter_member_var_t | ||||
| : public getter_t<T_value> | |||||
| : public getter_t<T_dataset, T_value> | |||||
| { | { | ||||
| using base_type = getter_t<T_value>; | |||||
| using base_type = getter_t<T_dataset, T_value>; | |||||
| using dataset_type = typename base_type::dataset_type; | |||||
| using value_type = typename base_type::value_type; | using value_type = typename base_type::value_type; | ||||
| using dataset_type = T_dataset; | |||||
| using member_type = T_member; | using member_type = T_member; | ||||
| member_type member; | member_type member; | ||||
| @@ -61,11 +48,11 @@ beg_namespace_cpphibernate_schema | |||||
| template<typename T_dataset, typename T_value, typename T_member> | template<typename T_dataset, typename T_value, typename T_member> | ||||
| struct getter_member_func_t | struct getter_member_func_t | ||||
| : public getter_t<T_value> | |||||
| : public getter_t<T_dataset, T_value> | |||||
| { | { | ||||
| using base_type = getter_t<T_value>; | |||||
| using base_type = getter_t<T_dataset, T_value>; | |||||
| using dataset_type = typename base_type::dataset_type; | |||||
| using value_type = typename base_type::value_type; | using value_type = typename base_type::value_type; | ||||
| using dataset_type = T_dataset; | |||||
| using member_type = T_member; | using member_type = T_member; | ||||
| member_type member; | member_type member; | ||||
| @@ -87,11 +74,11 @@ beg_namespace_cpphibernate_schema | |||||
| template<typename T_dataset, typename T_lambda> | template<typename T_dataset, typename T_lambda> | ||||
| struct getter_lambda_t | struct getter_lambda_t | ||||
| : public getter_t<decltype(std::declval<T_lambda>()(std::declval<T_dataset>()))> | |||||
| : public getter_t<T_dataset, decltype(std::declval<T_lambda>()(std::declval<T_dataset>()))> | |||||
| { | { | ||||
| using base_type = getter_t<decltype(std::declval<T_lambda>()(std::declval<T_dataset>()))>; | |||||
| using base_type = getter_t<T_dataset, decltype(std::declval<T_lambda>()(std::declval<T_dataset>()))>; | |||||
| using dataset_type = typename base_type::dataset_type; | |||||
| using value_type = typename base_type::value_type; | using value_type = typename base_type::value_type; | ||||
| using dataset_type = T_dataset; | |||||
| using lambda_type = T_lambda; | using lambda_type = T_lambda; | ||||
| lambda_type lambda; | lambda_type lambda; | ||||
| @@ -118,7 +105,7 @@ beg_namespace_cpphibernate_schema | |||||
| template<typename T> | template<typename T> | ||||
| struct is_getter_impl<T, mp::enable_if_c< | struct is_getter_impl<T, mp::enable_if_c< | ||||
| mp::is_base_of<getter_t<typename T::value_type>, T>::value>> | |||||
| mp::is_base_of<getter_t<typename T::dataset_type, typename T::value_type>, T>::value>> | |||||
| : public mp::c_true_t | : public mp::c_true_t | ||||
| { }; | { }; | ||||
| @@ -133,9 +120,6 @@ beg_namespace_cpphibernate_schema | |||||
| /* make */ | /* make */ | ||||
| constexpr decltype(auto) make_getter_none() | |||||
| { return __impl::getter_none_t(); } | |||||
| template<typename T_dataset, typename T_value> | template<typename T_dataset, typename T_value> | ||||
| constexpr decltype(auto) make_getter_member_var(T_value T_dataset::* member) | constexpr decltype(auto) make_getter_member_var(T_value T_dataset::* member) | ||||
| { return __impl::getter_member_var_t<T_dataset, T_value, T_value T_dataset::*>(member); } | { return __impl::getter_member_var_t<T_dataset, T_value, T_value T_dataset::*>(member); } | ||||
| @@ -152,55 +136,59 @@ beg_namespace_cpphibernate_schema | |||||
| constexpr decltype(auto) make_getter_lambda(T_lambda&& lambda, boost::hana::basic_type<T_dataset>) | constexpr decltype(auto) make_getter_lambda(T_lambda&& lambda, boost::hana::basic_type<T_dataset>) | ||||
| { return __impl::getter_lambda_t<T_dataset, T_lambda>(std::forward<T_lambda>(lambda)); } | { return __impl::getter_lambda_t<T_dataset, T_lambda>(std::forward<T_lambda>(lambda)); } | ||||
| /* operations */ | |||||
| namespace __impl | namespace __impl | ||||
| { | { | ||||
| /* getter_buildser */ | |||||
| /* getter_make_impl */ | |||||
| template<typename X, typename = void> | template<typename X, typename = void> | ||||
| struct getter_builder | |||||
| struct getter_make_impl | |||||
| { | { | ||||
| template<typename... Args> | template<typename... Args> | ||||
| static constexpr decltype(auto) apply(Args&&...) | |||||
| { return make_getter_none(); } | |||||
| static constexpr decltype(auto) apply(Args&&... args) | |||||
| { static_assert(sizeof...(args) == -1, "Invalid arguments to schema::getter::make(...)!"); } | |||||
| }; | }; | ||||
| template<typename T_dataset, typename T_value> | template<typename T_dataset, typename T_value> | ||||
| struct getter_builder<mp::list<T_value T_dataset::*>, void> | |||||
| struct getter_make_impl<mp::list<T_value T_dataset::*>, void> | |||||
| { | { | ||||
| static constexpr decltype(auto) apply(T_value T_dataset::*member) | static constexpr decltype(auto) apply(T_value T_dataset::*member) | ||||
| { return make_getter_member_var(member); } | { return make_getter_member_var(member); } | ||||
| }; | }; | ||||
| template<typename T_dataset, typename T_value> | template<typename T_dataset, typename T_value> | ||||
| struct getter_builder<mp::list<T_value (T_dataset::*)(void)>, void> | |||||
| struct getter_make_impl<mp::list<T_value (T_dataset::*)(void)>, void> | |||||
| { | { | ||||
| static constexpr decltype(auto) apply(T_value (T_dataset::*member)(void)) | static constexpr decltype(auto) apply(T_value (T_dataset::*member)(void)) | ||||
| { return make_getter_member_func(member); } | { return make_getter_member_func(member); } | ||||
| }; | }; | ||||
| template<typename T_dataset, typename T_value> | template<typename T_dataset, typename T_value> | ||||
| struct getter_builder<mp::list<T_value (T_dataset::*)(void) const>, void> | |||||
| struct getter_make_impl<mp::list<T_value (T_dataset::*)(void) const>, void> | |||||
| { | { | ||||
| static constexpr decltype(auto) apply(T_value (T_dataset::*member)(void) const) | static constexpr decltype(auto) apply(T_value (T_dataset::*member)(void) const) | ||||
| { return make_getter_member_func(member); } | { return make_getter_member_func(member); } | ||||
| }; | }; | ||||
| template<typename T_func, typename T_dataset_type, typename T_value_type> | |||||
| struct getter_builder<mp::list<T_func, T_dataset_type, T_value_type>, mp::enable_if_c< | |||||
| hana::is_a<hana::type_tag, mp::decay_t<T_dataset_type>> | |||||
| template<typename T_func, typename T_wrapped_dataset, typename T_value_type> | |||||
| struct getter_make_impl<mp::list<T_func, T_wrapped_dataset, T_value_type>, mp::enable_if_c< | |||||
| hana::is_a<hana::type_tag, mp::decay_t<T_wrapped_dataset>> | |||||
| && hana::is_a<hana::type_tag, mp::decay_t<T_value_type>>>> | && hana::is_a<hana::type_tag, mp::decay_t<T_value_type>>>> | ||||
| { | { | ||||
| static constexpr decltype(auto) apply(T_func&& func, T_dataset_type&& dataset_type, T_value_type&& value_type) | |||||
| { return make_getter_lambda(std::forward<T_func>(func), std::forward<T_dataset_type>(dataset_type), std::forward<T_value_type>(value_type)); } | |||||
| static constexpr decltype(auto) apply(T_func&& func, T_wrapped_dataset&& wrapped_dataset, T_value_type&& value_type) | |||||
| { return make_getter_lambda(std::forward<T_func>(func), std::forward<T_wrapped_dataset>(wrapped_dataset), std::forward<T_value_type>(value_type)); } | |||||
| }; | }; | ||||
| } | } | ||||
| /* make */ | |||||
| namespace getter | |||||
| { | |||||
| constexpr decltype(auto) make_getter = misc::make_generic_predicate<__impl::getter_builder> { }; | |||||
| constexpr decltype(auto) make = misc::make_generic_predicate<__impl::getter_make_impl> { }; | |||||
| } | |||||
| } | } | ||||
| end_namespace_cpphibernate_schema | end_namespace_cpphibernate_schema | ||||
| @@ -6,38 +6,38 @@ | |||||
| #define cpphibernate_make_string(str) \ | #define cpphibernate_make_string(str) \ | ||||
| #str | #str | ||||
| #define cpphibernate_make_schema(name, ...) \ | |||||
| cpphibernate::schema::make_schema( \ | |||||
| cpphibernate_make_string(name), \ | |||||
| cpphibernate::schema::make_tables(__VA_ARGS__)) | |||||
| #define cpphibernate_make_table_name(name, type, id, ...) \ | |||||
| cpphibernate::schema::make_table( \ | |||||
| cpphibernate_make_string(name), \ | |||||
| boost::hana::type_c<type>, \ | |||||
| boost::hana::size_c<id>, \ | |||||
| cpphibernate::schema::make_fields(__VA_ARGS__)) | |||||
| #define cpphibernate_make_table(name, id, ...) \ | |||||
| cpphibernate_make_table_name(name, name, id, __VA_ARGS__) | |||||
| #define cpphibernate_make_field_custom(name, getter, setter, ...) \ | |||||
| cpphibernate::schema::make_field( \ | |||||
| cpphibernate_make_string(name), \ | |||||
| cpphibernate::schema::make_getter(getter), \ | |||||
| cpphibernate::schema::make_setter(setter), \ | |||||
| cpphibernate::schema::make_attributes(__VA_ARGS__)) | |||||
| #define cpphibernate_make_field_name(name, member_ptr, ...) \ | |||||
| #define cpphibernate_make_schema(p_name, ...) \ | |||||
| cpphibernate::schema::make( \ | |||||
| cpphibernate_make_string(p_name), \ | |||||
| cpphibernate::schema::tables::make(__VA_ARGS__)) | |||||
| #define cpphibernate_make_table_name(p_name, p_type, p_id, ...) \ | |||||
| cpphibernate::schema::table::make( \ | |||||
| cpphibernate_make_string(p_name), \ | |||||
| boost::hana::type_c<p_type>, \ | |||||
| boost::hana::size_c<p_id>, \ | |||||
| cpphibernate::schema::fields::make(__VA_ARGS__)) | |||||
| #define cpphibernate_make_table(p_name, p_id, ...) \ | |||||
| cpphibernate_make_table_name(p_name, p_name, p_id, __VA_ARGS__) | |||||
| #define cpphibernate_make_field_custom(p_name, p_getter, p_setter, ...) \ | |||||
| cpphibernate::schema::field::make( \ | |||||
| cpphibernate_make_string(p_name), \ | |||||
| cpphibernate::schema::getter::make(p_getter), \ | |||||
| cpphibernate::schema::setter::make(p_setter), \ | |||||
| cpphibernate::schema::attributes::make(__VA_ARGS__)) | |||||
| #define cpphibernate_make_field_name(p_name, p_member_ptr, ...) \ | |||||
| cpphibernate_make_field_custom( \ | cpphibernate_make_field_custom( \ | ||||
| name, member_ptr, member_ptr, __VA_ARGS__) | |||||
| p_name, p_member_ptr, p_member_ptr, __VA_ARGS__) | |||||
| #define cpphibernate_make_field(type, member, ...) \ | |||||
| #define cpphibernate_make_field(p_type, p_member, ...) \ | |||||
| cpphibernate_make_field_name( \ | cpphibernate_make_field_name( \ | ||||
| member, &type::member, __VA_ARGS__) | |||||
| p_member, &p_type::p_member, __VA_ARGS__) | |||||
| #define cpphibernate_make_id(member_ptr) \ | |||||
| #define cpphibernate_make_id(p_member_ptr) \ | |||||
| cpphibernate_make_field_name( \ | cpphibernate_make_field_name( \ | ||||
| null, \ | |||||
| member_ptr, \ | |||||
| "p_id", \ | |||||
| p_member_ptr, \ | |||||
| cpphibernate::schema::attribute::primary_key) | cpphibernate::schema::attribute::primary_key) | ||||
| @@ -52,34 +52,201 @@ beg_namespace_cpphibernate_schema | |||||
| } | } | ||||
| }; | }; | ||||
| /* schema_builder */ | |||||
| } | |||||
| /* meta */ | |||||
| template<typename T> | |||||
| struct is_schema : mp::is_specialization_of<T, __impl::schema_t> { }; | |||||
| /* schema::make */ | |||||
| namespace __impl | |||||
| { | |||||
| template <typename X, typename = void> | template <typename X, typename = void> | ||||
| struct schema_builder | |||||
| struct schema_make_impl | |||||
| { | { | ||||
| template <typename... T_args> | template <typename... T_args> | ||||
| static constexpr decltype(auto) apply(T_args&&... args) | static constexpr decltype(auto) apply(T_args&&... args) | ||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::make_schema(...)!"); } | |||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::make(...)!"); } | |||||
| }; | }; | ||||
| template<typename T_name, typename T_tables> | template<typename T_name, typename T_tables> | ||||
| struct schema_builder<mp::list<T_name, T_tables>, mp::enable_if_c< | |||||
| is_tables<mp::clean_type<T_tables>>::value>> | |||||
| struct schema_make_impl<mp::list<T_name, T_tables>, mp::enable_if_c< | |||||
| is_tables<mp::decay_t<T_tables>>::value>> | |||||
| { | { | ||||
| static constexpr decltype(auto) apply(T_name&& name, T_tables&& tables) | static constexpr decltype(auto) apply(T_name&& name, T_tables&& tables) | ||||
| { return schema_t<T_name, T_tables>(std::forward<T_name>(name), std::forward<T_tables>(tables)); } | { return schema_t<T_name, T_tables>(std::forward<T_name>(name), std::forward<T_tables>(tables)); } | ||||
| }; | }; | ||||
| } | |||||
| constexpr decltype(auto) make = misc::make_generic_predicate<__impl::schema_make_impl> { }; | |||||
| /* schema::get_base_type */ | |||||
| namespace __impl | |||||
| { | |||||
| struct schema_get_base_type_impl | |||||
| { | |||||
| static constexpr decltype(auto) is_base_of_pred = hana::integral(hana::metafunction<mp::is_base_of>); | |||||
| struct do_fold_impl | |||||
| { | |||||
| template<typename T_type_1, typename T_type_2> | |||||
| constexpr decltype(auto) operator()(T_type_1&& type_1, T_type_2&& type_2) const | |||||
| { | |||||
| auto check = hana::or_(is_base_of_pred(type_1, type_2), is_base_of_pred(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_pred(type_1, type_2), type_2, type_1); | |||||
| } | |||||
| }; | |||||
| static constexpr decltype(auto) do_fold = do_fold_impl { }; | |||||
| template<typename T_wrapped_datasets, typename T_wrapped_dataset> | |||||
| static constexpr decltype(auto) get_base_types(T_wrapped_datasets&& wrapped_datasets, T_wrapped_dataset&& wrapped_dataset) | |||||
| { | |||||
| return hana::filter( | |||||
| std::forward<T_wrapped_datasets>(wrapped_datasets), | |||||
| [&](auto type){ | |||||
| return hana::and_( | |||||
| is_base_of_pred(type, wrapped_dataset), | |||||
| hana::not_equal(type, wrapped_dataset)); | |||||
| }); | |||||
| } | |||||
| template<typename T_schema, typename T_wrapped_dataset> | |||||
| constexpr decltype(auto) operator()(T_schema&& schema, T_wrapped_dataset&& wrapped_dataset) const | |||||
| { | |||||
| using wrapped_datasets_type = mp::decay_t<decltype( | |||||
| hana::transform( | |||||
| std::declval<T_schema>().tables, | |||||
| schema::table::get_wrapped_dataset))>; | |||||
| auto base_types = get_base_types(wrapped_datasets_type { }, std::forward<T_wrapped_dataset>(wrapped_dataset)); | |||||
| return hana::eval_if( | |||||
| hana::size(base_types) <= hana::size_c<0>, | |||||
| [&](auto _){ return hana::type_c<void>; }, | |||||
| [&](auto _){ return hana::fold(_(base_types), do_fold); }); | |||||
| } | |||||
| }; | |||||
| } | } | ||||
| /* meta */ | |||||
| constexpr decltype(auto) get_base_type = __impl::schema_get_base_type_impl { }; | |||||
| template<typename T> | |||||
| struct is_schema : mp::is_specialization_of<T, __impl::schema_t> { }; | |||||
| /* schema::get_root_base_type */ | |||||
| namespace __impl | |||||
| { | |||||
| struct schema_get_root_base_type_impl | |||||
| { | |||||
| template<typename T_wrapped_dataset> | |||||
| struct is_base_pred | |||||
| { | |||||
| using dataset_type = misc::decay_unwrap_t<T_wrapped_dataset>; | |||||
| template<typename T_type> | |||||
| constexpr decltype(auto) operator()(T_type&&) const | |||||
| { | |||||
| using type = misc::unwrap_t<T_type>; | |||||
| return hana::bool_c< | |||||
| std::is_base_of<type, dataset_type>::value | |||||
| && !std::is_same <type, dataset_type>::value>; | |||||
| } | |||||
| }; | |||||
| template<typename T_schema, typename T_wrapped_dataset> | |||||
| constexpr decltype(auto) operator()(T_schema&& schema, T_wrapped_dataset&& wrapped_dataset) const | |||||
| { | |||||
| auto all_types = hana::transform( | |||||
| schema.tables, | |||||
| table::get_wrapped_dataset); | |||||
| auto base_type = hana::find_if( | |||||
| all_types, | |||||
| is_base_pred<T_wrapped_dataset> { }); | |||||
| return hana::eval_if( | |||||
| base_type != hana::nothing, | |||||
| [&](auto _){ | |||||
| return schema_get_root_base_type_impl { }(schema, _(base_type).value()); | |||||
| }, | |||||
| [&]{ | |||||
| return wrapped_dataset; | |||||
| }); | |||||
| } | |||||
| }; | |||||
| } | |||||
| constexpr decltype(auto) get_root_base_type = __impl::schema_get_root_base_type_impl { }; | |||||
| /* schema::get_all_derived_types */ | |||||
| namespace __impl | |||||
| { | |||||
| struct schema_get_all_derived_types_impl | |||||
| { | |||||
| template<typename T_wrapped_dataset> | |||||
| struct is_derived_pred | |||||
| { | |||||
| using dataset_type = misc::decay_unwrap_t<T_wrapped_dataset>; | |||||
| template<typename T_type> | |||||
| constexpr decltype(auto) operator()(T_type&&) const | |||||
| { | |||||
| return hana::bool_c< | |||||
| std::is_base_of<dataset_type, misc::unwrap_t<T_type>>::value>; | |||||
| } | |||||
| }; | |||||
| template<typename T_schema, typename T_wrapped_dataset> | |||||
| constexpr decltype(auto) operator()(T_schema&& schema, T_wrapped_dataset&&) const | |||||
| { | |||||
| auto all_types = hana::transform( | |||||
| schema.tables, | |||||
| table::get_wrapped_dataset); | |||||
| auto derived_types = hana::filter( | |||||
| all_types, | |||||
| is_derived_pred<T_wrapped_dataset> { }); | |||||
| return derived_types; | |||||
| } | |||||
| }; | |||||
| } | |||||
| constexpr decltype(auto) get_all_derived_types = __impl::schema_get_all_derived_types_impl { }; | |||||
| /* schema::get_derived_types */ | |||||
| namespace __impl | |||||
| { | |||||
| struct schema_get_derived_types_impl | |||||
| { | |||||
| struct has_base_impl | |||||
| { | |||||
| template<typename T_schema, typename T_base_type, typename T_type> | |||||
| constexpr decltype(auto) operator()(T_schema&& schema, T_base_type& base_type, T_type&& type) const | |||||
| { return get_base_type(schema, type) == base_type; } | |||||
| }; | |||||
| /* make */ | |||||
| static constexpr decltype(auto) has_base = has_base_impl { }; | |||||
| constexpr decltype(auto) make_schema = misc::make_generic_predicate<__impl::schema_builder> { }; | |||||
| template<typename T_schema, typename T_wrapped_dataset> | |||||
| constexpr decltype(auto) operator()(T_schema&& schema, T_wrapped_dataset&& wrapped_dataset) const | |||||
| { | |||||
| using wrapped_datasets_type = mp::decay_t<decltype( | |||||
| hana::transform( | |||||
| std::declval<T_schema>().tables, | |||||
| schema::table::get_wrapped_dataset))>; | |||||
| using derived_wrapped_datasets_type = mp::decay_t<decltype( | |||||
| hana::filter( | |||||
| std::declval<wrapped_datasets_type>(), | |||||
| hana::partial( | |||||
| has_base, | |||||
| std::declval<T_schema>(), | |||||
| wrapped_dataset)))>; | |||||
| return derived_wrapped_datasets_type { }; | |||||
| } | |||||
| }; | |||||
| } | |||||
| constexpr decltype(auto) get_derived_types = __impl::schema_get_derived_types_impl { }; | |||||
| } | } | ||||
| end_namespace_cpphibernate_schema | end_namespace_cpphibernate_schema | ||||
| @@ -152,14 +152,15 @@ beg_namespace_cpphibernate_schema | |||||
| constexpr decltype(auto) make_setter_lambda(T_lambda&& lambda, boost::hana::basic_type<T_dataset>, boost::hana::basic_type<T_value>) | constexpr decltype(auto) make_setter_lambda(T_lambda&& lambda, boost::hana::basic_type<T_dataset>, boost::hana::basic_type<T_value>) | ||||
| { return __impl::setter_lambda_t<T_dataset, T_value, T_lambda>(std::forward<T_lambda>(lambda)); } | { return __impl::setter_lambda_t<T_dataset, T_value, T_lambda>(std::forward<T_lambda>(lambda)); } | ||||
| /* operations */ | |||||
| namespace __impl | namespace __impl | ||||
| { | { | ||||
| /* setter_buildser */ | |||||
| /* setter_make_impl */ | |||||
| template<typename X, typename = void> | template<typename X, typename = void> | ||||
| struct setter_builder | |||||
| struct setter_make_impl | |||||
| { | { | ||||
| template<typename... Args> | template<typename... Args> | ||||
| static constexpr decltype(auto) apply(Args&&...) | static constexpr decltype(auto) apply(Args&&...) | ||||
| @@ -167,40 +168,43 @@ beg_namespace_cpphibernate_schema | |||||
| }; | }; | ||||
| template<typename T_dataset, typename T_value> | template<typename T_dataset, typename T_value> | ||||
| struct setter_builder<mp::list<T_value T_dataset::*>, void> | |||||
| struct setter_make_impl<mp::list<T_value T_dataset::*>, void> | |||||
| { | { | ||||
| static constexpr decltype(auto) apply(T_value T_dataset::*member) | static constexpr decltype(auto) apply(T_value T_dataset::*member) | ||||
| { return make_setter_member_var(member); } | { return make_setter_member_var(member); } | ||||
| }; | }; | ||||
| template<typename T_dataset, typename T_value> | template<typename T_dataset, typename T_value> | ||||
| struct setter_builder<mp::list<T_value (T_dataset::*)(void)>, void> | |||||
| struct setter_make_impl<mp::list<T_value (T_dataset::*)(void)>, void> | |||||
| { | { | ||||
| static constexpr decltype(auto) apply(T_value (T_dataset::*member)(void)) | static constexpr decltype(auto) apply(T_value (T_dataset::*member)(void)) | ||||
| { return make_setter_member_func(member); } | { return make_setter_member_func(member); } | ||||
| }; | }; | ||||
| template<typename T_dataset, typename T_value> | template<typename T_dataset, typename T_value> | ||||
| struct setter_builder<mp::list<T_value (T_dataset::*)(void) const>, void> | |||||
| struct setter_make_impl<mp::list<T_value (T_dataset::*)(void) const>, void> | |||||
| { | { | ||||
| static constexpr decltype(auto) apply(T_value (T_dataset::*member)(void) const) | static constexpr decltype(auto) apply(T_value (T_dataset::*member)(void) const) | ||||
| { return make_setter_member_func(member); } | { return make_setter_member_func(member); } | ||||
| }; | }; | ||||
| template<typename T_func, typename T_dataset_type, typename T_value_type> | |||||
| struct setter_builder<mp::list<T_func, T_dataset_type, T_value_type>, mp::enable_if_c< | |||||
| hana::is_a<hana::type_tag, mp::clean_type<T_dataset_type>> | |||||
| && hana::is_a<hana::type_tag, mp::clean_type<T_value_type>>>> | |||||
| template<typename T_func, typename T_wrapped_dataset, typename T_value_type> | |||||
| struct setter_make_impl<mp::list<T_func, T_wrapped_dataset, T_value_type>, mp::enable_if_c< | |||||
| hana::is_a<hana::type_tag, mp::decay_t<T_wrapped_dataset>> | |||||
| && hana::is_a<hana::type_tag, mp::decay_t<T_value_type>>>> | |||||
| { | { | ||||
| static constexpr decltype(auto) apply(T_func&& func, T_dataset_type&& dataset_type, T_value_type&& value_type) | |||||
| { return make_setter_lambda(std::forward<T_func>(func), std::forward<T_dataset_type>(dataset_type), std::forward<T_value_type>(value_type)); } | |||||
| static constexpr decltype(auto) apply(T_func&& func, T_wrapped_dataset&& wrapped_dataset, T_value_type&& value_type) | |||||
| { return make_setter_lambda(std::forward<T_func>(func), std::forward<T_wrapped_dataset>(wrapped_dataset), std::forward<T_value_type>(value_type)); } | |||||
| }; | }; | ||||
| } | } | ||||
| /* make */ | |||||
| namespace setter | |||||
| { | |||||
| constexpr decltype(auto) make_setter = misc::make_generic_predicate<__impl::setter_builder> { }; | |||||
| constexpr decltype(auto) make = misc::make_generic_predicate<__impl::setter_make_impl> { }; | |||||
| } | |||||
| } | } | ||||
| end_namespace_cpphibernate_schema | end_namespace_cpphibernate_schema | ||||
| @@ -4,6 +4,7 @@ | |||||
| #include <cpphibernate/misc/wrap.h> | #include <cpphibernate/misc/wrap.h> | ||||
| #include <cpphibernate/misc/general.h> | #include <cpphibernate/misc/general.h> | ||||
| #include <cpphibernate/schema/fields.h> | #include <cpphibernate/schema/fields.h> | ||||
| #include <cpphibernate/schema/attribute.h> | |||||
| beg_namespace_cpphibernate_schema | beg_namespace_cpphibernate_schema | ||||
| { | { | ||||
| @@ -13,27 +14,27 @@ beg_namespace_cpphibernate_schema | |||||
| /* table_t */ | /* table_t */ | ||||
| template<typename T_name, typename T_dataset_wrapped, typename T_table_id, typename T_fields> | |||||
| template<typename T_name, typename T_wrapped_dataset, typename T_table_id, typename T_fields> | |||||
| struct table_t | struct table_t | ||||
| { | { | ||||
| using name_type = T_name; | using name_type = T_name; | ||||
| using dataset_wrapped_type = mp::decay_t<T_dataset_wrapped>; | |||||
| using wrapped_dataset_type = mp::decay_t<T_wrapped_dataset>; | |||||
| using table_id_type = T_table_id; | using table_id_type = T_table_id; | ||||
| using fields_type = T_fields; | using fields_type = T_fields; | ||||
| using this_type = table_t<name_type, dataset_wrapped_type, table_id_type, fields_type>; | |||||
| using this_type = table_t<name_type, wrapped_dataset_type, table_id_type, fields_type>; | |||||
| name_type name; | name_type name; | ||||
| dataset_wrapped_type dataset_wrapped; | |||||
| wrapped_dataset_type wrapped_dataset; | |||||
| table_id_type table_id; | table_id_type table_id; | ||||
| fields_type fields; | fields_type fields; | ||||
| constexpr table_t( | constexpr table_t( | ||||
| T_name p_name, | T_name p_name, | ||||
| T_dataset_wrapped p_dataset_wrapped, | |||||
| T_wrapped_dataset p_wrapped_dataset, | |||||
| T_table_id p_table_id, | T_table_id p_table_id, | ||||
| T_fields p_fields) | T_fields p_fields) | ||||
| : name (std::forward<T_name> (p_name)) | : name (std::forward<T_name> (p_name)) | ||||
| , dataset_wrapped (std::forward<T_dataset_wrapped>(p_dataset_wrapped)) | |||||
| , wrapped_dataset (std::forward<T_wrapped_dataset>(p_wrapped_dataset)) | |||||
| , table_id (std::forward<T_table_id> (p_table_id)) | , table_id (std::forward<T_table_id> (p_table_id)) | ||||
| , fields (std::forward<T_fields> (p_fields)) | , fields (std::forward<T_fields> (p_fields)) | ||||
| { } | { } | ||||
| @@ -50,7 +51,7 @@ beg_namespace_cpphibernate_schema | |||||
| os << indent << '{' | os << indent << '{' | ||||
| << incindent | << incindent | ||||
| << indent << "\"name\": \"" << name << "\"," | << indent << "\"name\": \"" << name << "\"," | ||||
| << indent << "\"dataset_wrapped\": \"" << utl::type_helper<misc::decay_unwrap_t<dataset_wrapped_type>>::name() << "\"" | |||||
| << indent << "\"wrapped_dataset\": \"" << utl::type_helper<misc::decay_unwrap_t<wrapped_dataset_type>>::name() << "\"" | |||||
| << indent << "\"table_id\": \"" << hana::value(table_id) << "\"" | << indent << "\"table_id\": \"" << hana::value(table_id) << "\"" | ||||
| << indent << "\"fields\": " | << indent << "\"fields\": " | ||||
| << indent << '[' | << indent << '[' | ||||
| @@ -66,44 +67,123 @@ beg_namespace_cpphibernate_schema | |||||
| } | } | ||||
| }; | }; | ||||
| /* table_builder */ | |||||
| } | |||||
| /* meta */ | |||||
| template<typename T> | |||||
| struct is_table | |||||
| : public mp::is_specialization_of<T, __impl::table_t> | |||||
| { }; | |||||
| template<typename... T> | |||||
| struct all_are_tables | |||||
| : mp::all_true<is_table<T>::value...> | |||||
| { }; | |||||
| /* operations */ | |||||
| namespace __impl | |||||
| { | |||||
| /* table_make_impl */ | |||||
| template <typename X, typename = void> | template <typename X, typename = void> | ||||
| struct table_builder | |||||
| struct table_make_impl | |||||
| { | { | ||||
| template <typename... T_args> | template <typename... T_args> | ||||
| static constexpr decltype(auto) apply(T_args&&... args) | static constexpr decltype(auto) apply(T_args&&... args) | ||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::make_table(...)!"); } | |||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::table::make(...)!"); } | |||||
| }; | }; | ||||
| template<typename T_name, typename T_dataset_wrapped, typename T_id, typename T_fields> | |||||
| struct table_builder<mp::list<T_name, T_dataset_wrapped, T_id, T_fields>, mp::enable_if_c< | |||||
| hana::is_a<hana::type_tag, T_dataset_wrapped> | |||||
| template<typename T_name, typename T_wrapped_dataset, typename T_id, typename T_fields> | |||||
| struct table_make_impl<mp::list<T_name, T_wrapped_dataset, T_id, T_fields>, mp::enable_if_c< | |||||
| hana::is_a<hana::type_tag, T_wrapped_dataset> | |||||
| && is_fields<mp::decay_t<T_fields>>::value>> | && is_fields<mp::decay_t<T_fields>>::value>> | ||||
| { | { | ||||
| static constexpr decltype(auto) apply(T_name&& name, T_dataset_wrapped&& dataset_wrapped, T_id&& id, T_fields&& fields) | |||||
| static constexpr decltype(auto) apply(T_name&& name, T_wrapped_dataset&& wrapped_dataset, T_id&& id, T_fields&& fields) | |||||
| { | { | ||||
| return table_t<T_name, T_dataset_wrapped, T_id, T_fields>( | |||||
| return table_t<T_name, T_wrapped_dataset, T_id, T_fields>( | |||||
| std::forward<T_name> (name), | std::forward<T_name> (name), | ||||
| std::forward<T_dataset_wrapped> (dataset_wrapped), | |||||
| std::forward<T_wrapped_dataset> (wrapped_dataset), | |||||
| std::forward<T_id> (id), | std::forward<T_id> (id), | ||||
| std::forward<T_fields> (fields)); | std::forward<T_fields> (fields)); | ||||
| } | } | ||||
| }; | }; | ||||
| /* table_get_wrapped_dataset_impl */ | |||||
| struct table_get_wrapped_dataset_impl | |||||
| { | |||||
| template<typename T_table> | |||||
| constexpr decltype(auto) operator()(T_table&& table) const | |||||
| { return table.wrapped_dataset; } | |||||
| }; | |||||
| /* table_get_primary_key_field_impl */ | |||||
| template<typename X, typename = void> | |||||
| struct table_get_primary_key_field_impl | |||||
| { | |||||
| template <typename... T_args> | |||||
| static constexpr decltype(auto) apply(T_args&&... args) | |||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::table::get_primary_key_field(...)!"); } | |||||
| }; | |||||
| template<typename T_table> | |||||
| struct table_get_primary_key_field_impl< | |||||
| mp::list<T_table>, | |||||
| mp::enable_if_c< | |||||
| is_table<mp::decay_t<T_table>>::value>> | |||||
| { | |||||
| template<size_t I> | |||||
| using is_primary_key_field = decltype(hana::contains( | |||||
| std::declval<T_table>().fields[hana::size_c<I>].attributes, | |||||
| attribute::primary_key)); | |||||
| template<size_t I, size_t N, typename = void> | |||||
| struct helper; | |||||
| template<size_t N> | |||||
| struct helper<N, N, void> | |||||
| { static_assert(N != N, "Unable to find primary key field for table!"); }; | |||||
| template<size_t I, size_t N> | |||||
| struct helper<I, N, mp::enable_if_c< | |||||
| !is_primary_key_field<I>::value>> | |||||
| { | |||||
| static constexpr decltype(auto) apply(T_table&& table) | |||||
| { return helper<I+1, N>::apply(std::forward<T_table>(table)); } | |||||
| }; | |||||
| template<size_t I, size_t N> | |||||
| struct helper<I, N, mp::enable_if_c< | |||||
| is_primary_key_field<I>::value>> | |||||
| { | |||||
| static constexpr decltype(auto) apply(T_table&& table) | |||||
| { return std::forward<T_table>(table).fields[hana::size_c<I>]; } | |||||
| }; | |||||
| static constexpr decltype(auto) apply(T_table&& table) | |||||
| { | |||||
| using count = mp::decay_t<decltype(hana::size(std::declval<T_table>().fields))>; | |||||
| return helper<0, count::value>::apply( | |||||
| std::forward<T_table>(table)); | |||||
| } | |||||
| }; | |||||
| } | } | ||||
| /* meta */ | |||||
| namespace table | |||||
| { | |||||
| template<typename T> | |||||
| struct is_table : mp::is_specialization_of<T, __impl::table_t> { }; | |||||
| constexpr decltype(auto) make = misc::make_generic_predicate<__impl::table_make_impl> { }; | |||||
| template<typename... T> | |||||
| struct all_are_tables : mp::all_true<is_table<T>::value...> { }; | |||||
| constexpr decltype(auto) get_wrapped_dataset = __impl::table_get_wrapped_dataset_impl { }; | |||||
| /* make */ | |||||
| constexpr decltype(auto) get_primary_key_field = misc::make_generic_predicate<__impl::table_get_primary_key_field_impl> { }; | |||||
| constexpr decltype(auto) make_table = misc::make_generic_predicate<__impl::table_builder> { }; | |||||
| } | |||||
| } | } | ||||
| end_namespace_cpphibernate_schema | end_namespace_cpphibernate_schema | ||||
| @@ -27,36 +27,94 @@ beg_namespace_cpphibernate_schema | |||||
| : mp::c_true_t | : mp::c_true_t | ||||
| { }; | { }; | ||||
| /* tables_builder */ | |||||
| } | |||||
| /* meta */ | |||||
| template<typename T> | |||||
| struct is_tables | |||||
| : public __impl::is_tables_impl<T> | |||||
| { }; | |||||
| /* operations */ | |||||
| namespace __impl | |||||
| { | |||||
| /* tables_make_impl */ | |||||
| template <typename X, typename = void> | template <typename X, typename = void> | ||||
| struct tables_builder | |||||
| struct tables_make_impl | |||||
| { | { | ||||
| template <typename... T_args> | template <typename... T_args> | ||||
| static constexpr decltype(auto) apply(T_args&&... args) | static constexpr decltype(auto) apply(T_args&&... args) | ||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::make_tables(...)!"); } | |||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::tables::make(...)!"); } | |||||
| }; | }; | ||||
| template<typename... T> | template<typename... T> | ||||
| struct tables_builder<mp::list<T...>, mp::enable_if<all_are_tables<T...>>> | |||||
| struct tables_make_impl<mp::list<T...>, mp::enable_if<all_are_tables<T...>>> | |||||
| { | { | ||||
| template <typename ...T_tables> | template <typename ...T_tables> | ||||
| static constexpr decltype(auto) apply(T_tables&&... tables) | static constexpr decltype(auto) apply(T_tables&&... tables) | ||||
| { return tables_t<T_tables...>(std::forward<T_tables>(tables)...); } | { return tables_t<T_tables...>(std::forward<T_tables>(tables)...); } | ||||
| }; | }; | ||||
| /* tables_find_impl */ | |||||
| template<typename X, typename = void> | |||||
| struct tables_find_impl | |||||
| { | |||||
| template<typename... T_args> | |||||
| static constexpr decltype(auto) apply(T_args&&... args) | |||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::tables::find(...)!"); } | |||||
| }; | |||||
| template<typename T_tables, typename T_wrapped_dataset> | |||||
| struct tables_find_impl< | |||||
| mp::list<T_tables, T_wrapped_dataset>, | |||||
| mp::enable_if_c< | |||||
| is_tables<mp::decay_t<T_tables>>::value>> | |||||
| { | |||||
| template<size_t I, size_t N, typename = void> | |||||
| struct helper; | |||||
| template<size_t N> | |||||
| struct helper<N, N, void> | |||||
| { static_assert(N != N, "Table for given datatype does not exist!"); }; | |||||
| template<size_t I, size_t N> | |||||
| struct helper<I, N, mp::enable_if_c< | |||||
| decltype(hana::not_equal(std::declval<T_tables>()[hana::size_c<I>].wrapped_dataset, T_wrapped_dataset { }))::value>> | |||||
| { | |||||
| static constexpr decltype(auto) apply(T_tables&& tables) | |||||
| { return helper<I+1, N>::apply(std::forward<T_tables>(tables)); } | |||||
| }; | |||||
| template<size_t I, size_t N> | |||||
| struct helper<I, N, mp::enable_if_c< | |||||
| decltype(hana::equal(std::declval<T_tables>()[hana::size_c<I>].wrapped_dataset, T_wrapped_dataset { }))::value>> | |||||
| { | |||||
| static constexpr decltype(auto) apply(T_tables&& tables) | |||||
| { return std::forward<T_tables>(tables)[hana::size_c<I>]; } | |||||
| }; | |||||
| static constexpr decltype(auto) apply(T_tables&& tables, T_wrapped_dataset&&) | |||||
| { | |||||
| using count_type = mp::decay_t<decltype(hana::size(std::declval<T_tables>()))>; | |||||
| return helper<0, count_type::value>::apply(std::forward<T_tables>(tables)); | |||||
| } | |||||
| }; | |||||
| } | } | ||||
| /* meta */ | |||||
| namespace tables | |||||
| { | |||||
| template<typename T> | |||||
| struct is_tables | |||||
| : public __impl::is_tables_impl<T> | |||||
| { }; | |||||
| constexpr decltype(auto) make = misc::make_generic_predicate<__impl::tables_make_impl> { }; | |||||
| /* make */ | |||||
| constexpr decltype(auto) find = misc::make_generic_predicate<__impl::tables_find_impl> { }; | |||||
| constexpr decltype(auto) make_tables = misc::make_generic_predicate<__impl::tables_builder> { }; | |||||
| } | |||||
| } | } | ||||
| end_namespace_cpphibernate_schema | end_namespace_cpphibernate_schema | ||||
| @@ -14,6 +14,7 @@ Set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PEDANTIC_CXX | |||||
| # Dependencies #################################################################################### | # Dependencies #################################################################################### | ||||
| Find_Package ( cpputils REQUIRED ) | Find_Package ( cpputils REQUIRED ) | ||||
| Find_Package ( cppmariadb REQUIRED ) | |||||
| # Project: cpphibernate ############################################################################### | # Project: cpphibernate ############################################################################### | ||||
| @@ -27,6 +28,7 @@ Target_Include_Directories ( | |||||
| Target_Link_Libraries ( | Target_Link_Libraries ( | ||||
| cpphibernate | cpphibernate | ||||
| cpputils | cpputils | ||||
| cppmariadb | |||||
| ) | ) | ||||
| If ( __COTIRE_INCLUDED ) | If ( __COTIRE_INCLUDED ) | ||||
| Cotire ( cpphibernate ) | Cotire ( cpphibernate ) | ||||
| @@ -0,0 +1,15 @@ | |||||
| #include <string> | |||||
| #include <iostream> | |||||
| #include <cpphibernate/driver/mariadb/schema/schema.h> | |||||
| using namespace ::cpphibernate::driver::mariadb_impl; | |||||
| void schema_t::update() | |||||
| { | |||||
| } | |||||
| void schema_t::print(std::ostream& os) const | |||||
| { | |||||
| os << "fuu" << std::endl; | |||||
| } | |||||
| @@ -1,5 +1,6 @@ | |||||
| #include <gtest/gtest.h> | #include <gtest/gtest.h> | ||||
| #include <cpphibernate.h> | #include <cpphibernate.h> | ||||
| #include <cpphibernate/driver/mariadb.h> | |||||
| using namespace ::cpphibernate; | using namespace ::cpphibernate; | ||||
| @@ -124,5 +125,7 @@ constexpr decltype(auto) test_schema = cpphibernate_make_schema( | |||||
| TEST(CppHibernateTests, fuuu) | TEST(CppHibernateTests, fuuu) | ||||
| { | { | ||||
| std::cout << test_schema << std::endl; | |||||
| ::cppmariadb::connection connection(reinterpret_cast<MYSQL*>(0x1234)); | |||||
| auto context = make_context<driver::mariadb>(test_schema, connection); | |||||
| std::cout << context.schema() << std::endl; | |||||
| } | } | ||||
| @@ -0,0 +1,77 @@ | |||||
| #include "mariadb_mock.h" | |||||
| MariaDbMock* mariadb_mock_instance; | |||||
| void MariaDbMock::setInstance(MariaDbMock* value) | |||||
| { | |||||
| mariadb_mock_instance = value; | |||||
| } | |||||
| void MariaDbMock::clearInstance(MariaDbMock* value) | |||||
| { | |||||
| if (mariadb_mock_instance == value) | |||||
| mariadb_mock_instance = nullptr; | |||||
| } | |||||
| my_ulonglong STDCALL mysql_num_rows (MYSQL_RES *res) | |||||
| { return (mariadb_mock_instance ? mariadb_mock_instance->mysql_num_rows(res) : 0); } | |||||
| unsigned int STDCALL mysql_num_fields (MYSQL_RES *res) | |||||
| { return (mariadb_mock_instance ? mariadb_mock_instance->mysql_num_fields(res) : 0); } | |||||
| MYSQL_ROWS* STDCALL mysql_row_tell (MYSQL_RES *res) | |||||
| { return (mariadb_mock_instance ? mariadb_mock_instance->mysql_row_tell(res) : nullptr); } | |||||
| void STDCALL mysql_free_result (MYSQL_RES *res) | |||||
| { if (mariadb_mock_instance) mariadb_mock_instance->mysql_free_result(res); } | |||||
| MYSQL_ROW_OFFSET STDCALL mysql_row_seek (MYSQL_RES *res, MYSQL_ROW_OFFSET offset) | |||||
| { return (mariadb_mock_instance ? mariadb_mock_instance->mysql_row_seek(res, offset) : nullptr); } | |||||
| void STDCALL mysql_data_seek (MYSQL_RES *res, unsigned long long offset) | |||||
| { if (mariadb_mock_instance) mariadb_mock_instance->mysql_data_seek(res, offset); } | |||||
| unsigned long* STDCALL mysql_fetch_lengths (MYSQL_RES *res) | |||||
| { return (mariadb_mock_instance ? mariadb_mock_instance->mysql_fetch_lengths(res) : nullptr); } | |||||
| MYSQL_ROW STDCALL mysql_fetch_row (MYSQL_RES *res) | |||||
| { return (mariadb_mock_instance ? mariadb_mock_instance->mysql_fetch_row(res) : nullptr); } | |||||
| MYSQL_FIELD* STDCALL mysql_fetch_fields (MYSQL_RES *res) | |||||
| { return (mariadb_mock_instance ? mariadb_mock_instance->mysql_fetch_fields(res) : nullptr); } | |||||
| int STDCALL mysql_real_query (MYSQL *mysql, const char *q, unsigned long length) | |||||
| { return (mariadb_mock_instance ? mariadb_mock_instance->mysql_real_query(mysql, q, length) : 0); } | |||||
| unsigned int STDCALL mysql_errno (MYSQL *mysql) | |||||
| { return (mariadb_mock_instance ? mariadb_mock_instance->mysql_errno(mysql) : 0); } | |||||
| const char* STDCALL mysql_error (MYSQL *mysql) | |||||
| { return (mariadb_mock_instance ? mariadb_mock_instance->mysql_error(mysql) : nullptr); } | |||||
| MYSQL_RES* STDCALL mysql_store_result (MYSQL *mysql) | |||||
| { return (mariadb_mock_instance ? mariadb_mock_instance->mysql_store_result(mysql) : nullptr); } | |||||
| MYSQL_RES* STDCALL mysql_use_result (MYSQL *mysql) | |||||
| { return (mariadb_mock_instance ? mariadb_mock_instance->mysql_use_result(mysql) : nullptr); } | |||||
| unsigned int STDCALL mysql_field_count (MYSQL *mysql) | |||||
| { return (mariadb_mock_instance ? mariadb_mock_instance->mysql_field_count(mysql) : 0); } | |||||
| my_ulonglong STDCALL mysql_affected_rows (MYSQL *mysql) | |||||
| { return (mariadb_mock_instance ? mariadb_mock_instance->mysql_affected_rows(mysql) : 0); } | |||||
| my_ulonglong STDCALL mysql_insert_id (MYSQL *mysql) | |||||
| { return (mariadb_mock_instance ? mariadb_mock_instance->mysql_insert_id(mysql) : 0); } | |||||
| unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, unsigned long length) | |||||
| { return (mariadb_mock_instance ? mariadb_mock_instance->mysql_real_escape_string(mysql, to, from, length) : 0); } | |||||
| void STDCALL mysql_close (MYSQL *mysql) | |||||
| { if (mariadb_mock_instance) mariadb_mock_instance->mysql_close(mysql); } | |||||
| MYSQL* STDCALL mysql_real_connect (MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag) | |||||
| { return (mariadb_mock_instance ? mariadb_mock_instance->mysql_real_connect(mysql, host, user, passwd, db, port, unix_socket, clientflag) : nullptr); } | |||||
| MYSQL* STDCALL mysql_init (MYSQL *mysql) | |||||
| { return (mariadb_mock_instance ? mariadb_mock_instance->mysql_init(mysql) : nullptr); } | |||||
| @@ -0,0 +1,121 @@ | |||||
| #pragma once | |||||
| #include <gmock/gmock.h> | |||||
| #include <mariadb/errmsg.h> | |||||
| #include <mariadb/mysqld_error.h> | |||||
| #include <mariadb/mysql.h> | |||||
| #define MARIADB_MOCK | |||||
| #if !defined(_WIN32) | |||||
| #define STDCALL | |||||
| #else | |||||
| #define STDCALL __stdcall | |||||
| #endif | |||||
| #define NOT_NULL_FLAG 1 /* field can't be NULL */ | |||||
| #define PRI_KEY_FLAG 2 /* field is part of a primary key */ | |||||
| #define UNIQUE_KEY_FLAG 4 /* field is part of a unique key */ | |||||
| #define MULTIPLE_KEY_FLAG 8 /* field is part of a key */ | |||||
| #define BLOB_FLAG 16 /* field is a blob */ | |||||
| #define UNSIGNED_FLAG 32 /* field is unsigned */ | |||||
| #define ZEROFILL_FLAG 64 /* field is zerofill */ | |||||
| #define BINARY_FLAG 128 | |||||
| #define ENUM_FLAG 256 /* field is an enum */ | |||||
| #define AUTO_INCREMENT_FLAG 512 /* field is a autoincrement field */ | |||||
| #define TIMESTAMP_FLAG 1024 /* field is a timestamp */ | |||||
| #define SET_FLAG 2048 /* field is a set */ | |||||
| #define NO_DEFAULT_VALUE_FLAG 4096 /* field doesn't have default value */ | |||||
| #define ON_UPDATE_NOW_FLAG 8192 /* field is set to NOW on UPDATE */ | |||||
| #define NUM_FLAG 32768 /* field is num (for clients) */ | |||||
| #define PART_KEY_FLAG 16384 /* Intern; Part of some key */ | |||||
| #define GROUP_FLAG 32768 /* Intern: Group field */ | |||||
| #define UNIQUE_FLAG 65536 /* Intern: Used by sql_yacc */ | |||||
| #define CLIENT_MYSQL 1 | |||||
| #define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */ | |||||
| #define CLIENT_LONG_FLAG 4 /* Get all column flags */ | |||||
| #define CLIENT_CONNECT_WITH_DB 8 /* One can specify db on connect */ | |||||
| #define CLIENT_NO_SCHEMA 16 /* Don't allow database.table.column */ | |||||
| #define CLIENT_COMPRESS 32 /* Can use compression protocol */ | |||||
| #define CLIENT_ODBC 64 /* Odbc client */ | |||||
| #define CLIENT_LOCAL_FILES 128 /* Can use LOAD DATA LOCAL */ | |||||
| #define CLIENT_IGNORE_SPACE 256 /* Ignore spaces before '(' */ | |||||
| #define CLIENT_INTERACTIVE 1024 /* This is an interactive client */ | |||||
| #define CLIENT_SSL 2048 /* Switch to SSL after handshake */ | |||||
| #define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */ | |||||
| #define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */ | |||||
| #define CLIENT_PROTOCOL_41 512 | |||||
| #define CLIENT_RESERVED 16384 | |||||
| #define CLIENT_SECURE_CONNECTION 32768 | |||||
| #define CLIENT_MULTI_STATEMENTS (1UL << 16) | |||||
| #define CLIENT_MULTI_RESULTS (1UL << 17) | |||||
| #define CLIENT_PS_MULTI_RESULTS (1UL << 18) | |||||
| #define CLIENT_PLUGIN_AUTH (1UL << 19) | |||||
| #define CLIENT_CONNECT_ATTRS (1UL << 20) | |||||
| #define CLIENT_SESSION_TRACKING (1UL << 23) | |||||
| #define CLIENT_PROGRESS (1UL << 29) | |||||
| #define CLIENT_PROGRESS_OBSOLETE CLIENT_PROGRESS | |||||
| #define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30) | |||||
| #define CLIENT_REMEMBER_OPTIONS (1UL << 31) | |||||
| struct MariaDbMock | |||||
| { | |||||
| private: | |||||
| static void setInstance(MariaDbMock* value); | |||||
| static void clearInstance(MariaDbMock* value); | |||||
| public: | |||||
| MOCK_METHOD1(mysql_num_rows, my_ulonglong (MYSQL_RES *res)); | |||||
| MOCK_METHOD1(mysql_num_fields, unsigned int (MYSQL_RES *res)); | |||||
| MOCK_METHOD1(mysql_row_tell, MYSQL_ROWS* (MYSQL_RES *res)); | |||||
| MOCK_METHOD1(mysql_free_result, void (MYSQL_RES *res)); | |||||
| MOCK_METHOD2(mysql_row_seek, MYSQL_ROW_OFFSET(MYSQL_RES *res, MYSQL_ROW_OFFSET)); | |||||
| MOCK_METHOD2(mysql_data_seek, void (MYSQL_RES *res, unsigned long long offset)); | |||||
| MOCK_METHOD1(mysql_fetch_lengths, unsigned long* (MYSQL_RES *res)); | |||||
| MOCK_METHOD1(mysql_fetch_row, MYSQL_ROW (MYSQL_RES *res)); | |||||
| MOCK_METHOD1(mysql_fetch_fields, MYSQL_FIELD* (MYSQL_RES *res)); | |||||
| MOCK_METHOD3(mysql_real_query, int (MYSQL *mysql, const char *q, unsigned long length)); | |||||
| MOCK_METHOD1(mysql_errno, unsigned int (MYSQL *mysql)); | |||||
| MOCK_METHOD1(mysql_error, const char* (MYSQL *mysql)); | |||||
| MOCK_METHOD1(mysql_store_result, MYSQL_RES* (MYSQL *mysql)); | |||||
| MOCK_METHOD1(mysql_use_result, MYSQL_RES* (MYSQL *mysql)); | |||||
| MOCK_METHOD1(mysql_field_count, unsigned int (MYSQL *mysql)); | |||||
| MOCK_METHOD1(mysql_affected_rows, my_ulonglong (MYSQL *mysql)); | |||||
| MOCK_METHOD1(mysql_insert_id, my_ulonglong (MYSQL *mysql)); | |||||
| MOCK_METHOD4(mysql_real_escape_string, unsigned long (MYSQL *mysql, char *to, const char *from, unsigned long length)); | |||||
| MOCK_METHOD1(mysql_close, void (MYSQL *mysql)); | |||||
| MOCK_METHOD8(mysql_real_connect, MYSQL* (MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag)); | |||||
| MOCK_METHOD1(mysql_init, MYSQL* (MYSQL *mysql)); | |||||
| MariaDbMock() | |||||
| { setInstance(this); } | |||||
| ~MariaDbMock() | |||||
| { clearInstance(this); } | |||||
| }; | |||||
| my_ulonglong STDCALL mysql_num_rows (MYSQL_RES *res); | |||||
| unsigned int STDCALL mysql_num_fields (MYSQL_RES *res); | |||||
| MYSQL_ROWS* STDCALL mysql_row_tell (MYSQL_RES *res); | |||||
| void STDCALL mysql_free_result (MYSQL_RES *res); | |||||
| MYSQL_ROW_OFFSET STDCALL mysql_row_seek (MYSQL_RES *res, MYSQL_ROW_OFFSET); | |||||
| void STDCALL mysql_data_seek (MYSQL_RES *res, unsigned long long offset); | |||||
| unsigned long* STDCALL mysql_fetch_lengths (MYSQL_RES *res); | |||||
| MYSQL_ROW STDCALL mysql_fetch_row (MYSQL_RES *res); | |||||
| MYSQL_FIELD* STDCALL mysql_fetch_fields (MYSQL_RES *res); | |||||
| int STDCALL mysql_real_query (MYSQL *mysql, const char *q, unsigned long length); | |||||
| unsigned int STDCALL mysql_errno (MYSQL *mysql); | |||||
| const char* STDCALL mysql_error (MYSQL *mysql); | |||||
| MYSQL_RES* STDCALL mysql_store_result (MYSQL *mysql); | |||||
| MYSQL_RES* STDCALL mysql_use_result (MYSQL *mysql); | |||||
| unsigned int STDCALL mysql_field_count (MYSQL *mysql); | |||||
| my_ulonglong STDCALL mysql_affected_rows (MYSQL *mysql); | |||||
| my_ulonglong STDCALL mysql_insert_id (MYSQL *mysql); | |||||
| unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, unsigned long length); | |||||
| void STDCALL mysql_close (MYSQL *mysql); | |||||
| MYSQL* STDCALL mysql_real_connect (MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag); | |||||
| MYSQL* STDCALL mysql_init (MYSQL *mysql); | |||||