@@ -1,6 +1,7 @@ | |||
#pragma once | |||
#include <cpphibernate/config.h> | |||
#include <cpphibernate/context.h> | |||
#include <cpphibernate/misc.h> | |||
#include <cpphibernate/modifier.h> | |||
#include <cpphibernate/schema.h> |
@@ -40,14 +40,20 @@ | |||
#define beg_namespace_cpphibernate 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 | |||
{ | |||
@@ -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 | |||
#include <cpphibernate/config.h> | |||
#include <cpputils/misc/type_helper.h> | |||
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)...); } | |||
}; | |||
/* 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 |
@@ -96,14 +96,6 @@ beg_namespace_cpphibernate_misc | |||
struct real_dataset_impl<std::list<T>, void> | |||
{ 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 */ | |||
@@ -15,7 +15,7 @@ beg_namespace_cpphibernate_modifier | |||
struct where_clause_and_t | |||
: public where_clause_t | |||
{ | |||
using clauses_type = hana::basic_tuple<T_clauses...>; | |||
using clauses_type = hana::tuple<T_clauses...>; | |||
clauses_type clauses; | |||
@@ -15,7 +15,7 @@ beg_namespace_cpphibernate_modifier | |||
struct where_clause_or_t | |||
: public where_clause_t | |||
{ | |||
using clauses_type = hana::basic_tuple<T_clauses...>; | |||
using clauses_type = hana::tuple<T_clauses...>; | |||
clauses_type clauses; | |||
@@ -13,7 +13,7 @@ beg_namespace_cpphibernate_schema | |||
/* attributes_t */ | |||
template<typename... T_attributes> | |||
using attributes_t = hana::basic_tuple<T_attributes...>; | |||
using attributes_t = hana::tuple<T_attributes...>; | |||
/* is_attributes_impl */ | |||
@@ -27,37 +27,47 @@ beg_namespace_cpphibernate_schema | |||
: 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> | |||
struct attributes_builder | |||
struct attributes_make_impl | |||
{ | |||
template<typename... 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> | |||
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>> | |||
{ | |||
template<typename... T_args> | |||
static constexpr decltype(auto) apply(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 |
@@ -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> | |||
struct field_builder | |||
struct field_make_impl | |||
{ | |||
template <typename ...T_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> | |||
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_setter<mp::decay_t<T_setter>>::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 |
@@ -13,7 +13,7 @@ beg_namespace_cpphibernate_schema | |||
/* fields_t */ | |||
template<typename... T_fields> | |||
using fields_t = hana::basic_tuple<T_fields...>; | |||
using fields_t = hana::tuple<T_fields...>; | |||
/* is_fields_impl */ | |||
@@ -27,18 +27,32 @@ beg_namespace_cpphibernate_schema | |||
: 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> | |||
struct fields_builder | |||
struct fields_make_impl | |||
{ | |||
template <typename ...T_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> | |||
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> | |||
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 |
@@ -11,35 +11,22 @@ beg_namespace_cpphibernate_schema | |||
/* getter_t */ | |||
template<typename T_value> | |||
template<typename T_dataset, typename T_value> | |||
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 */ | |||
template<typename T_dataset, typename T_value, typename T_member> | |||
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 dataset_type = T_dataset; | |||
using member_type = T_member; | |||
member_type member; | |||
@@ -61,11 +48,11 @@ beg_namespace_cpphibernate_schema | |||
template<typename T_dataset, typename T_value, typename T_member> | |||
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 dataset_type = T_dataset; | |||
using member_type = T_member; | |||
member_type member; | |||
@@ -87,11 +74,11 @@ beg_namespace_cpphibernate_schema | |||
template<typename T_dataset, typename T_lambda> | |||
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 dataset_type = T_dataset; | |||
using lambda_type = T_lambda; | |||
lambda_type lambda; | |||
@@ -118,7 +105,7 @@ beg_namespace_cpphibernate_schema | |||
template<typename T> | |||
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 | |||
{ }; | |||
@@ -133,9 +120,6 @@ beg_namespace_cpphibernate_schema | |||
/* make */ | |||
constexpr decltype(auto) make_getter_none() | |||
{ return __impl::getter_none_t(); } | |||
template<typename T_dataset, typename T_value> | |||
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); } | |||
@@ -152,55 +136,59 @@ beg_namespace_cpphibernate_schema | |||
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)); } | |||
/* operations */ | |||
namespace __impl | |||
{ | |||
/* getter_buildser */ | |||
/* getter_make_impl */ | |||
template<typename X, typename = void> | |||
struct getter_builder | |||
struct getter_make_impl | |||
{ | |||
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> | |||
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) | |||
{ return make_getter_member_var(member); } | |||
}; | |||
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)) | |||
{ return make_getter_member_func(member); } | |||
}; | |||
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) | |||
{ 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>>>> | |||
{ | |||
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 |
@@ -6,38 +6,38 @@ | |||
#define cpphibernate_make_string(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( \ | |||
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( \ | |||
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( \ | |||
null, \ | |||
member_ptr, \ | |||
"p_id", \ | |||
p_member_ptr, \ | |||
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> | |||
struct schema_builder | |||
struct schema_make_impl | |||
{ | |||
template <typename... T_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> | |||
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) | |||
{ 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 |
@@ -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>) | |||
{ return __impl::setter_lambda_t<T_dataset, T_value, T_lambda>(std::forward<T_lambda>(lambda)); } | |||
/* operations */ | |||
namespace __impl | |||
{ | |||
/* setter_buildser */ | |||
/* setter_make_impl */ | |||
template<typename X, typename = void> | |||
struct setter_builder | |||
struct setter_make_impl | |||
{ | |||
template<typename... Args> | |||
static constexpr decltype(auto) apply(Args&&...) | |||
@@ -167,40 +168,43 @@ beg_namespace_cpphibernate_schema | |||
}; | |||
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) | |||
{ return make_setter_member_var(member); } | |||
}; | |||
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)) | |||
{ return make_setter_member_func(member); } | |||
}; | |||
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) | |||
{ 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 |
@@ -4,6 +4,7 @@ | |||
#include <cpphibernate/misc/wrap.h> | |||
#include <cpphibernate/misc/general.h> | |||
#include <cpphibernate/schema/fields.h> | |||
#include <cpphibernate/schema/attribute.h> | |||
beg_namespace_cpphibernate_schema | |||
{ | |||
@@ -13,27 +14,27 @@ beg_namespace_cpphibernate_schema | |||
/* 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 | |||
{ | |||
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 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; | |||
dataset_wrapped_type dataset_wrapped; | |||
wrapped_dataset_type wrapped_dataset; | |||
table_id_type table_id; | |||
fields_type fields; | |||
constexpr table_t( | |||
T_name p_name, | |||
T_dataset_wrapped p_dataset_wrapped, | |||
T_wrapped_dataset p_wrapped_dataset, | |||
T_table_id p_table_id, | |||
T_fields p_fields) | |||
: 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)) | |||
, fields (std::forward<T_fields> (p_fields)) | |||
{ } | |||
@@ -50,7 +51,7 @@ beg_namespace_cpphibernate_schema | |||
os << indent << '{' | |||
<< incindent | |||
<< 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 << "\"fields\": " | |||
<< 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> | |||
struct table_builder | |||
struct table_make_impl | |||
{ | |||
template <typename... T_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>> | |||
{ | |||
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_dataset_wrapped> (dataset_wrapped), | |||
std::forward<T_wrapped_dataset> (wrapped_dataset), | |||
std::forward<T_id> (id), | |||
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 |
@@ -27,36 +27,94 @@ beg_namespace_cpphibernate_schema | |||
: 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> | |||
struct tables_builder | |||
struct tables_make_impl | |||
{ | |||
template <typename... T_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> | |||
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> | |||
static constexpr decltype(auto) apply(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 |
@@ -14,6 +14,7 @@ Set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PEDANTIC_CXX | |||
# Dependencies #################################################################################### | |||
Find_Package ( cpputils REQUIRED ) | |||
Find_Package ( cppmariadb REQUIRED ) | |||
# Project: cpphibernate ############################################################################### | |||
@@ -27,6 +28,7 @@ Target_Include_Directories ( | |||
Target_Link_Libraries ( | |||
cpphibernate | |||
cpputils | |||
cppmariadb | |||
) | |||
If ( __COTIRE_INCLUDED ) | |||
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 <cpphibernate.h> | |||
#include <cpphibernate/driver/mariadb.h> | |||
using namespace ::cpphibernate; | |||
@@ -124,5 +125,7 @@ constexpr decltype(auto) test_schema = cpphibernate_make_schema( | |||
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); |