From 79c46bbd381509a9c2cfc969d8d6d84136792475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sascha=20K=C3=BChl?= Date: Thu, 11 Dec 2025 15:41:45 +0100 Subject: [PATCH] fixed object generation on nested objects --- .../matador/object/foreign_node_completer.hpp | 17 ++++-- .../object/internal/shadow_repository.hpp | 9 ++++ include/matador/object/object.hpp | 3 +- include/matador/object/object_generator.hpp | 52 +++++++++++++++++-- .../object/internal/shadow_repository.cpp | 20 +++++++ source/core/object/object.cpp | 2 +- source/core/object/object_generator.cpp | 25 --------- source/core/object/restriction.cpp | 3 ++ 8 files changed, 97 insertions(+), 34 deletions(-) diff --git a/include/matador/object/foreign_node_completer.hpp b/include/matador/object/foreign_node_completer.hpp index fed65c2..6f8c37e 100644 --- a/include/matador/object/foreign_node_completer.hpp +++ b/include/matador/object/foreign_node_completer.hpp @@ -29,8 +29,7 @@ private: public: template static void complete(const std::shared_ptr &node) { - internal::shadow_repository shadow(node->repo_); - foreign_node_completer completer(shadow); + foreign_node_completer completer(internal::shadow_repository(node->repo_)); completer.complete_node(node); } @@ -83,7 +82,7 @@ private: } template - void attach_node(const std::string &name = "") { + void attach_node(const std::string &name) { if (repo_.contains(typeid(Type))) { return; } @@ -93,6 +92,18 @@ private: } } + template + void attach_node() { + if (repo_.contains(typeid(Type))) { + return; + } + + const auto node = repository_node::make_node(repo_.repo(), ""); + if (auto result = repo_.attach_node(node)) { + complete(result.value()); + } + } + template void attach_relation_node(const std::string &name, const std::string &join_column, const std::string &inverse_join_column) { using relation_value_type = many_to_many_relation; diff --git a/include/matador/object/internal/shadow_repository.hpp b/include/matador/object/internal/shadow_repository.hpp index 8647756..632a567 100644 --- a/include/matador/object/internal/shadow_repository.hpp +++ b/include/matador/object/internal/shadow_repository.hpp @@ -1,6 +1,8 @@ #ifndef SHADOW_SCHEMA_HPP #define SHADOW_SCHEMA_HPP +#include "matador/object/basic_object_info.hpp" + #include "matador/utils/result.hpp" #include "matador/utils/error.hpp" @@ -10,6 +12,7 @@ namespace matador::object { class repository; class repository_node; +class object; } namespace matador::object::internal { @@ -22,6 +25,7 @@ public: [[nodiscard]] repository& repo() const; [[nodiscard]] bool contains(const std::type_index& ti) const; + [[nodiscard]] utils::result basic_info(const std::type_index& ti) const; [[nodiscard]] utils::result find_node(const std::type_index &type_index) const; [[nodiscard]] utils::result find_node(const std::string &name) const; [[nodiscard]] utils::result attach_node(const std::shared_ptr &node) const; @@ -31,6 +35,11 @@ public: void expect_relation_node(const std::string &name, const std::type_index &ti) const; void remove_expected_relation_node(const std::string &name) const; + [[nodiscard]] std::shared_ptr provide_object_in_advance(const std::type_index &ti, const std::shared_ptr& obj) const; + [[nodiscard]] bool has_object_for_type(const std::type_index &ti) const; + [[nodiscard]] std::shared_ptr object_for_type(const std::type_index &ti) const; + void remove_object_for_type(const std::type_index &ti) const; + private: repository& repo_; }; diff --git a/include/matador/object/object.hpp b/include/matador/object/object.hpp index 4dff4f9..3106aad 100644 --- a/include/matador/object/object.hpp +++ b/include/matador/object/object.hpp @@ -23,6 +23,7 @@ public: [[nodiscard]] const utils::identifier& primary_key() const; [[nodiscard]] bool has_primary_key() const; + [[nodiscard]] bool empty() const; [[nodiscard]] const std::string& name() const; void update_name(const std::string& name); @@ -33,7 +34,7 @@ public: [[nodiscard]] bool has_constraints() const; [[nodiscard]] size_t constraint_count() const; - [[nodiscard]] const std::list& constraints() const; + [[nodiscard]] const std::list& constraints() const; friend std::ostream& operator<<(std::ostream& os, const object& obj); diff --git a/include/matador/object/object_generator.hpp b/include/matador/object/object_generator.hpp index 3bee984..8b56130 100644 --- a/include/matador/object/object_generator.hpp +++ b/include/matador/object/object_generator.hpp @@ -1,6 +1,7 @@ #ifndef MATADOR_OBJECT_GENERATOR_HPP #define MATADOR_OBJECT_GENERATOR_HPP +#include "matador/object/internal/shadow_repository.hpp" #include "matador/object/object.hpp" #include "matador/utils/access.hpp" @@ -60,7 +61,16 @@ public: template < class Type > static std::shared_ptr generate(std::unique_ptr&& t, repository &repo, const std::string &name) { - auto obj = acquire_object(repo, typeid(Type), name); + const internal::shadow_repository shadow_repo(repo); + const std::type_index ti(typeid(Type)); + if (shadow_repo.has_object_for_type(ti)) { + auto obj = shadow_repo.object_for_type(ti); + shadow_repo.remove_object_for_type(ti); + obj->update_name(name); + return obj; + } + + auto obj = shadow_repo.provide_object_in_advance(ti, std::make_shared(name)); object_generator gen(repo, obj); access::process(gen, *t); return obj; @@ -79,7 +89,7 @@ public: template void on_belongs_to(const char *id, Pointer &x, const utils::foreign_attributes &/*attr*/) { on_foreign_key(id, x); - create_fk_constraint( typeid(typename Pointer::value_type), id); + create_fk_constraint(id); } template static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {} @@ -106,14 +116,16 @@ private: } void create_pk_constraint(const std::string& name) const; - void create_fk_constraint(const std::type_index& ti, const std::string& name) const; + template + void create_fk_constraint(const std::string& name) const; void create_unique_constraint(const std::string& name) const; [[nodiscard]] std::list::iterator find_attribute_by_name(const std::string &name) const; void prepare_primary_key(attribute &ref, utils::identifier &&pk) const; - [[nodiscard]] std::shared_ptr fk_object(const std::type_index& ti) const; + template + [[nodiscard]] std::shared_ptr fk_object() const; static std::shared_ptr acquire_object(repository &repo, const std::type_index &ti, const std::string& name); private: @@ -138,5 +150,37 @@ void object_generator::on_attribute(const char *id, std::optional & /*x*/, std::ignore = emplace_attribute(id, attr, null_option_type::Nullable); } +template +void object_generator::create_fk_constraint(const std::string& name) const { + const auto pk_attr = find_attribute_by_name(name); + if (pk_attr == std::end(object_->attributes_)) { + return; + } + const auto obj = fk_object(); + restriction pk_constraint(*pk_attr); + pk_constraint.options_ |= utils::constraints::ForeignKey; + pk_constraint.owner_ = object_; + pk_constraint.reference_ = obj; + object_->constraints_.emplace_back(std::move(pk_constraint)); +} + +template +std::shared_ptr object_generator::fk_object() const { + const auto ti = std::type_index(typeid(Type)); + const internal::shadow_repository shadow_repo(repo_); + if (const auto result = shadow_repo.basic_info(ti)) { + return result->get().object(); + } + + if (shadow_repo.has_object_for_type(ti)) { + return shadow_repo.object_for_type(ti); + } + const auto obj = shadow_repo.provide_object_in_advance(ti, std::make_shared("")); + object_generator gen(repo_, obj); + Type t; + access::process(gen, t); + return obj; +} + } #endif //MATADOR_OBJECT_GENERATOR_HPP \ No newline at end of file diff --git a/source/core/object/internal/shadow_repository.cpp b/source/core/object/internal/shadow_repository.cpp index a2ce3b5..b4124a5 100644 --- a/source/core/object/internal/shadow_repository.cpp +++ b/source/core/object/internal/shadow_repository.cpp @@ -15,6 +15,10 @@ bool shadow_repository::contains( const std::type_index& ti ) const { return repo_.contains(ti); } +utils::result shadow_repository::basic_info(const std::type_index& ti) const { + return repo_.basic_info(ti); +} + utils::result shadow_repository::find_node( const std::type_index& type_index ) const { return repo_.find_node(type_index); } @@ -42,4 +46,20 @@ void shadow_repository::expect_relation_node(const std::string &name, const std: void shadow_repository::remove_expected_relation_node(const std::string &name) const { repo_.remove_expected_relation_node(name); } + +std::shared_ptr shadow_repository::provide_object_in_advance(const std::type_index& ti, const std::shared_ptr& obj) const { + return repo_.provide_object_in_advance(ti, obj); +} + +bool shadow_repository::has_object_for_type(const std::type_index& ti) const { + return repo_.has_object_for_type(ti); +} + +std::shared_ptr shadow_repository::object_for_type(const std::type_index& ti) const { + return repo_.object_for_type(ti); +} + +void shadow_repository::remove_object_for_type(const std::type_index& ti) const { + repo_.remove_object_for_type(ti); +} } diff --git a/source/core/object/object.cpp b/source/core/object/object.cpp index fa78a67..e546787 100644 --- a/source/core/object/object.cpp +++ b/source/core/object/object.cpp @@ -50,7 +50,7 @@ size_t object::constraint_count() const { return constraints_.size(); } -const std::list& object::constraints() const { +const std::list& object::constraints() const { return constraints_; } diff --git a/source/core/object/object_generator.cpp b/source/core/object/object_generator.cpp index 66e58bc..884d081 100644 --- a/source/core/object/object_generator.cpp +++ b/source/core/object/object_generator.cpp @@ -35,19 +35,6 @@ void object_generator::create_pk_constraint(const std::string& name) const { object_->constraints_.emplace_back(std::move(pk_constraint)); } -void object_generator::create_fk_constraint(const std::type_index& ti, const std::string& name) const { - const auto pk_attr = find_attribute_by_name(name); - if (pk_attr == std::end(object_->attributes_)) { - return; - } - const auto obj = fk_object(ti); - restriction pk_constraint(*pk_attr); - pk_constraint.options_ |= utils::constraints::ForeignKey; - pk_constraint.owner_ = object_; - pk_constraint.reference_ = obj; - object_->constraints_.emplace_back(std::move(pk_constraint)); -} - void object_generator::create_unique_constraint(const std::string& name) const { const auto pk_attr = find_attribute_by_name(name); if (pk_attr == std::end(object_->attributes_)) { @@ -68,16 +55,4 @@ void object_generator::prepare_primary_key(attribute& ref, utils::identifier &&p object_->pk_attribute_ = &ref; object_->pk_identifier_ = std::move(pk); } - -std::shared_ptr object_generator::fk_object(const std::type_index& ti) const { - const auto result = repo_.basic_info(ti); - if (result) { - return result->get().object(); - } - - if (repo_.has_object_for_type(ti)) { - return repo_.object_for_type(ti); - } - return repo_.provide_object_in_advance(ti, std::make_shared("")); -} } diff --git a/source/core/object/restriction.cpp b/source/core/object/restriction.cpp index b5f0678..502660f 100644 --- a/source/core/object/restriction.cpp +++ b/source/core/object/restriction.cpp @@ -40,6 +40,9 @@ const std::string& restriction::ref_column_name() const { std::ostream & operator<<(std::ostream &os, const class restriction &c) { os << "constraint " << c.type_string() << " for column " << c.column_name(); + if (c.is_foreign_key_constraint()) { + os << " references " << c.ref_table_name() << "." << c.ref_column_name(); + } return os; }