diff --git a/include/matador/orm/session_query_builder.hpp b/include/matador/orm/session_query_builder.hpp index 64026e8..6f57f0b 100644 --- a/include/matador/orm/session_query_builder.hpp +++ b/include/matador/orm/session_query_builder.hpp @@ -97,8 +97,8 @@ public: return utils::failure(query_build_error::UnknownType); } pk_ = pk; - table_info_stack_.push(info.value()); - entity_query_data_ = { std::make_shared(info.value().get().name(), build_alias('t', ++table_index)) }; + table_info_stack_.push({info.value(), std::make_shared(info.value().get().name(), build_alias('t', ++table_index))}); + entity_query_data_ = { table_info_stack_.top().table }; processed_tables_.insert({info->get().name(), entity_query_data_.root_table}); try { access::process(*this, info->get().prototype()); @@ -118,8 +118,8 @@ public: return utils::failure(query_build_error::UnknownType); } pk_ = nullptr; - table_info_stack_.push(info.value()); - entity_query_data_ = { std::make_shared(info.value().get().name(), build_alias('t', ++table_index)) }; + table_info_stack_.push({info.value(), std::make_shared(info.value().get().name(), build_alias('t', ++table_index))}); + entity_query_data_ = { table_info_stack_.top().table }; processed_tables_.insert({info->get().name(), entity_query_data_.root_table}); try { access::process(*this, info->get().prototype()); @@ -142,7 +142,7 @@ public: if (pk_.is_null()) { entity_query_data_.pk_column_name = id; } else if (pk_.is_integer()) { - const auto t = std::make_shared(table_info_stack_.top().get().name()); + const auto t = std::make_shared(table_info_stack_.top().info.get().name()); auto v = *pk_.as(); auto c = sql::column{t, id, ""}; auto co = std::make_unique>(c, query::basic_condition::operand_type::EQUAL, v); @@ -180,16 +180,12 @@ public: throw query_builder_exception{query_build_error::UnknownType}; } - const auto curr = processed_tables_.find(table_info_stack_.top().get().name()); - if (curr == processed_tables_.end()) { - throw query_builder_exception{query_build_error::UnexpectedError}; - }; auto next = processed_tables_.find(info->get().name()); if (next != processed_tables_.end()) { return; } - table_info_stack_.push(info.value()); - next = processed_tables_.insert({info->get().name(), std::make_shared(info->get().name(), build_alias('t', ++table_index))}).first; + table_info_stack_.push({info.value(), std::make_shared(info->get().name(), build_alias('t', ++table_index))}); + next = processed_tables_.insert({info->get().name(), table_info_stack_.top().table}).first; typename ContainerType::value_type::value_type obj; access::process(*this , obj); table_info_stack_.pop(); @@ -200,7 +196,7 @@ public: } append_join( - sql::column{curr->second, table_info_stack_.top().get().definition().primary_key()->name()}, + sql::column{table_info_stack_.top().table, table_info_stack_.top().info.get().definition().primary_key()->name()}, sql::column{next->second, join_column} ); } @@ -216,7 +212,13 @@ public: if (!info) { throw query_builder_exception{query_build_error::UnknownType}; } - table_info_stack_.push(info.value()); + + auto next = processed_tables_.find(info->get().name()); + if (next != processed_tables_.end()) { + return; + } + table_info_stack_.push({info.value(), std::make_shared(info->get().name(), build_alias('t', ++table_index))}); + next = processed_tables_.insert({info->get().name(), table_info_stack_.top().table}).first; typename ContainerType::value_type::value_type obj; access::process(*this , obj); table_info_stack_.pop(); @@ -227,11 +229,11 @@ public: } append_join( - sql::column{std::make_shared(table_info_stack_.top().get().name()), table_info_stack_.top().get().definition().primary_key()->name()}, + sql::column{table_info_stack_.top().table, table_info_stack_.top().info.get().definition().primary_key()->name()}, sql::column{std::make_shared(id), join_column} ); append_join( - sql::column{std::make_shared(id), inverse_join_column}, + sql::column{next->second, inverse_join_column}, sql::column{std::make_shared(info->get().name()), pk->name()} ); } @@ -246,7 +248,12 @@ public: if (!info) { throw query_builder_exception{query_build_error::UnknownType}; } - table_info_stack_.push(info.value()); + + auto next = processed_tables_.find(info->get().name()); + if (next != processed_tables_.end()) { + return; + } + table_info_stack_.push({info.value(), std::make_shared(info->get().name(), build_alias('t', ++table_index))}); typename ContainerType::value_type::value_type obj; access::process(*this , obj); table_info_stack_.pop(); @@ -259,7 +266,7 @@ public: const auto join_columns = join_column_collector_.collect(); append_join( - sql::column{std::make_shared(table_info_stack_.top().get().name()), table_info_stack_.top().get().definition().primary_key()->name()}, + sql::column{table_info_stack_.top().table, table_info_stack_.top().info.get().definition().primary_key()->name()}, sql::column{std::make_shared(id), join_columns.inverse_join_column} ); append_join( @@ -278,7 +285,12 @@ private: private: utils::value pk_; - std::stack> table_info_stack_; + struct table_info { + std::reference_wrapper info; + std::shared_ptr table; + }; + + std::stack table_info_stack_; std::unordered_map> processed_tables_; const object::schema &schema_; entity_query_data entity_query_data_; @@ -288,24 +300,19 @@ private: }; template -void session_query_builder::on_foreign_object(const char *id, Pointer &, const utils::foreign_attributes &attr) -{ +void session_query_builder::on_foreign_object(const char *id, Pointer &, const utils::foreign_attributes &attr) { if (attr.fetch() == utils::fetch_type::EAGER) { const auto info = schema_.info(); if (!info) { throw query_builder_exception{query_build_error::UnknownType}; } - const auto curr = processed_tables_.find(table_info_stack_.top().get().name()); - if (curr == processed_tables_.end()) { - throw query_builder_exception{query_build_error::UnexpectedError}; - }; auto next = processed_tables_.find(info->get().name()); if (next != processed_tables_.end()) { return; } - next = processed_tables_.insert({info->get().name(), std::make_shared(info->get().name(), build_alias('t', ++table_index))}).first; - table_info_stack_.push(info.value()); + table_info_stack_.push({info.value(), std::make_shared(info->get().name(), build_alias('t', ++table_index))}); + next = processed_tables_.insert({info->get().name(), table_info_stack_.top().table}).first; typename Pointer::value_type obj; access::process(*this, obj); table_info_stack_.pop(); @@ -315,7 +322,7 @@ void session_query_builder::on_foreign_object(const char *id, Pointer &, const u throw query_builder_exception{query_build_error::MissingPrimaryKey}; } append_join( - sql::column{curr->second, id}, + sql::column{table_info_stack_.top().table, id}, sql::column{next->second, pk->name()} ); } else { diff --git a/source/orm/orm/session_query_builder.cpp b/source/orm/orm/session_query_builder.cpp index 43fde1b..1f43c60 100644 --- a/source/orm/orm/session_query_builder.cpp +++ b/source/orm/orm/session_query_builder.cpp @@ -16,7 +16,7 @@ void session_query_builder::on_revision(const char *id, unsigned long long &/*re } void session_query_builder::push(const std::string &column_name) { - const auto it = processed_tables_.find(table_info_stack_.top().get().name()); + const auto it = processed_tables_.find(table_info_stack_.top().info.get().name()); if (it == processed_tables_.end()) { throw query_builder_exception{query_build_error::UnexpectedError}; } diff --git a/test/orm/orm/SessionQueryBuilderTest.cpp b/test/orm/orm/SessionQueryBuilderTest.cpp index e2f97fa..d7c89d4 100644 --- a/test/orm/orm/SessionQueryBuilderTest.cpp +++ b/test/orm/orm/SessionQueryBuilderTest.cpp @@ -215,8 +215,8 @@ TEST_CASE("Create sql query data for entity with eager many to many", "[query][e } std::vector> expected_join_data { - { "recipe_ingredients", R"("ingredients"."id" = "recipe_ingredients"."ingredient_id")"}, - { "recipes", R"("recipe_ingredients"."recipe_id" = "recipes"."id")"} + { "recipe_ingredients", R"("t01"."id" = "recipe_ingredients"."ingredient_id")"}, + { "recipes", R"("t02"."recipe_id" = "recipes"."id")"} }; query_context qc;