Browse Source

* implemented mariadb driver print schema methods

master
bergmann 5 years ago
parent
commit
db5f7e1c97
12 changed files with 309 additions and 23 deletions
  1. +1
    -1
      include/cpphibernate/driver/mariadb/schema/attributes.h
  2. +5
    -0
      include/cpphibernate/driver/mariadb/schema/field.h
  3. +2
    -0
      include/cpphibernate/driver/mariadb/schema/table.h
  4. +1
    -0
      include/cpphibernate/misc.h
  5. +9
    -0
      include/cpphibernate/misc/meta.h
  6. +112
    -0
      include/cpphibernate/misc/print.h
  7. +0
    -1
      include/cpphibernate/schema.h
  8. +1
    -1
      include/cpphibernate/schema/macros.h
  9. +0
    -19
      include/cpphibernate/schema/print.h
  10. +31
    -0
      src/driver/mariadb/schema/field.cpp
  11. +98
    -1
      src/driver/mariadb/schema/schema.cpp
  12. +49
    -0
      src/driver/mariadb/schema/table.cpp

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

@@ -9,7 +9,7 @@

beg_namespace_cpphibernate_driver_mariadb
{
/* attributes_t */

struct attributes_t :


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

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


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

@@ -57,6 +57,8 @@ beg_namespace_cpphibernate_driver_mariadb
, data_fields ()
{ }
virtual ~table_t() = default;

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

/* table_simple_t */


+ 1
- 0
include/cpphibernate/misc.h View File

@@ -2,4 +2,5 @@

#include <cpphibernate/misc/general.h>
#include <cpphibernate/misc/meta.h>
#include <cpphibernate/misc/print.h>
#include <cpphibernate/misc/wrap.h>

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

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

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

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

+ 0
- 1
include/cpphibernate/schema.h View File

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

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

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

+ 0
- 19
include/cpphibernate/schema/print.h View File

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

}

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

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

+ 98
- 1
src/driver/mariadb/schema/schema.cpp View File

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

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

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

Loading…
Cancel
Save