178 lines
4.8 KiB
C++
178 lines
4.8 KiB
C++
#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 <memory>
|
|
|
|
namespace matador::sql {
|
|
namespace detail {
|
|
template<class Type>
|
|
class identifier_binder;
|
|
}
|
|
|
|
class statement_impl;
|
|
class statement_proxy;
|
|
|
|
class statement {
|
|
public:
|
|
using logger_ptr = std::shared_ptr<abstract_sql_logger>;
|
|
|
|
/**
|
|
* 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<statement_proxy>& 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<class Type>
|
|
statement &bind(const Type &obj);
|
|
template<typename Type>
|
|
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<size_t, utils::error> 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<class Type>
|
|
utils::result<query_result<Type>, 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<query_result<record>, 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<class Type>
|
|
utils::result<std::unique_ptr<Type>, 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<std::optional<record>, utils::error> fetch_one() const;
|
|
|
|
/**
|
|
* Resets the prepared statement to
|
|
* reuse it.
|
|
*/
|
|
void reset() const;
|
|
|
|
[[nodiscard]] std::string sql() const;
|
|
|
|
[[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_;
|
|
std::shared_ptr<abstract_sql_logger> logger_;
|
|
};
|
|
|
|
template<typename Type>
|
|
statement &statement::bind(size_t pos, Type &value) {
|
|
statement_proxy_->bind(pos, value, *bindings_);
|
|
return *this;
|
|
}
|
|
|
|
template<class Type>
|
|
statement &statement::bind(const Type &obj) {
|
|
statement_proxy_->bind(obj, *bindings_);
|
|
return *this;
|
|
}
|
|
|
|
template<class Type>
|
|
utils::result<query_result<Type>, utils::error> statement::fetch() {
|
|
return statement_proxy_->fetch(*bindings_).and_then([](std::unique_ptr<query_result_impl> &&value) {
|
|
return utils::ok(query_result<Type>(std::forward<decltype(value)>(value)));
|
|
});
|
|
// if (!result.is_ok()) {
|
|
// return utils::error(result.err());
|
|
// }
|
|
// return query_result<Type>(result.release());
|
|
}
|
|
|
|
template<class Type>
|
|
utils::result<std::unique_ptr<Type>, utils::error> statement::fetch_one() {
|
|
auto result = statement_proxy_->fetch(*bindings_);
|
|
if (!result.is_ok()) {
|
|
return utils::failure(result.err());
|
|
}
|
|
auto records = query_result<Type>(result.release());
|
|
auto first = records.begin();
|
|
if (first == records.end()) {
|
|
return utils::ok(std::unique_ptr<Type>{nullptr});
|
|
}
|
|
|
|
return utils::ok(std::unique_ptr<Type>{first.release()});
|
|
}
|
|
}
|
|
|
|
#endif //QUERY_STATEMENT_HPP
|