implemented prepared statement for postgres and sqlite
This commit is contained in:
@@ -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{};
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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,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,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;
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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>;
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user