Browse Source

* Started refactoring

* Refactored schema implementation
refactoring
bergmann 4 years ago
parent
commit
856ff5cf75
63 changed files with 1705 additions and 2159 deletions
  1. +55
    -13
      CMakeLists.txt
  2. +0
    -46
      cmake/Findcppmariadb.cmake
  3. +0
    -46
      cmake/Findcpputils.cmake
  4. +0
    -34
      cmake/Findmariadb.cmake
  5. +10
    -0
      cmake/cpphibernate-config.cmake
  6. +15
    -0
      cmake/cpphibernate-options.cmake
  7. +31
    -0
      cmake/cpphibernate-var.cmake
  8. +1
    -1
      cmake/modules
  9. +0
    -9
      cmake/options.cmake
  10. +0
    -1
      cmake/options.h.in
  11. +3
    -6
      include/cpphibernate.h
  12. +3
    -64
      include/cpphibernate/config.h
  13. +0
    -123
      include/cpphibernate/context.h
  14. +4
    -6
      include/cpphibernate/misc.h
  15. +0
    -52
      include/cpphibernate/misc/container_helper.h
  16. +30
    -0
      include/cpphibernate/misc/equality_compare.h
  17. +61
    -0
      include/cpphibernate/misc/equality_compare.inl
  18. +0
    -32
      include/cpphibernate/misc/general.h
  19. +0
    -152
      include/cpphibernate/misc/meta.h
  20. +0
    -120
      include/cpphibernate/misc/nullable_helper.h
  21. +0
    -112
      include/cpphibernate/misc/print.h
  22. +26
    -0
      include/cpphibernate/misc/print_container.h
  23. +116
    -0
      include/cpphibernate/misc/print_container.inl
  24. +20
    -0
      include/cpphibernate/misc/printing.h
  25. +34
    -0
      include/cpphibernate/misc/type_helper.h
  26. +53
    -0
      include/cpphibernate/misc/type_helper.inl
  27. +0
    -44
      include/cpphibernate/misc/wrap.h
  28. +0
    -8
      include/cpphibernate/modifier.h
  29. +9
    -10
      include/cpphibernate/schema.h
  30. +39
    -24
      include/cpphibernate/schema/attribute.h
  31. +15
    -0
      include/cpphibernate/schema/attribute.inl
  32. +21
    -55
      include/cpphibernate/schema/attributes.h
  33. +62
    -0
      include/cpphibernate/schema/attributes.inl
  34. +22
    -110
      include/cpphibernate/schema/field.h
  35. +132
    -0
      include/cpphibernate/schema/field.inl
  36. +21
    -54
      include/cpphibernate/schema/fields.h
  37. +63
    -0
      include/cpphibernate/schema/fields.inl
  38. +0
    -192
      include/cpphibernate/schema/getter.h
  39. +12
    -17
      include/cpphibernate/schema/macros.h
  40. +22
    -236
      include/cpphibernate/schema/schema.h
  41. +102
    -0
      include/cpphibernate/schema/schema.inl
  42. +0
    -216
      include/cpphibernate/schema/setter.h
  43. +22
    -174
      include/cpphibernate/schema/table.h
  44. +129
    -0
      include/cpphibernate/schema/table.inl
  45. +21
    -102
      include/cpphibernate/schema/tables.h
  46. +63
    -0
      include/cpphibernate/schema/tables.inl
  47. +72
    -33
      include/cpphibernate/types.h
  48. +38
    -0
      include/cpphibernate/types.inl
  49. +92
    -40
      src/CMakeLists.txt
  50. +0
    -0
      src/cpphibernate/driver/mariadb/schema/field.xcpp
  51. +0
    -0
      src/cpphibernate/driver/mariadb/schema/schema.xcpp
  52. +0
    -0
      src/cpphibernate/driver/mariadb/schema/table.xcpp
  53. +39
    -27
      test/CMakeLists.txt
  54. +0
    -0
      test/cpphibernate/cpphibernate_create.xcpp
  55. +0
    -0
      test/cpphibernate/cpphibernate_destroy.xcpp
  56. +0
    -0
      test/cpphibernate/cpphibernate_init.xcpp
  57. +0
    -0
      test/cpphibernate/cpphibernate_read.xcpp
  58. +20
    -0
      test/cpphibernate/cpphibernate_tests.cpp
  59. +0
    -0
      test/cpphibernate/cpphibernate_update.xcpp
  60. +0
    -0
      test/cpphibernate/mariadb_mock.h
  61. +0
    -0
      test/cpphibernate/mariadb_mock.xcpp
  62. +0
    -0
      test/cpphibernate/test_helper.h
  63. +227
    -0
      test/cpphibernate/test_schema.h

+ 55
- 13
CMakeLists.txt View File

@@ -1,15 +1,57 @@
# Initialize CMake ################################################################################

