moved parameter_binder from member to parameter to bind, execute and fetch methods
This commit is contained in:
parent
ebd8bccfb3
commit
6e2baad3ef
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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_;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue