#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 #include #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 *res) : result_(res) {} query_result_iterator(query_result *res, object::object_ptr 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(std::make_shared>(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(std::make_shared>(result_->resolver_, std::move(obj))); } return tmp; } pointer operator->() { return obj_.get(); } object::object_ptr operator*() { return obj_; } object::object_ptr optr() { return obj_; } private: object::object_ptr obj_; query_result *result_{nullptr}; }; namespace detail { template < typename Type > std::shared_ptr create_prototype(const std::vector &/*prototype*/) { return std::make_shared(); } record create_prototype(const std::vector &prototype); } template class query_result final { public: using iterator = query_result_iterator; using creator_func = std::function()>; query_result(std::unique_ptr &&impl, const std::shared_ptr> &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; std::shared_ptr create(); void bind(const Type& obj); bool fetch(Type& obj); protected: std::unique_ptr impl_; std::shared_ptr> resolver_; creator_func creator_; }; template std::shared_ptr query_result::create() { return creator_(); } template void query_result::bind(const Type &obj) { impl_->bind(obj); } template bool query_result::fetch(Type &obj) { return impl_->fetch(obj); } } // namespace matador::sql #endif //QUERY_QUERY_RESULT_HPP