CMake_Minimum_Required ( VERSION 3.5.1 FATAL_ERROR )
Include ( CTest )
If ( NOT CMAKE_BUILD_TYPE )
Set ( CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build!" FORCE )
EndIf ( NOT CMAKE_BUILD_TYPE )
Set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/"
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/" )

# Projects ########################################################################################

Add_SubDirectory ( ${CMAKE_CURRENT_SOURCE_DIR}/src )
Add_SubDirectory ( ${CMAKE_CURRENT_SOURCE_DIR}/test )
CMake_Minimum_Required ( VERSION 3.12.0 FATAL_ERROR )

# Set CMAKE_BUILD_TYPE
If ( NOT CMAKE_BUILD_TYPE )
Set ( CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build!" FORCE )
EndIf ( NOT CMAKE_BUILD_TYPE )
Set_Property ( CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release RelWithDebInfo MinSizeRel )

# Set CMAKE_MODULE_PATH
If ( EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" )
Set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/" )
EndIf ( )
If ( EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" )
Set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" )
EndIf ( )

# Project #########################################################################################

Include ( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cpphibernate-var.cmake )
Include ( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cpphibernate-options.cmake )
Project ( cpphibernate
DESCRIPTION "A simple library"
VERSION "${CPPHIBERNATE_VERSION}" )
Include ( CTest )
Include ( GNUInstallDirs )

# Subdirectories
Add_SubDirectory ( ${CMAKE_CURRENT_SOURCE_DIR}/src )
Add_SubDirectory ( ${CMAKE_CURRENT_SOURCE_DIR}/test )

# Install
Include ( CMakePackageConfigHelpers )
Write_Basic_Package_Version_File ( "${CMAKE_CURRENT_BINARY_DIR}/cmake/cpphibernate-config-version.cmake"
VERSION ${CPPHIBERNATE_VERSION}
COMPATIBILITY AnyNewerVersion )
Configure_File ( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cpphibernate-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/cmake/cpphibernate-config.cmake"
@ONLY )

Set ( ConfigPackageLocation "${CPPHIBERNATE_INSTALL_DIR_SHARE}/cmake" )
Install ( EXPORT
cpphibernate
NAMESPACE
cpphibernate::
DESTINATION
${ConfigPackageLocation} )
Install ( FILES
"${CMAKE_CURRENT_BINARY_DIR}/cmake/cpphibernate-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/cmake/cpphibernate-config-version.cmake"
DESTINATION
${ConfigPackageLocation}
COMPONENT
Devel )

+ 0
- 46
cmake/Findcppmariadb.cmake View File

@@ -1,46 +0,0 @@
Include ( ExternalProject )
Include ( FindPackageHandleStandardArgs )

Set ( CPPMARIADB_PATH ${CMAKE_BINARY_DIR}/extern/cppmariadb )

If ( NOT TARGET cppmariadb_extern )
ExternalProject_Add ( cppmariadb_extern
PREFIX ${CPPMARIADB_PATH}
TMP_DIR ${CPPMARIADB_PATH}/tmp
STAMP_DIR ${CPPMARIADB_PATH}/stamp
SOURCE_DIR ${CPPMARIADB_PATH}/src
BINARY_DIR ${CPPMARIADB_PATH}/build
INSTALL_DIR ${CPPMARIADB_PATH}/install
GIT_REPOSITORY "https://git.bergmann89.de/cpp/cppmariadb.git"
GIT_TAG "master"
TEST_COMMAND make test
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_MODULE_PATH=${CMAKE_MODULE_PATH})
EndIf ( )

Set ( CPPMARIADB_LIBRARY ${CPPMARIADB_PATH}/install/lib/libcppmariadb.so )
Set ( CPPMARIADB_INCLUDE_DIR ${CPPMARIADB_PATH}/install/include )
Set ( CPPMARIADB_LIBRARIES ${CPPMARIADB_LIBRARY} )
Set ( CPPMARIADB_INCLUDE_DIRS ${CPPMARIADB_INCLUDE_DIR} )

File ( MAKE_DIRECTORY ${CPPMARIADB_INCLUDE_DIR} )

Find_Package_Handle_Standard_Args ( cppmariadb DEFAULT_MSG
CPPMARIADB_LIBRARY
CPPMARIADB_INCLUDE_DIR )

If ( NOT TARGET cppmariadb )
Add_Library ( cppmariadb SHARED IMPORTED )
Add_Dependencies ( cppmariadb cppmariadb_extern )
Set_Property ( TARGET cppmariadb
PROPERTY IMPORTED_LOCATION ${CPPMARIADB_LIBRARY} )
Set_Property ( TARGET cppmariadb
PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CPPMARIADB_INCLUDE_DIRS} )
Install ( FILES ${CPPMARIADB_LIBRARY} DESTINATION lib )
If ( CPPHIBERNATE_INSTALL_DEV_FILES )
Install ( DIRECTORY ${CPPMARIADB_INCLUDE_DIR}/ DESTINATION include )
EndIf ( )
EndIf ( )

+ 0
- 46
cmake/Findcpputils.cmake View File

@@ -1,46 +0,0 @@
Include ( ExternalProject )
Include ( FindPackageHandleStandardArgs )

Set ( CPPUTILS_PATH ${CMAKE_BINARY_DIR}/extern/cpputils )

If ( NOT TARGET cpputils_extern )
ExternalProject_Add ( cpputils_extern
PREFIX ${CPPUTILS_PATH}
TMP_DIR ${CPPUTILS_PATH}/tmp
STAMP_DIR ${CPPUTILS_PATH}/stamp
SOURCE_DIR ${CPPUTILS_PATH}/src
BINARY_DIR ${CPPUTILS_PATH}/build
INSTALL_DIR ${CPPUTILS_PATH}/install
GIT_REPOSITORY "https://git.bergmann89.de/cpp/cpputils.git"
GIT_TAG "master"
TEST_COMMAND make test
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_MODULE_PATH=${CMAKE_MODULE_PATH})
EndIf ( )

Set ( CPPUTILS_LIBRARY ${CPPUTILS_PATH}/install/lib/libcpputils.so )
Set ( CPPUTILS_INCLUDE_DIR ${CPPUTILS_PATH}/install/include )
Set ( CPPUTILS_LIBRARIES ${CPPUTILS_LIBRARY} )
Set ( CPPUTILS_INCLUDE_DIRS ${CPPUTILS_INCLUDE_DIR} )

File ( MAKE_DIRECTORY ${CPPUTILS_INCLUDE_DIR} )

Find_Package_Handle_Standard_Args ( cpputils DEFAULT_MSG
CPPUTILS_LIBRARY
CPPUTILS_INCLUDE_DIR )

If ( NOT TARGET cpputils )
Add_Library ( cpputils SHARED IMPORTED )
Add_Dependencies ( cpputils cpputils_extern )
Set_Property ( TARGET cpputils
PROPERTY IMPORTED_LOCATION ${CPPUTILS_LIBRARY} )
Set_Property ( TARGET cpputils
PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CPPUTILS_INCLUDE_DIRS} )
Install ( FILES ${CPPUTILS_LIBRARY} DESTINATION lib )
If ( CPPHIBERNATE_INSTALL_DEV_FILES )
Install ( DIRECTORY ${CPPUTILS_INCLUDE_DIR}/ DESTINATION include )
EndIf ( )
EndIf ( )

+ 0
- 34
cmake/Findmariadb.cmake View File

@@ -1,34 +0,0 @@
Find_Library ( MARIADB_LIBRARY
NAMES mariadb mysql
PATH_SUFFIXES mariadb )

Find_File ( MARIADB_INCLUDE_DIR
NAMES mysql.h
PATH_SUFFIXES mariadb )

Get_Filename_Component ( MARIADB_INCLUDE_DIR
${MARIADB_INCLUDE_DIR}
DIRECTORY )

Include ( FindPackageHandleStandardArgs )

Find_Package_Handle_Standard_Args ( mariadb DEFAULT_MSG
MARIADB_LIBRARY
MARIADB_INCLUDE_DIR )

Mark_As_Advanced ( MARIADB_LIBRARY
MARIADB_LIBRARIES )

If ( MARIADB_FOUND )
Set ( MARIADB_LIBRARIES ${MARIADB_LIBRARY} )
Set ( MARIADB_INCLUDE_DIRS ${MARIADB_INCLUDE_DIR} )

If ( NOT TARGET mariadb )
Add_Library ( mariadb UNKNOWN IMPORTED )
Set_Property ( TARGET mariadb
PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${MARIADB_INCLUDE_DIRS}" )
Set_Property ( TARGET mariadb
APPEND
PROPERTY IMPORTED_LOCATION "${MARIADB_LIBRARY}")
EndIf ( )
EndIf ( )

+ 10
- 0
cmake/cpphibernate-config.cmake View File

@@ -0,0 +1,10 @@
# cpphibernate-config.cmake - package configuration file

Message ( WARNING "Please configure the dependencies of this package!" )
# Include ( CMakeFindDependencyMacro )
# Find_Dependency ( <dependency> )

Include ( FindPackageHandleStandardArgs )
Set ( ${CMAKE_FIND_PACKAGE_NAME}_CONFIG ${CMAKE_CURRENT_LIST_FILE} )
Find_Package_Handle_Standard_Args ( cpphibernate CONFIG_MODE )
Include ( "${CMAKE_CURRENT_LIST_DIR}/cpphibernate.cmake")

+ 15
- 0
cmake/cpphibernate-options.cmake View File

@@ -0,0 +1,15 @@
Option ( CPPHIBERNATE_INSTALL_HEADER
"Install headers of cpphibernate."
ON )
Option ( CPPHIBERNATE_INSTALL_STATIC
"Install static library of cpphibernate."
ON )
Option ( CPPHIBERNATE_INSTALL_SHARED
"Install shared library of cpphibernate."
ON )
Option ( CPPHIBERNATE_INSTALL_DEBUG
"Install the stripped debug informations of cpphibernate."
OFF )
Option ( CPPHIBERNATE_NO_STRIP
"Do not strip debug symbols from binary."
OFF )

+ 31
- 0
cmake/cpphibernate-var.cmake View File

@@ -0,0 +1,31 @@
# Version
Set ( CPPHIBERNATE_VERSION_MAJOR 1 )
Set ( CPPHIBERNATE_VERSION_MINOR 0 )
Set ( CPPHIBERNATE_VERSION_PATCH 0 )
Set ( CPPHIBERNATE_VERSION_BUILD 0 )
Set ( CPPHIBERNATE_VERSION_SHORT "${CPPHIBERNATE_VERSION_MAJOR}.${CPPHIBERNATE_VERSION_MINOR}" )
Set ( CPPHIBERNATE_VERSION "${CPPHIBERNATE_VERSION_SHORT}.${CPPHIBERNATE_VERSION_PATCH}.${CPPHIBERNATE_VERSION_BUILD}" )
Set ( CPPHIBERNATE_NAME "cpphibernate-${CPPHIBERNATE_VERSION_SHORT}" )
Set ( CPPHIBERNATE_OUTPUTNAME "cpphibernate" )

# Install directories
Set ( CPPHIBERNATE_INSTALL_DIR_INCLUDE "include/${CPPHIBERNATE_NAME}" )
Set ( CPPHIBERNATE_INSTALL_DIR_LIB "lib" )
Set ( CPPHIBERNATE_INSTALL_DIR_SHARE "share/${CPPHIBERNATE_NAME}" )

# C Standard
Set ( CMAKE_C_STANDARD 11 )
Set ( CMAKE_CXX_STANDARD 17 )
Set ( CMAKE_C_STANDARD_REQUIRED ON )
Set ( CMAKE_CXX_STANDARD_REQUIRED ON )

# Git Version
Include ( git_helper OPTIONAL RESULT_VARIABLE HAS_GIT_HELPER )
If ( HAS_GIT_HELPER )
GitGetVersion ( ${CMAKE_CURRENT_LIST_DIR}/..
CPPHIBERNATE_VERSION_MAJOR
CPPHIBERNATE_VERSION_MINOR
CPPHIBERNATE_VERSION_PATCH
CPPHIBERNATE_VERSION_BUILD
CPPHIBERNATE_VERSION_HASH )
EndIf ( )

+ 1
- 1
cmake/modules

@@ -1 +1 @@
Subproject commit b125a1a176ae0aada1cd2ec90919061d202dcea9
Subproject commit 1a32531aef2deeebd5637b1873bc4e976628801c

+ 0
- 9
cmake/options.cmake View File

@@ -1,9 +0,0 @@
Option ( CPPHIBERNATE_BUILD_SHARED
"Build cpphibernate shared library"
ON )
Option ( CPPHIBERNATE_INSTALL_DEV_FILES
"Install development files of cpphibernate"
ON )
Option ( CPPHIBERNATE_DEBUG
"Enable debug output"
OFF )

+ 0
- 1
cmake/options.h.in View File

@@ -1 +0,0 @@
#cmakedefine CPPHIBERNATE_DEBUG

+ 3
- 6
include/cpphibernate.h View File

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

#include <cpphibernate/config.h>
#include <cpphibernate/context.h>
#include <cpphibernate/misc.h>
#include <cpphibernate/modifier.h>
#include <cpphibernate/schema.h>
#include <cpphibernate/types.h>
#include "cpphibernate/misc.h"
#include "cpphibernate/schema.h"
#include "cpphibernate/types.h"

+ 3
- 64
include/cpphibernate/config.h View File

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

#include <cppmp.h>
#include <boost/hana.hpp>
#include <cpputils/mp/core.h>
#include <cpphibernate/options.h>

#ifdef CPPHIBERNATE_DEBUG
# include <cpputils/logging/global.h>
# define cpphibernate_debug_log(...) log_global_message(debug) << __VA_ARGS__
#else
# define cpphibernate_debug_log(...) do { } while(0)
#endif

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

#define cpphibernate_constructable(name, value) \
name() = value

#define cpphibernate_copyable(name, value) \
name(const name&) = value; \
name& operator=(const name&) = value

#define cpphibernate_moveable(name, value) \
name(name&&) = value; \
name& operator=(name&&) = value

#define cpphibernate_define_namespace_beg(parent, name) \
parent { \
namespace name

#define cpphibernate_define_namespace_end(parent) \
} \
parent

#define beg_namespace_cpphibernate namespace cpphibernate
#define end_namespace_cpphibernate

#define beg_namespace_cpphibernate_schema cpphibernate_define_namespace_beg(beg_namespace_cpphibernate, schema)
#define end_namespace_cpphibernate_schema cpphibernate_define_namespace_end(end_namespace_cpphibernate)

#define beg_namespace_cpphibernate_misc cpphibernate_define_namespace_beg(beg_namespace_cpphibernate, misc)
#define end_namespace_cpphibernate_misc cpphibernate_define_namespace_end(end_namespace_cpphibernate)

#define beg_namespace_cpphibernate_modifier cpphibernate_define_namespace_beg(beg_namespace_cpphibernate, modifier)
#define end_namespace_cpphibernate_modifier cpphibernate_define_namespace_end(end_namespace_cpphibernate)

#define beg_namespace_cpphibernate_driver cpphibernate_define_namespace_beg(beg_namespace_cpphibernate, driver)
#define end_namespace_cpphibernate_driver cpphibernate_define_namespace_end(end_namespace_cpphibernate)

#define beg_namespace_cpphibernate_driver_mariadb cpphibernate_define_namespace_beg(beg_namespace_cpphibernate_driver, mariadb_impl)
#define end_namespace_cpphibernate_driver_mariadb cpphibernate_define_namespace_end(end_namespace_cpphibernate_driver)

beg_namespace_cpphibernate
namespace cpphibernate
{

namespace mp = ::utl::mp;
namespace mp = ::cppmp;
namespace hana = ::boost::hana;

}
end_namespace_cpphibernate

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

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

#include <memory>

#include <cpphibernate/misc.h>
#include <cpphibernate/config.h>
#include <cpphibernate/schema/table.h>
#include <cpphibernate/schema/tables.h>
#include <cpphibernate/modifier/where.h>
#include <cpphibernate/modifier/modifiers.h>

beg_namespace_cpphibernate
{

namespace __impl
{

template<typename T_driver, typename T_schema>
struct context_t
: public T_driver
{
public:
using base_type = T_driver;
using driver_type = T_driver;
using schema_type = T_schema;

private:
const schema_type& _schema;

public:
template<typename... T_args>
constexpr context_t(const schema_type& p_schema, T_args&&... args)
: base_type (p_schema, std::forward<T_args>(args)...)
, _schema (p_schema)
{ }

cpphibernate_copyable(context_t, delete);
cpphibernate_moveable(context_t, default);

/* init */

inline void init(bool recreate)
{ this->init_impl(recreate); }

/* create */

template<typename T_dataset>
constexpr void create(T_dataset& dataset)
{ this->create_impl(dataset); }

/* read */

template<typename T_dataset, typename... T_modifiers>
constexpr auto read(T_dataset& dataset, T_modifiers&&... modifiers)
-> mp::enable_if<
modifier::all_are_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());
}

/* update */

template<typename T_dataset>
constexpr void update(T_dataset& dataset)
{ this->update_impl(dataset); }

/* destroy */

template<typename T_dataset>
constexpr void destroy(T_dataset& dataset)
{ this->destroy_impl(dataset); }
};

}

/* make */

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

template<typename T_driver, typename T_schema, typename... T_args>
constexpr decltype(auto) make_context_ptr(T_schema&& schema, T_args&&... args)
{
using context_type = __impl::context_t<T_driver, T_schema>;
using pointer_type = std::unique_ptr<context_type>;
return pointer_type(new context_type(std::forward<T_schema>(schema), std::forward<T_args>(args)...));
}


}
end_namespace_cpphibernate

+ 4
- 6
include/cpphibernate/misc.h View File

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

#include <cpphibernate/misc/container_helper.h>
#include <cpphibernate/misc/general.h>
#include <cpphibernate/misc/meta.h>
#include <cpphibernate/misc/nullable_helper.h>
#include <cpphibernate/misc/print.h>
#include <cpphibernate/misc/wrap.h>
#include "misc/equality_compare.h"
#include "misc/print_container.h"
#include "misc/printing.h"
#include "misc/type_helper.h"

+ 0
- 52
include/cpphibernate/misc/container_helper.h View File

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

#include <set>
#include <list>
#include <vector>

#include <cpphibernate/config.h>

beg_namespace_cpphibernate_misc
{

/* container_helper */

template<typename T_container, typename = void>
struct container_helper;

template<typename T_value, typename... T_args>
struct container_helper<std::vector<T_value, T_args...>, void>
{
using container_type = std::vector<T_value, T_args...>;
using value_type = T_value;

template<typename... T_xargs>
static inline value_type& emplace(container_type& container, T_xargs&&... args)
{
container.emplace_back(std::forward<T_xargs>(args)...);
return container.back();
}

static inline void clear(container_type& container)
{ container.clear(); }
};

template<typename T_value, typename... T_args>
struct container_helper<std::list<T_value, T_args...>, void>
{
using container_type = std::list<T_value, T_args...>;
using value_type = T_value;

template<typename... T_xargs>
static inline value_type& emplace(container_type& container, T_xargs&&... args)
{
container.emplace_back(std::forward<T_xargs>(args)...);
return container.back();
}

static inline void clear(container_type& container)
{ container.clear(); }
};

}
end_namespace_cpphibernate_misc

+ 30
- 0
include/cpphibernate/misc/equality_compare.h View File

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

#include <cpphibernate/config.h>

namespace cpphibernate
{

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

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

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

}

#include "equality_compare.inl"

+ 61
- 0
include/cpphibernate/misc/equality_compare.inl View File

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

}

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

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

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

beg_namespace_cpphibernate_misc
{

/* make_generic_predicate */

template<template<typename...> class T_builder>
struct make_generic_predicate
{
template<typename... T_args>
constexpr decltype(auto) operator()(T_args&&... args) const
{ return T_builder<mp::list<T_args...>>::apply(std::forward<T_args>(args)...); }
};

/* get_dataset_id */

namespace __impl
{
struct counter_type_id
{ };
}

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

}
end_namespace_cpphibernate_misc

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

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

#include <list>
#include <vector>
#include <memory>

#include <cpphibernate/config.h>

#include <cpputils/misc/exception.h>
#include <cpputils/container/nullable.h>

beg_namespace_cpphibernate_misc
{

namespace __impl
{

/* is_container_impl */

template<typename T>
struct is_container_impl
: public mp::c_false_t
{ };

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

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

/* is_nullable_impl */

template<typename T>
struct is_nullable_impl
: public mp::c_false_t
{ };

template<typename T>
struct is_nullable_impl<utl::nullable<T>>
: public mp::c_true_t
{ };

template<typename T>
struct is_nullable_impl<std::unique_ptr<T>>
: public mp::c_true_t
{ };

template<typename T>
struct is_nullable_impl<std::shared_ptr<T>>
: public mp::c_true_t
{ };

/* is_pointer_impl */

template<typename T>
struct is_pointer_impl
: public mp::c_false_t
{ };

template<typename T>
struct is_pointer_impl<std::unique_ptr<T>>
: public mp::c_true_t
{ };

template<typename T>
struct is_pointer_impl<std::shared_ptr<T>>
: public mp::c_true_t
{ };

/* is_ordered_impl */

template<typename T>
struct is_ordered_impl
: public mp::c_false_t
{ };

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

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

/* real_dataset_impl */

template<typename T, typename = void>
struct real_dataset_impl
{ using type = T; };

template<typename T>
struct real_dataset_impl<utl::nullable<T>, void>
{ using type = typename real_dataset_impl<T>::type; };

template<typename T, typename... T_args>
struct real_dataset_impl<std::unique_ptr<T, T_args...>, void>
{ using type = typename real_dataset_impl<T>::type; };

template<typename T>
struct real_dataset_impl<std::shared_ptr<T>, void>
{ using type = typename real_dataset_impl<T>::type; };

template<typename T, typename... T_args>
struct real_dataset_impl<std::list<T, T_args...>, void>
{ using type = typename real_dataset_impl<T>::type; };

template<typename T, typename... T_args>
struct real_dataset_impl<std::vector<T, T_args...>, void>
{ using type = typename real_dataset_impl<T>::type; };
}

/* meta */

template<typename T>
struct is_container
: public __impl::is_container_impl<T>
{ };

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

template<typename T>
struct is_ordered
: public __impl::is_ordered_impl<T>
{ };

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

template<typename T>
using real_dataset_t = typename __impl::real_dataset_impl<T>::type;

/* hibernate_exception */

struct hibernate_exception
: public utl::exception
{
using utl::exception::exception;
};

}
end_namespace_cpphibernate_misc

