query/include/matador/sql/query_result.hpp

155 lines
3.7 KiB
C++

#ifndef QUERY_QUERY_RESULT_HPP
#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>
#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 {
public:
using iterator_category = std::forward_iterator_tag;
using value_type = Type;
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<Type> *res)
: result_(res)
{}
query_result_iterator(query_result<Type> *res, object::object_ptr<Type> obj)
: obj_(std::move(obj))
, result_(res)
{}
query_result_iterator(query_result_iterator&& x) noexcept
: obj_(std::move(x.obj_))
, result_(x.result_)
{}
query_result_iterator& operator=(query_result_iterator&& x) noexcept {
result_ = x.result_;
obj_ = std::move(x.obj_);
return *this;
}
~query_result_iterator() = default;
bool operator==(const query_result_iterator& rhs) const {
return obj_ == rhs.obj_;
}
bool operator!=(const query_result_iterator& rhs) const {
return !operator==(rhs);
}
self& operator++() {
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;
}
self operator++(int) {
const self tmp(result_, obj_);
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;
}
pointer operator->() {
return obj_.get();
}
object::object_ptr<Type> operator*() {
return obj_;
}
object::object_ptr<Type> optr() {
return obj_;
}
private:
object::object_ptr<Type> obj_;
query_result<Type> *result_{nullptr};
};
namespace detail {
template < typename Type >
std::shared_ptr<Type> create_prototype(const std::vector<object::attribute> &/*prototype*/) {
return std::make_shared<Type>();
}
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<std::shared_ptr<Type>()>;
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)); }
iterator end() { return {}; }
private:
friend class query_result_iterator<Type>;
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>
std::shared_ptr<Type> query_result<Type>::create() {
return creator_();
}
template<typename Type>
void query_result<Type>::bind(const Type &obj) {
impl_->bind(obj);
}
template<typename Type>
bool query_result<Type>::fetch(Type &obj) {
return impl_->fetch(obj);
}
}
// namespace matador::sql
#endif //QUERY_QUERY_RESULT_HPP