From f9333158e287f7dc6e6625e880817dc524d7f1ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sascha=20K=C3=BChl?= Date: Sun, 1 Feb 2026 13:17:40 +0100 Subject: [PATCH] collection resolver progress --- backends/postgres/src/postgres_connection.cpp | 3 +- include/matador/object/collection_proxy.hpp | 2 +- include/matador/object/collection_utils.hpp | 20 +++ include/matador/query/basic_schema.hpp | 2 +- .../query/query_collection_resolver.hpp | 9 +- include/matador/query/schema.hpp | 156 +++++++++--------- .../matador/query/select_query_builder.hpp | 2 +- .../sql/internal/query_result_impl.hpp | 116 ++++++------- .../matador/sql/producer_resolver_factory.hpp | 30 +--- source/core/CMakeLists.txt | 2 + source/core/object/collection_utils.cpp | 22 +++ .../orm/query/internal/query_result_impl.cpp | 10 ++ source/orm/sql/connection.cpp | 7 +- .../internal/collection_resolver_producer.cpp | 3 + source/orm/sql/producer_resolver_factory.cpp | 4 +- test/backends/QueryTest.cpp | 24 ++- test/backends/SchemaTest.cpp | 6 +- test/backends/SessionTest.cpp | 14 +- test/models/order.hpp | 5 +- test/orm/backend/test_connection.cpp | 1 + test/orm/backend/test_statement.cpp | 1 + 21 files changed, 247 insertions(+), 192 deletions(-) create mode 100644 include/matador/object/collection_utils.hpp create mode 100644 source/core/object/collection_utils.cpp diff --git a/backends/postgres/src/postgres_connection.cpp b/backends/postgres/src/postgres_connection.cpp index 55bb4f2..4da9bba 100644 --- a/backends/postgres/src/postgres_connection.cpp +++ b/backends/postgres/src/postgres_connection.cpp @@ -129,8 +129,7 @@ std::string postgres_connection::generate_statement_name(const sql::query_contex return name.str(); } -utils::result, utils::error> postgres_connection::prepare( - const sql::query_context &context) { +utils::result, utils::error> postgres_connection::prepare(const sql::query_context &context) { auto statement_name = generate_statement_name(context); PGresult *result = PQprepare(conn_, statement_name.c_str(), context.sql.c_str(), static_cast(context.bind_vars.size()), nullptr); diff --git a/include/matador/object/collection_proxy.hpp b/include/matador/object/collection_proxy.hpp index 99f4615..d2e7023 100644 --- a/include/matador/object/collection_proxy.hpp +++ b/include/matador/object/collection_proxy.hpp @@ -24,7 +24,7 @@ public: // Eager collection_proxy(std::weak_ptr> resolver, std::vector items) - : items_(std::move(items)), resolver_(std::move(resolver)) {} + : loaded_{true}, items_(std::move(items)), resolver_(std::move(resolver)) {} // Transient explicit collection_proxy(std::vector items) diff --git a/include/matador/object/collection_utils.hpp b/include/matador/object/collection_utils.hpp new file mode 100644 index 0000000..ee97117 --- /dev/null +++ b/include/matador/object/collection_utils.hpp @@ -0,0 +1,20 @@ +#ifndef MATADOR_COLLECTION_UTILS_HPP +#define MATADOR_COLLECTION_UTILS_HPP + +#include +#include + +namespace matador::object { +struct collection_composite_key { + std::type_index root_type; + std::type_index type; + std::string name; + + bool operator==(const collection_composite_key& other) const; +}; + +struct collection_composite_key_hash { + std::size_t operator()(const collection_composite_key& k) const noexcept; +}; +} +#endif //MATADOR_COLLECTION_UTILS_HPP \ No newline at end of file diff --git a/include/matador/query/basic_schema.hpp b/include/matador/query/basic_schema.hpp index 968a907..b471a9d 100644 --- a/include/matador/query/basic_schema.hpp +++ b/include/matador/query/basic_schema.hpp @@ -62,7 +62,7 @@ protected: object::repository repo_; std::unordered_map schema_nodes_; std::unordered_map> resolver_producers_; - std::unordered_map, sql::composite_key_hash> collection_resolver_producers_; + std::unordered_map, object::collection_composite_key_hash> collection_resolver_producers_; }; } #endif //MATADOR_BASIC_SCHEMA_HPP \ No newline at end of file diff --git a/include/matador/query/query_collection_resolver.hpp b/include/matador/query/query_collection_resolver.hpp index 42fe2bf..6e854ff 100644 --- a/include/matador/query/query_collection_resolver.hpp +++ b/include/matador/query/query_collection_resolver.hpp @@ -15,15 +15,20 @@ namespace matador::query { template class query_collection_resolver : public object::collection_resolver { public: - explicit query_collection_resolver(sql::statement &&stmt, const std::type_index& root_type, std::string join_column) + explicit query_collection_resolver(sql::statement &&stmt, + const std::type_index& root_type, + std::string join_column, + const std::shared_ptr> &resolver) : object::collection_resolver(root_type, join_column) , stmt_(std::move(stmt)) + , resolver_(resolver) {} std::vector resolve(const utils::identifier &id) override; protected: sql::statement stmt_; std::type_index index{typeid(Type)}; + std::shared_ptr> resolver_; }; struct value_to_identifier{ @@ -76,7 +81,7 @@ std::vector query_collection_resolver::resolve(const utils::identifi } identifier_creator creator; r.at(0).process(creator); - const auto op = std::make_shared>(std::shared_ptr>{}, creator.visitor.id_); + const auto op = std::make_shared>(resolver_, creator.visitor.id_); out.emplace_back(op); } return out; diff --git a/include/matador/query/schema.hpp b/include/matador/query/schema.hpp index dd614f4..f3373d7 100644 --- a/include/matador/query/schema.hpp +++ b/include/matador/query/schema.hpp @@ -18,27 +18,6 @@ class executor; } namespace matador::query { - -template -class query_object_resolver_producer : public sql::object_resolver_producer { -public: - query_object_resolver_producer() = default; - query_object_resolver_producer(const basic_schema& repo, const table& tab, std::string pk_name) - : object_resolver_producer(typeid(Type)) - , repo_(repo) - , table_(tab) - , pk_name_(std::move(pk_name)) {} - - std::shared_ptr produce(sql::executor &exec) override { - return std::make_shared>(repo_, exec, table_, std::move(pk_name_)); - } - -private: - const basic_schema& repo_; - const table& table_; - std::string pk_name_; -}; - template class query_collection_resolver_producer : public sql::collection_resolver_producer { public: @@ -53,6 +32,7 @@ public: std::shared_ptr produce(sql::executor &exec) override { const auto *pk_column = table_[pk_name_]; const auto *join_column = table_[collection_name()]; + const auto object_resolver = exec.resolver()->object_resolver(); auto stmt = query::select({*pk_column}) .from(table_) @@ -63,7 +43,7 @@ public: return {}; } - return std::make_shared>(stmt.release(), root_type(), collection_name()); + return std::make_shared>(stmt.release(), root_type(), collection_name(), object_resolver); } private: @@ -72,6 +52,82 @@ private: std::string pk_name_; }; +class producer_creator final { +public: + producer_creator(basic_schema& schema, const std::type_index& root_type) + : schema_(schema) + , root_type_(root_type) + {} + + template + static void on_primary_key(const char * /*id*/, ValueType &/*value*/, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) {} + static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {} + template + static void on_attribute(const char * /*id*/, Type &/*value*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {} + template + static void on_belongs_to(const char * /*id*/, Pointer & /*x*/, const utils::foreign_attributes &/*attr*/) {} + template + static void on_has_one(const char * /*id*/, Pointer & /*x*/, const utils::foreign_attributes &/*attr*/) {} + template + static void on_has_many_to_many(const char *, ContainerType &, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes &/*attr*/) {} + template + static void on_has_many_to_many(const char *, ContainerType &, const utils::foreign_attributes &/*attr*/) {} + + template + void on_has_many(const char * /*id*/, CollectionType &/*cont*/, const char *join_column, const utils::foreign_attributes &/*attr*/, std::enable_if_t::value> * = nullptr) { + const auto it = schema_.find(typeid(typename CollectionType::value_type::value_type)); + if (it == schema_.end()) { + throw query_builder_exception{query_build_error::UnknownType}; + } + if (!it->second.node().info().has_primary_key()) { + throw query_builder_exception{query_build_error::MissingPrimaryKey}; + } + + 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(typename CollectionType::value_type), join_column}; + schema_.collection_resolver_producers_[key] = std::move(producer); + } + + template + void on_has_many(const char * /*id*/, CollectionType &/*cont*/, const char * /*join_column*/, const utils::foreign_attributes &/*attr*/, std::enable_if_t::value> * = nullptr) { + + } + +private: + basic_schema& schema_; + const std::type_index root_type_; +}; + + +template +class query_object_resolver_producer : public sql::object_resolver_producer { +public: + query_object_resolver_producer() = default; + query_object_resolver_producer(basic_schema& repo, const table& tab, std::string pk_name) + : object_resolver_producer(typeid(Type)) + , repo_(repo) + , table_(tab) + , pk_name_(std::move(pk_name)) {} + + std::shared_ptr produce(sql::executor &exec) override { + producer_creator pc(repo_, typeid(Type)); + Type obj; + access::process(pc, obj); + + return std::make_shared>(repo_, exec, table_, std::move(pk_name_)); + } + +private: + basic_schema& repo_; + const table& table_; + std::string pk_name_; +}; + class schema; using schema_ref = std::reference_wrapper; @@ -180,57 +236,6 @@ utils::result schema::drop_table(const sql::connection &conn return utils::failure(info.err()); } -class producer_creator final { -public: - producer_creator(basic_schema& schema, const std::type_index& root_type) - : schema_(schema) - , root_type_(root_type) - {} - - template - static void on_primary_key(const char * /*id*/, ValueType &/*value*/, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) {} - static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {} - template - static void on_attribute(const char * /*id*/, Type &/*value*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {} - template - static void on_belongs_to(const char * /*id*/, Pointer & /*x*/, const utils::foreign_attributes &/*attr*/) {} - template - static void on_has_one(const char * /*id*/, Pointer & /*x*/, const utils::foreign_attributes &/*attr*/) {} - template - static void on_has_many_to_many(const char *, ContainerType &, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes &/*attr*/) {} - template - static void on_has_many_to_many(const char *, ContainerType &, const utils::foreign_attributes &/*attr*/) {} - - template - void on_has_many(const char * /*id*/, CollectionType &/*cont*/, const char *join_column, const utils::foreign_attributes &/*attr*/, std::enable_if_t::value> * = nullptr) { - const auto it = schema_.find(typeid(typename CollectionType::value_type::value_type)); - if (it == schema_.end()) { - throw query_builder_exception{query_build_error::UnknownType}; - } - if (!it->second.node().info().has_primary_key()) { - throw query_builder_exception{query_build_error::MissingPrimaryKey}; - } - - auto producer = std::make_unique>( - schema_, - it->second.table(), - it->second.node().info().primary_key_attribute()->name(), - root_type_, - join_column); - const sql::composite_key key{root_type_, typeid(typename CollectionType::value_type), join_column}; - schema_.collection_resolver_producers_[key] = std::move(producer); - } - - template - void on_has_many(const char * /*id*/, CollectionType &/*cont*/, const char * /*join_column*/, const utils::foreign_attributes &/*attr*/, std::enable_if_t::value> * = nullptr) { - - } - -private: - basic_schema& schema_; - const std::type_index root_type_; -}; - template void schema_observer::on_attach(const object::repository_node &node, const Type &/*prototype*/) const { const auto it = schema_.insert_table(typeid(Type), node); @@ -241,11 +246,6 @@ void schema_observer::on_attach(const object::repository_node &node, const auto producer = std::make_unique>(schema_, it->second.table(), it->second.node().info().primary_key_attribute()->name()); schema_.resolver_producers_[typeid(Type)] = std::move(producer); - - producer_creator pc(schema_, typeid(Type)); - Type obj; - access::process(pc, obj); - } template diff --git a/include/matador/query/select_query_builder.hpp b/include/matador/query/select_query_builder.hpp index 1d33f2f..62532ee 100644 --- a/include/matador/query/select_query_builder.hpp +++ b/include/matador/query/select_query_builder.hpp @@ -149,7 +149,7 @@ public: } template - void on_has_many(const char * /*id*/, CollectionType &, const char *join_column, const utils::foreign_attributes &attr, std::enable_if_t::value> * = nullptr) { + void on_has_many(const char * /*id*/, CollectionType &, const char * /*join_column*/, const utils::foreign_attributes &/*attr*/, std::enable_if_t::value> * = nullptr) { } template diff --git a/include/matador/sql/internal/query_result_impl.hpp b/include/matador/sql/internal/query_result_impl.hpp index c616dcf..d9f7a17 100644 --- a/include/matador/sql/internal/query_result_impl.hpp +++ b/include/matador/sql/internal/query_result_impl.hpp @@ -23,6 +23,7 @@ #include #include #include +#include namespace matador::utils { class value; @@ -63,9 +64,9 @@ public: template static void on_has_many(const char * /*id*/, ContainerType &, const char * /*join_column*/, const utils::foreign_attributes &/*attr*/) {} template - static void on_has_many_to_many(const char *id, ContainerType &c, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes &/*attr*/) {} + static void on_has_many_to_many(const char * /*id*/, ContainerType &c, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes &/*attr*/) {} template - static void on_has_many_to_many(const char *id, ContainerType &c, const utils::foreign_attributes &/*attr*/) {} + static void on_has_many_to_many(const char * /*id*/, ContainerType &c, const utils::foreign_attributes &/*attr*/) {} private: size_t column_index_{}; @@ -126,32 +127,10 @@ public: } template - void on_has_many(const char * /*id*/, CollectionType &cont, const char *join_column, const utils::foreign_attributes &attr, std::enable_if_t::value> * = nullptr) { - using value_type = typename CollectionType::value_type::value_type; - auto object_resolver = resolver_->object_resolver(); - auto resolver = resolver_->collection_resolver(result_type_, join_column); - - std::vector objects; - if (attr.fetch() == utils::fetch_type::Lazy) { - cont.reset(std::make_shared>(resolver, current_pk_)); - } else { - const auto ti = std::type_index(typeid(value_type)); - auto obj = std::make_shared(); - type_stack_.push(ti); - access::process(*this, *obj); - type_stack_.pop(); - auto ptr = typename CollectionType::value_type(std::make_shared>(object_resolver, obj)); - const auto pk = ptr.primary_key(); - if (ptr.primary_key().is_valid()) { - cont.push_back(ptr); - } - } - // auto cp = std::make_shared>(resolver, objects); - // cont.reset(); - } + void on_has_many(const char * /*id*/, CollectionType &cont, const char *join_column, const utils::foreign_attributes &attr, std::enable_if_t::value> * = nullptr); template - void on_has_many(const char * /*id*/, CollectionType &, const char *join_column, const utils::foreign_attributes &attr, std::enable_if_t::value> * = nullptr) { + void on_has_many(const char * /*id*/, CollectionType &, const char * /*join_column*/, const utils::foreign_attributes &/*attr*/, std::enable_if_t::value> * = nullptr) { } template @@ -164,38 +143,8 @@ public: } template - bool fetch(Type &obj) { - bool first = true; - do { - if (auto fetched = reader_->fetch(); !fetched.is_ok() || !*fetched) { - return !first; - } - last_pk_ = current_pk_; - current_pk_ = discover_current_primary_key(obj); - if (pk_has_changed()) { - reader_->unshift(); - last_pk_.clear(); - current_pk_.clear(); - break; - } - first = false; - type_stack_.emplace(typeid(Type)); - column_index_ = reader_->start_column_index(); - access::process(*this, obj); - type_stack_.pop(); - } while (last_pk_ == current_pk_); - return true; - } - - bool fetch(record &rec) { - if (auto fetched = reader_->fetch(); !fetched.is_ok() || !*fetched) { - return false; - } - - column_index_ = reader_->start_column_index(); - access::process(*this, rec); - return true; - } + bool fetch(Type &obj); + bool fetch(record &rec); [[nodiscard]] const std::vector &prototype() const; @@ -234,8 +183,59 @@ protected: std::stack type_stack_; utils::identifier current_pk_{}; utils::identifier last_pk_{}; + std::unordered_set initialized_collections_; }; +template +void query_result_impl::on_has_many(const char *, CollectionType &cont, const char *join_column, const utils::foreign_attributes &attr, std::enable_if_t::value> *) { + using value_type = typename CollectionType::value_type::value_type; + auto object_resolver = resolver_->object_resolver(); + auto resolver = resolver_->collection_resolver(result_type_, join_column); + + if (attr.fetch() == utils::fetch_type::Lazy) { + cont.reset(std::make_shared>(resolver, current_pk_)); + } else { + if (initialized_collections_.insert({result_type_, typeid(typename CollectionType::value_type), std::string{join_column}}).second) { + cont.reset(std::make_shared>(resolver, std::vector())); + } + + const auto ti = std::type_index(typeid(value_type)); + type_stack_.push(ti); + auto obj = std::make_shared(); + access::process(*this, *obj); + type_stack_.pop(); + auto ptr = typename CollectionType::value_type(std::make_shared>(object_resolver, obj)); + const auto pk = ptr.primary_key(); + if (ptr.primary_key().is_valid()) { + cont.push_back(ptr); + } + } +} + +template +bool query_result_impl::fetch(Type &obj) { + bool first = true; + do { + if (auto fetched = reader_->fetch(); !fetched.is_ok() || !*fetched) { + return !first; + } + last_pk_ = current_pk_; + current_pk_ = discover_current_primary_key(obj); + if (pk_has_changed()) { + reader_->unshift(); + last_pk_.clear(); + current_pk_.clear(); + break; + } + first = false; + type_stack_.emplace(typeid(Type)); + column_index_ = reader_->start_column_index(); + access::process(*this, obj); + type_stack_.pop(); + } while (last_pk_ == current_pk_); + return true; +} + namespace detail { template void pk_reader::on_primary_key(const char *id, ValueType &value, const utils::primary_key_attribute& attr) { diff --git a/include/matador/sql/producer_resolver_factory.hpp b/include/matador/sql/producer_resolver_factory.hpp index 4889dba..6fc2cce 100644 --- a/include/matador/sql/producer_resolver_factory.hpp +++ b/include/matador/sql/producer_resolver_factory.hpp @@ -6,6 +6,7 @@ #include "matador/object/abstract_collection_resolver.hpp" #include "matador/object/object_resolver_factory.hpp" #include "matador/object/collection_resolver_factory.hpp" +#include "matador/object/collection_utils.hpp" namespace matador::sql { class executor; @@ -19,33 +20,6 @@ private: std::unordered_map> resolvers_; }; -struct composite_key { - std::type_index root_type; - std::type_index type; - std::string name; - - bool operator==(const composite_key& other) const { - return root_type == other.root_type && - type == other.type && - name == other.name; - } -}; - -struct composite_key_hash { - std::size_t operator()(const composite_key& k) const noexcept { - const std::size_t h1 = std::hash{}(k.root_type); - const std::size_t h2 = std::hash{}(k.type); - const std::size_t h3 = std::hash{}(k.name); - - // Klassische Hash-Kombination (Boost-Style) - std::size_t seed = h1; - seed ^= h2 + 0x9e3779b9 + (seed << 6) + (seed >> 2); - seed ^= h3 + 0x9e3779b9 + (seed << 6) + (seed >> 2); - - return seed; - } -}; - class producer_collection_resolver_factory : public object::collection_resolver_factory { public: [[nodiscard]] std::shared_ptr acquire_collection_resolver(const std::type_index& root_type, @@ -54,7 +28,7 @@ public: void register_collection_resolver(std::shared_ptr&& resolver) override; private: - std::unordered_map, 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/source/core/CMakeLists.txt b/source/core/CMakeLists.txt index 732f883..b4d5b47 100644 --- a/source/core/CMakeLists.txt +++ b/source/core/CMakeLists.txt @@ -120,6 +120,8 @@ add_library(matador-core STATIC utils/uuid.cpp utils/value.cpp utils/version.cpp + ../../include/matador/object/collection_utils.hpp + object/collection_utils.cpp ) target_link_libraries(matador-core ${CMAKE_DL_LIBS}) diff --git a/source/core/object/collection_utils.cpp b/source/core/object/collection_utils.cpp new file mode 100644 index 0000000..79d210b --- /dev/null +++ b/source/core/object/collection_utils.cpp @@ -0,0 +1,22 @@ +#include "matador/object/collection_utils.hpp" + +namespace matador::object { +bool collection_composite_key::operator==(const collection_composite_key &other) const { + return root_type == other.root_type && + type == other.type && + name == other.name; +} + +std::size_t collection_composite_key_hash::operator()(const collection_composite_key &k) const noexcept { + const std::size_t h1 = std::hash{}(k.root_type); + const std::size_t h2 = std::hash{}(k.type); + const std::size_t h3 = std::hash{}(k.name); + + // Klassische Hash-Kombination (Boost-Style) + std::size_t seed = h1; + seed ^= h2 + 0x9e3779b9 + (seed << 6) + (seed >> 2); + seed ^= h3 + 0x9e3779b9 + (seed << 6) + (seed >> 2); + + return seed; +} +} diff --git a/source/orm/query/internal/query_result_impl.cpp b/source/orm/query/internal/query_result_impl.cpp index 531e26a..983db29 100644 --- a/source/orm/query/internal/query_result_impl.cpp +++ b/source/orm/query/internal/query_result_impl.cpp @@ -39,6 +39,16 @@ query_result_impl::on_attribute(const char *id, utils::value &val, const utils:: reader_->read_value(id, column_index_++, val, attr.size()); } +bool query_result_impl::fetch(record &rec) { + if (auto fetched = reader_->fetch(); !fetched.is_ok() || !*fetched) { + return false; + } + + column_index_ = reader_->start_column_index(); + access::process(*this, rec); + return true; +} + const std::vector &query_result_impl::prototype() const { return prototype_; } diff --git a/source/orm/sql/connection.cpp b/source/orm/sql/connection.cpp index c8b94d8..4861b42 100644 --- a/source/orm/sql/connection.cpp +++ b/source/orm/sql/connection.cpp @@ -244,7 +244,12 @@ utils::result, utils::error> connection::perform const auto rit = std::find_if( std::begin(*result), std::end(*result), - [&col](const auto &value) { return value.name() == col.name(); } + [&col, &ctx](const auto &value) { + if (ctx.table_name.empty()) { + return value.name() == col.name(); + } + return value.name() == col.name() || ctx.table_name + "." + value.name() == col.name(); + } ); if (col.type() == utils::basic_type::Null && rit != result->end()) { const_cast(col).change_type(rit->type()); diff --git a/source/orm/sql/internal/collection_resolver_producer.cpp b/source/orm/sql/internal/collection_resolver_producer.cpp index a2f57aa..6671315 100644 --- a/source/orm/sql/internal/collection_resolver_producer.cpp +++ b/source/orm/sql/internal/collection_resolver_producer.cpp @@ -4,12 +4,15 @@ namespace matador::sql { const std::type_index& collection_resolver_producer::root_type() const { return root_type_; } + const std::type_index& collection_resolver_producer::type() const { return type_; } + const std::string& collection_resolver_producer::collection_name() const { return collection_name_; } + collection_resolver_producer::collection_resolver_producer(const std::type_index& root_type, const std::type_index& type, std::string collection_name) diff --git a/source/orm/sql/producer_resolver_factory.cpp b/source/orm/sql/producer_resolver_factory.cpp index 92f3323..139fa8d 100644 --- a/source/orm/sql/producer_resolver_factory.cpp +++ b/source/orm/sql/producer_resolver_factory.cpp @@ -15,14 +15,14 @@ std::shared_ptr producer_collection_resolver_factory::acquire_collection_resolver(const std::type_index& root_type, const std::type_index& element_type, const std::string& collection_name) const { - const composite_key key{root_type, element_type, collection_name}; + 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; } return nullptr; } void producer_collection_resolver_factory::register_collection_resolver(std::shared_ptr&& resolver) { - const composite_key key{resolver->root_type(), resolver->type(), resolver->collection_name()}; + const object::collection_composite_key key{resolver->root_type(), resolver->type(), resolver->collection_name()}; resolvers_[key] = std::move(resolver); } } // namespace matador::sql diff --git a/test/backends/QueryTest.cpp b/test/backends/QueryTest.cpp index 9c9472b..69104bb 100644 --- a/test/backends/QueryTest.cpp +++ b/test/backends/QueryTest.cpp @@ -588,10 +588,8 @@ TEST_CASE_METHOD(QueryFixture, "Test load entity with eager has many relation", } TEST_CASE_METHOD(QueryFixture, "Test load entity with lazy has many relation", "[query][has_many][lazy]") { - // auto result = repo.attach("authors") - // .and_then( [this] { return repo.attach("books"); } ) - auto result = repo.attach("books") - .and_then( [this] { return repo.attach("authors"); } ) + auto result = repo.attach("authors") + .and_then( [this] { return repo.attach("books"); } ) .and_then([this] { return repo.create(db); } ); @@ -662,6 +660,13 @@ TEST_CASE_METHOD(QueryFixture, "Test load entity with lazy has many relation", " REQUIRE(a->year_of_birth == authors.at(index)->year_of_birth); REQUIRE(a->distinguished == authors.at(index)->distinguished); REQUIRE(!a->books.empty()); + for (const auto& b : a->books) { + const auto title = b->title; + // REQUIRE(b->id == books.at(index)->id); + // REQUIRE(b->title == books.at(index)->title); + // REQUIRE(b->author_id == books.at(index)->author_id); + // REQUIRE(b->published_in == books.at(index)->published_in); + } ++index; } } @@ -735,11 +740,12 @@ TEST_CASE_METHOD(QueryFixture, "Test load entity with lazy belongs to relation", } TEST_CASE_METHOD(QueryFixture, "Test load entity with eager belongs to relation", "[query][belongs_to][eager]") { - auto result = repo.attach("authors") - .and_then( [this] { return repo.attach("books"); } ) - .and_then([this] { - return repo.create(db); - } ); + // auto result = repo.attach("authors") + // .and_then( [this] { return repo.attach("books"); } ) + auto result = repo.attach("books") + .and_then( [this] { return repo.attach("authors"); }) + .and_then([this] { return repo.create(db); }); + REQUIRE(result.is_ok()); const std::vector authors { object_ptr{std::make_shared(1, "Michael", "Crichton", "23.10.1942", 1975, true)}, diff --git a/test/backends/SchemaTest.cpp b/test/backends/SchemaTest.cpp index 10a3d86..560ee56 100644 --- a/test/backends/SchemaTest.cpp +++ b/test/backends/SchemaTest.cpp @@ -17,8 +17,10 @@ TEST_CASE_METHOD(SchemaFixture, "Test schema one-two-many", "[schema][one-to-man using namespace matador::test; query::schema repo; - auto result = repo.attach("departments") - .and_then([&repo] { return repo.attach("employees"); }); + // auto result = repo.attach("departments") + // .and_then([&repo] { return repo.attach("employees"); }); + auto result = repo.attach("employees") + .and_then([&repo] { return repo.attach("departments"); }); REQUIRE(result); auto conn = pool.acquire(); diff --git a/test/backends/SessionTest.cpp b/test/backends/SessionTest.cpp index a713200..f5873e6 100644 --- a/test/backends/SessionTest.cpp +++ b/test/backends/SessionTest.cpp @@ -165,9 +165,12 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects", "[session][f } TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-many lazy relation", "[session][find][one-to-many][eager]") { - auto result = schema.attach("authors") - .and_then( [this] { return schema.attach("books"); } ) + // auto result = schema.attach("authors") + // .and_then( [this] { return schema.attach("books"); } ) + auto result = schema.attach("books") + .and_then( [this] { return schema.attach("authors"); } ) .and_then([this] { return schema.create(db); } ); + REQUIRE(result.is_ok()); schema.initialize_executor(ses); std::vector authors { @@ -217,11 +220,14 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-ma } TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-many eager relation", "[session][find][one-to-many][eager]") { - auto result = schema.attach("departments") - .and_then( [this] { return schema.attach("employees"); } ) + // auto result = repo.attach("departments") + // .and_then([this] { return repo.attach("employees"); }) + auto result = schema.attach("employees") + .and_then([this] { return schema.attach("departments"); }) .and_then([this] { return schema.create(db); } ); + REQUIRE(result.is_ok()); std::vector> departments; departments.emplace_back(new department{1, "Insurance"}); diff --git a/test/models/order.hpp b/test/models/order.hpp index 2fbfc0d..005669a 100644 --- a/test/models/order.hpp +++ b/test/models/order.hpp @@ -6,8 +6,7 @@ #include "matador/utils/access.hpp" #include "matador/object/object_ptr.hpp" - -#include +#include "matador/object/collection.hpp" namespace matador::test { struct order { @@ -23,7 +22,7 @@ struct order { std::string ship_region; std::string ship_postal_code; std::string ship_country; - std::vector > order_details_; + object::collection > order_details_; template void process(Operator &op) { diff --git a/test/orm/backend/test_connection.cpp b/test/orm/backend/test_connection.cpp index 109683b..12915fe 100644 --- a/test/orm/backend/test_connection.cpp +++ b/test/orm/backend/test_connection.cpp @@ -52,6 +52,7 @@ utils::result, utils::error> test_connec return utils::ok(std::make_unique(std::make_unique(), context.prototype, context.resolver, + context.result_type, context.prototype.size())); } diff --git a/test/orm/backend/test_statement.cpp b/test/orm/backend/test_statement.cpp index 49a04b7..8a63b50 100644 --- a/test/orm/backend/test_statement.cpp +++ b/test/orm/backend/test_statement.cpp @@ -22,6 +22,7 @@ utils::result, utils::error> test_statem return utils::ok(std::make_unique(std::make_unique(), query_.prototype, query_.resolver, + query_.result_type, query_.prototype.size())); }