+ 0
- 120
include/cpphibernate/misc/nullable_helper.h View File

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

#include <memory>

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

#include <cpputils/container/nullable.h>

beg_namespace_cpphibernate_misc
{

/* nullable_helper */

template<typename T_nullable, typename = void>
struct nullable_helper
{
using nullable_type = T_nullable;
using value_type = real_dataset_t<nullable_type>;

static value_type* get (const nullable_type&) = delete;
static value_type& set (nullable_type&, const value_type&) = delete;
static void clear (nullable_type&) = delete;
};

/* nullable_helper - utl::nullable */

template<typename T_value>
struct nullable_helper<utl::nullable<T_value>, void>
{
using nullable_type = utl::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 */

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

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

/* nullable_helper - std::shared_ptr */

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

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

}
end_namespace_cpphibernate_misc

+ 0
- 112
include/cpphibernate/misc/print.h View File

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

#include <list>
#include <vector>
#include <memory>
#include <iostream>

#include <cpphibernate/config.h>
#include <cpputils/misc/indent.h>

namespace std
{

template<typename T_char, typename T_traits, typename X>
inline auto operator <<(basic_ostream<T_char, T_traits>& os, X&& x)
-> ::utl::mp::enable_if<
utl::mp::is_valid<decltype(std::forward<X>(x).print(os))>,
basic_ostream<T_char, T_traits>&>
{
std::forward<X>(x).print(os);
return os;
}

}

beg_namespace_cpphibernate_misc
{

template<typename T_container, typename T_func>
struct container_printer
{
T_container container;
bool do_indent;
T_func func;

inline void print(std::ostream& os) const
{
using namespace ::utl;
auto beg = std::begin(container);
auto end = std::end (container);
if (beg != end)
{
if (do_indent)
{
os << indent << "["
<< incindent;
}
else
{
os << "[";
}

size_t index = 0;
for (auto it = beg; it != end; ++it)
{
if (index++)
os << ",";
if (!do_indent)
os << " ";
func(os, *it);
}

if (do_indent)
{
os << decindent
<< indent << "]";
}
else
{
os << " ]";
}
}
else
{
os << "[ ]";
}
}
};

struct print_container_builder
{
template<typename T_container, typename T_func>
constexpr decltype(auto) operator()(T_container&& container, bool do_indent, T_func&& func) const
{
return container_printer<T_container, T_func>
{
std::forward<T_container>(container),
do_indent,
std::forward<T_func>(func)
};
}

template<typename T_container>
constexpr decltype(auto) operator()(T_container&& container, bool do_indent) const
{
return this->operator()(
std::forward<T_container>(container),
do_indent,
[do_indent](auto& os, auto& value)
{
using namespace ::utl;
if (do_indent)
os << indent;
os << utl::to_string(value);
});
}
};

constexpr decltype(auto) print_container = print_container_builder { };

}
end_namespace_cpphibernate_misc

+ 26
- 0
include/cpphibernate/misc/print_container.h View File

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

#include <cpphibernate/config.h>

namespace cpphibernate
{

namespace __impl
{

/**
* @brief Helper type to build print container.
*/
template<typename X, typename = void>
struct print_container_builder;

}

/**
* @brief Predicate to create print container from the passed attributes.
*/
constexpr decltype(auto) make_print_container = mp::generic_predicate<__impl::print_container_builder> { };

}

#include "print_container.inl"

+ 116
- 0
include/cpphibernate/misc/print_container.inl View File

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

#include <cppcore/misc/indent.h>

#include "print_container.h"

namespace cpphibernate
{

namespace __impl
{

/* print_container */

template<typename T_container, typename T_func>
struct print_container
{
using container_type = T_container;
using func_type = T_func;

container_type container;
bool do_indent;
func_type func;

inline void print(std::ostream& os) const
{
using namespace ::cppcore;

auto beg = std::begin(container);
auto end = std::end (container);
if (beg != end)
{
if (do_indent)
{
os << indent << "["
<< incindent;
}
else
{
os << "[";
}

size_t index = 0;
for (auto it = beg; it != end; ++it)
{
if (index++)
os << ",";
if (!do_indent)
os << " ";
func(os, *it);
}

if (do_indent)
{
os << decindent
<< indent << "]";
}
else
{
os << " ]";
}
}
else
{
os << "[ ]";
}
}
};

/* print_container_builder */

template<typename X, typename>
struct print_container_builder
{
template<typename... T_args>
static constexpr decltype(auto) apply(T_args&&...)
{ 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>
{
static constexpr decltype(auto) apply(T_container&& container, bool do_indent, T_func&& func)
{
using print_container_type = print_container<T_container, T_func>;
return print_container_type {
std::forward<T_container>(container),
do_indent,
std::forward<T_func>(func),
};
}
};

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

make_print_container(
std::forward<T_container>(container),
do_indent,
[do_indent](auto& os, auto& value)
{
using namespace ::cppcore;
if (do_indent)
os << indent;
os << to_string(value);
});
}
};

}

}

+ 20
- 0
include/cpphibernate/misc/printing.h View File

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

#include <iostream>

#include <cpphibernate/config.h>

namespace std
{

template<typename T_char, typename T_traits, typename X>
inline auto operator <<(basic_ostream<T_char, T_traits>& os, X&& x)
-> ::cppmp::enable_if_t<
::cppmp::is_valid_v<decltype(std::forward<X>(x).print(os))>,
basic_ostream<T_char, T_traits>&>
{
std::forward<X>(x).print(os);
return os;
}

}

+ 34
- 0
include/cpphibernate/misc/type_helper.h View File

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

#include <cpphibernate/config.h>

namespace cpphibernate
{

/**
* @brief Evaluates to the basic dataset type (containers are removed).
*/
template<typename T>
struct real_dataset;

/**
* @brief Basic dataset type (containers are removed).
*/
template<typename T>
using real_dataset_t = typename real_dataset<T>::type;

/**
* @brief Extract the type stored in an type definition .
*/
template<typename T>
using unwrap_t = typename T::type;

/**
* @brief Extract the decayed type in an type definition.
*/
template<typename T>
using decay_unwrap_t = typename mp::decay_t<T>::type;

}

#include "type_helper.inl"

+ 53
- 0
include/cpphibernate/misc/type_helper.inl View File

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

#include "type_helper.h"

#include <list>
#include <vector>
#include <memory>

#include <cppcore/misc/nullable.h>
#include <cpphibernate/config.h>

namespace cpphibernate
{

namespace __impl
{

/* real_dataset_impl */

template<typename T, typename = void>
struct real_dataset_impl
{ using type = T; };

template<typename T>
struct real_dataset_impl<cppcore::nullable<T>, void>
{ using type = typename real_dataset_impl<T>::type; };

template<typename T, typename... T_args>
struct real_dataset_impl<std::unique_ptr<T, T_args...>, void>
{ using type = typename real_dataset_impl<T>::type; };

template<typename T>
struct real_dataset_impl<std::shared_ptr<T>, void>
{ using type = typename real_dataset_impl<T>::type; };

template<typename T, typename... T_args>
struct real_dataset_impl<std::list<T, T_args...>, void>
{ using type = typename real_dataset_impl<T>::type; };

template<typename T, typename... T_args>
struct real_dataset_impl<std::vector<T, T_args...>, void>
{ using type = typename real_dataset_impl<T>::type; };

}

/* real_dataset */

template<typename T>
struct real_dataset
: public __impl::real_dataset_impl<T>
{ };

}

+ 0
- 44
include/cpphibernate/misc/wrap.h View File

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

#include <list>
#include <vector>
#include <memory>

#include <cpphibernate/config.h>

#include <cpputils/container/nullable.h>

beg_namespace_cpphibernate_misc
{

template<typename T>
using unwrap_t = typename T::type;

template<typename T>
using decay_unwrap_t = typename mp::decay_t<T>::type;

namespace __impl
{

struct wrap_t
{
template<typename T>
constexpr decltype(auto) operator()(T) const noexcept
{ return hana::type_c<T>; }
};

struct unwrapped_t
{
template<typename T>
constexpr decltype(auto) operator()(T) const noexcept
{ return unwrap_t<T> { }; }
};

}

constexpr decltype(auto) wrap = __impl::wrap_t { };

constexpr decltype(auto) unwrap = __impl::unwrapped_t { };

}
end_namespace_cpphibernate_misc

+ 0
- 8
include/cpphibernate/modifier.h View File

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

#include <cpphibernate/modifier/limit.h>
#include <cpphibernate/modifier/modifier.h>
#include <cpphibernate/modifier/modifiers.h>
#include <cpphibernate/modifier/offset.h>
#include <cpphibernate/modifier/order_by.h>
#include <cpphibernate/modifier/where.h>

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

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

#include <cpphibernate/schema/attribute.h>
#include <cpphibernate/schema/attributes.h>
#include <cpphibernate/schema/field.h>
#include <cpphibernate/schema/fields.h>
#include <cpphibernate/schema/getter.h>
#include <cpphibernate/schema/macros.h>
#include <cpphibernate/schema/schema.h>
#include <cpphibernate/schema/setter.h>
#include <cpphibernate/schema/table.h>
#include <cpphibernate/schema/tables.h>
#include "schema/macros.h"

#include "schema/attribute.h"
#include "schema/attributes.h"
#include "schema/field.h"
#include "schema/fields.h"
#include "schema/table.h"
#include "schema/tables.h"
#include "schema/schema.h"

+ 39
- 24
include/cpphibernate/schema/attribute.h View File

@@ -1,23 +1,31 @@
#pragma once

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

beg_namespace_cpphibernate_schema
{
namespace cpphibernate {
namespace schema {

namespace __impl
{

/* attribute_t */
/**
* @brief Tag class to mark attribute types.
*/
struct tag_attribute
{ };

/**
* @brief Attribute implementation.
*/
template<typename T_inner>
struct attribute_t
: public T_inner
, public tag_attribute
, public tag_equality_comparable<tag_attribute>
{
using inner_type = T_inner;
using this_type = attribute_t<inner_type>;

cpphibernate_equality_comparable();
};

struct hex_t { static constexpr decltype(auto) name = "hex"; };
@@ -29,32 +37,39 @@ beg_namespace_cpphibernate_schema
namespace attribute
{

using hex_type = __impl::attribute_t<__impl::hex_t>;
using compress_type = __impl::attribute_t<__impl::compress_t>;
using primary_key_type = __impl::attribute_t<__impl::primary_key_t>;
using hex_type = __impl::attribute_t<__impl::hex_t>;
using compress_type = __impl::attribute_t<__impl::compress_t>;
using primary_key_type = __impl::attribute_t<__impl::primary_key_t>;

/** value is stored as hexadecimal string, and will be converted to its binary form on read */
constexpr hex_type hex { };
/**
* @brief Attribute to indicate that the value is stored as hexadecimal string.
*/
constexpr hex_type hex { };

/** value is stored as compressed binary, and will be uncompressed on read */
constexpr compress_type compress { };
/**
* @brief Attribute to indicate that the value is stored compressed.
*/
constexpr compress_type compress { };

/** this value represents a primary key (it must be stored in the dataset to be able to do the operations on the database) */
constexpr primary_key_type primary_key { };
/**
* @brief Attribute to indicate that the value is the primary key field.
*/
constexpr primary_key_type primary_key { };

}

/* meta */
/**
* @brief Evaluates to true_t if the passed type is an attribute type.
*/
template<typename T>
struct is_attribute;

/**
* @brief Is true if the passed type is an attribute, false otherwise.
*/
template<typename T>
struct is_attribute
: public mp::is_specialization_of<T, __impl::attribute_t>
{ };
constexpr bool is_attribute_v = is_attribute<T>::value;

template<typename... T>
struct all_are_attribures
: public mp::all_true<is_attribute<T>::value...>
{ };
} }

}
end_namespace_cpphibernate_schema
#include "attribute.inl"

+ 15
- 0
include/cpphibernate/schema/attribute.inl View File

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

#include "attribute.h"

namespace cpphibernate {
namespace schema {

/* is_attribute */

template<typename T>
struct is_attribute
: public mp::is_base_of<__impl::tag_attribute, T>
{ };

} }

+ 21
- 55
include/cpphibernate/schema/attributes.h View File

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

#include <cpphibernate/config.h>
#include <cpphibernate/misc.h>
#include <cpphibernate/schema/attribute.h>

beg_namespace_cpphibernate_schema
{
namespace cpphibernate {
namespace schema {

namespace __impl
{

/* attributes_t */

template<typename... T_attributes>
using attributes_t = hana::tuple<T_attributes...>;

/* is_attributes_impl */

/**
* @brief Helper type to build attributes.
*/
template<typename T, typename = void>
struct is_attributes_impl
: mp::c_false_t
{ };

template<typename... T>
struct is_attributes_impl<attributes_t<T...>, mp::enable_if<all_are_attribures<T...>>>
: mp::c_true_t
{ };
struct attributes_builder;

}

/* meta */

/**
* @brief Evaluates to true_t if the passed type is a attributes type.
*/
template<typename T>
struct is_attributes
: public __impl::is_attributes_impl<T>
{ };

/* operations */

namespace __impl
{
struct is_attributes;

/* attributes_make_impl */

template<typename T, typename = void>
struct attributes_make_impl
{
template<typename... T_args>
static constexpr decltype(auto) apply(T_args&&...)
{ static_assert(sizeof...(T_args) == -1, "Invalid parameters for hibernate::schema::attributes::make(...)!"); }
};

template<typename... T>
struct attributes_make_impl<mp::list<T...>, mp::enable_if_c<
all_are_attribures<mp::decay_t<T>...>::value>>
{
template<typename... T_args>
static constexpr decltype(auto) apply(T_args&&...)
{ return attributes_t<mp::decay_t<T_args>...> { }; }
};

}

namespace attributes
{
/**
* @brief Is true if the passed type is an attributes type, false otherwise.
*/
template<typename T>
constexpr bool is_attributes_v = is_attributes<T>::value;

constexpr decltype(auto) make = misc::make_generic_predicate<__impl::attributes_make_impl> { };
/**
* @brief Predicate to create an attributes object from the passed attributes.
*/
constexpr decltype(auto) make_attributes = mp::generic_predicate<__impl::attributes_builder> { };

}
} }

}
end_namespace_cpphibernate_schema
#include "attributes.inl"

+ 62
- 0
include/cpphibernate/schema/attributes.inl View File

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

#include "attributes.h"

namespace cpphibernate {
namespace schema {

namespace __impl
{

/* attributes_t */

template<typename... T_attributes>
using attributes_t = hana::basic_tuple<T_attributes...>;

/* attributes_builder */

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

template<typename... T>
struct attributes_builder<
mp::list<T...>,
mp::enable_if_t<
mp::is_true_v<is_attribute_v<mp::decay_t<T>>...>>>
{
static constexpr decltype(auto) apply(T&&...)
{
using attributes_type = attributes_t<mp::decay_t<T>...>;
return attributes_type { };
}
};

/* is_attributes_impl */

template<typename T, typename = void>
struct is_attributes_impl
: mp::false_t
{ };

template<typename... T>
struct is_attributes_impl<
attributes_t<T...>,
mp::enable_if_t<mp::is_true_v<is_attribute_v<mp::decay_t<T>>...>>>
: mp::true_t
{ };

}

/* is_attributes */

template<typename T>
struct is_attributes
: public __impl::is_attributes_impl<T>
{ };

} }

+ 22
- 110
include/cpphibernate/schema/field.h View File

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

#include <cpphibernate/misc.h>
#include <cpphibernate/config.h>
#include <cpphibernate/schema/getter.h>
#include <cpphibernate/schema/setter.h>
#include <cpphibernate/schema/attributes.h>

#include <cpputils/misc/indent.h>
#include <cpputils/misc/type_helper.h>

beg_namespace_cpphibernate_schema
{
namespace cpphibernate {
namespace schema {

namespace __impl
{

/* field_t */

template<typename T_name, typename T_getter, typename T_setter, typename T_attributes>
struct field_t
{
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(
T_name&& p_name,
T_getter&& p_getter,
T_setter&& p_setter,
T_attributes&& p_attributes)
: name (std::forward<T_name> (p_name))
, getter (std::forward<T_getter> (p_getter))
, setter (std::forward<T_setter> (p_setter))
, attributes (std::forward<T_attributes>(p_attributes))
{ }

cpphibernate_copyable(field_t, delete);
cpphibernate_moveable(field_t, default);

cpphibernate_equality_comparable();

inline void print(std::ostream& os) const
{
using namespace ::utl;
using value_type = typename mp::decay_t<getter_type>::value_type;
using dataset_type = misc::real_dataset_t<value_type>;
size_t index = 0;
os << indent << '{'
<< incindent
<< indent << "\"name\": \"" << name << "\","
<< indent << "\"value_type\": \"" << utl::type_helper<value_type>::name() << "\""
<< indent << "\"dataset_type\": \"" << utl::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 << '}';
}
};
/**
* @brief Helper type to build field objects.
*/
template<typename X, typename = void>
struct field_builder;

}

/* meta */

/**
* @brief Evaluates to true_t if the passed type is a field type.
*/
template<typename T>
struct is_field
: public mp::is_specialization_of<T, __impl::field_t>
{ };

template<typename... T>
struct all_are_fields
: public mp::all_true<is_field<T>::value...>
{ };

/* operations */

namespace __impl
{

/* field_make_impl */

template<typename X, typename = void>
struct field_make_impl
{
template <typename ...T_args>
static constexpr decltype(auto) apply(T_args&&... args)
{ static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::field::make(...)!"); }
};

template<typename T_name, typename T_getter, typename T_setter, typename T_attributes>
struct field_make_impl<mp::list<T_name, T_getter, T_setter, T_attributes>, mp::enable_if_c<
is_getter<mp::decay_t<T_getter>>::value
&& is_setter<mp::decay_t<T_setter>>::value
&& is_attributes<mp::decay_t<T_attributes>>::value>>
{
using field_type = field_t<T_name, T_getter, T_setter, T_attributes>;
struct is_field;

static constexpr decltype(auto) apply(T_name&& name, T_getter&& getter, T_setter&& setter, T_attributes&& attributes)
{ return field_type(std::forward<T_name>(name), std::forward<T_getter>(getter), std::forward<T_setter>(setter), std::forward<T_attributes>(attributes)); }
};

}

namespace field
{
/**
* @brief Is true if the passed type is an attributes type, false otherwise.
*/
template<typename T>
constexpr bool is_field_v = is_field<T>::value;

constexpr decltype(auto) make = misc::make_generic_predicate<__impl::field_make_impl> { };
/**
* @brief Predicate to create an field object from the passed attributes.
*/
constexpr decltype(auto) make_field = mp::generic_predicate<__impl::field_builder> { };

}
} }

}
end_namespace_cpphibernate_schema
#include "field.inl"

+ 132
- 0
include/cpphibernate/schema/field.inl View File

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

#include <cppcore/misc/indent.h>
#include <cppcore/misc/type_helper.h>

#include <cpphibernate/misc/type_helper.h>

#include "field.h"

namespace cpphibernate {
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(
T_name&& p_name,
T_getter&& p_getter,
T_setter&& p_setter,
T_attributes&& p_attributes)
: name (std::forward<T_name> (p_name))
, getter (std::forward<T_getter> (p_getter))
, setter (std::forward<T_setter> (p_setter))
, 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 << '}';
}
};

/* field_builder */

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

template<typename T_name, typename T_getter, typename T_setter, typename T_attributes>
struct field_builder<
mp::list<T_name, T_getter, T_setter, T_attributes>,
mp::enable_if_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>>
>>
{
using name_type = T_name;
using getter_type = T_getter;
using setter_type = T_setter;
using attributes_type = T_attributes;
using field_type = field_t<name_type, getter_type, setter_type, attributes_type>;

static constexpr decltype(auto) apply(
name_type&& name,
getter_type&& getter,
setter_type&& setter,
attributes_type&& attributes)
{
return field_type(
std::forward<name_type> (name),
std::forward<getter_type> (getter),
std::forward<setter_type> (setter),
std::forward<attributes_type> (attributes));
}
};

}

/* is_field */

template<typename T>
struct is_field
: public mp::is_base_of<__impl::tag_field, T>
{ };

} }

+ 21
- 54
include/cpphibernate/schema/fields.h View File

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

#include <cpphibernate/config.h>
#include <cpphibernate/misc/general.h>
#include <cpphibernate/schema/field.h>

beg_namespace_cpphibernate_schema
{
namespace cpphibernate {
namespace schema {

namespace __impl
{

/* fields_t */

template<typename... T_fields>
using fields_t = hana::tuple<T_fields...>;

/* is_fields_impl */

/**
* @brief Helper type to build fields.
*/
template<typename T, typename = void>
struct is_fields_impl
: public mp::c_false_t
{ };

template<typename... T>
struct is_fields_impl<fields_t<T...>, mp::enable_if<all_are_fields<T...>>>
: public mp::c_true_t
{ };
struct fields_builder;

}

/* meta */

/**
* @brief Evaluates to true_t if the passed type is a fields type.
*/
template<typename T>
struct is_fields :
public __impl::is_fields_impl<T>
{ };

/* operations */

namespace __impl
{
struct is_fields;

/* fields_make_impl */

template <typename T, typename = void>
struct fields_make_impl
{
template <typename ...T_args>
static constexpr decltype(auto) apply(T_args&&... args)
{ static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::fields::make(...)!"); }
};

template<typename... T>
struct fields_make_impl<mp::list<T...>, mp::enable_if<all_are_fields<T...>>>
{
template <typename ...T_args>
static constexpr decltype(auto) apply(T_args&&... args)
{ return fields_t<T_args...>(std::forward<T_args>(args)...); }
};

}

namespace fields
{
/**
* @brief Is true if the passed type is an fields type, false otherwise.
*/
template<typename T>
constexpr bool is_fields_v = is_fields<T>::value;

constexpr decltype(auto) make = misc::make_generic_predicate<__impl::fields_make_impl> { };
/**
* @brief Predicate to create an fields object from the passed fields.
*/
constexpr decltype(auto) make_fields = mp::generic_predicate<__impl::fields_builder> { };

}
} }

}
end_namespace_cpphibernate_schema
#include "fields.inl"

+ 63
- 0
include/cpphibernate/schema/fields.inl View File

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

#include "fields.h"

namespace cpphibernate {
namespace schema {

namespace __impl
{

/* fields_t */

template<typename... T_fields>
using fields_t = hana::basic_tuple<T_fields...>;

/* fields_builder */

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

template<typename... T>
struct fields_builder<
mp::list<T...>,
mp::enable_if_t<mp::is_true_v<
is_field_v<mp::decay_t<T>>...>>>
{
template<typename... T_args>
static constexpr decltype(auto) apply(T_args&&... args)
{
using fields_type = fields_t<T_args...>;
return fields_type(std::forward<T_args>(args)...);
}
};

/* is_fields_impl */

template<typename T, typename = void>
struct is_fields_impl
: mp::false_t
{ };

template<typename... T>
struct is_fields_impl<
fields_t<T...>,
mp::enable_if_t<mp::is_true_v<is_field_v<mp::decay_t<T>>...>>>
: mp::true_t
{ };

}

/* is_fields */

template<typename T>
struct is_fields
: public __impl::is_fields_impl<T>
{ };

} }

+ 0
- 192
include/cpphibernate/schema/getter.h View File

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

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

beg_namespace_cpphibernate_schema
{

namespace __impl
{

/* getter_t */

template<typename T_dataset, typename T_value>
struct getter_t
{
using dataset_type = T_dataset;
using value_type = T_value;
};

/* getter_member_var_t */

template<typename T_dataset, typename T_value, typename T_member>
struct getter_member_var_t
: public getter_t<T_dataset, T_value>
{
using base_type = getter_t<T_dataset, T_value>;
using dataset_type = typename base_type::dataset_type;
using value_type = typename base_type::value_type;
using member_type = T_member;

member_type member;

template<typename X_member>
constexpr getter_member_var_t(X_member&& p_member)
: member(std::forward<X_member>(p_member))
{ }

cpphibernate_copyable(getter_member_var_t, delete);
cpphibernate_moveable(getter_member_var_t, default);

template<typename X_dataset>
constexpr decltype(auto) operator()(X_dataset&& data) const
{ return std::forward<X_dataset>(data).*member; }
};

/* getter_member_func_t */

template<typename T_dataset, typename T_value, typename T_member>
struct getter_member_func_t
: public getter_t<T_dataset, T_value>
{
using base_type = getter_t<T_dataset, T_value>;
using dataset_type = typename base_type::dataset_type;
using value_type = typename base_type::value_type;
using member_type = T_member;

member_type member;

template<typename X_member>
constexpr getter_member_func_t(X_member&& p_member)
: member(std::forward<X_member>(p_member))
{ };

cpphibernate_copyable(getter_member_func_t, delete);
cpphibernate_moveable(getter_member_func_t, default);

template<typename X_dataset>
constexpr decltype(auto) operator()(X_dataset&& data) const
{ return (std::forward<X_dataset>(data).*member)(); }
};

/* getter_lambda_t */

template<typename T_lambda, typename T_dataset, typename T_value>
struct getter_lambda_t
: public getter_t<T_dataset, T_value>
{
using base_type = getter_t<T_dataset, T_value>;
using dataset_type = typename base_type::dataset_type;
using value_type = typename base_type::value_type;
using lambda_type = T_lambda;

lambda_type lambda;

template<typename X_lambda>
constexpr getter_lambda_t(X_lambda&& p_lambda)
: lambda(std::forward<X_lambda>(p_lambda))
{ }

cpphibernate_copyable(getter_lambda_t, delete);
cpphibernate_moveable(getter_lambda_t, default);

template<typename X_dataset>
constexpr decltype(auto) operator()(X_dataset&& data) const
{ return lambda(std::forward<X_dataset>(data)); }
};

/* is_getter_impl */

template<typename T, typename = void>
struct is_getter_impl
: public mp::c_false_t
{ };

template<typename T>
struct is_getter_impl<T, mp::enable_if<
mp::is_base_of<getter_t<typename T::dataset_type, typename T::value_type>, T>>>
: public mp::c_true_t
{ };

}

/* meta */

template<typename T>
struct is_getter :
public __impl::is_getter_impl<T>
{ };

/* make */

template<typename T_dataset, typename T_value>
constexpr decltype(auto) make_getter_member_var(T_value T_dataset::* member)
{
using getter_type = __impl::getter_member_var_t<T_dataset, T_value, T_value T_dataset::*>;
return getter_type(member);
}

template<typename T_dataset, typename T_value>
constexpr decltype(auto) make_getter_member_func(T_value (T_dataset::*member)())
{
using getter_type = __impl::getter_member_func_t<T_dataset, T_value, T_value (T_dataset::*)()>;
return getter_type(member);
}

template<typename T_dataset, typename T_value>
constexpr decltype(auto) make_getter_member_func(T_value (T_dataset::*member)() const)
{
using getter_type = __impl::getter_member_func_t<const T_dataset, T_value, T_value (T_dataset::*)() const>;
return getter_type(member);
}

template<typename T_lambda, typename T_wrapped_dataset, typename T_wrapped_value>
constexpr decltype(auto) make_getter_lambda(T_lambda&& lambda, T_wrapped_dataset&&, T_wrapped_value&&)
{
using getter_type = __impl::getter_lambda_t<T_lambda, misc::decay_unwrap_t<T_wrapped_dataset>, misc::decay_unwrap_t<T_wrapped_value>>;
return getter_type(std::forward<T_lambda>(lambda));
}

/* operations */

namespace __impl
{

/* getter_make_impl */

struct getter_make_impl
{
template<typename T_dataset, typename T_value>
constexpr decltype(auto) operator()(T_value T_dataset::*member) const
{ return make_getter_member_var(member); }

template<typename T_dataset, typename T_value>
constexpr decltype(auto) operator()(T_value (T_dataset::*member)(void)) const
{ return make_getter_member_func(member); }

template<typename T_dataset, typename T_value>
constexpr decltype(auto) operator()(T_value (T_dataset::*member)(void) const) const
{ return make_getter_member_func(member); }

template<typename T_func, typename T_dataset, typename T_value>
constexpr decltype(auto) operator()(T_func&& func, hana::type<T_dataset>&& wrapped_dataset, hana::type<T_value>&& wrapped_value) const
{ return make_getter_lambda(std::forward<T_func>(func), std::forward<hana::type<T_dataset>>(wrapped_dataset), std::forward<hana::type<T_value>>(wrapped_value)); }

template<typename T_getter>
constexpr auto operator()(T_getter&& getter) const
-> mp::enable_if<is_getter<T_getter>, T_getter>
{ return std::forward<T_getter>(getter); }
};

}

namespace getter
{

constexpr decltype(auto) make = __impl::getter_make_impl { };

}

}
end_namespace_cpphibernate_schema

+ 12
- 17
include/cpphibernate/schema/macros.h View File

@@ -1,32 +1,31 @@
#pragma once

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

#define cpphibernate_make_string(str) \
#str

#define cpphibernate_make_schema(p_name, ...) \
cpphibernate::schema::make( \
cpphibernate::schema::make_schema( \
cpphibernate_make_string(p_name), \
cpphibernate::schema::tables::make(__VA_ARGS__))
cpphibernate::schema::make_tables(__VA_ARGS__))

#define cpphibernate_make_table_name(p_name, p_type, p_id, ...) \
cpphibernate::schema::table::make( \
cpphibernate::schema::make_table( \
cpphibernate_make_string(p_name), \
boost::hana::type_c<p_type>, \
boost::hana::size_c<p_id>, \
cpphibernate::schema::fields::make(__VA_ARGS__))
cpphibernate::schema::make_fields(__VA_ARGS__))

#define cpphibernate_make_table(p_name, p_id, ...) \
cpphibernate_make_table_name(p_name, p_name, p_id, __VA_ARGS__)

#define cpphibernate_make_field_custom(p_name, p_getter, p_setter, ...) \
cpphibernate::schema::field::make( \
cpphibernate::schema::make_field( \
cpphibernate_make_string(p_name), \
cpphibernate::schema::getter::make(p_getter), \
cpphibernate::schema::setter::make(p_setter), \
cpphibernate::schema::attributes::make(__VA_ARGS__))
cpphibernate::mp::make_getter(p_getter), \
cpphibernate::mp::make_setter(p_setter), \
cpphibernate::schema::make_attributes(__VA_ARGS__))

#define cpphibernate_make_field_name(p_name, p_member_ptr, ...) \
cpphibernate_make_field_custom( \
@@ -45,14 +44,10 @@
#define cpphibernate_make_temp_id(p_dataset, p_value) \
cpphibernate_make_field_custom( \
id, \
::cpphibernate::schema::make_getter_lambda( \
::cpphibernate::mp::make_getter( \
[](p_dataset&) { \
return p_value { }; \
}, \
::boost::hana::type_c<p_dataset>, \
::boost::hana::type_c<p_value>), \
::cpphibernate::schema::make_setter_lambda( \
[](p_dataset&, p_value&&) { }, \
::boost::hana::type_c<p_dataset>, \
::boost::hana::type_c<p_value>), \
}), \
::cpphibernate::mp::make_setter( \
[](p_dataset&, p_value&&) { }), \
cpphibernate::schema::attribute::primary_key)

+ 22
- 236
include/cpphibernate/schema/schema.h View File

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

#include <cpphibernate/config.h>
#include <cpphibernate/misc/general.h>
#include <cpphibernate/schema/tables.h>

beg_namespace_cpphibernate_schema
{
namespace cpphibernate {
namespace schema {

namespace __impl
{

/* schema_t */

template<typename T_name, typename T_tables>
struct schema_t
{
using name_type = T_name;
using tables_type = T_tables;

name_type name;
tables_type tables;

constexpr schema_t(
T_name&& p_name,
T_tables&& p_tables)
: name (std::forward<T_name> (p_name))
, tables(std::forward<T_tables>(p_tables))
{ }

cpphibernate_copyable(schema_t, delete);
cpphibernate_moveable(schema_t, default);

inline void print(std::ostream& os) const
{
using namespace ::utl;
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 << '}';
}
};
/**
* @brief Helper type to build schema objects.
*/
template<typename X, typename = void>
struct schema_builder;

}

/* meta */

/**
* @brief Evaluates to true_t if the passed type is a schema type.
*/
template<typename T>
struct is_schema : mp::is_specialization_of<T, __impl::schema_t> { };

/* schema::make */

namespace __impl
{
template <typename X, typename = void>
struct schema_make_impl
{
template <typename... T_args>
static constexpr decltype(auto) apply(T_args&&... args)
{ static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::make(...)!"); }
};

template<typename T_name, typename T_tables>
struct schema_make_impl<mp::list<T_name, T_tables>, mp::enable_if_c<
is_tables<mp::decay_t<T_tables>>::value>>
{
static constexpr decltype(auto) apply(T_name&& name, T_tables&& tables)
{ return schema_t<T_name, T_tables>(std::forward<T_name>(name), std::forward<T_tables>(tables)); }
};
}

constexpr decltype(auto) make = misc::make_generic_predicate<__impl::schema_make_impl> { };

/* schema::get_base_type */

namespace __impl
{
struct schema_get_base_type_impl
{
static constexpr decltype(auto) is_base_of_pred = hana::integral(hana::metafunction<mp::is_base_of>);

struct do_fold_impl
{
template<typename T_type_1, typename T_type_2>
constexpr decltype(auto) operator()(T_type_1&& type_1, T_type_2&& type_2) const
{
auto check = hana::or_(is_base_of_pred(type_1, type_2), is_base_of_pred(type_2, type_1));
static_assert(decltype(check)::value, "A dataset must not have more than one base class!");
return hana::if_(is_base_of_pred(type_1, type_2), type_2, type_1);
}
};

static constexpr decltype(auto) do_fold = do_fold_impl { };

template<typename T_wrapped_datasets, typename T_wrapped_dataset>
static constexpr decltype(auto) get_base_types(T_wrapped_datasets&& wrapped_datasets, T_wrapped_dataset&& wrapped_dataset)
{
return hana::filter(
std::forward<T_wrapped_datasets>(wrapped_datasets),
[&](auto type){
return hana::and_(
is_base_of_pred(type, wrapped_dataset),
hana::not_equal(type, wrapped_dataset));
});
}

template<typename T_schema, typename T_wrapped_dataset>
constexpr decltype(auto) operator()(T_schema&& schema, T_wrapped_dataset&& wrapped_dataset) const
{
using wrapped_datasets_type = mp::decay_t<decltype(
hana::transform(
std::declval<T_schema>().tables,
schema::table::get_wrapped_dataset))>;
auto base_types = get_base_types(wrapped_datasets_type { }, std::forward<T_wrapped_dataset>(wrapped_dataset));
return hana::eval_if(
hana::size(base_types) <= hana::size_c<0>,
[&](auto _){ return hana::type_c<void>; },
[&](auto _){ return hana::fold(_(base_types), do_fold); });
}
};
}

constexpr decltype(auto) get_base_type = __impl::schema_get_base_type_impl { };
struct is_schema;

/* schema::get_root_base_type */

namespace __impl
{
struct schema_get_root_base_type_impl
{
template<typename T_wrapped_dataset>
struct is_base_pred
{
using dataset_type = misc::decay_unwrap_t<T_wrapped_dataset>;

template<typename T_type>
constexpr decltype(auto) operator()(T_type&&) const
{
using type = misc::unwrap_t<T_type>;
return hana::bool_c<
std::is_base_of<type, dataset_type>::value
&& !std::is_same <type, dataset_type>::value>;
}
};

template<typename T_schema, typename T_wrapped_dataset>
constexpr decltype(auto) operator()(T_schema&& schema, T_wrapped_dataset&& wrapped_dataset) const
{
auto all_types = hana::transform(
schema.tables,
table::get_wrapped_dataset);
auto base_type = hana::find_if(
all_types,
is_base_pred<T_wrapped_dataset> { });
return hana::eval_if(
base_type != hana::nothing,
[&](auto _){
return schema_get_root_base_type_impl { }(schema, _(base_type).value());
},
[&]{
return wrapped_dataset;
});
}
};
}

constexpr decltype(auto) get_root_base_type = __impl::schema_get_root_base_type_impl { };

/* schema::get_all_derived_types */

namespace __impl
{
struct schema_get_all_derived_types_impl
{
template<typename T_wrapped_dataset>
struct is_derived_pred
{
using dataset_type = misc::decay_unwrap_t<T_wrapped_dataset>;

template<typename T_type>
constexpr decltype(auto) operator()(T_type&&) const
{
return hana::bool_c<
std::is_base_of<dataset_type, misc::decay_unwrap_t<T_type>>::value>;
}
};

template<typename T_schema, typename T_wrapped_dataset>
constexpr decltype(auto) operator()(T_schema&& schema, T_wrapped_dataset&&) const
{
auto all_types = hana::transform(
schema.tables,
table::get_wrapped_dataset);
auto derived_types = hana::filter(
all_types,
is_derived_pred<T_wrapped_dataset> { });
return derived_types;
}
};
}

constexpr decltype(auto) get_all_derived_types = __impl::schema_get_all_derived_types_impl { };

/* schema::get_derived_types */

namespace __impl
{
struct schema_get_derived_types_impl
{
struct has_base_impl
{
template<typename T_schema, typename T_base_type, typename T_type>
constexpr decltype(auto) operator()(T_schema&& schema, T_base_type& base_type, T_type&& type) const
{ return get_base_type(schema, type) == base_type; }
};

static constexpr decltype(auto) has_base = has_base_impl { };
/**
* @brief Is true if the passed type is an attributes type, false otherwise.
*/
template<typename T>
constexpr bool is_schema_v = is_schema<T>::value;

template<typename T_schema, typename T_wrapped_dataset>
constexpr decltype(auto) operator()(T_schema&& schema, T_wrapped_dataset&& wrapped_dataset) const
{
using wrapped_datasets_type = mp::decay_t<decltype(
hana::transform(
std::declval<T_schema>().tables,
schema::table::get_wrapped_dataset))>;
using derived_wrapped_datasets_type = mp::decay_t<decltype(
hana::filter(
std::declval<wrapped_datasets_type>(),
hana::partial(
has_base,
std::declval<T_schema>(),
wrapped_dataset)))>;
return derived_wrapped_datasets_type { };
}
};
}
/**
* @brief Predicate to create an schema object from the passed attributes.
*/
constexpr decltype(auto) make_schema = mp::generic_predicate<__impl::schema_builder> { };

constexpr decltype(auto) get_derived_types = __impl::schema_get_derived_types_impl { };
} }

}
end_namespace_cpphibernate_schema
#include "schema.inl"

+ 102
- 0
include/cpphibernate/schema/schema.inl View File

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

#include "schema.h"

namespace cpphibernate {
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(
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 << '}';
}
};

/* schema_builder */

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

template<typename T_name, typename T_tables>
struct schema_builder<
mp::list<T_name, T_tables>,
mp::enable_if_t<
is_tables_v<mp::decay_t<T_tables>>>>
{
using name_type = T_name;
using tables_type = T_tables;
using schema_type = schema_t<name_type, tables_type>;

static constexpr decltype(auto) apply(
name_type&& name,
tables_type&& tables)
{
return schema_type(
std::forward<name_type> (name),
std::forward<tables_type>(tables));
}
};

}

/* is_schema */

template<typename T>
struct is_schema
: public mp::is_base_of<__impl::tag_schema, T>
{ };

} }

