implemented prepared statement for postgres and sqlite

This commit is contained in:
2023-12-09 11:08:03 +01:00
parent 8ba70cc79e
commit da423ea8bb
59 changed files with 1769 additions and 314 deletions
+3
View File
@@ -1,6 +1,8 @@
#ifndef QUERY_ANY_TYPE_HPP
#define QUERY_ANY_TYPE_HPP
#include "matador/sql/placeholder.hpp"
#include <string>
#include <variant>
@@ -13,6 +15,7 @@ using any_type = std::variant<
bool,
const char*,
std::string,
placeholder,
nullptr_t>;
}
@@ -10,6 +10,8 @@
namespace matador::sql {
struct placeholder;
template < typename DestType, typename SourceType >
void convert(DestType &dest, SourceType source, typename std::enable_if<std::is_same<DestType, SourceType>::value>::type* = nullptr)
{
@@ -122,6 +124,7 @@ struct any_type_to_visitor
void operator()(double &x) { convert(result, x); }
void operator()(const char *x) { convert(result, x); }
void operator()(std::string &x) { convert(result, x); }
void operator()(placeholder &/*x*/) {}
Type result{};
};
+2 -1
View File
@@ -10,6 +10,7 @@
namespace matador::sql {
class dialect;
class query_context;
class basic_condition
{
@@ -32,7 +33,7 @@ public:
LIKE
};
virtual std::string evaluate(dialect &dialect) const = 0;
virtual std::string evaluate(dialect &dialect, query_context &query) const = 0;
static std::unordered_map<operand_t, std::string> operands;
};
+24 -29
View File
@@ -3,15 +3,13 @@
#include "matador/sql/basic_condition.hpp"
#include "matador/sql/dialect.hpp"
#include "matador/sql/placeholder.hpp"
#include "matador/sql/query_context.hpp"
#include <memory>
namespace matador::sql {
struct placeholder {};
const placeholder _;
/**
* @class condition
* @brief Represents a sql query condition
@@ -27,8 +25,6 @@ const placeholder _;
/// @cond MATADOR_DEV
class query;
template<class L, class R, class Enabled = void>
class condition;
@@ -40,7 +36,7 @@ public:
placeholder value;
std::string evaluate(dialect &d) const override;
std::string evaluate(dialect &d, query_context &query) const override;
};
template<class T>
@@ -57,9 +53,9 @@ public:
T value;
std::string evaluate(dialect &d) const override
std::string evaluate(dialect &d, query_context &query) const override
{
d.add_host_var(field_.name());
query.bind_vars.emplace_back(field_.name());
return d.prepare_identifier(field_.name()) + " " + operand + " " + std::to_string(value);
}
};
@@ -77,9 +73,9 @@ public:
T value;
std::string evaluate(dialect &d) const override
std::string evaluate(dialect &d, query_context &query) const override
{
d.add_host_var(field_.name());
query.bind_vars.emplace_back(field_.name());
return d.prepare_identifier(field_.name()) + " " + operand + " '" + value + "'";
}
};
@@ -98,7 +94,7 @@ public:
T value;
std::string evaluate(dialect &d) const override
std::string evaluate(dialect &d, query_context &query) const override
{
return std::to_string(value) + " " + operand + " " + d.prepare_identifier(field_.name());
}
@@ -117,7 +113,7 @@ public:
T value;
std::string evaluate(dialect &d) const override
std::string evaluate(dialect &d, query_context &query) const override
{
return "'" + std::to_string(value) + "' " + operand + " " + d.prepare_identifier(field_.name());
}
@@ -159,13 +155,12 @@ public:
* @param d The d used to evaluate
* @return A condition IN part of the query
*/
std::string evaluate(dialect &d) const override {
std::string evaluate(dialect &d, query_context &query) const override {
auto count = size();
for (size_t i = 0; i < count; ++i) {
d.add_host_var(field_.name());
query.bind_vars.emplace_back(field_.name());
}
std::string result = d.prepare_identifier(field_.name()) + " IN (";
if (args_.size() < 2) {
for (const auto &val : args_) {
@@ -205,7 +200,7 @@ private:
* @endcode
*/
template <>
class condition<column, query> : public basic_column_condition
class condition<column, query_context> : public basic_column_condition
{
public:
/**
@@ -219,7 +214,7 @@ public:
* @param op Operand of the condition
* @param q The query to be evaluated to the IN arguments
*/
condition(column col, basic_condition::operand_t op, query &q);
condition(column col, basic_condition::operand_t op, query_context &q);
/**
* @brief Evaluates the condition
@@ -230,10 +225,10 @@ public:
* @param d The d used to evaluate
* @return A condition IN part of the query
*/
std::string evaluate(dialect &d) const override;
std::string evaluate(dialect &d, query_context &query) const override;
private:
query &query_;
query_context &query_;
};
/**
@@ -265,9 +260,9 @@ public:
* @param d The d used to evaluate
* @return A condition BETWEEN part of the query
*/
std::string evaluate(dialect &d) const override {
d.add_host_var(field_.name());
d.add_host_var(field_.name());
std::string evaluate(dialect &d, query_context &query) const override {
query.bind_vars.emplace_back(field_.name());
query.bind_vars.emplace_back(field_.name());
return d.prepare_identifier(field_.name()) + " BETWEEN " + std::to_string(range_.first) + " AND " + std::to_string(range_.second);
}
@@ -307,11 +302,11 @@ public:
* @param d The d used to evaluate
* @return The evaluated string based on the compile type
*/
std::string evaluate(dialect &d) const override
std::string evaluate(dialect &d, query_context &query) const override
{
// ensure the numbering order for host vars
auto cl = left.evaluate(d);
auto cr = right.evaluate(d);
auto cl = left.evaluate(d, query);
auto cr = right.evaluate(d, query);
if (operand == basic_condition::operand_t::AND) {
return "(" + cl + " " + basic_condition::operands[operand] + " " + cr + ")";
} else {
@@ -350,7 +345,7 @@ public:
* @param d The d used to evaluate
* @return The evaluated string based on the compile type
*/
std::string evaluate(dialect &d) const override
std::string evaluate(dialect &d, query_context &query) const override
{
return operand + " (" + cond.evaluate(d) + ")";
}
@@ -397,7 +392,7 @@ condition<column, std::initializer_list<V>> in(const column &col, std::initializ
* @param q The query to be executes as sub select
* @return The condition object
*/
condition<column, query> in(const column &col, query &&q);
condition<column, query_context> in(const column &col, query_context &&q);
/**
* @brief Creates a between condition.
@@ -456,7 +451,7 @@ condition<column, T> operator==(const column &col, T val)
* @param q The query to compare with
* @return The condition object representing the equality operation
*/
condition<column, query> equals(const column &col, query &q);
condition<column, query_context> equals(const column &col, query_context &q);
/**
* @brief Condition inequality operator for a column and a value
+4 -2
View File
@@ -4,8 +4,10 @@
#include "matador/sql/connection_info.hpp"
#include "matador/sql/connection_impl.hpp"
#include "matador/sql/dialect.hpp"
#include "matador/sql/query_context.hpp"
#include "matador/sql/query_result.hpp"
#include "matador/sql/record.hpp"
#include "matador/sql/statement.hpp"
#include "matador/utils/logger.hpp"
@@ -13,8 +15,6 @@
namespace matador::sql {
class connection_impl;
class connection
{
public:
@@ -37,6 +37,8 @@ public:
[[nodiscard]] std::unique_ptr<query_result_impl> fetch(const std::string &sql) const;
[[nodiscard]] std::pair<size_t, std::string> execute(const std::string &sql) const;
statement prepare(query_context &&query) const;
private:
connection_info connection_info_;
std::unique_ptr<connection_impl> connection_;
+3 -1
View File
@@ -3,7 +3,9 @@
#include "matador/sql/connection_info.hpp"
#include "matador/sql/query_result_impl.hpp"
#include "matador/sql/query_context.hpp"
#include "matador/sql/record.hpp"
#include "matador/sql/statement_impl.hpp"
#include <memory>
@@ -22,7 +24,7 @@ public:
virtual size_t execute(const std::string &stmt) = 0;
virtual std::unique_ptr<query_result_impl> fetch(const std::string &stmt) = 0;
virtual void prepare(const std::string &stmt) = 0;
virtual std::unique_ptr<statement_impl> prepare(query_context context) = 0;
virtual record describe(const std::string &table) = 0;
virtual bool exists(const std::string &table_name) = 0;
+24 -19
View File
@@ -4,6 +4,7 @@
#include "matador/sql/types.hpp"
#include <cstdint>
#include <functional>
#include <string>
#include <unordered_map>
#include <vector>
@@ -12,7 +13,7 @@ namespace matador::sql {
class column;
class dialect
class dialect final
{
public:
enum class token_t : uint8_t
@@ -65,14 +66,11 @@ public:
using data_type_to_string_map = std::unordered_map<data_type_t, std::string>;
using sql_func_to_string_map = std::unordered_map<sql_function_t, std::string>;
public:
dialect() = default;
dialect(const token_to_string_map &token_replace_map, const data_type_to_string_map &data_type_replace_map);
explicit dialect(const data_type_to_string_map &data_type_replace_map);
explicit dialect(const token_to_string_map &token_replace_map);
using next_placeholder_func = std::function<std::string(size_t)>;
const std::string& token_at(token_t token) const;
const std::string& data_type_at(data_type_t type) const;
public:
[[nodiscard]] const std::string& token_at(token_t token) const;
[[nodiscard]] const std::string& data_type_at(data_type_t type) const;
/**
* Prepare sql dialect identifier for execution
@@ -82,14 +80,14 @@ public:
* @param str The identifier string to be prepared
* @return The prepared string
*/
std::string prepare_identifier(const column &col) const;
[[nodiscard]] std::string prepare_identifier(const column &col) const;
/**
* Prepare string literal
*
* @param str String literal to be prepared
*/
std::string prepare_literal(const std::string &str) const;
[[nodiscard]] std::string prepare_literal(const std::string &str) const;
/**
* Wrap identifier quotes around a sql identifier keyword
@@ -118,7 +116,7 @@ public:
*
* @return How the identifier quotes should be escaped
*/
virtual escape_identifier_t identifier_escape_type() const;
[[nodiscard]] virtual escape_identifier_t identifier_escape_type() const;
/**
* Generates a next placeholder string. default is
@@ -126,17 +124,24 @@ public:
*
* @return Placeholder string
*/
virtual std::string next_placeholder() const;
[[nodiscard]] std::string next_placeholder(const std::vector<std::string> &bind_vars) const;
void add_host_var(const std::string &host_var);
void add_column(const std::string &column);
const std::vector<std::string>& host_vars() const;
const std::vector<std::string>& columns() const;
/**
* Returns the default schema name.
*
* @return The default schema name.
*/
[[nodiscard]] std::string default_schema_name() const;
private:
std::vector<std::string> host_vars_;
std::vector<std::string> columns_;
dialect() = default;
private:
friend class dialect_builder;
next_placeholder_func placeholder_func_ = [](size_t) { return "?"; };
std::string default_schema_name_;
token_to_string_map tokens_ {
{token_t::CREATE, "CREATE"},
+30
View File
@@ -0,0 +1,30 @@
#ifndef QUERY_DIALECT_BUILDER_HPP
#define QUERY_DIALECT_BUILDER_HPP
#include "matador/sql/dialect.hpp"
namespace matador::sql {
class dialect_builder
{
public:
static dialect_builder& builder();
dialect_builder& create();
dialect_builder& with_token_replace_map(const dialect::token_to_string_map &token_replace_map);
dialect_builder& with_data_type_replace_map(const dialect::data_type_to_string_map &data_type_replace_map);
dialect_builder& with_placeholder_func(const dialect::next_placeholder_func &func);
dialect_builder& with_default_schema_name(const std::string &schema_name);
dialect build();
private:
dialect_builder() = default;
private:
dialect dialect_;
};
}
#endif //QUERY_DIALECT_BUILDER_HPP
+55
View File
@@ -0,0 +1,55 @@
#ifndef QUERY_OBJECT_BINDER_HPP
#define QUERY_OBJECT_BINDER_HPP
#include "matador/utils/cascade_type.hpp"
#include "matador/utils/field_attributes.hpp"
#include <string>
namespace matador::sql {
class parameter_binder;
class object_binder
{
public:
explicit object_binder(parameter_binder &binder);
void reset();
template < class V >
void on_primary_key(const char *id, V &val, typename std::enable_if<std::is_integral<V>::value && !std::is_same<bool, V>::value>::type* = 0)
{
binder_.bind(index_++, val);
}
void on_primary_key(const char *id, std::string &, size_t);
void on_revision(const char *id, unsigned long long &/*rev*/);
template<typename Type>
void on_attribute(const char *id, Type &val, const utils::field_attributes &/*attr*/ = utils::null_attributes)
{
binder_.bind(index_++, val);
}
template<class Type, template < class ... > class Pointer>
void on_belongs_to(const char *id, Pointer<Type> &x, utils::cascade_type)
{
// binder_.bind(index_++, val);
}
template<class Type, template < class ... > class Pointer>
void on_has_one(const char *id, Pointer<Type> &x, utils::cascade_type)
{
// binder_.bind(index_++, val);
}
template<class ContainerType>
void on_has_many(const char *, ContainerType &, const char *, const char *, utils::cascade_type) {}
template<class ContainerType>
void on_has_many(const char *, ContainerType &, utils::cascade_type) {}
private:
parameter_binder &binder_;
size_t index_{0};
};
}
#endif //QUERY_OBJECT_BINDER_HPP
+37
View File
@@ -0,0 +1,37 @@
#ifndef QUERY_PARAMETER_BINDER_HPP
#define QUERY_PARAMETER_BINDER_HPP
#include <string>
#include <cstring>
namespace matador::sql {
class parameter_binder
{
public:
virtual ~parameter_binder() = default;
virtual void bind(size_t pos, char) = 0;
virtual void bind(size_t pos, short) = 0;
virtual void bind(size_t pos, int) = 0;
virtual void bind(size_t pos, long) = 0;
virtual void bind(size_t pos, long long) = 0;
virtual void bind(size_t pos, unsigned char) = 0;
virtual void bind(size_t pos, unsigned short) = 0;
virtual void bind(size_t pos, unsigned int) = 0;
virtual void bind(size_t pos, unsigned long) = 0;
virtual void bind(size_t pos, unsigned long long) = 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 matador::time&) = 0;
// virtual void bind(size_t pos, const matador::date&) = 0;
};
}
#endif //QUERY_PARAMETER_BINDER_HPP
+14
View File
@@ -0,0 +1,14 @@
#ifndef QUERY_PLACEHOLDER_HPP
#define QUERY_PLACEHOLDER_HPP
namespace matador::sql {
struct placeholder {};
inline constexpr bool operator==(const placeholder&, const placeholder&) { return true; }
const placeholder _;
}
#endif //QUERY_PLACEHOLDER_HPP
@@ -0,0 +1,49 @@
#ifndef QUERY_PLACEHOLDER_GENERATOR_HPP
#define QUERY_PLACEHOLDER_GENERATOR_HPP
#include "matador/sql/any_type.hpp"
#include "matador/utils/cascade_type.hpp"
#include "matador/utils/field_attributes.hpp"
#include <vector>
namespace matador::sql {
class placeholder_generator
{
public:
template < class V >
void on_primary_key(const char *id, V &val, typename std::enable_if<std::is_integral<V>::value && !std::is_same<bool, V>::value>::type* = 0)
{
placeholder_values.emplace_back(_);
}
void on_primary_key(const char *id, std::string &, size_t);
void on_revision(const char *id, unsigned long long &/*rev*/);
template<typename Type>
void on_attribute(const char *id, Type &val, const utils::field_attributes &/*attr*/ = utils::null_attributes)
{
placeholder_values.emplace_back(_);
}
template<class Type, template < class ... > class Pointer>
void on_belongs_to(const char *id, Pointer<Type> &x, utils::cascade_type)
{
placeholder_values.emplace_back(_);
}
template<class Type, template < class ... > class Pointer>
void on_has_one(const char *id, Pointer<Type> &x, utils::cascade_type)
{
placeholder_values.emplace_back(_);
}
template<class ContainerType>
void on_has_many(const char *, ContainerType &, const char *, const char *, utils::cascade_type) {}
template<class ContainerType>
void on_has_many(const char *, ContainerType &, utils::cascade_type) {}
std::vector<any_type> placeholder_values;
};
}
#endif //QUERY_PLACEHOLDER_GENERATOR_HPP
+7 -11
View File
@@ -4,6 +4,7 @@
#include "matador/sql/basic_condition.hpp"
#include "matador/sql/column.hpp"
#include "matador/sql/key_value_pair.hpp"
#include "matador/sql/query_context.hpp"
#include "matador/sql/record.hpp"
#include <string>
@@ -18,7 +19,7 @@ class dialect;
namespace detail {
struct any_type_to_string_visitor
{
explicit any_type_to_string_visitor(const dialect &d) : d(d) {}
explicit any_type_to_string_visitor(const dialect &d, query_context &query);
void operator()(char &x) { to_string(x); }
void operator()(short &x) { to_string(x); }
@@ -35,6 +36,7 @@ struct any_type_to_string_visitor
void operator()(double &x) { to_string(x); }
void operator()(const char *x) { to_string(x); }
void operator()(std::string &x) { to_string(x); }
void operator()(placeholder &x) { to_string(x); }
template<typename Type>
void to_string(Type &val)
@@ -43,8 +45,10 @@ struct any_type_to_string_visitor
}
void to_string(const char *val);
void to_string(std::string &val);
void to_string(placeholder &val);
const dialect &d;
query_context &query;
std::string result;
};
@@ -59,14 +63,6 @@ enum class join_type_t {
INNER, OUTER, LEFT, RIGHT
};
struct query
{
std::string sql;
std::string table_name;
record prototype;
std::vector<any_type> host_vars;
};
class query_builder
{
private:
@@ -134,7 +130,7 @@ public:
query_builder& offset(size_t count);
query_builder& limit(size_t count);
query compile();
query_context compile();
private:
void transition_to(state_t next);
@@ -150,7 +146,7 @@ private:
detail::any_type_to_string_visitor value_to_string_;
query query_;
query_context query_;
using query_state_set = std::unordered_set<state_t>;
using query_state_transition_map = std::unordered_map<state_t, query_state_set>;
+20
View File
@@ -0,0 +1,20 @@
#ifndef QUERY_QUERY_CONTEXT_HPP
#define QUERY_QUERY_CONTEXT_HPP
#include "matador/sql/record.hpp"
namespace matador::sql {
struct query_context
{
std::string sql;
std::string command_name;
std::string table_name;
record prototype;
std::vector<any_type> host_vars;
std::vector<std::string> bind_vars;
};
}
#endif //QUERY_QUERY_CONTEXT_HPP
+21 -1
View File
@@ -6,9 +6,11 @@
#include "matador/sql/column_name_generator.hpp"
#include "matador/sql/key_value_generator.hpp"
#include "matador/sql/key_value_pair.hpp"
#include "matador/sql/placeholder_generator.hpp"
#include "matador/sql/query_builder.hpp"
#include "matador/sql/query_result.hpp"
#include "matador/sql/record.hpp"
#include "matador/sql/statement.hpp"
#include "matador/sql/table_repository.hpp"
#include "matador/sql/value_extractor.hpp"
@@ -35,6 +37,7 @@ public:
using query_intermediate::query_intermediate;
std::pair<size_t, std::string> execute();
statement prepare();
};
class query_select_finish : public query_intermediate
@@ -57,6 +60,8 @@ public:
return fetch_one().at(0).as<Type>();
}
statement prepare();
private:
std::unique_ptr<query_result_impl> fetch();
};
@@ -140,6 +145,15 @@ public:
query_from_intermediate from(const std::string &table, const std::string &as = "");
};
template < class Type >
std::vector<any_type> as_placeholder(const Type &obj)
{
placeholder_generator generator;
matador::utils::access::process(generator, obj);
return generator.placeholder_values;
}
class query_into_intermediate : public query_intermediate
{
public:
@@ -147,6 +161,12 @@ public:
query_execute_finish values(std::initializer_list<any_type> values);
template<class Type>
query_execute_finish values()
{
Type obj;
return {session_, builder_.values(as_placeholder(obj))};
}
template<class Type>
query_execute_finish values(const Type &obj)
{
return {session_, builder_.values(value_extractor::extract(obj))};
@@ -216,7 +236,7 @@ public:
class query_update_intermediate : public query_start_intermediate
{
public:
query_update_intermediate(session &s, std::string table_name);
query_update_intermediate(session &s, const std::string& table_name);
query_set_intermediate set(std::initializer_list<key_value_pair> columns);
template<class Type>
-14
View File
@@ -1,14 +0,0 @@
#ifndef QUERY_RESULT_HPP
#define QUERY_RESULT_HPP
#include <string>
namespace matador::sql {
struct result
{
std::string sql;
};
}
#endif //QUERY_RESULT_HPP
+10 -5
View File
@@ -6,6 +6,7 @@
#include "matador/sql/connection_pool.hpp"
#include "matador/sql/query_builder.hpp"
#include "matador/sql/query_intermediates.hpp"
#include "matador/sql/statement.hpp"
#include "matador/sql/table_repository.hpp"
#include <unordered_map>
@@ -22,18 +23,16 @@ public:
query_create_intermediate create();
query_drop_intermediate drop();
template < class Type >
query_select_intermediate select()
{
return query_select_intermediate{*this, column_generator::generate<Type>(table_repository_)};
}
query_select_intermediate select();
query_select_intermediate select(std::initializer_list<column> columns);
query_insert_intermediate insert();
query_update_intermediate update(const std::string &table);
query_delete_intermediate remove();
[[nodiscard]] query_result<record> fetch(const query &q) const;
[[nodiscard]] query_result<record> fetch(const query_context &q) const;
// [[nodiscard]] query_result<record> fetch(const std::string &sql) const;
[[nodiscard]] std::pair<size_t, std::string> execute(const std::string &sql) const;
statement prepare(query_context q) const;
record describe_table(const std::string &table_name) const;
bool table_exists(const std::string &table_name) const;
@@ -61,5 +60,11 @@ private:
mutable std::unordered_map<std::string, record> prototypes_;
};
template<class Type>
query_select_intermediate session::select()
{
return query_select_intermediate{*this, column_generator::generate<Type>(table_repository_)};
}
}
#endif //QUERY_SESSION_HPP
+55
View File
@@ -0,0 +1,55 @@
#ifndef QUERY_STATEMENT_HPP
#define QUERY_STATEMENT_HPP
#include "matador/sql/object_binder.hpp"
#include "matador/sql/query_result.hpp"
#include "matador/sql/statement_impl.hpp"
#include "matador/utils/logger.hpp"
#include <memory>
namespace matador::sql {
class statement
{
public:
explicit statement(std::unique_ptr<statement_impl> impl, const utils::logger &logger);
template < typename Type >
statement& bind(size_t pos, const Type &value)
{
statement_->bind(pos, value);
return *this;
}
statement& bind(size_t pos, std::string &val, size_t size);
template < class Type >
statement& bind(const Type &obj)
{
object_binder_.reset();
matador::utils::access::process(object_binder_, obj);
return *this;
}
size_t execute();
template<class Type>
query_result<Type> fetch()
{
logger_.info(statement_->query_.sql);
return query_result<Type>(statement_->fetch());
}
query_result<record> fetch();
void reset();
private:
std::unique_ptr<statement_impl> statement_;
const utils::logger &logger_;
object_binder object_binder_;
};
}
#endif //QUERY_STATEMENT_HPP
+36
View File
@@ -0,0 +1,36 @@
#ifndef QUERY_STATEMENT_CACHE_HPP
#define QUERY_STATEMENT_CACHE_HPP
#include "matador/sql/statement.hpp"
#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>
namespace matador::sql {
class connection;
struct cache_info
{
std::unique_ptr<statement> statement_;
size_t connection_id_;
};
class statement_cache
{
public:
statement& acquire(const std::string &stmt, const connection &conn);
void release(const statement &stmt);
private:
mutable std::mutex mutex_;
size_t max_cache_size_{256};
std::hash<std::string> hash_;
using statement_map = std::unordered_map<size_t, cache_info>;
statement_map statement_map_;
};
}
#endif //QUERY_STATEMENT_CACHE_HPP
+47
View File
@@ -0,0 +1,47 @@
#ifndef QUERY_STATEMENT_IMPL_HPP
#define QUERY_STATEMENT_IMPL_HPP
#include "matador/sql/query_context.hpp"
#include "matador/sql/query_result_impl.hpp"
#include "matador/sql/parameter_binder.hpp"
#include <memory>
namespace matador::sql {
class statement_impl
{
protected:
explicit statement_impl(query_context query);
public:
virtual ~statement_impl() = default;
virtual size_t execute() = 0;
virtual std::unique_ptr<query_result_impl> fetch() = 0;
template < class V >
void bind(size_t pos, V &val)
{
binder().bind(pos, val);
}
void bind(size_t pos, std::string &val, size_t size)
{
binder().bind(pos, val, size);
}
virtual void reset() = 0;
protected:
virtual parameter_binder& binder() = 0;
protected:
friend class statement;
query_context query_;
};
}
#endif //QUERY_STATEMENT_IMPL_HPP