moved parameter_binder from member to parameter to bind, execute and fetch methods

This commit is contained in:
sascha 2025-07-30 21:00:40 +02:00
parent ebd8bccfb3
commit 6e2baad3ef
18 changed files with 169 additions and 168 deletions

View File

@ -1,14 +1,13 @@
#ifndef QUERY_POSTGRES_PARAMETER_BINDER_H #ifndef QUERY_POSTGRES_PARAMETER_BINDER_H
#define QUERY_POSTGRES_PARAMETER_BINDER_H #define QUERY_POSTGRES_PARAMETER_BINDER_H
#include "matador/utils/attribute_writer.hpp" #include "matador/sql/interface/parameter_binder.hpp"
#include <vector> #include <vector>
namespace matador::backends::postgres { namespace matador::backends::postgres {
class postgres_parameter_binder final : public utils::attribute_writer class postgres_parameter_binder final : public sql::interface::parameter_binder {
{
public: public:
struct bind_data { struct bind_data {
explicit bind_data(size_t size); explicit bind_data(size_t size);

View File

@ -2,8 +2,7 @@
#define QUERY_POSTGRES_STATEMENT_HPP #define QUERY_POSTGRES_STATEMENT_HPP
#include "matador/sql/interface/statement_impl.hpp" #include "matador/sql/interface/statement_impl.hpp"
#include "matador/sql/interface/parameter_binder.hpp"
#include "postgres_parameter_binder.h"
#include <libpq-fe.h> #include <libpq-fe.h>
@ -14,18 +13,17 @@ class postgres_statement final : public sql::statement_impl
public: public:
postgres_statement(PGconn *db, std::string name, const sql::query_context &query); postgres_statement(PGconn *db, std::string name, const sql::query_context &query);
utils::result<size_t, utils::error> execute() override; utils::result<size_t, utils::error> execute(const sql::interface::parameter_binder& bindings) override;
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetch() override; utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetch(const sql::interface::parameter_binder& bindings) override;
void reset() override; void reset() override;
protected: protected:
utils::attribute_writer& binder() override; [[nodiscard]] std::unique_ptr<utils::attribute_writer> create_binder() const override;
private: private:
PGconn *db_{nullptr}; PGconn *db_{nullptr};
std::string name_; std::string name_;
postgres_parameter_binder binder_;
}; };
} }

View File

@ -53,7 +53,7 @@ postgres_parameter_binder::bind_data::bind_data(const size_t size)
, formats(size) , formats(size)
{} {}
postgres_parameter_binder::postgres_parameter_binder(size_t size) postgres_parameter_binder::postgres_parameter_binder(const size_t size)
: bind_data_(size) : bind_data_(size)
{} {}

View File

@ -1,5 +1,6 @@
#include "postgres_statement.hpp" #include "postgres_statement.hpp"
#include "postgres_error.hpp" #include "postgres_error.hpp"
#include "postgres_parameter_binder.h"
#include "postgres_result_reader.hpp" #include "postgres_result_reader.hpp"
namespace matador::backends::postgres { namespace matador::backends::postgres {
@ -8,17 +9,19 @@ postgres_statement::postgres_statement(PGconn *db, std::string name, const sql::
: statement_impl(query) : statement_impl(query)
, db_(db) , db_(db)
, name_(std::move(name)) , name_(std::move(name))
, binder_(query_.bind_vars.size())
{} {}
utils::result<size_t, utils::error> postgres_statement::execute() utils::result<size_t, utils::error> postgres_statement::execute(const sql::interface::parameter_binder& bindings) {
{ const auto* postgres_bindings = dynamic_cast<const postgres_parameter_binder*>(&bindings);
if (!postgres_bindings) {
return utils::failure(utils::error(sql::error_code::EXECUTE_FAILED, "Failed to cast bindings to postgres bindings"));
}
PGresult *res = PQexecPrepared(db_, PGresult *res = PQexecPrepared(db_,
name_.c_str(), name_.c_str(),
static_cast<int>(binder_.params().values.size()), static_cast<int>(postgres_bindings->params().values.size()),
binder_.params().values.data(), postgres_bindings->params().values.data(),
binder_.params().lengths.data(), postgres_bindings->params().lengths.data(),
binder_.params().formats.data(), postgres_bindings->params().formats.data(),
0); 0);
if (is_result_error(res)) { if (is_result_error(res)) {
@ -30,17 +33,20 @@ utils::result<size_t, utils::error> postgres_statement::execute()
return utils::ok(static_cast<size_t>(0)); return utils::ok(static_cast<size_t>(0));
} }
return utils::ok(static_cast<size_t>(std::stoul(tuples))); return utils::ok((std::stoul(tuples)));
} }
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> postgres_statement::fetch() utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> postgres_statement::fetch(const sql::interface::parameter_binder& bindings) {
{ const auto* postgres_bindings = dynamic_cast<const postgres_parameter_binder*>(&bindings);
if (!postgres_bindings) {
return utils::failure(utils::error(sql::error_code::EXECUTE_FAILED, "Failed to cast bindings to postgres bindings"));
}
PGresult *res = PQexecPrepared(db_, PGresult *res = PQexecPrepared(db_,
name_.c_str(), name_.c_str(),
static_cast<int>(binder_.params().values.size()), static_cast<int>(postgres_bindings->params().values.size()),
binder_.params().values.data(), postgres_bindings->params().values.data(),
binder_.params().lengths.data(), postgres_bindings->params().lengths.data(),
binder_.params().formats.data(), postgres_bindings->params().formats.data(),
0); 0);
if (is_result_error(res)) { if (is_result_error(res)) {
@ -52,9 +58,7 @@ utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> postgres_st
void postgres_statement::reset() {} void postgres_statement::reset() {}
utils::attribute_writer& postgres_statement::binder() std::unique_ptr<utils::attribute_writer> postgres_statement::create_binder() const {
{ return std::make_unique<postgres_parameter_binder>(query_.bind_vars.size());
return binder_;
} }
} }

View File

@ -1,37 +1,11 @@
#ifndef QUERY_PARAMETER_BINDER_HPP #ifndef QUERY_PARAMETER_BINDER_HPP
#define QUERY_PARAMETER_BINDER_HPP #define QUERY_PARAMETER_BINDER_HPP
#include "matador/utils/types.hpp" #include "matador/utils/attribute_writer.hpp"
#include <string>
#include <cstring>
namespace matador::sql::interface { namespace matador::sql::interface {
class parameter_binder using parameter_binder = utils::attribute_writer;
{
public:
virtual ~parameter_binder() = default;
virtual void bind(size_t pos, int8_t) = 0;
virtual void bind(size_t pos, int16_t) = 0;
virtual void bind(size_t pos, int32_t) = 0;
virtual void bind(size_t pos, int64_t) = 0;
virtual void bind(size_t pos, uint8_t) = 0;
virtual void bind(size_t pos, uint16_t) = 0;
virtual void bind(size_t pos, uint32_t) = 0;
virtual void bind(size_t pos, uint64_t) = 0;
virtual void bind(size_t pos, bool) = 0;
virtual void bind(size_t pos, float) = 0;
virtual void bind(size_t pos, double) = 0;
virtual void bind(size_t pos, const char *) = 0;
virtual void bind(size_t pos, const char *, size_t size) = 0;
virtual void bind(size_t pos, const std::string&) = 0;
virtual void bind(size_t pos, const std::string &x, size_t size) = 0;
virtual void bind(size_t pos, const utils::blob &) = 0;
// virtual void bind(size_t pos, const matador::time&) = 0;
// virtual void bind(size_t pos, const matador::date&) = 0;
};
} }

View File

@ -3,6 +3,7 @@
#include "matador/sql/query_context.hpp" #include "matador/sql/query_context.hpp"
#include "matador/sql/internal/query_result_impl.hpp" #include "matador/sql/internal/query_result_impl.hpp"
#include "matador/sql/interface/parameter_binder.hpp"
#include "matador/sql/object_parameter_binder.hpp" #include "matador/sql/object_parameter_binder.hpp"
#include "matador/utils/data_type_traits.hpp" #include "matador/utils/data_type_traits.hpp"
@ -21,24 +22,23 @@ protected:
public: public:
virtual ~statement_impl() = default; virtual ~statement_impl() = default;
virtual utils::result<size_t, utils::error> execute() = 0; virtual utils::result<size_t, utils::error> execute(const interface::parameter_binder& bindings) = 0;
virtual utils::result<std::unique_ptr<query_result_impl>, utils::error> fetch() = 0; virtual utils::result<std::unique_ptr<query_result_impl>, utils::error> fetch(const interface::parameter_binder& bindings) = 0;
template < class Type > template < class Type >
void bind_object(Type &obj) void bind_object(Type &obj, const interface::parameter_binder& bindings) {
{
object_parameter_binder object_binder_; object_parameter_binder object_binder_;
object_binder_.reset(start_index()); object_binder_.reset(start_index());
object_binder_.bind(obj, binder()); object_binder_.bind(obj, bindings);
} }
template < class Type > template < class Type >
void bind(const size_t pos, Type &val) { void bind(const size_t pos, Type &val, const interface::parameter_binder& bindings) {
utils::data_type_traits<Type>::bind_value(binder(), adjust_index(pos), val); utils::data_type_traits<Type>::bind_value(bindings, adjust_index(pos), val);
} }
void bind(size_t pos, const char *value, size_t size); void bind(size_t pos, const char *value, size_t size, interface::parameter_binder& bindings) const;
void bind(size_t pos, std::string &val, size_t size); void bind(size_t pos, std::string &val, size_t size, interface::parameter_binder& bindings) const;
virtual void reset() = 0; virtual void reset() = 0;
@ -46,12 +46,13 @@ public:
[[nodiscard]] bool is_valid_host_var(const std::string &host_var, size_t pos) const; [[nodiscard]] bool is_valid_host_var(const std::string &host_var, size_t pos) const;
protected: protected:
virtual utils::attribute_writer& binder() = 0;
[[nodiscard]] virtual size_t start_index() const; [[nodiscard]] virtual size_t start_index() const;
[[nodiscard]] virtual size_t adjust_index(size_t index) const; [[nodiscard]] virtual size_t adjust_index(size_t index) const;
[[nodiscard]] virtual std::unique_ptr<utils::attribute_writer> create_binder() const = 0;
protected: protected:
friend class statement; friend class statement;
friend class statement_proxy;
query_context query_; query_context query_;
}; };

View File

@ -2,6 +2,7 @@
#define STATEMENT_PROXY_HPP #define STATEMENT_PROXY_HPP
#include "matador/sql/interface/statement_impl.hpp" #include "matador/sql/interface/statement_impl.hpp"
#include "matador/sql/interface/parameter_binder.hpp"
namespace matador::sql { namespace matador::sql {
class statement_proxy { class statement_proxy {
@ -11,22 +12,24 @@ protected:
public: public:
virtual ~statement_proxy() = default; virtual ~statement_proxy() = default;
virtual utils::result<size_t, utils::error> execute() = 0; virtual utils::result<size_t, utils::error> execute(interface::parameter_binder& bindings) = 0;
virtual utils::result<std::unique_ptr<query_result_impl>, utils::error> fetch() = 0; virtual utils::result<std::unique_ptr<query_result_impl>, utils::error> fetch(interface::parameter_binder& bindings) = 0;
template<class Type> template<class Type>
void bind(const Type &obj) { void bind(const Type &obj, const interface::parameter_binder& bindings) {
statement_->bind_object(obj); statement_->bind_object(obj, bindings);
} }
template<typename Type> template<typename Type>
void bind(size_t pos, Type &value) { void bind(size_t pos, Type &value, const interface::parameter_binder& bindings) {
statement_->bind(pos, value); statement_->bind(pos, value, bindings);
} }
void bind(size_t pos, const char *value, size_t size) const; void bind(size_t pos, const char *value, size_t size, interface::parameter_binder& bindings) const;
void bind(size_t pos, std::string &val, size_t size) const; void bind(size_t pos, std::string &val, size_t size, interface::parameter_binder& bindings) const;
void reset() const; void reset() const;
[[nodiscard]] std::unique_ptr<utils::attribute_writer> create_binder() const;
protected: protected:
std::unique_ptr<statement_impl> statement_; std::unique_ptr<statement_impl> statement_;
}; };

View File

@ -9,8 +9,6 @@
#include "matador/utils/foreign_attributes.hpp" #include "matador/utils/foreign_attributes.hpp"
#include "matador/utils/primary_key_attribute.hpp" #include "matador/utils/primary_key_attribute.hpp"
#include <string>
namespace matador::sql { namespace matador::sql {
namespace detail { namespace detail {
@ -61,8 +59,7 @@ private:
} }
class object_parameter_binder class object_parameter_binder {
{
public: public:
template<class Type> template<class Type>
void bind(Type &obj, utils::attribute_writer &binder) { void bind(Type &obj, utils::attribute_writer &binder) {

View File

@ -5,6 +5,7 @@
#include "matador/sql/query_result.hpp" #include "matador/sql/query_result.hpp"
#include "matador/sql/interface/statement_proxy.hpp" #include "matador/sql/interface/statement_proxy.hpp"
#include "matador/sql/interface/parameter_binder.hpp"
#include "matador/utils/error.hpp" #include "matador/utils/error.hpp"
#include "matador/utils/result.hpp" #include "matador/utils/result.hpp"
@ -38,10 +39,7 @@ public:
* *
* @param x The statement to move from * @param x The statement to move from
*/ */
statement(statement &&x) noexcept statement(statement &&x) noexcept;
: statement_proxy_(std::move(x.statement_proxy_))
, logger_(std::move(x.logger_)) {
}
/** /**
* Assignment move constructor for statement * Assignment move constructor for statement
@ -49,14 +47,10 @@ public:
* @param x The statement to move from * @param x The statement to move from
* @return Reference to this * @return Reference to this
*/ */
statement &operator=(statement &&x) noexcept { statement &operator=(statement &&x) noexcept;
statement_proxy_ = std::move(x.statement_proxy_);
logger_ = std::move(x.logger_);
return *this;
}
statement(const statement &x) = default; statement(const statement &x);
statement &operator=(const statement &x) = default; statement &operator=(const statement &x);
statement &bind(size_t pos, const char *value); statement &bind(size_t pos, const char *value);
statement &bind(size_t pos, std::string &val, size_t size); statement &bind(size_t pos, std::string &val, size_t size);
@ -134,24 +128,25 @@ private:
private: private:
std::shared_ptr<statement_proxy> statement_proxy_; std::shared_ptr<statement_proxy> statement_proxy_;
std::unique_ptr<utils::attribute_writer> bindings_;
std::shared_ptr<abstract_sql_logger> logger_; std::shared_ptr<abstract_sql_logger> logger_;
}; };
template<typename Type> template<typename Type>
statement &statement::bind(size_t pos, Type &value) { statement &statement::bind(size_t pos, Type &value) {
statement_proxy_->bind(pos, value); statement_proxy_->bind(pos, value, *bindings_);
return *this; return *this;
} }
template<class Type> template<class Type>
statement &statement::bind(const Type &obj) { statement &statement::bind(const Type &obj) {
statement_proxy_->bind(obj); statement_proxy_->bind(obj, bindings_);
return *this; return *this;
} }
template<class Type> template<class Type>
utils::result<query_result<Type>, utils::error> statement::fetch() { utils::result<query_result<Type>, utils::error> statement::fetch() {
return statement_proxy_->fetch().and_then([](std::unique_ptr<query_result_impl> &&value) { 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))); return utils::ok(query_result<Type>(std::forward<decltype(value)>(value)));
}); });
// if (!result.is_ok()) { // if (!result.is_ok()) {
@ -162,7 +157,7 @@ utils::result<query_result<Type>, utils::error> statement::fetch() {
template<class Type> template<class Type>
utils::result<std::unique_ptr<Type>, utils::error> statement::fetch_one() { utils::result<std::unique_ptr<Type>, utils::error> statement::fetch_one() {
auto result = statement_proxy_->fetch(); auto result = statement_proxy_->fetch(*bindings_);
if (!result.is_ok()) { if (!result.is_ok()) {
return utils::failure(result.err()); return utils::failure(result.err());
} }

View File

@ -19,11 +19,11 @@ public:
explicit connection_statement_proxy(std::unique_ptr<statement_impl>&& stmt) explicit connection_statement_proxy(std::unique_ptr<statement_impl>&& stmt)
: statement_proxy(std::move(stmt)) {} : statement_proxy(std::move(stmt)) {}
utils::result<size_t, utils::error> execute() override { utils::result<size_t, utils::error> execute(interface::parameter_binder& bindings) override {
return statement_->execute(); return statement_->execute(bindings);
} }
utils::result<std::unique_ptr<query_result_impl>, utils::error> fetch() override { utils::result<std::unique_ptr<query_result_impl>, utils::error> fetch(interface::parameter_binder& bindings) override {
return statement_->fetch(); return statement_->fetch(bindings);
} }
}; };

View File

@ -6,35 +6,29 @@ statement_impl::statement_impl(query_context query)
: query_(std::move(query)) : query_(std::move(query))
{} {}
void statement_impl::bind(const size_t pos, const char *value, const size_t size) void statement_impl::bind(const size_t pos, const char *value, const size_t size, interface::parameter_binder& bindings) const {
{ utils::data_type_traits<const char*>::bind_value(bindings, adjust_index(pos), value, size);
utils::data_type_traits<const char*>::bind_value(binder(), adjust_index(pos), value, size);
} }
void statement_impl::bind(const size_t pos, std::string &val, const size_t size) void statement_impl::bind(const size_t pos, std::string &val, const size_t size, interface::parameter_binder& bindings) const {
{ utils::data_type_traits<std::string>::bind_value(bindings, adjust_index(pos), val, size);
utils::data_type_traits<std::string>::bind_value(binder(), adjust_index(pos), val, size);
} }
const std::vector<std::string> &statement_impl::bind_vars() const const std::vector<std::string> &statement_impl::bind_vars() const {
{
return query_.bind_vars; return query_.bind_vars;
} }
bool statement_impl::is_valid_host_var(const std::string &host_var, const size_t pos) const bool statement_impl::is_valid_host_var(const std::string &host_var, const size_t pos) const {
{
const auto host_var_at_pos = bind_vars().at(pos); const auto host_var_at_pos = bind_vars().at(pos);
return host_var_at_pos == host_var; return host_var_at_pos == host_var;
} }
size_t statement_impl::start_index() const size_t statement_impl::start_index() const {
{
return 0; return 0;
} }
size_t statement_impl::adjust_index( size_t index ) const size_t statement_impl::adjust_index(const size_t index) const {
{
return index; return index;
} }

View File

@ -4,14 +4,18 @@ namespace matador::sql {
statement_proxy::statement_proxy(std::unique_ptr<statement_impl>&& stmt) statement_proxy::statement_proxy(std::unique_ptr<statement_impl>&& stmt)
: statement_(std::move(stmt)){} : statement_(std::move(stmt)){}
void statement_proxy::bind(const size_t pos, const char* value, const size_t size) const { void statement_proxy::bind(const size_t pos, const char* value, const size_t size, interface::parameter_binder& bindings) const {
statement_->bind(pos, value, size); statement_->bind(pos, value, size, bindings);
} }
void statement_proxy::bind(const size_t pos, std::string& val, const size_t size) const { void statement_proxy::bind(const size_t pos, std::string& val, const size_t size, interface::parameter_binder& bindings) const {
statement_->bind(pos, val, size); statement_->bind(pos, val, size, bindings);
} }
void statement_proxy::reset() const { void statement_proxy::reset() const {
statement_->reset(); statement_->reset();
} }
std::unique_ptr<utils::attribute_writer> statement_proxy::create_binder() const {
return statement_->create_binder();
}
} }

View File

@ -11,20 +11,47 @@ statement::statement(const std::shared_ptr<statement_proxy>& proxy, logger_ptr
: statement_proxy_(proxy) : statement_proxy_(proxy)
, logger_(std::move(logger)){} , logger_(std::move(logger)){}
statement &statement::bind(const size_t pos, const char *value) { statement::statement(statement&& x) noexcept
statement_proxy_->bind(pos, value, strlen(value)); : statement_proxy_(std::move(x.statement_proxy_))
, bindings_(std::move(x.bindings_))
, logger_(std::move(x.logger_)) {
}
statement& statement::operator=(statement&& x) noexcept {
statement_proxy_ = std::move(x.statement_proxy_);
bindings_ = std::move(x.bindings_);
logger_ = std::move(x.logger_);
return *this; return *this;
} }
statement &statement::bind(const size_t pos, std::string &val, const size_t size) statement::statement(const statement& x)
{ : statement_proxy_(x.statement_proxy_)
statement_proxy_->bind(pos, val, size); , bindings_(x.statement_proxy_->create_binder())
, logger_(x.logger_) {
}
statement& statement::operator=(const statement& x) {
if (&x == this) {
return *this;
}
statement_proxy_ = x.statement_proxy_;
bindings_ = x.statement_proxy_->create_binder();
logger_ = x.logger_;
return *this;
}
statement &statement::bind(const size_t pos, const char *value) {
statement_proxy_->bind(pos, value, strlen(value), *bindings_);
return *this;
}
statement &statement::bind(const size_t pos, std::string &val, const size_t size) {
statement_proxy_->bind(pos, val, size, *bindings_);
return *this; return *this;
} }
utils::result<size_t, utils::error> statement::execute() const { utils::result<size_t, utils::error> statement::execute() const {
// logger_.info(statement_->query_.sql); // logger_.info(statement_->query_.sql);
return statement_proxy_->execute(); return statement_proxy_->execute(*bindings_);
} }
//bool is_unknown(const std::vector<object::column_definition> &columns) { //bool is_unknown(const std::vector<object::column_definition> &columns) {
@ -39,7 +66,7 @@ utils::result<query_result<record>, utils::error> statement::fetch() const {
// } // }
auto result = statement_proxy_->fetch(); auto result = statement_proxy_->fetch(*bindings_);
if (!result.is_ok()) { if (!result.is_ok()) {
return utils::failure(result.err()); return utils::failure(result.err());
} }
@ -49,7 +76,7 @@ utils::result<query_result<record>, utils::error> statement::fetch() const {
utils::result<std::optional<record>, utils::error> statement::fetch_one() const { utils::result<std::optional<record>, utils::error> statement::fetch_one() const {
// logger_.info(statement_->query_.sql); // logger_.info(statement_->query_.sql);
auto result = statement_proxy_->fetch(); auto result = statement_proxy_->fetch(*bindings_);
if (!result.is_ok()) { if (!result.is_ok()) {
return utils::failure(result.err()); return utils::failure(result.err());
} }

View File

@ -10,11 +10,11 @@ public:
explicit statement_cache_proxy(std::unique_ptr<statement_impl>&& stmt) explicit statement_cache_proxy(std::unique_ptr<statement_impl>&& stmt)
: statement_proxy(std::move(stmt)) {} : statement_proxy(std::move(stmt)) {}
utils::result<size_t, utils::error> execute() override { utils::result<size_t, utils::error> execute(interface::parameter_binder& bindings) override {
return statement_->execute(); return statement_->execute(bindings);
} }
utils::result<std::unique_ptr<query_result_impl>, utils::error> fetch() override { utils::result<std::unique_ptr<query_result_impl>, utils::error> fetch(interface::parameter_binder& bindings) override {
return statement_->fetch(); return statement_->fetch(bindings);
} }
}; };
@ -43,8 +43,8 @@ utils::result<statement, utils::error> statement_cache::acquire(const query_cont
// If cache max size reached ensure space // If cache max size reached ensure space
if (cache_map_.size() >= max_size_) { if (cache_map_.size() >= max_size_) {
const size_t& lru_key = usage_list_.back(); const auto& key_to_remove = usage_list_.back();
cache_map_.erase(lru_key); cache_map_.erase(key_to_remove);
usage_list_.pop_back(); usage_list_.pop_back();
} }

View File

@ -1,4 +1,5 @@
#include "test_connection.hpp" #include "test_connection.hpp"
#include "test_statement.hpp"
#include "test_result_reader.hpp" #include "test_result_reader.hpp"
#include "matador/sql/query_context.hpp" #include "matador/sql/query_context.hpp"
@ -17,25 +18,21 @@ namespace matador::test::orm {
test_connection::test_connection(const sql::connection_info &info) test_connection::test_connection(const sql::connection_info &info)
: connection_impl(info) {} : connection_impl(info) {}
utils::result<void, utils::error> test_connection::open() utils::result<void, utils::error> test_connection::open() {
{
is_open_ = true; is_open_ = true;
return utils::ok<void>(); return utils::ok<void>();
} }
utils::result<void, utils::error> test_connection::close() utils::result<void, utils::error> test_connection::close() {
{
is_open_ = false; is_open_ = false;
return utils::ok<void>(); return utils::ok<void>();
} }
utils::result<bool, utils::error> test_connection::is_open() const utils::result<bool, utils::error> test_connection::is_open() const {
{
return utils::ok(is_open_); return utils::ok(is_open_);
} }
utils::result<bool, utils::error> test_connection::is_valid() const utils::result<bool, utils::error> test_connection::is_valid() const {
{
return is_open(); return is_open();
} }
@ -47,33 +44,28 @@ utils::result<utils::version, utils::error> test_connection::server_version() co
return utils::ok(utils::version{3, 2, 1}); return utils::ok(utils::version{3, 2, 1});
} }
utils::result<size_t, utils::error> test_connection::execute(const std::string &/*stmt*/) utils::result<size_t, utils::error> test_connection::execute(const std::string &/*stmt*/) {
{
return utils::ok(static_cast<size_t>(4)); return utils::ok(static_cast<size_t>(4));
} }
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> test_connection::fetch(const sql::query_context &context) utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> test_connection::fetch(const sql::query_context &context) {
{
return utils::ok(std::make_unique<sql::query_result_impl>(std::make_unique<test_result_reader>(), context.prototype, context.prototype.size())); return utils::ok(std::make_unique<sql::query_result_impl>(std::make_unique<test_result_reader>(), context.prototype, context.prototype.size()));
} }
utils::result<std::unique_ptr<sql::statement_impl>, utils::error> test_connection::prepare(const sql::query_context &/*context*/) utils::result<std::unique_ptr<sql::statement_impl>, utils::error> test_connection::prepare(const sql::query_context &context) {
{ std::unique_ptr<sql::statement_impl> s(std::make_unique<test_statement>(context));
return utils::ok(std::unique_ptr<sql::statement_impl>{}); return utils::ok(std::move(s));
} }
utils::result<std::vector<object::attribute_definition>, utils::error> test_connection::describe(const std::string &/*table*/) utils::result<std::vector<object::attribute_definition>, utils::error> test_connection::describe(const std::string &/*table*/) {
{
return utils::ok(std::vector<object::attribute_definition>{}); return utils::ok(std::vector<object::attribute_definition>{});
} }
utils::result<bool, utils::error> test_connection::exists(const std::string &/*schema_name*/, const std::string &/*table_name*/) utils::result<bool, utils::error> test_connection::exists(const std::string &/*schema_name*/, const std::string &/*table_name*/) {
{
return utils::ok(false); return utils::ok(false);
} }
std::string test_connection::to_escaped_string(const utils::blob& value) const std::string test_connection::to_escaped_string(const utils::blob& value) const {
{
return utils::to_string(value); return utils::to_string(value);
} }

View File

@ -1,22 +1,22 @@
#include "test_statement.hpp" #include "test_statement.hpp"
#include "test_result_reader.hpp" #include "test_result_reader.hpp"
#include "test_parameter_binder.hpp"
namespace matador::test::orm { namespace matador::test::orm {
test_statement::test_statement(const sql::query_context &query) test_statement::test_statement(const sql::query_context &query)
: statement_impl(query) {} : statement_impl(query) {}
utils::result<size_t, utils::error> test_statement::execute() { utils::result<size_t, utils::error> test_statement::execute(const sql::interface::parameter_binder &/*bindings*/) {
return utils::ok(static_cast<size_t>(8)); return utils::ok(static_cast<size_t>(8));
} }
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> test_statement::fetch() { utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> test_statement::fetch(const sql::interface::parameter_binder &/*bindings*/) {
return utils::ok(std::make_unique<sql::query_result_impl>(std::make_unique<test_result_reader>(), query_.prototype, query_.prototype.size())); return utils::ok(std::make_unique<sql::query_result_impl>(std::make_unique<test_result_reader>(), query_.prototype, query_.prototype.size()));
} }
void test_statement::reset() {} void test_statement::reset() {}
std::unique_ptr<utils::attribute_writer> test_statement::create_binder() const {
utils::attribute_writer &test_statement::binder() { return std::make_unique<test_parameter_binder>();
return binder_;
} }
} // namespace matador::test::orm } // namespace matador::test::orm

View File

@ -1,8 +1,6 @@
#ifndef TEST_STATEMENT_HPP #ifndef TEST_STATEMENT_HPP
#define TEST_STATEMENT_HPP #define TEST_STATEMENT_HPP
#include "test_parameter_binder.hpp"
#include "matador/sql/interface/statement_impl.hpp" #include "matador/sql/interface/statement_impl.hpp"
namespace matador::test::orm { namespace matador::test::orm {
@ -10,15 +8,12 @@ namespace matador::test::orm {
class test_statement final : public sql::statement_impl { class test_statement final : public sql::statement_impl {
public: public:
explicit test_statement(const sql::query_context &query); explicit test_statement(const sql::query_context &query);
utils::result<size_t, utils::error> execute() override; utils::result<size_t, utils::error> execute(const sql::interface::parameter_binder &bindings) override;
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetch() override; utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetch(const sql::interface::parameter_binder &bindings) override;
void reset() override; void reset() override;
protected: protected:
utils::attribute_writer &binder() override; [[nodiscard]] std::unique_ptr<utils::attribute_writer> create_binder() const override;
private:
test_parameter_binder binder_;
}; };
} }

View File

@ -17,12 +17,12 @@ TEST_CASE("Test statement cache", "[statement][cache]") {
backend_provider::instance().register_backend("noop", std::make_unique<orm::test_backend_service>()); backend_provider::instance().register_backend("noop", std::make_unique<orm::test_backend_service>());
connection_pool pool("noop://noop.db", 4); connection_pool pool("noop://noop.db", 4);
statement_cache cache(pool, 4); statement_cache cache(pool, 2);
query_context ctx; query_context ctx;
ctx.sql = "SELECT * FROM person"; ctx.sql = "SELECT * FROM person";
REQUIRE(cache.capacity() == 4); REQUIRE(cache.capacity() == 2);
REQUIRE(cache.empty()); REQUIRE(cache.empty());
auto result = cache.acquire(ctx); auto result = cache.acquire(ctx);
@ -30,7 +30,25 @@ TEST_CASE("Test statement cache", "[statement][cache]") {
REQUIRE(cache.size() == 1); REQUIRE(cache.size() == 1);
REQUIRE(!cache.empty()); REQUIRE(!cache.empty());
REQUIRE(cache.capacity() == 4); REQUIRE(cache.capacity() == 2);
const auto stmt = result.value(); const auto stmt = result.value();
ctx.sql = "SELECT title FROM book";
result = cache.acquire(ctx);
REQUIRE(result);
REQUIRE(cache.size() == 2);
REQUIRE(!cache.empty());
REQUIRE(cache.capacity() == 2);
ctx.sql = "SELECT name FROM author";
result = cache.acquire(ctx);
REQUIRE(result);
REQUIRE(cache.size() == 2);
REQUIRE(!cache.empty());
REQUIRE(cache.capacity() == 2);
} }