@@ -9,7 +9,7 @@ | |||
beg_namespace_cpphibernate_driver_mariadb | |||
{ | |||
/* attributes_t */ | |||
struct attributes_t : | |||
@@ -2,6 +2,9 @@ | |||
#include <cpphibernate/misc.h> | |||
#include <cpphibernate/config.h> | |||
#include <cpphibernate/schema/field.h> | |||
#include <cpphibernate/schema/table.h> | |||
#include <cpphibernate/schema/schema.h> | |||
#include <cpphibernate/driver/mariadb/schema/field.fwd.h> | |||
#include <cpphibernate/driver/mariadb/schema/table.fwd.h> | |||
#include <cpphibernate/driver/mariadb/schema/attributes.h> | |||
@@ -40,6 +43,8 @@ beg_namespace_cpphibernate_driver_mariadb | |||
, referenced_table (nullptr) | |||
{ } | |||
virtual ~field_t() = default; | |||
void print(std::ostream& os) const; | |||
}; | |||
/* simple_field_t */ | |||
@@ -57,6 +57,8 @@ beg_namespace_cpphibernate_driver_mariadb | |||
, data_fields () | |||
{ } | |||
virtual ~table_t() = default; | |||
void print(std::ostream& os) const; | |||
}; | |||
/* table_simple_t */ | |||
@@ -2,4 +2,5 @@ | |||
#include <cpphibernate/misc/general.h> | |||
#include <cpphibernate/misc/meta.h> | |||
#include <cpphibernate/misc/print.h> | |||
#include <cpphibernate/misc/wrap.h> |
@@ -6,6 +6,7 @@ | |||
#include <cpphibernate/config.h> | |||
#include <cpputils/misc/exception.h> | |||
#include <cpputils/container/nullable.h> | |||
beg_namespace_cpphibernate_misc | |||
@@ -118,5 +119,13 @@ beg_namespace_cpphibernate_misc | |||
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,0 +1,112 @@ | |||
#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 |
@@ -6,7 +6,6 @@ | |||
#include <cpphibernate/schema/fields.h> | |||
#include <cpphibernate/schema/getter.h> | |||
#include <cpphibernate/schema/macros.h> | |||
#include <cpphibernate/schema/print.h> | |||
#include <cpphibernate/schema/schema.h> | |||
#include <cpphibernate/schema/setter.h> | |||
#include <cpphibernate/schema/table.h> |
@@ -38,6 +38,6 @@ | |||
#define cpphibernate_make_id(p_member_ptr) \ | |||
cpphibernate_make_field_name( \ | |||
"p_id", \ | |||
id, \ | |||
p_member_ptr, \ | |||
cpphibernate::schema::attribute::primary_key) |
@@ -1,19 +0,0 @@ | |||
#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) | |||
-> ::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; | |||
} | |||
} |
@@ -0,0 +1,31 @@ | |||
#include <string> | |||
#include <iostream> | |||
#include <cpputils/misc/enum.h> | |||
#include <cpputils/misc/string.h> | |||
#include <cpputils/misc/indent.h> | |||
#include <cpphibernate/misc.h> | |||
#include <cpphibernate/driver/mariadb/schema/field.h> | |||
#include <cpphibernate/driver/mariadb/schema/table.h> | |||
using namespace ::utl; | |||
using namespace ::cpphibernate::driver::mariadb_impl; | |||
void field_t::print(std::ostream& os) const | |||
{ | |||
os << indent << '{' | |||
<< incindent | |||
<< indent << "\"table_dataset_id\": " << table_dataset_id << "," | |||
<< indent << "\"value_dataset_id\": " << value_dataset_id << "," | |||
<< indent << "\"value_is_nullable\": " << (value_is_nullable ? "true" : "false") << "," | |||
<< indent << "\"value_is_container\": " << (value_is_container ? "true" : "false") << "," | |||
<< indent << "\"schema_name\": \"" << schema_name << "\"," | |||
<< indent << "\"table_name\": \"" << table_name << "\"," | |||
<< indent << "\"field_name\": \"" << field_name << "\"," | |||
<< indent << "\"attributes\": " << misc::print_container(attributes, false) << "," | |||
<< indent << "\"table\": " << (table ? std::string("\"") + table->table_name + "\"" : "null") << "," | |||
<< indent << "\"referenced_table\": " << (referenced_table ? std::string("\"") + referenced_table->table_name + "\"" : "null") | |||
<< decindent | |||
<< indent << '}'; | |||
} |
@@ -1,15 +1,112 @@ | |||
#include <string> | |||
#include <iostream> | |||
#include <cpputils/misc/enum.h> | |||
#include <cpputils/misc/string.h> | |||
#include <cpputils/misc/indent.h> | |||
#include <cpphibernate/misc.h> | |||
#include <cpphibernate/driver/mariadb/schema/schema.h> | |||
using namespace ::utl; | |||
using namespace ::cpphibernate::driver::mariadb_impl; | |||
void schema_t::update() | |||
{ | |||
// clear everything | |||
for (auto& kvp : tables) | |||
{ | |||
assert(static_cast<bool>(kvp.second)); | |||
auto& table = *kvp.second; | |||
table.primary_key_field = nullptr; | |||
table.derived_tables.clear(); | |||
table.foreign_key_fields.clear(); | |||
table.foreign_table_fields.clear(); | |||
table.foreign_table_one_fields.clear(); | |||
table.foreign_table_many_fields.clear(); | |||
table.data_fields.clear(); | |||
} | |||
// update references | |||
for (auto& kvp : tables) | |||
{ | |||
assert(static_cast<bool>(kvp.second)); | |||
auto& table = *kvp.second; | |||
// base table | |||
auto it = tables.find(table.base_dataset_id); | |||
table.base_table = (it != tables.end() | |||
? it->second.get() | |||
: nullptr); | |||
// derived tables | |||
for (auto& id : table.derived_dataset_ids) | |||
{ | |||
it = tables.find(id); | |||
if (it == tables.end()) | |||
throw misc::hibernate_exception(std::string("unable to find derived table for dataset id ") + std::to_string(id)); | |||
table.derived_tables.emplace_back(it->second.get()); | |||
} | |||
// update fields | |||
for (auto& ptr : table.fields) | |||
{ | |||
auto& field = *ptr; | |||
// table | |||
if (table.dataset_id != field.table_dataset_id) | |||
throw misc::hibernate_exception(std::string("dataset id of field '") + field.table_name + '.' + field.field_name + "' does not match!"); | |||
field.table = &table; | |||
// referenced table | |||
it = tables.find(field.value_dataset_id); | |||
auto referenced_table = (it != tables.end() | |||
? it->second.get() | |||
: nullptr); | |||
field.referenced_table = referenced_table; | |||
// is primary key field | |||
if (field.attributes.count(attribute_t::primary_key)) | |||
{ | |||
if (static_cast<bool>(table.primary_key_field)) | |||
throw misc::hibernate_exception(std::string("Table '") + table.table_name + "' can not have more then one primary key!"); | |||
table.primary_key_field = &field; | |||
} | |||
// is foreign table field | |||
else if (static_cast<bool>(referenced_table)) | |||
{ | |||
table.foreign_table_fields.emplace_back(&field); | |||
if (field.value_is_container) | |||
{ | |||
table.foreign_table_many_fields.emplace_back(&field); | |||
referenced_table->foreign_key_fields.push_back(&field); | |||
} | |||
else | |||
{ | |||
table.foreign_table_one_fields.emplace_back(&field); | |||
} | |||
} | |||
// is data field | |||
else | |||
{ | |||
table.data_fields.emplace_back(&field); | |||
} | |||
} | |||
if (!static_cast<bool>(table.primary_key_field)) | |||
throw misc::hibernate_exception(std::string("Table '") + table.table_name + "' does not have a primary key!"); | |||
} | |||
} | |||
void schema_t::print(std::ostream& os) const | |||
{ | |||
os << "fuu" << std::endl; | |||
os << indent << '{' | |||
<< incindent | |||
<< indent << "\"schema_name\": \"" << schema_name << "\"," | |||
<< indent << "\"tables\": " << misc::print_container(tables, true, [](auto& os, auto& kvp) { | |||
kvp.second->print(os); | |||
}) | |||
<< decindent | |||
<< indent << '}'; | |||
} |
@@ -0,0 +1,49 @@ | |||
#include <string> | |||
#include <iostream> | |||
#include <cpputils/misc/enum.h> | |||
#include <cpputils/misc/string.h> | |||
#include <cpputils/misc/indent.h> | |||
#include <cpphibernate/misc.h> | |||
#include <cpphibernate/driver/mariadb/schema/table.h> | |||
using namespace ::utl; | |||
using namespace ::cpphibernate::driver::mariadb_impl; | |||
void table_t::print(std::ostream& os) const | |||
{ | |||
os << indent << '{' | |||
<< incindent | |||
<< indent << "\"dataset_id\": " << dataset_id << "," | |||
<< indent << "\"base_dataset_id\": " << base_dataset_id << "," | |||
<< indent << "\"table_id\": " << table_id << "," | |||
<< indent << "\"derived_dataset_ids\": " << misc::print_container(derived_dataset_ids, false) << "," | |||
<< indent << "\"schema_name\": \"" << schema_name << "\"," | |||
<< indent << "\"table_name\": \"" << table_name << "\"," | |||
<< indent << "\"fields\":" << misc::print_container(fields, true, [](auto& os, auto& field) { | |||
field->print(os); | |||
}) << "," | |||
<< indent << "\"base_table\": " << (base_table ? std::string("\"") + base_table->table_name + "\"" : "null") << "," | |||
<< indent << "\"derived_tables\":" << misc::print_container(derived_tables, true, [](auto& os, auto& ptr){ | |||
os << indent << '"' << ptr->table_name << '"'; | |||
}) << "," | |||
<< indent << "\"primary_key_field\": " << (primary_key_field ? std::string("\"") + primary_key_field->field_name + "\"" : "null") << "," | |||
<< indent << "\"foreign_key_fields\": " << misc::print_container(foreign_key_fields, true, [](auto& os, auto& ptr){ | |||
os << indent << '"' << ptr->table_name << '.' << ptr->field_name << '"'; | |||
}) << "," | |||
<< indent << "\"foreign_table_fields\": " << misc::print_container(foreign_table_fields, true, [](auto& os, auto& ptr){ | |||
os << indent << '"' << ptr->field_name << '"'; | |||
}) << "," | |||
<< indent << "\"foreign_table_one_fields\": " << misc::print_container(foreign_table_one_fields, true, [](auto& os, auto& ptr){ | |||
os << indent << '"' << ptr->field_name << '"'; | |||
}) << "," | |||
<< indent << "\"foreign_table_many_fields\": " << misc::print_container(foreign_table_many_fields, true, [](auto& os, auto& ptr){ | |||
os << indent << '"' << ptr->field_name << '"'; | |||
}) << "," | |||
<< indent << "\"data_fields\": " << misc::print_container(data_fields, true, [](auto& os, auto& ptr){ | |||
os << indent << '"' << ptr->field_name << '"'; | |||
}) | |||
<< decindent | |||
<< indent << '}'; | |||
} |