215 lines
5.7 KiB
C++
215 lines
5.7 KiB
C++
#include "matador/object/repository.hpp"
|
|
|
|
#include "matador/logger/log_manager.hpp"
|
|
|
|
#include "author.hpp"
|
|
#include "book.hpp"
|
|
#include "recipe.hpp"
|
|
|
|
#include <iostream>
|
|
|
|
/*
|
|
* node author
|
|
*
|
|
* relation_endpoints
|
|
* 1. - field_name "books"
|
|
* - type "has_many"
|
|
* - node <author>
|
|
* - foreign endpoint (1) "author"
|
|
*
|
|
* node book
|
|
* 2. - field_name "author_id"
|
|
* - type "belongs_to"
|
|
* - node <book>
|
|
* - foreign endpoint (2) "books"
|
|
*
|
|
* Attach process:
|
|
*
|
|
* attach<author>
|
|
* - relation completer detects "has_many<book>"
|
|
* - has_many<book> doesn't find <book> (not yet attached)
|
|
* - create endpoint (1) without foreign endpoint
|
|
* - create node many_to_many_relation<author, book>("author_id", "id")
|
|
* - 3. create endpoint
|
|
* - field name "author_id"
|
|
* - type "belongs_to"
|
|
* - node <many_to_many_relation<author, book>>
|
|
* - foreign endpoint (1) "author
|
|
* - set foreign endpoint of (1) to endpoint (3)
|
|
* - register endpoint in authors node by type book
|
|
* - attach (internal) node<many_to_many_relation<author, book>>
|
|
*
|
|
* attach<book>
|
|
* - relation completer detects "belongs_to<author>"
|
|
* - belongs_to<author> finds <book>
|
|
* - try to find relation endpoint of type book in authors node
|
|
* - if endpoint was found
|
|
* - validate node in endpoint
|
|
* - if node is of type many_to_many_relation
|
|
* - detach node of endpoint
|
|
* - update node in endpoint to <book>
|
|
* - else
|
|
* - create endpoint <book> (1)
|
|
* - create endpoint <author> (2)
|
|
* - set foreign endpoint of (1) to endpoint (2)
|
|
* - set foreign endpoint of (2) to endpoint (1)
|
|
* - check relation endpoints...
|
|
*/
|
|
|
|
namespace demo {
|
|
struct names {
|
|
unsigned int id{};
|
|
std::vector<std::string> names_list;
|
|
|
|
template<typename Operator>
|
|
void process(Operator &op) {
|
|
namespace field = matador::access;
|
|
field::primary_key( op, "id", id );
|
|
field::has_many(op, "name_list", names_list, "names_id", matador::utils::fetch_type::EAGER);
|
|
}
|
|
};
|
|
|
|
struct user;
|
|
struct profile {
|
|
unsigned int id{};
|
|
std::string first_name;
|
|
std::string last_name;
|
|
matador::object::object_ptr<demo::user> user;
|
|
|
|
template<typename Operator>
|
|
void process(Operator &op) {
|
|
namespace field = matador::access;
|
|
field::primary_key( op, "id", id );
|
|
field::attribute( op, "first_name", first_name, 255 );
|
|
field::attribute( op, "last_name", last_name, 255 );
|
|
field::belongs_to( op, "user_id", user, matador::utils::CascadeNoneFetchLazy );
|
|
}
|
|
};
|
|
struct user {
|
|
unsigned int id{};
|
|
std::string username;
|
|
matador::object::object_ptr<demo::profile> profile;
|
|
|
|
template<typename Operator>
|
|
void process(Operator &op) {
|
|
namespace field = matador::access;
|
|
field::primary_key( op, "id", id );
|
|
field::attribute( op, "username", username, 255 );
|
|
field::has_one(op, "profile_id", profile, matador::utils::CascadeNoneFetchLazy );
|
|
}
|
|
};
|
|
|
|
struct person {
|
|
unsigned int id{};
|
|
std::string name;
|
|
|
|
template<typename Operator>
|
|
void process(Operator &op) {
|
|
namespace field = matador::access;
|
|
field::primary_key( op, "id", id );
|
|
field::attribute( op, "name", name, 255 );
|
|
}
|
|
};
|
|
|
|
struct person_repo {
|
|
unsigned int id{};
|
|
matador::object::collection<matador::object::object_ptr<person>> person_list;
|
|
|
|
template<typename Operator>
|
|
void process(Operator &op) {
|
|
namespace field = matador::access;
|
|
field::primary_key( op, "id", id );
|
|
field::has_many( op, "person_list", person_list, "person_id", matador::utils::CascadeNoneFetchLazy );
|
|
}
|
|
};
|
|
}
|
|
|
|
using namespace demo;
|
|
using namespace matador;
|
|
|
|
int main() {
|
|
// logger::default_min_log_level(logger::log_level::LVL_DEBUG);
|
|
// logger::add_log_sink(logger::create_stdout_sink());
|
|
|
|
{
|
|
// has_many with builtin-type
|
|
object::repository repo;
|
|
|
|
auto result = repo.attach<names>("names");
|
|
|
|
repo.dump(std::cout);
|
|
}
|
|
{
|
|
// has_many with foreign without belongs_to
|
|
object::repository repo;
|
|
|
|
auto result = repo.attach<person_repo>("person_repo")
|
|
.and_then([&repo] { return repo.attach<person>("persons"); });
|
|
|
|
repo.dump(std::cout);
|
|
}
|
|
{
|
|
// has_many with foreign without belongs_to
|
|
object::repository repo;
|
|
|
|
auto result = repo.attach<person>("persons")
|
|
.and_then([&repo] { return repo.attach<person_repo>("person_repo"); });
|
|
|
|
repo.dump(std::cout);
|
|
}
|
|
{
|
|
// has_many to belongs_to
|
|
object::repository repo;
|
|
|
|
auto result = repo.attach<author>("authors")
|
|
.and_then([&repo] { return repo.attach<book>("books"); });
|
|
|
|
repo.dump(std::cout);
|
|
}
|
|
{
|
|
// belongs_to to has_many
|
|
object::repository repo;
|
|
|
|
auto result = repo.attach<book>("books")
|
|
.and_then([&repo] { return repo.attach<author>("authors"); });
|
|
|
|
repo.dump(std::cout);
|
|
}
|
|
{
|
|
// has_many_to_many (with join columns first)
|
|
object::repository repo;
|
|
|
|
auto result = repo.attach<demo::ingredient>("ingredients")
|
|
.and_then([&repo] { return repo.attach<recipe>("recipes"); });
|
|
|
|
repo.dump(std::cout);
|
|
}
|
|
{
|
|
// has_many_to_many (with join columns last)
|
|
object::repository repo;
|
|
|
|
auto result = repo.attach<demo::recipe>("recipes")
|
|
.and_then([&repo] { return repo.attach<ingredient>("ingredients"); });
|
|
|
|
repo.dump(std::cout);
|
|
}
|
|
{
|
|
// belongs_to to has_one
|
|
object::repository repo;
|
|
|
|
auto result = repo.attach<profile>("profiles")
|
|
.and_then([&repo] { return repo.attach<user>("users"); });
|
|
|
|
repo.dump(std::cout);
|
|
}
|
|
{
|
|
// has_one to belongs_to
|
|
object::repository repo;
|
|
|
|
auto result = repo.attach<user>("users")
|
|
.and_then([&repo] { return repo.attach<profile>("profiles"); });
|
|
|
|
repo.dump(std::cout);
|
|
}
|
|
}
|