ソースを参照

* Refactored mariadb schema classes

refactoring
bergmann 6年前
コミット
a023dc8178
92個のファイルの変更3629行の追加2410行の削除
  1. +1
    -0
      include/cpphibernate.h
  2. +3
    -0
      include/cpphibernate/context.h
  3. +106
    -0
      include/cpphibernate/context/context.h
  4. +203
    -0
      include/cpphibernate/context/context.inl
  5. +3
    -7
      include/cpphibernate/driver/mariadb.h
  6. +6
    -0
      include/cpphibernate/driver/mariadb/classes.h
  7. +3
    -0
      include/cpphibernate/driver/mariadb/classes/attributes.h
  8. +43
    -0
      include/cpphibernate/driver/mariadb/classes/attributes/attributes.h
  9. +22
    -10
      include/cpphibernate/driver/mariadb/classes/attributes/attributes.inl
  10. +4
    -0
      include/cpphibernate/driver/mariadb/classes/fields.h
  11. +106
    -0
      include/cpphibernate/driver/mariadb/classes/fields/field.h
  12. +126
    -0
      include/cpphibernate/driver/mariadb/classes/fields/field.inl
  13. +39
    -0
      include/cpphibernate/driver/mariadb/classes/fields/field_data.h
  14. +27
    -0
      include/cpphibernate/driver/mariadb/classes/fields/field_data.inl
  15. +39
    -0
      include/cpphibernate/driver/mariadb/classes/fields/field_foreign_table.h
  16. +27
    -0
      include/cpphibernate/driver/mariadb/classes/fields/field_foreign_table.inl
  17. +44
    -0
      include/cpphibernate/driver/mariadb/classes/fields/field_primary_key.h
  18. +33
    -0
      include/cpphibernate/driver/mariadb/classes/fields/field_primary_key.inl
  19. +39
    -0
      include/cpphibernate/driver/mariadb/classes/fields/field_simple.h
  20. +27
    -0
      include/cpphibernate/driver/mariadb/classes/fields/field_simple.inl
  21. +48
    -0
      include/cpphibernate/driver/mariadb/classes/fields/field_value.h
  22. +37
    -0
      include/cpphibernate/driver/mariadb/classes/fields/field_value.inl
  23. +39
    -0
      include/cpphibernate/driver/mariadb/classes/fields/fields.h
  24. +67
    -0
      include/cpphibernate/driver/mariadb/classes/fields/fields.inl
  25. +21
    -0
      include/cpphibernate/driver/mariadb/classes/forward.h
  26. +3
    -0
      include/cpphibernate/driver/mariadb/classes/schema.h
  27. +80
    -0
      include/cpphibernate/driver/mariadb/classes/schema/schema.h
  28. +43
    -0
      include/cpphibernate/driver/mariadb/classes/schema/schema.inl
  29. +4
    -0
      include/cpphibernate/driver/mariadb/classes/tables.h
  30. +115
    -0
      include/cpphibernate/driver/mariadb/classes/tables/table.h
  31. +99
    -0
      include/cpphibernate/driver/mariadb/classes/tables/table.inl
  32. +39
    -0
      include/cpphibernate/driver/mariadb/classes/tables/table_polymorphic.h
  33. +60
    -0
      include/cpphibernate/driver/mariadb/classes/tables/table_polymorphic.inl
  34. +39
    -0
      include/cpphibernate/driver/mariadb/classes/tables/table_simple.h
  35. +27
    -0
      include/cpphibernate/driver/mariadb/classes/tables/table_simple.inl
  36. +38
    -0
      include/cpphibernate/driver/mariadb/classes/tables/tables.h
  37. +67
    -0
      include/cpphibernate/driver/mariadb/classes/tables/tables.inl
  38. +34
    -12
      include/cpphibernate/driver/mariadb/driver.h
  39. +16
    -0
      include/cpphibernate/driver/mariadb/driver.inl
  40. +5
    -4
      include/cpphibernate/driver/mariadb/helper.h
  41. +31
    -32
      include/cpphibernate/driver/mariadb/helper/key_properties.h
  42. +50
    -0
      include/cpphibernate/driver/mariadb/helper/key_properties.inl
  43. +35
    -0
      include/cpphibernate/driver/mariadb/helper/nullable_helper.h
  44. +75
    -0
      include/cpphibernate/driver/mariadb/helper/nullable_helper.inl
  45. +42
    -565
      include/cpphibernate/driver/mariadb/helper/type_properties.h
  46. +563
    -0
      include/cpphibernate/driver/mariadb/helper/type_properties.inl
  47. +0
    -24
      include/cpphibernate/driver/mariadb/schema.h
  48. +0
    -34
      include/cpphibernate/driver/mariadb/schema/attributes.fwd.h
  49. +0
    -23
      include/cpphibernate/driver/mariadb/schema/attributes.h
  50. +0
    -31
      include/cpphibernate/driver/mariadb/schema/field.fwd.h
  51. +0
    -213
      include/cpphibernate/driver/mariadb/schema/field.h
  52. +0
    -228
      include/cpphibernate/driver/mariadb/schema/field.inl
  53. +0
    -29
      include/cpphibernate/driver/mariadb/schema/fields.fwd.h
  54. +0
    -25
      include/cpphibernate/driver/mariadb/schema/fields.h
  55. +0
    -55
      include/cpphibernate/driver/mariadb/schema/fields.inl
  56. +0
    -13
      include/cpphibernate/driver/mariadb/schema/filter.fwd.h
  57. +0
    -54
      include/cpphibernate/driver/mariadb/schema/filter.h
  58. +0
    -122
      include/cpphibernate/driver/mariadb/schema/filter.inl
  59. +0
    -27
      include/cpphibernate/driver/mariadb/schema/schema.fwd.h
  60. +0
    -37
      include/cpphibernate/driver/mariadb/schema/schema.h
  61. +0
    -40
      include/cpphibernate/driver/mariadb/schema/schema.inl
  62. +0
    -31
      include/cpphibernate/driver/mariadb/schema/table.fwd.h
  63. +0
    -208
      include/cpphibernate/driver/mariadb/schema/table.h
  64. +0
    -218
      include/cpphibernate/driver/mariadb/schema/table.inl
  65. +0
    -29
      include/cpphibernate/driver/mariadb/schema/tables.fwd.h
  66. +0
    -23
      include/cpphibernate/driver/mariadb/schema/tables.h
  67. +0
    -55
      include/cpphibernate/driver/mariadb/schema/tables.inl
  68. +37
    -5
      include/cpphibernate/misc/equality_compare.h
  69. +0
    -61
      include/cpphibernate/misc/equality_compare.inl
  70. +33
    -5
      include/cpphibernate/misc/print_container.inl
  71. +61
    -0
      include/cpphibernate/misc/type_helper.h
  72. +75
    -0
      include/cpphibernate/misc/type_helper.inl
  73. +16
    -0
      include/cpphibernate/schema/attribute.h
  74. +80
    -0
      include/cpphibernate/schema/field.h
  75. +30
    -59
      include/cpphibernate/schema/field.inl
  76. +81
    -0
      include/cpphibernate/schema/schema.h
  77. +136
    -42
      include/cpphibernate/schema/schema.inl
  78. +86
    -0
      include/cpphibernate/schema/table.h
  79. +48
    -55
      include/cpphibernate/schema/table.inl
  80. +10
    -0
      include/cpphibernate/types.h
  81. +19
    -0
      src/CMakeLists.txt
  82. +0
    -0
      src/cpphibernate/driver/mariadb/classes/field.xcpp
  83. +135
    -0
      src/cpphibernate/driver/mariadb/classes/fields/field.cpp
  84. +0
    -0
      src/cpphibernate/driver/mariadb/classes/schema.xcpp
  85. +127
    -0
      src/cpphibernate/driver/mariadb/classes/schema/schema.cpp
  86. +0
    -0
      src/cpphibernate/driver/mariadb/classes/table.xcpp
  87. +66
    -0
      src/cpphibernate/driver/mariadb/classes/tables/table.cpp
  88. +1
    -1
      test/CMakeLists.txt
  89. +9
    -3
      test/cpphibernate/cpphibernate_init.cpp
  90. +0
    -29
      test/cpphibernate/cpphibernate_tests.cpp
  91. +0
    -0
      test/cpphibernate/mariadb_mock.cpp
  92. +1
    -1
      test/cpphibernate/test_helper.h

+ 1
- 0
include/cpphibernate.h ファイルの表示

@@ -1,5 +1,6 @@
#pragma once

#include "cpphibernate/context.h"
#include "cpphibernate/misc.h"
#include "cpphibernate/modifier.h"
#include "cpphibernate/schema.h"


+ 3
- 0
include/cpphibernate/context.h ファイルの表示

@@ -0,0 +1,3 @@
#pragma once

#include "context/context.h"

+ 106
- 0
include/cpphibernate/context/context.h ファイルの表示

@@ -0,0 +1,106 @@
#pragma once

#include <cpphibernate/config.h>

namespace cpphibernate
{

/**
* @brief Context class for cpphibernate.
*/
template<typename T_driver, typename T_schema>
struct context
: public T_driver
{
public:
using base_type = T_driver;
using driver_type = T_driver;
using schema_type = T_schema;

private:
const schema_type& _schema;

public:
/**
* @brief Value constructor. Create a new context object.
*
* @param p_schema Database schema to use.
* @param p_args Arguments to pass to underlying driver.
*/
template<typename... T_args>
constexpr context(const schema_type& p_schema, T_args&&... p_args);

/**
* @brief Nove constructor.
*/
constexpr context(context&&) = default;

/**
* @brief Copy constrcutor.
*/
constexpr context(const context&) = default;

/**
* @brief Initialize the database. This will create all non exsitsing tables.
*/
template<typename... T_args>
constexpr decltype(auto) init(T_args&&... args);

/**
* @brief Create the passed object in the database.
*/
template<typename... T_args>
constexpr decltype(auto) create(T_args&&... args);

/**
* @brief Read an object from the database.
*/
template<typename... T_args>
constexpr decltype(auto) read(T_args&&... args);

/**
* @brief Update the passed object in the database.
*/
template<typename... T_args>
constexpr decltype(auto) update(T_args&&... args);

/**
* @brief Destroy the passed object in the database.
*/
template<typename... T_args>
constexpr decltype(auto) destroy(T_args&&... args);
};

/**
* @brief Create a new cpphibernate context.
*
* @tparam T_driver Hibernate driver to use.
* @tparam T_schema Database schema to use.
* @tparam T_args Arguments to pass to underlying driver implementation.
*
* @param schema Database schema to use.
* @param args Arguments to pass to underlying driver implementation.
*
* @return Created hibernate context.
*/
template<typename T_driver, typename T_schema, typename... T_args>
constexpr decltype(auto) make_context(T_schema&& schema, T_args&&... args);

/**
* @brief Create a new cpphibernate context as a unique pointer.
*
* @tparam T_driver Hibernate driver to use.
* @tparam T_schema Database schema to use.
* @tparam T_args Arguments to pass to underlying driver implementation.
*
* @param schema Database schema to use.
* @param args Arguments to pass to underlying driver implementation.
*
* @return Unique pointer of the created hibernate context.
*/
template<typename T_driver, typename T_schema, typename... T_args>
constexpr decltype(auto) make_context_ptr(T_schema&& schema, T_args&&... args);

}

#include "context.inl"

+ 203
- 0
include/cpphibernate/context/context.inl ファイルの表示

@@ -0,0 +1,203 @@
#pragma once

#include "context.h"

namespace cpphibernate
{

namespace __impl
{

/* init_builder */

template<typename X, typename = void>
struct init_builder
{
template<typename... T_args>
static constexpr decltype(auto) apply(T_args&&...)
{ static_assert(sizeof...(T_args) == -1, "Invalid parameters for context::init(...)!"); }
};

constexpr decltype(auto) init = mp::generic_predicate<init_builder> { };
#if 0
template<typename T_impl>
struct init_builder<mp::list<T_impl, bool>, void>
{
static constexpr decltype(auto) apply(T_impl& impl, bool recreate)
{ return impl.init(recreate); }
};
#endif
/* create_builder */

template<typename X, typename = void>
struct create_builder
{
template<typename... T_args>
static constexpr decltype(auto) apply(T_args&&...)
{ static_assert(sizeof...(T_args) == -1, "Invalid parameters for context::create(...)!"); }
};

constexpr decltype(auto) create = mp::generic_predicate<create_builder> { };
#if 0
template<typename T_impl, typename T_dataset>
struct create_impl<mp::list<T_impl, T_dataset>, void>
{
static constexpr decltype(auto) apply(T_impl& impl, T_dataset& dataset)
{ return impl.create(dataset); }
};
#endif
/* read_builder */

template<typename X, typename = void>
struct read_builder
{
template<typename... T_args>
static constexpr decltype(auto) apply(T_args&&...)
{ static_assert(sizeof...(T_args) == -1, "Invalid parameters for context::read(...)!"); }
};

constexpr decltype(auto) read = mp::generic_predicate<read_builder> { };
#if 0
template<typename T_impl, typename T_dataset, typename... T_modifiers>
struct create_impl<
mp::list<T_impl, T_dataset, T_modifiers...>,
mp::enable_if_t<mp::is_true_v<is_modifier_v<mp::decay_t<T_modifiers>>...>>>
{
static constexpr decltype(auto) apply(T_impl& impl, T_dataset& dataset, T_modifiers&&... modifiers)
{ return impl.read(dataset, make_modifiers(std::forward<T_modifiers>(modifiers)...)); }
};
#endif
/* update_builder */

template<typename X, typename = void>
struct update_builder
{
template<typename... T_args>
static constexpr decltype(auto) apply(T_args&&...)
{ static_assert(sizeof...(T_args) == -1, "Invalid parameters for context::update(...)!"); }
};

constexpr decltype(auto) update = mp::generic_predicate<update_builder> { };
#if 0
template<typename T_impl, typename T_dataset>
struct update_impl<mp::list<T_impl, T_dataset>, void>
{
static constexpr decltype(auto) apply(T_impl& impl, T_dataset& dataset)
{ return impl.update(dataset); }
};
#endif
/* destroy_builder */

template<typename X, typename = void>
struct destroy_builder
{
template<typename... T_args>
static constexpr decltype(auto) apply(T_args&&...)
{ static_assert(sizeof...(T_args) == -1, "Invalid parameters for context::destroy(...)!"); }
};

constexpr decltype(auto) destroy = mp::generic_predicate<destroy_builder> { };
#if 0
template<typename T_impl, typename T_dataset>
struct destroy_impl<mp::list<T_impl, T_dataset>, void>
{
static constexpr decltype(auto) apply(T_impl& impl, T_dataset& dataset)
{ return impl.create(dataset); }
};
#endif

}

/* context */

template<typename T_driver, typename T_schema>
template<typename... T_args>
constexpr context<T_driver, T_schema>::context(const schema_type& p_schema, T_args&&... p_args)
: base_type (p_schema, std::forward<T_args>(p_args)...)
, _schema (p_schema)
{ }

template<typename T_driver, typename T_schema>
template<typename... T_args>
constexpr decltype(auto) context<T_driver, T_schema>::init(T_args&&... args)
{ return __impl::init(*this, std::forward<T_args>(args)...); }

template<typename T_driver, typename T_schema>
template<typename... T_args>
constexpr decltype(auto) context<T_driver, T_schema>::create(T_args&&... args)
{ return __impl::create(*this, std::forward<T_args>(args)...); }

template<typename T_driver, typename T_schema>
template<typename... T_args>
constexpr decltype(auto) context<T_driver, T_schema>::read(T_args&&... args)
{ return __impl::read(*this, std::forward<T_args>(args)...); }

template<typename T_driver, typename T_schema>
template<typename... T_args>
constexpr decltype(auto) context<T_driver, T_schema>::update(T_args&&... args)
{ return __impl::update(*this, std::forward<T_args>(args)...); }

template<typename T_driver, typename T_schema>
template<typename... T_args>
constexpr decltype(auto) context<T_driver, T_schema>::destroy(T_args&&... args)
{ return __impl::destroy(*this, std::forward<T_args>(args)...); }


#if 0
template<typename T_dataset, typename... T_modifiers>
constexpr auto read(T_dataset& dataset, T_modifiers&&... modifiers)
-> mp::enable_if<
modifier::all_are_modifiers<mp::decay_t<T_modifiers>...>>
{
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, modifier::make_list(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, modifier::make_list(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, modifier::make_list());
}
#endif

/* make_context */

template<typename T_driver, typename T_schema, typename... T_args>
constexpr decltype(auto) make_context(T_schema&& schema, T_args&&... args)
{
using context_type = context<T_driver, T_schema>;
return context_type(std::forward<T_schema>(schema), std::forward<T_args>(args)...);
}

/* make_context_ptr */

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 = context<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)...));
}

}

+ 3
- 7
include/cpphibernate/driver/mariadb.h ファイルの表示

@@ -1,12 +1,8 @@
#pragma once

#include <cpphibernate/config.h>
#include <cpphibernate/driver/mariadb/mariadb.h>
#include <cpphibernate/driver/mariadb/driver.h>

beg_namespace_cpphibernate_driver
namespace cpphibernate
{
using mariadb = mariadb_impl::mariadb_driver_t;

using mariadb_driver = ::cpphibernate::mariadb::driver_t;
}
end_namespace_cpphibernate_driver

+ 6
- 0
include/cpphibernate/driver/mariadb/classes.h ファイルの表示

@@ -0,0 +1,6 @@
#pragma once

#include "classes/attributes.h"
#include "classes/fields.h"
#include "classes/tables.h"
#include "classes/schema.h"

+ 3
- 0
include/cpphibernate/driver/mariadb/classes/attributes.h ファイルの表示

@@ -0,0 +1,3 @@
#pragma once

#include "attributes/attributes.h"

+ 43
- 0
include/cpphibernate/driver/mariadb/classes/attributes/attributes.h ファイルの表示

@@ -0,0 +1,43 @@
#pragma once

#include <cpphibernate/config.h>

#include "../forward.h"

namespace cpphibernate {
namespace mariadb {

namespace __impl
{

/**
* @brief Helper class to create attributes type.
*/
template<typename X, typename = void>
struct attributes_builder;

}

/**
* @brief Attributes enumeration
*/
enum class attribute_t
{
hex, //!< The field is stored hex encoded.
compress, //!< The field is stored compressed.
primary_key, //!< The field is the primary key.
};

/**
* @brief Set of attributes.
*/
struct attributes_t;

/**
* @brief Predicate to create attributes set from attributes schema.
*/
constexpr decltype(auto) make_attributes = mp::generic_predicate<__impl::attributes_builder> { };

} }

#include "attributes.inl"

include/cpphibernate/driver/mariadb/schema/attributes.inl → include/cpphibernate/driver/mariadb/classes/attributes/attributes.inl ファイルの表示

@@ -1,9 +1,14 @@
#pragma once

#include <cpphibernate/driver/mariadb/schema/attributes.h>
#include <set>

beg_namespace_cpphibernate_driver_mariadb
{
#include <cpphibernate/schema/attribute.h>
#include <cpphibernate/schema/attributes.h>

#include "attributes.h"

namespace cpphibernate {
namespace mariadb {

namespace __impl
{
@@ -25,10 +30,10 @@ beg_namespace_cpphibernate_driver_mariadb
struct attribute_converter<schema::attribute::primary_key_type>
{ static constexpr decltype(auto) value = attribute_t::primary_key; };

/* make_attributes_impl */
/* attributes_builder */

template<typename T, typename>
struct make_attributes_impl
struct attributes_builder
{
template<typename... T_args>
static constexpr decltype(auto) apply(T_args&&... args)
@@ -36,10 +41,9 @@ beg_namespace_cpphibernate_driver_mariadb
};

template<typename T_attributes>
struct make_attributes_impl<
struct attributes_builder<
mp::list<T_attributes>,
mp::enable_if_c<
schema::is_attributes<mp::decay_t<T_attributes>>::value>>
mp::enable_if_t<schema::is_attributes_v<mp::decay_t<T_attributes>>>>
{
template<size_t... I>
static constexpr decltype(auto) helper(T_attributes&&, const std::index_sequence<I...>&)
@@ -58,5 +62,13 @@ beg_namespace_cpphibernate_driver_mariadb

}

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

} }

+ 4
- 0
include/cpphibernate/driver/mariadb/classes/fields.h ファイルの表示

@@ -0,0 +1,4 @@
#pragma once

#include "fields/field.h"
#include "fields/fields.h"

+ 106
- 0
include/cpphibernate/driver/mariadb/classes/fields/field.h ファイルの表示

@@ -0,0 +1,106 @@
#pragma once

#include <memory>
#include <cpphibernate/config.h>

#include "../forward.h"
#include "../attributes.h"

namespace cpphibernate {
namespace mariadb {

/**
* @brief Abstract field class.
*/
struct field_t
{
public:
size_t id { 0 }; //!< unique id of the field
size_t value_id { 0 }; //!< unique id of the value type
size_t real_value_id { 0 }; //!< unique id of the real/unwrapped value type

bool value_is_nullable { false }; //!< value is stored in a nullable container
bool value_is_pointer { false }; //!< value is stored in a pointer container
bool value_is_container { false }; //!< value is stored in a container
bool value_is_ordered { false }; //!< value is stored in a ordered container (vector, list, ...)
bool value_is_auto_incremented { false }; //!< value is a auto incremented field

const table_t& table; //!< table this field belongs to
const table_t* referenced_table { nullptr }; //!< table that belongs to the value (if exists)

std::string name; //!< name of the SQL field
std::string type; //!< SQL type name
std::string create_arguments; //!< additional arguments for CREATE TABLE command

std::string convert_to_open; //!< SQL code to open the "convert to" operation
std::string convert_to_close; //!< SQL code to close the "convert to" operation
std::string convert_from_open; //!< SQL code to open the "convert from" operation
std::string convert_from_close; //!< SQL code to close the "convert from" operation

attributes_t attributes; //!< attributes for the field

public:
/**
* @brief Value constructor. Creates a mariadb field from the cpphibernate field.
*
* @param[in] p_owner Owner of the field.
* @param[in] p_schema Cpphibernate schema the mariadb field belongs to.
* @param[in] p_table Cpphibernate table the mariadb field belongs to.
* @param[in] p_field Cpphibernate field to create mariadb field for.
*/
template<
typename T_schema,
typename T_table,
typename T_field>
inline field_t(
const table_t& p_owner,
const T_schema& p_schema,
const T_table& p_table,
const T_field& p_field);

/**
* @brief Move constructor.
*/
inline field_t(field_t&& other) = delete;

/**
* @brief Copy constructor.
*/
inline field_t(const field_t&) = delete;

/**
* @brief Destructor.
*/
virtual ~field_t() = 0;

/**
* @brief Print the field values to the passed stream.
*/
std::ostream& print(std::ostream& os) const;

private:
/**
* @brief Initialize the field.
*/
void init();
};

namespace __impl
{

/**
* @brief Helper type to build table.
*/
template<typename X, typename = void>
struct field_builder;

}

/**
* @brief Predicate to create mariadb table class.
*/
constexpr decltype(auto) make_field = mp::generic_predicate<__impl::field_builder> { };

} }

#include "field.inl"

+ 126
- 0
include/cpphibernate/driver/mariadb/classes/fields/field.inl ファイルの表示

@@ -0,0 +1,126 @@
#pragma once

#include <cpphibernate/schema/field.h>
#include <cpphibernate/schema/table.h>
#include <cpphibernate/schema/schema.h>

#include "field.h"
#include "field_data.h"
#include "field_primary_key.h"
#include "field_foreign_table.h"

namespace cpphibernate {
namespace mariadb {

template<
typename T_schema,
typename T_table,
typename T_field>
field_t::field_t(
const table_t& p_owner,
const T_schema& p_schema,
const T_table& p_table,
const T_field& p_field)
: id (get_type_id(hana::type_c<mp::decay_t<T_field>>))
, value_id (get_type_id(hana::type_c<typename T_field::value_type>))
, real_value_id (get_type_id(hana::type_c<real_dataset_t<typename T_field::value_type>>))
, value_is_nullable (is_nullable_v <typename T_field::value_type>)
, value_is_pointer (is_pointer_v <typename T_field::value_type>)
, value_is_container (is_container_v<typename T_field::value_type>)
, value_is_ordered (is_ordered_v <typename T_field::value_type>)
, value_is_auto_incremented (false)
, table (p_owner)
, referenced_table (nullptr)
, name (p_field.name)
, type ()
, create_arguments ()
, convert_to_open ()
, convert_to_close ()
, convert_from_open ()
, convert_from_close ()
, attributes (make_attributes(p_field.attributes))
{ }

namespace __impl
{

/* field_builder */

template<typename X, typename>
struct field_builder
{
template<typename... T_args>
static constexpr decltype(auto) apply(T_args&&... args)
{ static_assert(sizeof...(args) == 0, "Invalid parameters for mariadb::make_field(...)!"); }
};

template<typename T_owner, typename T_schema, typename T_table, typename T_field>
struct field_builder<
mp::list<T_owner, T_schema, T_table, T_field>,
mp::enable_if_t<
mp::is_base_of_v<table_t, mp::decay_t<T_owner>>
&& schema::is_schema_v<mp::decay_t<T_schema>>
&& schema::is_table_v<mp::decay_t<T_table>>
&& schema::is_field_v<mp::decay_t<T_field>>>>
{

/* is_primary_key_field */

template<typename X_field>
struct is_primary_key_field
: public decltype(
hana::contains(
std::declval<mp::decay_t<X_field>>().attributes,
schema::attribute::primary_key))
{ };

/* is_foreign_table_field */

template<typename X_schema, typename X_field>
struct is_foreign_table_field
: public decltype(
hana::contains(
hana::transform(
std::declval<X_schema>().tables,
schema::get_wrapped_dataset),
std::declval<X_field>().wrapped_real_value_type))
{ };

/* field_type */

template<typename X_schema, typename X_field, typename = void>
struct field_type
{ using type = field_data_t<T_field>; };

template<typename X_schema, typename X_field>
struct field_type<
X_schema,
X_field,
mp::enable_if_t<is_primary_key_field<X_field>::value>>
{ using type = field_primary_key_t<X_field>; };

template<typename X_schema, typename X_field>
struct field_type<
X_schema,
X_field,
mp::enable_if_t<is_foreign_table_field<X_schema, X_field>::value>>
{ using type = field_foreign_table_t<X_field>; };

template<typename X_schema, typename X_field>
using field_type_t = typename field_type<X_schema, X_field>::type;

/* apply */

static constexpr decltype(auto) apply(const table_t& owner, const T_schema& schema, const T_table& table, const T_field& field)
{
using schema_type = mp::decay_t<T_schema>;
using field_type = mp::decay_t<T_field>;
using return_type = field_type_t<schema_type, field_type>;

return std::make_unique<return_type>(owner, schema, table, field);
}
};

}

} }

+ 39
- 0
include/cpphibernate/driver/mariadb/classes/fields/field_data.h ファイルの表示

@@ -0,0 +1,39 @@
#pragma once

#include "field_value.h"

namespace cpphibernate {
namespace mariadb {

/**
* @brief Field that represents a data field.
*/
template<typename T_field>
struct field_data_t
: public field_value_t<T_field>
{
private:
using base_type = field_value_t<T_field>;

public:
/**
* @brief Value constructor. Creates a mariadb field from the cpphibernate field.
*
* @param[in] p_owner Owner of the field.
* @param[in] p_schema Cpphibernate schema the mariadb field belongs to.
* @param[in] p_table Cpphibernate table the mariadb field belongs to.
* @param[in] p_field Cpphibernate field to create mariadb field for.
*/
template<
typename T_schema,
typename T_table>
inline field_data_t(
const table_t& p_owner,
const T_schema& p_schema,
const T_table& p_table,
const T_field& p_field);
};

} }

#include "field_data.inl"

+ 27
- 0
include/cpphibernate/driver/mariadb/classes/fields/field_data.inl ファイルの表示

@@ -0,0 +1,27 @@
#pragma once

#include "field_data.h"

namespace cpphibernate {
namespace mariadb {

/* field_data_t */

template<
typename T_field>
template<
typename T_schema,
typename T_table>
field_data_t<T_field>::field_data_t(
const table_t& p_owner,
const T_schema& p_schema,
const T_table& p_table,
const T_field& p_field)
: field_value_t<T_field>::field_value_t(
p_owner,
p_schema,
p_table,
p_field)
{ }

} }

+ 39
- 0
include/cpphibernate/driver/mariadb/classes/fields/field_foreign_table.h ファイルの表示

@@ -0,0 +1,39 @@
#pragma once

#include "field_simple.h"

namespace cpphibernate {
namespace mariadb {

/**
* @brief Field that represents a foreign table.
*/
template<typename T_field>
struct field_foreign_table_t
: public field_simple_t<T_field>
{
private:
using base_type = field_simple_t<T_field>;

public:
/**
* @brief Value constructor. Creates a mariadb field from the cpphibernate field.
*
* @param[in] p_owner Owner of the field.
* @param[in] p_schema Cpphibernate schema the mariadb field belongs to.
* @param[in] p_table Cpphibernate table the mariadb field belongs to.
* @param[in] p_field Cpphibernate field to create mariadb field for.
*/
template<
typename T_schema,
typename T_table>
inline field_foreign_table_t(
const table_t& p_owner,
const T_schema& p_schema,
const T_table& p_table,
const T_field& p_field);
};

} }

#include "field_foreign_table.inl"

+ 27
- 0
include/cpphibernate/driver/mariadb/classes/fields/field_foreign_table.inl ファイルの表示

@@ -0,0 +1,27 @@
#pragma once

#include "field_foreign_table.h"

namespace cpphibernate {
namespace mariadb {

/* field_foreign_table_t */

template<
typename T_field>
template<
typename T_schema,
typename T_table>
field_foreign_table_t<T_field>::field_foreign_table_t(
const table_t& p_owner,
const T_schema& p_schema,
const T_table& p_table,
const T_field& p_field)
: field_simple_t<T_field>::field_simple_t(
p_owner,
p_schema,
p_table,
p_field)
{ }

} }

+ 44
- 0
include/cpphibernate/driver/mariadb/classes/fields/field_primary_key.h ファイルの表示

@@ -0,0 +1,44 @@
#pragma once

#include "field_value.h"
#include "../../helper/key_properties.h"

namespace cpphibernate {
namespace mariadb {

/**
* @brief Field that represents a primary key field.
*/
template<typename T_field>
struct field_primary_key_t
: public field_value_t<T_field>
{
private:
using base_type = field_value_t<T_field>;

public:
static constexpr decltype(auto) key_props =
key_properties<typename decltype(+base_type::value_type)::type> { };

public:
/**
* @brief Value constructor. Creates a mariadb field from the cpphibernate field.
*
* @param[in] p_owner Owner of the field.
* @param[in] p_schema Cpphibernate schema the mariadb field belongs to.
* @param[in] p_table Cpphibernate table the mariadb field belongs to.
* @param[in] p_field Cpphibernate field to create mariadb field for.
*/
template<
typename T_schema,
typename T_table>
inline field_primary_key_t(
const table_t& p_owner,
const T_schema& p_schema,
const T_table& p_table,
const T_field& p_field);
};

} }

#include "field_primary_key.inl"

+ 33
- 0
include/cpphibernate/driver/mariadb/classes/fields/field_primary_key.inl ファイルの表示

@@ -0,0 +1,33 @@
#pragma once

#include "field_primary_key.h"

namespace cpphibernate {
namespace mariadb {

/* field_primary_key_t */

template<
typename T_field>
template<
typename T_schema,
typename T_table>
field_primary_key_t<T_field>::field_primary_key_t(
const table_t& p_owner,
const T_schema& p_schema,
const T_table& p_table,
const T_field& p_field)
: field_value_t<T_field>::field_value_t(
p_owner,
p_schema,
p_table,
p_field)
{
this->value_is_auto_incremented = key_props.is_auto_generated();
auto args = key_props.create_table_argument();
if (args)
this->create_arguments = args;
this->name = this->table.name + '_' + this->name;
}

} }

+ 39
- 0
include/cpphibernate/driver/mariadb/classes/fields/field_simple.h ファイルの表示

@@ -0,0 +1,39 @@
#pragma once

#include "field.h"

namespace cpphibernate {
namespace mariadb {

/**
* @brief Field that completely implementes the abstract field_t
*/
template<typename T_field>
struct field_simple_t
: public field_t
{
private:
using base_type = field_t;

public:
/**
* @brief Value constructor. Creates a mariadb field from the cpphibernate field.
*
* @param[in] p_owner Owner of the field.
* @param[in] p_schema Cpphibernate schema the mariadb field belongs to.
* @param[in] p_table Cpphibernate table the mariadb field belongs to.
* @param[in] p_field Cpphibernate field to create mariadb field for.
*/
template<
typename T_schema,
typename T_table>
inline field_simple_t(
const table_t& p_owner,
const T_schema& p_schema,
const T_table& p_table,
const T_field& p_field);
};

} }

#include "field_simple.inl"

+ 27
- 0
include/cpphibernate/driver/mariadb/classes/fields/field_simple.inl ファイルの表示

@@ -0,0 +1,27 @@
#pragma once

#include "field_simple.h"

namespace cpphibernate {
namespace mariadb {

/* field_simple_t */

template<
typename T_field>
template<
typename T_schema,
typename T_table>
field_simple_t<T_field>::field_simple_t(
const table_t& p_owner,
const T_schema& p_schema,
const T_table& p_table,
const T_field& p_field)
: field_t::field_t(
p_owner,
p_schema,
p_table,
p_field)
{ }

} }

+ 48
- 0
include/cpphibernate/driver/mariadb/classes/fields/field_value.h ファイルの表示

@@ -0,0 +1,48 @@
#pragma once

#include "field_simple.h"
#include "../../helper/type_properties.h"

namespace cpphibernate {
namespace mariadb {

/**
* @brief Field that represents a simple value.
*/
template<typename T_field>
struct field_value_t
: public field_simple_t<T_field>
{
private:
using base_type = field_simple_t<T_field>;

public:
static constexpr decltype(auto) field_type =
hana::type_c<mp::decay_t<T_field>>;
static constexpr decltype(auto) value_type =
hana::type_c<typename decltype(+field_type)::type::value_type>;
static constexpr decltype(auto) value_props =
type_properties<typename decltype(+value_type)::type> { };

public:
/**
* @brief Value constructor. Creates a mariadb field from the cpphibernate field.
*
* @param[in] p_owner Owner of the field.
* @param[in] p_schema Cpphibernate schema the mariadb field belongs to.
* @param[in] p_table Cpphibernate table the mariadb field belongs to.
* @param[in] p_field Cpphibernate field to create mariadb field for.
*/
template<
typename T_schema,
typename T_table>
inline field_value_t(
const table_t& p_owner,
const T_schema& p_schema,
const T_table& p_table,
const T_field& p_field);
};

} }

#include "field_value.inl"

+ 37
- 0
include/cpphibernate/driver/mariadb/classes/fields/field_value.inl ファイルの表示

@@ -0,0 +1,37 @@
#pragma once

#include "field_value.h"

namespace cpphibernate {
namespace mariadb {

/* field_value_t */

template<
typename T_field>
template<
typename T_schema,
typename T_table>
field_value_t<T_field>::field_value_t(
const table_t& p_owner,
const T_schema& p_schema,
const T_table& p_table,
const T_field& p_field)
: field_simple_t<T_field>::field_simple_t(
p_owner,
p_schema,
p_table,
p_field)
{
this->type = value_props.type();
if (value_props.convert_to_open())
this->convert_to_open = this->convert_to_open + value_props.convert_to_open();
if (value_props.convert_to_close())
this->convert_to_close = value_props.convert_to_close() + this->convert_to_close;
if (value_props.convert_from_open())
this->convert_from_open = this->convert_from_open + value_props.convert_from_open();
if (value_props.convert_from_close())
this->convert_from_close = value_props.convert_from_close() + this->convert_from_close;
}

} }

+ 39
- 0
include/cpphibernate/driver/mariadb/classes/fields/fields.h ファイルの表示

@@ -0,0 +1,39 @@
#pragma once

#include <vector>

#include "../forward.h"
#include "field.h"

namespace cpphibernate {
namespace mariadb {

/**
* @brief Vector of fields.
*/
struct fields_t
: public std::vector<field_ptr_u>
{
using base_type = std::vector<field_ptr_u>;
using base_type::base_type;
};

namespace __impl
{

/**
* @brief Helper class to create table vector.
*/
template<typename X, typename = void>
struct fields_builder;

}

/**
* @brief Predicate to create table vector.
*/
constexpr decltype(auto) make_fields = mp::generic_predicate<__impl::fields_builder> { };

} }

#include "fields.inl"

+ 67
- 0
include/cpphibernate/driver/mariadb/classes/fields/fields.inl ファイルの表示

@@ -0,0 +1,67 @@
#pragma once

#include <cpphibernate/schema/table.h>
#include <cpphibernate/schema/schema.h>

#include "field.h"
#include "fields.h"

namespace cpphibernate {
namespace mariadb {

namespace __impl
{

/* fields_builder */

template<typename X, typename>
struct fields_builder
{
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_owner, typename T_schema, typename T_table>
struct fields_builder<
mp::list<T_owner, T_schema, T_table>,
mp::enable_if_t<
mp::is_same_v<table_t, mp::decay_t<T_owner>>
&& schema::is_schema_v<mp::decay_t<T_schema>>
&& schema::is_table_v<mp::decay_t<T_table>>>>
{
template<typename T_index>
static constexpr void emplace(
fields_t& result,
const table_t& owner,
const T_schema& schema,
const T_table& table,
T_index&& index)
{
result.emplace_back(make_field(owner, schema, table, table.fields[index]));
}

template<size_t... I>
static auto helper(
const table_t& owner,
const T_schema& schema,
const T_table& table,
std::index_sequence<I...>&&)
{
fields_t ret;
int dummy[] = { 0, (emplace(ret, owner, schema, table, hana::size_c<I>), void(), 0)... };
(void) dummy;
return ret;
}

static constexpr decltype(auto) apply(
const table_t& owner, const T_schema& schema, const T_table& table)
{
using size = decltype(hana::size(table.fields));
return helper(owner, schema, table, std::make_index_sequence<size::value> { });
}
};

}

} }

+ 21
- 0
include/cpphibernate/driver/mariadb/classes/forward.h ファイルの表示

@@ -0,0 +1,21 @@
#pragma once

#include <memory>
#include <cpphibernate/config.h>

namespace cpphibernate {
namespace mariadb {

enum class attribute_t;
struct attributes_t;
struct field_t;
struct fields_t;
struct table_t;
struct tables_t;
struct schema_t;

using field_ptr_u = std::unique_ptr<const field_t>;
using table_ptr_u = std::unique_ptr<const table_t>;
using schema_ptr_u = std::unique_ptr<schema_t>;

} }

+ 3
- 0
include/cpphibernate/driver/mariadb/classes/schema.h ファイルの表示

@@ -0,0 +1,3 @@
#pragma once

#include "schema/schema.h"

+ 80
- 0
include/cpphibernate/driver/mariadb/classes/schema/schema.h ファイルの表示

@@ -0,0 +1,80 @@
#pragma once

#include <cpphibernate/config.h>

#include "../forward.h"
#include "../tables/tables.h"

namespace cpphibernate {
namespace mariadb {

/**
* @brief Class to wrapp all values needed by the maraidb schema.
*/
struct schema_t
{
public:
using table_map = std::map<size_t, const table_t *>;

private:
table_map _lookup; //!< dataset id to table pointer map

public:
std::string name; //!< name of the schema
tables_t tables; //!< tables that are managed by this schema.

public:
/**
* @brief Default constructor.
*/
inline schema_t() = default;

/**
* @brief Value constructor.
*
* @param[in] p_schema Cpphibernate schema to create mariadb schema from.
*/
template<typename T_schema>
inline schema_t(const T_schema& p_schema);

/**
* @brief Move constructor.
*/
inline schema_t(schema_t&&) = delete;

/**
* @brief Copy constructor.
*/
inline schema_t(const schema_t&) = delete;

/**
* @brief Print the schema to the passed stream.
*/
std::ostream& print(std::ostream& os) const;

private:
/**
* @brief Initialize the field.
*/
void init();
};

namespace __impl
{

/**
* @brief Helper type to build schema.
*/
template<typename X, typename = void>
struct schema_builder;

}

/**
* @brief Predicate to create mariadb schema class.
*/
constexpr decltype(auto) make_schema = mp::generic_predicate<__impl::schema_builder> { };

} }

#include "schema.inl"

+ 43
- 0
include/cpphibernate/driver/mariadb/classes/schema/schema.inl ファイルの表示

@@ -0,0 +1,43 @@
#pragma once

#include <cpphibernate/schema/schema.h>

#include "schema.h"

namespace cpphibernate {
namespace mariadb {

/* schema_t */

template<typename T_schema>
schema_t::schema_t(const T_schema& p_schema)
: name (p_schema.name)
, tables(make_tables(*this, p_schema))
{ init(); }

namespace __impl
{

/* schema_builder */

template<typename T, typename>
struct schema_builder
{
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 schema_builder<
mp::list<T_schema>,
mp::enable_if_t<
schema::is_schema_v<mp::decay_t<T_schema>>>>
{
static decltype(auto) apply(const T_schema& p_schema)
{ return std::make_unique<schema_t>(p_schema); }
};

}

} }

+ 4
- 0
include/cpphibernate/driver/mariadb/classes/tables.h ファイルの表示

@@ -0,0 +1,4 @@
#pragma once

#include "tables/table.h"
#include "tables/tables.h"

+ 115
- 0
include/cpphibernate/driver/mariadb/classes/tables/table.h ファイルの表示

@@ -0,0 +1,115 @@
#pragma once

#include <vector>
#include <memory>
#include <cpphibernate/config.h>

#include "../forward.h"
#include "../fields/fields.h"

namespace cpphibernate {
namespace mariadb {

/**
* @brief Abstract table class.
*/
struct table_t
{
public:
using size_vector = std::vector<size_t>; //!< vector of size_t
using table_vector = std::vector<const table_t *>; //!< vector of constant field pointers
using field_vector = std::vector<const field_t *>; //!< vector of constant field pointers
using field_map = std::map<size_t, const field_t *>; //!< map of field id to field

private:
field_map _lookup; //!< field id to field pointer map

public:
size_t id { 0 }; //!< unique id of the table assigned by the user
size_t dataset_id { 0 }; //!< unique id of the dataset type
size_t base_dataset_id { 0 }; //!< unique id of the dataset type
size_vector derived_dataset_ids; //!< vector of ids of all derived dataset

bool is_used_in_container { false }; //!< indicates if this table is used inside a container

std::string name; //!< name of the table
const schema_t& schema; //!< schema this table is owned by
fields_t fields; //!< vector of fields managed by this table

const table_t * base_table { nullptr }; //!< base table (if has one)
table_vector derived_tables; //!< vector of pointers of all derived tables

const field_t * primary_key_field { nullptr }; //!< primary key field
field_vector foreign_key_fields; //!< vector of pointers of all foreign key fields
field_vector foreign_table_fields; //!< vector of pointers of all foreign table fields
field_vector foreign_table_one_fields; //!< vector of pointers of all foreign table one fields
field_vector foreign_table_many_fields; //!< vector of pointers of all foreign table many fields
field_vector data_fields; //!< vector of pointers of all normal data fields

public:
/**
* @brief Default constructor.
*/
inline table_t() = default;

/**
* @brief Value constructor. Creates a mariadb table from the cpphibernate table.
*
* @param[in] p_owner Owner of the table.
* @param[in] p_schema Cpphibernate schema the table belongs to.
* @param[in] p_table Cpphibernate table to create mariadb table for.
*/
template<
typename T_schema,
typename T_table>
inline table_t(
const schema_t& p_owner,
const T_schema& p_schema,
const T_table& p_table);

/**
* @brief Move constructor.
*/
inline table_t(table_t&& other) = delete;

/**
* @brief Copy constructor.
*/
inline table_t(const table_t&) = delete;

/**
* @brief Destructor.
*/
virtual ~table_t() = 0;

/**
* @brief Print the table to the passed stream.
*/
std::ostream& print(std::ostream& os) const;

private:
/**
* @brief Initialize the field.
*/
void init();
};

namespace __impl
{

/**
* @brief Helper type to build table.
*/
template<typename X, typename = void>
struct table_builder;

}

/**
* @brief Predicate to create mariadb table class.
*/
constexpr decltype(auto) make_table = mp::generic_predicate<__impl::table_builder> { };

} }

#include "table.inl"

+ 99
- 0
include/cpphibernate/driver/mariadb/classes/tables/table.inl ファイルの表示

@@ -0,0 +1,99 @@
#pragma once

#include <cpphibernate/schema/table.h>
#include <cpphibernate/schema/schema.h>

#include "table.h"
#include "table_simple.h"
#include "table_polymorphic.h"

namespace cpphibernate {
namespace mariadb {

/* table_t */

template<
typename T_schema,
typename T_table>
table_t::table_t(
const schema_t& p_owner,
const T_schema& p_schema,
const T_table& p_table)
: id (hana::value(p_table.table_id))
, dataset_id(get_type_id(p_table.wrapped_dataset))
, name (p_table.name)
, schema (p_owner)
, fields (make_fields(*this, p_schema, p_table))
{ init(); }

namespace __impl
{

/* table_builder */

template<typename X, typename>
struct table_builder
{
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_owner, typename T_schema, typename T_table>
struct table_builder<
mp::list<T_owner, T_schema, T_table>,
mp::enable_if_t<
mp::is_same_v<schema_t, mp::decay_t<T_owner>>
&& schema::is_schema_v<mp::decay_t<T_schema>>
&& schema::is_table_v<mp::decay_t<T_table>>>>
{

/* table_type */

template<
typename T_dataset,
typename T_base_dataset,
typename T_derived_datasets,
typename = void>
struct table_type
{ using type = table_simple_t /* table_simple_t<mp::decay_t<T_schema>, mp::decay_t<T_table>, T_base_dataset> */; };

template<
typename T_dataset,
typename T_base_dataset,
typename T_derived_datasets>
struct table_type<
T_dataset,
T_base_dataset,
T_derived_datasets,
mp::enable_if_t<
decltype(hana::size(std::declval<T_derived_datasets>()) != hana::size_c<0>)::value
|| decltype(hana::not_equal(std::declval<T_base_dataset>(), hana::type_c<void>))::value>>
{ using type = table_polymorphic_t /* table_polymorphic_t<mp::decay_t<T_schema>, mp::decay_t<T_table>, T_base_dataset> */; };

template<
typename T_dataset,
typename T_base_dataset,
typename T_derived_datasets>
using table_type_t = typename table_type<T_dataset, T_base_dataset, T_derived_datasets>::type;

/* apply */

static decltype(auto) apply(const schema_t& owner, const T_schema& schema, const T_table& table)
{
using dataset_type = decltype(+table.wrapped_dataset);
using base_dataset_type = mp::decay_t<decltype(schema::get_base_type(schema, table.wrapped_dataset))>;
using derived_datasets_type = mp::decay_t<decltype(schema::get_derived_types(schema, table.wrapped_dataset))>;
using table_type = table_type_t<dataset_type, base_dataset_type, derived_datasets_type>;

return std::make_unique<table_type>(
owner, schema, table,
base_dataset_type { }, derived_datasets_type { });
}

};


}

} }

+ 39
- 0
include/cpphibernate/driver/mariadb/classes/tables/table_polymorphic.h ファイルの表示

@@ -0,0 +1,39 @@
#pragma once

#include <cpphibernate/config.h>

#include "table.h"

namespace cpphibernate {
namespace mariadb {

/**
* @brief Table for polymorphic data types.
*/
struct table_polymorphic_t
: public table_t
{
public:
/**
* @brief Value constructor. Creates a mariadb table from the cpphibernate table.
*
* @param[in] p_owner Owner of the table.
* @param[in] p_schema Cpphibernate schema the table belongs to.
* @param[in] p_table Cpphibernate table to create mariadb table for.
*/
template<
typename T_schema,
typename T_table,
typename T_base_dataset,
typename T_derived_datasets>
inline table_polymorphic_t(
const schema_t& p_owner,
const T_schema& p_schema,
const T_table& p_table,
const T_base_dataset&&,
const T_derived_datasets&&);
};

} }

#include "table_polymorphic.inl"

+ 60
- 0
include/cpphibernate/driver/mariadb/classes/tables/table_polymorphic.inl ファイルの表示

@@ -0,0 +1,60 @@
#pragma once

#include "table_polymorphic.h"

namespace cpphibernate {
namespace mariadb {

namespace __impl
{

/* make_dataset_id_vector */

struct make_dataset_id_vector_impl
{
template<typename T_datasets, size_t... I>
static constexpr decltype(auto) helper(const T_datasets& datasets, std::index_sequence<I...>)
{
return std::vector<size_t>({
get_type_id(datasets[hana::size_c<I>])...
});
}

template<typename T_datasets>
constexpr decltype(auto) operator()(const T_datasets& datasets) const
{
using size = mp::decay_t<decltype(hana::size(datasets))>;
return helper(datasets, std::make_index_sequence<size::value> { });
}
};

static constexpr decltype(auto) make_dataset_id_vector = make_dataset_id_vector_impl { };

}

/* table_polymorphic_t */

template<
typename T_schema,
typename T_table,
typename T_base_dataset,
typename T_derived_datasets>
table_polymorphic_t::table_polymorphic_t(
const schema_t& p_owner,
const T_schema& p_schema,
const T_table& p_table,
const T_base_dataset&&,
const T_derived_datasets&&)
: table_t(
p_owner,
p_schema,
p_table)
{
this->base_dataset_id = hana::if_(
hana::equal(T_base_dataset { }, hana::type_c<void>),
static_cast<size_t>(0),
get_type_id(T_base_dataset { }));
this->derived_dataset_ids = __impl::make_dataset_id_vector(T_derived_datasets { });
}

} }

+ 39
- 0
include/cpphibernate/driver/mariadb/classes/tables/table_simple.h ファイルの表示

@@ -0,0 +1,39 @@
#pragma once

#include <cpphibernate/config.h>

#include "table.h"

namespace cpphibernate {
namespace mariadb {

/**
* @brief Table for non polymorphic datatypes.
*/
struct table_simple_t
: public table_t
{
public:
/**
* @brief Value constructor. Creates a mariadb table from the cpphibernate table.
*
* @param[in] p_owner Owner of the table.
* @param[in] p_schema Cpphibernate schema the table belongs to.
* @param[in] p_table Cpphibernate table to create mariadb table for.
*/
template<
typename T_schema,
typename T_table,
typename T_base_dataset,
typename T_derived_datasets>
inline table_simple_t(
const schema_t& p_owner,
const T_schema& p_schema,
const T_table& p_table,
const T_base_dataset&&,
const T_derived_datasets&&);
};

} }

#include "table_simple.inl"

+ 27
- 0
include/cpphibernate/driver/mariadb/classes/tables/table_simple.inl ファイルの表示

@@ -0,0 +1,27 @@
#pragma once

#include "table_simple.h"

namespace cpphibernate {
namespace mariadb {

/* table_simple_t */

template<
typename T_schema,
typename T_table,
typename T_base_dataset,
typename T_derived_datasets>
table_simple_t::table_simple_t(
const schema_t& p_owner,
const T_schema& p_schema,
const T_table& p_table,
const T_base_dataset&&,
const T_derived_datasets&&)
: table_t(
p_owner,
p_schema,
p_table)
{ }

} }

+ 38
- 0
include/cpphibernate/driver/mariadb/classes/tables/tables.h ファイルの表示

@@ -0,0 +1,38 @@
#pragma once

#include <vector>

#include "table.h"

namespace cpphibernate {
namespace mariadb {

/**
* @brief Vector of tables.
*/
struct tables_t
: public std::vector<table_ptr_u>
{
using base_type = std::vector<table_ptr_u>;
using base_type::base_type;
};

namespace __impl
{

/**
* @brief Helper class to create table vector.
*/
template<typename X, typename = void>
struct tables_builder;

}

/**
* @brief Predicate to create table vector.
*/
constexpr decltype(auto) make_tables = mp::generic_predicate<__impl::tables_builder> { };

} }

#include "tables.inl"

+ 67
- 0
include/cpphibernate/driver/mariadb/classes/tables/tables.inl ファイルの表示

@@ -0,0 +1,67 @@
#pragma once

#include <cpphibernate/schema/tables.h>
#include <cpphibernate/schema/schema.h>

#include "tables.h"

namespace cpphibernate {
namespace mariadb {

namespace __impl
{

/* tables_builder */

template<typename X, typename>
struct tables_builder
{
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_owner,
typename T_schema>
struct tables_builder<
mp::list<T_owner, T_schema>,
mp::enable_if_t<
mp::is_same_v<schema_t, mp::decay_t<T_owner>>
&& schema::is_schema_v<mp::decay_t<T_schema>>>>
{
template<typename T_index>
static constexpr void emplace(
tables_t& result,
const schema_t& owner,
const T_schema& schema,
T_index&& index)
{
result.emplace_back(make_table(owner, schema, schema.tables[index]));
}

template<size_t... I>
static decltype(auto) helper(
const schema_t& owner,
const T_schema& schema,
std::index_sequence<I...> seq)
{
tables_t ret;
ret.reserve(sizeof...(I));
int dummy[] = { 0, (emplace(ret, owner, schema, hana::size_c<I>), void(), 0)... };
(void) dummy;
return ret;
}

static constexpr decltype(auto) apply(
const schema_t& owner,
const T_schema& schema)
{
using size = decltype(hana::size(schema.tables));
return helper(owner, schema, std::make_index_sequence<size::value> { });
}
};

}

} }

include/cpphibernate/driver/mariadb/mariadb.h → include/cpphibernate/driver/mariadb/driver.h ファイルの表示

@@ -1,16 +1,37 @@
#pragma once

#include <cppmariadb.h>
#include <cpphibernate/config.h>
#include <cpphibernate/driver/mariadb/impl.h>
#include <cpphibernate/driver/mariadb/schema.h>
#include <cpphibernate/driver/mariadb/schema/filter.h>

beg_namespace_cpphibernate_driver_mariadb
{
#include "classes.h"
// #include <cpphibernate/config.h>
// #include <cpphibernate/driver/mariadb/impl.h>
// #include <cpphibernate/driver/mariadb/schema.h>
// #include <cpphibernate/driver/mariadb/schema/filter.h>

struct mariadb_driver_t
namespace cpphibernate {
namespace mariadb {

/**
* @brief Mariadb driver.
*/
struct driver_t
{
private:
schema_ptr_u _schema;

public:
/**
* @brief Constructor. Initializes the driver with the passed schema.
*/
template<typename T_schema>
inline driver_t(T_schema&& p_schema);

/**
* @brief Print the schema of the driver to the passed stream.
*/
inline std::ostream& print(std::ostream& os) const;

/*
public:
using lock_type = std::unique_ptr<transaction_lock>;

@@ -21,9 +42,8 @@ beg_namespace_cpphibernate_driver_mariadb

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)))
mariadb_driver_t(T_schema&& p_schema)
: _schema(make_schema(std::forward<T_schema>(p_schema)))
{ }

cpphibernate_copyable(mariadb_driver_t, delete);
@@ -114,7 +134,9 @@ beg_namespace_cpphibernate_driver_mariadb

destroy_impl_t<T_dataset>::apply(context);
}
*/
};

}
end_namespace_cpphibernate_driver_mariadb
} }

#include "driver.inl"

+ 16
- 0
include/cpphibernate/driver/mariadb/driver.inl ファイルの表示

@@ -0,0 +1,16 @@
#pragma once

#include "driver.h"

namespace cpphibernate {
namespace mariadb {

template<typename T_schema>
driver_t::driver_t(T_schema&& p_schema)
: _schema(make_schema(std::forward<T_schema>(p_schema)))
{ }

std::ostream& driver_t::print(std::ostream& os) const
{ return _schema->print(os); }

} }

+ 5
- 4
include/cpphibernate/driver/mariadb/helper.h ファイルの表示

@@ -1,6 +1,7 @@
#pragma once

#include <cpphibernate/driver/mariadb/helper/context.h>
#include <cpphibernate/driver/mariadb/helper/key_properties.h>
#include <cpphibernate/driver/mariadb/helper/transaction_lock.h>
#include <cpphibernate/driver/mariadb/helper/type_properties.h>
#include "helper/key_properties.h"
#include "helper/type_properties.h"
#include "helper/key_properties.h"
#include "helper/transaction_lock.h"
#include "helper/type_properties.h"

+ 31
- 32
include/cpphibernate/driver/mariadb/helper/key_properties.h ファイルの表示

@@ -1,42 +1,41 @@
#pragma once

#include <cpphibernate/types.h>
#include <cpphibernate/config.h>
#include <cpputils/container/nullable.h>

beg_namespace_cpphibernate_driver_mariadb
{

/* key_properties */
namespace cpphibernate {
namespace mariadb {

/**
* @brief Key type properties for the passed type.
*
* @tparam T_key Type to get key properties for.
*/
template<typename T_key, typename = void>
struct key_properties;

template<>
struct key_properties<uuid, void>
struct key_properties
{
using auto_generated = mp::c_false_t;
using key_type = uuid;

static constexpr decltype(auto) create_table_argument = "";
static constexpr decltype(auto) create_key_query = "SELECT Uuid()";

static bool is_default(const key_type& key)
{ return key == key_type(); }
using key_type = T_key;

/**
* @brief Check if the passed key value is the default value.
*/
static bool is_default(const key_type& key) = delete;

/**
* @brief Returns true if the key type is auto generated, false otherwise.
*/
static constexpr bool is_auto_generated() = delete;

/**
* @brief Returns extra arguments to use for creating the table.
*/
static constexpr const char * create_table_argument() = delete;

/**
* @brief Return the query to create a new key value.
*/
static constexpr const char * create_key_query() = delete;
};

template<typename T_key>
struct key_properties<T_key, mp::enable_if<mp::is_integral<T_key>>>
{
using auto_generated = mp::c_true_t;
using key_type = T_key;

static constexpr decltype(auto) create_table_argument = "AUTO_INCREMENT";
static constexpr decltype(auto) create_key_query = "";

static bool is_default(const key_type& key)
{ return key == key_type(); }
};
} }

}
end_namespace_cpphibernate_driver_mariadb
#include "key_properties.inl"

+ 50
- 0
include/cpphibernate/driver/mariadb/helper/key_properties.inl ファイルの表示

@@ -0,0 +1,50 @@
#pragma once

#include "key_properties.h"

#include <cpphibernate/types.h>

namespace cpphibernate {
namespace mariadb {

/* key_properties */

template<>
struct key_properties<uuid, void>
{
using key_type = uuid;

static bool is_default(const key_type& key)
{ return key == key_type(); }

static constexpr bool is_auto_generated()
{ return false; }

static constexpr const char * create_table_argument()
{ return nullptr; }

static constexpr const char * create_key_query()
{ return "SELECT Uuid()"; }
};

template<typename T_key>
struct key_properties<
T_key,
mp::enable_if_t<mp::is_integral_v<mp::decay_t<T_key>>>>
{
using key_type = mp::decay_t<T_key>;

static bool is_default(const key_type& key)
{ return key == key_type(); }

static constexpr bool is_auto_generated()
{ return true; }

static constexpr const char * create_table_argument()
{ return "AUTO_INCREMENT"; }

static constexpr const char * create_key_query()
{ return nullptr; }
};

} }

+ 35
- 0
include/cpphibernate/driver/mariadb/helper/nullable_helper.h ファイルの表示

@@ -0,0 +1,35 @@
#pragma once

#include <cpphibernate/config.h>

namespace cpphibernate {
namespace mariadb {

/**
* @brief Helper class to manage operations on nullable types.
*/
template<typename T_nullable, typename = void>
struct nullable_helper
{
using nullable_type = T_nullable;
using value_type = real_dataset_t<nullable_type>;

/**
* @brief Get a pointer to the stored value of the nullable object.
*/
static value_type* get(const nullable_type&) = delete;

/**
* @brief Set the new value of the nullable object.
*/
static value_type& set(nullable_type&, const value_type&) = delete;

/**
* @brief Destroy the stored value of a nullable objec (clear the nullable object).
*/
static void clear(nullable_type&) = delete;
};

} }

#include "nullable_helper.inl"

+ 75
- 0
include/cpphibernate/driver/mariadb/helper/nullable_helper.inl ファイルの表示

@@ -0,0 +1,75 @@
#include "nullable_helper.h"

#include <memory>

#include <cppcore/misc/nullable.h>

namespace cpphibernate {
namespace mariadb {


/* nullable_helper - cppcore::nullable */

template<typename T_value>
struct nullable_helper<cppcore::nullable<T_value>, void>
{
using nullable_type = cppcore::nullable<T_value>;
using value_type = T_value;

static inline value_type* get(nullable_type& x)
{ return x.has_value() ? &x.value() : nullptr; }

static inline const value_type* get(const nullable_type& x)
{ return x.has_value() ? &x.value() : nullptr; }

static inline value_type& set(nullable_type& x, const value_type* value)
{ return *(x = *value); }

static inline value_type& set(nullable_type& x, const value_type& value)
{ return *(x = value); }

static inline value_type& set(nullable_type& x, value_type&& value)
{ return *(x = std::move(value)); }

static void clear(nullable_type& x)
{ x.reset(); }
};

/* nullable_helper - std::unique_ptr/std::shared_ptr */

template<typename T>
struct nullable_helper<
T,
mp::enable_if_t<
mp::is_specialization_of_v<T, std::unique_ptr>
|| mp::is_specialization_of_v<T, std::shared_ptr>>>
{
using nullable_type = T;
using value_type = typename nullable_type::element_type;

static inline value_type* get(const nullable_type& x)
{ return x.get(); }

static inline value_type& set(nullable_type& x, value_type* value)
{
x.reset(value);
return *x;
}

static inline value_type& set(nullable_type& x, const value_type& value)
{
x.reset(new value_type(value));
return *x;
}

static inline value_type& set(nullable_type& x, value_type&& value)
{
x.reset(new value_type(std::move(value)));
return *x;
}

static void clear(nullable_type& x)
{ return x.reset(); }
};

} }

+ 42
- 565
include/cpphibernate/driver/mariadb/helper/type_properties.h ファイルの表示

@@ -1,583 +1,60 @@
#pragma once

#include <cpputils/misc/enum.h>
#include <cpputils/misc/flags.h>
#include <cpputils/misc/string.h>

#include <cpphibernate/misc.h>
#include <cpphibernate/types.h>
#include <cpphibernate/config.h>
#include <cpputils/container/nullable.h>

beg_namespace_cpphibernate_driver_mariadb
{

/* value_t */
#include <cppcore/misc/nullable.h>

using value_t = utl::nullable<std::string>;
namespace cpphibernate {
namespace mariadb {

/* type_properties */
/**
* @brief Value received from the database.
*/
using value_t = cppcore::nullable<std::string>;

/**
* @brief Type properties for the passed type.
*
* @tparam T Type to get properties for.
*/
template<typename T, typename = void>
struct type_properties
{
static constexpr void type () = delete;
static T convert_to (const value_t&) = delete;
static value_t convert_from (const T&) = delete;
static constexpr const char* convert_to_open () = delete;
static constexpr const char* convert_to_close () = delete;
static constexpr const char* convert_from_open () = delete;
static constexpr const char* convert_from_close() = delete;
};

template<>
struct type_properties<bool, void>
{
static constexpr decltype(auto) type()
{ return "BOOLEAN"; }

static inline bool convert_to(const value_t& value)
{ return utl::from_string<int>(*value); }

static inline value_t convert_from(const bool& value)
{ return utl::to_string(static_cast<int>(value)); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<uint8_t, void>
{
static constexpr decltype(auto) type()
{ return "TINYINT UNSIGNED"; }

static inline uint8_t convert_to(const value_t& value)
{ return static_cast<uint8_t>(utl::from_string<int>(*value)); }

static inline value_t convert_from(const uint8_t& value)
{ return utl::to_string(static_cast<int>(value)); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<int8_t, void>
{
static constexpr decltype(auto) type()
{ return "TINYINT"; }

static inline int8_t convert_to(const value_t& value)
{ return static_cast<int8_t>(utl::from_string<int>(*value)); }

static inline value_t convert_from(const int8_t& value)
{ return utl::to_string(static_cast<int>(value)); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<uint16_t, void>
{
static constexpr decltype(auto) type()
{ return "SMALLINT UNSIGNED"; }

static inline uint16_t convert_to(const value_t& value)
{ return utl::from_string<uint16_t>(*value); }

static inline value_t convert_from(const uint16_t& value)
{ return utl::to_string(value); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<int16_t, void>
{
static constexpr decltype(auto) type()
{ return "SMALLINT"; }

static inline int16_t convert_to(const value_t& value)
{ return utl::from_string<int16_t>(*value); }

static inline value_t convert_from(const int16_t& value)
{ return utl::to_string(value); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<uint32_t, void>
{
static constexpr decltype(auto) type()
{ return "INT UNSIGNED"; }

static inline uint32_t convert_to(const value_t& value)
{ return utl::from_string<uint32_t>(*value); }

static inline value_t convert_from(const uint32_t& value)
{ return utl::to_string(value); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<int32_t, void>
{
static constexpr decltype(auto) type()
{ return "INT"; }

static inline int32_t convert_to(const value_t& value)
{ return utl::from_string<int32_t>(*value); }

static inline value_t convert_from(const int32_t& value)
{ return utl::to_string(value); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<uint64_t, void>
{
static constexpr decltype(auto) type()
{ return "BIGINT UNSIGNED"; }

static inline uint64_t convert_to(const value_t& value)
{ return utl::from_string<uint64_t>(*value); }

static inline value_t convert_from(const uint64_t& value)
{ return utl::to_string(value); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<int64_t, void>
{
static constexpr decltype(auto) type()
{ return "BIGINT"; }

static inline int64_t convert_to(const value_t& value)
{ return utl::from_string<int64_t>(*value); }

static inline value_t convert_from(const int64_t& value)
{ return utl::to_string(value); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<float, void>
{
static constexpr decltype(auto) type()
{ return "FLOAT"; }

static inline float convert_to(const value_t& value)
{ return utl::from_string<float>(*value); }

static inline value_t convert_from(const float& value)
{ return utl::to_string(value); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<double, void>
{
static constexpr decltype(auto) type()
{ return "DOUBLE"; }

static inline double convert_to(const value_t& value)
{ return utl::from_string<double>(*value); }

static inline value_t convert_from(const double& value)
{ return utl::to_string(value); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<uuid, void>
{
static constexpr decltype(auto) type()
{ return "BINARY(16)"; }

static inline uuid convert_to(const value_t& value)
{ return utl::from_string<uuid>(*value); }

static inline value_t convert_from(const uuid& value)
{ return utl::to_string(value); }

static constexpr const char* convert_to_open()
{ return "UuidToBin("; }

static constexpr const char* convert_to_close()
{ return ")"; }

static constexpr const char* convert_from_open()
{ return "BinToUuid("; }

static constexpr const char* convert_from_close()
{ return ")"; }
};

template<>
struct type_properties<timestamp, void>
{
static constexpr decltype(auto) type()
{ return "BIGINT"; }

static inline timestamp convert_to(const value_t& value)
{ return timestamp(utl::from_string<uint64_t>(*value)); }

static inline value_t convert_from(const timestamp& value)
{ return utl::to_string(static_cast<uint64_t>(value)); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<std::string, void>
{
static constexpr decltype(auto) type()
{ return "VARCHAR(100)"; }
/**
* @brief Get the mariadb type.
*/
static constexpr const char * type() = delete;

static inline std::string convert_to(const value_t& value)
{ return *value; }
/**
* @brief Convert a value from the database to its actual type.
*/
static T convert_to(const value_t&) = delete;

static inline value_t convert_from(const std::string& value)
{ return value; }
/**
* @brief Convert the actual value to a database value.
*/
static value_t convert_from(const T&) = delete;

static constexpr const char* convert_to_open()
{ return nullptr; }
/**
* @brief Get the string to start the "convert to" operation.
*/
static constexpr const char * convert_to_open() = delete;

static constexpr const char* convert_to_close()
{ return nullptr; }
/**
* @brief Get the string to end the "convert to" operation.
*/
static constexpr const char * convert_to_close() = delete;

static constexpr const char* convert_from_open()
{ return nullptr; }
/**
* @brief Get the string to start the "convert from" operation.
*/
static constexpr const char * convert_from_open() = delete;

static constexpr const char* convert_from_close()
{ return nullptr; }
/**
* @brief Get the string to end the "convert from" operation.
*/
static constexpr const char * convert_from_close() = delete;
};

template<size_t N>
struct type_properties<string<N>, void>
{
static inline std::string make_type()
{ return std::string("VARCHAR(") + utl::to_string(N) + ")"; }

static inline decltype(auto) type()
{
static const std::string v = make_type();
return v;
}

static inline std::string convert_to(const value_t& value)
{ return *value; }

static inline value_t convert_from(const std::string& value)
{ return value; }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<typename T>
struct type_properties<T, mp::enable_if<misc::is_nullable<mp::decay_t<T>>>>
{
using nullable_type = T;
using nullable_helper_type = misc::nullable_helper<nullable_type>;
using value_type = typename nullable_helper_type::value_type;
using value_type_props = type_properties<value_type>;

static constexpr decltype(auto) type()
{ return value_type_props::type(); }

static inline nullable_type convert_to(const value_t& value)
{
nullable_type ret;
if (value.has_value())
nullable_helper_type::set(ret, value_type_props::convert_to(value));
return ret;
}

static inline value_t convert_from(const nullable_type& value)
{
value_t ret;
auto v = nullable_helper_type::get(value);
if (v)
ret = value_type_props::convert_from(*v);
return ret;
}

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<typename T>
struct type_properties<T, mp::enable_if<std::is_enum<mp::clean_type<T>>>>
{
using enum_type = T;
using base_type = typename std::underlying_type<enum_type>::type;

static std::string make_type()
{
std::ostringstream os;
os << "ENUM ( ";
auto e = enum_type::first;
while (e <= enum_type::last)
{
if (e != enum_type::first)
os << ", ";
os << "'" << utl::enum_conversion<enum_type>::to_string(e, false) << "'";
e = static_cast<enum_type>(static_cast<base_type>(e) + 1);
}
os << " )";
return os.str();
}

static inline decltype(auto) type()
{
static const std::string v = make_type();
return v;
}

static inline enum_type convert_to(const value_t& value)
{
enum_type ret;
if (!utl::enum_conversion<enum_type>::try_to_enum(*value, ret, false))
throw misc::hibernate_exception("unable to convert enum value!");
return ret;
}

static inline value_t convert_from(const enum_type& value)
{ return utl::enum_conversion<enum_type>::to_string(value, false); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<typename T>
struct type_properties<T, mp::enable_if<mp::is_specialization_of<mp::clean_type<T>, utl::flags>>>
{
using flags_type = T;
using enum_type = typename flags_type::enum_type;
using base_type = typename std::underlying_type<enum_type>::type;

static inline std::string make_type()
{
std::ostringstream os;
os << "SET ( ";
auto e = enum_type::first;
while (e <= enum_type::last)
{
if (e != enum_type::first)
os << ", ";
os << "'" << utl::to_string(e) << "'";
e = static_cast<enum_type>(static_cast<base_type>(e) + 1);
}
os << " )";
return os.str();
}

static inline decltype(auto) type()
{
static const std::string v = make_type();
return v;
}

static inline flags_type convert_to(const value_t& value)
{
auto s = *value;
auto c = s.c_str();
auto e = c + s.size();
auto p = c;
flags_type ret;
while (c <= e)
{
if (c == e || *c == ',')
{
if (c - p > 0)
ret.set(utl::enum_conversion<enum_type>::to_enum(std::string(p, static_cast<size_t>(c - p)), true));
p = c + 1;
}
++c;
}
return ret;
}

static inline value_t convert_from(const flags_type& value)
{
std::ostringstream os;
bool first = true;
for (auto e : value)
{
if (first) first = false;
else os << ",";
os << utl::enum_conversion<enum_type>::to_string(e, false);
}
return os.str();
}

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};
} }

}
end_namespace_cpphibernate_driver_mariadb
#include "type_properties.inl"

+ 563
- 0
include/cpphibernate/driver/mariadb/helper/type_properties.inl ファイルの表示

@@ -0,0 +1,563 @@
#pragma once

#include <cpphibernate/types.h>
#include <cppcore/conversion/string.h>

#include "type_properties.h"
#include "nullable_helper.h"

namespace cpphibernate {
namespace mariadb {

template<>
struct type_properties<bool, void>
{
static constexpr decltype(auto) type()
{ return "BOOLEAN"; }

static inline bool convert_to(const value_t& value)
{ return cppcore::from_string<int>(*value); }

static inline value_t convert_from(const bool& value)
{ return cppcore::to_string(static_cast<int>(value)); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<uint8_t, void>
{
static constexpr decltype(auto) type()
{ return "TINYINT UNSIGNED"; }

static inline uint8_t convert_to(const value_t& value)
{ return static_cast<uint8_t>(cppcore::from_string<int>(*value)); }

static inline value_t convert_from(const uint8_t& value)
{ return cppcore::to_string(static_cast<int>(value)); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<int8_t, void>
{
static constexpr decltype(auto) type()
{ return "TINYINT"; }

static inline int8_t convert_to(const value_t& value)
{ return static_cast<int8_t>(cppcore::from_string<int>(*value)); }

static inline value_t convert_from(const int8_t& value)
{ return cppcore::to_string(static_cast<int>(value)); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<uint16_t, void>
{
static constexpr decltype(auto) type()
{ return "SMALLINT UNSIGNED"; }

static inline uint16_t convert_to(const value_t& value)
{ return cppcore::from_string<uint16_t>(*value); }

static inline value_t convert_from(const uint16_t& value)
{ return cppcore::to_string(value); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<int16_t, void>
{
static constexpr decltype(auto) type()
{ return "SMALLINT"; }

static inline int16_t convert_to(const value_t& value)
{ return cppcore::from_string<int16_t>(*value); }

static inline value_t convert_from(const int16_t& value)
{ return cppcore::to_string(value); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<uint32_t, void>
{
static constexpr decltype(auto) type()
{ return "INT UNSIGNED"; }

static inline uint32_t convert_to(const value_t& value)
{ return cppcore::from_string<uint32_t>(*value); }

static inline value_t convert_from(const uint32_t& value)
{ return cppcore::to_string(value); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<int32_t, void>
{
static constexpr decltype(auto) type()
{ return "INT"; }

static inline int32_t convert_to(const value_t& value)
{ return cppcore::from_string<int32_t>(*value); }

static inline value_t convert_from(const int32_t& value)
{ return cppcore::to_string(value); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<uint64_t, void>
{
static constexpr decltype(auto) type()
{ return "BIGINT UNSIGNED"; }

static inline uint64_t convert_to(const value_t& value)
{ return cppcore::from_string<uint64_t>(*value); }

static inline value_t convert_from(const uint64_t& value)
{ return cppcore::to_string(value); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<int64_t, void>
{
static constexpr decltype(auto) type()
{ return "BIGINT"; }

static inline int64_t convert_to(const value_t& value)
{ return cppcore::from_string<int64_t>(*value); }

static inline value_t convert_from(const int64_t& value)
{ return cppcore::to_string(value); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<float, void>
{
static constexpr decltype(auto) type()
{ return "FLOAT"; }

static inline float convert_to(const value_t& value)
{ return cppcore::from_string<float>(*value); }

static inline value_t convert_from(const float& value)
{ return cppcore::to_string(value); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<double, void>
{
static constexpr decltype(auto) type()
{ return "DOUBLE"; }

static inline double convert_to(const value_t& value)
{ return cppcore::from_string<double>(*value); }

static inline value_t convert_from(const double& value)
{ return cppcore::to_string(value); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<uuid, void>
{
static constexpr decltype(auto) type()
{ return "BINARY(16)"; }

static inline uuid convert_to(const value_t& value)
{ return cppcore::from_string<uuid>(*value); }

static inline value_t convert_from(const uuid& value)
{ return cppcore::to_string(value); }

static constexpr const char* convert_to_open()
{ return "UuidToBin("; }

static constexpr const char* convert_to_close()
{ return ")"; }

static constexpr const char* convert_from_open()
{ return "BinToUuid("; }

static constexpr const char* convert_from_close()
{ return ")"; }
};

template<>
struct type_properties<timestamp, void>
{
static constexpr decltype(auto) type()
{ return "BIGINT"; }

static inline timestamp convert_to(const value_t& value)
{ return timestamp(cppcore::from_string<uint64_t>(*value)); }

static inline value_t convert_from(const timestamp& value)
{ return cppcore::to_string(static_cast<uint64_t>(value)); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<>
struct type_properties<std::string, void>
{
static constexpr decltype(auto) type()
{ return "VARCHAR(100)"; }

static inline std::string convert_to(const value_t& value)
{ return *value; }

static inline value_t convert_from(const std::string& value)
{ return value; }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<size_t N>
struct type_properties<string<N>, void>
{
static inline std::string make_type()
{ return std::string("VARCHAR(") + cppcore::to_string(N) + ")"; }

static inline decltype(auto) type()
{
static const std::string v = make_type();
return v;
}

static inline std::string convert_to(const value_t& value)
{ return *value; }

static inline value_t convert_from(const std::string& value)
{ return value; }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<typename T>
struct type_properties<T, mp::enable_if_t<is_nullable_v<mp::decay_t<T>>>>
{
using nullable_type = T;
using nullable_helper_type = nullable_helper<nullable_type>;
using value_type = typename nullable_helper_type::value_type;

static constexpr decltype(auto) nullable = nullable_helper_type { };
static constexpr decltype(auto) value_props = type_properties<value_type> { };

static constexpr decltype(auto) type()
{ return value_props.type(); }

static inline decltype(auto) convert_to(const value_t& value)
{
nullable_type ret;
if (value.has_value())
nullable.set(ret, value_props.convert_to(value));
return ret;
}

static inline value_t convert_from(const nullable_type& value)
{
value_t ret;
auto v = nullable.get(value);
if (v)
ret = value_props.convert_from(*v);
return ret;
}

static constexpr const char* convert_to_open()
{ return value_props.convert_to_open(); }

static constexpr const char* convert_to_close()
{ return value_props.convert_to_close(); }

static constexpr const char* convert_from_open()
{ return value_props.convert_from_open(); }

static constexpr const char* convert_from_close()
{ return value_props.convert_from_close(); }
};

template<typename T>
struct type_properties<T, mp::enable_if_t<mp::is_enum_v<mp::decay_t<T>>>>
{
using enum_type = T;
using base_type = typename std::underlying_type<enum_type>::type;

static std::string make_type()
{
std::ostringstream os;
os << "ENUM ( ";
auto e = enum_type::first;
while (e <= enum_type::last)
{
if (e != enum_type::first)
os << ", ";
os << "'" << cppcore::enum_conversion<enum_type>::to_string(e, false) << "'";
e = static_cast<enum_type>(static_cast<base_type>(e) + 1);
}
os << " )";
return os.str();
}

static inline decltype(auto) type()
{
static const std::string v = make_type();
return v;
}

static inline enum_type convert_to(const value_t& value)
{
enum_type ret;
if (!cppcore::enum_conversion<enum_type>::try_to_enum(*value, ret, false))
throw exception("unable to convert enum value!");
return ret;
}

static inline value_t convert_from(const enum_type& value)
{ return cppcore::enum_conversion<enum_type>::to_string(value, false); }

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

template<typename T>
struct type_properties<T, mp::enable_if_t<mp::is_specialization_of_v<mp::decay_t<T>, cppcore::flags>>>
{
using flags_type = T;
using enum_type = typename flags_type::enum_type;
using base_type = typename std::underlying_type<enum_type>::type;

static inline std::string make_type()
{
std::ostringstream os;
os << "SET ( ";
auto e = enum_type::first;
while (e <= enum_type::last)
{
if (e != enum_type::first)
os << ", ";
os << "'" << cppcore::to_string(e) << "'";
e = static_cast<enum_type>(static_cast<base_type>(e) + 1);
}
os << " )";
return os.str();
}

static inline decltype(auto) type()
{
static const std::string v = make_type();
return v;
}

static inline flags_type convert_to(const value_t& value)
{
auto s = *value;
auto c = s.c_str();
auto e = c + s.size();
auto p = c;
flags_type ret;
while (c <= e)
{
if (c == e || *c == ',')
{
if (c - p > 0)
ret.set(cppcore::enum_conversion<enum_type>::to_enum(std::string(p, static_cast<size_t>(c - p)), true));
p = c + 1;
}
++c;
}
return ret;
}

static inline value_t convert_from(const flags_type& value)
{
std::ostringstream os;
bool first = true;
for (auto e : value)
{
if (first) first = false;
else os << ",";
os << cppcore::enum_conversion<enum_type>::to_string(e, false);
}
return os.str();
}

static constexpr const char* convert_to_open()
{ return nullptr; }

static constexpr const char* convert_to_close()
{ return nullptr; }

static constexpr const char* convert_from_open()
{ return nullptr; }

static constexpr const char* convert_from_close()
{ return nullptr; }
};

} }

+ 0
- 24
include/cpphibernate/driver/mariadb/schema.h ファイルの表示

@@ -1,24 +0,0 @@
#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/filter.h>
#include <cpphibernate/driver/mariadb/schema/schema.h>
#include <cpphibernate/driver/mariadb/schema/table.h>
#include <cpphibernate/driver/mariadb/schema/tables.h>

#include <cpphibernate/driver/mariadb/schema/attributes.inl>
#include <cpphibernate/driver/mariadb/schema/field.inl>
#include <cpphibernate/driver/mariadb/schema/fields.inl>
#include <cpphibernate/driver/mariadb/schema/filter.inl>
#include <cpphibernate/driver/mariadb/schema/schema.inl>
#include <cpphibernate/driver/mariadb/schema/table.inl>
#include <cpphibernate/driver/mariadb/schema/tables.inl>

+ 0
- 34
include/cpphibernate/driver/mariadb/schema/attributes.fwd.h ファイルの表示

@@ -1,34 +0,0 @@
#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
- 23
include/cpphibernate/driver/mariadb/schema/attributes.h ファイルの表示

@@ -1,23 +0,0 @@
#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;
};

}
end_namespace_cpphibernate_driver_mariadb

+ 0
- 31
include/cpphibernate/driver/mariadb/schema/field.fwd.h ファイルの表示

@@ -1,31 +0,0 @@
#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
- 213
include/cpphibernate/driver/mariadb/schema/field.h ファイルの表示

@@ -1,213 +0,0 @@
#pragma once

#include <cpphibernate/misc.h>
#include <cpphibernate/config.h>
#include <cpphibernate/schema/field.h>
#include <cpphibernate/schema/table.h>
#include <cpphibernate/schema/schema.h>
#include <cpphibernate/driver/mariadb/helper.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
{
public:
size_t id { 0 }; // unique id of the field
size_t dataset_id { 0 }; // unique id of the dataset type
size_t real_dataset_id { 0 }; // unique id of the real/unwrapped dataset type
size_t value_id { 0 }; // unique id of the value type
size_t real_value_id { 0 }; // unique id of the real/unwrapped value type

bool value_is_nullable { false }; // value is stored in a nullable container
bool value_is_pointer { false }; // value is stored in a pointer container
bool value_is_container { false }; // value is stored in a container
bool value_is_ordered { false }; // value is stored in a ordered container (vector, list, ...)
bool value_is_auto_incremented { false }; // value is a auto incremented field

table_t* table { nullptr }; // table this field belongs to
table_t* referenced_table { nullptr }; // table that belongs to the value (if exists)

std::string schema_name; // name of the SQL schema
std::string table_name; // name of the SQL table
std::string field_name; // name of the SQL field
std::string type; // SQL type name
std::string create_arguments; // additional arguments for CREATE TABLE command

std::string convert_to_open; // SQL code to open the "convert to" operation
std::string convert_to_close; // SQL code to close the "convert to" operation
std::string convert_from_open; // SQL code to open the "convert from" operation
std::string convert_from_close; // SQL code to close the "convert from" operation

attributes_t attributes; // attributes for the field

inline field_t() = default;
inline field_t(const field_t&) = delete;
inline field_t(field_t&& other)
: id (std::move(other).id)
, dataset_id (std::move(other).dataset_id)
, real_dataset_id (std::move(other).real_dataset_id)
, value_id (std::move(other).value_id)
, real_value_id (std::move(other).real_value_id)
, value_is_nullable (std::move(other).value_is_nullable)
, value_is_pointer (std::move(other).value_is_pointer)
, value_is_container (std::move(other).value_is_container)
, value_is_auto_incremented (std::move(other).value_is_auto_incremented)
, table (nullptr)
, referenced_table (nullptr)
, schema_name (std::move(other).schema_name)
, table_name (std::move(other).table_name)
, field_name (std::move(other).field_name)
, type (std::move(other).type)
, create_arguments (std::move(other).create_arguments)
, convert_to_open (std::move(other).convert_to_open)
, convert_to_close (std::move(other).convert_to_close)
, convert_from_open (std::move(other).convert_from_open)
, convert_from_close (std::move(other).convert_from_close)
, attributes (std::move(other).attributes)
{ }
virtual ~field_t() { };

void print (std::ostream& os) const;
virtual void update ();

/* CRUD */
using read_context_ptr = std::unique_ptr<read_context>;

virtual value_t foreign_create_update (const create_update_context& context) const;
virtual read_context_ptr foreign_read (const read_context& context, bool fake_context) const;

/* properties */
virtual value_t get (const data_context& context) const;
virtual void set (const data_context& context, const value_t&) const;
virtual bool is_default (const data_context& context) const;
virtual std::string generate_value (::cppmariadb::connection& connection) const;

/* statements */
virtual ::cppmariadb::statement& get_statement_foreign_one_delete(bool key_known) const;
virtual ::cppmariadb::statement& get_statement_foreign_many_update() const;

protected:
using statement_ptr = std::unique_ptr<::cppmariadb::statement>;

::cppmariadb::statement& get_statement_foreign_one_delete_impl(bool key_known, statement_ptr& known, statement_ptr& unknown) const;
::cppmariadb::statement& get_statement_foreign_many_update_impl(statement_ptr& statement) const;
};

/* simple_field_t */

template<typename T_field>
struct simple_field_t
: public field_t
{
using base_type = field_t;
using field_type = mp::decay_t<T_field>;
using getter_type = typename field_type::getter_type;
using dataset_type = mp::decay_t<typename getter_type::dataset_type>;
using real_dataset_type = misc::real_dataset_t<dataset_type>;
using value_type = mp::decay_t<typename getter_type::value_type>;
using real_value_type = misc::real_dataset_t<value_type>;
using type_props = type_properties<value_type>;

const field_type& field;

inline simple_field_t(const field_type& p_field)
: field_t ()
, field (p_field)
{ }

virtual void update() override;
};

/* value_field_t */

template<typename T_field>
struct value_field_t
: public simple_field_t<T_field>
{
using base_type = simple_field_t<T_field>;
using field_type = typename base_type::field_type;
using getter_type = typename base_type::getter_type;
using dataset_type = typename base_type::dataset_type;
using real_dataset_type = typename base_type::dataset_type;
using value_type = typename base_type::value_type;
using real_value_type = typename base_type::real_value_type;
using type_props = typename base_type::type_props;

using base_type::base_type;

static_assert(mp::is_same<dataset_type, real_dataset_type>::value, "internal error: dataset type mismatch!");

virtual void update () override;
virtual value_t get (const data_context& context) const override;
virtual void set (const data_context& context, const value_t& value) const override;
};

/* primary_key_field_t */

template<typename T_field>
struct primary_key_field_t
: public value_field_t<T_field>
{
using base_type = value_field_t<T_field>;
using field_type = typename base_type::field_type;
using dataset_type = typename base_type::dataset_type;
using value_type = typename base_type::value_type;
using key_props = key_properties<value_type>;

using base_type::base_type;

virtual void update () override;
virtual bool is_default (const data_context& context) const override;
virtual std::string generate_value(::cppmariadb::connection& connection) const override;
};

/* data_field_t */

template<typename T_field>
struct data_field_t
: public value_field_t<T_field>
{
using base_type = value_field_t<T_field>;

using base_type::base_type;
};

/* foreign_table_field_t */

template<typename T_field>
struct foreign_table_field_t
: public simple_field_t<T_field>
{
public:
using base_type = simple_field_t<T_field>;
using value_type = typename base_type::value_type;
using real_value_type = typename base_type::real_value_type;
using dataset_type = typename base_type::dataset_type;

using base_type::base_type;

public:
/* CRUD */
virtual value_t foreign_create_update(const create_update_context& context) const override;
virtual read_context_ptr foreign_read (const read_context& context, bool fake_context) const override;

/* statements */
virtual ::cppmariadb::statement& get_statement_foreign_one_delete(bool key_known) const override;
virtual ::cppmariadb::statement& get_statement_foreign_many_update() const override;

private:
using statement_ptr = std::unique_ptr<::cppmariadb::statement>;

mutable statement_ptr _statement_foreign_one_delete_key_known;
mutable statement_ptr _statement_foreign_one_delete_key_unknown;
mutable statement_ptr _statement_foreign_many_update;
};

}
end_namespace_cpphibernate_driver_mariadb

+ 0
- 228
include/cpphibernate/driver/mariadb/schema/field.inl ファイルの表示

@@ -1,228 +0,0 @@
#pragma once

#include <cpphibernate/driver/mariadb/schema/field.h>
#include <cpphibernate/driver/mariadb/impl/create_update.h>

beg_namespace_cpphibernate_driver_mariadb
{

/* simple_field_t */

template<typename T_field>
void simple_field_t<T_field>
::update()
{
base_type::update();

id = misc::get_type_id(hana::type_c<field_type>);
dataset_id = misc::get_type_id(hana::type_c<dataset_type>);
real_dataset_id = misc::get_type_id(hana::type_c<real_dataset_type>);
value_id = misc::get_type_id(hana::type_c<value_type>);
real_value_id = misc::get_type_id(hana::type_c<real_value_type>);

value_is_nullable = misc::is_nullable<value_type>::value;
value_is_pointer = misc::is_pointer<value_type>::value;
value_is_container = misc::is_container<value_type>::value;
value_is_ordered = misc::is_ordered<value_type>::value;
}

/* value_field_t */

template<typename T_field>
void value_field_t<T_field>
::update()
{
base_type::update();

this->type = type_props::type();

if (type_props::convert_to_open())
this->convert_to_open = this->convert_to_open + type_props::convert_to_open();
if (type_props::convert_to_close())
this->convert_to_close = type_props::convert_to_close() + this->convert_to_close;
if (type_props::convert_from_open())
this->convert_from_open = this->convert_from_open + type_props::convert_from_open();
if (type_props::convert_from_close())
this->convert_from_close = type_props::convert_from_close() + this->convert_from_close;
}

template<typename T_field>
value_t value_field_t<T_field>
::get(const data_context& context) const
{
auto& dataset = context.get<dataset_type>();
return type_props::convert_from(this->field.getter(dataset));
}

template<typename T_field>
void value_field_t<T_field>
::set(const data_context& context, const value_t& value) const
{
auto& dataset = context.get<dataset_type>();
this->field.setter(dataset, type_props::convert_to(value));
}

/* primary_key_field_t */

template<typename T_field>
void primary_key_field_t<T_field>
::update()
{
base_type::update();

this->value_is_auto_incremented = key_props::auto_generated::value;
}

template<typename T_field>
bool primary_key_field_t<T_field>
::is_default(const data_context& context) const
{
auto& dataset = context.get<dataset_type>();
return key_props::is_default(this->field.getter(dataset));
}

template<typename T_field>
std::string primary_key_field_t<T_field>
::generate_value(::cppmariadb::connection& connection) const
{
auto ret = connection.execute_used(key_props::create_key_query);
if (!ret || !ret->next())
throw misc::hibernate_exception("unable to generate key value!");
return ret->current()->at(0).template get<std::string>();
}

/* foreign_table_field_t */

template<typename T_field>
value_t foreign_table_field_t<T_field>
::foreign_create_update(const create_update_context& context) const
{
auto& dataset = context.get<dataset_type>();
auto& foreign = this->field.getter(dataset);
auto next_context = change_context(context, foreign);

using foreign_dataset_type = mp::decay_t<decltype(foreign)>;
return create_update_impl_t<foreign_dataset_type>::apply(
next_context,
false);
}

template<typename T_field>
read_context_ptr foreign_table_field_t<T_field>
::foreign_read(const read_context& context, bool fake_context) const
{
if (!fake_context)
{
auto& dataset = context.get<dataset_type>();
auto& member = this->field.getter(dataset);
auto new_context = make_read_context(member, context.schema, context.connection, context.filter);
using context_type = mp::decay_t<decltype(new_context)>;
return std::make_unique<context_type>(new_context);
}
else
{
auto new_context = make_fake_context(hana::type_c<value_type>, context.schema, context.connection, context.filter);
using context_type = mp::decay_t<decltype(new_context)>;
return std::make_unique<context_type>(new_context);
}
}

template<typename T_field>
::cppmariadb::statement& foreign_table_field_t<T_field>
::get_statement_foreign_one_delete(bool key_known) const
{
return base_type::get_statement_foreign_one_delete_impl(
key_known,
_statement_foreign_one_delete_key_known,
_statement_foreign_one_delete_key_unknown);
}

template<typename T_field>
::cppmariadb::statement& foreign_table_field_t<T_field>
::get_statement_foreign_many_update() const
{ return base_type::get_statement_foreign_many_update_impl(_statement_foreign_many_update); }

namespace __impl
{

/* is_primary_key_field */

template<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_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_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_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 return_type = field_type_t<schema_type, field_type>;
using primary_key_type = primary_key_field_t<field_type>;
return_type ret(field);
ret.schema_name = schema.name;
ret.table_name = table.name;
ret.field_name = field.name;
ret.attributes = make_attributes(field.attributes);
hana::eval_if(
hana::equal(hana::type_c<return_type>, hana::type_c<primary_key_type>),
[&ret](){
ret.field_name = ret.table_name + "_" + ret.field_name;
}, [](){ });
return ret;
}
};

}

}
end_namespace_cpphibernate_driver_mariadb

+ 0
- 29
include/cpphibernate/driver/mariadb/schema/fields.fwd.h ファイルの表示

@@ -1,29 +0,0 @@
#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
- 25
include/cpphibernate/driver/mariadb/schema/fields.h ファイルの表示

@@ -1,25 +0,0 @@
#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;
};

}
end_namespace_cpphibernate_driver_mariadb

+ 0
- 55
include/cpphibernate/driver/mariadb/schema/fields.inl ファイルの表示

@@ -1,55 +0,0 @@
#pragma once

#include <cpphibernate/driver/mariadb/schema/fields.h>

beg_namespace_cpphibernate_driver_mariadb
{

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
- 13
include/cpphibernate/driver/mariadb/schema/filter.fwd.h ファイルの表示

@@ -1,13 +0,0 @@
#pragma once

#include <cpphibernate/config.h>

beg_namespace_cpphibernate_driver_mariadb
{

/* filter_t */

struct filter_t;

}
end_namespace_cpphibernate_driver_mariadb

+ 0
- 54
include/cpphibernate/driver/mariadb/schema/filter.h ファイルの表示

@@ -1,54 +0,0 @@
#pragma once

#include <set>
#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/filter.fwd.h>
#include <cpphibernate/driver/mariadb/schema/schema.fwd.h>

beg_namespace_cpphibernate_driver_mariadb
{

namespace __impl
{

/* filter_add_element */

template<typename T, typename = void>
struct filter_add_element_impl;

constexpr decltype(auto) filter_add_element = misc::make_generic_predicate<__impl::filter_add_element_impl> { };

}

/* filter_t */

struct filter_t
{
public:
using field_set_type = std::set<const field_t*>;
using table_set_type = std::set<const table_t*>;

size_t cache_id { 0 };
bool exclusive { true };
field_set_type fields;
table_set_type tables;

inline bool is_excluded(const table_t& table) const;
inline bool is_excluded(const field_t& field) const;

template<typename... T_args>
inline void set_inclusive(const schema_t& schema, T_args&&... args);

template<typename... T_args>
inline void set_exclusive(const schema_t& schema, T_args&&... args);

inline void clear();

private:
void update_tables();
};

}
end_namespace_cpphibernate_driver_mariadb

+ 0
- 122
include/cpphibernate/driver/mariadb/schema/filter.inl ファイルの表示

@@ -1,122 +0,0 @@
#pragma once

#include <cpphibernate/driver/mariadb/schema/filter.h>
#include <cpphibernate/driver/mariadb/schema/schema.inl>

beg_namespace_cpphibernate_driver_mariadb
{

namespace __impl
{

/* filter_add_element_impl */

template<typename T, typename>
struct filter_add_element_impl
{
template<typename... T_args>
static constexpr decltype(auto) apply(T_args&&... args)
{ static_assert(sizeof...(args) == -1, "Invalid parameters for mariadb::filter_add_element(...)!"); }
};

template<typename T_table>
struct filter_add_element_impl<
mp::list<filter_t&, const schema_t&, T_table>,
mp::enable_if_c<
schema::is_table<mp::decay_t<T_table>>::value>>
{
static constexpr decltype(auto) apply(filter_t& filter, const schema_t& schema, const T_table& table)
{
auto dataset_id = misc::get_type_id(table.wrapped_dataset);
auto& t = schema.table(dataset_id);
filter.tables.emplace(&t);
for (auto& ptr : t.fields)
{
filter.fields.emplace(ptr.get());
}
}
};

template<typename T_field>
struct filter_add_element_impl<
mp::list<filter_t&, const schema_t&, T_field>,
mp::enable_if_c<
schema::is_field<mp::decay_t<T_field>>::value>>
{
static constexpr decltype(auto) apply(filter_t& filter, const schema_t& schema, const T_field& field)
{
auto field_id = misc::get_type_id(hana::type_c<mp::decay_t<T_field>>);
auto& f = schema.field(field_id);
filter.fields.emplace(&f);
filter.tables.emplace(f.table);
}
};

}

/* filter_t */

bool filter_t::is_excluded(const table_t& table) const
{
auto ret = static_cast<bool>(tables.count(&table));
if (!exclusive)
ret = !ret;
return ret;
}

bool filter_t::is_excluded(const field_t& field) const
{
auto ret = static_cast<bool>(fields.count(&field));
if (!exclusive)
ret = !ret;
return ret;
}

template<typename... T_args>
void filter_t::set_inclusive(const schema_t& schema, T_args&&... args)
{
clear();
exclusive = false;
cache_id = static_cast<size_t>(utl::get_unique_id<filter_t, mp::decay_t<T_args>...>());
int dummy[] = { 0, (__impl::filter_add_element(*this, schema, std::forward<T_args>(args)), void(), 0)... };
(void)dummy;
}

template<typename... T_args>
void filter_t::set_exclusive(const schema_t& schema, T_args&&... args)
{
clear();
exclusive = true;
cache_id = static_cast<size_t>(utl::get_unique_id<filter_t, mp::decay_t<T_args>...>());
int dummy[] = { 0, (__impl::filter_add_element(*this, schema, std::forward<T_args>(args)), void(), 0)... };
(void)dummy;

// remove excluded tables if not all fields are excluded
auto it = tables.begin();
while (it != tables.end())
{
bool removed = false;
for (auto& field : (*it)->fields)
{
if (fields.count(field.get()))
{
it = tables.erase(it);
removed = true;
break;
}
}
if (!removed)
++it;
}
}

void filter_t::clear()
{
cache_id = 0;
exclusive = true;
fields.clear();
tables.clear();
}

}
end_namespace_cpphibernate_driver_mariadb

+ 0
- 27
include/cpphibernate/driver/mariadb/schema/schema.fwd.h ファイルの表示

@@ -1,27 +0,0 @@
#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
- 37
include/cpphibernate/driver/mariadb/schema/schema.h ファイルの表示

@@ -1,37 +0,0 @@
#pragma once

#include <cpphibernate/misc.h>
#include <cpphibernate/config.h>
#include <cpphibernate/driver/mariadb/helper/context.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;

const table_t& table(size_t dataset_id) const;
const field_t& field(size_t field_id) const;

/* CRUD */
void init(const init_context& context) const;
};

}
end_namespace_cpphibernate_driver_mariadb

+ 0
- 40
include/cpphibernate/driver/mariadb/schema/schema.inl ファイルの表示

@@ -1,40 +0,0 @@
#pragma once

#include <cpphibernate/driver/mariadb/schema/schema.h>

beg_namespace_cpphibernate_driver_mariadb
{

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
- 31
include/cpphibernate/driver/mariadb/schema/table.fwd.h ファイルの表示

@@ -1,31 +0,0 @@
#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
- 208
include/cpphibernate/driver/mariadb/schema/table.h ファイルの表示

@@ -1,208 +0,0 @@
#pragma once

#include <memory>
#include <vector>

#include <cppmariadb.h>
#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>
#include <cpphibernate/driver/mariadb/schema/filter.fwd.h>
#include <cpphibernate/driver/mariadb/helper/context.h>

beg_namespace_cpphibernate_driver_mariadb
{

/* table_t */

struct table_t
{
public:
size_t dataset_id { 0 };
size_t base_dataset_id { 0 };
size_t table_id { 0 };
bool is_used_in_container { false };

std::vector<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() { };

void print(std::ostream& os) const;

const table_t* get_derived_by_table_id(size_t id) const;
const table_t* get_derived_by_dataset_id(size_t id) const;

virtual void emplace (const read_context& context) const;
std::string get_where_primary_key(const data_context& context) const;
std::string build_delete_query (const std::string* where) const;

/* CRUD */
inline void init_stage1(const init_context& context) const
{ return init_stage1_exec(context); }

inline void init_stage2(const init_context& context) const
{ return init_stage2_exec(context); }

inline decltype(auto) create_update(const create_update_context& context) const
{ return create_update_intern(context); }

inline void read(const read_context& context) const
{ return read_exec(context); }

inline void destroy(const destroy_context& context) const
{ return destroy_intern(context); }

private:
template<typename T_schema, typename T_table, typename T_base_dataset>
friend struct table_simple_t;

template<typename T_schema, typename T_table, typename T_base_dataset>
friend struct table_polymorphic_t;

using statement_ptr = std::unique_ptr<::cppmariadb::statement>;
using map_key = std::tuple<size_t, const field_t*>;
using statement_map = std::map<map_key, ::cppmariadb::statement>;

mutable statement_ptr _statement_key_from_base;
mutable statement_ptr _statement_create_table;
mutable statement_ptr _statement_alter_table;
mutable statement_ptr _statement_insert_into;
mutable statement_map _statement_select_static;
mutable statement_map _statement_select_dynamic;
mutable statement_map _statement_update;
mutable statement_ptr _statement_foreign_many_delete;
mutable statement_ptr _statement_delete;

::cppmariadb::statement& get_statement_key_from_base() const;
::cppmariadb::statement& get_statement_create_table() const;
::cppmariadb::statement* get_statement_alter_table() const;
::cppmariadb::statement* get_statement_insert_into() const;
::cppmariadb::statement& get_statement_select(const read_context& context) const;
::cppmariadb::statement* get_statement_update(const filter_t& filter, const field_t* owner) const;
::cppmariadb::statement& get_statement_foreign_many_delete() const;
::cppmariadb::statement& get_statement_delete() const;

void execute_foreign_many_delete(const base_context& context) const;

std::string execute_create_update(
const create_update_context& context,
::cppmariadb::statement* statement) const;

std::string get_primary_key(const data_context& context) const;
std::string get_key_from_base(const data_context& context) const;

virtual std::string create_update_base(const create_update_context& context) const;

protected:
using table_set = std::set<const table_t*>;

void init_stage1_exec (const init_context& context) const;
void init_stage2_exec (const init_context& context) const;

virtual std::string create_update_intern(const create_update_context& context) const;
std::string create_update_exec (const create_update_context& context) const;

void read_exec (const read_context& context) const;

virtual void destroy_intern (const destroy_context& context) const;
void destroy_exec (const destroy_context& context) const;
void destroy_cleanup (const base_context& context, table_set& processed, bool check_derived, bool check_base) const;
};

/* table_simple_t */

template<typename T_schema, typename T_table, typename T_base_dataset>
struct table_simple_t
: public table_t
{
public:
using schema_type = T_schema;
using table_type = T_table;
using base_dataset_type = T_base_dataset;
using dataset_type = typename table_type::dataset_type;

const schema_type& schema;
const table_type& table;

inline table_simple_t(const schema_type& p_schema, const table_type& p_table)
: schema(p_schema)
, table (p_table)
{ }

inline table_simple_t(const table_simple_t&) = delete;

inline table_simple_t(table_simple_t&& other)
: table_t(std::move(other))
, schema (std::move(other).schema)
, table (std::move(other).table)
{ }
};

/* table_polymorphic_t */

template<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>
{
public:
using base_type = table_simple_t<T_schema, T_table, T_base_dataset>;
using schema_type = typename base_type::schema_type;
using table_type = typename base_type::table_type;
using base_dataset_type = typename base_type::base_dataset_type;
using dataset_type = typename table_type::dataset_type;
using real_dataset_type = misc::real_dataset_t<dataset_type>;

using base_type::base_type;

virtual void emplace(const read_context& context) const override;

private:
template<typename T_dataset, typename T_pred, typename T_include_self>
constexpr void for_each_derived(T_dataset& dataset, const T_include_self& include_self, const T_pred& pred) const;

protected:
virtual std::string create_update_intern(const create_update_context& context) const override;
virtual void destroy_intern (const destroy_context& context) const override;

private:
virtual std::string create_update_base(const create_update_context& context) const override;
};

}
end_namespace_cpphibernate_driver_mariadb

+ 0
- 218
include/cpphibernate/driver/mariadb/schema/table.inl ファイルの表示

@@ -1,218 +0,0 @@
#pragma once

#include <cpphibernate/config.h>
#include <cpphibernate/driver/mariadb/schema/table.h>

beg_namespace_cpphibernate_driver_mariadb
{

/* table_polymorphic_t */

template<typename T_schema, typename T_table, typename T_base_dataset>
void table_polymorphic_t<T_schema, T_table, T_base_dataset>
::emplace(const read_context& context) const
{
hana::eval_if(
std::is_abstract<real_dataset_type> { },
[](){
throw misc::hibernate_exception(std::string("can not create dataset of abstract type: ")
+ utl::type_helper<real_dataset_type>::name());
},
[&context, this](auto _){
_(context).template emplace<real_dataset_type>(this);
});
}

template<typename T_schema, typename T_table, typename T_base_dataset>
template<typename T_dataset, typename T_pred, typename T_include_self>
constexpr void table_polymorphic_t<T_schema, T_table, T_base_dataset>
::for_each_derived(T_dataset& dataset, const T_include_self& include_self, const T_pred& pred) const
{
auto derived_types = hana::filter(
schema::get_all_derived_types(this->schema, hana::type_c<dataset_type>),
[&](auto type){
return hana::and_(
hana::not_(hana::trait<std::is_abstract>(type)),
hana::or_(
type != hana::type_c<dataset_type>,
include_self));
});

hana::for_each(derived_types, [&](auto& type){
using derived_type = misc::decay_unwrap_t<decltype(type)>;
auto* derived = dynamic_cast<derived_type*>(&dataset);
if (derived)
pred(*derived);
});
}

template<typename T_schema, typename T_table, typename T_base_dataset>
std::string table_polymorphic_t<T_schema, T_table, T_base_dataset>
::create_update_intern(const create_update_context& context) const
{
bool done = false;
auto& dataset = context.get<dataset_type>();
for_each_derived(dataset, hana::false_c, [&](auto& derived_dataset){
if (!done)
{
using derived_dataset_type = mp::decay_t<decltype(derived_dataset)>;
auto derived_dataset_id = misc::get_type_id(hana::type_c<derived_dataset_type>);
auto derived_table = this->get_derived_by_dataset_id(derived_dataset_id);
if (!derived_table)
{
throw misc::hibernate_exception(static_cast<std::ostringstream&>(std::ostringstream { }
<< "unable to find derived table info for dataset '"
<< utl::type_helper<derived_dataset_type>::name() << "'!").str());
}
derived_table->create_update(change_context(context, derived_dataset));
done = true;
}
});

return done
? *this->primary_key_field->get(context)
: this->create_update_exec(context);
}

template<typename T_schema, typename T_table, typename T_base_dataset>
void table_polymorphic_t<T_schema, T_table, T_base_dataset>
::destroy_intern(const destroy_context& context) const
{
bool done = false;
auto& dataset = context.get<dataset_type>();
for_each_derived(dataset, hana::false_c, [&](auto& derived_dataset){
if (!done)
{
using derived_dataset_type = mp::decay_t<decltype(derived_dataset)>;
auto derived_dataset_id = misc::get_type_id(hana::type_c<derived_dataset_type>);
auto derived_table = this->get_derived_by_dataset_id(derived_dataset_id);
if (!derived_table)
{
throw misc::hibernate_exception(static_cast<std::ostringstream&>(std::ostringstream { }
<< "unable to find derived table info for dataset '"
<< utl::type_helper<derived_dataset_type>::name() << "'!").str());
}
auto new_context = change_context(context, derived_dataset);
derived_table->destroy(new_context);
done = true;
}
});

if (!done)
{
this->destroy_exec(context);
}
}

template<typename T_schema, typename T_table, typename T_base_dataset>
std::string table_polymorphic_t<T_schema, T_table, T_base_dataset>
::create_update_base(const create_update_context& context) const
{
return hana::eval_if(
mp::is_same<base_dataset_type, void> { },
[this]()->std::string {
throw misc::hibernate_exception(static_cast<std::ostringstream&>(std::ostringstream { }
<< "'" << this->table_name << "' does not have a base table").str());
},
[this, &context](auto _)->std::string {
using tmp_type = misc::decay_unwrap_t<decltype(_(hana::type_c<base_dataset_type>))>;
assert(this->base_table);
auto& dataset = context.get<dataset_type>();
auto& base = static_cast<tmp_type&>(dataset);
return this->base_table->create_update_exec(change_context(context, base));
});
}

namespace __impl
{

/* make_dataset_id_vector */

struct make_dataset_id_vector_impl
{
template<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 real_dataset_type = misc::real_dataset_t<dataset_type>;
using table_type = table_type_t<dataset_type, base_type>;

static_assert(mp::is_same<dataset_type, real_dataset_type>::value, "table cn only be created for simple dataset types (not for containers)!");

table_type ret(schema, table);
ret.dataset_id = misc::get_type_id(table.wrapped_dataset);
ret.base_dataset_id = misc::get_type_id(wrapped_base_type { });
ret.derived_dataset_ids = make_dataset_id_vector(derived_wrapped_types_type { });
ret.table_id = hana::value(table.table_id);
ret.schema_name = schema.name;
ret.table_name = table.name;
ret.fields = make_fields(schema, table);
return ret;
}
};

}

}
end_namespace_cpphibernate_driver_mariadb

+ 0
- 29
include/cpphibernate/driver/mariadb/schema/tables.fwd.h ファイルの表示

@@ -1,29 +0,0 @@
#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
- 23
include/cpphibernate/driver/mariadb/schema/tables.h ファイルの表示

@@ -1,23 +0,0 @@
#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;
};

}
end_namespace_cpphibernate_driver_mariadb

+ 0
- 55
include/cpphibernate/driver/mariadb/schema/tables.inl ファイルの表示

@@ -1,55 +0,0 @@
#pragma once

#include <cpphibernate/driver/mariadb/schema/tables.h>

beg_namespace_cpphibernate_driver_mariadb
{

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

+ 37
- 5
include/cpphibernate/misc/equality_compare.h ファイルの表示

@@ -5,26 +5,58 @@
namespace cpphibernate
{

namespace __impl
{

template<typename T_lhs, typename T_rhs>
using equality_compare_equal = mp::bool_t<hana::value(hana::equal(
hana::type_c<mp::decay_t<T_lhs>>,
hana::type_c<mp::decay_t<T_rhs>>))>;

template<typename T_lhs, typename T_rhs>
using equality_compare_not_equal = mp::bool_t<hana::value(hana::not_equal(
hana::type_c<mp::decay_t<T_lhs>>,
hana::type_c<mp::decay_t<T_rhs>>))>;

}

/**
* @brief Tag all objects that are equality comparable to each other.
*
* @tparam T_group Type used for groupig different types.
*/
template<typename T_group>
struct tag_equality_comparable;
struct tag_equality_comparable
{
static constexpr decltype(auto) equality_compare_group = hana::type_c<T_group>;
};

/**
* @brief Equality compare for all objects that has the quality compare tag
*/
template<typename T_lhs, typename T_rhs>
constexpr decltype(auto) operator == (T_lhs&& lhs, T_rhs&& rhs);
constexpr auto operator == (T_lhs&&, T_rhs&&)
-> mp::enable_if_t<
mp::is_valid_v<decltype(std::declval<T_lhs>().equality_compare_group)>
&& mp::is_valid_v<decltype(std::declval<T_rhs>().equality_compare_group)>
&& mp::is_same_v<
typename decltype(+std::declval<T_lhs>().equality_compare_group)::type,
typename decltype(+std::declval<T_rhs>().equality_compare_group)::type>,
__impl::equality_compare_equal<T_lhs, T_rhs>>
{ return __impl::equality_compare_equal<T_lhs, T_rhs> { }; }

/**
* @brief Equality compare for all objects that has the quality compare tag
*/
template<typename T_lhs, typename T_rhs>
constexpr decltype(auto) operator != (T_lhs&& lhs, T_rhs&& rhs);
constexpr auto operator != (T_lhs&&, T_rhs&&)
-> mp::enable_if_t<
mp::is_valid_v<decltype(std::declval<T_lhs>().equality_compare_group)>
&& mp::is_valid_v<decltype(std::declval<T_rhs>().equality_compare_group)>
&& mp::is_same_v<
typename decltype(+std::declval<T_lhs>().equality_compare_group)::type,
typename decltype(+std::declval<T_rhs>().equality_compare_group)::type>,
__impl::equality_compare_not_equal<T_lhs, T_rhs>>
{ return __impl::equality_compare_not_equal<T_lhs, T_rhs> { }; }

}

#include "equality_compare.inl"

+ 0
- 61
include/cpphibernate/misc/equality_compare.inl ファイルの表示

@@ -1,61 +0,0 @@
#pragma once

#include "equality_compare.h"

namespace cpphibernate
{

namespace __impl
{

template<typename T_lhs, typename T_rhs, typename = void>
struct equality_compare_impl
{
static constexpr decltype(auto) equal(T_lhs&&, T_rhs&&)
{ static_assert(sizeof(T_lhs) == -1, "Unable to equality compare these two types."); }

static constexpr decltype(auto) not_equal(T_lhs&&, T_rhs&&)
{ static_assert(sizeof(T_lhs) == -1, "Unable to equality compare these two types."); }
};

template<typename T_lhs, typename T_rhs>
struct equality_compare_impl<
T_lhs,
T_rhs,
mp::enable_if_t<
mp::is_valid_v<typename T_lhs::equality_compare_group_type>
&& mp::is_valid_v<typename T_rhs::equality_compare_group_type>
&& mp::is_same_v<
typename T_lhs::equality_compare_group_type,
typename T_rhs::equality_compare_group_type>>>
{
static constexpr decltype(auto) equal(T_lhs&&, T_rhs&&)
{ return hana::type_c<mp::decay_t<T_lhs>> == hana::type_c<mp::decay_t<T_rhs>>; }

static constexpr decltype(auto) not_equal(T_lhs&&, T_rhs&&)
{ return hana::type_c<mp::decay_t<T_lhs>> != hana::type_c<mp::decay_t<T_rhs>>; }
};

};

template<typename T_group>
struct tag_equality_comparable
{
using equality_compare_group_type = T_group;
};

template<typename T_lhs, typename T_rhs>
constexpr decltype(auto) operator == (T_lhs&& lhs, T_rhs&& rhs)
{
using equality_compare_type = __impl::equality_compare_impl<T_lhs, T_rhs>;
return equality_compare_type::equal(std::forward<T_lhs>(lhs), std::forward<T_rhs>(rhs));
}

template<typename T_lhs, typename T_rhs>
constexpr decltype(auto) operator != (T_lhs&& lhs, T_rhs&& rhs)
{
using equality_compare_type = __impl::equality_compare_impl<T_lhs, T_rhs>;
return equality_compare_type::not_equal(std::forward<T_lhs>(lhs), std::forward<T_rhs>(rhs));
}

}

+ 33
- 5
include/cpphibernate/misc/print_container.inl ファイルの表示

@@ -1,6 +1,7 @@
#pragma once

#include <cppcore/misc/indent.h>
#include <cppcore/conversion/string.h>

#include "print_container.h"

@@ -77,8 +78,10 @@ namespace cpphibernate
{ static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_print_container(...)!"); }
};

template<typename T_container, typename T_func>
struct print_container_builder<mp::list<T_container, bool, T_func>, void>
template<typename T_container, typename T_bool, typename T_func>
struct print_container_builder<
mp::list<T_container, T_bool, T_func>,
mp::enable_if_t<mp::is_same_v<bool, mp::decay_t<T_bool>>>>
{
static constexpr decltype(auto) apply(T_container&& container, bool do_indent, T_func&& func)
{
@@ -91,14 +94,16 @@ namespace cpphibernate
}
};

template<typename T_container>
struct print_container_builder<mp::list<T_container, bool>, void>
template<typename T_container, typename T_bool>
struct print_container_builder<
mp::list<T_container, T_bool>,
mp::enable_if_t<mp::is_same_v<bool, mp::decay_t<T_bool>>>>
{
static constexpr decltype(auto) apply(T_container&& container, bool do_indent)
{
using namespace ::cppcore;

make_print_container(
return make_print_container(
std::forward<T_container>(container),
do_indent,
[do_indent](auto& os, auto& value)
@@ -114,3 +119,26 @@ namespace cpphibernate
}

}

namespace std
{

template<
typename T_print_container,
typename T_char,
typename T_traits>
inline auto
operator << (
basic_ostream<T_char, T_traits>& os,
const T_print_container& ctnr)
-> ::cppmp::enable_if_t<
::cppmp::is_specialization_of_v<
::cppmp::decay_t<T_print_container>,
::cpphibernate::__impl::print_container>,
basic_ostream<T_char, T_traits>&>
{
ctnr.print(os);
return os;
}

}

+ 61
- 0
include/cpphibernate/misc/type_helper.h ファイルの表示

@@ -29,6 +29,67 @@ namespace cpphibernate
template<typename T>
using decay_unwrap_t = typename mp::decay_t<T>::type;

/**
* @brief Unwrap the passed hana::type and return an object of the inner type.
*/
template<typename T>
constexpr decltype(auto) unwrap(T&& t)
{ return typename decltype(+t)::type { }; }

/**
* @brief Get a unique ID for the passed type
*/
template<typename T_type>
constexpr decltype(auto) get_type_id(T_type&&);

/**
* @brief Evaluates to true_t if the passed type is a container, false_t otherwise.
*/
template<typename T>
struct is_container;

/**
* @brief Is true if the passed type is a container, false otherwise.
*/
template<typename T>
constexpr decltype(auto) is_container_v = is_container<T>::value;

/**
* @brief Evaluates to true_t if the passed type is an ordered container type, false_t otherwise.
*/
template<typename T>
struct is_ordered;

/**
* @brief Is true if the passed type is an ordered container type, false otherwise.
*/
template<typename T>
constexpr decltype(auto) is_ordered_v = is_ordered<T>::value;

/**
* @brief Evaluates to true_t if the passed type is a nullable type, false_t otherwise.
*/
template<typename T>
struct is_pointer;

/**
* @brief Is true if the passed type is a pointer type, false otherwise.
*/
template<typename T>
constexpr decltype(auto) is_pointer_v = is_pointer<T>::value;

/**
* @brief Evaluates to true_t if the passed type is a pointer type, false_t otherwise.
*/
template<typename T>
struct is_nullable;

/**
* @brief Is true if the passed type is a nullable type, false otherwise.
*/
template<typename T>
constexpr decltype(auto) is_nullable_v = is_nullable<T>::value;

}

#include "type_helper.inl"

+ 75
- 0
include/cpphibernate/misc/type_helper.inl ファイルの表示

@@ -50,4 +50,79 @@ namespace cpphibernate
: public __impl::real_dataset_impl<T>
{ };

/* get_dataset_id */

namespace __impl
{
struct counter_type_id
{ };
}

template<typename T_type>
constexpr decltype(auto) get_type_id(T_type&&)
{ return cppcore::get_unique_id<__impl::counter_type_id, mp::decay_t<T_type>>(); }

/* is_container */

template<typename T>
struct is_container
: public mp::false_t
{ };

template<typename T, typename... T_args>
struct is_container<std::list<T, T_args...>>
: public mp::true_t
{ };

template<typename T, typename... T_args>
struct is_container<std::vector<T, T_args...>>
: public mp::true_t
{ };

/* is_ordered */

template<typename T>
struct is_ordered
: public mp::false_t
{ };

template<typename T, typename... T_args>
struct is_ordered<std::list<T, T_args...>>
: public mp::true_t
{ };

template<typename T, typename... T_args>
struct is_ordered<std::vector<T, T_args...>>
: public mp::true_t
{ };

/* is_pointer */

template<typename T>
struct is_pointer
: public mp::false_t
{ };

template<typename T, typename... T_args>
struct is_pointer<std::unique_ptr<T, T_args...>>
: public mp::true_t
{ };

template<typename T>
struct is_pointer<std::shared_ptr<T>>
: public mp::true_t
{ };

/* is_nullable */

template<typename T>
struct is_nullable
: public is_pointer<T>
{ };

template<typename T>
struct is_nullable<cppcore::nullable<T>>
: public mp::true_t
{ };

}

+ 16
- 0
include/cpphibernate/schema/attribute.h ファイルの表示

@@ -26,6 +26,22 @@ namespace schema {
{
using inner_type = T_inner;
using this_type = attribute_t<inner_type>;

/*
template<typename T_other>
constexpr decltype(auto) operator==(T_other&&) const
{
return ::boost::hana::type<mp::decay_t<decltype(*this)>> { } ==
::boost::hana::type<mp::decay_t<T_other>> { };
}

template<typename T_other>
constexpr decltype(auto) operator!=(T_other&&) const
{
return ::boost::hana::type<mp::decay_t<decltype(*this)>> { } !=
::boost::hana::type<mp::decay_t<T_other>> { };
}
*/
};

struct hex_t { static constexpr decltype(auto) name = "hex"; };


+ 80
- 0
include/cpphibernate/schema/field.h ファイルの表示

@@ -1,6 +1,7 @@
#pragma once

#include <cpphibernate/config.h>
#include <cpphibernate/misc/type_helper.h>

namespace cpphibernate {
namespace schema {
@@ -8,6 +9,85 @@ namespace schema {
namespace __impl
{

/**
* @brief Tag class to mark field types.
*/
struct tag_field
{ };

/**
* @brief Represents a data field in the schema.
*
* @tparam T_name Type of the name of the field.
* @tparam T_getter Type of the getter of the field.
* @tparam T_setter Type of the setter of the field.
* @tparam T_attributes Type of the attributes of the field.
*/
template<typename T_name, typename T_getter, typename T_setter, typename T_attributes>
struct field_t
: public tag_field
, public tag_equality_comparable<tag_field>
{
using name_type = T_name;
using getter_type = T_getter;
using setter_type = T_setter;
using dataset_type = typename mp::decay_t<getter_type>::object_type;
using real_dataset_type = real_dataset_t<dataset_type>;
using value_type = typename mp::decay_t<getter_type>::value_type;
using real_value_type = real_dataset_t<value_type>;
using attributes_type = T_attributes;
using this_type = field_t<name_type, getter_type, setter_type, attributes_type>;

name_type name; //!< Name of the field.
getter_type getter; //!< Getter of the field, to get values from the dataset.
setter_type setter; //!< Setter of the field, to set values of the dataset.
attributes_type attributes; //!< List of attributes for this field.

hana::type<value_type> wrapped_value_type; //!< Type of the stoed value.
hana::type<dataset_type> wrapped_dataset_type; //!< Type of the real stored value (containers are removed).
hana::type<real_value_type> wrapped_real_value_type; //!< Type of the dataset this fields uses.
hana::type<real_dataset_type> wrapped_real_dataset_type; //!< Type of the read dataset (contaiers are removed).

/**
* @brief Constrcutor.
*
* @param[in] p_name Name of the field.
* @param[in] p_getter Getter to receive the represented value from the dataset.
* @param[in] p_setter Setter to set the represented value at the dataset.
* @param[in] p_attributes List of attributes of the field.
*/
constexpr field_t(
T_name&& p_name,
T_getter&& p_getter,
T_setter&& p_setter,
T_attributes&& p_attributes);

/**
* @brief Move constructor.
*/
constexpr field_t(field_t&&) = default;

/**
* @brief Copy constructor.
*/
constexpr field_t(const field_t&) = delete;

/**
* @brief Move assignment constructor.
*/
constexpr field_t& operator = (field_t&&) = default;

/**
* @brief Copy assignment constructor.
*/
constexpr field_t& operator = (const field_t&) = delete;

/**
* @brief Print the field to the passed stream.
*/
inline void print(std::ostream& os) const;
};

/**
* @brief Helper type to build field objects.
*/


+ 30
- 59
include/cpphibernate/schema/field.inl ファイルの表示

@@ -3,9 +3,8 @@
#include <cppcore/misc/indent.h>
#include <cppcore/misc/type_helper.h>

#include <cpphibernate/misc/type_helper.h>

#include "field.h"
#include "attributes.h"

namespace cpphibernate {
namespace schema {
@@ -13,30 +12,11 @@ namespace schema {
namespace __impl
{

/* tag_field */

struct tag_field
{ };

/* field_t */

template<typename T_name, typename T_getter, typename T_setter, typename T_attributes>
struct field_t
: public tag_field
, public tag_equality_comparable<tag_field>
{
using name_type = T_name;
using getter_type = T_getter;
using setter_type = T_setter;
using attributes_type = T_attributes;
using this_type = field_t<name_type, getter_type, setter_type, attributes_type>;

name_type name;
getter_type getter;
setter_type setter;
attributes_type attributes;

constexpr field_t(
constexpr field_t<T_name, T_getter, T_setter, T_attributes>
::field_t(
T_name&& p_name,
T_getter&& p_getter,
T_setter&& p_setter,
@@ -47,38 +27,30 @@ namespace schema {
, attributes (std::forward<T_attributes>(p_attributes))
{ }

constexpr field_t(field_t&&) = default;
constexpr field_t(const field_t&) = delete;

constexpr field_t& operator = (field_t&&) = default;
constexpr field_t& operator = (const field_t&) = delete;

inline void print(std::ostream& os) const
{
using namespace ::cppcore;

using value_type = typename mp::decay_t<getter_type>::value_type;
using dataset_type = real_dataset_t<value_type>;

size_t index = 0;
os << indent << '{'
<< incindent
<< indent << "\"name\": \"" << name << "\","
<< indent << "\"value_type\": \"" << type_helper<value_type>::name() << "\""
<< indent << "\"dataset_type\": \"" << type_helper<dataset_type>::name() << "\""
<< indent << "\"attributes\": "
<< indent << '['
<< incindent;
hana::for_each(attributes, [&](auto& attrib){
if (index++ > 0) os << ",";
os << indent << '"' << attrib.name << '"';
});
os << decindent
<< indent << ']'
<< decindent
<< indent << '}';
}
};
template<typename T_name, typename T_getter, typename T_setter, typename T_attributes>
void field_t<T_name, T_getter, T_setter, T_attributes>
::print(std::ostream& os) const
{
using namespace ::cppcore;

size_t index = 0;
os << indent << '{'
<< incindent
<< indent << "\"name\": \"" << name << "\","
<< indent << "\"value_type\": \"" << type_helper<value_type>::name() << "\""
<< indent << "\"dataset_type\": \"" << type_helper<dataset_type>::name() << "\""
<< indent << "\"attributes\": "
<< indent << '['
<< incindent;
hana::for_each(attributes, [&](auto& attrib){
if (index++ > 0) os << ",";
os << indent << '"' << attrib.name << '"';
});
os << decindent
<< indent << ']'
<< decindent
<< indent << '}';
}

/* field_builder */

@@ -95,10 +67,9 @@ namespace schema {
mp::list<T_name, T_getter, T_setter, T_attributes>,
mp::enable_if_t<
true
// && mp::is_getter_v<mp::decay_t<T_getter>>
// && mp::is_setter_v<mp::decay_t<T_setter>>
// && is_attributes_v<mp::decay_t<T_attributes>>
>>
&& mp::is_getter_v<mp::decay_t<T_getter>>
&& mp::is_setter_v<mp::decay_t<T_setter>>
&& is_attributes_v<mp::decay_t<T_attributes>>>>
{
using name_type = T_name;
using getter_type = T_getter;


+ 81
- 0
include/cpphibernate/schema/schema.h ファイルの表示

@@ -8,12 +8,83 @@ namespace schema {
namespace __impl
{

/**
* @brief Tag class to mark schema objects.
*/
struct tag_schema
{ };

/**
* @brief Schema type with all tables and fields for a database layout.
*
* @tparam T_name Name of the schema.
* @tparam T_tables List of all tables that belong to this schema.
*/
template<typename T_name, typename T_tables>
struct schema_t
: public tag_schema
, public tag_equality_comparable<tag_schema>
{
using name_type = T_name;
using tables_type = T_tables;

name_type name; //!< Name of the schema.
tables_type tables; //!< List of all tables that belongs to the schema.

/**
* @brief Constructor.
*
* @param[in] p_name Name of the schema.
* @param[in] p_tables List of all tables that belongs to the schema.
*/
constexpr schema_t(
name_type&& p_name,
tables_type&& p_tables);

/**
* @brief Move constructor.
*/
constexpr schema_t(schema_t&&) = default;

/**
* @brief Copy constructor.
*/
constexpr schema_t(const schema_t&) = delete;

/**
* @brief Move assignment constructor.
*/
constexpr schema_t& operator = (schema_t&&) = default;

/**
* @brief Copy assignment constructor.
*/
constexpr schema_t& operator = (const schema_t&) = delete;

/**
* @brief Print the whole schema to the passed stream.
*/
inline void print(std::ostream& os) const;
};

/**
* @brief Helper type to build schema objects.
*/
template<typename X, typename = void>
struct schema_builder;

/**
* @brief Helper type to get the base type of the passed dataset type.
*/
template<typename X, typename = void>
struct get_base_type_builder;

/**
* @brief Helper type to get the derived types of the passed dataset type.
*/
template<typename X, typename = void>
struct get_derived_types_builder;

}

/**
@@ -33,6 +104,16 @@ namespace schema {
*/
constexpr decltype(auto) make_schema = mp::generic_predicate<__impl::schema_builder> { };

/**
* @brief Predicate to get the base type of the passed dataset type.
*/
constexpr decltype(auto) get_base_type = mp::generic_predicate<__impl::get_base_type_builder> { };

/**
* @brief Predicate to get the derived types of the passed dataset type.
*/
constexpr decltype(auto) get_derived_types = mp::generic_predicate<__impl::get_derived_types_builder> { };

} }

#include "schema.inl"

+ 136
- 42
include/cpphibernate/schema/schema.inl ファイルの表示

@@ -1,5 +1,8 @@
#pragma once

#include <cppcore/misc/indent.h>

#include "tables.h"
#include "schema.h"

namespace cpphibernate {
@@ -8,57 +11,39 @@ namespace schema {
namespace __impl
{

/* tag_schema */

struct tag_schema
{ };

/* schema_t */

template<typename T_name, typename T_tables>
struct schema_t
: public tag_schema
, public tag_equality_comparable<tag_schema>
{
using name_type = T_name;
using tables_type = T_tables;

name_type name;
tables_type tables;

constexpr schema_t(
constexpr schema_t<T_name, T_tables>
::schema_t(
name_type&& p_name,
tables_type&& p_tables)
: name (std::forward<name_type> (p_name))
, tables(std::forward<tables_type>(p_tables))
{ }

constexpr schema_t(schema_t&&) = default;
constexpr schema_t(const schema_t&) = delete;

constexpr schema_t& operator = (schema_t&&) = default;
constexpr schema_t& operator = (const schema_t&) = delete;

inline void print(std::ostream& os) const
{
using namespace ::cppcore;
size_t index = 0;
os << indent << '{'
<< incindent
<< indent << "\"name\": \"" << name << "\","
<< indent << "\"tables\": "
<< indent << '['
<< incindent;
hana::for_each(tables, [&](auto& table){
if (index++ > 0) os << ",";
table.print(os);
});
os << decindent
<< indent << ']'
<< decindent
<< indent << '}';
}
};
template<typename T_name, typename T_tables>
void schema_t<T_name, T_tables>
::print(std::ostream& os) const
{
using namespace ::cppcore;

size_t index = 0;
os << indent << '{'
<< incindent
<< indent << "\"name\": \"" << name << "\","
<< indent << "\"tables\": "
<< indent << '['
<< incindent;
hana::for_each(tables, [&](auto& table){
if (index++ > 0) os << ",";
table.print(os);
});
os << decindent
<< indent << ']'
<< decindent
<< indent << '}';
}

/* schema_builder */

@@ -90,6 +75,115 @@ namespace schema {
}
};

/* get_base_type_builder */

template<typename X, typename>
struct get_base_type_builder
{
template<typename... T_args>
static constexpr decltype(auto) apply(T_args&&...)
{ static_assert(sizeof...(T_args) == -1, "Invalid parameters for get_base_type(...)!"); }
};

template<typename T_schema, typename T_wrapped_dataset>
struct get_base_type_builder<
mp::list<T_schema, T_wrapped_dataset>,
mp::enable_if_t<is_schema_v<mp::decay_t<T_schema>>>>
{

/* is_base_of */

static constexpr decltype(auto) is_base_of = hana::integral(hana::metafunction<mp::is_base_of>);

/* do_fold */

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(type_1, type_2), is_base_of(type_2, type_1));
static_assert(decltype(check)::value, "A dataset must not have more than one base class!");
return hana::if_(is_base_of(type_1, type_2), type_2, type_1);
}
};

static constexpr decltype(auto) do_fold = do_fold_impl { };

/* get_base_types */

template<typename T_datasets, typename T_dataset>
static constexpr decltype(auto) get_base_types(T_datasets datasets, T_dataset dataset)
{
return hana::filter(
datasets,
[&](auto type){
return hana::and_(
is_base_of(type, dataset),
hana::not_equal(type, dataset));
});
}

/* apply */

static constexpr decltype(auto) apply(
const T_schema& schema,
const T_wrapped_dataset& wrapped_dataset)
{
decltype(auto) wrapped_datasets = hana::transform(
schema.tables,
schema::get_wrapped_dataset);
decltype(auto) base_types = get_base_types(wrapped_datasets, wrapped_dataset);
return hana::eval_if(
hana::size(base_types) <= hana::size_c<0>,
[&](auto _){ return hana::type_c<void>; },
[&](auto _){ return hana::fold(_(base_types), do_fold); });
}
};

/* get_derived_types_builder */

template<typename X, typename>
struct get_derived_types_builder
{
template<typename... T_args>
static constexpr decltype(auto) apply(T_args&&...)
{ static_assert(sizeof...(T_args) == -1, "Invalid parameters for get_derived_types(...)!"); }
};

template<typename T_schema, typename T_dataset>
struct get_derived_types_builder<
mp::list<T_schema, T_dataset>,
mp::enable_if_t<
schema::is_schema_v<mp::decay_t<T_schema>>
&& mp::is_same_v<hana::type_tag, hana::tag_of_t<T_dataset>>
>>
{
struct has_base_impl
{
template<typename T_type>
constexpr decltype(auto) operator()(T_type&&) const
{
return decltype(hana::equal(
get_base_type(
std::declval<T_schema>(),
std::declval<T_type>()),
std::declval<T_dataset>())) { };
}
};

static constexpr decltype(auto) has_base = has_base_impl { };

static constexpr decltype(auto) apply(T_schema&& schema, T_dataset&& dataset)
{
constexpr decltype(auto) dataset_types =
decltype(hana::transform(schema.tables, schema::get_wrapped_dataset)) { };
constexpr decltype(auto) derived_types =
decltype(hana::filter(dataset_types, has_base)) { };
return derived_types;
}
};

}

/* is_schema */


+ 86
- 0
include/cpphibernate/schema/table.h ファイルの表示

@@ -8,12 +8,93 @@ namespace schema {
namespace __impl
{

/**
* @brief Tag class to mark table objects.
*/
struct tag_table
{ };

/**
* @brief Represents a data field in the schema.
*
* @tparam T_name Name of the table.
* @tparam T_wrapped_dataset Dataset type the table represents.
* @tparam T_table_id Unique ID assigned by the user.
* @tparam T_fields List of field that belongs to the table.
*/
template<
typename T_name,
typename T_wrapped_dataset,
typename T_table_id,
typename T_fields>
struct table_t
: public tag_table
, public tag_equality_comparable<tag_table>
{
using name_type = T_name;
using wrapped_dataset_type = mp::decay_t<T_wrapped_dataset>;
using dataset_type = decay_unwrap_t<wrapped_dataset_type>;
using table_id_type = T_table_id;
using fields_type = T_fields;
using this_type = table_t<name_type, wrapped_dataset_type, table_id_type, fields_type>;

name_type name; //!< Name of the table.
wrapped_dataset_type wrapped_dataset; //!< Dataset type this table represents.
table_id_type table_id; //!< Unique ID of the table, assigned by the user.
fields_type fields; //!< List of fields that belongs to the table.

/**
* @brief Constructor.
*
* @param[in] p_name Name of the table.
* @param[in] p_wrapped_dataset Dataset type this table represents.
* @param[in] p_table_id Unique ID of the table assigned by the user.
* @param[in] p_fields List of fields that belongs to the table.
*/
constexpr table_t(
name_type p_name,
wrapped_dataset_type p_wrapped_dataset,
table_id_type p_table_id,
fields_type p_fields);

/**
* @brief Move constructor.
*/
constexpr table_t(table_t&&) = default;

/**
* @brief Copy constructor.
*/
constexpr table_t(const table_t&) = delete;

/**
* @brief Move assignment constructor.
*/
constexpr table_t& operator = (table_t&&) = default;

/**
* @brief Copy assignment constructor.
*/
constexpr table_t& operator = (const table_t&) = delete;

/**
* @brief Print the table to the passed stream.
*/
inline void print(std::ostream& os) const;
};

/**
* @brief Helper type to build table objects.
*/
template<typename X, typename = void>
struct table_builder;

/**
* @brief Helper type to get the wrapped dataset of the passed table.
*/
template<typename X, typename = void>
struct table_get_wrapped_dataset;

}

/**
@@ -33,6 +114,11 @@ namespace schema {
*/
constexpr decltype(auto) make_table = mp::generic_predicate<__impl::table_builder> { };

/**
* @brief Predicate to get the wrapped dataset of the passed table.
*/
constexpr decltype(auto) get_wrapped_dataset = mp::generic_predicate<__impl::table_get_wrapped_dataset> { };

} }

#include "table.inl"

+ 48
- 55
include/cpphibernate/schema/table.inl ファイルの表示

@@ -1,5 +1,8 @@
#pragma once

#include <cpphibernate/misc/type_helper.h>

#include "fields.h"
#include "table.h"

namespace cpphibernate {
@@ -8,35 +11,11 @@ namespace schema {
namespace __impl
{

/* tag_table */

struct tag_table
{ };

/* table_t */

template<
typename T_name,
typename T_wrapped_dataset,
typename T_table_id,
typename T_fields>
struct table_t
: public tag_table
, public tag_equality_comparable<tag_table>
{
using name_type = T_name;
using wrapped_dataset_type = mp::decay_t<T_wrapped_dataset>;
using dataset_type = decay_unwrap_t<wrapped_dataset_type>;
using table_id_type = T_table_id;
using fields_type = T_fields;
using this_type = table_t<name_type, wrapped_dataset_type, table_id_type, fields_type>;

name_type name;
wrapped_dataset_type wrapped_dataset;
table_id_type table_id;
fields_type fields;

constexpr table_t(
template<typename T_name, typename T_wrapped_dataset, typename T_table_id, typename T_fields>
constexpr table_t<T_name, T_wrapped_dataset, T_table_id, T_fields>
::table_t(
name_type p_name,
wrapped_dataset_type p_wrapped_dataset,
table_id_type p_table_id,
@@ -47,34 +26,29 @@ namespace schema {
, fields (std::forward<fields_type> (p_fields))
{ }

constexpr table_t(table_t&&) = default;
constexpr table_t(const table_t&) = delete;

constexpr table_t& operator = (table_t&&) = default;
constexpr table_t& operator = (const table_t&) = delete;

inline void print(std::ostream& os) const
{
using namespace ::cppcore;
size_t index = 0;
os << indent << '{'
<< incindent
<< indent << "\"name\": \"" << name << "\","
<< indent << "\"wrapped_dataset\": \"" << type_helper<dataset_type>::name() << "\""
<< indent << "\"table_id\": \"" << hana::value(table_id) << "\""
<< indent << "\"fields\": "
<< indent << '['
<< incindent;
hana::for_each(fields, [&](auto& table){
if (index++ > 0) os << ",";
table.print(os);
});
os << decindent
<< indent << ']'
<< decindent
<< indent << '}';
}
};
template<typename T_name, typename T_wrapped_dataset, typename T_table_id, typename T_fields>
void table_t<T_name, T_wrapped_dataset, T_table_id, T_fields>
::print(std::ostream& os) const
{
using namespace ::cppcore;
size_t index = 0;
os << indent << '{'
<< incindent
<< indent << "\"name\": \"" << name << "\","
<< indent << "\"wrapped_dataset\": \"" << type_helper<dataset_type>::name() << "\""
<< indent << "\"table_id\": \"" << hana::value(table_id) << "\""
<< indent << "\"fields\": "
<< indent << '['
<< incindent;
hana::for_each(fields, [&](auto& table){
if (index++ > 0) os << ",";
table.print(os);
});
os << decindent
<< indent << ']'
<< decindent
<< indent << '}';
}

/* table_builder */

@@ -117,6 +91,25 @@ namespace schema {
}
};

/* table_get_wrapped_dataset */

template<typename X, typename>
struct table_get_wrapped_dataset
{
template<typename... T_args>
static constexpr decltype(auto) apply(T_args&&...)
{ static_assert(sizeof...(T_args) == -1, "Invalid parameters for get_wrapped_dataset(...)!"); }
};

template<typename T_table>
struct table_get_wrapped_dataset<
mp::list<T_table>,
mp::enable_if_t<is_table_v<mp::decay_t<T_table>>>>
{
static constexpr decltype(auto) apply(T_table&& table)
{ return std::forward<T_table>(table).wrapped_dataset; }
};

}

/* is_table */


+ 10
- 0
include/cpphibernate/types.h ファイルの表示

@@ -5,10 +5,20 @@
#include <iostream>

#include <cpphibernate/config.h>
#include <cppcore/misc/exception.h>

namespace cpphibernate
{

/**
* @brief Hibernate exception class.
*/
struct exception
: public cppcore::exception
{
using cppcore::exception::exception;
};

/**
* @brief Represents a string with an fixed length.
*/


+ 19
- 0
src/CMakeLists.txt ファイルの表示

@@ -7,6 +7,10 @@ Include ( strip_symbols OPTIONAL RESULT_VARIABLE HAS_STRIP_S
Find_Package ( Hana REQUIRED )
Find_Package ( cppmp REQUIRED )
Find_Package ( cppcore REQUIRED )
Find_Package ( cppmariadb REQUIRED )
If ( cppmariadb_FOUND )
Set ( CPPHIBERNATE_HAS_CPPMARIADB true )
EndIf ( )

# Object Library ##################################################################################

@@ -29,6 +33,11 @@ Target_Link_Libraries ( cpphibernate-objects
hana
cppmp::cppmp
cppcore::cppcore )
If ( CPPHIBERNATE_HAS_CPPMARIADB )
Target_Link_Libraries ( cpphibernate-objects
PUBLIC
cppmariadb::cppmariadb-shared )
EndIf ( )

# Static Library ##################################################################################

@@ -41,6 +50,11 @@ Target_Include_Directories ( cpphibernate-static
PUBLIC
$<BUILD_INTERFACE:${CPPHIBERNATE_INCLUDE_DIR}>
$<INSTALL_INTERFACE:${CPPHIBERNATE_INSTALL_DIR_INCLUDE}> )
If ( CPPHIBERNATE_HAS_CPPMARIADB )
Target_Link_Libraries ( cpphibernate-static
PUBLIC
cppmariadb::cppmariadb-static )
EndIf ( )

# Shared Library ##################################################################################

@@ -54,6 +68,11 @@ Target_Include_Directories ( cpphibernate-shared
PUBLIC
$<BUILD_INTERFACE:${CPPHIBERNATE_INCLUDE_DIR}>
$<INSTALL_INTERFACE:${CPPHIBERNATE_INSTALL_DIR_INCLUDE}> )
If ( CPPHIBERNATE_HAS_CPPMARIADB )
Target_Link_Libraries ( cpphibernate-shared
PUBLIC
cppmariadb::cppmariadb-shared )
EndIf ( )

# Optimization ####################################################################################



src/cpphibernate/driver/mariadb/schema/field.xcpp → src/cpphibernate/driver/mariadb/classes/field.xcpp ファイルの表示


+ 135
- 0
src/cpphibernate/driver/mariadb/classes/fields/field.cpp ファイルの表示

@@ -0,0 +1,135 @@
#include <cpphibernate/misc/print_container.h>
#include <cpphibernate/driver/mariadb/classes/fields/field.h>
#include <cpphibernate/driver/mariadb/classes/tables/table.h>

#include <cppcore/misc/indent.h>

using namespace ::cpphibernate;
using namespace ::cpphibernate::mariadb;

/* field_t */

field_t::~field_t()
{ }

std::ostream& field_t::print(std::ostream& os) const
{
using namespace ::cppcore;

os << indent << '{'
<< incindent

<< indent << "\"id\": " << id << ","
// TODO
// << indent << "\"dataset_id\": " << dataset_id << ","
// << indent << "\"real_dataset_id\": " << real_dataset_id << ","
<< indent << "\"value_id\": " << value_id << ","
<< indent << "\"real_value_id\": " << real_value_id << ","
<< indent << "\"value_is_nullable\": " << (value_is_nullable ? "true" : "false") << ","
<< indent << "\"value_is_pointer\": " << (value_is_pointer ? "true" : "false") << ","
<< indent << "\"value_is_container\": " << (value_is_container ? "true" : "false") << ","
<< indent << "\"value_is_auto_incremented\": " << (value_is_auto_incremented ? "true" : "false") << ","
<< indent << "\"table\": " << '"' << table.name << "\","
<< indent << "\"referenced_table\": " << (referenced_table
? std::string("\"") + referenced_table->name + "\""
: "null") << ","

// TODO
// << indent << "\"schema_name\": \"" << schema_name << "\","
// << indent << "\"table_name\": \"" << table_name << "\","
// << indent << "\"field_name\": \"" << field_name << "\","
<< indent << "\"name\": \"" << name << "\","
<< indent << "\"type\": \"" << type << "\","
<< indent << "\"create_arguments\": \"" << create_arguments << "\","

<< indent << "\"convert_to_open\": \"" << convert_to_open << "\","
<< indent << "\"convert_to_close\": \"" << convert_to_close << "\","
<< indent << "\"convert_from_open\": \"" << convert_from_open << "\","
<< indent << "\"convert_from_close\": \"" << convert_from_close << "\","

<< indent << "\"attributes\": " << make_print_container(attributes, false)

<< decindent
<< indent << '}';

return os;
}

void field_t::init()
{
/* conver_to_open */
{
std::ostringstream ss;
for (auto& attrib : attributes)
{
switch(attrib)
{
case attribute_t::hex:
ss << "HEX(";
break;
case attribute_t::compress:
ss << "COMPRESS(";
break;
default:
break;
}
}
convert_to_open = ss.str();
}

/* convert_to_close */
{
std::ostringstream ss;
for (auto& attrib : attributes)
{
switch(attrib)
{
case attribute_t::hex:
case attribute_t::compress:
ss << ')';
break;
default:
break;
}
}
convert_to_close = ss.str();
}

/* convert_from_open */
{
std::ostringstream ss;
for (auto& attrib : attributes)
{
switch(attrib)
{
case attribute_t::hex:
ss << "UNHEX(";
break;
case attribute_t::compress:
ss << "UNCOMPRESS(";
break;
default:
break;
}
}
convert_from_open = ss.str();
}

/* convert_from_close */
{
std::ostringstream ss;
for (auto& attrib : attributes)
{
switch(attrib)
{
case attribute_t::hex:
case attribute_t::compress:
ss << ')';
break;
default:
break;
}
}
convert_from_close = ss.str();
}
}

src/cpphibernate/driver/mariadb/schema/schema.xcpp → src/cpphibernate/driver/mariadb/classes/schema.xcpp ファイルの表示


+ 127
- 0
src/cpphibernate/driver/mariadb/classes/schema/schema.cpp ファイルの表示

@@ -0,0 +1,127 @@
#include <cpphibernate/misc/print_container.h>
#include <cpphibernate/driver/mariadb/classes/schema/schema.h>

#include <cppcore/misc/indent.h>

using namespace ::cpphibernate;
using namespace ::cpphibernate::mariadb;

/* schema_t */

std::ostream& schema_t::print(std::ostream& os) const
{
using namespace ::cppcore;

os << indent << '{'
<< incindent
<< indent << "\"schema_name\": \"" << name << "\","
<< indent << "\"tables\": " << make_print_container(tables, true, [](auto& s, auto& table) {
table->print(s);
})
<< decindent
<< indent << '}';

return os;
}

void schema_t::init()
{
/* build lookup */
for (auto& t : tables)
{
assert(static_cast<bool>(t));
_lookup.emplace(t->dataset_id, t.get());
}

/* update table referencs */
for (auto& t : tables)
{
assert(static_cast<bool>(t));
auto& table = const_cast<table_t&>(*t);

/* get base table */
auto it = _lookup.find(table.base_dataset_id);
table.base_table = (it != _lookup.end()
? it->second
: nullptr);

/* dereived tables */
for (auto& id : table.derived_dataset_ids)
{
it = _lookup.find(id);
if (it == _lookup.end())
throw exception(std::string("unable to find derived table for dataset id ") + std::to_string(id));
table.derived_tables.emplace_back(it->second);
}

/* update fields */
for (auto& f : table.fields)
{
assert(static_cast<bool>(f));
auto& field = const_cast<field_t&>(*f);

/* referenced_table */
it = _lookup.find(field.real_value_id);
auto * referenced_table = (it != _lookup.end()
? const_cast<table_t*>(it->second)
: nullptr);
field.referenced_table = referenced_table;

/* primary key field */
if (field.attributes.count(attribute_t::primary_key))
{
if (static_cast<bool>(table.primary_key_field))
throw exception(std::string("Table '") + table.name + "' can not have more then one primary key!");
table.primary_key_field = &field;
}

/* foreign table field */
else if (static_cast<bool>(referenced_table))
{
table.foreign_table_fields.emplace_back(&field);
if (field.value_is_container)
{
referenced_table->is_used_in_container = true;
}
}

/* normal data field */
else
{
table.data_fields.emplace_back(&field);
}
}
if (!static_cast<bool>(table.primary_key_field))
throw exception(std::string("Table '") + table.name + "' does not have a primary key!");
}

/* update foreign fields (one, many, key) */
for (auto& t : tables)
{
assert(static_cast<bool>(t));
auto& table = const_cast<table_t&>(*t);

for (auto& f : table.foreign_table_fields)
{
assert(static_cast<bool>(f));
assert(static_cast<bool>(f->referenced_table));

auto& field = *f;
auto& referenced_table = const_cast<table_t&>(*field.referenced_table);

if (field.value_is_container)
{
table.foreign_table_many_fields.emplace_back(&field);
referenced_table.foreign_key_fields.emplace_back(&field);
}
else
{
table.foreign_table_one_fields.emplace_back(&field);
if (referenced_table.is_used_in_container)
{
referenced_table.foreign_key_fields.push_back(&field);
}
}
}
}
}

src/cpphibernate/driver/mariadb/schema/table.xcpp → src/cpphibernate/driver/mariadb/classes/table.xcpp ファイルの表示


+ 66
- 0
src/cpphibernate/driver/mariadb/classes/tables/table.cpp ファイルの表示

@@ -0,0 +1,66 @@
#include <cpphibernate/misc/print_container.h>
#include <cpphibernate/driver/mariadb/classes/tables/table.h>

#include <cppcore/misc/indent.h>

using namespace ::cpphibernate;
using namespace ::cpphibernate::mariadb;

/* table_t */

table_t::~table_t()
{ }

std::ostream& table_t::print(std::ostream& os) const
{
using namespace ::cppcore;

os << indent << '{'
<< incindent
<< indent << "\"id\": " << id << ","
// TODO
<< indent << "\"dataset_id\": " << dataset_id << ","
<< indent << "\"base_dataset_id\": " << base_dataset_id << ","
<< indent << "\"derived_dataset_ids\": " << make_print_container(derived_dataset_ids, false) << ","
// TODO
// << indent << "\"schema_name\": \"" << schema_name << "\","
// << indent << "\"table_name\": \"" << table_name << "\","
<< indent << "\"name\": \"" << name << "\","
<< indent << "\"base_table\": " << (base_table ? std::string("\"") + base_table->name + "\"" : "null") << ","
<< indent << "\"derived_tables\":" << make_print_container(derived_tables, true, [](auto& s, auto& ptr){
s << indent << '"' << ptr->name << '"';
}) << ","
<< indent << "\"primary_key_field\": " << (primary_key_field ? std::string("\"") + primary_key_field->name + "\"" : "null") << ","
<< indent << "\"foreign_key_fields\": " << make_print_container(foreign_key_fields, true, [](auto& s, auto& ptr){
s << indent << '"' << ptr->name << '.' << ptr->name << '"';
}) << ","
<< indent << "\"foreign_table_fields\": " << make_print_container(foreign_table_fields, true, [](auto& s, auto& ptr){
s << indent << '"' << ptr->name << '"';
}) << ","
<< indent << "\"foreign_table_one_fields\": " << make_print_container(foreign_table_one_fields, true, [](auto& s, auto& ptr){
s << indent << '"' << ptr->name << '"';
}) << ","
<< indent << "\"foreign_table_many_fields\": " << make_print_container(foreign_table_many_fields, true, [](auto& s, auto& ptr){
s << indent << '"' << ptr->name << '"';
}) << ","
<< indent << "\"data_fields\": " << make_print_container(data_fields, true, [](auto& s, auto& ptr){
s << indent << '"' << ptr->name << '"';
}) << ","
<< indent << "\"fields\":" << make_print_container(fields, true, [](auto& s, auto& field) {
field->print(s);
})
<< decindent
<< indent << '}';

return os;
}

void table_t::init()
{
/* build field lookup */
for (auto& f : fields)
{
assert(static_cast<bool>(f));
_lookup.emplace(f->id, f.get());
}
}

+ 1
- 1
test/CMakeLists.txt ファイルの表示

@@ -23,7 +23,7 @@ Add_Executable ( cpphibernate-test
Target_Link_Libraries ( cpphibernate-test
PUBLIC
cpphibernate-objects
GTest::Main )
GMock::Main )

# pedantic
If ( HAS_PEDANTIC )


test/cpphibernate/cpphibernate_init.xcpp → test/cpphibernate/cpphibernate_init.cpp ファイルの表示

@@ -7,8 +7,11 @@
using namespace ::testing;
using namespace ::cpphibernate;

namespace hana = ::boost::hana;

TEST(CppHibernateTests, init)
{
/*
StrictMock<mariadb_mock> mock;

expect_query(mock, "START TRANSACTION");
@@ -293,8 +296,11 @@ TEST(CppHibernateTests, init)
mock,
mysql_close(
reinterpret_cast<MYSQL*>(0x1111)));
*/
::cppmariadb::connection connection(reinterpret_cast<MYSQL*>(0x1111));
auto context = make_context<driver::mariadb>(test_schema, connection);
context.init(true);
auto context = make_context<mariadb_driver>(test_schema);
(void)context;
context.print(std::cout) << std::endl << std::endl;

// context.init(true);
}

+ 0
- 29
test/cpphibernate/cpphibernate_tests.cpp ファイルの表示

@@ -1,29 +0,0 @@
#include <gtest/gtest.h>

#include <cpphibernate.h>

#include "test_schema.h"

using namespace ::testing;
using namespace ::cpphibernate;
using namespace ::cpphibernate::schema;

using namespace hana::literals;

constexpr decltype(auto) tmp_table = test_schema.tables[0_c];
constexpr decltype(auto) tmp_field = tmp_table.fields[0_c];
constexpr decltype(auto) mod = make_modifiers(
limit(5_c),
offset(3_c),
order_by(
ascending(tmp_field),
descending(tmp_field)),
where(
or_(
negation(equal(tmp_field, 1)),
negation(equal(tmp_field, 1)))));

TEST(cpphibernate_tests, dummy)
{
(void)mod;
}

test/cpphibernate/mariadb_mock.xcpp → test/cpphibernate/mariadb_mock.cpp ファイルの表示


+ 1
- 1
test/cpphibernate/test_helper.h ファイルの表示

@@ -180,4 +180,4 @@ inline void expect_query(T_mock& mock, const std::string& query, T_result&& resu

template<typename T_mock>
inline void expect_query(T_mock& mock, const std::string& query)
{ expect_query(mock, query, result_stored()); }
{ expect_query(mock, query, result_stored()); }

読み込み中…
キャンセル
保存