+ 0
- 216
include/cpphibernate/schema/setter.h View File

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

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

beg_namespace_cpphibernate_schema
{

namespace __impl
{

/* setter_t */

template<typename T_dataset, typename T_value>
struct setter_t
{
using dataset_type = T_dataset;
using value_type = T_value;
};

/* setter_none_t */

struct setter_none_t
: public setter_t<void, void>
{
using base_type = setter_t<void, void>;
using dataset_type = typename base_type::dataset_type;
using value_type = typename base_type::value_type;

cpphibernate_constructable(setter_none_t, default);
cpphibernate_copyable (setter_none_t, delete);
cpphibernate_moveable (setter_none_t, default);
};

/* setter_member_var_t */

template<typename T_dataset, typename T_value, typename T_member>
struct setter_member_var_t
: public setter_t<T_dataset, T_value>
{
using base_type = setter_t<T_dataset, T_value>;
using value_type = typename base_type::value_type;
using dataset_type = typename base_type::dataset_type;
using member_type = T_member;

member_type member;

template<typename X_member>
constexpr setter_member_var_t(X_member&& p_member)
: member(std::forward<X_member>(p_member))
{ }

cpphibernate_copyable(setter_member_var_t, delete);
cpphibernate_moveable(setter_member_var_t, default);

template<typename X_dataset, typename X_value>
constexpr decltype(auto) operator()(X_dataset&& data, X_value&& value) const
{ return std::forward<X_dataset>(data).*member = std::forward<X_value>(value); }
};

/* setter_member_func_t */

template<typename T_dataset, typename T_value, typename T_member>
struct setter_member_func_t
: public setter_t<T_dataset, T_value>
{
using base_type = setter_t<T_dataset, T_value>;
using value_type = typename base_type::value_type;
using dataset_type = typename base_type::dataset_type;
using member_type = T_member;

member_type member;

template<typename X_member>
constexpr setter_member_func_t(X_member&& p_member)
: member(std::forward<X_member>(p_member))
{ };

cpphibernate_copyable(setter_member_func_t, delete);
cpphibernate_moveable(setter_member_func_t, default);

template<typename X_dataset, typename X_value>
constexpr decltype(auto) operator()(X_dataset&& data, X_value&& value) const
{ return (std::forward<X_dataset>(data).*member)(std::forward<X_value>(value)); }
};

/* setter_lambda_t */

template<typename T_lambda, typename T_dataset, typename T_value>
struct setter_lambda_t
: public setter_t<T_dataset, T_value>
{
using base_type = setter_t<T_dataset, T_value>;
using value_type = typename base_type::value_type;
using dataset_type = typename base_type::dataset_type;
using lambda_type = T_lambda;

lambda_type lambda;

template<typename X_lambda>
constexpr setter_lambda_t(X_lambda&& p_lambda)
: lambda(std::forward<X_lambda>(p_lambda))
{ }

cpphibernate_copyable(setter_lambda_t, delete);
cpphibernate_moveable(setter_lambda_t, default);

template<typename X_dataset, typename X_value>
constexpr decltype(auto) operator()(X_dataset&& data, X_value&& value) const
{ return lambda(std::forward<X_dataset>(data), std::forward<X_value>(value)); }
};

/* is_setter_impl */

template<typename T, typename = void>
struct is_setter_impl
: public mp::c_false_t
{ };

template<typename T>
struct is_setter_impl<T, mp::enable_if<
mp::is_base_of<setter_t<typename T::dataset_type, typename T::value_type>, T>>>
: public mp::c_true_t
{ };

}

/* meta */

template<typename T>
struct is_setter :
public __impl::is_setter_impl<T>
{ };

/* make */

constexpr decltype(auto) make_setter_none()
{
using setter_type = __impl::setter_none_t;
return setter_type();
}

template<typename T_dataset, typename T_value>
constexpr decltype(auto) make_setter_member_var(T_value T_dataset::* member)
{
using setter_type = __impl::setter_member_var_t<T_dataset, T_value, T_value T_dataset::*>;
return setter_type(member);
}

template<typename T_dataset, typename T_value, typename T_return>
constexpr decltype(auto) make_setter_member_func(T_return (T_dataset::*member)(T_value))
{
using setter_type = __impl::setter_member_func_t<T_dataset, T_value, T_return (T_dataset::*)(T_value)>;
return setter_type(member);
}

template<typename T_dataset, typename T_value, typename T_return>
constexpr decltype(auto) make_setter_member_func(T_return (T_dataset::*member)(T_value) const)
{
using setter_type = __impl::setter_member_func_t<const T_dataset, T_value, T_return (T_dataset::*)(T_value) const>;
return setter_type(member);
}

template<typename T_lambda, typename T_wrapped_dataset, typename T_wrapped_value>
constexpr decltype(auto) make_setter_lambda(T_lambda&& lambda, T_wrapped_dataset&&, T_wrapped_value&&)
{
using setter_type = __impl::setter_lambda_t<T_lambda, misc::decay_unwrap_t<T_wrapped_dataset>, misc::decay_unwrap_t<T_wrapped_value>>;
return setter_type(std::forward<T_lambda>(lambda));
}

/* operations */

namespace __impl
{

/* setter_make_impl */

struct setter_make_impl
{
template<typename T_dataset, typename T_value>
constexpr decltype(auto) operator()(T_value T_dataset::*member) const
{ return make_setter_member_var(member); }

template<typename T_dataset, typename T_value>
constexpr decltype(auto) operator()(void (T_dataset::*member)(T_value)) const
{ return make_setter_member_func(member); }

template<typename T_dataset, typename T_value>
constexpr decltype(auto) operator()(void (T_dataset::*member)(T_value&)) const
{ return make_setter_member_func(member); }

template<typename T_dataset, typename T_value>
constexpr decltype(auto) operator()(void (T_dataset::*member)(T_value&&)) const
{ return make_setter_member_func(member); }

template<typename T_func, typename T_wrapped_dataset, typename T_wrapped_value>
constexpr decltype(auto) operator()(T_func&& func, T_wrapped_dataset&&, T_wrapped_value&&) const
{ return make_setter_lambda(std::forward<T_func>(func), T_wrapped_dataset { }, T_wrapped_value { }); }

template<typename T_setter>
constexpr auto operator()(T_setter&& setter) const
-> mp::enable_if<is_setter<T_setter>, T_setter>
{ return std::forward<T_setter>(setter); }
};

}

namespace setter
{

constexpr decltype(auto) make = __impl::setter_make_impl { };

}

}
end_namespace_cpphibernate_schema

