finished relation completer

This commit is contained in:
Sascha Kühl
2025-07-07 15:50:09 +02:00
parent c974628bee
commit e85543719c
17 changed files with 396 additions and 142 deletions
+8
View File
@@ -13,3 +13,11 @@ target_link_libraries(sandbox PRIVATE
${CMAKE_DL_LIBS}
${SQLite3_LIBRARIES}
)
add_executable(work work.cpp)
target_link_libraries(work PRIVATE
matador-core
matador-orm
${CMAKE_DL_LIBS}
${SQLite3_LIBRARIES}
)
+61
View File
@@ -0,0 +1,61 @@
#ifndef QUERY_RECIPE_HPP
#define QUERY_RECIPE_HPP
#include "matador/utils/access.hpp"
#include "matador/utils/foreign_attributes.hpp"
#include "matador/object/collection.hpp"
#include "matador/object/object_ptr.hpp"
#include "matador/object/many_to_many_relation.hpp"
#include <string>
namespace demo {
struct recipe;
struct ingredient
{
unsigned int id{};
std::string name;
matador::object::collection<matador::object::object_ptr<recipe>> recipes{};
ingredient()= default;
ingredient(const unsigned int id, std::string name)
: id(id), name(std::move(name)) {}
template<class Operator>
void process(Operator &op) {
namespace field = matador::access;
field::primary_key(op, "id", id);
field::attribute(op, "name", name, 255);
field::has_many_to_many(op, "recipe_ingredients", recipes, "ingredient_id", "recipe_id", matador::utils::fetch_type::EAGER);
}
};
struct recipe
{
unsigned int id{};
std::string name;
matador::object::collection<matador::object::object_ptr<ingredient>> ingredients{};
recipe()= default;
recipe(const unsigned int id, std::string name)
: id(id), name(std::move(name)) {}
template<class Operator>
void process(Operator &op) {
namespace field = matador::access;
field::primary_key(op, "id", id);
field::attribute(op, "name", name, 255);
field::has_many_to_many(op, "recipe_ingredients", ingredients, matador::utils::fetch_type::LAZY);
}
};
class recipe_ingredient : public matador::object::many_to_many_relation<recipe, ingredient> {
public:
recipe_ingredient() : many_to_many_relation("recipe_id", "ingredient_id") {}
};
}
#endif //QUERY_RECIPE_HPP
+92
View File
@@ -4,6 +4,7 @@
#include "author.hpp"
#include "book.hpp"
#include "recipe.hpp"
#include <iostream>
@@ -54,6 +55,51 @@
* - 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<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::default_foreign_attributes );
}
};
struct user {
unsigned int id{};
std::string username;
matador::object::object_ptr<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::default_foreign_attributes );
}
};
}
using namespace demo;
using namespace matador;
@@ -62,6 +108,15 @@ int main() {
logger::add_log_sink(logger::create_stdout_sink());
{
// has_many with builtin-type
object::schema schema;
auto result = schema.attach<names>("names");
schema.dump(std::cout);
}
{
// has_many to belongs_to
object::schema schema;
auto result = schema.attach<author>("authors")
@@ -70,6 +125,7 @@ int main() {
schema.dump(std::cout);
}
{
// belongs_to to has_many
object::schema schema;
auto result = schema.attach<book>("books")
@@ -77,4 +133,40 @@ int main() {
schema.dump(std::cout);
}
{
// has_many_to_many (with join columns first)
object::schema schema;
auto result = schema.attach<ingredient>("ingredients")
.and_then([&schema] { return schema.attach<recipe>("recipes"); });
schema.dump(std::cout);
}
{
// has_many_to_many (with join columns last)
object::schema schema;
auto result = schema.attach<recipe>("recipes")
.and_then([&schema] { return schema.attach<ingredient>("ingredients"); });
schema.dump(std::cout);
}
{
// belongs_to to has_one
object::schema schema;
auto result = schema.attach<profile>("profiles")
.and_then([&schema] { return schema.attach<user>("users"); });
schema.dump(std::cout);
}
{
// has_one to belongs_to
object::schema schema;
auto result = schema.attach<user>("users")
.and_then([&schema] { return schema.attach<profile>("profiles"); });
schema.dump(std::cout);
}
}
+38 -15
View File
@@ -11,17 +11,38 @@
#include "work/admin/UserSession.hpp"
#include "work/jobs/Job.hpp"
#include "work/jobs/Task.hpp""
#include "work/jobs/Task.hpp"
#include "work/jobs/Payload.hpp"
#include "work/jobs/IdPayload.hpp"
#include "work/jobs/IdListPayload.hpp"
#include "matador/utils/default_type_traits.hpp"
#include "matador/object/schema.hpp"
#include "matador/sql/connection.hpp"
#include "matador/orm/session.hpp"
template <> struct matador::utils::data_type_traits<work::core::timestamp, void> {
static basic_type type(std::size_t /*size*/) { return basic_type::type_uint64; }
static void read_value(attribute_reader &reader, const char *id, size_t index, nullptr_t &/*value*/) {
}
static void bind_value(attribute_writer &binder, size_t index, nullptr_t &/*value*/) {
}
};
template <> struct matador::utils::data_type_traits<work::core::UserInfo, void> {
static basic_type type(std::size_t /*size*/) { return basic_type::type_uint64; }
static void read_value(attribute_reader &reader, const char *id, size_t index, nullptr_t &/*value*/) {
}
static void bind_value(attribute_writer &binder, size_t index, nullptr_t &/*value*/) {
}
};
using namespace matador;
using namespace work::models;
@@ -51,36 +72,38 @@ using namespace work::models;
int main() {
object::schema schema("Administration");
auto result = schema.attach<admin::CollectionCenter>("collection_center")
auto result = schema.attach<admin::CollectionCenter>("collection_centers")
.and_then([&schema] { return schema.attach<admin::UserDirectory>("user_directories"); })
.and_then([&schema] { return schema.attach<admin::LdapGroupSchemaSettings>("ldap_group_schema_settings"); })
.and_then([&schema] { return schema.attach<admin::LdapImportSettings>("ldap_import_settings"); })
.and_then([&schema] { return schema.attach<admin::LdapUserSchemaSettings>("ldap_user_schema_settings"); })
.and_then([&schema] { return schema.attach<admin::UserDirectory, admin::InternalUserDirectory>("internal_user_directories"); })
.and_then([&schema] { return schema.attach<admin::UserDirectory, admin::LdapUserDirectory>("ldap_user_directories"); } )
.and_then([&schema] { return schema.attach<admin::InternalUserDirectory, admin::UserDirectory>("internal_user_directories"); })
.and_then([&schema] { return schema.attach<admin::LdapUserDirectory, admin::UserDirectory>("ldap_user_directories"); } )
.and_then([&schema] { return schema.attach<admin::LoginHistory>("login_histories"); })
.and_then([&schema] { return schema.attach<admin::Scenario>("scenarios"); })
.and_then([&schema] { return schema.attach<admin::User>("users"); })
.and_then([&schema] { return schema.attach<admin::UserSession>("user_sessions"); })
.and_then([&schema] { return schema.attach<jobs::Job>("jobs"); })
.and_then([&schema] { return schema.attach<jobs::Payload>("payloads"); })
.and_then([&schema] { return schema.attach<jobs::Payload, jobs::IdPayload>("id_list_payloads"); })
.and_then([&schema] { return schema.attach<jobs::Payload, jobs::IdListPayload>("id_payloads"); })
.and_then([&schema] { return schema.attach<jobs::IdPayload, jobs::Payload>("id_list_payloads"); })
.and_then([&schema] { return schema.attach<jobs::IdListPayload, jobs::Payload>("id_payloads"); })
.and_then([&schema] { return schema.attach<jobs::Task>("tasks"); });
if (!result.is_ok()) {
std::cout << "error: " << result.err().message() << std::endl;
return 0;
}
const std::string dns{"sqlite://demo.db"};
sql::connection c(dns);
result = c.open();
// orm::session s()
if (!result.is_ok()) {
return 0;
}
schema.dump(std::cout);
// const std::string dns{"sqlite://demo.db"};
// sql::connection c(dns);
//
// result = c.open();
//
// // orm::session s()
// if (!result.is_ok()) {
// return 0;
// }
return 0;
+2 -1
View File
@@ -4,6 +4,7 @@
#include "../core/Model.hpp"
#include "matador/object/collection.hpp"
#include "matador/object/object_ptr.hpp"
#include "matador/utils/base_class.hpp"
#include "matador/utils/enum_mapper.hpp"
@@ -29,7 +30,7 @@ struct CollectionCenter : core::Model {
std::string name;
matador::utils::blob symbol;
CollectionCenterType type{CollectionCenterType::NoType};
matador::object::collection<User> users;
matador::object::collection<matador::object::object_ptr<User>> users;
template<typename Operator>
void process( Operator& op ) {
+1 -1
View File
@@ -7,7 +7,7 @@
#include "../core/Model.hpp"
#include "matador/object/object_ptr.hpp""
#include "matador/object/object_ptr.hpp"
#include "matador/utils/base_class.hpp"
#include "matador/utils/enum_mapper.hpp"
+1 -1
View File
@@ -42,7 +42,7 @@ struct Scenario : core::Model {
std::string description;
matador::utils::blob symbol;
ScenarioState state{ScenarioState::InvalidState};
matador::object::collection<CollectionCenter> collection_center;
matador::object::collection<matador::object::object_ptr<CollectionCenter>> collection_center;
template<typename Operator>
void process( Operator& op ) {
+1 -1
View File
@@ -6,7 +6,7 @@
#include "../core/Model.hpp"
#include "../core/Types.hpp"
#include "matador/object/object_ptr.hpp""
#include "matador/object/object_ptr.hpp"
#include "matador/utils/base_class.hpp"
#include "matador/utils/types.hpp"
+1 -1
View File
@@ -8,7 +8,7 @@
#include "../core/Model.hpp"
#include "../core/Types.hpp"
#include "matador/object/object_ptr.hpp""
#include "matador/object/object_ptr.hpp"
#include "matador/utils/base_class.hpp"
+3 -1
View File
@@ -5,6 +5,8 @@
#include "matador/object/collection.hpp"
#include "matador/utils/foreign_attributes.hpp"
namespace work::models::jobs {
struct IdListPayload : Payload {
matador::object::collection<unsigned long long> ids;
@@ -12,7 +14,7 @@ struct IdListPayload : Payload {
void process( Operator& op ) {
namespace field = matador::access;
field::process( op, *matador::base_class<Payload>( this ) );
field::has_many( op, "payload_ids", ids );
field::has_many( op, "payload_ids", ids, "payload_id", matador::utils::default_foreign_attributes );
}
};
}
+1 -1
View File
@@ -35,7 +35,7 @@ struct Job : core::Model {
field::attribute( op, "state", state );
field::attribute( op, "mode", mode );
field::attribute( op, "created_at", created_at );
field::belongs_to( op, "payload", payload, matador::utils::default_foreign_attributes );
field::has_one(op, "payload", payload, matador::utils::default_foreign_attributes );
field::belongs_to( op, "task", task, matador::utils::default_foreign_attributes );
field::attribute( op, "user_info", user_info );
}
+4
View File
@@ -6,13 +6,17 @@
#include "matador/utils/base_class.hpp"
namespace work::models::jobs {
struct Job;
struct Payload : core::Model {
std::string type;
matador::object::object_ptr<Job> job;
template<typename Operator>
void process( Operator& op ) {
namespace field = matador::access;
field::process( op, *matador::base_class<Model>( this ) );
field::attribute( op, "type", type, 255 );
field::belongs_to( op, "job", job, matador::utils::default_foreign_attributes );
}
};
}