#ifndef QUERY_QUERY_RESULT_HPP #define QUERY_QUERY_RESULT_HPP #include #include "matador/sql/query_result_impl.hpp" #include namespace matador::sql { 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, std::unique_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) { return obj_ == rhs.obj_; } bool operator!=(const query_result_iterator& rhs) { return obj_ != rhs.obj_; } self& operator++() { obj_.reset(result_->create()); result_->bind(*obj_); if (!result_->fetch(*obj_)) { obj_.reset(); } return *this; } self operator++(int) { const self tmp(result_, obj_); obj_.reset(result_->create()); result_->bind(*obj_); if (!result_->fetch(*obj_)) { obj_.reset(); } return std::move(tmp); } pointer operator->() { return obj_.get(); } reference operator*() { return *obj_; } pointer get() { return obj_.get(); } pointer release() { return obj_.release(); } private: std::unique_ptr obj_; query_result *result_{nullptr}; }; namespace detail { template < typename Type > Type* create_prototype(const record &/*prototype*/) { return new Type{}; } template <> record* create_prototype(const record &prototype); } template < typename Type > class query_result { public: using iterator = query_result_iterator; using creator_func = std::function; public: explicit query_result(std::unique_ptr impl) : impl_(std::move(impl)) {} query_result(std::unique_ptr impl, record record_prototype) : record_prototype_(std::move(record_prototype)) , impl_(std::move(impl)) {} iterator begin() { return std::move(++iterator(this)); } iterator end() { return {}; } private: friend class query_result_iterator; Type* create() { return detail::create_prototype(record_prototype_); } void bind(const Type &obj) { impl_->bind(obj); } bool fetch(Type &obj) { return impl_->fetch(obj); } private: record record_prototype_; std::unique_ptr impl_; }; } #endif //QUERY_QUERY_RESULT_HPP