+ 22
- 174
include/cpphibernate/schema/table.h View File

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

#include <cpphibernate/config.h>
#include <cpphibernate/misc/wrap.h>
#include <cpphibernate/misc/general.h>
#include <cpphibernate/schema/fields.h>
#include <cpphibernate/schema/attribute.h>

beg_namespace_cpphibernate_schema
{
namespace cpphibernate {
namespace schema {

namespace __impl
{

/* table_t */

template<typename T_name, typename T_wrapped_dataset, typename T_table_id, typename T_fields>
struct table_t
{
using name_type = T_name;
using wrapped_dataset_type = mp::decay_t<T_wrapped_dataset>;
using dataset_type = misc::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(
T_name p_name,
T_wrapped_dataset p_wrapped_dataset,
T_table_id p_table_id,
T_fields p_fields)
: name (std::forward<T_name> (p_name))
, wrapped_dataset (std::forward<T_wrapped_dataset>(p_wrapped_dataset))
, table_id (std::forward<T_table_id> (p_table_id))
, fields (std::forward<T_fields> (p_fields))
{ }

cpphibernate_copyable(table_t, delete);
cpphibernate_moveable(table_t, default);

cpphibernate_equality_comparable();

inline void print(std::ostream& os) const
{
using namespace ::utl;
size_t index = 0;
os << indent << '{'
<< incindent
<< indent << "\"name\": \"" << name << "\","
<< indent << "\"wrapped_dataset\": \"" << utl::type_helper<misc::decay_unwrap_t<wrapped_dataset_type>>::name() << "\""
<< indent << "\"table_id\": \"" << hana::value(table_id) << "\""
<< indent << "\"fields\": "
<< indent << '['
<< incindent;
hana::for_each(fields, [&](auto& field){
if (index++ > 0) os << ",";
field.print(os);
});
os << decindent
<< indent << ']'
<< decindent
<< indent << '}';
}
};

}

/* meta */

template<typename T>
struct is_table
: public mp::is_specialization_of<T, __impl::table_t>
{ };

template<typename... T>
struct all_are_tables
: mp::all_true<is_table<T>::value...>
{ };

/* operations */

namespace __impl
{

/* table_make_impl */

template <typename X, typename = void>
struct table_make_impl
{
template <typename... T_args>
static constexpr decltype(auto) apply(T_args&&... args)
{ static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::table::make(...)!"); }
};

template<typename T_name, typename T_wrapped_dataset, typename T_id, typename T_fields>
struct table_make_impl<mp::list<T_name, T_wrapped_dataset, T_id, T_fields>, mp::enable_if_c<
hana::is_a<hana::type_tag, T_wrapped_dataset>
&& is_fields<mp::decay_t<T_fields>>::value>>
{
static constexpr decltype(auto) apply(T_name&& name, T_wrapped_dataset&& wrapped_dataset, T_id&& id, T_fields&& fields)
{
return table_t<T_name, T_wrapped_dataset, T_id, T_fields>(
std::forward<T_name> (name),
std::forward<T_wrapped_dataset> (wrapped_dataset),
std::forward<T_id> (id),
std::forward<T_fields> (fields));
}
};

/* table_get_wrapped_dataset_impl */

struct table_get_wrapped_dataset_impl
{
template<typename T_table>
constexpr decltype(auto) operator()(T_table&& table) const
{ return table.wrapped_dataset; }
};

/* table_get_primary_key_field_impl */

/**
* @brief Helper type to build table objects.
*/
template<typename X, typename = void>
struct table_get_primary_key_field_impl
{
template <typename... T_args>
static constexpr decltype(auto) apply(T_args&&... args)
{ static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::table::get_primary_key_field(...)!"); }
};

template<typename T_table>
struct table_get_primary_key_field_impl<
mp::list<T_table>,
mp::enable_if_c<
is_table<mp::decay_t<T_table>>::value>>
{
template<size_t I>
using is_primary_key_field = decltype(hana::contains(
std::declval<T_table>().fields[hana::size_c<I>].attributes,
attribute::primary_key));

template<size_t I, size_t N, typename = void>
struct helper;

template<size_t N>
struct helper<N, N, void>
{ static_assert(N != N, "Unable to find primary key field for table!"); };

template<size_t I, size_t N>
struct helper<I, N, mp::enable_if_c<
!is_primary_key_field<I>::value>>
{
static constexpr decltype(auto) apply(T_table&& table)
{ return helper<I+1, N>::apply(std::forward<T_table>(table)); }
};

template<size_t I, size_t N>
struct helper<I, N, mp::enable_if_c<
is_primary_key_field<I>::value>>
{
static constexpr decltype(auto) apply(T_table&& table)
{ return std::forward<T_table>(table).fields[hana::size_c<I>]; }
};

static constexpr decltype(auto) apply(T_table&& table)
{
using count = mp::decay_t<decltype(hana::size(std::declval<T_table>().fields))>;
return helper<0, count::value>::apply(
std::forward<T_table>(table));
}
};
struct table_builder;

}

namespace table
{

constexpr decltype(auto) make = misc::make_generic_predicate<__impl::table_make_impl> { };
/**
* @brief Evaluates to true_t if the passed type is a table type.
*/
template<typename T>
struct is_table;

constexpr decltype(auto) get_wrapped_dataset = __impl::table_get_wrapped_dataset_impl { };
/**
* @brief Is true if the passed type is an attributes type, false otherwise.
*/
template<typename T>
constexpr bool is_table_v = is_table<T>::value;

constexpr decltype(auto) get_primary_key_field = misc::make_generic_predicate<__impl::table_get_primary_key_field_impl> { };
/**
* @brief Predicate to create an table object from the passed attributes.
*/
constexpr decltype(auto) make_table = mp::generic_predicate<__impl::table_builder> { };

}
} }

}
end_namespace_cpphibernate_schema
#include "table.inl"

+ 129
- 0
include/cpphibernate/schema/table.inl View File

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

#include "table.h"

namespace cpphibernate {
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(
name_type p_name,
wrapped_dataset_type p_wrapped_dataset,
table_id_type p_table_id,
fields_type p_fields)
: name (std::forward<name_type> (p_name))
, wrapped_dataset (std::forward<wrapped_dataset_type>(p_wrapped_dataset))
, table_id (std::forward<table_id_type> (p_table_id))
, 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 << '}';
}
};

/* table_builder */

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

template<
typename T_name,
typename T_wrapped_dataset,
typename T_table_id,
typename T_fields>
struct table_builder<
mp::list<T_name, T_wrapped_dataset, T_table_id, T_fields>,
mp::enable_if_t<
mp::is_valid_v<unwrap_t<mp::decay_t<T_wrapped_dataset>>>
&& is_fields_v<mp::decay_t<T_fields>>>>
{
using name_type = T_name;
using wrapped_dataset_type = T_wrapped_dataset;
using table_id_type = T_table_id;
using fields_type = T_fields;
using table_type = table_t<name_type, wrapped_dataset_type, table_id_type, fields_type>;

static constexpr decltype(auto) apply(
name_type&& name,
wrapped_dataset_type&& wrapped_dataset,
table_id_type&& table_id,
fields_type&& fields)
{
return table_type(
std::forward<name_type> (name),
std::forward<wrapped_dataset_type> (wrapped_dataset),
std::forward<table_id_type> (table_id),
std::forward<fields_type> (fields));
}
};

}

