#ifndef QUERY_STATEMENT_HPP #define QUERY_STATEMENT_HPP #include "matador/sql/abstract_sql_logger.hpp" #include "matador/sql/query_result.hpp" #include "matador/sql/interface/statement_proxy.hpp" #include "matador/utils/error.hpp" #include "matador/utils/result.hpp" #include namespace matador::sql { namespace detail { template class identifier_binder; } class statement_impl; class statement_proxy; class statement { public: using logger_ptr = std::shared_ptr; /** * Creates a statement initialized from the * given statement implementation object holding * the implementation for the selected database * * @param proxy The statement proxy implementation object * @param logger The logger handler to write SQL log messages to */ explicit statement(const std::shared_ptr& proxy, logger_ptr logger = null_logger); /** * Copy move constructor for statement * * @param x The statement to move from */ statement(statement &&x) noexcept; /** * Assignment move constructor for statement * * @param x The statement to move from * @return Reference to this */ statement &operator=(statement &&x) noexcept; statement(const statement &x); statement &operator=(const statement &x); statement &bind(size_t pos, const char *value); statement &bind(size_t pos, std::string &val, size_t size); /** * Bind an object to the statement starting * at the given position index. * * @param obj The object to bind * @return The next index to bind */ template statement &bind(const Type &obj); template statement &bind(size_t pos, Type &value); /** * Executes the prepared statement and returns * the number of affected rows. * * @return The number of affected rows */ [[nodiscard]] utils::result execute() const; /** * Fetches the result of the prepared * statement. If a prepared statement was not * a SELECT statement, an empty query result set * is returned. * * @tparam Type Type of the fetched result * @return The query result set */ template utils::result, utils::error> fetch(); /** * Fetches the result of the prepared * statement. The type is the record representing an * unknown variable type. * If the prepared statement was not * a SELECT statement, an empty query result set * is returned. * * @return The query result set */ [[nodiscard]] utils::result, utils::error> fetch() const; /** * Fetches the first result of a prepared statement. * If a prepared statement is empty or not * a SELECT statement, a nullptr is returned. * * @tparam Type Type of the fetched result * @return The query result set */ template utils::result, utils::error> fetch_one(); /** * Fetches the first result of a prepared statement. * The type is a record representing an unknown variable type. * If a prepared statement is empty or not * a SELECT statement, a nullptr is returned. * * @return The query result set */ [[nodiscard]] utils::result, utils::error> fetch_one() const; /** * Resets the prepared statement to * reuse it. */ void reset() const; [[nodiscard]] std::string sql() const; [[nodiscard]] utils::result, utils::error> fetch_internal() const; private: template friend class detail::identifier_binder; private: std::shared_ptr statement_proxy_; std::unique_ptr bindings_; std::shared_ptr logger_; }; template statement &statement::bind(size_t pos, Type &value) { statement_proxy_->bind(pos, value, *bindings_); return *this; } template statement &statement::bind(const Type &obj) { statement_proxy_->bind(obj, *bindings_); return *this; } template utils::result, utils::error> statement::fetch() { return statement_proxy_->fetch(*bindings_).and_then([](std::unique_ptr &&value) { return utils::ok(query_result(std::forward(value))); }); // if (!result.is_ok()) { // return utils::error(result.err()); // } // return query_result(result.release()); } template utils::result, utils::error> statement::fetch_one() { auto result = statement_proxy_->fetch(*bindings_); if (!result.is_ok()) { return utils::failure(result.err()); } auto records = query_result(result.release()); auto first = records.begin(); if (first == records.end()) { return utils::ok(std::unique_ptr{nullptr}); } return utils::ok(std::unique_ptr{first.release()}); } } #endif //QUERY_STATEMENT_HPP