added belongs to many eager test loading via sql join (progress)

This commit is contained in:
Sascha Kühl 2025-02-17 22:16:03 +01:00
parent 5109659882
commit 901d9c071a
5 changed files with 64 additions and 15 deletions

View File

@ -89,11 +89,6 @@ utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> postgres_co
return utils::failure(make_error(sql::error_code::FETCH_FAILED, res, conn_, "Failed to fetch", context.sql)); return utils::failure(make_error(sql::error_code::FETCH_FAILED, res, conn_, "Failed to fetch", context.sql));
} }
// const auto is_unknown = std::all_of( context.prototype.begin(), context.prototype.end(), [](const object::attribute_definition &a) {return a.is_null();} );
// if (!is_unknown) {
// return utils::ok(std::make_unique<sql::query_result_impl>(std::make_unique<postgres_result_reader>(res), context.prototype));
// }
std::vector<object::attribute_definition> prototype = context.prototype; std::vector<object::attribute_definition> prototype = context.prototype;
const int num_col = PQnfields(res); const int num_col = PQnfields(res);

View File

@ -100,13 +100,13 @@ void postgres_result_reader::read_value(const char * /*id*/, const size_t index,
} }
} }
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, time &value) { void postgres_result_reader::read_value(const char * /*id*/, const size_t index, time &/*value*/) {
// if (const auto val = column(index); strlen(val) > 0) { // if (const auto val = column(index); strlen(val) > 0) {
// value = time::parse(val, "%Y-%m-%d %T.%f"); // value = time::parse(val, "%Y-%m-%d %T.%f");
// } // }
} }
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, date &value) { void postgres_result_reader::read_value(const char * /*id*/, const size_t index, date &/*value*/) {
// if (const auto val = column(index); strlen(val) > 0) { // if (const auto val = column(index); strlen(val) > 0) {
// value.set(val, matador::utils::date_format::ISO8601); // value.set(val, matador::utils::date_format::ISO8601);
// } // }

View File

@ -5,6 +5,7 @@
#include "models/airplane.hpp" #include "models/airplane.hpp"
#include "models/author.hpp" #include "models/author.hpp"
#include "models/book.hpp" #include "models/book.hpp"
#include "models/department.hpp"
#include "models/flight.hpp" #include "models/flight.hpp"
#include <iostream> #include <iostream>
@ -94,7 +95,7 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects", "[session][f
} }
} }
TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-many relation", "[session][find][one-to-many]") { TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-many lazy relation", "[session][find][one-to-many][eager]") {
auto result = ses.attach<author>("authors") auto result = ses.attach<author>("authors")
.and_then( [this] { return ses.attach<book>("books"); } ) .and_then( [this] { return ses.attach<book>("books"); } )
.and_then( [this] { return ses.create_schema(); } ); .and_then( [this] { return ses.create_schema(); } );
@ -146,3 +147,56 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-ma
std::cout << "author: " << it->first_name << " (books: " << it->books.size() << ")\n"; std::cout << "author: " << it->first_name << " (books: " << it->books.size() << ")\n";
} }
} }
TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-many eager relation", "[session][find][one-to-many][eager]") {
auto result = ses.attach<department>("departments")
.and_then( [this] { return ses.attach<employee>("employees"); } )
.and_then( [this] { return ses.create_schema(); } );
tables_to_drop.emplace("departments");
tables_to_drop.emplace("employees");
std::vector<std::unique_ptr<department>> departments;
departments.emplace_back(new department{1, "Insurance", {}});
departments.emplace_back(new department{ 2, "Invoice", {}});
for (auto &&a: departments) {
auto res = ses.insert(a.release());
REQUIRE(res.is_ok());
}
auto find_result = ses.find<department>();
REQUIRE(find_result.is_ok());
auto all_departments = find_result.release();
std::vector<object_ptr<department>> departments_repo;
for (auto it = all_departments.begin(); it != all_departments.end(); ++it) {
std::cout << "author: " << it->name << " (employees: " << it->employees.size() << ")\n";
departments_repo.emplace_back(it.release());
}
REQUIRE(departments_repo.size() == 2);
std::vector<std::unique_ptr<employee>> employees;
employees.emplace_back( new employee{3, "George", "Orwell", departments_repo[0]} );
employees.emplace_back( new employee{4, "Chris", "Tucker", departments_repo[0]} );
employees.emplace_back( new employee{5, "Steven", "King", departments_repo[0]} );
employees.emplace_back( new employee{6, "John", "Wayne", departments_repo[0]} );
employees.emplace_back( new employee{7, "Clint", "Eastwood", departments_repo[0]} );
employees.emplace_back( new employee{8, "Emma", "Thompson", departments_repo[1]} );
employees.emplace_back( new employee{9, "Ed", "Wood", departments_repo[1]} );
employees.emplace_back( new employee{10, "Steven", "Spielberg", departments_repo[1]} );
employees.emplace_back( new employee{11, "Jane", "Fonda", departments_repo[1]} );
employees.emplace_back( new employee{12, "Julia", "Roberts", departments_repo[1]} );
for (auto &&b: employees) {
auto res = ses.insert(b.release());
REQUIRE(res.is_ok());
}
find_result = ses.find<department>();
REQUIRE(find_result);
all_departments = find_result.release();
for (auto it = all_departments.begin(); it != all_departments.end(); ++it) {
std::cout << "author: " << it->name << " (employees: " << it->employees.size() << ")\n";
}
}

View File

@ -14,7 +14,7 @@ struct department {
unsigned int id{}; unsigned int id{};
std::string name; std::string name;
std::vector<object::object_ptr<employee>> employees; std::vector<object::object_ptr<employee>> employees;
object::object_ptr<employee> manager; // object::object_ptr<employee> manager;
template<typename Operator> template<typename Operator>
void process(Operator &op) { void process(Operator &op) {
@ -22,7 +22,7 @@ struct department {
field::primary_key(op, "id", id); field::primary_key(op, "id", id);
field::attribute(op, "name", name, 63); field::attribute(op, "name", name, 63);
field::has_many(op, "employees", employees, "dep_id", utils::fetch_type::EAGER); field::has_many(op, "employees", employees, "dep_id", utils::fetch_type::EAGER);
field::belongs_to(op, "manager_id", manager, utils::fetch_type::EAGER); // field::belongs_to(op, "manager_id", manager, utils::fetch_type::EAGER);
} }
}; };

View File

@ -70,7 +70,7 @@ TEST_CASE("Create sql query data for entity with eager has one", "[query][entity
REQUIRE(data->where_clause); REQUIRE(data->where_clause);
auto cond = data->where_clause->evaluate(db.dialect(), qc); auto cond = data->where_clause->evaluate(db.dialect(), qc);
REQUIRE(cond == R"("flights"."id" = 17)"); REQUIRE(cond == R"("t01"."id" = 17)");
} }
TEST_CASE("Create sql query data for entity with eager belongs to", "[query][entity][builder]") { TEST_CASE("Create sql query data for entity with eager belongs to", "[query][entity][builder]") {
@ -119,7 +119,7 @@ TEST_CASE("Create sql query data for entity with eager belongs to", "[query][ent
REQUIRE(data->where_clause); REQUIRE(data->where_clause);
auto cond = data->where_clause->evaluate(db.dialect(), qc); auto cond = data->where_clause->evaluate(db.dialect(), qc);
REQUIRE(cond == R"("books"."id" = 17)"); REQUIRE(cond == R"("t01"."id" = 17)");
auto q = matador::query::query::select(data->columns) auto q = matador::query::query::select(data->columns)
.from(data->root_table->name); .from(data->root_table->name);
@ -188,7 +188,7 @@ TEST_CASE("Create sql query data for entity with eager has many belongs to", "[q
REQUIRE(data->where_clause); REQUIRE(data->where_clause);
auto cond = data->where_clause->evaluate(db.dialect(), qc); auto cond = data->where_clause->evaluate(db.dialect(), qc);
REQUIRE(cond == R"("orders"."order_id" = 17)"); REQUIRE(cond == R"("t01"."order_id" = 17)");
} }
TEST_CASE("Create sql query data for entity with eager many to many", "[query][entity][builder]") { TEST_CASE("Create sql query data for entity with eager many to many", "[query][entity][builder]") {
@ -233,7 +233,7 @@ TEST_CASE("Create sql query data for entity with eager many to many", "[query][e
REQUIRE(data->where_clause); REQUIRE(data->where_clause);
auto cond = data->where_clause->evaluate(db.dialect(), qc); auto cond = data->where_clause->evaluate(db.dialect(), qc);
REQUIRE(cond == R"("ingredients"."id" = 17)"); REQUIRE(cond == R"("t01"."id" = 17)");
} }
TEST_CASE("Create sql query data for entity with eager many to many (inverse part)", "[query][entity][builder]") { TEST_CASE("Create sql query data for entity with eager many to many (inverse part)", "[query][entity][builder]") {
@ -278,7 +278,7 @@ TEST_CASE("Create sql query data for entity with eager many to many (inverse par
REQUIRE(data->where_clause); REQUIRE(data->where_clause);
auto cond = data->where_clause->evaluate(db.dialect(), qc); auto cond = data->where_clause->evaluate(db.dialect(), qc);
REQUIRE(cond == R"("courses"."id" = 17)"); REQUIRE(cond == R"("t01"."id" = 17)");
} }
TEST_CASE("Test eager relationship", "[session][eager]") { TEST_CASE("Test eager relationship", "[session][eager]") {