progress on combining foreign_node_completer and relation_completer
This commit is contained in:
@@ -19,6 +19,7 @@ namespace matador::object {
|
||||
* that all foreign nodes needed by the given node
|
||||
* relations are attached in schema.
|
||||
*/
|
||||
template < typename NodeType >
|
||||
class foreign_node_completer final {
|
||||
private:
|
||||
using node_ptr = std::shared_ptr<repository_node>;
|
||||
@@ -27,9 +28,9 @@ public:
|
||||
template<class Type>
|
||||
static void complete(const std::shared_ptr<repository_node> &node) {
|
||||
internal::shadow_repository shadow(node->repo_);
|
||||
foreign_node_completer completer(shadow);
|
||||
foreign_node_completer<Type> completer(shadow);
|
||||
|
||||
completer.complete_node<Type>(node);
|
||||
completer.complete_node(node);
|
||||
}
|
||||
|
||||
template<class PrimaryKeyType>
|
||||
@@ -56,13 +57,14 @@ public:
|
||||
void on_has_many_to_many(const char *id, CollectionType &collection, const utils::foreign_attributes &attr);
|
||||
|
||||
private:
|
||||
explicit foreign_node_completer(internal::shadow_repository &shadow);
|
||||
explicit foreign_node_completer(internal::shadow_repository &shadow)
|
||||
: repo_(shadow)
|
||||
, log_(logger::create_logger("node_completer")) {}
|
||||
|
||||
template<typename Type>
|
||||
void complete_node(const std::shared_ptr<repository_node> &node) {
|
||||
nodes_.push(node);
|
||||
|
||||
Type obj;
|
||||
NodeType obj;
|
||||
access::process(*this, obj);
|
||||
nodes_.pop();
|
||||
}
|
||||
@@ -77,6 +79,21 @@ private:
|
||||
complete<Type>(result.value());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
void attach_relation_node(const std::string &name) {
|
||||
if (repo_.contains(typeid(Type))) {
|
||||
return;
|
||||
}
|
||||
const auto node = repository_node::make_node<Type>(repo_.repo(), "");
|
||||
if (auto result = repo_.attach_node(node)) {
|
||||
complete<Type>(result.value());
|
||||
}
|
||||
}
|
||||
private:
|
||||
template< typename Type >
|
||||
friend class foreign_node_completer;
|
||||
|
||||
private:
|
||||
std::stack<node_ptr> nodes_;
|
||||
internal::shadow_repository &repo_;
|
||||
@@ -85,29 +102,34 @@ private:
|
||||
};
|
||||
|
||||
|
||||
template < typename NodeType >
|
||||
template<class ForeignPointerType>
|
||||
void foreign_node_completer::on_belongs_to( const char* /*id*/, ForeignPointerType&, const utils::foreign_attributes& ) {
|
||||
void foreign_node_completer<NodeType>::on_belongs_to( const char* /*id*/, ForeignPointerType&, const utils::foreign_attributes& ) {
|
||||
attach_node<typename ForeignPointerType::value_type>();
|
||||
}
|
||||
|
||||
template < typename NodeType >
|
||||
template<class ForeignPointerType>
|
||||
void foreign_node_completer::on_has_one( const char*, ForeignPointerType&, const utils::foreign_attributes& ) {
|
||||
void foreign_node_completer<NodeType>::on_has_one( const char*, ForeignPointerType&, const utils::foreign_attributes& ) {
|
||||
attach_node<typename ForeignPointerType::value_type>();
|
||||
}
|
||||
|
||||
template < typename NodeType >
|
||||
template<class CollectionType>
|
||||
void foreign_node_completer::on_has_many( const char* /*id*/, CollectionType&, const char* /*join_column*/, const utils::foreign_attributes& /*attr*/, std::enable_if_t<is_object_ptr<typename CollectionType::value_type>::value>* ) {
|
||||
void foreign_node_completer<NodeType>::on_has_many( const char* /*id*/, CollectionType&, const char* /*join_column*/, const utils::foreign_attributes& /*attr*/, std::enable_if_t<is_object_ptr<typename CollectionType::value_type>::value>* ) {
|
||||
attach_node<typename CollectionType::value_type::value_type>();
|
||||
}
|
||||
|
||||
template < typename NodeType >
|
||||
template<class CollectionType>
|
||||
void foreign_node_completer::on_has_many_to_many( const char* /*id*/, CollectionType& /*collection*/, const char* /*join_column*/, const char* /*inverse_join_column*/, const utils::foreign_attributes& /*attr*/ ) {
|
||||
attach_node<typename CollectionType::value_type::value_type>(/*id*/);
|
||||
void foreign_node_completer<NodeType>::on_has_many_to_many( const char* id, CollectionType& /*collection*/, const char* /*join_column*/, const char* /*inverse_join_column*/, const utils::foreign_attributes& /*attr*/ ) {
|
||||
attach_relation_node<typename CollectionType::value_type::value_type>(id);
|
||||
}
|
||||
|
||||
template < typename NodeType >
|
||||
template<class CollectionType>
|
||||
void foreign_node_completer::on_has_many_to_many( const char* /*id*/, CollectionType& /*collection*/, const utils::foreign_attributes& /*attr*/ ) {
|
||||
attach_node<typename CollectionType::value_type::value_type>(/*id*/);
|
||||
void foreign_node_completer<NodeType>::on_has_many_to_many( const char* id, CollectionType& /*collection*/, const utils::foreign_attributes& /*attr*/ ) {
|
||||
attach_relation_node<typename CollectionType::value_type::value_type>(id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ public:
|
||||
template<class Operator>
|
||||
void process(Operator &op) {
|
||||
namespace field = matador::access;
|
||||
field::belongs_to(op, local_name_.c_str(), local_, utils::default_foreign_attributes);
|
||||
field::belongs_to(op, remote_name_.c_str(), remote_, utils::default_foreign_attributes);
|
||||
field::belongs_to(op, local_name_.c_str(), local_, utils::CascadeNoneFetchLazy);
|
||||
field::belongs_to(op, remote_name_.c_str(), remote_, utils::CascadeNoneFetchLazy);
|
||||
}
|
||||
|
||||
object_ptr<LocalType> local() const { return local_; }
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
template<class Operator>
|
||||
void process(Operator &op) {
|
||||
namespace field = matador::access;
|
||||
field::belongs_to(op, local_name_.c_str(), local_, utils::default_foreign_attributes);
|
||||
field::belongs_to(op, local_name_.c_str(), local_, utils::CascadeNoneFetchLazy);
|
||||
field::attribute(op, type_name_.c_str(), value_);
|
||||
}
|
||||
|
||||
|
||||
@@ -165,14 +165,14 @@ void relation_completer<Type>::on_has_many(const char *id, CollectionType &,
|
||||
using value_type = typename CollectionType::value_type::value_type;
|
||||
using relation_value_type = many_to_many_relation<Type, value_type>;
|
||||
|
||||
// Check if the object_ptr type is already inserted in the schema (by id)
|
||||
auto result = schema_.find_node(typeid(value_type));
|
||||
if (!result) {
|
||||
// Todo: throw internal error or attach node
|
||||
return;
|
||||
}
|
||||
const auto foreign_node = result.value();
|
||||
// has foreign node corresponding join column (join_column)
|
||||
// Check if the object_ptr type is already inserted in the schema (by id)
|
||||
auto result = schema_.find_node(typeid(value_type));
|
||||
if (!result) {
|
||||
// Todo: throw internal error or attach node
|
||||
return;
|
||||
}
|
||||
const auto foreign_node = result.value();
|
||||
// has foreign node corresponding join column (join_column)
|
||||
|
||||
if (const auto it = foreign_node->info_->find_relation_endpoint(typeid(Type)); it != foreign_node->info().endpoint_end()) {
|
||||
// corresponding belongs_to is available and was called (has_many <-> belongs_to)
|
||||
@@ -257,35 +257,35 @@ void relation_completer<Type>::on_has_many_to_many(const char *id,
|
||||
|
||||
const auto foreign_node = result.value();
|
||||
result = schema_.find_node(id);
|
||||
if (!result) {
|
||||
// Relation not found.
|
||||
auto creator = [join_column, inverse_join_column] {
|
||||
return std::make_unique<relation_value_type>(join_column, inverse_join_column);
|
||||
};
|
||||
|
||||
result = repository_node::make_relation_node<relation_value_type>(schema_.repo(), id, std::move(creator));
|
||||
if (!result) {
|
||||
// Todo: throw internal error
|
||||
return;
|
||||
}
|
||||
|
||||
auto& node = result.value();
|
||||
const auto local_endpoint = std::make_shared<relation_endpoint>(id, relation_type::HAS_MANY, node);
|
||||
const auto join_endpoint = std::make_shared<relation_endpoint>(join_column, relation_type::BELONGS_TO, nodes_.top());
|
||||
const auto inverse_join_endpoint = std::make_shared<relation_endpoint>(inverse_join_column, relation_type::BELONGS_TO, foreign_node);
|
||||
const auto foreign_endpoint = std::make_shared<relation_endpoint>(id, relation_type::HAS_MANY, node);
|
||||
// register relation endpoint in local node
|
||||
nodes_.top()->info_->register_relation_endpoint(typeid(typename CollectionType::value_type::value_type), local_endpoint);
|
||||
// register relation endpoint in foreign node
|
||||
foreign_node->info_->register_relation_endpoint(nodes_.top()->type_index(), foreign_endpoint);
|
||||
// register endpoints in relation node
|
||||
node->info_->register_relation_endpoint(nodes_.top()->type_index(), join_endpoint);
|
||||
node->info_->register_relation_endpoint(typeid(typename CollectionType::value_type::value_type), inverse_join_endpoint);
|
||||
|
||||
// link endpoints
|
||||
link_relation_endpoints(local_endpoint, join_endpoint);
|
||||
link_relation_endpoints(foreign_endpoint, inverse_join_endpoint);
|
||||
if (result) {
|
||||
return;
|
||||
}
|
||||
// Relation not found.
|
||||
auto creator = [join_column, inverse_join_column] {
|
||||
return std::make_unique<relation_value_type>(join_column, inverse_join_column);
|
||||
};
|
||||
|
||||
result = repository_node::make_relation_node<relation_value_type>(schema_.repo(), id, std::move(creator));
|
||||
if (!result) {
|
||||
// Todo: throw internal error
|
||||
return;
|
||||
}
|
||||
|
||||
auto& node = result.value();
|
||||
const auto local_endpoint = std::make_shared<relation_endpoint>(id, relation_type::HAS_MANY, node);
|
||||
const auto join_endpoint = std::make_shared<relation_endpoint>(join_column, relation_type::BELONGS_TO, nodes_.top());
|
||||
const auto inverse_join_endpoint = std::make_shared<relation_endpoint>(inverse_join_column, relation_type::BELONGS_TO, foreign_node);
|
||||
const auto foreign_endpoint = std::make_shared<relation_endpoint>(id, relation_type::HAS_MANY, node);
|
||||
// register relation endpoint in local node
|
||||
nodes_.top()->info_->register_relation_endpoint(typeid(typename CollectionType::value_type::value_type), local_endpoint);
|
||||
// register relation endpoint in foreign node
|
||||
foreign_node->info_->register_relation_endpoint(nodes_.top()->type_index(), foreign_endpoint);
|
||||
// register endpoints in relation node
|
||||
node->info_->register_relation_endpoint(nodes_.top()->type_index(), join_endpoint);
|
||||
node->info_->register_relation_endpoint(typeid(typename CollectionType::value_type::value_type), inverse_join_endpoint);
|
||||
// link endpoints
|
||||
link_relation_endpoints(local_endpoint, join_endpoint);
|
||||
link_relation_endpoints(foreign_endpoint, inverse_join_endpoint);
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
if (auto result = attach_node(node, parent); !result) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
foreign_node_completer::complete<Type>(node);
|
||||
foreign_node_completer<Type>::template complete<Type>(node);
|
||||
relation_completer<Type>::complete(node);
|
||||
} else if (!has_node(name)) {
|
||||
it->second->update_name(name);
|
||||
@@ -177,10 +177,19 @@ private:
|
||||
static void insert_node(const node_ptr &parent, const node_ptr &child);
|
||||
void remove_node(const node_ptr &node);
|
||||
|
||||
bool expecting_relation_node(const std::string &name) const;
|
||||
template<typename NodeType>
|
||||
void expect_relation_node(const std::string &name) {
|
||||
expected_relation_nodes_[name] = std::type_index(typeid(NodeType));
|
||||
}
|
||||
void remove_expected_relation_node(const std::string &name);
|
||||
|
||||
private:
|
||||
friend class internal::shadow_repository;
|
||||
friend class repository_node;
|
||||
friend class attribute_generator;
|
||||
template < typename NodeType >
|
||||
friend class foreign_node_completer;
|
||||
|
||||
std::string name_;
|
||||
std::shared_ptr<repository_node> root_;
|
||||
@@ -190,6 +199,7 @@ private:
|
||||
logger::logger log_;
|
||||
|
||||
std::unordered_map<std::type_index, attribute*> missing_references_;
|
||||
std::unordered_map<std::string, std::type_index> expected_relation_nodes_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -96,6 +96,7 @@ private:
|
||||
friend class repository;
|
||||
template<typename Type>
|
||||
friend class relation_completer;
|
||||
template < typename NodeType >
|
||||
friend class foreign_node_completer;
|
||||
friend class const_repository_node_iterator;
|
||||
|
||||
|
||||
@@ -212,15 +212,15 @@ public:
|
||||
template < class Type >
|
||||
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||
template < class Pointer >
|
||||
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {}
|
||||
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||
template < class Pointer >
|
||||
static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {}
|
||||
static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||
|
||||
template<class ContainerType>
|
||||
static void on_has_many(const char * /*id*/,
|
||||
ContainerType &/*c*/,
|
||||
const char * /*join_column*/,
|
||||
const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {}
|
||||
const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||
template<class ContainerType>
|
||||
static void on_has_many_to_many(const char * /*id*/,
|
||||
ContainerType &/*c*/,
|
||||
|
||||
@@ -34,15 +34,15 @@ public:
|
||||
template < class Type >
|
||||
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||
template < class Pointer >
|
||||
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {}
|
||||
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||
template < class Pointer >
|
||||
static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {}
|
||||
static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||
|
||||
template<class ContainerType>
|
||||
static void on_has_many(const char * /*id*/,
|
||||
ContainerType &/*c*/,
|
||||
const char * /*join_column*/,
|
||||
const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {}
|
||||
const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||
template<class ContainerType>
|
||||
static void on_has_many_to_many(const char * /*id*/,
|
||||
ContainerType &/*c*/,
|
||||
@@ -88,18 +88,18 @@ public:
|
||||
void on_attribute(const char *id, utils::value &val, const utils::field_attributes &attr = utils::null_attributes);
|
||||
|
||||
template<class Type, template < class ... > class Pointer>
|
||||
void on_belongs_to(const char *id, Pointer<Type> &x, const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {
|
||||
void on_belongs_to(const char *id, Pointer<Type> &x, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {
|
||||
fk_result_binder_.bind(*x, id, index_++, *binder_);
|
||||
}
|
||||
template<class Type, template < class ... > class Pointer>
|
||||
void on_has_one(const char *id, Pointer<Type> &x, const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {
|
||||
void on_has_one(const char *id, Pointer<Type> &x, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {
|
||||
fk_result_binder_.bind(*x, id, index_++, *binder_);
|
||||
}
|
||||
template<class ContainerType>
|
||||
static void on_has_many(const char * /*id*/,
|
||||
ContainerType &/*c*/,
|
||||
const char * /*join_column*/,
|
||||
const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {}
|
||||
const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||
template<class ContainerType>
|
||||
static void on_has_many_to_many(const char * /*id*/,
|
||||
ContainerType &/*c*/,
|
||||
|
||||
@@ -29,18 +29,18 @@ public:
|
||||
}
|
||||
|
||||
template<class Type, template < class ... > class Pointer>
|
||||
void on_belongs_to(const char * /*id*/, Pointer<Type> &x, const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {
|
||||
void on_belongs_to(const char * /*id*/, Pointer<Type> &x, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {
|
||||
pk_binder_.bind(*x, index_++, *binder_);
|
||||
}
|
||||
template<class Type, template < class ... > class Pointer>
|
||||
void on_has_one(const char * /*id*/, Pointer<Type> &x, const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {
|
||||
void on_has_one(const char * /*id*/, Pointer<Type> &x, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {
|
||||
pk_binder_.bind(*x, index_++, *binder_);
|
||||
}
|
||||
template<class ContainerType>
|
||||
static void on_has_many(const char * /*id*/,
|
||||
ContainerType &/*c*/,
|
||||
const char * /*join_column*/,
|
||||
const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {}
|
||||
const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||
template<class ContainerType>
|
||||
static void on_has_many_to_many(const char * /*id*/,
|
||||
ContainerType &/*c*/,
|
||||
|
||||
@@ -26,15 +26,15 @@ public:
|
||||
template < class Type >
|
||||
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||
template < class Pointer >
|
||||
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {}
|
||||
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||
template < class Pointer >
|
||||
static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {}
|
||||
static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||
|
||||
template<class ContainerType>
|
||||
static void on_has_many(const char * /*id*/,
|
||||
ContainerType &/*c*/,
|
||||
const char * /*join_column*/,
|
||||
const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {}
|
||||
const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||
template<class ContainerType>
|
||||
static void on_has_many_to_many(const char * /*id*/,
|
||||
ContainerType &/*c*/,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "matador/utils/fetch_type.hpp"
|
||||
#include "matador/utils/cascade_type.hpp"
|
||||
|
||||
// ReSharper disable CppNonExplicitConvertingConstructor
|
||||
namespace matador::utils {
|
||||
|
||||
class foreign_attributes
|
||||
@@ -27,7 +28,9 @@ private:
|
||||
fetch_type fetch_{fetch_type::LAZY};
|
||||
};
|
||||
|
||||
const foreign_attributes default_foreign_attributes {};
|
||||
const foreign_attributes CascadeNoneFetchLazy {};
|
||||
const foreign_attributes CascadeAllFetchLazy {cascade_type::ALL, fetch_type::LAZY};
|
||||
const foreign_attributes CascadeAllFetchEager {cascade_type::ALL, fetch_type::EAGER};
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user