implemented lazy loading for object_ptr and belongs_to

This commit is contained in:
2026-01-15 12:40:54 +01:00
parent db8e137c11
commit 7626331866
81 changed files with 1790 additions and 927 deletions
+5 -1
View File
@@ -25,7 +25,8 @@ public:
* @param info The database connection info data
* @param sql_logger The logging handler
*/
explicit connection(const connection_info& info, const logger_ptr &sql_logger = null_logger);
explicit connection(const connection_info& info, logger_ptr sql_logger = null_logger);
explicit connection(const connection_info& info, std::shared_ptr<producer_resolver_factory> resolver_factory, logger_ptr sql_logger = null_logger);
/**
* @brief Creates a database connection from a connection string.
*
@@ -33,6 +34,7 @@ public:
* @param sql_logger The logging handler
*/
explicit connection(const std::string &dns, const logger_ptr &sql_logger = null_logger);
explicit connection(const std::string &dns, std::shared_ptr<producer_resolver_factory> resolver_factory, const logger_ptr &sql_logger = null_logger);
/**
* Copies a given connection
*
@@ -138,6 +140,7 @@ public:
[[nodiscard]] std::string str( const query_context& ctx ) const override;
[[nodiscard]] const class dialect &dialect() const override;
[[nodiscard]] std::shared_ptr<producer_resolver_factory> resolver_factory() const override;
private:
[[nodiscard]] utils::result<std::unique_ptr<statement_impl>, utils::error> perform_prepare(const query_context &ctx) const;
@@ -149,6 +152,7 @@ private:
std::unique_ptr<connection_impl> connection_;
std::shared_ptr<abstract_sql_logger> logger_ = std::make_shared<null_sql_logger>();
std::shared_ptr<producer_resolver_factory> resolver_factory_ = std::make_shared<producer_resolver_factory>();
};
}
+2
View File
@@ -46,6 +46,7 @@ private:
class connection_pool {
public:
connection_pool(const std::string &dns, size_t count);
connection_pool(const std::string &dns, size_t count, std::function<connection(const connection_info &)> &&connection_creator);
connection_ptr acquire();
connection_ptr try_acquire();
@@ -74,6 +75,7 @@ private:
connection_map idle_connections_;
const connection_info info_;
std::function<connection(const connection_info &)> connection_creator_;
};
}
+3
View File
@@ -1,6 +1,8 @@
#ifndef EXECUTOR_HPP
#define EXECUTOR_HPP
#include "matador/sql/producer_resolver_factory.hpp"
#include "matador/utils/error.hpp"
#include "matador/utils/result.hpp"
@@ -20,6 +22,7 @@ public:
[[nodiscard]] virtual utils::result<std::unique_ptr<query_result_impl>, utils::error> fetch(const query_context &ctx) const = 0;
[[nodiscard]] virtual utils::result<statement, utils::error> prepare(const query_context &ctx) = 0;
[[nodiscard]] virtual std::string str(const query_context &ctx) const = 0;
[[nodiscard]] virtual std::shared_ptr<producer_resolver_factory> resolver_factory() const = 0;
};
}
+3
View File
@@ -28,6 +28,9 @@ public:
field(field &&x) noexcept;
field& operator=(field &&x) noexcept;
bool operator==(const field& rhs) const;
bool operator!=(const field& rhs) const;
template<typename Type>
field& operator=(Type value) {
value_ = std::move(value);
@@ -7,11 +7,13 @@
#include "matador/sql/object_parameter_binder.hpp"
#include "matador/utils/data_type_traits.hpp"
#include "matador/utils/error.hpp"
#include "matador/utils/result.hpp"
#include <memory>
namespace matador::sql {
class query_result_impl;
class sql_error;
class statement_impl {
@@ -40,6 +40,8 @@ public:
[[nodiscard]] std::unique_ptr<utils::attribute_writer> create_binder() const;
protected:
friend class statement;
std::unique_ptr<statement_impl> statement_;
};
@@ -0,0 +1,51 @@
#ifndef MATADOR_IDENTIFIER_READER_HPP
#define MATADOR_IDENTIFIER_READER_HPP
#include "matador/utils/access.hpp"
#include "matador/utils/identifier.hpp"
#include "matador/utils/primary_key_attribute.hpp"
namespace matador::sql {
class query_result_reader;
}
namespace matador::sql::internal {
class identifier_reader final {
public:
explicit identifier_reader(query_result_reader &reader);
template<class Type>
utils::identifier read(const Type &obj, const size_t column_index) {
identifier_.clear();
column_index_ = column_index;
access::process(*this, obj);
return identifier_;
}
template<typename ValueType>
void on_primary_key(const char *id, ValueType &value, const utils::primary_key_attribute& attr = utils::default_pk_attributes) {
utils::data_type_traits<ValueType>::read_value(reader_, id, column_index_, value, attr.size());
identifier_ = value;
}
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
template < class Type >
static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
template < class Pointer >
static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {}
template < class Pointer >
static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {}
template<class ContainerType>
static void on_has_many(const char * /*id*/, ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {}
template<class ContainerType>
static void on_has_many_to_many(const char * /*id*/, ContainerType & /*c*/, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes &/*attr*/) {}
template<class ContainerType>
static void on_has_many_to_many(const char * /*id*/, ContainerType & /*c*/, const utils::foreign_attributes &/*attr*/) {}
private:
query_result_reader &reader_;
size_t column_index_{};
utils::identifier identifier_;
};
}
#endif //MATADOR_IDENTIFIER_READER_HPP
@@ -0,0 +1,33 @@
#ifndef MATADOR_IDENTIFIER_STATEMENT_BINDER_HPP
#define MATADOR_IDENTIFIER_STATEMENT_BINDER_HPP
#include "matador/utils/identifier.hpp"
namespace matador::sql {
class statement;
class identifier_statement_binder : public utils::identifier_serializer {
public:
explicit identifier_statement_binder(statement &stmt, size_t index = 0);
void bind(const utils::identifier &id);
void serialize(int8_t &, const utils::field_attributes &) override;
void serialize(int16_t &, const utils::field_attributes &) override;
void serialize(int32_t &, const utils::field_attributes &) override;
void serialize(int64_t &, const utils::field_attributes &) override;
void serialize(uint8_t &, const utils::field_attributes &) override;
void serialize(uint16_t &, const utils::field_attributes &) override;
void serialize(uint32_t &, const utils::field_attributes &) override;
void serialize(uint64_t &, const utils::field_attributes &) override;
void serialize(const char *, const utils::field_attributes &) override;
void serialize(std::string &, const utils::field_attributes &) override;
void serialize(utils::null_type_t &, const utils::field_attributes &) override;
private:
statement &stmt_;
size_t index_{};
};
}
#endif //MATADOR_IDENTIFIER_STATEMENT_BINDER_HPP
@@ -10,16 +10,17 @@
#include "matador/sql/interface/query_result_reader.hpp"
#include "matador/sql/internal/query_result_pk_resolver.hpp"
#include "matador/sql/internal/identifier_reader.hpp"
#include "matador/sql/record.hpp"
#include "matador/object/attribute.hpp"
#include "matador/object/object_proxy.hpp"
#include "matador/object/object_resolver_factory.hpp"
#include <iostream>
#include <memory>
#include <stack>
#include <string>
#include <typeindex>
#include <unordered_set>
namespace matador::utils {
class value;
@@ -73,9 +74,9 @@ private:
class query_result_impl {
public:
query_result_impl(std::unique_ptr<query_result_reader> &&reader,
std::vector<object::attribute> &&prototype, size_t column_index = 0);
query_result_impl(std::unique_ptr<query_result_reader> &&reader,
const std::vector<object::attribute> &prototype, size_t column_index = 0);
std::vector<object::attribute> prototype,
const std::shared_ptr<object::object_resolver_factory>& resolver_factory,
size_t column_index = 0);
template<typename ValueType>
void on_primary_key(const char *id, ValueType &value, const utils::primary_key_attribute& attr = utils::default_pk_attributes) {
@@ -122,17 +123,19 @@ public:
}
template<class ContainerType>
void on_has_many(const char * /*id*/, ContainerType &cont, const char * /*join_column*/,
const utils::foreign_attributes &attr) {
void on_has_many(const char * /*id*/, ContainerType &cont, const char * /*join_column*/, const utils::foreign_attributes &attr) {
using value_type = typename ContainerType::value_type::value_type;
auto resolver = resolver_factory_->resolver<value_type>();
if (attr.fetch() == utils::fetch_type::Lazy) {
// pk_reader_.read(*id, column_index_++);
} else {
const auto ti = std::type_index(typeid(typename ContainerType::value_type::value_type));
auto obj = std::make_unique<typename ContainerType::value_type::value_type>();
const auto ti = std::type_index(typeid(value_type));
auto obj = std::make_shared<typename ContainerType::value_type::value_type>();
type_stack_.push(ti);
access::process(*this, *obj);
type_stack_.pop();
auto ptr = typename ContainerType::value_type(obj.release());
auto ptr = typename ContainerType::value_type(std::make_shared<object::object_proxy<value_type>>(resolver, obj));
const auto pk = ptr.primary_key();
if (ptr.primary_key().is_valid()) {
cont.push_back(ptr);
@@ -194,16 +197,18 @@ private:
template<class Pointer>
void on_foreign_key(Pointer &x, const utils::foreign_attributes &attr) {
if (x.empty()) {
x.reset(new typename Pointer::value_type);
}
const auto resolver = resolver_factory_->resolver<typename Pointer::value_type>();
if (attr.fetch() == utils::fetch_type::Lazy) {
pk_reader_.read(*x, column_index_++);
typename Pointer::value_type obj;
auto pk = id_reader_.read(obj, column_index_++);
x = Pointer(std::make_shared<object::object_proxy<typename Pointer::value_type>>(resolver, pk));
} else {
auto obj = std::make_shared<typename Pointer::value_type>();
const auto ti = std::type_index(typeid(*x));
type_stack_.push(ti);
access::process(*this, *x);
access::process(*this, *obj);
type_stack_.pop();
x = Pointer(std::make_shared<object::object_proxy<typename Pointer::value_type>>(resolver, obj));
}
}
@@ -211,6 +216,8 @@ protected:
size_t column_index_ = 0;
std::vector<object::attribute> prototype_;
std::unique_ptr<query_result_reader> reader_;
std::shared_ptr<object::object_resolver_factory> resolver_factory_;
internal::identifier_reader id_reader_;
detail::pk_reader pk_reader_;
std::stack<std::type_index> type_stack_;
utils::identifier current_pk_{};
@@ -50,9 +50,9 @@ public:
template<class ContainerType>
static void on_has_many(const char * /*id*/, ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {}
template<class ContainerType>
static void on_has_many_to_many(const char *id, ContainerType &c, const char *join_column, const char *inverse_join_column, const utils::foreign_attributes &/*attr*/) {}
static void on_has_many_to_many(const char * /*id*/, ContainerType & /*c*/, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes &/*attr*/) {}
template<class ContainerType>
static void on_has_many_to_many(const char *id, ContainerType &c, const utils::foreign_attributes &/*attr*/) {}
static void on_has_many_to_many(const char * /*id*/, ContainerType & /*c*/, const utils::foreign_attributes &/*attr*/) {}
private:
template<class Type>
@@ -60,8 +60,8 @@ private:
if (fetch == utils::fetch_type::Lazy) {
++column_index_;
} else {
const Type obj;
type_stack_.push(typeid(Type));
const Type obj{};
type_stack_.emplace(typeid(Type));
access::process(*this, obj);
type_stack_.pop();
}
@@ -0,0 +1,24 @@
#ifndef MATADOR_RESOLVER_PRODUCER_HPP
#define MATADOR_RESOLVER_PRODUCER_HPP
#include "matador/object/object_resolver.hpp"
#include <memory>
namespace matador::sql {
class executor;
class resolver_producer {
public:
virtual ~resolver_producer() = default;
virtual std::shared_ptr<object::abstract_object_resolver> produce(executor &exec) = 0;
[[nodiscard]] const std::type_index& type() const;
protected:
explicit resolver_producer(const std::type_index &type);
private:
std::type_index type_;
};
}
#endif //MATADOR_RESOLVER_PRODUCER_HPP
@@ -0,0 +1,35 @@
#ifndef MATADOR_STATEMENT_OBJECT_RESOLVER_HPP
#define MATADOR_STATEMENT_OBJECT_RESOLVER_HPP
#include "matador/object/object_resolver.hpp"
#include "matador/sql/statement.hpp"
#include "matador/sql/internal/identifier_statement_binder.hpp"
namespace matador::sql {
template<typename Type>
class statement_object_resolver : public object::object_resolver<Type> {
public:
explicit statement_object_resolver(statement stmt)
: statement_(std::move(stmt)) {}
std::shared_ptr<Type> resolve(const utils::identifier &id) override;
protected:
statement statement_;
std::type_index index{typeid(Type)};
};
template<typename Type>
std::shared_ptr<Type> statement_object_resolver<Type>::resolve(const utils::identifier &id) {
identifier_statement_binder binder(statement_);
binder.bind(id);
auto result = statement_.template fetch_one<Type>();
if (!result) {
return nullptr;
}
return std::make_shared<Type>(*result);
}
}
#endif //MATADOR_STATEMENT_OBJECT_RESOLVER_HPP
@@ -0,0 +1,21 @@
#ifndef MATADOR_RESOLVER_FACTORY_HPP
#define MATADOR_RESOLVER_FACTORY_HPP
#include "matador/object/object_resolver_factory.hpp"
#include "matador/sql/internal/resolver_producer.hpp"
namespace matador::sql {
class executor;
class producer_resolver_factory : public object::object_resolver_factory {
public:
std::shared_ptr<object::abstract_object_resolver> acquire_resolver(const std::type_index &type) override;
void register_resolver(std::shared_ptr<object::abstract_object_resolver> &&resolver) override;
private:
std::unordered_map<std::type_index, std::shared_ptr<object::abstract_object_resolver>> resolvers_;
};
}
#endif //MATADOR_RESOLVER_FACTORY_HPP
+19 -25
View File
@@ -2,31 +2,29 @@
#define QUERY_QUERY_DATA_HPP
#include "matador/object/attribute.hpp"
#include "matador/object/object_resolver_factory.hpp"
#include "matador/utils/types.hpp"
#include <unordered_map>
namespace matador::sql {
enum class sql_command {
SQL_UNKNOWN,
SQL_CREATE,
SQL_CREATE_TABLE,
SQL_CREATE_SCHEMA,
SQL_CREATE_DATABASE,
SQL_UPDATE,
SQL_INSERT,
SQL_DELETE,
SQL_SELECT,
SQL_DROP,
SQL_DROP_TABLE,
SQL_DROP_SCHEMA,
SQL_DROP_DATABASE,
SQL_ALTER,
SQL_ALTER_TABLE,
SQL_ALTER_SCHEMA
};
SQL_UNKNOWN,
SQL_CREATE,
SQL_CREATE_TABLE,
SQL_CREATE_SCHEMA,
SQL_CREATE_DATABASE,
SQL_UPDATE,
SQL_INSERT,
SQL_DELETE,
SQL_SELECT,
SQL_DROP,
SQL_DROP_TABLE,
SQL_DROP_SCHEMA,
SQL_DROP_DATABASE,
SQL_ALTER,
SQL_ALTER_TABLE,
SQL_ALTER_SCHEMA
};
struct sql_command_info {
std::string sql;
@@ -40,14 +38,10 @@ struct query_context {
std::string schema_name{};
std::string table_name{};
std::vector<object::attribute> prototype{};
// std::vector<std::string> result_vars{};
std::vector<std::string> bind_vars{};
std::vector<utils::database_type> bind_types{};
// std::unordered_map<std::string, std::string> column_aliases{};
// std::unordered_map<std::string, std::string> table_aliases{};
std::shared_ptr<object::object_resolver_factory> resolver_factory{};
};
}
#endif //QUERY_QUERY_DATA_HPP
+132
View File
@@ -0,0 +1,132 @@
#ifndef MATADOR_QUERY_RECORD_RESULT_HPP
#define MATADOR_QUERY_RECORD_RESULT_HPP
#include "matador/sql/query_result.hpp"
namespace matador::sql {
template <>
class query_result<record>;
template <>
class query_result_iterator<record> {
public:
using iterator_category = std::forward_iterator_tag;
using value_type = record;
using difference_type = std::ptrdiff_t;
using self = query_result_iterator; /**< Shortcut for this class. */
using pointer = value_type*; /**< Shortcut for the pointer type. */
using reference = value_type&; /**< Shortcut for the reference type */
public:
query_result_iterator() = default;
explicit query_result_iterator(query_result<record> *res)
: result_(res)
{}
query_result_iterator(query_result<record> *res, record rec)
: record_(std::move(rec))
, result_(res)
{}
query_result_iterator(query_result_iterator&& x) noexcept
: record_(std::move(x.record_))
, result_(x.result_)
{}
query_result_iterator& operator=(query_result_iterator&& x) noexcept {
result_ = x.result_;
record_ = std::move(x.record_);
return *this;
}
~query_result_iterator() = default;
bool operator==(const query_result_iterator& rhs) const {
return record_ == rhs.record_;
}
bool operator!=(const query_result_iterator& rhs) const {
return !(*this == rhs);
}
self& operator++();
self operator++(int);
pointer operator->() { return &record_; }
reference operator*() { return record_; }
record release() { return std::move(record_); }
private:
record record_;
query_result<record> *result_{nullptr};
};
template<>
class query_result<record> final {
public:
using iterator = query_result_iterator<record>;
query_result(std::unique_ptr<query_result_impl> &&impl, const std::vector<object::attribute> &prototype)
: impl_(std::move(impl))
, prototype_(prototype) {}
iterator begin() { return std::move(++iterator(this)); }
iterator end() { return {}; }
private:
friend class query_result_iterator<record>;
[[nodiscard]] record create() const;
void bind(const record& obj) const;
bool fetch(record& obj) const;
protected:
std::unique_ptr<query_result_impl> impl_;
std::vector<object::attribute> prototype_;
};
inline record query_result<record>::create() const {
record rec;
int index{0};
for (const auto &col: prototype_) {
rec.append({
col.name(),
col.type(),
col.attributes().options(),
col.attributes().size(),
index++
});
}
return rec;
}
inline void query_result<record>::bind(const record &obj) const {
impl_->bind(obj);
}
inline bool query_result<record>::fetch(record &obj) const {
return impl_->fetch(obj);
}
inline query_result_iterator<record>::self & query_result_iterator<record>::operator++() {
record_ = result_->create();
result_->bind(record_);
if (!result_->fetch(record_)) {
record_.clear();
}
return *this;
}
inline query_result_iterator<record>::self query_result_iterator<record>::operator++(int) {
self tmp(result_, record_);
record_ = result_->create();
result_->bind(record_);
if (!result_->fetch(record_)) {
record_.clear();
}
return tmp;
}
}
#endif //MATADOR_QUERY_RECORD_RESULT_HPP
+35 -43
View File
@@ -2,22 +2,24 @@
#define QUERY_QUERY_RESULT_HPP
#include "matador/object/attribute.hpp"
#include "matador/object/object_ptr.hpp"
#include "matador/sql/internal/query_result_impl.hpp"
#include <functional>
#include <memory>
namespace matador::sql {
#include "matador/object/object.hpp"
namespace matador::sql {
class record;
class query_result_impl;
template < typename Type >
class query_result;
template < typename Type >
class query_result_iterator
{
class query_result_iterator {
public:
using iterator_category = std::forward_iterator_tag;
using value_type = Type;
@@ -31,7 +33,7 @@ public:
explicit query_result_iterator(query_result<Type> *res)
: result_(res)
{}
query_result_iterator(query_result<Type> *res, std::unique_ptr<Type> obj)
query_result_iterator(query_result<Type> *res, object::object_ptr<Type> obj)
: obj_(std::move(obj))
, result_(res)
{}
@@ -48,19 +50,20 @@ public:
~query_result_iterator() = default;
bool operator==(const query_result_iterator& rhs) {
bool operator==(const query_result_iterator& rhs) const {
return obj_ == rhs.obj_;
}
bool operator!=(const query_result_iterator& rhs) {
return obj_ != rhs.obj_;
bool operator!=(const query_result_iterator& rhs) const {
return !operator==(rhs);
}
self& operator++() {
obj_.reset(result_->create());
result_->bind(*obj_);
if (!result_->fetch(*obj_)) {
obj_.reset();
auto obj = result_->create();
result_->bind(*obj);
obj_.reset();
if (result_->fetch(*obj)) {
obj_ = object::object_ptr<Type>(std::make_shared<object::object_proxy<Type>>(result_->resolver_, std::move(obj)));
}
return *this;
@@ -69,10 +72,11 @@ public:
self operator++(int) {
const self tmp(result_, obj_);
obj_.reset(result_->create());
result_->bind(*obj_);
if (!result_->fetch(*obj_)) {
obj_.reset();
auto obj = result_->create();
result_->bind(*obj);
obj_.reset();
if (result_->fetch(*obj)) {
obj_ = object::object_ptr<Type>(std::make_shared<object::object_proxy<Type>>(result_->resolver_, std::move(obj)));
}
return tmp;
@@ -82,50 +86,37 @@ public:
return obj_.get();
}
reference operator*() {
return *obj_;
object::object_ptr<Type> operator*() {
return obj_;
}
pointer get() {
return obj_.get();
}
pointer release() {
return obj_.release();
object::object_ptr<Type> optr() {
return obj_;
}
private:
std::unique_ptr<Type> obj_;
object::object_ptr<Type> obj_;
query_result<Type> *result_{nullptr};
};
namespace detail {
template < typename Type >
Type* create_prototype(const std::vector<object::attribute> &/*prototype*/) {
return new Type{};
std::shared_ptr<Type> create_prototype(const std::vector<object::attribute> &/*prototype*/) {
return std::make_shared<Type>();
}
template <>
record* create_prototype<record>(const std::vector<object::attribute> &prototype);
record create_prototype(const std::vector<object::attribute> &prototype);
}
template<typename Type>
class query_result final {
public:
using iterator = query_result_iterator<Type>;
using creator_func = std::function<Type*()>;
using creator_func = std::function<std::shared_ptr<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());
// }) {}
query_result(std::unique_ptr<query_result_impl> &&impl, creator_func&& creator)
query_result(std::unique_ptr<query_result_impl> &&impl, const std::shared_ptr<object::object_resolver<Type>> &resolver, creator_func&& creator)
: impl_(std::move(impl))
, resolver_(resolver)
, creator_(std::move(creator)) {}
iterator begin() { return std::move(++iterator(this)); }
@@ -134,17 +125,18 @@ public:
private:
friend class query_result_iterator<Type>;
Type* create();
std::shared_ptr<Type> create();
void bind(const Type& obj);
bool fetch(Type& obj);
protected:
std::unique_ptr<query_result_impl> impl_;
std::shared_ptr<object::object_resolver<Type>> resolver_;
creator_func creator_;
};
template<typename Type>
Type *query_result<Type>::create() {
std::shared_ptr<Type> query_result<Type>::create() {
return creator_();
}
@@ -157,6 +149,6 @@ template<typename Type>
bool query_result<Type>::fetch(Type &obj) {
return impl_->fetch(obj);
}
} // namespace matador::sql
}
// namespace matador::sql
#endif //QUERY_QUERY_RESULT_HPP
+3
View File
@@ -28,6 +28,9 @@ public:
record& operator=(record&&) noexcept = default;
~record() = default;
bool operator==(const record& rhs) const;
bool operator!=(const record& rhs) const;
template<class Operator>
void process(Operator &op) {
for(auto &f : fields_) {
+35 -16
View File
@@ -2,20 +2,20 @@
#define QUERY_STATEMENT_HPP
#include "matador/sql/abstract_sql_logger.hpp"
#include "matador/sql/error_code.hpp"
#include "matador/sql/query_result.hpp"
#include "matador/sql/interface/statement_proxy.hpp"
#include "matador/object/basic_repository.hpp"
#include "matador/utils/error.hpp"
#include "matador/utils/result.hpp"
#include <iostream>
#include <memory>
namespace matador::sql {
namespace detail {
template<class Type>
class identifier_binder;
}
class statement_impl;
class statement_proxy;
@@ -104,7 +104,10 @@ public:
* @return The query result set
*/
template<class Type>
utils::result<std::unique_ptr<Type>, utils::error> fetch_one();
utils::result<object::object_ptr<Type>, utils::error> fetch_one();
template<class Type>
utils::result<std::shared_ptr<Type>, utils::error> fetch_one_raw();
/**
* Fetches the first result of a prepared statement.
* The type is a record representing an unknown variable type.
@@ -140,10 +143,6 @@ public:
[[nodiscard]] utils::result<std::unique_ptr<query_result_impl>, utils::error> fetch_internal() const;
private:
template<class Type>
friend class detail::identifier_binder;
private:
std::shared_ptr<statement_proxy> statement_proxy_;
std::unique_ptr<utils::attribute_writer> bindings_;
@@ -165,31 +164,51 @@ statement &statement::bind(const Type &obj) {
template<class Type>
utils::result<query_result<Type>, utils::error> statement::fetch() {
std::cout << statement_proxy_->sql() << std::endl;
return statement_proxy_->fetch(*bindings_).and_then([](std::unique_ptr<query_result_impl> &&value) {
return statement_proxy_->fetch(*bindings_).and_then([this](std::unique_ptr<query_result_impl> &&value) {
auto resolver = statement_proxy_->statement_->query_.resolver_factory->resolver<Type>();
const auto prototype = value->prototype();
return utils::ok(query_result<Type>(std::forward<decltype(value)>(value), [prototype] {
return utils::ok(query_result<Type>(std::forward<decltype(value)>(value), resolver, [prototype] {
return detail::create_prototype<Type>(prototype);
}));
});
}
template<class Type>
utils::result<std::unique_ptr<Type>, utils::error> statement::fetch_one() {
utils::result<object::object_ptr<Type>, utils::error> statement::fetch_one() {
std::cout << statement_proxy_->sql() << std::endl;
auto result = statement_proxy_->fetch(*bindings_);
if (!result.is_ok()) {
return utils::failure(result.err());
}
auto resolver = statement_proxy_->statement_->query_.resolver_factory->resolver<Type>();
const auto prototype = result.value()->prototype();
auto records = query_result<Type>(result.release(), [prototype] {
auto records = query_result<Type>(result.release(), resolver, [prototype] {
return detail::create_prototype<Type>(prototype);
});
auto first = records.begin();
if (first == records.end()) {
return utils::ok(std::unique_ptr<Type>{nullptr});
return utils::failure(utils::error{
error_code::FETCH_FAILED,
"Failed to find entity."
});
}
return utils::ok(std::unique_ptr<Type>{first.release()});
return utils::ok(first.optr());
}
template<class Type>
utils::result<std::shared_ptr<Type>, utils::error> statement::fetch_one_raw() {
auto result = statement_proxy_->fetch(*bindings_);
if (!result.is_ok()) {
return utils::failure(result.err());
}
auto obj = std::make_shared<Type>();
(*result)->bind(*obj);
if (!(*result)->fetch(*obj)) {
return utils::ok(std::shared_ptr<Type>{});
}
return utils::ok(obj);
}
}
+1 -1
View File
@@ -77,7 +77,7 @@ private:
std::mutex mutex_;
connection_pool &pool_;
const sql::dialect &dialect_;
const dialect &dialect_;
utils::message_bus &bus_;
};