has many primitive collection resolver
This commit is contained in:
parent
a714cd2a53
commit
68eb2b6a6e
|
|
@ -31,6 +31,46 @@ protected:
|
|||
std::shared_ptr<object::object_resolver<typename Type::value_type>> resolver_;
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
class query_collection_primitive_resolver : public object::collection_resolver<Type> {
|
||||
public:
|
||||
explicit query_collection_primitive_resolver(sql::statement &&stmt,
|
||||
const std::type_index& root_type,
|
||||
std::string join_column//,
|
||||
/*const std::shared_ptr<object::object_resolver<typename Type::value_type>> &resolver*/)
|
||||
: object::collection_resolver<Type>(root_type, join_column)
|
||||
, stmt_(std::move(stmt))
|
||||
// , resolver_(resolver)
|
||||
{}
|
||||
|
||||
std::vector<Type> resolve(const utils::identifier &id) override {
|
||||
sql::identifier_statement_binder binder(stmt_);
|
||||
binder.bind(id);
|
||||
|
||||
auto result = stmt_.fetch();
|
||||
if (!result) {
|
||||
return {};
|
||||
}
|
||||
std::vector<Type> out;
|
||||
for (auto &r : *result) {
|
||||
// Todo: convert the first value of record into an utils::identifier
|
||||
// then create a object_proxy<Type>(resolver, identifier)
|
||||
if (r.size() != 1) {
|
||||
continue;
|
||||
}
|
||||
auto val = r.at<Type>(0);
|
||||
if (val.has_value()) {
|
||||
out.push_back(*val);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
protected:
|
||||
sql::statement stmt_;
|
||||
std::type_index index{typeid(Type)};
|
||||
// std::shared_ptr<object::object_resolver<typename Type::value_type>> resolver_;
|
||||
};
|
||||
|
||||
struct value_to_identifier{
|
||||
void operator()(const int8_t &x) { assign(x); }
|
||||
void operator()(const int16_t &x) { assign(x); }
|
||||
|
|
|
|||
|
|
@ -54,6 +54,41 @@ private:
|
|||
std::string pk_name_;
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
class query_collection_primitive_resolver_producer : public sql::collection_resolver_producer {
|
||||
public:
|
||||
query_collection_primitive_resolver_producer() = default;
|
||||
query_collection_primitive_resolver_producer(const basic_schema& repo, const table& tab, std::string value_name, const std::type_index& root_type, std::string join_column)
|
||||
: collection_resolver_producer(root_type, typeid(Type), std::move(join_column))
|
||||
, repo_(repo)
|
||||
, table_(tab)
|
||||
, value_name_(std::move(value_name))
|
||||
{}
|
||||
|
||||
utils::result<sql::query_context, utils::error> build_query(const sql::dialect& d) override {
|
||||
const auto *value_column = table_[value_name_];
|
||||
const auto *join_column = table_[collection_name()];
|
||||
|
||||
const auto stmt = select({*value_column})
|
||||
.from(table_)
|
||||
.where(*join_column == utils::_)
|
||||
.compile(d);
|
||||
|
||||
return utils::ok(stmt);
|
||||
}
|
||||
|
||||
std::shared_ptr<object::abstract_collection_resolver> produce(sql::statement&& stmt, const sql::resolver_service& rs) override {
|
||||
// const auto object_resolver = rs.object_resolver<typename Type::value_type>();
|
||||
|
||||
return std::make_shared<query_collection_primitive_resolver<Type>>(std::move(stmt), root_type(), collection_name()/*, object_resolver*/);
|
||||
}
|
||||
|
||||
private:
|
||||
const basic_schema& repo_;
|
||||
const table& table_;
|
||||
std::string value_name_;
|
||||
};
|
||||
|
||||
class producer_creator final {
|
||||
public:
|
||||
producer_creator(basic_schema& schema, const std::type_index& root_type)
|
||||
|
|
@ -94,7 +129,20 @@ public:
|
|||
}
|
||||
|
||||
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) {
|
||||
const auto it = schema_.find(id);
|
||||
if (it == schema_.end()) {
|
||||
throw query_builder_exception{error_code::UnknownType, "Unknown type" + std::string{id}};
|
||||
}
|
||||
auto producer = std::make_unique<query_collection_primitive_resolver_producer<typename CollectionType::value_type>>(
|
||||
schema_,
|
||||
it->second.table(),
|
||||
"value",
|
||||
root_type_,
|
||||
join_column);
|
||||
const object::collection_composite_key key{root_type_, typeid(typename CollectionType::value_type), join_column};
|
||||
schema_.collection_resolver_producers_[key] = std::move(producer);
|
||||
}
|
||||
|
||||
template<class CollectionType>
|
||||
void on_has_many_to_many(const char *id, CollectionType &, const char *join_column, const char *inverse_join_column, const utils::foreign_attributes &/*attr*/) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
#include <utility>
|
||||
|
||||
#include "catch2/catch_test_macros.hpp"
|
||||
|
||||
#include "SessionFixture.hpp"
|
||||
|
|
@ -207,4 +205,8 @@ TEST_CASE_METHOD(SessionFixture, "Test insert object with has many primitive rel
|
|||
auto clist = *colorlist_result;
|
||||
REQUIRE(clist.is_persistent());
|
||||
REQUIRE(clist->colors.size() == 3);
|
||||
std::vector<std::string> expected_colors{"red", "green", "blue"};
|
||||
for (const auto &cstr: clist->colors) {
|
||||
REQUIRE(std::find(expected_colors.begin(), expected_colors.end(), cstr) != expected_colors.end());
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue