diff --git a/test/backends/SessionInsertHasManyToManyTest.cpp b/test/backends/SessionInsertHasManyToManyTest.cpp index 9f0d610..61d4f49 100644 --- a/test/backends/SessionInsertHasManyToManyTest.cpp +++ b/test/backends/SessionInsertHasManyToManyTest.cpp @@ -14,6 +14,63 @@ using namespace matador::object; using namespace matador::test; using namespace matador::query::meta; +namespace matador::test { +template +struct recipe_pk_generator; + +template +struct ingredient_pk_generator { + unsigned int id{}; + std::string name; + collection>> recipes{}; + + ingredient_pk_generator() = default; + + explicit ingredient_pk_generator(std::string name) + : name(std::move(name)) { + } + + template + void process(Operator &op) { + namespace field = matador::access; + field::primary_key(op, "id", id, PkAttribute); + field::attribute(op, "name", name, UniqueVarChar255); + field::has_many_to_many(op, "recipe_ingredients", recipes, "ingredient_id", "recipe_id", utils::CascadeAllFetchEager); + } +}; + +template +struct recipe_pk_generator { + unsigned int id{}; + std::string name; + collection>> ingredients{}; + + recipe_pk_generator() = default; + explicit recipe_pk_generator(std::string name) + : name(std::move(name)) { + } + recipe_pk_generator(std::string name, std::vector>> ings) + : name(std::move(name)) + , ingredients(std::move(ings)){ + } + + template + void process(Operator &op) { + namespace field = matador::access; + field::primary_key(op, "id", id, PkAttribute); + field::attribute(op, "name", name, UniqueVarChar255); + field::has_many_to_many(op, "recipe_ingredients", ingredients, utils::CascadeAllFetchLazy); + } +}; + +using ingredient_identity = ingredient_pk_generator; +using ingredient_table = ingredient_pk_generator; +using ingredient_sequence = ingredient_pk_generator; +using recipe_identity = recipe_pk_generator; +using recipe_table = recipe_pk_generator; +using recipe_sequence = recipe_pk_generator; +} + TEST_CASE_METHOD(SessionFixture, "Test insert object with has many to many relation", "[session][insert][has_many_to_many]") { auto result = schema.attach("recipes") .and_then( [this] { return schema.attach("ingredients"); } ) @@ -38,19 +95,126 @@ TEST_CASE_METHOD(SessionFixture, "Test insert object with has many to many relat }; for (auto &r: recipes) { + REQUIRE(r.is_transient()); auto res = ses.insert(r); REQUIRE(res.is_ok()); + REQUIRE(res->is_persistent()); } auto recipe_result = ses.find(1); - // auto recipe_result = ses.find(RECIPE.id == 1); REQUIRE(recipe_result.is_ok()); + REQUIRE(recipe_result->is_persistent()); + REQUIRE(recipe_result.value()->ingredients.size() == 3); +} - // auto r = *recipe_result->begin(); - auto r = *recipe_result; - std::cout << r->name << " (ingredients: " << r->ingredients.size() << ")" << std::endl; - // REQUIRE(r->name != ""); - for (const auto &ingr: r->ingredients) { - std::cout << " " << ingr->name << std::endl; +TEST_CASE_METHOD(SessionFixture, "Test insert object with has many to many relation identity", "[session][insert][identity][has_many_to_many]") { + auto result = schema.attach("recipes") + .and_then( [this] { return schema.attach("ingredients"); } ) + .and_then([this] { return schema.create(db); } ); + + query::session ses({bus, connection::dns, 4}, schema); + + std::vector ingredients { + make_object("Apple"), + make_object("Strawberry"), + make_object("Pineapple"), + make_object("Sugar"), + make_object("Flour"), + make_object("Butter"), + make_object("Beans") + }; + + std::vector recipes { + make_object("Apple Pie", std::vector{ingredients[0], ingredients[3], ingredients[4]}), + make_object("Strawberry Cake", std::vector{ingredients[5], ingredients[6]}), + make_object("Pineapple Pie", std::vector{ingredients[0], ingredients[1], ingredients[2]}) + }; + + for (auto &r: recipes) { + REQUIRE(r.is_transient()); + auto res = ses.insert(r); + REQUIRE(res.is_ok()); + REQUIRE(res->is_persistent()); } -} \ No newline at end of file + + auto recipe_result = ses.find(1); + REQUIRE(recipe_result.is_ok()); + REQUIRE(recipe_result->is_persistent()); + REQUIRE(recipe_result.value()->ingredients.size() == 3); +} + +TEST_CASE_METHOD(SessionFixture, "Test insert object with has many to many relation table sequence", "[session][insert][table_sequence][has_many_to_many]") { + auto result = schema.attach("recipes") + .and_then( [this] { return schema.attach("ingredients"); } ) + .and_then([this] { return schema.create(db); } ); + + query::session ses({bus, connection::dns, 4}, schema); + + std::vector ingredients { + make_object("Apple"), + make_object("Strawberry"), + make_object("Pineapple"), + make_object("Sugar"), + make_object("Flour"), + make_object("Butter"), + make_object("Beans") + }; + + std::vector recipes { + make_object("Apple Pie", std::vector{ingredients[0], ingredients[3], ingredients[4]}), + make_object("Strawberry Cake", std::vector{ingredients[5], ingredients[6]}), + make_object("Pineapple Pie", std::vector{ingredients[0], ingredients[1], ingredients[2]}) + }; + + for (auto &r: recipes) { + REQUIRE(r.is_transient()); + auto res = ses.insert(r); + REQUIRE(res.is_ok()); + REQUIRE(res->is_persistent()); + } + + auto recipe_result = ses.find(1); + REQUIRE(recipe_result.is_ok()); + REQUIRE(recipe_result->is_persistent()); + REQUIRE(recipe_result.value()->ingredients.size() == 3); +} + +TEST_CASE_METHOD(SessionFixture, "Test insert object with has many to many relation sequence", "[session][insert][sequence][has_many_to_many]") { + auto result = schema.attach("recipes") + .and_then( [this] { return schema.attach("ingredients"); } ) + .and_then([this] { return schema.create(db); } ); + + query::session ses({bus, connection::dns, 4}, schema); + + std::vector ingredients { + make_object("Apple"), + make_object("Strawberry"), + make_object("Pineapple"), + make_object("Sugar"), + make_object("Flour"), + make_object("Butter"), + make_object("Beans") + }; + + std::vector recipes { + make_object("Apple Pie", std::vector{ingredients[0], ingredients[3], ingredients[4]}), + make_object("Strawberry Cake", std::vector{ingredients[5], ingredients[6]}), + make_object("Pineapple Pie", std::vector{ingredients[0], ingredients[1], ingredients[2]}) + }; + + for (auto &r: recipes) { + REQUIRE(r.is_transient()); + auto res = ses.insert(r); + REQUIRE(res.is_ok()); + REQUIRE(res->is_persistent()); + } + + auto recipe_result = ses.find(1); + REQUIRE(recipe_result.is_ok()); + REQUIRE(recipe_result->is_persistent()); + REQUIRE(recipe_result.value()->ingredients.size() == 3); + + const auto ing_result = ses.find(ingredients[0]->id); + REQUIRE(ing_result.is_ok()); + REQUIRE(ing_result.value()->recipes.size() == 2); +}