fixed session tests
This commit is contained in:
parent
cb0f6322f4
commit
463647ba59
|
|
@ -100,61 +100,25 @@ public:
|
|||
|
||||
utils::result<void, utils::error> create_schema() const;
|
||||
|
||||
/**
|
||||
* Insert the given object into the session.
|
||||
*
|
||||
* @tparam Type Type of object to insert
|
||||
* @param obj Object to insert
|
||||
* @return Inserted object
|
||||
*/
|
||||
template<typename Type>
|
||||
utils::result<object::object_ptr<Type>, utils::error> insert(Type *obj);
|
||||
|
||||
template< class Type, typename... Args >
|
||||
utils::result<object::object_ptr<Type>, utils::error> insert(Args&&... args) {
|
||||
return insert(new Type(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<typename Type, typename PrimaryKeyType>
|
||||
utils::result<object::object_ptr<Type>, utils::error> find(const PrimaryKeyType &pk) {
|
||||
auto info = schema_->info<Type>();
|
||||
if (!info) {
|
||||
return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type."));
|
||||
}
|
||||
|
||||
session_query_builder eqb(*schema_, *this);
|
||||
auto data = eqb.build<Type>(pk);
|
||||
if (!data.is_ok()) {
|
||||
return utils::failure(make_error(error_code::FailedToBuildQuery, "Failed to build query for type " + info->get().name() + "."));
|
||||
}
|
||||
|
||||
auto res = build_select_query(data.release()).prepare(*this);
|
||||
// auto obj = build_select_query(data.release()).template fetch_one<Type>(*this);
|
||||
|
||||
if (!res) {
|
||||
return utils::failure(res.err());
|
||||
}
|
||||
auto stmt_result = res->bind(0, const_cast<PrimaryKeyType&>(pk)).template fetch_one<Type>();
|
||||
if (!stmt_result) {
|
||||
return utils::failure(make_error(error_code::FailedToFindObject, "Failed to find object of type " + info->get().name() + " with primary key " + std::to_string(pk) + "."));
|
||||
}
|
||||
return utils::ok(object::object_ptr<Type>{ stmt_result->release() });
|
||||
}
|
||||
utils::result<object::object_ptr<Type>, utils::error> insert(Args&&... args);
|
||||
|
||||
template<typename Type>
|
||||
utils::result<sql::query_result<Type>, utils::error> find() {
|
||||
auto info = schema_->info<Type>();
|
||||
if (!info) {
|
||||
return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type."));
|
||||
}
|
||||
utils::result<object::object_ptr<Type>, utils::error> update(const object::object_ptr<Type> &obj);
|
||||
|
||||
session_query_builder eqb(*schema_, *this);
|
||||
auto data = eqb.build<Type>();
|
||||
if (!data.is_ok()) {
|
||||
return utils::failure(make_error(error_code::FailedToBuildQuery, "Failed to build query for type " + info->get().name() + "."));
|
||||
}
|
||||
|
||||
const auto ctx = build_select_query(data.release()).compile(dialect_, query::query_mode::Prepared);
|
||||
|
||||
auto result = fetch(ctx);
|
||||
if (!result.is_ok()) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
return utils::ok(sql::query_result<Type>(result.release(), []{ return new Type();}));
|
||||
}
|
||||
template<typename Type, typename PrimaryKeyType>
|
||||
utils::result<object::object_ptr<Type>, utils::error> find(const PrimaryKeyType &pk);
|
||||
template<typename Type>
|
||||
utils::result<sql::query_result<Type>, utils::error> find();
|
||||
|
||||
template<typename Type>
|
||||
utils::result<void, utils::error> drop_table();
|
||||
|
|
@ -207,14 +171,89 @@ utils::result<object::object_ptr<Type>, utils::error> session::insert(Type *obj)
|
|||
auto res = query::query::insert()
|
||||
.into(info->get().name(), sql::column_generator::generate<Type>(*schema_, true))
|
||||
.values(*obj)
|
||||
.execute(*this);
|
||||
.prepare(*this);
|
||||
if (!res) {
|
||||
return utils::failure(res.err());
|
||||
}
|
||||
|
||||
if (const auto insert_result = res->bind(*obj).execute(); !insert_result.is_ok()) {
|
||||
return utils::failure(insert_result.err());
|
||||
}
|
||||
return utils::ok(object::object_ptr{obj});
|
||||
}
|
||||
|
||||
template<class Type, typename ... Args>
|
||||
utils::result<object::object_ptr<Type>, utils::error> session::insert( Args&&... args ) {
|
||||
return insert(new Type(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
utils::result<object::object_ptr<Type>, utils::error> session::update( const object::object_ptr<Type>& obj ) {
|
||||
auto info = schema_->info<Type>();
|
||||
if (!info) {
|
||||
return utils::failure(info.err());
|
||||
}
|
||||
|
||||
auto res = query::query::update(info->get().name())
|
||||
.set(*obj)
|
||||
// .where(sql::column(info->prototype().primary_key()->name()) == _)
|
||||
.prepare(*this);
|
||||
if (!res) {
|
||||
return utils::failure(res.err());
|
||||
}
|
||||
|
||||
if (const auto insert_result = res->bind(*obj).execute(); !insert_result.is_ok()) {
|
||||
return utils::failure(insert_result.err());
|
||||
}
|
||||
return utils::ok(object::object_ptr{obj});
|
||||
}
|
||||
|
||||
template<typename Type, typename PrimaryKeyType>
|
||||
utils::result<object::object_ptr<Type>, utils::error> session::find( const PrimaryKeyType& pk ) {
|
||||
auto info = schema_->info<Type>();
|
||||
if (!info) {
|
||||
return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type."));
|
||||
}
|
||||
|
||||
session_query_builder eqb(*schema_, *this);
|
||||
auto data = eqb.build<Type>(pk);
|
||||
if (!data.is_ok()) {
|
||||
return utils::failure(make_error(error_code::FailedToBuildQuery, "Failed to build query for type " + info->get().name() + "."));
|
||||
}
|
||||
|
||||
auto res = build_select_query(data.release()).prepare(*this);
|
||||
|
||||
if (!res) {
|
||||
return utils::failure(res.err());
|
||||
}
|
||||
auto stmt_result = res->bind(0, const_cast<PrimaryKeyType&>(pk)).template fetch_one<Type>();
|
||||
if (stmt_result && !stmt_result.value()) {
|
||||
return utils::failure(make_error(error_code::FailedToFindObject, "Failed to find object of type " + info->get().name() + " with primary key " + std::to_string(pk) + "."));
|
||||
}
|
||||
return utils::ok(object::object_ptr<Type>{ stmt_result->release() });
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
utils::result<sql::query_result<Type>, utils::error> session::find() {
|
||||
auto info = schema_->info<Type>();
|
||||
if (!info) {
|
||||
return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type."));
|
||||
}
|
||||
|
||||
session_query_builder eqb(*schema_, *this);
|
||||
auto data = eqb.build<Type>();
|
||||
if (!data.is_ok()) {
|
||||
return utils::failure(make_error(error_code::FailedToBuildQuery, "Failed to build query for type " + info->get().name() + "."));
|
||||
}
|
||||
|
||||
auto result = build_select_query(data.release()).prepare(*this);
|
||||
if (!result.is_ok()) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
|
||||
return result->template fetch<Type>();
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
utils::result<void, utils::error> session::drop_table() {
|
||||
auto info = schema_->info<Type>();
|
||||
|
|
|
|||
|
|
@ -261,6 +261,11 @@ void session_query_builder::on_foreign_object(const char *id, Pointer &, const u
|
|||
if (!info) {
|
||||
throw query_builder_exception{query_build_error::UnknownType};
|
||||
}
|
||||
auto pk = info->get().definition().primary_key();
|
||||
if (!pk) {
|
||||
throw query_builder_exception{query_build_error::MissingPrimaryKey};
|
||||
}
|
||||
|
||||
const auto foreign_table = std::make_shared<sql::table>(info->get().name(), build_alias('t', ++table_index));
|
||||
if (attr.fetch() == utils::fetch_type::EAGER) {
|
||||
|
||||
|
|
@ -274,10 +279,6 @@ void session_query_builder::on_foreign_object(const char *id, Pointer &, const u
|
|||
access::process(*this, obj);
|
||||
table_info_stack_.pop();
|
||||
|
||||
auto pk = info->get().definition().primary_key();
|
||||
if (!pk) {
|
||||
throw query_builder_exception{query_build_error::MissingPrimaryKey};
|
||||
}
|
||||
append_join(
|
||||
sql::column{table_info_stack_.top().table, id},
|
||||
sql::column{next->second, pk->name()}
|
||||
|
|
@ -287,9 +288,9 @@ void session_query_builder::on_foreign_object(const char *id, Pointer &, const u
|
|||
using namespace matador::utils;
|
||||
using namespace matador::query;
|
||||
// create select query
|
||||
auto result = matador::query::query::select<typename Pointer::value_type>(schema_)
|
||||
auto result = matador::query::query::select(sql::column_generator::generate<typename Pointer::value_type>(schema_, true))
|
||||
.from(*foreign_table)
|
||||
.where(sql::column(foreign_table, id, "") == _)
|
||||
.where(sql::column(foreign_table, pk->name(), "") == _)
|
||||
.prepare(executor_);
|
||||
if (!result) {
|
||||
throw query_builder_exception(query_build_error::QueryError, result.release_error());
|
||||
|
|
|
|||
|
|
@ -31,7 +31,10 @@ public:
|
|||
return utils::failure(result.err());
|
||||
}
|
||||
|
||||
return utils::ok(sql::query_result<Type>(result.release()));
|
||||
const auto prototype = result.value()->prototype();
|
||||
return utils::ok(sql::query_result<Type>(result.release(), [prototype] {
|
||||
return sql::detail::create_prototype<Type>(prototype);
|
||||
}));
|
||||
}
|
||||
[[nodiscard]] utils::result<sql::query_result<sql::record>, utils::error> fetch_all(const sql::executor &exec) const;
|
||||
|
||||
|
|
@ -43,7 +46,10 @@ public:
|
|||
return utils::failure(result.err());
|
||||
}
|
||||
|
||||
auto objects = sql::query_result<Type>(result.release());
|
||||
const auto prototype = result.value()->prototype();
|
||||
auto objects = sql::query_result<Type>(result.release(), [prototype] {
|
||||
return sql::detail::create_prototype<Type>(prototype);
|
||||
});
|
||||
auto first = objects.begin();
|
||||
if (first == objects.end()) {
|
||||
return utils::ok(std::unique_ptr<Type>{nullptr});
|
||||
|
|
|
|||
|
|
@ -40,8 +40,7 @@ public:
|
|||
, result_(x.result_)
|
||||
{}
|
||||
|
||||
query_result_iterator& operator=(query_result_iterator&& x) noexcept
|
||||
{
|
||||
query_result_iterator& operator=(query_result_iterator&& x) noexcept {
|
||||
result_ = x.result_;
|
||||
obj_ = std::move(x.obj_);
|
||||
return *this;
|
||||
|
|
@ -49,18 +48,15 @@ public:
|
|||
|
||||
~query_result_iterator() = default;
|
||||
|
||||
bool operator==(const query_result_iterator& rhs)
|
||||
{
|
||||
bool operator==(const query_result_iterator& rhs) {
|
||||
return obj_ == rhs.obj_;
|
||||
}
|
||||
|
||||
bool operator!=(const query_result_iterator& rhs)
|
||||
{
|
||||
bool operator!=(const query_result_iterator& rhs) {
|
||||
return obj_ != rhs.obj_;
|
||||
}
|
||||
|
||||
self& operator++()
|
||||
{
|
||||
self& operator++() {
|
||||
obj_.reset(result_->create());
|
||||
result_->bind(*obj_);
|
||||
if (!result_->fetch(*obj_)) {
|
||||
|
|
@ -70,8 +66,7 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
self operator++(int)
|
||||
{
|
||||
self operator++(int) {
|
||||
const self tmp(result_, obj_);
|
||||
|
||||
obj_.reset(result_->create());
|
||||
|
|
@ -83,23 +78,19 @@ public:
|
|||
return tmp;
|
||||
}
|
||||
|
||||
pointer operator->()
|
||||
{
|
||||
pointer operator->() {
|
||||
return obj_.get();
|
||||
}
|
||||
|
||||
reference operator*()
|
||||
{
|
||||
reference operator*() {
|
||||
return *obj_;
|
||||
}
|
||||
|
||||
pointer get()
|
||||
{
|
||||
pointer get() {
|
||||
return obj_.get();
|
||||
}
|
||||
|
||||
pointer release()
|
||||
{
|
||||
pointer release() {
|
||||
return obj_.release();
|
||||
}
|
||||
|
||||
|
|
@ -111,8 +102,7 @@ private:
|
|||
namespace detail {
|
||||
|
||||
template < typename Type >
|
||||
Type* create_prototype(const std::vector<object::attribute_definition> &/*prototype*/)
|
||||
{
|
||||
Type* create_prototype(const std::vector<object::attribute_definition> &/*prototype*/) {
|
||||
return new Type{};
|
||||
}
|
||||
|
||||
|
|
@ -128,11 +118,11 @@ public:
|
|||
using creator_func = std::function<Type*()>;
|
||||
|
||||
public:
|
||||
explicit query_result(std::unique_ptr<query_result_impl> &&impl)
|
||||
: impl_(std::move(impl))
|
||||
, creator_([this] {
|
||||
return detail::create_prototype<Type>(impl_->prototype());
|
||||
}) {}
|
||||
// explicit query_result(std::unique_ptr<query_result_impl> &&impl)
|
||||
// : impl_(std::move(impl))
|
||||
// , creator_([this] {
|
||||
// return detail::create_prototype<Type>(impl_->prototype());
|
||||
// }) {}
|
||||
|
||||
query_result(std::unique_ptr<query_result_impl> &&impl, creator_func&& creator)
|
||||
: impl_(std::move(impl))
|
||||
|
|
|
|||
|
|
@ -150,7 +150,10 @@ statement &statement::bind(const Type &obj) {
|
|||
template<class Type>
|
||||
utils::result<query_result<Type>, utils::error> statement::fetch() {
|
||||
return statement_proxy_->fetch(*bindings_).and_then([](std::unique_ptr<query_result_impl> &&value) {
|
||||
return utils::ok(query_result<Type>(std::forward<decltype(value)>(value)));
|
||||
const auto prototype = value->prototype();
|
||||
return utils::ok(query_result<Type>(std::forward<decltype(value)>(value), [prototype] {
|
||||
return detail::create_prototype<Type>(prototype);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -160,7 +163,10 @@ utils::result<std::unique_ptr<Type>, utils::error> statement::fetch_one() {
|
|||
if (!result.is_ok()) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
auto records = query_result<Type>(result.release());
|
||||
const auto prototype = result.value()->prototype();
|
||||
auto records = query_result<Type>(result.release(), [prototype] {
|
||||
return detail::create_prototype<Type>(prototype);
|
||||
});
|
||||
auto first = records.begin();
|
||||
if (first == records.end()) {
|
||||
return utils::ok(std::unique_ptr<Type>{nullptr});
|
||||
|
|
|
|||
|
|
@ -108,7 +108,10 @@ utils::result<sql::query_result<sql::record>, utils::error> session::fetch_all(c
|
|||
if (!res) {
|
||||
return utils::failure(res.err());
|
||||
}
|
||||
return utils::ok(sql::query_result<sql::record>{std::move(*res)});
|
||||
const auto prototype = res.value()->prototype();
|
||||
return utils::ok(sql::query_result<sql::record>{std::move(*res), [prototype] {
|
||||
return sql::detail::create_prototype<sql::record>(prototype);
|
||||
}});
|
||||
}
|
||||
|
||||
utils::result<size_t, utils::error> session::execute(const std::string &sql) const {
|
||||
|
|
|
|||
|
|
@ -53,7 +53,10 @@ utils::result<std::optional<sql::record>, utils::error> fetchable_query::fetch_o
|
|||
return utils::failure(result.err());
|
||||
}
|
||||
|
||||
sql::query_result<sql::record> records(std::move(*result));
|
||||
const auto prototype = result.value()->prototype();
|
||||
sql::query_result<sql::record> records(std::move(*result), [prototype] {
|
||||
return detail::create_prototype(prototype);
|
||||
});
|
||||
auto first = records.begin();
|
||||
if (first == records.end()) {
|
||||
return utils::ok(std::optional<sql::record>{std::nullopt});
|
||||
|
|
|
|||
|
|
@ -61,7 +61,10 @@ utils::result<query_result<record>, utils::error> statement::fetch() const {
|
|||
return utils::failure(result.err());
|
||||
}
|
||||
// logger_.info(statement_->query_.sql);
|
||||
return utils::ok(query_result<record>{std::move(*result)});
|
||||
const auto prototype = result.value()->prototype();
|
||||
return utils::ok(query_result<record>(std::move(*result), [prototype] {
|
||||
return detail::create_prototype<record>(prototype);
|
||||
}));
|
||||
}
|
||||
|
||||
utils::result<std::optional<record>, utils::error> statement::fetch_one() const {
|
||||
|
|
@ -71,7 +74,10 @@ utils::result<std::optional<record>, utils::error> statement::fetch_one() const
|
|||
return utils::failure(result.err());
|
||||
}
|
||||
|
||||
query_result<record> records(std::move(*result));
|
||||
const auto prototype = result.value()->prototype();
|
||||
query_result<record> records(std::move(*result), [prototype] {
|
||||
return sql::detail::create_prototype<record>(prototype);
|
||||
});
|
||||
auto first = records.begin();
|
||||
if (first == records.end()) {
|
||||
return utils::ok(std::optional<record>{std::nullopt});
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-ma
|
|||
TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with many-to-many eager relation", "[session][find][many-to-many][eager]") {
|
||||
auto result = ses.attach<recipe>("recipes")
|
||||
.and_then( [this] { return ses.attach<ingredient>("ingredients"); } )
|
||||
.and_then( [this] { return ses.attach<recipe_ingredient>("recipe_ingredients"); } )
|
||||
// .and_then( [this] { return ses.attach<recipe_ingredient>("recipe_ingredients"); } )
|
||||
.and_then( [this] { return ses.create_schema(); } );
|
||||
|
||||
tables_to_drop.emplace("recipes");
|
||||
|
|
@ -217,7 +217,6 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with many-to-m
|
|||
|
||||
std::vector<std::unique_ptr<ingredient>> ingredients;
|
||||
ingredients.push_back(std::make_unique<ingredient>(1, "Apple"));
|
||||
ingredients.push_back(std::make_unique<ingredient>(1, "Apple"));
|
||||
ingredients.push_back(std::make_unique<ingredient>(2, "Strawberry"));
|
||||
ingredients.push_back(std::make_unique<ingredient>(3, "Pineapple"));
|
||||
ingredients.push_back(std::make_unique<ingredient>(4, "Sugar"));
|
||||
|
|
|
|||
Loading…
Reference in New Issue