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*/) {}
|
||||
template<class Pointer>
|
||||
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>
|
||||
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:
|
||||
basic_schema& schema_;
|
||||
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]") {
|
||||
// auto result = repo.attach<author>("authors")
|
||||
// .and_then( [this] { return repo.attach<book>("books"); } )
|
||||
auto result = repo.attach<book>("books")
|
||||
.and_then( [this] { return repo.attach<author>("authors"); })
|
||||
.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);
|
||||
++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