/* is_table */

template<typename T>
struct is_table
: public mp::is_specialization_of<T, __impl::table_t>
{ };

} }

+ 21
- 102
include/cpphibernate/schema/tables.h View File

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

#include <cpphibernate/config.h>
#include <cpphibernate/misc/general.h>
#include <cpphibernate/schema/table.h>

beg_namespace_cpphibernate_schema
{
namespace cpphibernate {
namespace schema {

namespace __impl
{

/* tables_t */

template<typename... T_table>
using tables_t = hana::tuple<T_table...>;

/* is_tables_impl */

/**
* @brief Helper type to build tables.
*/
template<typename T, typename = void>
struct is_tables_impl
: mp::c_false_t
{ };

template<typename... T>
struct is_tables_impl<tables_t<T...>, mp::enable_if<all_are_tables<T...>>>
: mp::c_true_t
{ };
struct tables_builder;

}

/* meta */

/**
* @brief Evaluates to true_t if the passed type is a tables type.
*/
template<typename T>
struct is_tables
: public __impl::is_tables_impl<T>
{ };

/* operations */

namespace __impl
{

/* tables_make_impl */

template <typename X, typename = void>
struct tables_make_impl
{
template <typename... T_args>
static constexpr decltype(auto) apply(T_args&&... args)
{ static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::tables::make(...)!"); }
};

template<typename... T>
struct tables_make_impl<mp::list<T...>, mp::enable_if<all_are_tables<T...>>>
{
template <typename ...T_tables>
static constexpr decltype(auto) apply(T_tables&&... tables)
{ return tables_t<T_tables...>(std::forward<T_tables>(tables)...); }
};

/* tables_find_impl */
struct is_tables;

template<typename X, typename = void>
struct tables_find_impl
{
template<typename... T_args>
static constexpr decltype(auto) apply(T_args&&... args)
{ static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::tables::find(...)!"); }
};

template<typename T_tables, typename T_wrapped_dataset>
struct tables_find_impl<
mp::list<T_tables, T_wrapped_dataset>,
mp::enable_if_c<
is_tables<mp::decay_t<T_tables>>::value>>
{
template<size_t I, size_t N, typename = void>
struct helper;

template<size_t N>
struct helper<N, N, void>
{ static_assert(N != N, "Table for given datatype does not exist!"); };

template<size_t I, size_t N>
struct helper<I, N, mp::enable_if_c<
decltype(hana::not_equal(std::declval<T_tables>()[hana::size_c<I>].wrapped_dataset, T_wrapped_dataset { }))::value>>
{
static constexpr decltype(auto) apply(T_tables&& tables)
{ return helper<I+1, N>::apply(std::forward<T_tables>(tables)); }
};

template<size_t I, size_t N>
struct helper<I, N, mp::enable_if_c<
decltype(hana::equal(std::declval<T_tables>()[hana::size_c<I>].wrapped_dataset, T_wrapped_dataset { }))::value>>
{
static constexpr decltype(auto) apply(T_tables&& tables)
{ return std::forward<T_tables>(tables)[hana::size_c<I>]; }
};

static constexpr decltype(auto) apply(T_tables&& tables, T_wrapped_dataset&&)
{
using count_type = mp::decay_t<decltype(hana::size(std::declval<T_tables>()))>;
return helper<0, count_type::value>::apply(std::forward<T_tables>(tables));
}
};

}

namespace tables
{

constexpr decltype(auto) make = misc::make_generic_predicate<__impl::tables_make_impl> { };
/**
* @brief Is true if the passed type is an tables type, false otherwise.
*/
template<typename T>
constexpr bool is_tables_v = is_tables<T>::value;

constexpr decltype(auto) find = misc::make_generic_predicate<__impl::tables_find_impl> { };
/**
* @brief Predicate to create an tables object from the passed tables.
*/
constexpr decltype(auto) make_tables = mp::generic_predicate<__impl::tables_builder> { };

}
} }

}
end_namespace_cpphibernate_schema
#include "tables.inl"

+ 63
- 0
include/cpphibernate/schema/tables.inl View File

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

#include "tables.h"

namespace cpphibernate {
namespace schema {

namespace __impl
{

/* tables_t */

template<typename... T_tables>
using tables_t = hana::basic_tuple<T_tables...>;

/* tables_builder */

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

template<typename... T>
struct tables_builder<
mp::list<T...>,
mp::enable_if_t<mp::is_true_v<
is_table_v<mp::decay_t<T>>...>>>
{
template<typename... T_args>
static constexpr decltype(auto) apply(T_args&&... args)
{
using tables_type = tables_t<T_args...>;
return tables_type(std::forward<T_args>(args)...);
}
};

/* is_tables_impl */

template<typename T, typename = void>
struct is_tables_impl
: mp::false_t
{ };

template<typename... T>
struct is_tables_impl<
tables_t<T...>,
mp::enable_if_t<mp::is_true_v<is_table_v<mp::decay_t<T>>...>>>
: mp::true_t
{ };

}

/* is_tables */

template<typename T>
struct is_tables
: public __impl::is_tables_impl<T>
{ };

} }

+ 72
- 33
include/cpphibernate/types.h View File

@@ -1,75 +1,114 @@
#pragma once

#include <string>
#include <cstddef>
#include <iostream>

#include <cpphibernate/config.h>

#include <cpputils/misc/exception.h>

beg_namespace_cpphibernate
namespace cpphibernate
{

/* string */

/**
* @brief Represents a string with an fixed length.
*/
template<size_t N>
struct string
: public std::string
{
static constexpr decltype(auto) max_size = N;

using std::string::string;
using std::string::operator=;
};

/* timestamp */

/**
* @brief Timestamp class.
*/
struct timestamp
{
uint64_t value;

/**
* @brief Default constructor.
*/
inline timestamp() = default;

inline timestamp(uint64_t v)
: value(v)
{ }
/**
* @brief Value constructor.
*/
inline timestamp(uint64_t v);

inline timestamp& operator=(const uint64_t& v)
{
value = v;
return *this;
}
/**
* @brief Value assignment constructor.
*/
inline timestamp& operator=(const uint64_t& v);

inline operator uint64_t() const
{ return value; }
/**
* @brief Impicit type conversion to base type.
*/
inline operator uint64_t() const;
};

/* uuid */

/**
* @brief A typical UUID implementation.
*/
struct uuid
: public std::array<uint8_t, 16>
{
public:
inline uuid()
: std::array<uint8_t, 16>::array({ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } })
{ }

inline uuid(const std::string& str)
: std::array<uint8_t, 16>::array({ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } })
{
if (!from_string(str, *this))
throw utl::argument_exception("str", "invalid uuid");
}

cpphibernate_copyable(uuid, default);
cpphibernate_moveable(uuid, default);

/**
* @brief Default constructor.
*/
inline uuid();

/**
* @brief Construtor to create a UUID from a string.
*
* @param[in] str String to create UUID from.
*/
inline uuid(const std::string& str);

/**
* @brief Move constructor.
*/
inline uuid(uuid&&) = default;

/**
* @brief Copy constructor.
*/
inline uuid(const uuid&) = default;

/**
* @brief Write the UUID to passed stream.
*
* @param[in] os Stream to write UUID to.
*/
void to_string(std::ostream& os) const;

/**
* @brief Write the UUID to passed stream.
*
* @param[in] os Stream to write UUID to.
*
* @return Stream passed as parameter.
*/
std::ostream& operator<<(std::ostream& os) const;

public:
/**
* @brief Create an UUID object from an string.
*
* @param[in] str String to create UUID from.
* @param[in] val Parameter to store converted object in
*
* @retval true If the convertion was successful.
* @retval false If the string could not be converted.
*/
static bool from_string(const std::string& str, uuid& val);
};

}
end_namespace_cpphibernate

#include "types.inl"

+ 38
- 0
include/cpphibernate/types.inl View File

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

#include <cppcore/misc/exception.h>

#include "types.h"

namespace cpphibernate
{

/* timestamp */

timestamp::timestamp(uint64_t v)
: value(v)
{ }

timestamp& timestamp::operator=(const uint64_t& v)
{
value = v;
return *this;
}

timestamp::operator uint64_t() const
{ return value; }

/* uuid */

uuid::uuid()
: std::array<uint8_t, 16>::array({ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } })
{ }

uuid::uuid(const std::string& str)
: std::array<uint8_t, 16>::array({ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } })
{
if (!from_string(str, *this))
throw ::cppcore::argument_exception("str", "invalid uuid");
}

}

+ 92
- 40
src/CMakeLists.txt View File

@@ -1,53 +1,105 @@
# Initialize ######################################################################################

Include ( cotire OPTIONAL )
Include ( pedantic OPTIONAL )
Include ( strip_symbols OPTIONAL )
Include ( cotire OPTIONAL RESULT_VARIABLE HAS_COTIRE )
Include ( pedantic OPTIONAL RESULT_VARIABLE HAS_PEDANTIC )
Include ( strip_symbols OPTIONAL RESULT_VARIABLE HAS_STRIP_SYMBOLS )

Include ( ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/options.cmake )
Find_Package ( Hana REQUIRED )
Find_Package ( cppmp REQUIRED )
Find_Package ( cppcore REQUIRED )

Set ( BUILD_SHARED_LIBS ${CPPHIBERNATE_BUILD_SHARED} )
Set ( CMAKE_CXX_STANDARD 17 )
Set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PEDANTIC_C_FLAGS}" )
Set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PEDANTIC_CXX_FLAGS}" )
# Object Library ##################################################################################

# Dependencies ####################################################################################
Set ( CMAKE_POSITION_INDEPENDENT_CODE ON )
Set ( CPPHIBERNATE_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../include )
File ( GLOB_RECURSE CPPHIBERNATE_HEADER_FILES ${CPPHIBERNATE_INCLUDE_DIR}/*.h )
File ( GLOB_RECURSE CPPHIBERNATE_INLINE_FILES ${CPPHIBERNATE_INCLUDE_DIR}/*.inl )
File ( GLOB_RECURSE CPPHIBERNATE_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp )
Add_Library ( cpphibernate-objects
OBJECT
${CPPHIBERNATE_HEADER_FILES}
${CPPHIBERNATE_INLINE_FILES}
${CPPHIBERNATE_SOURCE_FILES} )
Target_Include_Directories ( cpphibernate-objects
PUBLIC
$<BUILD_INTERFACE:${CPPHIBERNATE_INCLUDE_DIR}>
$<INSTALL_INTERFACE:${CPPHIBERNATE_INSTALL_DIR_INCLUDE}> )
Target_Link_Libraries ( cpphibernate-objects
PUBLIC
hana
cppmp::cppmp
cppcore::cppcore )

Find_Package ( cpputils REQUIRED )
Find_Package ( cppmariadb REQUIRED )
# Static Library ##################################################################################

# Project: cpphibernate ###############################################################################
Add_Library ( cpphibernate-static STATIC $<TARGET_OBJECTS:cpphibernate-objects> )
Set_Target_Properties ( cpphibernate-static
PROPERTIES
OUTPUT_NAME "${CPPHIBERNATE_OUTPUTNAME}"
VERSION ${CPPHIBERNATE_VERSION} )
Target_Include_Directories ( cpphibernate-static
PUBLIC
$<BUILD_INTERFACE:${CPPHIBERNATE_INCLUDE_DIR}>
$<INSTALL_INTERFACE:${CPPHIBERNATE_INSTALL_DIR_INCLUDE}> )

# Build
Project ( cpphibernate VERSION 1.0.0.0 LANGUAGES CXX )
Set ( CPPHIBERNATE_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../include )
Set ( CPPHIBERNATE_GENERATE_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated )
File ( GLOB_RECURSE SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp )
Add_Library ( cpphibernate ${SOURCE_FILES} )
Configure_File ( ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/options.h.in
${CPPHIBERNATE_GENERATE_DIR}/cpphibernate/options.h )
Target_Include_Directories ( cpphibernate
PUBLIC ${CPPHIBERNATE_INCLUDE_DIR}
${CPPHIBERNATE_GENERATE_DIR} )
Target_Link_Libraries ( cpphibernate
cpputils
cppmariadb )

# Install
If ( BUILD_SHARED_LIBS OR CPPHIBERNATE_INSTALL_DEV_FILES )
Install ( TARGETS cpphibernate DESTINATION lib )
# Shared Library ##################################################################################

Add_Library ( cpphibernate-shared SHARED $<TARGET_OBJECTS:cpphibernate-objects> )
Set_Target_Properties ( cpphibernate-shared
PROPERTIES
OUTPUT_NAME "${CPPHIBERNATE_OUTPUTNAME}"
VERSION ${CPPHIBERNATE_VERSION}
SOVERSION ${CPPHIBERNATE_VERSION_SHORT} )
Target_Include_Directories ( cpphibernate-shared
PUBLIC
$<BUILD_INTERFACE:${CPPHIBERNATE_INCLUDE_DIR}>
$<INSTALL_INTERFACE:${CPPHIBERNATE_INSTALL_DIR_INCLUDE}> )

# Optimization ####################################################################################

# pedantic
If ( HAS_PEDANTIC )
Pedantic_Apply_Flags_Target ( cpphibernate-objects ALL )
Pedantic_Apply_Flags_Target ( cpphibernate-static ALL )
Pedantic_Apply_Flags_Target ( cpphibernate-shared ALL )
EndIf ( )

# cotire
If ( HAS_COTIRE )
Cotire ( cpphibernate-objects )
Cotire ( cpphibernate-static )
Cotire ( cpphibernate-shared )
EndIf ( )

# Install #########################################################################################

# Header
If ( CPPHIBERNATE_INSTALL_HEADER )
Install ( FILES ${CPPHIBERNATE_INCLUDE_DIR}/cpphibernate.h
DESTINATION ${CPPHIBERNATE_INSTALL_DIR_INCLUDE} )
Install ( DIRECTORY ${CPPHIBERNATE_INCLUDE_DIR}/cpphibernate
DESTINATION ${CPPHIBERNATE_INSTALL_DIR_INCLUDE} )
EndIf ( )

# Static
If ( CPPHIBERNATE_INSTALL_STATIC )
Install ( TARGETS cpphibernate-static
EXPORT cpphibernate
DESTINATION ${CPPHIBERNATE_INSTALL_DIR_LIB} )
EndIf ( )

If ( CPPHIBERNATE_INSTALL_DEV_FILES )
Install ( FILES ${CPPHIBERNATE_INCLUDE_DIR}/cpphibernate.h DESTINATION include )
Install ( DIRECTORY ${CPPHIBERNATE_INCLUDE_DIR}/cpphibernate DESTINATION include )
Install ( DIRECTORY ${CPPHIBERNATE_GENERATE_DIR}/cpphibernate DESTINATION include )
# Shared
If ( CPPHIBERNATE_INSTALL_SHARED )
Install ( TARGETS cpphibernate-shared
EXPORT cpphibernate
DESTINATION ${CPPHIBERNATE_INSTALL_DIR_LIB} )
EndIf ( )

# Optimize
If ( __COTIRE_INCLUDED )
Cotire ( cpphibernate )
# Debug
If ( HAS_STRIP_SYMBOLS AND NOT CPPHIBERNATE_NO_STRIP )
Strip_Symbols ( cpphibernate-shared CPPHIBERNATE_DBG_FILE )
If ( CPPHIBERNATE_INSTALL_DEBUG )
Install ( FILES ${CPPHIBERNATE_DBG_FILE}
DESTINATION ${CPPHIBERNATE_INSTALL_DIR_LIB} )
EndIf ( )
EndIf ( )
If ( __STRIP_SYMBOLS_INCLUDED AND BUILD_SHARED_LIBS )
Strip_Symbols ( cpphibernate DBG_FILE )
EndIf ()

src/cpphibernate/driver/mariadb/schema/field.cpp → src/cpphibernate/driver/mariadb/schema/field.xcpp View File


src/cpphibernate/driver/mariadb/schema/schema.cpp → src/cpphibernate/driver/mariadb/schema/schema.xcpp View File


src/cpphibernate/driver/mariadb/schema/table.cpp → src/cpphibernate/driver/mariadb/schema/table.xcpp View File


+ 39
- 27
test/CMakeLists.txt View File

@@ -1,31 +1,43 @@
# Initialize ######################################################################################

Include ( cotire OPTIONAL )
Include ( pedantic OPTIONAL )
Include ( cmake_tests OPTIONAL )

Include ( ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/options.cmake )

Set ( CMAKE_CXX_STANDARD 17 )
Set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PEDANTIC_C_FLAGS}" )
Set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PEDANTIC_CXX_FLAGS}" )

# Project: test_cpphibernate ##########################################################################

Project ( test_cpphibernate )
File ( GLOB_RECURSE SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp )
List ( FILTER SOURCE_FILES EXCLUDE REGEX "/_[A-Za-z0-9_-]*\.cpp$" )
Add_Executable ( test_cpphibernate EXCLUDE_FROM_ALL ${SOURCE_FILES} )
Target_Link_Libraries ( test_cpphibernate
cpphibernate
gmock_main
gmock
gtest
pthread )
If ( __COTIRE_INCLUDED )
Cotire ( test_cpphibernate )
Include ( cotire OPTIONAL RESULT_VARIABLE HAS_COTIRE )
Include ( pedantic OPTIONAL RESULT_VARIABLE HAS_PEDANTIC )
Include ( cmake_tests OPTIONAL RESULT_VARIABLE HAS_CMAKE_TESTS )

# Test ############################################################################################

Find_Package ( GTest )
If ( NOT "${GTest_FOUND}" )
Return ( )
EndIf ( )
If ( __CMAKE_TESTS_INCLUDED )
Add_CMake_Test ( NAME cpphibernate
TARGET test_cpphibernate )

File ( GLOB_RECURSE CPPHIBERNATE_TEST_HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h )
File ( GLOB_RECURSE CPPHIBERNATE_TEST_INLINE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.inl )
File ( GLOB_RECURSE CPPHIBERNATE_TEST_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp )

Add_Executable ( cpphibernate-test
EXCLUDE_FROM_ALL
${CPPHIBERNATE_TEST_HEADER_FILES}
${CPPHIBERNATE_TEST_INLINE_FILES}
${CPPHIBERNATE_TEST_SOURCE_FILES} )
Target_Link_Libraries ( cpphibernate-test
PUBLIC
cpphibernate-objects
GTest::Main )

# pedantic
If ( HAS_PEDANTIC )
Pedantic_Apply_Flags_Target ( cpphibernate-test ALL )
EndIf ( )

# optimization
If ( HAS_COTIRE )
Cotire ( cpphibernate-test )
EndIf ( )

# test
If ( HAS_CMAKE_TESTS )
Add_CMake_Test ( NAME cpphibernate TARGET cpphibernate-test )
Else ( )
Add_Test ( NAME cpphibernate COMMAND cpphibernate-test )
EndIf ( )

test/cpphibernate_create.cpp → test/cpphibernate/cpphibernate_create.xcpp View File


test/cpphibernate_destroy.cpp → test/cpphibernate/cpphibernate_destroy.xcpp View File


test/cpphibernate_init.cpp → test/cpphibernate/cpphibernate_init.xcpp View File


test/cpphibernate_read.cpp → test/cpphibernate/cpphibernate_read.xcpp View File


+ 20
- 0
test/cpphibernate/cpphibernate_tests.cpp View File

@@ -0,0 +1,20 @@
#include <gtest/gtest.h>

#include <cpphibernate.h>

#include "test_schema.h"

constexpr decltype(auto) x = ::cpphibernate::mp::make_getter(
[](std::string&) {
return int { };
});

using namespace ::testing;
using namespace ::cpphibernate;
using namespace ::cpphibernate::schema;

TEST(cpphibernate, getHelloWorld)
{
(void)x;
// std::cout << test_schema << std::endl;
}

test/cpphibernate_update.cpp → test/cpphibernate/cpphibernate_update.xcpp View File


test/mariadb_mock.h → test/cpphibernate/mariadb_mock.h View File


test/mariadb_mock.cpp → test/cpphibernate/mariadb_mock.xcpp View File


test/test_helper.h → test/cpphibernate/test_helper.h View File


+ 227
- 0
test/cpphibernate/test_schema.h View File

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

#include <cpphibernate.h>
#include <cppcore/conversion/enum.h>

enum class test_enum
{
test0,
test1,
test2,
test3,

first = test0,
last = test3,
};

cppcore_define_enum_value_traits(
test_enum,
{ test_enum::test0, "test0" },
{ test_enum::test1, "test1" },
{ test_enum::test2, "test2" },
{ test_enum::test3, "test3" }
);

struct test1
{
::cpphibernate::uuid id;
std::string str_data;
::cpphibernate::string<64> str64_data;

cppcore::nullable<uint32_t> u32_nullable;
std::unique_ptr<uint32_t> u32_ptr_u;
std::shared_ptr<uint32_t> u32_ptr_s;
};

struct test2
{
::cpphibernate::uuid id;
uint8_t u8_data;
int8_t i8_data;
uint16_t u16_data;
int16_t i16_data;
};

struct test3
{
::cpphibernate::uuid id;
uint32_t u32_data;
int32_t i32_data;
uint64_t u64_data;
int64_t i64_data;
};

struct base
{
::cpphibernate::uuid id;
std::string name;

virtual ~base() = default;
};

struct derived1
: public base
{
::cpphibernate::uuid derived1_id;
test1 test1_data;
test_enum enum_data;
};

struct derived2
: public base
{
::cpphibernate::uuid derived2_id;
cppcore::nullable<test2> test2_nullable;
std::unique_ptr<test2> test2_ptr_u;
std::shared_ptr<test2> test2_ptr_s;
};

struct derived3
: public derived2
{
::cpphibernate::uuid derived3_id;
std::list<test3> test3_list;
std::vector<test3> test3_vector;
};

struct dummy_id
{
int data;

inline dummy_id(int p_data = 0)
: data(p_data)
{ }
};

struct dummy_owner
{
::cpphibernate::uuid id;
std::vector<dummy_id> dummies;
};

struct double_usage_item
{
unsigned int id { 0 };
int data { 0 };

double_usage_item(int p_data = 0)
: data(p_data)
{ }
};

struct double_usage
{
int id { 0 };
std::unique_ptr<double_usage_item> single_item;
std::vector<double_usage_item> multiple_items;
};

struct double_usage_wrapper
{
int id { 0 };
std::unique_ptr<double_usage> double_usage;
};

constexpr decltype(auto) test_schema = cpphibernate_make_schema(
test,
cpphibernate_make_table_name(
tbl_test1,
test1,
1,
cpphibernate_make_id (&test1::id),
cpphibernate_make_field (test1, str_data),
cpphibernate_make_field (test1, str64_data),
cpphibernate_make_field (test1, u32_nullable),
cpphibernate_make_field (test1, u32_ptr_u),
cpphibernate_make_field (test1, u32_ptr_s)
),
cpphibernate_make_table_name(
tbl_test2,
test2,
2,
cpphibernate_make_id (&test2::id),
cpphibernate_make_field (test2, u8_data),
cpphibernate_make_field (test2, i8_data),
cpphibernate_make_field (test2, u16_data),
cpphibernate_make_field (test2, i16_data)
),
cpphibernate_make_table_name(
tbl_test3,
test3,
3,
cpphibernate_make_id (&test3::id),
cpphibernate_make_field (test3, u32_data),
cpphibernate_make_field (test3, i32_data),
cpphibernate_make_field (test3, u64_data),
cpphibernate_make_field (test3, i64_data)
),

cpphibernate_make_table_name(
tbl_base,
base,
10,
cpphibernate_make_id (&base::id),
cpphibernate_make_field (base, name)
),
cpphibernate_make_table_name(
tbl_derived1,
derived1,
11,
cpphibernate_make_id (&derived1::derived1_id),
cpphibernate_make_field (derived1, test1_data),
cpphibernate_make_field (derived1, enum_data)
),
cpphibernate_make_table_name(
tbl_derived2,
derived2,
12,
cpphibernate_make_id (&derived2::derived2_id),
cpphibernate_make_field (derived2, test2_nullable),
cpphibernate_make_field (derived2, test2_ptr_u),
cpphibernate_make_field (derived2, test2_ptr_s)
),
cpphibernate_make_table_name(
tbl_derived3,
derived3,
13,
cpphibernate_make_id (&derived3::derived3_id),
cpphibernate_make_field (derived3, test3_list),
cpphibernate_make_field (derived3, test3_vector)
),
cpphibernate_make_table_name(
tbl_dummy_id,
dummy_id,
14,
cpphibernate_make_temp_id (dummy_id, ::cpphibernate::uuid),
cpphibernate_make_field (dummy_id, data)
),
cpphibernate_make_table_name(
tbl_dummy_owner,
dummy_owner,
15,
cpphibernate_make_id (&dummy_owner::id),
cpphibernate_make_field (dummy_owner, dummies)
),
cpphibernate_make_table_name(
tbl_double_usage_item,
double_usage_item,
16,
cpphibernate_make_id (&double_usage_item::id),
cpphibernate_make_field (double_usage_item, data)
),
cpphibernate_make_table_name(
tbl_double_usage,
double_usage,
17,
cpphibernate_make_id (&double_usage::id),
cpphibernate_make_field (double_usage, single_item),
cpphibernate_make_field (double_usage, multiple_items)
),
cpphibernate_make_table_name(
tbl_double_usage_wrapper,
double_usage_wrapper,
18,
cpphibernate_make_id (&double_usage_wrapper::id),
cpphibernate_make_field (double_usage_wrapper, double_usage)
)
);

Loading…
Cancel
Save