diff --git a/include/matador/object/collection_resolver_factory.hpp b/include/matador/object/collection_resolver_factory.hpp index f7ea756..cf9901c 100644 --- a/include/matador/object/collection_resolver_factory.hpp +++ b/include/matador/object/collection_resolver_factory.hpp @@ -3,6 +3,8 @@ #include "matador/object/collection_resolver.hpp" +#include + namespace matador::object { class abstract_collection_resolver_factory { public: @@ -29,20 +31,20 @@ class abstract_joined_object_resolver_factory { public: virtual ~abstract_joined_object_resolver_factory() = default; - [[nodiscard]] virtual std::shared_ptr acquire_joined_object_resolver(const std::type_index &root_type, const std::type_index &element_type, const std::string &collection_name) const = 0; - virtual void register_joined_object_resolver(std::shared_ptr &&resolver) = 0; + [[nodiscard]] virtual std::shared_ptr acquire_joined_object_resolver(const std::type_index &root_type, const std::type_index &element_type, const std::string &collection_name) const = 0; + virtual void register_joined_object_resolver(std::shared_ptr &&resolver, const std::type_index& root_type, const std::string& join_column) = 0; }; class joined_object_resolver_factory : public abstract_joined_object_resolver_factory { public: template - [[nodiscard]] std::shared_ptr> resolver(const std::type_index &root_type, const std::string &collection_name) const { + [[nodiscard]] std::shared_ptr> resolver(const std::type_index &root_type, const std::string &collection_name) const { const auto res = acquire_joined_object_resolver(root_type, typeid(Type), collection_name); if (!res) { - return std::dynamic_pointer_cast>(res); + return std::dynamic_pointer_cast>(res); } - return std::dynamic_pointer_cast>(res); + return std::dynamic_pointer_cast>(res); } }; } diff --git a/include/matador/object/object_ptr.hpp b/include/matador/object/object_ptr.hpp index d691587..124aca3 100644 --- a/include/matador/object/object_ptr.hpp +++ b/include/matador/object/object_ptr.hpp @@ -55,6 +55,7 @@ public: } void reset() { proxy_.reset(); } + void reset(const std::shared_ptr>& proxy) { proxy_ = proxy; } operator bool() const { return valid(); } [[nodiscard]] bool valid() const { return proxy_ != nullptr && !proxy_->empty(); } diff --git a/include/matador/object/object_resolver.hpp b/include/matador/object/object_resolver.hpp index e9dc52d..01eab20 100644 --- a/include/matador/object/object_resolver.hpp +++ b/include/matador/object/object_resolver.hpp @@ -19,11 +19,12 @@ public: virtual std::shared_ptr resolve(const utils::identifier& id) = 0; }; template -class joined_object_resolver : public abstract_joined_resolver { +class joined_object_resolver : public abstract_joined_resolver, public object_resolver { public: - joined_object_resolver(const std::type_index& root_type, const std::string& join_column) : abstract_joined_resolver(root_type, typeid(Type), join_column) {} + joined_object_resolver(const std::type_index& root_type, const std::string& join_column) + : abstract_joined_resolver(root_type, typeid(Type), join_column) {} - virtual std::shared_ptr resolve(const utils::identifier& id) = 0; + std::shared_ptr resolve(const utils::identifier& id) override = 0; }; } #endif //MATADOR_OBJECT_LOADER_HPP \ No newline at end of file diff --git a/include/matador/query/basic_schema.hpp b/include/matador/query/basic_schema.hpp index 6c04a91..5fffe8a 100644 --- a/include/matador/query/basic_schema.hpp +++ b/include/matador/query/basic_schema.hpp @@ -103,7 +103,7 @@ public: [[nodiscard]] const std::unordered_map>& resolver_producers() const; [[nodiscard]] const std::unordered_map, object::collection_composite_key_hash>& collection_resolver_producers() const; - [[nodiscard]] const std::unordered_map, object::collection_composite_key_hash>& joined_object_resolver_producers() const; + [[nodiscard]] const std::unordered_map, object::collection_composite_key_hash>& joined_object_resolver_producers() const; protected: template @@ -114,7 +114,7 @@ protected: std::unordered_map schema_nodes_; std::unordered_map> resolver_producers_; std::unordered_map, object::collection_composite_key_hash> collection_resolver_producers_; - std::unordered_map, object::collection_composite_key_hash> joined_object_resolver_producers_; + std::unordered_map, object::collection_composite_key_hash> joined_object_resolver_producers_; }; } #endif //MATADOR_BASIC_SCHEMA_HPP \ No newline at end of file diff --git a/include/matador/query/query_object_resolver.hpp b/include/matador/query/query_object_resolver.hpp index e648aa6..e1dec6e 100644 --- a/include/matador/query/query_object_resolver.hpp +++ b/include/matador/query/query_object_resolver.hpp @@ -22,6 +22,17 @@ protected: sql::statement stmt_; }; +template +class query_joined_object_resolver : public object::joined_object_resolver { +public: + explicit query_joined_object_resolver(sql::statement &&stmt) + : stmt_(std::move(stmt)) {} + + std::shared_ptr resolve(const utils::identifier &id) override; +protected: + sql::statement stmt_; +}; + template std::shared_ptr query_object_resolver::resolve(const utils::identifier &id) { sql::identifier_statement_binder binder(stmt_); @@ -34,5 +45,16 @@ std::shared_ptr query_object_resolver::resolve(const utils::identifi return *result; } +template +std::shared_ptr query_joined_object_resolver::resolve(const utils::identifier &id) { + sql::identifier_statement_binder binder(stmt_); + binder.bind(id); + + auto result = stmt_.template fetch_one_raw(); + if (!result) { + return nullptr; + } + return *result; +} } #endif //MATADOR_QUERY_OBJECT_LOADER_HPP \ No newline at end of file diff --git a/include/matador/query/schema.hpp b/include/matador/query/schema.hpp index f899e49..796d30b 100644 --- a/include/matador/query/schema.hpp +++ b/include/matador/query/schema.hpp @@ -45,22 +45,17 @@ template class query_joined_object_resolver_producer : public sql::joined_object_resolver_producer { public: query_joined_object_resolver_producer() = default; - query_joined_object_resolver_producer(basic_schema& repo, const table& tab, std::string pk_name, const std::type_index& root_type, std::string join_column) + query_joined_object_resolver_producer(basic_schema& repo, const table& tab, std::string pk_name, const std::type_index& root_type, const std::string &join_column) : joined_object_resolver_producer(root_type, typeid(Type), join_column) , repo_(repo) , table_(tab) , pk_name_(std::move(pk_name)) {} - std::shared_ptr produce(sql::statement&& stmt) override { + std::shared_ptr produce(sql::statement&& stmt) override { return std::make_shared>(std::move(stmt)); } - utils::result build_query(const sql::dialect& d) override { - const auto *pk_column = table_[pk_name_]; - const auto *join_column = table_[collection_name()]; - - return utils::ok(sql::query_context{}); - } + utils::result build_query(const sql::dialect& /*d*/) override; private: basic_schema& repo_; @@ -162,9 +157,11 @@ public: throw query_builder_exception{error_code::MissingPrimaryKey, "Missing primary key"}; } - auto producer = std::make_unique>( + auto producer = std::make_unique>( schema_, it->second.table(), + it->second.node().info().primary_key_attribute()->name(), + root_type_, join_column); const object::collection_composite_key key{root_type_, typeid(Pointer), join_column}; schema_.joined_object_resolver_producers_[key] = std::move(producer); @@ -338,8 +335,7 @@ utils::result schema::drop_table(const sql::connection &conn } template -utils::result query_object_resolver_producer:: -build_query(const sql::dialect &d) { +utils::result query_object_resolver_producer::build_query(const sql::dialect &d) { producer_creator pc(repo_, typeid(Type)); Type obj; access::process(pc, obj); @@ -354,6 +350,22 @@ build_query(const sql::dialect &d) { return utils::ok(result->compile(d)); } +template +utils::result query_joined_object_resolver_producer::build_query(const sql::dialect &d) { + // producer_creator pc(repo_, typeid(Type)); + // Type obj; + // access::process(pc, obj); + + select_query_builder qb(repo_); + const auto *join_column = table_[collection_name()]; + const auto result = qb.build(*join_column == utils::_); + if (!result) { + return utils::failure(result.err()); + } + + return utils::ok(result->compile(d)); +} + template void schema_observer::on_attach(const object::repository_node &node, const Type &/*prototype*/) const { primary_key_generator_finder finder; diff --git a/include/matador/sql/internal/object_resolver_producer.hpp b/include/matador/sql/internal/object_resolver_producer.hpp index 5094c1e..c2f0d34 100644 --- a/include/matador/sql/internal/object_resolver_producer.hpp +++ b/include/matador/sql/internal/object_resolver_producer.hpp @@ -32,7 +32,7 @@ class joined_object_resolver_producer { public: virtual ~joined_object_resolver_producer() = default; virtual utils::result build_query(const dialect& d) = 0; - virtual std::shared_ptr produce(statement&& stmt) = 0; + virtual std::shared_ptr produce(statement&& stmt) = 0; [[nodiscard]] const std::type_index& root_type() const; [[nodiscard]] const std::type_index& type() const; diff --git a/include/matador/sql/internal/query_result_impl.hpp b/include/matador/sql/internal/query_result_impl.hpp index 5dbf53a..cd8df39 100644 --- a/include/matador/sql/internal/query_result_impl.hpp +++ b/include/matador/sql/internal/query_result_impl.hpp @@ -130,16 +130,16 @@ void query_result_impl::on_belongs_to(const char*, Pointer& x, const utils::fore template void query_result_impl::on_has_one(const char*, object::object_ptr& x, const char *join_column, const utils::foreign_attributes& attr) { - const auto resolver = resolver_->collection_resolver(result_type_, join_column); + const auto resolver = resolver_->joined_object_resolver(result_type_, join_column); if (attr.fetch() == utils::fetch_type::Lazy) { - x = object::object_ptr(std::make_shared>(resolver, id_reader_.read(x, column_index_++))); + x.reset(std::make_shared>(resolver, utils::identifier{})); } else { auto obj = std::make_shared(); const auto ti = std::type_index(typeid(*x)); type_stack_.push(ti); access::process(*this, *obj); type_stack_.pop(); - x = object::object_ptr(std::make_shared>(resolver, obj)); + x.reset(std::make_shared>(resolver, obj)); } } diff --git a/include/matador/sql/producer_resolver_factory.hpp b/include/matador/sql/producer_resolver_factory.hpp index fa0a09a..58aa109 100644 --- a/include/matador/sql/producer_resolver_factory.hpp +++ b/include/matador/sql/producer_resolver_factory.hpp @@ -33,13 +33,13 @@ private: class producer_joined_object_resolver_factory : public object::joined_object_resolver_factory { public: - [[nodiscard]] std::shared_ptr acquire_joined_object_resolver(const std::type_index& root_type, + [[nodiscard]] std::shared_ptr acquire_joined_object_resolver(const std::type_index& root_type, const std::type_index& element_type, const std::string& collection_name) const override; - void register_joined_object_resolver(std::shared_ptr&& resolver) override; + void register_joined_object_resolver(std::shared_ptr&& resolver, const std::type_index& root_type, const std::string& join_column) override; private: - std::unordered_map, object::collection_composite_key_hash> resolvers_; + std::unordered_map, object::collection_composite_key_hash> resolvers_; }; } #endif //MATADOR_RESOLVER_FACTORY_HPP \ No newline at end of file diff --git a/include/matador/sql/resolver_service.hpp b/include/matador/sql/resolver_service.hpp index 0987830..eb3827c 100644 --- a/include/matador/sql/resolver_service.hpp +++ b/include/matador/sql/resolver_service.hpp @@ -17,18 +17,18 @@ public: } template - std::shared_ptr> joined_object_resolver(const std::type_index &root_type, const std::string &join_column) const { + std::shared_ptr> joined_object_resolver(const std::type_index &root_type, const std::string &join_column) const { return joined_object_resolver_factory_.resolver(root_type, join_column); } void register_object_resolver(std::shared_ptr &&resolver); void register_collection_resolver(std::shared_ptr&& resolver); - void register_joined_object_resolver(std::shared_ptr&& resolver); + void register_joined_object_resolver(std::shared_ptr&& resolver, const std::type_index& root_type, const std::string& join_column); private: - sql::producer_resolver_factory object_resolver_factory_; - sql::producer_collection_resolver_factory collection_resolver_factory_; - sql::producer_resolver_factory joined_object_resolver_factory_; + producer_resolver_factory object_resolver_factory_; + producer_collection_resolver_factory collection_resolver_factory_; + producer_joined_object_resolver_factory joined_object_resolver_factory_; }; } #endif // MATADOR_RESOLVER_SERVICE_HPP diff --git a/source/core/object/abstract_joined_resolver.cpp b/source/core/object/abstract_joined_resolver.cpp index c9f9b56..edf7782 100644 --- a/source/core/object/abstract_joined_resolver.cpp +++ b/source/core/object/abstract_joined_resolver.cpp @@ -1,4 +1,4 @@ -#include "matador/object/abstract_collection_resolver.hpp" +#include "matador/object/abstract_joined_resolver.hpp" namespace matador::object { const std::type_index& abstract_joined_resolver::root_type() const { diff --git a/source/orm/query/basic_schema.cpp b/source/orm/query/basic_schema.cpp index 0a29b43..fe94bde 100644 --- a/source/orm/query/basic_schema.cpp +++ b/source/orm/query/basic_schema.cpp @@ -145,7 +145,7 @@ const std::unordered_map, object::collection_composite_key_hash>& basic_schema::joined_object_resolver_producers() const { +const std::unordered_map, object::collection_composite_key_hash>& basic_schema::joined_object_resolver_producers() const { return joined_object_resolver_producers_; } diff --git a/source/orm/query/session.cpp b/source/orm/query/session.cpp index bdc2b2b..8e82f0d 100644 --- a/source/orm/query/session.cpp +++ b/source/orm/query/session.cpp @@ -93,12 +93,12 @@ session::session(session_context&& ctx, const basic_schema &scm) } } - for (const auto &pair : schema_.joined_object_resolver_producers()) { + for (const auto &pair : schema_.joined_object_resolver_producers()) { auto res = pair.second->build_query(dialect_).and_then([this](sql::query_context&& query_ctx) -> result { query_ctx.resolver = resolver_service_; return cache_.acquire(query_ctx); }).and_then([&pair, this](sql::statement&& stmt) -> result { - resolver_service_->register_collection_resolver(pair.second->produce(std::move(stmt), *resolver_service_)); + resolver_service_->register_joined_object_resolver(pair.second->produce(std::move(stmt)), pair.second->root_type(), pair.second->collection_name()); return ok(); }).or_else([](const auto &err) { diff --git a/source/orm/sql/producer_resolver_factory.cpp b/source/orm/sql/producer_resolver_factory.cpp index aff72db..3715fdc 100644 --- a/source/orm/sql/producer_resolver_factory.cpp +++ b/source/orm/sql/producer_resolver_factory.cpp @@ -26,9 +26,9 @@ void producer_collection_resolver_factory::register_collection_resolver(std::sha resolvers_[key] = std::move(resolver); } -std::shared_ptr producer_joined_object_resolver_factory::acquire_joined_object_resolver(const std::type_index& root_type, - const std::type_index& element_type, - const std::string& collection_name) const { +std::shared_ptr producer_joined_object_resolver_factory::acquire_joined_object_resolver(const std::type_index& root_type, + const std::type_index& element_type, + const std::string& collection_name) const { const object::collection_composite_key key{root_type, element_type, collection_name}; if (const auto it = resolvers_.find(key); it != resolvers_.end()) { return it->second; @@ -36,8 +36,8 @@ std::shared_ptr producer_joined_object_resolve return nullptr; } -void producer_joined_object_resolver_factory::register_joined_object_resolver(std::shared_ptr&& resolver) { - const object::collection_composite_key key{resolver->root_type(), resolver->type(), resolver->collection_name()}; +void producer_joined_object_resolver_factory::register_joined_object_resolver(std::shared_ptr&& resolver, const std::type_index& root_type, const std::string& join_column) { + const object::collection_composite_key key{root_type, resolver->type(), join_column}; resolvers_[key] = std::move(resolver); } } // namespace matador::sql diff --git a/source/orm/sql/resolver_service.cpp b/source/orm/sql/resolver_service.cpp index b3db96f..790b8c9 100644 --- a/source/orm/sql/resolver_service.cpp +++ b/source/orm/sql/resolver_service.cpp @@ -9,7 +9,7 @@ void resolver_service::register_collection_resolver(std::shared_ptr&& resolver) { - joined_object_resolver_factory_.register_object_resolver(std::move(resolver)); +void resolver_service::register_joined_object_resolver(std::shared_ptr&& resolver, const std::type_index& root_type, const std::string& join_column) { + joined_object_resolver_factory_.register_joined_object_resolver(std::move(resolver), root_type, join_column); } } // namespace matador::query \ No newline at end of file diff --git a/test/backends/SessionInsertHasOne.cpp b/test/backends/SessionInsertHasOne.cpp index 1ab5ba6..9f3a9b3 100644 --- a/test/backends/SessionInsertHasOne.cpp +++ b/test/backends/SessionInsertHasOne.cpp @@ -21,7 +21,7 @@ TEST_CASE_METHOD(SessionFixture, "Test insert object with has_one relation", "[s session ses({bus, connection::dns, 4}, schema); const auto u = make_object("user1", "password"); - const auto us = make_object("session1", u); + auto us = make_object("session1", u); REQUIRE(u.is_transient()); REQUIRE(us.is_transient()); @@ -31,5 +31,7 @@ TEST_CASE_METHOD(SessionFixture, "Test insert object with has_one relation", "[s const auto user_result = ses.find(u->id); REQUIRE(user_result.is_ok()); - REQUIRE(user_result.value()->session->session_token == "session1"); + // REQUIRE(user_result.value()->session->session_token == "session1"); + us = user_result.value()->session; + const auto token = us->session_token; } \ No newline at end of file