fixed has many and belongs to eager loading via sql join

This commit is contained in:
2025-02-16 19:57:14 +01:00
parent ec96c15905
commit 66d5bc6c86
8 changed files with 157 additions and 84 deletions
+73 -9
View File
@@ -1,7 +1,10 @@
#include <iostream>
#include <catch2/catch_test_macros.hpp>
#include "matador/sql/backend_provider.hpp"
#include "matador/sql/connection.hpp"
#include "matador/sql/column.hpp"
#include "matador/sql/table.hpp"
#include "matador/query/query.hpp"
@@ -20,6 +23,7 @@
using namespace matador::object;
using namespace matador::orm;
using namespace matador::query;
using namespace matador::sql;
using namespace matador::test;
@@ -36,7 +40,7 @@ TEST_CASE("Create sql query data for entity with eager has one", "[query][entity
auto data = eqb.build<flight>(17U);
REQUIRE(data.is_ok());
REQUIRE(data->root_table_name == "flights");
REQUIRE(data->root_table->name == "flights");
REQUIRE(data->joins.size() == 1);
const std::vector<column> expected_columns {
{ "flights", "id", "c01" },
@@ -51,7 +55,7 @@ TEST_CASE("Create sql query data for entity with eager has one", "[query][entity
}
std::vector<std::pair<std::string, std::string>> expected_join_data {
{ "airplanes", R"("flights"."airplane_id" = "airplanes"."id")"}
{ "airplanes", R"("t01"."airplane_id" = "t02"."id")"}
};
query_context qc;
@@ -81,7 +85,7 @@ TEST_CASE("Create sql query data for entity with eager belongs to", "[query][ent
auto data = eqb.build<book>(17);
REQUIRE(data.is_ok());
REQUIRE(data->root_table_name == "books");
REQUIRE(data->root_table->name == "books");
REQUIRE(data->joins.size() == 1);
const std::vector<column> expected_columns {
{ "books", "id", "c01" },
@@ -100,7 +104,7 @@ TEST_CASE("Create sql query data for entity with eager belongs to", "[query][ent
}
std::vector<std::pair<std::string, std::string>> expected_join_data {
{ "authors", R"("books"."author_id" = "authors"."id")"}
{ "authors", R"("t01"."author_id" = "t02"."id")"}
};
query_context qc;
@@ -116,7 +120,7 @@ TEST_CASE("Create sql query data for entity with eager belongs to", "[query][ent
REQUIRE(cond == R"("books"."id" = 17)");
auto q = matador::query::query::select(data->columns)
.from(data->root_table_name);
.from(data->root_table->name);
for (auto &jd : data->joins) {
q.join_left(*jd.join_table)
@@ -143,7 +147,7 @@ TEST_CASE("Create sql query data for entity with eager has many belongs to", "[q
auto data = eqb.build<order>(17);
REQUIRE(data.is_ok());
REQUIRE(data->root_table_name == "orders");
REQUIRE(data->root_table->name == "orders");
REQUIRE(data->joins.size() == 1);
const std::vector<column> expected_columns = {
{ "orders", "order_id", "c01" },
@@ -168,7 +172,7 @@ TEST_CASE("Create sql query data for entity with eager has many belongs to", "[q
}
std::vector<std::pair<std::string, std::string>> expected_join_data {
{ "order_details", R"("orders"."order_id" = "order_details"."order_id")"}
{ "order_details", R"("t01"."order_id" = "t02"."order_id")"}
};
query_context qc;
@@ -197,7 +201,7 @@ TEST_CASE("Create sql query data for entity with eager many to many", "[query][e
auto data = eqb.build<ingredient>(17);
REQUIRE(data.is_ok());
REQUIRE(data->root_table_name == "ingredients");
REQUIRE(data->root_table->name == "ingredients");
REQUIRE(data->joins.size() == 2);
const std::vector<column> expected_columns {
{ "ingredients", "id", "c01" },
@@ -241,7 +245,7 @@ TEST_CASE("Create sql query data for entity with eager many to many (inverse par
auto data = eqb.build<course>(17);
REQUIRE(data.is_ok());
REQUIRE(data->root_table_name == "courses");
REQUIRE(data->root_table->name == "courses");
REQUIRE(data->joins.size() == 2);
const std::vector<column> expected_columns {
{ "courses", "id", "c01" },
@@ -270,4 +274,64 @@ TEST_CASE("Create sql query data for entity with eager many to many (inverse par
REQUIRE(data->where_clause);
auto cond = data->where_clause->evaluate(db.dialect(), qc);
REQUIRE(cond == R"("courses"."id" = 17)");
}
namespace matador::test::orm {
struct employee;
struct department {
unsigned int id{};
std::string name;
std::vector<object_ptr<employee>> employees;
template<typename Operator>
void process(Operator &op) {
namespace field = matador::access;
field::primary_key(op, "id", id);
field::attribute(op, "name", name, 63);
field::has_many(op, "employees", employees, "dep_id", utils::fetch_type::EAGER);
}
};
struct employee {
unsigned int id{};
std::string first_name;
std::string last_name;
object_ptr<department> dep;
template<typename Operator>
void process(Operator &op) {
namespace field = matador::access;
field::primary_key(op, "id", id);
field::attribute(op, "first_name", first_name, 63);
field::attribute(op, "last_name", last_name, 63);
field::belongs_to(op, "dep_id", dep, utils::fetch_type::EAGER);
}
};
}
TEST_CASE("Test eager relationship", "[session][eager]") {
using namespace matador::test;
backend_provider::instance().register_backend("noop", std::make_unique<orm::test_backend_service>());
connection db("noop://noop.db");
schema scm("noop");
auto result = scm.attach<orm::department>("departments")
.and_then( [&scm] { return scm.attach<orm::employee>("employees"); } );
session_query_builder eqb(scm);
auto data = eqb.build<orm::department>();
REQUIRE(data.is_ok());
auto ctx = query::select(data->columns)
.from(*data->root_table)
.join_left(data->joins)
.where(std::move(data->where_clause))
.order_by(column{data->root_table, data->pk_column_name})
.asc()
.str(db);
std::cout << ctx << std::endl;
}