has many to many collection resolver progress
This commit is contained in:
parent
b2d5db2702
commit
73abd61eba
|
|
@ -69,10 +69,6 @@ public:
|
||||||
static void on_belongs_to(const char * /*id*/, Pointer & /*x*/, const utils::foreign_attributes &/*attr*/) {}
|
static void on_belongs_to(const char * /*id*/, Pointer & /*x*/, const utils::foreign_attributes &/*attr*/) {}
|
||||||
template<class Pointer>
|
template<class Pointer>
|
||||||
static void on_has_one(const char * /*id*/, Pointer & /*x*/, const utils::foreign_attributes &/*attr*/) {}
|
static void on_has_one(const char * /*id*/, Pointer & /*x*/, const utils::foreign_attributes &/*attr*/) {}
|
||||||
template<class ContainerType>
|
|
||||||
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<class ContainerType>
|
|
||||||
static void on_has_many_to_many(const char *, ContainerType &, const utils::foreign_attributes &/*attr*/) {}
|
|
||||||
|
|
||||||
template<class CollectionType>
|
template<class CollectionType>
|
||||||
void on_has_many(const char * /*id*/, CollectionType &/*cont*/, const char *join_column, const utils::foreign_attributes &/*attr*/, std::enable_if_t<object::is_object_ptr<typename CollectionType::value_type>::value> * = nullptr) {
|
void on_has_many(const char * /*id*/, CollectionType &/*cont*/, const char *join_column, const utils::foreign_attributes &/*attr*/, std::enable_if_t<object::is_object_ptr<typename CollectionType::value_type>::value> * = nullptr) {
|
||||||
|
|
@ -99,6 +95,20 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class CollectionType>
|
||||||
|
void on_has_many_to_many(const char *, CollectionType &, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes &/*attr*/) {
|
||||||
|
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};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
template<class ContainerType>
|
||||||
|
static void on_has_many_to_many(const char *, ContainerType &, const utils::foreign_attributes &/*attr*/) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
basic_schema& schema_;
|
basic_schema& schema_;
|
||||||
const std::type_index root_type_;
|
const std::type_index root_type_;
|
||||||
|
|
|
||||||
|
|
@ -740,8 +740,6 @@ 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]") {
|
TEST_CASE_METHOD(QueryFixture, "Test load entity with eager belongs to relation", "[query][belongs_to][eager]") {
|
||||||
// auto result = repo.attach<author>("authors")
|
|
||||||
// .and_then( [this] { return repo.attach<book>("books"); } )
|
|
||||||
auto result = repo.attach<book>("books")
|
auto result = repo.attach<book>("books")
|
||||||
.and_then( [this] { return repo.attach<author>("authors"); })
|
.and_then( [this] { return repo.attach<author>("authors"); })
|
||||||
.and_then([this] { return repo.create(db); });
|
.and_then([this] { return repo.create(db); });
|
||||||
|
|
@ -816,4 +814,84 @@ TEST_CASE_METHOD(QueryFixture, "Test load entity with eager belongs to relation"
|
||||||
REQUIRE(b->published_in == books.at(index)->published_in);
|
REQUIRE(b->published_in == books.at(index)->published_in);
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE_METHOD(QueryFixture, "Test load entity with eager has many to many relation", "[query][has_many_to_many][eager]") {
|
||||||
|
auto result = repo.attach<ingredient>("ingredients")
|
||||||
|
.and_then( [this] { return repo.attach<recipe>("recipes"); } )
|
||||||
|
.and_then([this] {return repo.create(db); });
|
||||||
|
|
||||||
|
REQUIRE(db.exists(RECIPE.table_name()));
|
||||||
|
REQUIRE(db.exists(INGREDIENT.table_name()));
|
||||||
|
REQUIRE(db.exists(RECIPE_INGREDIENT.table_name()));
|
||||||
|
|
||||||
|
std::vector<ingredient> ingredients {
|
||||||
|
{1, "Apple"},
|
||||||
|
{2, "Strawberry"},
|
||||||
|
{3, "Pineapple"},
|
||||||
|
{4, "Sugar"},
|
||||||
|
{5, "Flour"},
|
||||||
|
{6, "Butter"},
|
||||||
|
{7, "Beans"}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto &i: ingredients) {
|
||||||
|
auto res = query::insert()
|
||||||
|
.into(INGREDIENT, {INGREDIENT.id, INGREDIENT.name})
|
||||||
|
.values(i)
|
||||||
|
.execute(db);
|
||||||
|
REQUIRE(res.is_ok());
|
||||||
|
REQUIRE(*res == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<recipe> recipes{
|
||||||
|
{7, "Apple Crumble"},
|
||||||
|
{8, "Beans Chili"},
|
||||||
|
{9, "Fruit Salad"}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto &r: recipes) {
|
||||||
|
auto res = query::insert()
|
||||||
|
.into(RECIPE, {RECIPE.id, RECIPE.name})
|
||||||
|
.values(r)
|
||||||
|
.execute(db);
|
||||||
|
REQUIRE(res.is_ok());
|
||||||
|
REQUIRE(*res == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<int, int>> recipe_ingredients {
|
||||||
|
{ 7, 1 },
|
||||||
|
{ 7, 4 },
|
||||||
|
{ 7, 5 },
|
||||||
|
{ 8, 6 },
|
||||||
|
{ 8, 7 },
|
||||||
|
{ 9, 1 },
|
||||||
|
{ 9, 2 },
|
||||||
|
{ 9, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto & [recipe_id, ingredient_id]: recipe_ingredients) {
|
||||||
|
auto res = query::insert()
|
||||||
|
.into(RECIPE_INGREDIENT, {RECIPE_INGREDIENT.recipe_id, RECIPE_INGREDIENT.ingredient_id})
|
||||||
|
.values({recipe_id, ingredient_id})
|
||||||
|
.execute(db);
|
||||||
|
REQUIRE(res.is_ok());
|
||||||
|
REQUIRE(*res == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto r = RECIPE.as("r");
|
||||||
|
const auto ri= RECIPE_INGREDIENT.as("ri");
|
||||||
|
const auto i = INGREDIENT.as("i");
|
||||||
|
|
||||||
|
auto ingredients_result = query::select({r.id, r.name, ri.ingredient_id, i.name})
|
||||||
|
.from(r)
|
||||||
|
.join_left(ri).on(r.id == ri.recipe_id)
|
||||||
|
.join_left(i).on(ri.ingredient_id == i.id)
|
||||||
|
.order_by({i.id, r.id}).asc()
|
||||||
|
.fetch_all<ingredient>(db);
|
||||||
|
REQUIRE(ingredients_result.is_ok());
|
||||||
|
|
||||||
|
for (const auto &ing : *ingredients_result) {
|
||||||
|
REQUIRE(!ing->recipes.empty());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue