progress on combining foreign_node_completer and relation_completer
This commit is contained in:
parent
98da0884f1
commit
2e354b435c
|
|
@ -27,7 +27,7 @@ struct author {
|
||||||
field::attribute( op, "date_of_birth", date_of_birth, 31 );
|
field::attribute( op, "date_of_birth", date_of_birth, 31 );
|
||||||
field::attribute( op, "year_of_birth", year_of_birth );
|
field::attribute( op, "year_of_birth", year_of_birth );
|
||||||
field::attribute( op, "distinguished", distinguished );
|
field::attribute( op, "distinguished", distinguished );
|
||||||
field::has_many( op, "books", books, "author_id", matador::utils::default_foreign_attributes );
|
field::has_many( op, "books", books, "author_id", matador::utils::CascadeNoneFetchLazy );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ struct book {
|
||||||
namespace field = matador::access;
|
namespace field = matador::access;
|
||||||
field::primary_key( op, "id", id );
|
field::primary_key( op, "id", id );
|
||||||
field::attribute( op, "title", title, 511 );
|
field::attribute( op, "title", title, 511 );
|
||||||
field::belongs_to( op, "author_id", book_author, matador::utils::default_foreign_attributes );
|
field::belongs_to( op, "author_id", book_author, matador::utils::CascadeNoneFetchLazy );
|
||||||
field::attribute( op, "published_in", published_in );
|
field::attribute( op, "published_in", published_in );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ struct book {
|
||||||
namespace field = matador::access;
|
namespace field = matador::access;
|
||||||
field::primary_key( op, "id", id );
|
field::primary_key( op, "id", id );
|
||||||
field::attribute( op, "title", title, 511 );
|
field::attribute( op, "title", title, 511 );
|
||||||
field::has_one( op, "author_id", book_author, matador::utils::default_foreign_attributes );
|
field::has_one( op, "author_id", book_author, matador::utils::CascadeNoneFetchLazy );
|
||||||
field::attribute( op, "published_in", published_in );
|
field::attribute( op, "published_in", published_in );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -89,7 +89,7 @@ struct job {
|
||||||
void process( Operator& op ) {
|
void process( Operator& op ) {
|
||||||
namespace field = matador::access;
|
namespace field = matador::access;
|
||||||
field::primary_key( op, "id", id );
|
field::primary_key( op, "id", id );
|
||||||
field::belongs_to( op, "payload", data, matador::utils::default_foreign_attributes );
|
field::belongs_to( op, "payload", data, matador::utils::CascadeNoneFetchLazy );
|
||||||
field::attribute( op, "type", type, 511 );
|
field::attribute( op, "type", type, 511 );
|
||||||
field::attribute( op, "description", description, 511 );
|
field::attribute( op, "description", description, 511 );
|
||||||
field::attribute( op, "state", state );
|
field::attribute( op, "state", state );
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ struct profile {
|
||||||
field::primary_key( op, "id", id );
|
field::primary_key( op, "id", id );
|
||||||
field::attribute( op, "first_name", first_name, 255 );
|
field::attribute( op, "first_name", first_name, 255 );
|
||||||
field::attribute( op, "last_name", last_name, 255 );
|
field::attribute( op, "last_name", last_name, 255 );
|
||||||
field::belongs_to( op, "user_id", user, matador::utils::default_foreign_attributes );
|
field::belongs_to( op, "user_id", user, matador::utils::CascadeNoneFetchLazy );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
struct user {
|
struct user {
|
||||||
|
|
@ -95,7 +95,7 @@ struct user {
|
||||||
namespace field = matador::access;
|
namespace field = matador::access;
|
||||||
field::primary_key( op, "id", id );
|
field::primary_key( op, "id", id );
|
||||||
field::attribute( op, "username", username, 255 );
|
field::attribute( op, "username", username, 255 );
|
||||||
field::has_one(op, "profile_id", profile, matador::utils::default_foreign_attributes );
|
field::has_one(op, "profile_id", profile, matador::utils::CascadeNoneFetchLazy );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -119,7 +119,7 @@ struct person_repo {
|
||||||
void process(Operator &op) {
|
void process(Operator &op) {
|
||||||
namespace field = matador::access;
|
namespace field = matador::access;
|
||||||
field::primary_key( op, "id", id );
|
field::primary_key( op, "id", id );
|
||||||
field::has_many( op, "person_list", person_list, "person_id", matador::utils::default_foreign_attributes );
|
field::has_many( op, "person_list", person_list, "person_id", matador::utils::CascadeNoneFetchLazy );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ struct IdListPayload : Payload {
|
||||||
void process( Operator& op ) {
|
void process( Operator& op ) {
|
||||||
namespace field = matador::access;
|
namespace field = matador::access;
|
||||||
field::process( op, *matador::base_class<Payload>( this ) );
|
field::process( op, *matador::base_class<Payload>( this ) );
|
||||||
field::has_many( op, "payload_ids", payload_ids, "payload_id", matador::utils::default_foreign_attributes );
|
field::has_many( op, "payload_ids", payload_ids, "payload_id", matador::utils::CascadeNoneFetchLazy );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ namespace matador::object {
|
||||||
* that all foreign nodes needed by the given node
|
* that all foreign nodes needed by the given node
|
||||||
* relations are attached in schema.
|
* relations are attached in schema.
|
||||||
*/
|
*/
|
||||||
|
template < typename NodeType >
|
||||||
class foreign_node_completer final {
|
class foreign_node_completer final {
|
||||||
private:
|
private:
|
||||||
using node_ptr = std::shared_ptr<repository_node>;
|
using node_ptr = std::shared_ptr<repository_node>;
|
||||||
|
|
@ -27,9 +28,9 @@ public:
|
||||||
template<class Type>
|
template<class Type>
|
||||||
static void complete(const std::shared_ptr<repository_node> &node) {
|
static void complete(const std::shared_ptr<repository_node> &node) {
|
||||||
internal::shadow_repository shadow(node->repo_);
|
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>
|
template<class PrimaryKeyType>
|
||||||
|
|
@ -56,13 +57,14 @@ public:
|
||||||
void on_has_many_to_many(const char *id, CollectionType &collection, const utils::foreign_attributes &attr);
|
void on_has_many_to_many(const char *id, CollectionType &collection, const utils::foreign_attributes &attr);
|
||||||
|
|
||||||
private:
|
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) {
|
void complete_node(const std::shared_ptr<repository_node> &node) {
|
||||||
nodes_.push(node);
|
nodes_.push(node);
|
||||||
|
|
||||||
Type obj;
|
NodeType obj;
|
||||||
access::process(*this, obj);
|
access::process(*this, obj);
|
||||||
nodes_.pop();
|
nodes_.pop();
|
||||||
}
|
}
|
||||||
|
|
@ -77,6 +79,21 @@ private:
|
||||||
complete<Type>(result.value());
|
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:
|
private:
|
||||||
std::stack<node_ptr> nodes_;
|
std::stack<node_ptr> nodes_;
|
||||||
internal::shadow_repository &repo_;
|
internal::shadow_repository &repo_;
|
||||||
|
|
@ -85,29 +102,34 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template < typename NodeType >
|
||||||
template<class ForeignPointerType>
|
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>();
|
attach_node<typename ForeignPointerType::value_type>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < typename NodeType >
|
||||||
template<class ForeignPointerType>
|
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>();
|
attach_node<typename ForeignPointerType::value_type>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < typename NodeType >
|
||||||
template<class CollectionType>
|
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>();
|
attach_node<typename CollectionType::value_type::value_type>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < typename NodeType >
|
||||||
template<class CollectionType>
|
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*/ ) {
|
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_node<typename CollectionType::value_type::value_type>(/*id*/);
|
attach_relation_node<typename CollectionType::value_type::value_type>(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < typename NodeType >
|
||||||
template<class CollectionType>
|
template<class CollectionType>
|
||||||
void foreign_node_completer::on_has_many_to_many( const char* /*id*/, CollectionType& /*collection*/, const utils::foreign_attributes& /*attr*/ ) {
|
void foreign_node_completer<NodeType>::on_has_many_to_many( const char* id, CollectionType& /*collection*/, const utils::foreign_attributes& /*attr*/ ) {
|
||||||
attach_node<typename CollectionType::value_type::value_type>(/*id*/);
|
attach_relation_node<typename CollectionType::value_type::value_type>(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,8 @@ public:
|
||||||
template<class Operator>
|
template<class Operator>
|
||||||
void process(Operator &op) {
|
void process(Operator &op) {
|
||||||
namespace field = matador::access;
|
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::belongs_to(op, remote_name_.c_str(), remote_, utils::default_foreign_attributes);
|
field::belongs_to(op, remote_name_.c_str(), remote_, utils::CascadeNoneFetchLazy);
|
||||||
}
|
}
|
||||||
|
|
||||||
object_ptr<LocalType> local() const { return local_; }
|
object_ptr<LocalType> local() const { return local_; }
|
||||||
|
|
@ -44,7 +44,7 @@ public:
|
||||||
template<class Operator>
|
template<class Operator>
|
||||||
void process(Operator &op) {
|
void process(Operator &op) {
|
||||||
namespace field = matador::access;
|
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_);
|
field::attribute(op, type_name_.c_str(), value_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -257,7 +257,9 @@ void relation_completer<Type>::on_has_many_to_many(const char *id,
|
||||||
|
|
||||||
const auto foreign_node = result.value();
|
const auto foreign_node = result.value();
|
||||||
result = schema_.find_node(id);
|
result = schema_.find_node(id);
|
||||||
if (!result) {
|
if (result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Relation not found.
|
// Relation not found.
|
||||||
auto creator = [join_column, inverse_join_column] {
|
auto creator = [join_column, inverse_join_column] {
|
||||||
return std::make_unique<relation_value_type>(join_column, inverse_join_column);
|
return std::make_unique<relation_value_type>(join_column, inverse_join_column);
|
||||||
|
|
@ -281,11 +283,9 @@ void relation_completer<Type>::on_has_many_to_many(const char *id,
|
||||||
// register endpoints in relation node
|
// register endpoints in relation node
|
||||||
node->info_->register_relation_endpoint(nodes_.top()->type_index(), join_endpoint);
|
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);
|
node->info_->register_relation_endpoint(typeid(typename CollectionType::value_type::value_type), inverse_join_endpoint);
|
||||||
|
|
||||||
// link endpoints
|
// link endpoints
|
||||||
link_relation_endpoints(local_endpoint, join_endpoint);
|
link_relation_endpoints(local_endpoint, join_endpoint);
|
||||||
link_relation_endpoints(foreign_endpoint, inverse_join_endpoint);
|
link_relation_endpoints(foreign_endpoint, inverse_join_endpoint);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ public:
|
||||||
if (auto result = attach_node(node, parent); !result) {
|
if (auto result = attach_node(node, parent); !result) {
|
||||||
return utils::failure(result.err());
|
return utils::failure(result.err());
|
||||||
}
|
}
|
||||||
foreign_node_completer::complete<Type>(node);
|
foreign_node_completer<Type>::template complete<Type>(node);
|
||||||
relation_completer<Type>::complete(node);
|
relation_completer<Type>::complete(node);
|
||||||
} else if (!has_node(name)) {
|
} else if (!has_node(name)) {
|
||||||
it->second->update_name(name);
|
it->second->update_name(name);
|
||||||
|
|
@ -177,10 +177,19 @@ private:
|
||||||
static void insert_node(const node_ptr &parent, const node_ptr &child);
|
static void insert_node(const node_ptr &parent, const node_ptr &child);
|
||||||
void remove_node(const node_ptr &node);
|
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:
|
private:
|
||||||
friend class internal::shadow_repository;
|
friend class internal::shadow_repository;
|
||||||
friend class repository_node;
|
friend class repository_node;
|
||||||
friend class attribute_generator;
|
friend class attribute_generator;
|
||||||
|
template < typename NodeType >
|
||||||
|
friend class foreign_node_completer;
|
||||||
|
|
||||||
std::string name_;
|
std::string name_;
|
||||||
std::shared_ptr<repository_node> root_;
|
std::shared_ptr<repository_node> root_;
|
||||||
|
|
@ -190,6 +199,7 @@ private:
|
||||||
logger::logger log_;
|
logger::logger log_;
|
||||||
|
|
||||||
std::unordered_map<std::type_index, attribute*> missing_references_;
|
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;
|
friend class repository;
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
friend class relation_completer;
|
friend class relation_completer;
|
||||||
|
template < typename NodeType >
|
||||||
friend class foreign_node_completer;
|
friend class foreign_node_completer;
|
||||||
friend class const_repository_node_iterator;
|
friend class const_repository_node_iterator;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -212,15 +212,15 @@ public:
|
||||||
template < class Type >
|
template < class Type >
|
||||||
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
template < class Pointer >
|
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 >
|
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>
|
template<class ContainerType>
|
||||||
static void on_has_many(const char * /*id*/,
|
static void on_has_many(const char * /*id*/,
|
||||||
ContainerType &/*c*/,
|
ContainerType &/*c*/,
|
||||||
const char * /*join_column*/,
|
const char * /*join_column*/,
|
||||||
const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {}
|
const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many_to_many(const char * /*id*/,
|
static void on_has_many_to_many(const char * /*id*/,
|
||||||
ContainerType &/*c*/,
|
ContainerType &/*c*/,
|
||||||
|
|
|
||||||
|
|
@ -34,15 +34,15 @@ public:
|
||||||
template < class Type >
|
template < class Type >
|
||||||
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
template < class Pointer >
|
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 >
|
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>
|
template<class ContainerType>
|
||||||
static void on_has_many(const char * /*id*/,
|
static void on_has_many(const char * /*id*/,
|
||||||
ContainerType &/*c*/,
|
ContainerType &/*c*/,
|
||||||
const char * /*join_column*/,
|
const char * /*join_column*/,
|
||||||
const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {}
|
const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many_to_many(const char * /*id*/,
|
static void on_has_many_to_many(const char * /*id*/,
|
||||||
ContainerType &/*c*/,
|
ContainerType &/*c*/,
|
||||||
|
|
@ -88,18 +88,18 @@ public:
|
||||||
void on_attribute(const char *id, utils::value &val, const utils::field_attributes &attr = utils::null_attributes);
|
void on_attribute(const char *id, utils::value &val, const utils::field_attributes &attr = utils::null_attributes);
|
||||||
|
|
||||||
template<class Type, template < class ... > class Pointer>
|
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_);
|
fk_result_binder_.bind(*x, id, index_++, *binder_);
|
||||||
}
|
}
|
||||||
template<class Type, template < class ... > class Pointer>
|
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_);
|
fk_result_binder_.bind(*x, id, index_++, *binder_);
|
||||||
}
|
}
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many(const char * /*id*/,
|
static void on_has_many(const char * /*id*/,
|
||||||
ContainerType &/*c*/,
|
ContainerType &/*c*/,
|
||||||
const char * /*join_column*/,
|
const char * /*join_column*/,
|
||||||
const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {}
|
const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many_to_many(const char * /*id*/,
|
static void on_has_many_to_many(const char * /*id*/,
|
||||||
ContainerType &/*c*/,
|
ContainerType &/*c*/,
|
||||||
|
|
|
||||||
|
|
@ -29,18 +29,18 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Type, template < class ... > class Pointer>
|
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_);
|
pk_binder_.bind(*x, index_++, *binder_);
|
||||||
}
|
}
|
||||||
template<class Type, template < class ... > class Pointer>
|
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_);
|
pk_binder_.bind(*x, index_++, *binder_);
|
||||||
}
|
}
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many(const char * /*id*/,
|
static void on_has_many(const char * /*id*/,
|
||||||
ContainerType &/*c*/,
|
ContainerType &/*c*/,
|
||||||
const char * /*join_column*/,
|
const char * /*join_column*/,
|
||||||
const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {}
|
const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many_to_many(const char * /*id*/,
|
static void on_has_many_to_many(const char * /*id*/,
|
||||||
ContainerType &/*c*/,
|
ContainerType &/*c*/,
|
||||||
|
|
|
||||||
|
|
@ -26,15 +26,15 @@ public:
|
||||||
template < class Type >
|
template < class Type >
|
||||||
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
template < class Pointer >
|
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 >
|
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>
|
template<class ContainerType>
|
||||||
static void on_has_many(const char * /*id*/,
|
static void on_has_many(const char * /*id*/,
|
||||||
ContainerType &/*c*/,
|
ContainerType &/*c*/,
|
||||||
const char * /*join_column*/,
|
const char * /*join_column*/,
|
||||||
const utils::foreign_attributes &/*attr*/ = utils::default_foreign_attributes) {}
|
const utils::foreign_attributes &/*attr*/ = utils::CascadeNoneFetchLazy) {}
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
static void on_has_many_to_many(const char * /*id*/,
|
static void on_has_many_to_many(const char * /*id*/,
|
||||||
ContainerType &/*c*/,
|
ContainerType &/*c*/,
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include "matador/utils/fetch_type.hpp"
|
#include "matador/utils/fetch_type.hpp"
|
||||||
#include "matador/utils/cascade_type.hpp"
|
#include "matador/utils/cascade_type.hpp"
|
||||||
|
|
||||||
|
// ReSharper disable CppNonExplicitConvertingConstructor
|
||||||
namespace matador::utils {
|
namespace matador::utils {
|
||||||
|
|
||||||
class foreign_attributes
|
class foreign_attributes
|
||||||
|
|
@ -27,7 +28,9 @@ private:
|
||||||
fetch_type fetch_{fetch_type::LAZY};
|
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};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
#include "matador/object/foreign_node_completer.hpp"
|
|
||||||
|
|
||||||
#include "matador/object/repository.hpp"
|
|
||||||
|
|
||||||
#include "matador/logger/logger.hpp"
|
|
||||||
|
|
||||||
namespace matador::object {
|
|
||||||
foreign_node_completer::foreign_node_completer(internal::shadow_repository &shadow)
|
|
||||||
: repo_(shadow)
|
|
||||||
, log_(logger::create_logger("node_completer")) {}
|
|
||||||
}
|
|
||||||
|
|
@ -201,4 +201,12 @@ bool repository::has_node(const std::type_index &index) const {
|
||||||
bool repository::has_node(const node_ptr& node) const {
|
bool repository::has_node(const node_ptr& node) const {
|
||||||
return nodes_by_name_.count(node->name()) > 0 || nodes_by_type_.count(node->type_index()) > 0;
|
return nodes_by_name_.count(node->name()) > 0 || nodes_by_type_.count(node->type_index()) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool repository::expecting_relation_node( const std::string& name ) const {
|
||||||
|
return expected_relation_nodes_.count(name) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void repository::remove_expected_relation_node( const std::string& name ) {
|
||||||
|
expected_relation_nodes_.erase(name);
|
||||||
|
}
|
||||||
} // namespace matador::object
|
} // namespace matador::object
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,12 @@
|
||||||
#include "matador/orm/schema.hpp"
|
#include "matador/orm/schema.hpp"
|
||||||
|
|
||||||
#include "../models/department.hpp"
|
#include "../models/department.hpp"
|
||||||
|
#include "../models/recipe.hpp"
|
||||||
|
|
||||||
using namespace matador;
|
using namespace matador;
|
||||||
using namespace matador::test;
|
using namespace matador::test;
|
||||||
|
|
||||||
TEST_CASE_METHOD(SchemaFixture, "Test schema one-two-many", "[schema]") {
|
TEST_CASE_METHOD(SchemaFixture, "Test schema one-two-many", "[schema][one-to-many]") {
|
||||||
using namespace matador::test;
|
using namespace matador::test;
|
||||||
orm::schema repo(pool/*, "NoopSchema"*/);
|
orm::schema repo(pool/*, "NoopSchema"*/);
|
||||||
|
|
||||||
|
|
@ -34,3 +35,26 @@ TEST_CASE_METHOD(SchemaFixture, "Test schema one-two-many", "[schema]") {
|
||||||
REQUIRE(exists_result.is_ok());
|
REQUIRE(exists_result.is_ok());
|
||||||
REQUIRE(!exists_result.value());
|
REQUIRE(!exists_result.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(SchemaFixture, "Test schema many-to-many", "[schema][many-to-many]") {
|
||||||
|
using namespace matador::test;
|
||||||
|
orm::schema repo(pool/*, "NoopSchema"*/);
|
||||||
|
|
||||||
|
auto result = repo.attach<recipe>("recipes")
|
||||||
|
.and_then( [&repo] { return repo.attach<ingredient>("ingredients"); } );
|
||||||
|
REQUIRE(result);
|
||||||
|
|
||||||
|
result = repo.create();
|
||||||
|
REQUIRE(result);
|
||||||
|
|
||||||
|
auto exists_result = repo.table_exists("recipes");
|
||||||
|
REQUIRE(exists_result.is_ok());
|
||||||
|
REQUIRE(exists_result.value());
|
||||||
|
|
||||||
|
result = repo.drop();
|
||||||
|
REQUIRE(result);
|
||||||
|
|
||||||
|
exists_result = repo.table_exists("recipes");
|
||||||
|
REQUIRE(exists_result.is_ok());
|
||||||
|
REQUIRE(!exists_result.value());
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include "matador/object/repository.hpp"
|
#include "matador/object/repository.hpp"
|
||||||
|
|
||||||
#include "../../models/department.hpp"
|
#include "../../models/department.hpp"
|
||||||
|
#include "../../models/recipe.hpp"
|
||||||
|
|
||||||
struct node {};
|
struct node {};
|
||||||
|
|
||||||
|
|
@ -30,50 +31,51 @@ struct names {
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_CASE("Test empty prototype tree", "[schema_node][empty]") {
|
TEST_CASE("Test empty prototype tree", "[schema_node][empty]") {
|
||||||
const object::repository tree;
|
const object::repository repo;
|
||||||
|
|
||||||
REQUIRE( tree.empty() );
|
REQUIRE( repo.empty() );
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Test add type to prototype tree", "[schema_node][add]") {
|
TEST_CASE("Test add type to prototype tree", "[schema_node][add]") {
|
||||||
object::repository tree;
|
object::repository repo;
|
||||||
|
|
||||||
REQUIRE( tree.empty() );
|
REQUIRE( repo.empty() );
|
||||||
|
|
||||||
auto res = tree.attach<person>("person");
|
auto res = repo.attach<person>("person");
|
||||||
REQUIRE( res.is_ok() );
|
REQUIRE( res.is_ok() );
|
||||||
res = tree.attach<student, person>("student");
|
res = repo.attach<student, person>("student");
|
||||||
REQUIRE( res.is_ok() );
|
REQUIRE( res.is_ok() );
|
||||||
res = tree.attach<teacher, person>("teacher");
|
res = repo.attach<teacher, person>("teacher");
|
||||||
REQUIRE( res.is_ok() );
|
REQUIRE( res.is_ok() );
|
||||||
|
|
||||||
REQUIRE( !tree.empty() );
|
REQUIRE( !repo.empty() );
|
||||||
REQUIRE( tree.size() == 3 );
|
REQUIRE( repo.size() == 3 );
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Test next and previous of schema node", "[schema_node][next][previous]") {
|
TEST_CASE("Test next and previous of schema node", "[schema_node][next][previous]") {
|
||||||
object::repository tree;
|
object::repository repo;
|
||||||
|
|
||||||
REQUIRE( tree.empty() );
|
REQUIRE( repo.empty() );
|
||||||
|
|
||||||
auto res = tree.attach<person>("person");
|
auto res = repo.attach<person>("person");
|
||||||
REQUIRE( res.is_ok() );
|
REQUIRE( res.is_ok() );
|
||||||
|
|
||||||
REQUIRE( tree.size() == 1 );
|
REQUIRE( repo.size() == 1 );
|
||||||
|
|
||||||
auto it = tree.begin();
|
auto it = repo.begin();
|
||||||
REQUIRE( it->name() == "person" );
|
REQUIRE( it->name() == "person" );
|
||||||
REQUIRE( (--it)->name() == "person" );
|
REQUIRE( (--it)->name() == "person" );
|
||||||
REQUIRE( ++it == tree.end() );
|
REQUIRE( ++it == repo.end() );
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Test automatic creating of a relation table with foreign key", "[schema][relation_table][foreign_key]") {
|
TEST_CASE("Test automatic creating of a relation table with foreign key", "[schema][relation_table][foreign_key]") {
|
||||||
object::repository tree;
|
object::repository repo;
|
||||||
|
|
||||||
REQUIRE( tree.empty() );
|
REQUIRE( repo.empty() );
|
||||||
|
|
||||||
auto res = tree.attach<test::department>("department");
|
auto res = repo.attach<test::department>("department");
|
||||||
REQUIRE( res.is_ok() );
|
REQUIRE( res.is_ok() );
|
||||||
|
REQUIRE(repo.size() == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Test automatic creating of a relation table with values", "[schema][relation_table][values]") {
|
TEST_CASE("Test automatic creating of a relation table with values", "[schema][relation_table][values]") {
|
||||||
|
|
@ -84,3 +86,31 @@ TEST_CASE("Test automatic creating of a relation table with values", "[schema][r
|
||||||
auto res = repo.attach<names>("names");
|
auto res = repo.attach<names>("names");
|
||||||
REQUIRE( res.is_ok() );
|
REQUIRE( res.is_ok() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Test one to many", "[relation][one-to-many]") {
|
||||||
|
object::repository repo;
|
||||||
|
|
||||||
|
REQUIRE( repo.empty() );
|
||||||
|
|
||||||
|
auto res = repo.attach<test::department>("departments")
|
||||||
|
.and_then( [&repo] { return repo.attach<test::employee>("employees"); } );
|
||||||
|
REQUIRE( res.is_ok() );
|
||||||
|
REQUIRE(repo.size() == 2);
|
||||||
|
REQUIRE(repo.contains("departments"));
|
||||||
|
REQUIRE(repo.contains("employees"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Test many to many relation", "[relation][many-to-many]") {
|
||||||
|
object::repository repo;
|
||||||
|
|
||||||
|
REQUIRE(repo.empty());
|
||||||
|
|
||||||
|
auto result = repo.attach<test::recipe>("recipes")
|
||||||
|
.and_then( [&repo] { return repo.attach<test::ingredient>("ingredients"); } );
|
||||||
|
REQUIRE(result);
|
||||||
|
|
||||||
|
REQUIRE(repo.size() == 3);
|
||||||
|
REQUIRE(repo.contains("ingredients"));
|
||||||
|
REQUIRE(repo.contains("recipes"));
|
||||||
|
REQUIRE(repo.contains("recipe_ingredients"));
|
||||||
|
}
|
||||||
|
|
@ -21,8 +21,8 @@ struct order_details
|
||||||
void process(Operator &op) {
|
void process(Operator &op) {
|
||||||
namespace field = matador::access;
|
namespace field = matador::access;
|
||||||
field::primary_key(op, "order_details_id", order_details_id);
|
field::primary_key(op, "order_details_id", order_details_id);
|
||||||
field::belongs_to(op, "order_id", order_, utils::default_foreign_attributes);
|
field::belongs_to(op, "order_id", order_, utils::CascadeNoneFetchLazy);
|
||||||
field::has_one(op, "product_id", product_, utils::default_foreign_attributes);
|
field::has_one(op, "product_id", product_, utils::CascadeNoneFetchLazy);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue