Browse Source

* implemented first part of the mariadb driver (internal schema class interface without business logic)

master
bergmann 5 years ago
parent
commit
46de82724f
36 changed files with 1775 additions and 190 deletions
  1. +1
    -0
      include/cpphibernate.h
  2. +12
    -6
      include/cpphibernate/config.h
  3. +122
    -0
      include/cpphibernate/context.h
  4. +12
    -0
      include/cpphibernate/driver/mariadb.h
  5. +34
    -0
      include/cpphibernate/driver/mariadb/mariadb.h
  6. +15
    -0
      include/cpphibernate/driver/mariadb/schema.h
  7. +34
    -0
      include/cpphibernate/driver/mariadb/schema/attributes.fwd.h
  8. +76
    -0
      include/cpphibernate/driver/mariadb/schema/attributes.h
  9. +31
    -0
      include/cpphibernate/driver/mariadb/schema/field.fwd.h
  10. +193
    -0
      include/cpphibernate/driver/mariadb/schema/field.h
  11. +29
    -0
      include/cpphibernate/driver/mariadb/schema/fields.fwd.h
  12. +71
    -0
      include/cpphibernate/driver/mariadb/schema/fields.h
  13. +27
    -0
      include/cpphibernate/driver/mariadb/schema/schema.fwd.h
  14. +61
    -0
      include/cpphibernate/driver/mariadb/schema/schema.h
  15. +31
    -0
      include/cpphibernate/driver/mariadb/schema/table.fwd.h
  16. +194
    -0
      include/cpphibernate/driver/mariadb/schema/table.h
  17. +29
    -0
      include/cpphibernate/driver/mariadb/schema/tables.fwd.h
  18. +69
    -0
      include/cpphibernate/driver/mariadb/schema/tables.h
  19. +13
    -0
      include/cpphibernate/misc/general.h
  20. +0
    -8
      include/cpphibernate/misc/meta.h
  21. +1
    -1
      include/cpphibernate/modifier/where/clauses/and.h
  22. +1
    -1
      include/cpphibernate/modifier/where/clauses/or.h
  23. +24
    -14
      include/cpphibernate/schema/attributes.h
  24. +27
    -17
      include/cpphibernate/schema/field.h
  25. +23
    -13
      include/cpphibernate/schema/fields.h
  26. +31
    -43
      include/cpphibernate/schema/getter.h
  27. +29
    -29
      include/cpphibernate/schema/macros.h
  28. +177
    -10
      include/cpphibernate/schema/schema.h
  29. +17
    -13
      include/cpphibernate/schema/setter.h
  30. +103
    -23
      include/cpphibernate/schema/table.h
  31. +69
    -11
      include/cpphibernate/schema/tables.h
  32. +2
    -0
      src/CMakeLists.txt
  33. +15
    -0
      src/driver/mariadb/schema/schema.cpp
  34. +4
    -1
      test/cpphibernate.cpp
  35. +77
    -0
      test/mariadb_mock.cpp
  36. +121
    -0
      test/mariadb_mock.h

+ 1
- 0
include/cpphibernate.h View File

@@ -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>

+ 12
- 6
include/cpphibernate/config.h View File

@@ -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
{


+ 122
- 0
include/cpphibernate/context.h View File

@@ -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

+ 12
- 0
include/cpphibernate/driver/mariadb.h View File

@@ -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

+ 34
- 0
include/cpphibernate/driver/mariadb/mariadb.h View File

@@ -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

+ 15
- 0
include/cpphibernate/driver/mariadb/schema.h View File

@@ -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>

+ 34
- 0
include/cpphibernate/driver/mariadb/schema/attributes.fwd.h View File

@@ -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

+ 76
- 0
include/cpphibernate/driver/mariadb/schema/attributes.h View File

@@ -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

+ 31
- 0
include/cpphibernate/driver/mariadb/schema/field.fwd.h View File

@@ -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

+ 193
- 0
include/cpphibernate/driver/mariadb/schema/field.h View File

@@ -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

+ 29
- 0
include/cpphibernate/driver/mariadb/schema/fields.fwd.h View File

@@ -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

+ 71
- 0
include/cpphibernate/driver/mariadb/schema/fields.h View File

@@ -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

+ 27
- 0
include/cpphibernate/driver/mariadb/schema/schema.fwd.h View File

@@ -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

+ 61
- 0
include/cpphibernate/driver/mariadb/schema/schema.h View File

@@ -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

+ 31
- 0
include/cpphibernate/driver/mariadb/schema/table.fwd.h View File

@@ -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

+ 194
- 0
include/cpphibernate/driver/mariadb/schema/table.h View File

@@ -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

+ 29
- 0
include/cpphibernate/driver/mariadb/schema/tables.fwd.h View File

@@ -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

+ 69
- 0
include/cpphibernate/driver/mariadb/schema/tables.h View File

@@ -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

+ 13
- 0
include/cpphibernate/misc/general.h View File

@@ -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

+ 0
- 8
include/cpphibernate/misc/meta.h View File

@@ -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 */


+ 1
- 1
include/cpphibernate/modifier/where/clauses/and.h View File

@@ -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;



+ 1
- 1
include/cpphibernate/modifier/where/clauses/or.h View File

@@ -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;



+ 24
- 14
include/cpphibernate/schema/attributes.h View File

@@ -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

+ 27
- 17
include/cpphibernate/schema/field.h View File

@@ -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

+ 23
- 13
include/cpphibernate/schema/fields.h View File

@@ -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

+ 31
- 43
include/cpphibernate/schema/getter.h View File

@@ -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

+ 29
- 29
include/cpphibernate/schema/macros.h View File

@@ -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)

+ 177
- 10
include/cpphibernate/schema/schema.h View File

@@ -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

+ 17
- 13
include/cpphibernate/schema/setter.h View File

@@ -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

+ 103
- 23
include/cpphibernate/schema/table.h View File

@@ -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

+ 69
- 11
include/cpphibernate/schema/tables.h View File

@@ -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

+ 2
- 0
src/CMakeLists.txt View File

@@ -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 )


+ 15
- 0
src/driver/mariadb/schema/schema.cpp View File

@@ -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;
}

+ 4
- 1
test/cpphibernate.cpp View File

@@ -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;
}

+ 77
- 0
test/mariadb_mock.cpp View File

@@ -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); }

+ 121
- 0
test/mariadb_mock.h View File

@@ -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);

Loading…
Cancel
Save