From d4ef97ef5a1db2f2b6d12ad840069c5c39321304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sascha=20K=C3=BChl?= Date: Mon, 8 Dec 2025 19:45:35 +0100 Subject: [PATCH] removed make_relation_node method from repository_node --- backends/postgres/test/CMakeLists.txt | 4 +- include/matador/object/attribute.hpp | 3 + include/matador/object/basic_object_info.hpp | 5 +- include/matador/object/constraint.hpp | 3 + .../matador/object/foreign_node_completer.hpp | 4 +- include/matador/object/object.hpp | 3 + include/matador/object/object_info.hpp | 2 +- include/matador/object/relation_completer.hpp | 59 +++++++++---------- include/matador/object/repository_node.hpp | 33 ++--------- source/core/object/attribute.cpp | 46 ++------------- source/core/object/basic_object_info.cpp | 6 +- source/core/object/constraint.cpp | 5 ++ source/core/object/object.cpp | 15 ++++- source/core/object/repository_node.cpp | 25 +------- test/core/object/SchemaTest.cpp | 10 +++- 15 files changed, 90 insertions(+), 133 deletions(-) diff --git a/backends/postgres/test/CMakeLists.txt b/backends/postgres/test/CMakeLists.txt index 5c5040d..d7e535e 100644 --- a/backends/postgres/test/CMakeLists.txt +++ b/backends/postgres/test/CMakeLists.txt @@ -2,8 +2,8 @@ CPMAddPackage("gh:catchorg/Catch2@3.7.1") list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras) -set(POSTGRES_CONNECTION_STRING "postgres://test:test123!@127.0.0.1:15442/matador") -#set(POSTGRES_CONNECTION_STRING "postgres://test:test123!@127.0.0.1:5432/matador") +#set(POSTGRES_CONNECTION_STRING "postgres://test:test123!@127.0.0.1:15442/matador") +set(POSTGRES_CONNECTION_STRING "postgres://test:test123!@127.0.0.1:5432/matador") configure_file(Connection.hpp.in ${PROJECT_BINARY_DIR}/backends/postgres/test/connection.hpp @ONLY IMMEDIATE) diff --git a/include/matador/object/attribute.hpp b/include/matador/object/attribute.hpp index b15ee5d..510484d 100644 --- a/include/matador/object/attribute.hpp +++ b/include/matador/object/attribute.hpp @@ -6,6 +6,7 @@ #include "matador/utils/field_attributes.hpp" #include +#include namespace matador::object { @@ -60,6 +61,8 @@ public: return type() == utils::data_type_traits::type(attributes().size()); } + friend std::ostream& operator<<(std::ostream& os, const attribute& attr); + private: friend class object; friend class attribute_generator; diff --git a/include/matador/object/basic_object_info.hpp b/include/matador/object/basic_object_info.hpp index 4f375dd..e4b892c 100644 --- a/include/matador/object/basic_object_info.hpp +++ b/include/matador/object/basic_object_info.hpp @@ -26,6 +26,7 @@ public: [[nodiscard]] std::type_index type_index() const; [[nodiscard]] std::string name() const; + [[nodiscard]] const class object& object() const; [[nodiscard]] const std::list& attributes() const; [[nodiscard]] const std::list& constraints() const; @@ -54,10 +55,10 @@ public: [[nodiscard]] bool endpoints_empty() const; protected: - basic_object_info(std::shared_ptr node, std::unique_ptr &&obj); + basic_object_info(std::shared_ptr node, std::unique_ptr &&obj); protected: - std::unique_ptr object_; + std::unique_ptr object_; std::shared_ptr node_; /**< prototype node of the represented object type */ t_endpoint_map relation_endpoints_; }; diff --git a/include/matador/object/constraint.hpp b/include/matador/object/constraint.hpp index 61ab7f4..70b19b1 100644 --- a/include/matador/object/constraint.hpp +++ b/include/matador/object/constraint.hpp @@ -3,6 +3,7 @@ #include "matador/utils/constraints.hpp" +#include #include #include @@ -28,6 +29,8 @@ public: [[nodiscard]] const std::string& ref_table_name() const; [[nodiscard]] const std::string& ref_column_name() const; + friend std::ostream& operator<<(std::ostream& os, const constraint& c); + private: friend class constraint_builder; friend class constraints_generator; diff --git a/include/matador/object/foreign_node_completer.hpp b/include/matador/object/foreign_node_completer.hpp index 0eb965a..fed65c2 100644 --- a/include/matador/object/foreign_node_completer.hpp +++ b/include/matador/object/foreign_node_completer.hpp @@ -115,13 +115,13 @@ private: return std::make_unique(join_column, inverse_join_column); }; - result = repository_node::make_relation_node(repo_.repo(), name, std::move(creator)); + auto node = repository_node::make_node(repo_.repo(), name, std::move(creator)); + result = repo_.attach_node(node); if (!result) { // Todo: throw internal error return; } - auto& node = result.value(); complete(result.value()); // auto& node = result.value(); diff --git a/include/matador/object/object.hpp b/include/matador/object/object.hpp index d1dda19..713af7e 100644 --- a/include/matador/object/object.hpp +++ b/include/matador/object/object.hpp @@ -7,6 +7,7 @@ #include "matador/utils/identifier.hpp" #include +#include namespace matador::object { @@ -38,6 +39,8 @@ public: [[nodiscard]] size_t constraint_count() const; [[nodiscard]] const std::list& constraints() const; + friend std::ostream& operator<<(std::ostream& os, const object& obj); + private: friend class constraints_generator; friend class attribute_generator; diff --git a/include/matador/object/object_info.hpp b/include/matador/object/object_info.hpp index 94fe8ab..614bf83 100644 --- a/include/matador/object/object_info.hpp +++ b/include/matador/object/object_info.hpp @@ -14,7 +14,7 @@ public: using create_func = std::function()>; object_info(const std::shared_ptr& node, - std::unique_ptr &&obj, + std::unique_ptr &&obj, create_func&& creator) : basic_object_info(node, std::move(obj)) , creator_(std::move(creator)){ diff --git a/include/matador/object/relation_completer.hpp b/include/matador/object/relation_completer.hpp index 3e38fe8..71f88fa 100644 --- a/include/matador/object/relation_completer.hpp +++ b/include/matador/object/relation_completer.hpp @@ -186,28 +186,28 @@ void relation_completer::on_has_many(const char *id, CollectionType &, const auto local_endpoint = std::make_shared(id, relation_type::HasMany, foreign_node); nodes_.top()->info_->register_relation_endpoint(typeid(value_type), local_endpoint); } else { - // A relation table is necessary - // Endpoint was not found. - // Always attach a many-to-many relation type. If later a - // belongs-to relation handles this relation, the many-to-many - // relation is maybe detached. - log_.debug("node '%s' has has many foreign keys '%s' mapped by '%s'", nodes_.top()->name().c_str(), id, join_column); - result = repository_node::make_relation_node( - schema_.repo(), id, [join_column] { - return std::make_unique("id", join_column); - }); - if (!result) { - // Todo: throw internal error - return; - } - const auto local_endpoint = std::make_shared(id, relation_type::HasMany, result.value()); - const auto foreign_endpoint = std::make_shared("id", relation_type::BelongsTo, nodes_.top()); - nodes_.top()->info_->register_relation_endpoint(typeid(value_type), local_endpoint); - result.value()->info_->register_relation_endpoint(nodes_.top()->type_index(), foreign_endpoint); - link_relation_endpoints(local_endpoint, foreign_endpoint); + // A relation table is necessary + // Endpoint was not found. + // Always attach a many-to-many relation type. If later a + // belongs-to relation handles this relation, the many-to-many + // relation is maybe detached. + log_.debug("node '%s' has has many foreign keys '%s' mapped by '%s'", nodes_.top()->name().c_str(), id, join_column); + auto node = repository_node::make_node(schema_.repo(), id, [join_column] { + return std::make_unique("id", join_column); + }); + result = schema_.attach_node(node); + if (!result) { + // Todo: throw internal error + return; + } + const auto local_endpoint = std::make_shared(id, relation_type::HasMany, node); + const auto foreign_endpoint = std::make_shared("id", relation_type::BelongsTo, nodes_.top()); + nodes_.top()->info_->register_relation_endpoint(typeid(value_type), local_endpoint); + node->info_->register_relation_endpoint(nodes_.top()->type_index(), foreign_endpoint); + link_relation_endpoints(local_endpoint, foreign_endpoint); - const auto foreign_value_endpoint = std::make_shared(join_column, relation_type::BelongsTo, foreign_node); - result.value()->info_->register_relation_endpoint(typeid(value_type), foreign_value_endpoint); + const auto foreign_value_endpoint = std::make_shared(join_column, relation_type::BelongsTo, foreign_node); + node->info_->register_relation_endpoint(typeid(value_type), foreign_value_endpoint); } } @@ -220,21 +220,20 @@ void relation_completer::on_has_many(const char *id, CollectionType &, con using value_type = typename CollectionType::value_type; using relation_value_type = many_to_relation; - const auto result = repository_node::make_relation_node( - schema_.repo(), id, [join_column] { - return std::make_unique(join_column, "value"); - }); - + auto node = repository_node::make_node(schema_.repo(), id, [join_column] { + return std::make_unique(join_column, "value"); + }); + const auto result = schema_.attach_node(node); if (!result) { // Todo: throw internal exception return; } - const auto local_endpoint = std::make_shared(id, relation_type::HasMany, result.value()); + const auto local_endpoint = std::make_shared(id, relation_type::HasMany, node); const auto foreign_endpoint = std::make_shared(join_column, relation_type::BelongsTo, nodes_.top()); nodes_.top()->info_->register_relation_endpoint(typeid(value_type), local_endpoint); - result.value()->info_->register_relation_endpoint(nodes_.top()->type_index(), foreign_endpoint); + node->info_->register_relation_endpoint(nodes_.top()->type_index(), foreign_endpoint); link_relation_endpoints(local_endpoint, foreign_endpoint); } @@ -265,13 +264,13 @@ void relation_completer::on_has_many_to_many(const char *id, return std::make_unique(join_column, inverse_join_column); }; - result = repository_node::make_relation_node(schema_.repo(), id, std::move(creator)); + auto node = repository_node::make_node(schema_.repo(), id, std::move(creator)); + result = schema_.attach_node(node); if (!result) { // Todo: throw internal error return; } - auto& node = result.value(); const auto local_endpoint = std::make_shared(id, relation_type::HasMany, node); const auto join_endpoint = std::make_shared(join_column, relation_type::BelongsTo, nodes_.top()); const auto inverse_join_endpoint = std::make_shared(inverse_join_column, relation_type::BelongsTo, foreign_node); diff --git a/include/matador/object/repository_node.hpp b/include/matador/object/repository_node.hpp index a669558..e6dd865 100644 --- a/include/matador/object/repository_node.hpp +++ b/include/matador/object/repository_node.hpp @@ -4,7 +4,6 @@ #include "matador/object/attribute_generator.hpp" #include "matador/object/object_generator.hpp" #include "matador/object/object_info.hpp" -#include "matador/object/primary_key_resolver.hpp" #include @@ -16,42 +15,24 @@ class repository; class repository_node final { public: using node_ptr = std::shared_ptr; + template< typename Type> + using creator_func = std::function()>; template < typename Type > - static std::shared_ptr make_node(repository& repo, const std::string& name) { + static std::shared_ptr make_node(repository& repo, const std::string& name, creator_func creator = []{ return std::make_unique(); }) { auto node = std::shared_ptr(new repository_node(repo, name, typeid(Type))); - primary_key_resolver resolver; - auto pk_info = resolver.resolve(); - auto obj = object_generator::generate(repo, name); + auto obj = object_generator::generate(creator(), repo, name); auto info = std::make_unique>( node, std::move(obj), - []{ return std::make_unique(); } + std::forward>(creator) ); node->info_ = std::move(info); return node; } - template < typename Type, typename CreatorFunc > - static utils::result make_relation_node(repository& repo, const std::string& name, CreatorFunc &&creator) { - const auto result = make_and_attach_node(repo, name, typeid(Type)); - if (!result) { - return result; - } - - auto obj = object_generator::generate(creator(), repo, name); - auto info = std::make_unique>( - result.value(), - std::move(obj), - std::forward(creator) - ); - result.value()->info_ = std::move(info); - - return result; - } - static std::shared_ptr make_null_node(repository& repo); repository_node(const repository_node& other) = delete; @@ -87,10 +68,6 @@ private: void unlink(); static utils::result make_and_attach_node(repository& repo, const std::string& name, const std::type_index& ti); - static attribute* determine_reference_column(const std::type_index& ti, - const std::string& table_name, - const primary_key_info& pk_info, - repository& repo); private: friend class repository; diff --git a/source/core/object/attribute.cpp b/source/core/object/attribute.cpp index eab3474..d762cf4 100644 --- a/source/core/object/attribute.cpp +++ b/source/core/object/attribute.cpp @@ -92,45 +92,9 @@ bool attribute::is_null() const { return type_ == utils::basic_type::type_null; } -// attribute make_column(const std::string &name, utils::basic_type type, utils::field_attributes attr, -// null_option_type null_opt) { -// return {name, type, attr, null_opt}; -// } -// -// template<> -// attribute make_column(const std::string &name, utils::field_attributes attr, -// null_option_type null_opt) { -// return make_column(name, utils::data_type_traits::type(attr.size()), attr, null_opt); -// } -// -// template<> -// attribute make_pk_column(const std::string &name, size_t size) { -// return make_column(name, {size, utils::constraints::PrimaryKey}); -// } -// -// template<> -// attribute make_fk_column(const std::string &name, size_t size, const std::shared_ptr &ref_column) { -// return { -// name, utils::data_type_traits::type(size), 0, ref_column, -// {size, utils::constraints::ForeignKey}, null_option_type::NOT_NULL -// }; -// } -// -// template<> -// attribute make_fk_column( const std::string& name, const std::string& ref_table_name, const std::string& ref_column_name ) { -// return { -// name, utils::basic_type::type_varchar, 0, -// std::make_shared(ref_column_name, utils::basic_type::type_varchar, ref_table_name, attribute_options{utils::constraints::ForeignKey}), -// { 0, utils::constraints::ForeignKey }, null_option_type::NOT_NULL -// }; -// } -// -// template<> -// attribute make_fk_column(const std::string &name, size_t size, const std::string &ref_table_name, const std::string &ref_column_name) { -// const auto ref_column = std::make_shared(ref_column_name, utils::basic_type::type_varchar, ref_table_name, attribute_options{utils::constraints::ForeignKey}); -// return { -// name, utils::data_type_traits::type(size), 0, ref_column, -// {size, utils::constraints::ForeignKey}, null_option_type::NOT_NULL -// }; -// } +std::ostream & operator<<(std::ostream &os, const attribute &attr) { + os << attr.name_; + return os; +} + } diff --git a/source/core/object/basic_object_info.cpp b/source/core/object/basic_object_info.cpp index f5b7808..e9be1a0 100644 --- a/source/core/object/basic_object_info.cpp +++ b/source/core/object/basic_object_info.cpp @@ -20,7 +20,7 @@ namespace matador::object { // : node_(std::move(node)) // , attributes_(attributes) {} -basic_object_info::basic_object_info(std::shared_ptr node, std::unique_ptr&& obj) +basic_object_info::basic_object_info(std::shared_ptr node, std::unique_ptr&& obj) : object_(std::move(obj)) , node_(std::move(node)) {} @@ -32,6 +32,10 @@ std::string basic_object_info::name() const { return node_->name(); } +const class object & basic_object_info::object() const { + return *object_; +} + const std::list& basic_object_info::attributes() const { return object_->attributes(); } diff --git a/source/core/object/constraint.cpp b/source/core/object/constraint.cpp index 4ad10f6..3ab0f19 100644 --- a/source/core/object/constraint.cpp +++ b/source/core/object/constraint.cpp @@ -52,6 +52,11 @@ const std::string& constraint::ref_column_name() const { return ref_column_name_; } +std::ostream & operator<<(std::ostream &os, const class constraint &c) { + os << "constraint " << c.name_ << " for column " << c.column_name(); + return os; +} + constraint_builder & constraint_builder::constraint(std::string name) { constraint_name = std::move(name); return *this; diff --git a/source/core/object/object.cpp b/source/core/object/object.cpp index 4cd2a4d..f54cf79 100644 --- a/source/core/object/object.cpp +++ b/source/core/object/object.cpp @@ -75,4 +75,17 @@ size_t object::constraint_count() const { const std::list& object::constraints() const { return constraints_; } -} \ No newline at end of file + +std::ostream & operator<<(std::ostream &os, const object &obj) { + os << "Object " << obj.name_ << "\nAttributes:\n"; + for (const auto &attr : obj.attributes_) { + os << " " << attr << "\n"; + } + os << "Constraints:\n"; + for (const auto &con : obj.constraints_) { + os << " " << con << "\n"; + } + os << "\n"; + return os; +} +} diff --git a/source/core/object/repository_node.cpp b/source/core/object/repository_node.cpp index 7188e18..a9e9ff6 100644 --- a/source/core/object/repository_node.cpp +++ b/source/core/object/repository_node.cpp @@ -26,7 +26,7 @@ repository_node::repository_node(repository &repo, std::string name, const std:: std::shared_ptr repository_node::make_null_node(repository &repo) { auto node = std::shared_ptr(new repository_node(repo)); - node->info_ = std::make_unique(node/*, std::shared_ptr{}*/); + node->info_ = std::make_unique(node); return node; } @@ -101,27 +101,4 @@ utils::result repository_node::make_and return repo.attach_node(node, ""); } - -attribute* repository_node::determine_reference_column(const std::type_index& ti, - const std::string& table_name, - const primary_key_info& pk_info, - repository& repo) { - const auto it = repo.missing_references_.find(ti); - if (it == repo.missing_references_.end()) { - return new attribute(pk_info.pk_column_name, pk_info.type, {utils::constraints::ForeignKey}, null_option_type::NotNull); - } - - auto ref_column = it->second; - repo.missing_references_.erase(it); - ref_column->name(pk_info.pk_column_name); - ref_column->owner()->update_name(table_name); - ref_column->change_type(pk_info.type); - ref_column->attributes() = utils::constraints::ForeignKey; - - if (table_name.empty()) { - repo.missing_references_.insert({ti, ref_column}); - } - - return ref_column; -} } diff --git a/test/core/object/SchemaTest.cpp b/test/core/object/SchemaTest.cpp index 1e675fe..c0cb54e 100644 --- a/test/core/object/SchemaTest.cpp +++ b/test/core/object/SchemaTest.cpp @@ -104,6 +104,9 @@ TEST_CASE("Test one to many", "[relation][one-to-many]") { REQUIRE(repo.size() == 2); REQUIRE(repo.contains("departments")); REQUIRE(repo.contains("employees")); + + std::cout << repo.basic_info("departments")->get().object(); + std::cout << repo.basic_info("employees")->get().object(); } TEST_CASE("Test one to many reverse", "[relation][one-to-many][reverse]") { @@ -117,6 +120,9 @@ TEST_CASE("Test one to many reverse", "[relation][one-to-many][reverse]") { REQUIRE(repo.size() == 2); REQUIRE(repo.contains("departments")); REQUIRE(repo.contains("employees")); + + std::cout << repo.basic_info("departments")->get().object(); + std::cout << repo.basic_info("employees")->get().object(); } TEST_CASE("Test many to many relation", "[relation][many-to-many]") { @@ -133,5 +139,7 @@ TEST_CASE("Test many to many relation", "[relation][many-to-many]") { REQUIRE(repo.contains("recipes")); REQUIRE(repo.contains("recipe_ingredients")); - auto info = repo.basic_info("ingredients"); + std::cout << repo.basic_info("ingredients")->get().object(); + std::cout << repo.basic_info("recipes")->get().object(); + std::cout << repo.basic_info("recipe_ingredients")->get().object(); }