implemented prepared statement for postgres and sqlite
This commit is contained in:
+18
-3
@@ -19,7 +19,13 @@ set(SQL_SOURCES
|
||||
sql/table_repository.cpp
|
||||
sql/any_type_to_visitor.cpp
|
||||
sql/query_result.cpp
|
||||
sql/query_result_reader.cpp)
|
||||
sql/query_result_reader.cpp
|
||||
sql/statement_cache.cpp
|
||||
sql/statement_impl.cpp
|
||||
sql/dialect_builder.cpp
|
||||
sql/object_binder.cpp
|
||||
sql/placeholder_generator.cpp
|
||||
)
|
||||
|
||||
set(SQL_HEADER
|
||||
../include/matador/sql/dialect.hpp
|
||||
@@ -31,7 +37,6 @@ set(SQL_HEADER
|
||||
../include/matador/sql/condition.hpp
|
||||
../include/matador/sql/connection.hpp
|
||||
../include/matador/sql/query_intermediates.hpp
|
||||
../include/matador/sql/result.hpp
|
||||
../include/matador/sql/record.hpp
|
||||
../include/matador/sql/query_result.hpp
|
||||
../include/matador/sql/connection_impl.hpp
|
||||
@@ -50,7 +55,17 @@ set(SQL_HEADER
|
||||
../include/matador/sql/table_repository.hpp
|
||||
../include/matador/sql/any_type_to_visitor.hpp
|
||||
../include/matador/sql/query_result_reader.hpp
|
||||
../include/matador/sql/to_value.hpp)
|
||||
../include/matador/sql/to_value.hpp
|
||||
../include/matador/sql/statement_cache.hpp
|
||||
../include/matador/sql/statement.hpp
|
||||
../include/matador/sql/statement_impl.hpp
|
||||
../include/matador/sql/query_context.hpp
|
||||
sql/statement.cpp
|
||||
../include/matador/sql/parameter_binder.hpp
|
||||
../include/matador/sql/dialect_builder.hpp
|
||||
../include/matador/sql/object_binder.hpp
|
||||
../include/matador/sql/placeholder_generator.hpp
|
||||
)
|
||||
|
||||
set(UTILS_HEADER
|
||||
../include/matador/utils/field_attributes.hpp
|
||||
|
||||
+13
-13
@@ -3,21 +3,21 @@
|
||||
namespace matador::sql {
|
||||
|
||||
condition<column, placeholder, std::enable_if<true>::type>::condition(const column &fld, basic_condition::operand_t op, const placeholder &val)
|
||||
: basic_column_condition(fld, op)
|
||||
, value(val)
|
||||
{ }
|
||||
|
||||
std::string condition<column, placeholder, std::enable_if<true>::type>::evaluate(dialect &d) const {
|
||||
d.add_host_var(field_.name());
|
||||
return d.prepare_identifier(field_.name()) + " " + operand + " " + d.next_placeholder();
|
||||
}
|
||||
|
||||
condition<column, query>::condition(column col, basic_condition::operand_t op, query &q)
|
||||
: basic_column_condition(std::move(col), op)
|
||||
, query_(q)
|
||||
: basic_column_condition(fld, op), value(val)
|
||||
{}
|
||||
|
||||
std::string condition<column, query>::evaluate(dialect &d) const {
|
||||
std::string condition<column, placeholder, std::enable_if<true>::type>::evaluate(dialect &d, query_context &query) const
|
||||
{
|
||||
query.bind_vars.emplace_back(field_.name());
|
||||
return d.prepare_identifier(field_.name()) + " " + operand + " " + d.next_placeholder(query.bind_vars);
|
||||
}
|
||||
|
||||
condition<column, query_context>::condition(column col, basic_condition::operand_t op, query_context &q)
|
||||
: basic_column_condition(std::move(col), op), query_(q)
|
||||
{}
|
||||
|
||||
std::string condition<column, query_context>::evaluate(dialect &d, query_context &query) const
|
||||
{
|
||||
std::string result(d.prepare_identifier(field_.name()) + " " + operand + " (");
|
||||
result += (")");
|
||||
return result;
|
||||
|
||||
@@ -88,4 +88,9 @@ std::unique_ptr<query_result_impl> connection::fetch(const std::string &sql) con
|
||||
return connection_->fetch(sql);
|
||||
}
|
||||
|
||||
statement connection::prepare(query_context &&query) const
|
||||
{
|
||||
return statement(connection_->prepare(std::move(query)), logger_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-38
@@ -5,25 +5,6 @@
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
dialect::dialect(const dialect::token_to_string_map &token_replace_map, const dialect::data_type_to_string_map &data_type_replace_map)
|
||||
{
|
||||
for (const auto &token : token_replace_map) {
|
||||
tokens_[token.first] = token.second;
|
||||
}
|
||||
|
||||
for (const auto &data_type : data_type_replace_map) {
|
||||
data_types_[data_type.first] = data_type.second;
|
||||
}
|
||||
}
|
||||
|
||||
dialect::dialect(const dialect::data_type_to_string_map &data_type_replace_map)
|
||||
: dialect({}, data_type_replace_map)
|
||||
{}
|
||||
|
||||
dialect::dialect(const dialect::token_to_string_map &token_replace_map)
|
||||
: dialect(token_replace_map, {})
|
||||
{}
|
||||
|
||||
const std::string& dialect::token_at(dialect::token_t token) const
|
||||
{
|
||||
return tokens_.at(token);
|
||||
@@ -85,29 +66,14 @@ dialect::escape_identifier_t dialect::identifier_escape_type() const
|
||||
return dialect::escape_identifier_t::ESCAPE_BOTH_SAME;
|
||||
}
|
||||
|
||||
std::string dialect::next_placeholder() const
|
||||
std::string dialect::next_placeholder(const std::vector<std::string> &bind_vars) const
|
||||
{
|
||||
return "?";
|
||||
return placeholder_func_(bind_vars.size());
|
||||
}
|
||||
|
||||
void dialect::add_host_var(const std::string &host_var)
|
||||
std::string dialect::default_schema_name() const
|
||||
{
|
||||
host_vars_.emplace_back(host_var);
|
||||
}
|
||||
|
||||
void dialect::add_column(const std::string &column)
|
||||
{
|
||||
columns_.emplace_back(column);
|
||||
}
|
||||
|
||||
const std::vector<std::string> &dialect::host_vars() const
|
||||
{
|
||||
return host_vars_;
|
||||
}
|
||||
|
||||
const std::vector<std::string> &dialect::columns() const
|
||||
{
|
||||
return columns_;
|
||||
return default_schema_name_;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#include "matador/sql/dialect_builder.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
dialect_builder &dialect_builder::builder()
|
||||
{
|
||||
static dialect_builder instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
dialect_builder &dialect_builder::create()
|
||||
{
|
||||
dialect_ = {};
|
||||
return *this;
|
||||
}
|
||||
|
||||
dialect_builder& dialect_builder::with_token_replace_map(const dialect::token_to_string_map &token_replace_map)
|
||||
{
|
||||
for (const auto &token : token_replace_map) {
|
||||
dialect_.tokens_[token.first] = token.second;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
dialect_builder& dialect_builder::with_data_type_replace_map(const dialect::data_type_to_string_map &data_type_replace_map)
|
||||
{
|
||||
for (const auto &data_type : data_type_replace_map) {
|
||||
dialect_.data_types_[data_type.first] = data_type.second;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
dialect_builder& dialect_builder::with_placeholder_func(const dialect::next_placeholder_func &func)
|
||||
{
|
||||
dialect_.placeholder_func_ = func;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
dialect_builder &dialect_builder::with_default_schema_name(const std::string &schema_name)
|
||||
{
|
||||
dialect_.default_schema_name_ = schema_name;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
dialect dialect_builder::build()
|
||||
{
|
||||
return dialect_;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#include "matador/sql/object_binder.hpp"
|
||||
#include "matador/sql/parameter_binder.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
object_binder::object_binder(parameter_binder &binder)
|
||||
: binder_(binder) {}
|
||||
|
||||
void object_binder::reset()
|
||||
{
|
||||
index_ = 0;
|
||||
}
|
||||
|
||||
void object_binder::on_primary_key(const char *id, std::string &val, size_t)
|
||||
{
|
||||
binder_.bind(index_++, val);
|
||||
}
|
||||
|
||||
void object_binder::on_revision(const char *id, unsigned long long int &rev)
|
||||
{
|
||||
binder_.bind(index_++, rev);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "matador/sql/placeholder_generator.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
void placeholder_generator::on_primary_key(const char *id, std::string &, size_t)
|
||||
{
|
||||
placeholder_values.emplace_back(_);
|
||||
}
|
||||
|
||||
void placeholder_generator::on_revision(const char *id, unsigned long long int &)
|
||||
{
|
||||
placeholder_values.emplace_back(_);
|
||||
}
|
||||
|
||||
}
|
||||
+153
-114
@@ -9,6 +9,9 @@ namespace matador::sql {
|
||||
|
||||
namespace detail {
|
||||
|
||||
any_type_to_string_visitor::any_type_to_string_visitor(const dialect &d, query_context &query)
|
||||
: d(d), query(query) {}
|
||||
|
||||
void any_type_to_string_visitor::to_string(const char *val)
|
||||
{
|
||||
result = "'" + d.prepare_literal(val) + "'";
|
||||
@@ -19,69 +22,76 @@ void any_type_to_string_visitor::to_string(std::string &val)
|
||||
result = "'" + d.prepare_literal(val) + "'";
|
||||
}
|
||||
|
||||
void any_type_to_string_visitor::to_string(placeholder &/*val*/)
|
||||
{
|
||||
query.bind_vars.emplace_back("unknown");
|
||||
result = d.next_placeholder(query.bind_vars);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// poor mens state machine
|
||||
// but does the job for query
|
||||
query_builder::query_state_transition_map query_builder::transitions_{
|
||||
{state_t::QUERY_INIT, {state_t::QUERY_CREATE, state_t::QUERY_DROP, state_t::QUERY_SELECT, state_t::QUERY_INSERT, state_t::QUERY_UPDATE, state_t::QUERY_DELETE}},
|
||||
{state_t::QUERY_CREATE, {state_t::QUERY_TABLE_CREATE}},
|
||||
{state_t::QUERY_DROP, {state_t::QUERY_TABLE_DROP}},
|
||||
{state_t::QUERY_SELECT, {state_t::QUERY_FROM}},
|
||||
{state_t::QUERY_INSERT, {state_t::QUERY_INTO}},
|
||||
{state_t::QUERY_UPDATE, {state_t::QUERY_SET}},
|
||||
{state_t::QUERY_DELETE, {state_t::QUERY_FROM}},
|
||||
{state_t::QUERY_TABLE_CREATE, {state_t::QUERY_FINISH}},
|
||||
{state_t::QUERY_TABLE_DROP, {state_t::QUERY_FINISH}},
|
||||
{state_t::QUERY_FROM, {state_t::QUERY_OFFSET, state_t::QUERY_LIMIT, state_t::QUERY_WHERE, state_t::QUERY_ORDER_BY, state_t::QUERY_GROUP_BY, state_t::QUERY_FINISH}},
|
||||
{state_t::QUERY_SET, {state_t::QUERY_WHERE, state_t::QUERY_FINISH}},
|
||||
{state_t::QUERY_INTO, {state_t::QUERY_VALUES}},
|
||||
{state_t::QUERY_WHERE, {state_t::QUERY_ORDER_BY, state_t::QUERY_GROUP_BY, state_t::QUERY_OFFSET, state_t::QUERY_LIMIT, state_t::QUERY_FINISH}},
|
||||
{state_t::QUERY_ORDER_BY, {state_t::QUERY_ORDER_DIRECTION}},
|
||||
{state_t::QUERY_ORDER_DIRECTION, {state_t::QUERY_OFFSET, state_t::QUERY_LIMIT, state_t::QUERY_FINISH}},
|
||||
{state_t::QUERY_GROUP_BY, {state_t::QUERY_ORDER_BY, state_t::QUERY_FINISH}},
|
||||
{state_t::QUERY_OFFSET, {state_t::QUERY_LIMIT}},
|
||||
{state_t::QUERY_LIMIT, {state_t::QUERY_FINISH}},
|
||||
{state_t::QUERY_VALUES, {state_t::QUERY_FINISH}},
|
||||
{state_t::QUERY_FINISH, {}},
|
||||
{state_t::QUERY_INIT, {state_t::QUERY_CREATE, state_t::QUERY_DROP, state_t::QUERY_SELECT, state_t::QUERY_INSERT, state_t::QUERY_UPDATE, state_t::QUERY_DELETE}},
|
||||
{state_t::QUERY_CREATE, {state_t::QUERY_TABLE_CREATE}},
|
||||
{state_t::QUERY_DROP, {state_t::QUERY_TABLE_DROP}},
|
||||
{state_t::QUERY_SELECT, {state_t::QUERY_FROM}},
|
||||
{state_t::QUERY_INSERT, {state_t::QUERY_INTO}},
|
||||
{state_t::QUERY_UPDATE, {state_t::QUERY_SET}},
|
||||
{state_t::QUERY_DELETE, {state_t::QUERY_FROM}},
|
||||
{state_t::QUERY_TABLE_CREATE, {state_t::QUERY_FINISH}},
|
||||
{state_t::QUERY_TABLE_DROP, {state_t::QUERY_FINISH}},
|
||||
{state_t::QUERY_FROM, {state_t::QUERY_OFFSET, state_t::QUERY_LIMIT, state_t::QUERY_WHERE, state_t::QUERY_ORDER_BY, state_t::QUERY_GROUP_BY, state_t::QUERY_FINISH}},
|
||||
{state_t::QUERY_SET, {state_t::QUERY_WHERE, state_t::QUERY_FINISH}},
|
||||
{state_t::QUERY_INTO, {state_t::QUERY_VALUES}},
|
||||
{state_t::QUERY_WHERE, {state_t::QUERY_ORDER_BY, state_t::QUERY_GROUP_BY, state_t::QUERY_OFFSET, state_t::QUERY_LIMIT, state_t::QUERY_FINISH}},
|
||||
{state_t::QUERY_ORDER_BY, {state_t::QUERY_ORDER_DIRECTION}},
|
||||
{state_t::QUERY_ORDER_DIRECTION, {state_t::QUERY_OFFSET, state_t::QUERY_LIMIT, state_t::QUERY_FINISH}},
|
||||
{state_t::QUERY_GROUP_BY, {state_t::QUERY_ORDER_BY, state_t::QUERY_FINISH}},
|
||||
{state_t::QUERY_OFFSET, {state_t::QUERY_LIMIT}},
|
||||
{state_t::QUERY_LIMIT, {state_t::QUERY_FINISH}},
|
||||
{state_t::QUERY_VALUES, {state_t::QUERY_FINISH}},
|
||||
{state_t::QUERY_FINISH, {}},
|
||||
};
|
||||
|
||||
query_builder::query_state_to_string_map query_builder::state_strings_ {
|
||||
{ state_t::QUERY_INIT, "init" },
|
||||
{ state_t::QUERY_CREATE, "create" },
|
||||
{ state_t::QUERY_DROP, "drop" },
|
||||
{ state_t::QUERY_SELECT, "select" },
|
||||
{ state_t::QUERY_INSERT, "insert" },
|
||||
{ state_t::QUERY_UPDATE, "update" },
|
||||
{ state_t::QUERY_DELETE, "delete" },
|
||||
{ state_t::QUERY_TABLE_CREATE, "table" },
|
||||
{ state_t::QUERY_TABLE_DROP, "table" },
|
||||
{ state_t::QUERY_FROM, "from" },
|
||||
{ state_t::QUERY_SET, "set" },
|
||||
{ state_t::QUERY_INTO, "into" },
|
||||
{ state_t::QUERY_WHERE, "where" },
|
||||
{ state_t::QUERY_ORDER_BY, "order_by" },
|
||||
{ state_t::QUERY_GROUP_BY, "group_by" },
|
||||
{ state_t::QUERY_OFFSET, "offset" },
|
||||
{ state_t::QUERY_LIMIT, "limit" },
|
||||
{ state_t::QUERY_FINISH, "finish" },
|
||||
query_builder::query_state_to_string_map query_builder::state_strings_{
|
||||
{state_t::QUERY_INIT, "init"},
|
||||
{state_t::QUERY_CREATE, "create"},
|
||||
{state_t::QUERY_DROP, "drop"},
|
||||
{state_t::QUERY_SELECT, "select"},
|
||||
{state_t::QUERY_INSERT, "insert"},
|
||||
{state_t::QUERY_UPDATE, "update"},
|
||||
{state_t::QUERY_DELETE, "delete"},
|
||||
{state_t::QUERY_TABLE_CREATE, "table"},
|
||||
{state_t::QUERY_TABLE_DROP, "table"},
|
||||
{state_t::QUERY_FROM, "from"},
|
||||
{state_t::QUERY_SET, "set"},
|
||||
{state_t::QUERY_INTO, "into"},
|
||||
{state_t::QUERY_WHERE, "where"},
|
||||
{state_t::QUERY_ORDER_BY, "order_by"},
|
||||
{state_t::QUERY_GROUP_BY, "group_by"},
|
||||
{state_t::QUERY_OFFSET, "offset"},
|
||||
{state_t::QUERY_LIMIT, "limit"},
|
||||
{state_t::QUERY_FINISH, "finish"},
|
||||
};
|
||||
|
||||
query_builder::query_command_to_string_map query_builder::command_strings_ {
|
||||
{ command_t::UNKNOWN, "unknown" },
|
||||
{ command_t::CREATE, "create" },
|
||||
{ command_t::DROP, "drop" },
|
||||
{ command_t::SELECT, "select" },
|
||||
{ command_t::INSERT, "insert" },
|
||||
{ command_t::UPDATE, "update" },
|
||||
{ command_t::REMOVE, "remove" },
|
||||
query_builder::query_command_to_string_map query_builder::command_strings_{
|
||||
{command_t::UNKNOWN, "unknown"},
|
||||
{command_t::CREATE, "create"},
|
||||
{command_t::DROP, "drop"},
|
||||
{command_t::SELECT, "select"},
|
||||
{command_t::INSERT, "insert"},
|
||||
{command_t::UPDATE, "update"},
|
||||
{command_t::REMOVE, "remove"},
|
||||
};
|
||||
|
||||
query_builder::query_builder(const dialect &d)
|
||||
: dialect_(d)
|
||||
, value_to_string_(d) {}
|
||||
: dialect_(d), value_to_string_(d, query_)
|
||||
{}
|
||||
|
||||
query_builder& query_builder::create() {
|
||||
query_builder &query_builder::create()
|
||||
{
|
||||
initialize(command_t::CREATE, state_t::QUERY_CREATE);
|
||||
|
||||
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::CREATE));
|
||||
@@ -89,7 +99,8 @@ query_builder& query_builder::create() {
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::drop() {
|
||||
query_builder &query_builder::drop()
|
||||
{
|
||||
initialize(command_t::DROP, state_t::QUERY_DROP);
|
||||
|
||||
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::DROP));
|
||||
@@ -97,7 +108,7 @@ query_builder& query_builder::drop() {
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::select(std::initializer_list<column> columns)
|
||||
query_builder &query_builder::select(std::initializer_list<column> columns)
|
||||
{
|
||||
return select(std::vector<column>{columns});
|
||||
}
|
||||
@@ -112,7 +123,7 @@ query_builder &query_builder::select(const std::vector<column> &columns)
|
||||
|
||||
std::string result;
|
||||
if (columns.size() < 2) {
|
||||
for (const auto &col : columns) {
|
||||
for (const auto &col: columns) {
|
||||
result.append(dialect_.prepare_identifier(col));
|
||||
query_.prototype.append(col);
|
||||
}
|
||||
@@ -131,7 +142,8 @@ query_builder &query_builder::select(const std::vector<column> &columns)
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::insert() {
|
||||
query_builder &query_builder::insert()
|
||||
{
|
||||
initialize(command_t::INSERT, state_t::QUERY_INSERT);
|
||||
|
||||
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::INSERT));
|
||||
@@ -139,7 +151,8 @@ query_builder& query_builder::insert() {
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::update(const std::string &table) {
|
||||
query_builder &query_builder::update(const std::string &table)
|
||||
{
|
||||
initialize(command_t::UPDATE, state_t::QUERY_UPDATE);
|
||||
|
||||
query_.table_name = table;
|
||||
@@ -148,7 +161,8 @@ query_builder& query_builder::update(const std::string &table) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::remove() {
|
||||
query_builder &query_builder::remove()
|
||||
{
|
||||
initialize(command_t::REMOVE, state_t::QUERY_DELETE);
|
||||
|
||||
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::REMOVE));
|
||||
@@ -156,7 +170,7 @@ query_builder& query_builder::remove() {
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::table(const std::string &table, std::initializer_list<column> columns)
|
||||
query_builder &query_builder::table(const std::string &table, std::initializer_list<column> columns)
|
||||
{
|
||||
return this->table(table, std::vector<column>{columns});
|
||||
}
|
||||
@@ -176,7 +190,8 @@ struct column_context
|
||||
|
||||
std::string build_create_column(const column &col, const dialect &d, column_context &context);
|
||||
|
||||
query_builder &query_builder::table(const std::string &table, const std::vector<column> &columns) {
|
||||
query_builder &query_builder::table(const std::string &table, const std::vector<column> &columns)
|
||||
{
|
||||
transition_to(state_t::QUERY_TABLE_CREATE);
|
||||
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::TABLE) + " " + dialect_.prepare_identifier(table) + " ");
|
||||
@@ -187,7 +202,7 @@ query_builder &query_builder::table(const std::string &table, const std::vector<
|
||||
column_context context;
|
||||
|
||||
if (columns.size() < 2) {
|
||||
for (const auto &col : columns) {
|
||||
for (const auto &col: columns) {
|
||||
result.append(build_create_column(col, dialect_, context));
|
||||
}
|
||||
} else {
|
||||
@@ -202,7 +217,7 @@ query_builder &query_builder::table(const std::string &table, const std::vector<
|
||||
if (!context.primary_keys.empty()) {
|
||||
result.append(", CONSTRAINT PK_" + table + " PRIMARY KEY (" + utils::join(context.primary_keys, ", ") + ")");
|
||||
}
|
||||
for (const auto &fk : context.foreign_contexts) {
|
||||
for (const auto &fk: context.foreign_contexts) {
|
||||
result += ", CONSTRAINT FK_" + table;
|
||||
result += "_" + fk.column;
|
||||
result += " FOREIGN KEY (" + fk.column + ")";
|
||||
@@ -214,7 +229,8 @@ query_builder &query_builder::table(const std::string &table, const std::vector<
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::table(const std::string &table) {
|
||||
query_builder &query_builder::table(const std::string &table)
|
||||
{
|
||||
transition_to(state_t::QUERY_TABLE_DROP);
|
||||
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::TABLE) + " " + dialect_.prepare_identifier(table));
|
||||
@@ -223,7 +239,7 @@ query_builder& query_builder::table(const std::string &table) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::into(const std::string &table, std::initializer_list<std::string> column_names)
|
||||
query_builder &query_builder::into(const std::string &table, std::initializer_list<std::string> column_names)
|
||||
{
|
||||
return into(table, std::vector<std::string>{column_names});
|
||||
}
|
||||
@@ -237,7 +253,7 @@ query_builder &query_builder::into(const std::string &table, const std::vector<s
|
||||
|
||||
std::string result{"("};
|
||||
if (column_names.size() < 2) {
|
||||
for (const auto &col : column_names) {
|
||||
for (const auto &col: column_names) {
|
||||
result.append(dialect_.prepare_identifier(col));
|
||||
}
|
||||
} else {
|
||||
@@ -254,19 +270,20 @@ query_builder &query_builder::into(const std::string &table, const std::vector<s
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::values(std::initializer_list<any_type> values)
|
||||
query_builder &query_builder::values(std::initializer_list<any_type> values)
|
||||
{
|
||||
return this->values(std::vector<any_type>{values});
|
||||
}
|
||||
|
||||
query_builder& query_builder::values(const std::vector<any_type> &values) {
|
||||
query_builder &query_builder::values(const std::vector<any_type> &values)
|
||||
{
|
||||
transition_to(state_t::QUERY_VALUES);
|
||||
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::VALUES) + " ");
|
||||
|
||||
std::string result{"("};
|
||||
if (values.size() < 2) {
|
||||
for (auto val : values) {
|
||||
for (auto val: values) {
|
||||
query_.host_vars.push_back(val);
|
||||
std::visit(value_to_string_, val);
|
||||
result.append(value_to_string_.result);
|
||||
@@ -291,10 +308,20 @@ query_builder& query_builder::values(const std::vector<any_type> &values) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::from(const std::string &table, const std::string &as) {
|
||||
query_builder &query_builder::from(const std::string &table, const std::string &as)
|
||||
{
|
||||
transition_to(state_t::QUERY_FROM);
|
||||
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::FROM) + " " + dialect_.prepare_identifier(table) + (as.empty() ? "" : " " + as));
|
||||
if (dialect_.default_schema_name().empty()) {
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::FROM) +
|
||||
" " + dialect_.prepare_identifier(table) +
|
||||
(as.empty() ? "" : " " + as));
|
||||
} else {
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::FROM) +
|
||||
" " + dialect_.prepare_identifier(dialect_.default_schema_name()) +
|
||||
"." + dialect_.prepare_identifier(table) +
|
||||
(as.empty() ? "" : " " + as));
|
||||
}
|
||||
query_.table_name = table;
|
||||
|
||||
return *this;
|
||||
@@ -315,14 +342,15 @@ query_builder &query_builder::set(std::initializer_list<key_value_pair> key_valu
|
||||
return set(std::vector<key_value_pair>{key_values});
|
||||
}
|
||||
|
||||
query_builder& query_builder::set(const std::vector<key_value_pair> &key_values) {
|
||||
query_builder &query_builder::set(const std::vector<key_value_pair> &key_values)
|
||||
{
|
||||
transition_to(state_t::QUERY_SET);
|
||||
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::SET) + " ");
|
||||
|
||||
std::string result;
|
||||
if (key_values.size() < 2) {
|
||||
for (const auto &col : key_values) {
|
||||
for (const auto &col: key_values) {
|
||||
result.append(dialect_.prepare_identifier(col.name()) + "=");
|
||||
auto var = col.value();
|
||||
std::visit(value_to_string_, var);
|
||||
@@ -347,67 +375,76 @@ query_builder& query_builder::set(const std::vector<key_value_pair> &key_values)
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::where(const basic_condition &cond) {
|
||||
query_builder &query_builder::where(const basic_condition &cond)
|
||||
{
|
||||
transition_to(state_t::QUERY_WHERE);
|
||||
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::WHERE) + " ");
|
||||
query_parts_.emplace_back(cond.evaluate(const_cast<dialect &>(dialect_)));
|
||||
query_parts_.emplace_back(cond.evaluate(const_cast<dialect &>(dialect_), query_));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::order_by(const std::string& column) {
|
||||
transition_to(state_t::QUERY_ORDER_BY);
|
||||
query_builder &query_builder::order_by(const std::string &column)
|
||||
{
|
||||
transition_to(state_t::QUERY_ORDER_BY);
|
||||
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::ORDER_BY) + " " + dialect_.prepare_identifier(column));
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::ORDER_BY) + " " + dialect_.prepare_identifier(column));
|
||||
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::group_by(const std::string& column) {
|
||||
transition_to(state_t::QUERY_GROUP_BY);
|
||||
query_builder &query_builder::group_by(const std::string &column)
|
||||
{
|
||||
transition_to(state_t::QUERY_GROUP_BY);
|
||||
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::GROUP_BY) + " " + dialect_.prepare_identifier(column));
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::GROUP_BY) + " " + dialect_.prepare_identifier(column));
|
||||
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::asc() {
|
||||
transition_to(state_t::QUERY_ORDER_DIRECTION);
|
||||
query_builder &query_builder::asc()
|
||||
{
|
||||
transition_to(state_t::QUERY_ORDER_DIRECTION);
|
||||
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::ASC));
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::ASC));
|
||||
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::desc() {
|
||||
transition_to(state_t::QUERY_ORDER_DIRECTION);
|
||||
query_builder &query_builder::desc()
|
||||
{
|
||||
transition_to(state_t::QUERY_ORDER_DIRECTION);
|
||||
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::DESC));
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::DESC));
|
||||
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::offset( size_t count ) {
|
||||
transition_to(state_t::QUERY_OFFSET);
|
||||
query_builder &query_builder::offset(size_t count)
|
||||
{
|
||||
transition_to(state_t::QUERY_OFFSET);
|
||||
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::OFFSET) + " " + std::to_string(count));
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::OFFSET) + " " + std::to_string(count));
|
||||
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
query_builder& query_builder::limit( size_t count ) {
|
||||
transition_to(state_t::QUERY_LIMIT);
|
||||
query_builder &query_builder::limit(size_t count)
|
||||
{
|
||||
transition_to(state_t::QUERY_LIMIT);
|
||||
|
||||
query_parts_.emplace_back( " " + dialect_.token_at(dialect::token_t::LIMIT) + " " + std::to_string( count));
|
||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::LIMIT) + " " + std::to_string(count));
|
||||
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
query query_builder::compile() {
|
||||
for (const auto &part : query_parts_) {
|
||||
query_context query_builder::compile()
|
||||
{
|
||||
for (const auto &part: query_parts_) {
|
||||
query_.sql.append(part);
|
||||
}
|
||||
query_.command_name = command_strings_[command_];
|
||||
return query_;
|
||||
}
|
||||
|
||||
@@ -427,22 +464,23 @@ void query_builder::initialize(query_builder::command_t cmd, query_builder::stat
|
||||
query_parts_.clear();
|
||||
}
|
||||
|
||||
std::string build_create_column(const column &col, const dialect &d, column_context &context) {
|
||||
std::string result = d.prepare_identifier(col.name()) + " " + d.data_type_at(col.type());
|
||||
if (col.attributes().size() > 0) {
|
||||
result.append("(" + std::to_string(col.attributes().size()) +")");
|
||||
}
|
||||
if (is_constraint_set(col.attributes().options(), utils::constraints::NOT_NULL)) {
|
||||
result.append(" NOT NULL");
|
||||
}
|
||||
if (is_constraint_set(col.attributes().options(), utils::constraints::PRIMARY_KEY)) {
|
||||
context.primary_keys.emplace_back(col.name());
|
||||
}
|
||||
if (is_constraint_set(col.attributes().options(), utils::constraints::FOREIGN_KEY)) {
|
||||
context.foreign_contexts.push_back({col.name(), col.ref_table(), col.ref_column()});
|
||||
}
|
||||
std::string build_create_column(const column &col, const dialect &d, column_context &context)
|
||||
{
|
||||
std::string result = d.prepare_identifier(col.name()) + " " + d.data_type_at(col.type());
|
||||
if (col.attributes().size() > 0) {
|
||||
result.append("(" + std::to_string(col.attributes().size()) + ")");
|
||||
}
|
||||
if (is_constraint_set(col.attributes().options(), utils::constraints::NOT_NULL)) {
|
||||
result.append(" NOT NULL");
|
||||
}
|
||||
if (is_constraint_set(col.attributes().options(), utils::constraints::PRIMARY_KEY)) {
|
||||
context.primary_keys.emplace_back(col.name());
|
||||
}
|
||||
if (is_constraint_set(col.attributes().options(), utils::constraints::FOREIGN_KEY)) {
|
||||
context.foreign_contexts.push_back({col.name(), col.ref_table(), col.ref_column()});
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
column alias(const std::string &column, const std::string &as)
|
||||
@@ -450,7 +488,8 @@ column alias(const std::string &column, const std::string &as)
|
||||
return {column, as};
|
||||
}
|
||||
|
||||
column alias(column &&col, const std::string &as) {
|
||||
column alias(column &&col, const std::string &as)
|
||||
{
|
||||
col.alias(as);
|
||||
return std::move(col);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,11 @@ std::unique_ptr<query_result_impl> query_select_finish::fetch()
|
||||
return session_.fetch(builder_.compile().sql);
|
||||
}
|
||||
|
||||
statement query_select_finish::prepare()
|
||||
{
|
||||
return session_.prepare(builder_.compile());
|
||||
}
|
||||
|
||||
query_intermediate::query_intermediate(session &db, query_builder &query)
|
||||
: session_(db), builder_(query) {}
|
||||
|
||||
@@ -103,6 +108,11 @@ std::pair<size_t, std::string> query_execute_finish::execute()
|
||||
return session_.execute(builder_.compile().sql);
|
||||
}
|
||||
|
||||
statement query_execute_finish::prepare()
|
||||
{
|
||||
return session_.prepare(builder_.compile());
|
||||
}
|
||||
|
||||
query_execute_finish query_into_intermediate::values(std::initializer_list<any_type> values)
|
||||
{
|
||||
return {session_, builder_.values(values)};
|
||||
@@ -140,10 +150,10 @@ query_execute_where_intermediate query_set_intermediate::where(const basic_condi
|
||||
return {session_, builder_.where(cond)};
|
||||
}
|
||||
|
||||
query_update_intermediate::query_update_intermediate(session &s, std::string table_name)
|
||||
query_update_intermediate::query_update_intermediate(session &s, const std::string& table_name)
|
||||
: query_start_intermediate(s)
|
||||
{
|
||||
builder_.update(std::move(table_name));
|
||||
builder_.update(table_name);
|
||||
}
|
||||
|
||||
query_set_intermediate query_update_intermediate::set(std::initializer_list<key_value_pair> columns)
|
||||
|
||||
+10
-1
@@ -40,7 +40,7 @@ query_delete_intermediate session::remove()
|
||||
return query_delete_intermediate{*this};
|
||||
}
|
||||
|
||||
query_result<record> session::fetch(const query &q) const
|
||||
query_result<record> session::fetch(const query_context &q) const
|
||||
{
|
||||
auto c = pool_.acquire();
|
||||
if (!c.valid()) {
|
||||
@@ -73,6 +73,15 @@ std::pair<size_t, std::string> session::execute(const std::string &sql) const {
|
||||
return c->execute(sql);
|
||||
}
|
||||
|
||||
statement session::prepare(query_context q) const
|
||||
{
|
||||
auto c = pool_.acquire();
|
||||
if (!c.valid()) {
|
||||
throw std::logic_error("no database connection available");
|
||||
}
|
||||
return c->prepare(std::move(q));
|
||||
}
|
||||
|
||||
record session::describe_table(const std::string &table_name) const
|
||||
{
|
||||
auto c = pool_.acquire();
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "matador/sql/statement.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
statement::statement(std::unique_ptr<statement_impl> impl, const utils::logger &logger)
|
||||
: statement_(std::move(impl))
|
||||
, logger_(logger)
|
||||
, object_binder_(statement_->binder())
|
||||
{}
|
||||
|
||||
statement &statement::bind(size_t pos, std::string &val, size_t size)
|
||||
{
|
||||
statement_->bind(pos, val, size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
size_t statement::execute()
|
||||
{
|
||||
logger_.info(statement_->query_.sql);
|
||||
return statement_->execute();
|
||||
}
|
||||
|
||||
query_result<record> statement::fetch()
|
||||
{
|
||||
logger_.info(statement_->query_.sql);
|
||||
return query_result<record>(statement_->fetch());
|
||||
}
|
||||
|
||||
void statement::reset()
|
||||
{
|
||||
statement_->reset();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "matador/sql/statement_cache.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
statement &statement_cache::acquire(const std::string &stmt, const connection &conn) {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
auto key = hash_(stmt);
|
||||
auto it = statement_map_.find(key);
|
||||
if (it == statement_map_.end()) {
|
||||
|
||||
}
|
||||
return *it->second.statement_;
|
||||
}
|
||||
|
||||
void statement_cache::release(const statement &stmt) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "matador/sql/statement_impl.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
statement_impl::statement_impl(query_context query)
|
||||
: query_(std::move(query))
|
||||
{}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user