initial matador ng commit
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
#include "matador/query/attribute_string_writer.hpp"
|
||||
|
||||
// #include "matador/sql/connection_impl.hpp"
|
||||
#include <matador/utils/convert.hpp>
|
||||
|
||||
|
||||
#include "matador/sql/dialect.hpp"
|
||||
|
||||
#include "matador/utils/string.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
attribute_string_writer::attribute_string_writer(const sql::dialect &d, const std::optional<std::reference_wrapper<const sql::connection_impl>> conn)
|
||||
: dialect_(d)
|
||||
, conn_(conn) {}
|
||||
|
||||
const sql::dialect& attribute_string_writer::dialect() const {
|
||||
return dialect_;
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const int8_t& x ) {
|
||||
result_ = std::to_string(x) ;
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const int16_t& x ) {
|
||||
result_ = std::to_string(x) ;
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const int32_t& x ) {
|
||||
result_ = std::to_string(x) ;
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const int64_t& x ) {
|
||||
result_ = std::to_string(x) ;
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const uint8_t& x ) {
|
||||
result_ = std::to_string(x) ;
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const uint16_t& x ) {
|
||||
result_ = std::to_string(x) ;
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const uint32_t& x ) {
|
||||
result_ = std::to_string(x) ;
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const uint64_t& x ) {
|
||||
result_ = std::to_string(x) ;
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const bool& x ) {
|
||||
// result_ = "'" + conn_->dialect().prepare_literal(x ? "true" : "false") + "'";
|
||||
result_ = dialect_.to_string(x);
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const float& x ) {
|
||||
if (const auto res = utils::to<std::string>(x); res.is_error()) {
|
||||
result_ = *res;
|
||||
}
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const double& x ) {
|
||||
if (const auto res = utils::to<std::string>(x); res.is_error()) {
|
||||
result_ = *res;
|
||||
}
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const time& /*x*/ ) {
|
||||
// result_ = "'" + dialect_.prepare_literal(utils::to_string(x, "%F %T.%f")) + "'";
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const date& /*x*/ ) {
|
||||
// result_ = "'" + dialect_.prepare_literal(utils::to_string(x)) + "'";
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t pos, const char* x ) {
|
||||
write_value(pos, std::string(x) );
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t pos, const char* x, size_t /*size*/) {
|
||||
write_value(pos, std::string(x) );
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const std::string& x ) {
|
||||
result_ = "'" + dialect_.prepare_literal(x) + "'";
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const std::string& x, size_t /*size*/) {
|
||||
result_ = "'" + dialect_.prepare_literal(x) + "'";
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const utils::blob& x ) {
|
||||
// "This is a binary Data string" as binary data:
|
||||
// MySQL: X'5468697320697320612062616E617279204461746120737472696E67'
|
||||
// Postgres: '\\x5468697320697320612062616E617279204461746120737472696E67'
|
||||
// MSSQL: 0x5468697320697320612062616E617279204461746120737472696E67
|
||||
// Sqlite: X'5468697320697320612062616E617279204461746120737472696E67'
|
||||
if (conn_.has_value()) {
|
||||
// result_ = dialect_.token_at(sql::dialect_token::BEGIN_BINARY_DATA) + conn_.value().get().to_escaped_string(x) + dialect_.token_at(sql::dialect_token::END_BINARY_DATA);
|
||||
} else {
|
||||
result_ = dialect_.token_at(sql::dialect_token::BEGIN_BINARY_DATA) + dialect_.to_escaped_string(x) + dialect_.token_at(sql::dialect_token::END_BINARY_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
void attribute_string_writer::write_value(size_t /*pos*/, const utils::value &/*x*/, size_t /*size*/) {}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "matador/query/basic_condition.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
std::unordered_map<basic_condition::operand_type, std::string> basic_condition::operands{
|
||||
{operand_type::EQUAL, "="},
|
||||
{operand_type::NOT_EQUAL, "<>"},
|
||||
{operand_type::LESS, "<"},
|
||||
{operand_type::LESS_EQUAL, "<="},
|
||||
{operand_type::GREATER, ">"},
|
||||
{operand_type::GREATER_EQUAL, ">="},
|
||||
{operand_type::OR, "OR"},
|
||||
{operand_type::AND, "AND"},
|
||||
{operand_type::NOT, "NOT"},
|
||||
{operand_type::IN_LIST, "IN"},
|
||||
{operand_type::LIKE, "LIKE"}
|
||||
};
|
||||
|
||||
basic_column_condition::basic_column_condition(sql::column fld, const operand_type op)
|
||||
: field_(std::move(fld)), operand(operands[op])
|
||||
{ }
|
||||
|
||||
basic_in_condition::basic_in_condition(sql::column fld)
|
||||
: field_(std::move(fld))
|
||||
{ }
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#include "matador/query/condition.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
condition<sql::column, utils::placeholder>::condition(const sql::column &fld, const operand_type op, const utils::placeholder &val)
|
||||
: basic_column_condition(fld, op), value(val)
|
||||
{}
|
||||
|
||||
std::string condition<sql::column, utils::placeholder>::evaluate(const sql::dialect &d, sql::query_context &query) const
|
||||
{
|
||||
query.bind_vars.emplace_back(field_.name);
|
||||
return d.prepare_identifier(field_) + " " + operand + " " + d.next_placeholder(query.bind_vars);
|
||||
}
|
||||
|
||||
condition<sql::column, sql::query_context>::condition(sql::column col, const operand_type op, sql::query_context &q)
|
||||
: basic_column_condition(std::move(col), op), query_(q)
|
||||
{}
|
||||
|
||||
std::string condition<sql::column, sql::query_context>::evaluate(const sql::dialect &d, sql::query_context &/*query*/) const
|
||||
{
|
||||
std::string result(d.prepare_identifier(field_) + " " + operand + " (");
|
||||
result += query_.sql;
|
||||
result += ")";
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string condition<sql::column, sql::column>::evaluate(const sql::dialect &d, sql::query_context &/*query*/) const {
|
||||
return d.prepare_condition(field_) + " " + operand + " " + d.prepare_condition(other_column_);
|
||||
}
|
||||
|
||||
condition<sql::column, sql::query_context> in(const sql::column &col, sql::query_context &&q)
|
||||
{
|
||||
return {col, basic_condition::operand_type::IN_LIST, q};
|
||||
}
|
||||
|
||||
condition<sql::column, std::string> like(const sql::column &col, const std::string &val) {
|
||||
return { col, basic_condition::operand_type::LIKE, val };
|
||||
}
|
||||
|
||||
condition<sql::column, sql::column> operator==(const sql::column &a, const sql::column &b)
|
||||
{
|
||||
return {a, basic_condition::operand_type::EQUAL, b};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#include "matador/query/fk_value_extractor.hpp"
|
||||
|
||||
namespace matador::query::detail {
|
||||
|
||||
void fk_value_extractor::on_primary_key(const char *, std::string &pk, size_t)
|
||||
{
|
||||
value_ = pk;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "matador/query/intermediates/executable_query.hpp"
|
||||
#include "matador/query/query_compiler.hpp"
|
||||
|
||||
#include "matador/sql/executor.hpp"
|
||||
#include "matador/sql/statement.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
utils::result<size_t, utils::error> executable_query::execute(const sql::executor &exec) const
|
||||
{
|
||||
query_compiler compiler;
|
||||
return exec.execute(compiler.compile(*context_, exec.dialect(), std::nullopt));
|
||||
}
|
||||
|
||||
utils::result<sql::statement, utils::error> executable_query::prepare(const sql::executor &exec) const
|
||||
{
|
||||
query_compiler compiler;
|
||||
return exec.prepare(compiler.compile(*context_, exec.dialect(), std::nullopt));
|
||||
}
|
||||
|
||||
std::string executable_query::str(const sql::executor &exec) const
|
||||
{
|
||||
query_compiler compiler;
|
||||
return exec.str(compiler.compile(*context_, exec.dialect(), std::nullopt));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#include "../../../../include/matador/query/intermediates/fetchable_query.hpp"
|
||||
|
||||
#include "../../../../include/matador/sql/executor.hpp"
|
||||
#include "../../../../include/matador/sql/statement.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
utils::result<sql::query_result<sql::record>, utils::error> fetchable_query::fetch_all(const sql::executor &exec) const
|
||||
{
|
||||
query_compiler compiler;
|
||||
return exec.fetch(compiler.compile(*context_, exec.dialect(), std::nullopt))
|
||||
.and_then([](auto &&res) {
|
||||
return utils::ok(sql::query_result<sql::record>(std::forward<decltype(res)>(res)));
|
||||
});
|
||||
// if (!result.is_ok()) {
|
||||
// return utils::error(result.err());
|
||||
// }
|
||||
//
|
||||
// return utils::ok(query_result<record>(std::move(*result)));
|
||||
}
|
||||
|
||||
utils::result<std::optional<sql::record>, utils::error> fetchable_query::fetch_one(const sql::executor &exec) const
|
||||
{
|
||||
query_compiler compiler;
|
||||
auto result = exec.fetch(compiler.compile(*context_, exec.dialect(), std::nullopt));
|
||||
if (!result.is_ok()) {
|
||||
return utils::failure(result.err());
|
||||
}
|
||||
|
||||
sql::query_result<sql::record> records(std::move(*result));
|
||||
auto first = records.begin();
|
||||
if (first == records.end()) {
|
||||
return utils::ok(std::optional<sql::record>{std::nullopt});
|
||||
}
|
||||
|
||||
return utils::ok(std::optional<sql::record>{*first.get()});
|
||||
}
|
||||
|
||||
std::string fetchable_query::str(const sql::executor &exec) const
|
||||
{
|
||||
query_compiler compiler;
|
||||
return exec.str(compiler.compile(*context_, exec.dialect(), std::nullopt));
|
||||
}
|
||||
|
||||
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetchable_query::fetch(const sql::executor &exec) const
|
||||
{
|
||||
query_compiler compiler;
|
||||
return exec.fetch(compiler.compile(*context_, exec.dialect(), std::nullopt));
|
||||
}
|
||||
|
||||
utils::result<sql::statement, utils::error> fetchable_query::prepare(const sql::executor &exec) const
|
||||
{
|
||||
query_compiler compiler;
|
||||
return exec.prepare(compiler.compile(*context_, exec.dialect(), std::nullopt));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#include "matador/query/intermediates/query_create_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_create_intermediate::query_create_intermediate()
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_create_part>());
|
||||
}
|
||||
|
||||
executable_query query_create_intermediate::table(const sql::table &table, const std::initializer_list<sql::column_definition> columns)
|
||||
{
|
||||
return this->table(table, std::vector<sql::column_definition>{columns});
|
||||
}
|
||||
|
||||
executable_query query_create_intermediate::table(const sql::table &table, const std::vector<sql::column_definition> &columns)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_create_table_part>(table, columns));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "matador/query/intermediates/query_delete_from_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_execute_where_intermediate query_delete_from_intermediate::where_clause(std::unique_ptr<basic_condition> &&cond)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_where_part>(std::move(cond)));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "matador/query/intermediates/query_delete_intermediate.hpp"
|
||||
|
||||
#include "matador/query/intermediates/query_delete_from_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_delete_intermediate::query_delete_intermediate()
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_delete_part>());
|
||||
}
|
||||
|
||||
query_delete_from_intermediate query_delete_intermediate::from(const sql::table &table)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_delete_from_part>(table));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "matador/query/intermediates/query_drop_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_drop_intermediate::query_drop_intermediate()
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_drop_part>());
|
||||
}
|
||||
|
||||
executable_query query_drop_intermediate::table(const sql::table &table)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_drop_table_part>(table));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "matador/query/intermediates/query_execute_limit_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_execute_offset_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_execute_offset_intermediate query_execute_limit_intermediate::offset(size_t offset) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_offset_part>(offset));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
} // namespace matador::query
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "matador/query/intermediates/query_execute_offset_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_execute_limit_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
query_execute_limit_intermediate query_execute_offset_intermediate::limit(size_t limit) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_limit_part>(limit));
|
||||
return {context_};
|
||||
}
|
||||
} // namespace matador::query
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "matador/query/intermediates/query_execute_order_by_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_execute_order_direction_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_execute_order_direction_intermediate query_execute_order_by_intermediate::asc() {
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_asc_part>());
|
||||
return {context_};
|
||||
}
|
||||
query_execute_order_direction_intermediate query_execute_order_by_intermediate::desc() {
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_desc_part>());
|
||||
return {context_};
|
||||
}
|
||||
|
||||
} // namespace matador::query
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "matador/query/intermediates/query_execute_order_direction_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_execute_limit_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_execute_limit_intermediate query_execute_order_direction_intermediate::limit(size_t limit) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_limit_part>(limit));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "matador/query/intermediates/query_execute_where_intermediate.hpp"
|
||||
|
||||
#include "matador/query/intermediates/query_execute_limit_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_execute_order_by_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_execute_limit_intermediate query_execute_where_intermediate::limit(size_t limit)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_limit_part>(limit));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_execute_order_by_intermediate query_execute_where_intermediate::order_by(const sql::column &col)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(col));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
#include "matador/query/intermediates/query_from_intermediate.hpp"
|
||||
|
||||
#include "matador/query/intermediates/query_join_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_group_by_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_order_by_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_join_intermediate query_from_intermediate::join_left(const sql::table &t)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_join_part>(t));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_from_intermediate query_from_intermediate::join_left(join_data &data)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_join_part>(*data.join_table));
|
||||
context_->parts.push_back(std::make_unique<internal::query_on_part>(std::move(data.condition)));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_from_intermediate query_from_intermediate::join_left(std::vector<join_data> &data_vector)
|
||||
{
|
||||
for (auto &data : data_vector) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_join_part>(*data.join_table));
|
||||
context_->parts.push_back(std::make_unique<internal::query_on_part>(std::move(data.condition)));
|
||||
}
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_where_intermediate query_from_intermediate::where_clause(std::unique_ptr<basic_condition> &&cond)
|
||||
{
|
||||
if (cond) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_where_part>(std::move(cond)));
|
||||
}
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_group_by_intermediate query_from_intermediate::group_by(const sql::column &col)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_group_by_part>(col));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_order_by_intermediate query_from_intermediate::order_by(const sql::column &col)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(col));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "matador/query/intermediates/query_group_by_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_order_by_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_order_by_intermediate query_group_by_intermediate::order_by(const sql::column &col)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(col));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "matador/query/intermediates/query_insert_intermediate.hpp"
|
||||
|
||||
#include "matador/query/intermediates/query_into_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_insert_intermediate::query_insert_intermediate()
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_insert_part>());
|
||||
}
|
||||
|
||||
query_into_intermediate query_insert_intermediate::into(const sql::table &table, std::initializer_list<sql::column> columns)
|
||||
{
|
||||
return into(table, std::move(std::vector<sql::column>{columns}));
|
||||
}
|
||||
|
||||
query_into_intermediate query_insert_intermediate::into(const sql::table &table, std::vector<sql::column> &&columns)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_into_part>(table, columns));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_into_intermediate query_insert_intermediate::into(const sql::table &table, const std::vector<std::string> &column_names) {
|
||||
std::vector<sql::column> columns;
|
||||
columns.reserve(column_names.size());
|
||||
for (const auto &col_name : column_names) {
|
||||
columns.emplace_back(col_name);
|
||||
}
|
||||
return into(table, std::move(columns));
|
||||
}
|
||||
|
||||
query_into_intermediate query_insert_intermediate::into(const sql::table &table)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_into_part>(table, table.columns));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "matador/query/intermediates/query_intermediate.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_intermediate::query_intermediate()
|
||||
: context_(std::make_shared<query_data>()) {}
|
||||
|
||||
query_intermediate::query_intermediate(const std::shared_ptr<query_data> &context)
|
||||
: context_(context)
|
||||
{}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "matador/query/intermediates/query_into_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
executable_query query_into_intermediate::values(const std::initializer_list<std::variant<utils::placeholder, utils::database_type>> values)
|
||||
{
|
||||
return this->values(std::vector(values));
|
||||
}
|
||||
|
||||
executable_query query_into_intermediate::values(std::vector<std::variant<utils::placeholder, utils::database_type>> &&values) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_values_part>(std::move(values)));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
} // namespace matador::query
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "matador/query/intermediates/query_join_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_on_intermediate query_join_intermediate::on_clause(std::unique_ptr<basic_condition> &&cond)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_on_part>(std::move(cond)));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "matador/query/intermediates/query_limit_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_offset_intermediate.hpp"
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_offset_intermediate query_limit_intermediate::offset(size_t offset)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_offset_part>(offset));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "matador/query/intermediates/query_offset_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_limit_intermediate.hpp"
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_limit_intermediate query_offset_intermediate::limit(size_t limit)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_limit_part>(limit));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "matador/query/intermediates/query_order_by_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_order_direction_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_order_direction_intermediate query_order_by_intermediate::asc()
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_asc_part>());
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_order_direction_intermediate query_order_by_intermediate::desc()
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_desc_part>());
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "matador/query/intermediates/query_order_direction_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_limit_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_limit_intermediate query_order_direction_intermediate::limit(size_t limit)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_limit_part>(limit));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#include "matador/query/intermediates/query_select_intermediate.hpp"
|
||||
|
||||
#include "matador/query/intermediates/query_join_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_select_intermediate::query_select_intermediate(const std::vector<sql::column>& columns)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_select_part>(columns));
|
||||
}
|
||||
|
||||
query_from_intermediate query_select_intermediate::from(const sql::table& t)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_from_part>(t));
|
||||
context_->tables.insert({t.name, t});
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "matador/query/intermediates/query_set_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_execute_where_intermediate query_set_intermediate::where_clause(std::unique_ptr<basic_condition> &&cond)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_where_part>(std::move(cond)));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#include "matador/query/intermediates/query_where_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_group_by_intermediate.hpp"
|
||||
#include "matador/query/intermediates/query_order_by_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_group_by_intermediate query_where_intermediate::group_by(const sql::column &col)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_group_by_part>(col));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_order_by_intermediate query_where_intermediate::order_by(const sql::column &col)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(col));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "matador/query/internal/basic_type_to_string_visitor.hpp"
|
||||
|
||||
namespace matador::query::internal {
|
||||
|
||||
basic_type_to_string_visitor::basic_type_to_string_visitor(attribute_string_writer &writer, sql::query_context &query)
|
||||
: writer(&writer), query(query)
|
||||
{}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "matador/query/internal/key_value_pair.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace matador::query::internal {
|
||||
|
||||
key_value_pair::key_value_pair(std::string name, utils::database_type value)
|
||||
: name_(std::move(name))
|
||||
, value_(std::move(value)) {
|
||||
}
|
||||
|
||||
key_value_pair::key_value_pair(const sql::column &col, utils::database_type value)
|
||||
: name_(col.name)
|
||||
, value_(std::move(value)) {
|
||||
}
|
||||
|
||||
key_value_pair::key_value_pair(const char *name, utils::database_type value)
|
||||
: name_(name)
|
||||
, value_(std::move(value)) {
|
||||
}
|
||||
|
||||
const std::string &key_value_pair::name() const {
|
||||
return name_;
|
||||
}
|
||||
|
||||
const utils::database_type& key_value_pair::value() const {
|
||||
return value_;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace matador::query::internal {
|
||||
|
||||
query_select_part::query_select_part(std::vector<sql::column> columns)
|
||||
: query_part(sql::dialect_token::SELECT)
|
||||
, columns_(std::move(columns)) {}
|
||||
|
||||
void query_select_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
const std::vector<sql::column>& query_select_part::columns() const
|
||||
{
|
||||
return columns_;
|
||||
}
|
||||
|
||||
query_from_part::query_from_part(sql::table t)
|
||||
: query_part(sql::dialect_token::FROM)
|
||||
, table_(std::move(t)) {}
|
||||
|
||||
const sql::table &query_from_part::table() const
|
||||
{
|
||||
return table_;
|
||||
}
|
||||
|
||||
void query_from_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_join_part::query_join_part(sql::table t)
|
||||
: query_part(sql::dialect_token::JOIN)
|
||||
, table_(std::move(t)) {}
|
||||
|
||||
const sql::table &query_join_part::table() const
|
||||
{
|
||||
return table_;
|
||||
}
|
||||
|
||||
void query_join_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_on_part::query_on_part(std::unique_ptr<basic_condition> &&cond)
|
||||
: query_part(sql::dialect_token::ON)
|
||||
, condition_(std::move(cond)) {}
|
||||
|
||||
const basic_condition &query_on_part::condition() const
|
||||
{
|
||||
return *condition_;
|
||||
}
|
||||
|
||||
void query_on_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_where_part::query_where_part(std::unique_ptr<basic_condition> &&cond)
|
||||
: query_part(sql::dialect_token::WHERE)
|
||||
, condition_(std::move(cond)) {}
|
||||
|
||||
void query_where_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
const basic_condition &query_where_part::condition() const
|
||||
{
|
||||
return *condition_;
|
||||
}
|
||||
|
||||
query_table_name_part::query_table_name_part(sql::dialect_token token, std::string table_name)
|
||||
: query_part(token)
|
||||
, table_name_(std::move(table_name)) {}
|
||||
|
||||
query_group_by_part::query_group_by_part(sql::column col)
|
||||
: query_part(sql::dialect_token::GROUP_BY)
|
||||
, column_(std::move(col))
|
||||
{}
|
||||
|
||||
const sql::column &query_group_by_part::column() const
|
||||
{
|
||||
return column_;
|
||||
}
|
||||
|
||||
void query_group_by_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_order_by_part::query_order_by_part(sql::column col)
|
||||
: query_part(sql::dialect_token::ORDER_BY)
|
||||
, column_(std::move(col))
|
||||
{}
|
||||
|
||||
const sql::column &query_order_by_part::column() const
|
||||
{
|
||||
return column_;
|
||||
}
|
||||
|
||||
void query_order_by_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_order_by_asc_part::query_order_by_asc_part()
|
||||
: query_part(sql::dialect_token::ASC)
|
||||
{}
|
||||
|
||||
void query_order_by_asc_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_order_by_desc_part::query_order_by_desc_part()
|
||||
: query_part(sql::dialect_token::DESC)
|
||||
{}
|
||||
|
||||
void query_order_by_desc_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_offset_part::query_offset_part(size_t offset)
|
||||
: query_part(sql::dialect_token::OFFSET)
|
||||
, offset_(offset) {}
|
||||
|
||||
size_t query_offset_part::offset() const
|
||||
{
|
||||
return offset_;
|
||||
}
|
||||
|
||||
void query_offset_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_limit_part::query_limit_part(size_t limit)
|
||||
: query_part(sql::dialect_token::LIMIT)
|
||||
, limit_(limit) {}
|
||||
|
||||
size_t query_limit_part::limit() const
|
||||
{
|
||||
return limit_;
|
||||
}
|
||||
|
||||
void query_limit_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_insert_part::query_insert_part()
|
||||
: query_part(sql::dialect_token::INSERT) {}
|
||||
|
||||
void query_insert_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_into_part::query_into_part(sql::table t, std::vector<sql::column> columns)
|
||||
: query_part(sql::dialect_token::INSERT)
|
||||
, table_(std::move(t))
|
||||
, columns_(std::move(columns)) {}
|
||||
|
||||
const sql::table &query_into_part::table() const
|
||||
{
|
||||
return table_;
|
||||
}
|
||||
|
||||
const std::vector<sql::column> &query_into_part::columns() const
|
||||
{
|
||||
return columns_;
|
||||
}
|
||||
|
||||
void query_into_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_values_part::query_values_part(std::vector<std::variant<utils::placeholder, utils::database_type>> &&values)
|
||||
: query_part(sql::dialect_token::VALUES)
|
||||
, values_(std::move(values)) {}
|
||||
|
||||
const std::vector<std::variant<utils::placeholder, utils::database_type>>& query_values_part::values() const
|
||||
{
|
||||
return values_;
|
||||
}
|
||||
|
||||
void query_values_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_update_part::query_update_part(sql::table table)
|
||||
: query_part(sql::dialect_token::UPDATE)
|
||||
, table_(std::move(table)) {}
|
||||
|
||||
const sql::table& query_update_part::table() const
|
||||
{
|
||||
return table_;
|
||||
}
|
||||
|
||||
void query_update_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_set_part::query_set_part(const std::vector<key_value_pair>& key_value_pairs)
|
||||
: query_part(sql::dialect_token::SET)
|
||||
, key_value_pairs_(key_value_pairs) {}
|
||||
|
||||
const std::vector<key_value_pair> &query_set_part::key_values() const
|
||||
{
|
||||
return key_value_pairs_;
|
||||
}
|
||||
|
||||
void query_set_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_delete_part::query_delete_part()
|
||||
: query_part(sql::dialect_token::REMOVE) {}
|
||||
|
||||
void query_delete_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_delete_from_part::query_delete_from_part(sql::table table)
|
||||
: query_part(sql::dialect_token::FROM)
|
||||
, table_(std::move(table)) {}
|
||||
|
||||
const sql::table &query_delete_from_part::table() const
|
||||
{
|
||||
return table_;
|
||||
}
|
||||
|
||||
void query_delete_from_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_create_part::query_create_part()
|
||||
: query_part(sql::dialect_token::CREATE) {}
|
||||
|
||||
void query_create_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_create_table_part::query_create_table_part(sql::table table, std::vector<sql::column_definition> columns)
|
||||
: query_part(sql::dialect_token::TABLE)
|
||||
, table_(std::move(table))
|
||||
, columns_(std::move(columns)) {}
|
||||
|
||||
const sql::table &query_create_table_part::table() const
|
||||
{
|
||||
return table_;
|
||||
}
|
||||
|
||||
const std::vector<sql::column_definition> &query_create_table_part::columns() const
|
||||
{
|
||||
return columns_;
|
||||
}
|
||||
|
||||
void query_create_table_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_drop_part::query_drop_part()
|
||||
: query_part(sql::dialect_token::DROP) {}
|
||||
|
||||
void query_drop_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_drop_table_part::query_drop_table_part(sql::table table)
|
||||
: query_part(sql::dialect_token::TABLE)
|
||||
, table_(std::move(table)) {}
|
||||
|
||||
const sql::table &query_drop_table_part::table() const
|
||||
{
|
||||
return table_;
|
||||
}
|
||||
|
||||
void query_drop_table_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "matador/sql/internal/query_result_impl.hpp"
|
||||
|
||||
#include "matador/sql/interface/query_result_reader.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
detail::pk_reader::pk_reader(query_result_reader &reader)
|
||||
: reader_(reader) {}
|
||||
|
||||
void detail::pk_reader::on_primary_key(const char *id, std::string &value, size_t size)
|
||||
{
|
||||
utils::data_type_traits<std::string>::read_value(reader_, id, column_index_++, value, size);
|
||||
}
|
||||
|
||||
query_result_impl::query_result_impl(std::unique_ptr<query_result_reader> &&reader, std::vector<column_definition> &&prototype, const size_t column_index)
|
||||
: column_index_(column_index)
|
||||
, prototype_(std::move(prototype))
|
||||
, reader_(std::move(reader))
|
||||
, pk_reader_(*reader_)
|
||||
{}
|
||||
|
||||
query_result_impl::query_result_impl(std::unique_ptr<query_result_reader> &&reader, const std::vector<column_definition> &prototype, const size_t column_index)
|
||||
: column_index_(column_index)
|
||||
, prototype_(prototype)
|
||||
, reader_(std::move(reader))
|
||||
, pk_reader_(*reader_)
|
||||
{}
|
||||
|
||||
void query_result_impl::on_primary_key(const char *id, std::string &value, size_t size)
|
||||
{
|
||||
utils::data_type_traits<std::string>::read_value(*reader_, id, column_index_++, value, size);
|
||||
}
|
||||
|
||||
void query_result_impl::on_revision(const char *id, uint64_t &rev)
|
||||
{
|
||||
utils::data_type_traits<uint64_t>::read_value(*reader_, id, column_index_++, rev);
|
||||
reader_->read_value(id, column_index_++, rev);
|
||||
}
|
||||
|
||||
void query_result_impl::on_attribute(const char *id, char *value, const utils::field_attributes &attr)
|
||||
{
|
||||
utils::data_type_traits<char*>::read_value(*reader_, id, column_index_++, value, attr.size());
|
||||
}
|
||||
|
||||
void query_result_impl::on_attribute(const char *id, std::string &value, const utils::field_attributes &attr)
|
||||
{
|
||||
utils::data_type_traits<std::string>::read_value(*reader_, id, column_index_++, value, attr.size());
|
||||
}
|
||||
|
||||
void
|
||||
query_result_impl::on_attribute(const char *id, utils::value &val, const utils::field_attributes &attr)
|
||||
{
|
||||
reader_->read_value(id, column_index_++, val, attr.size());
|
||||
}
|
||||
|
||||
const std::vector<column_definition>& query_result_impl::prototype() const
|
||||
{
|
||||
return prototype_;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "matador/query/key_value_generator.hpp"
|
||||
|
||||
#include "matador/query/value_extractor.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
void key_value_generator::on_primary_key(const char *id, std::string &x, size_t)
|
||||
{
|
||||
result_.emplace_back(id, x);
|
||||
}
|
||||
|
||||
void key_value_generator::on_revision(const char *id, unsigned long long int &x)
|
||||
{
|
||||
result_.emplace_back(id, x);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
#include "matador/query/query.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
sql::column alias(const std::string &column, const std::string &as)
|
||||
{
|
||||
return sql::column{column, as};
|
||||
}
|
||||
|
||||
sql::column alias(sql::column &&col, const std::string &as)
|
||||
{
|
||||
col.as(as);
|
||||
return std::move(col);
|
||||
}
|
||||
|
||||
sql::column count(const std::string &column)
|
||||
{
|
||||
return {sql::sql_function_t::COUNT, column};
|
||||
}
|
||||
|
||||
sql::column count_all()
|
||||
{
|
||||
return count("*");
|
||||
}
|
||||
|
||||
query_create_intermediate query::create()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
query_drop_intermediate query::drop() {
|
||||
return {};
|
||||
}
|
||||
|
||||
query_select_intermediate query::select( const std::initializer_list<sql::column> columns) {
|
||||
return select(std::vector<sql::column>{columns});
|
||||
}
|
||||
|
||||
query_select_intermediate query::select(const std::vector<sql::column>& columns) {
|
||||
return query_select_intermediate{columns};
|
||||
}
|
||||
|
||||
query_select_intermediate query::select(const std::vector<std::string> &column_names) {
|
||||
std::vector<sql::column> columns;
|
||||
columns.reserve(column_names.size());
|
||||
for (const auto &col_name : column_names) {
|
||||
columns.emplace_back(col_name);
|
||||
}
|
||||
return select(columns);
|
||||
}
|
||||
|
||||
query_select_intermediate query::select(std::vector<sql::column> columns, const std::initializer_list<sql::column> additional_columns) {
|
||||
for (const auto &col : additional_columns) {
|
||||
columns.push_back(col);
|
||||
}
|
||||
return query_select_intermediate{columns};
|
||||
}
|
||||
|
||||
query_insert_intermediate query::insert() {
|
||||
return {};
|
||||
}
|
||||
|
||||
query_update_intermediate query::update(const sql::table &table) {
|
||||
return query_update_intermediate{table};
|
||||
}
|
||||
|
||||
query_delete_intermediate query::remove() {
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,357 @@
|
||||
#include "matador/query/query_compiler.hpp"
|
||||
|
||||
#include "matador/query/attribute_string_writer.hpp"
|
||||
#include "matador/query/query_data.hpp"
|
||||
|
||||
#include "matador/query/internal/basic_type_to_string_visitor.hpp"
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
#include "matador/sql/query_context.hpp"
|
||||
#include "matador/sql/connection.hpp"
|
||||
#include "matador/sql/dialect.hpp"
|
||||
|
||||
#include "matador/utils/string.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
sql::query_context query_compiler::compile(const query_data &data,
|
||||
const sql::dialect &d,
|
||||
std::optional<std::reference_wrapper<const sql::connection_impl>> conn)
|
||||
{
|
||||
data_ = &data;
|
||||
dialect_ = &d;
|
||||
connection_ = conn;
|
||||
query_ = {};
|
||||
for (const auto &part: data.parts) {
|
||||
part->accept(*this);
|
||||
}
|
||||
connection_ = std::nullopt;
|
||||
dialect_ = nullptr;
|
||||
data_ = nullptr;
|
||||
|
||||
return query_;
|
||||
}
|
||||
|
||||
std::string handle_column(sql::query_context &ctx, const sql::dialect *d, const query_data &data, const sql::column &col) {
|
||||
ctx.result_vars.emplace_back(col.name);
|
||||
const auto& column_table = col.table_.get();
|
||||
ctx.column_aliases.insert({column_table->has_alias() ? column_table->alias : column_table->name + "." + col.name, col.alias});
|
||||
if (col.is_function()) {
|
||||
ctx.prototype.emplace_back(col.has_alias() ? col.alias : col.name);
|
||||
ctx.prototype.back().type(utils::basic_type::type_int32);
|
||||
} else {
|
||||
ctx.prototype.emplace_back(col.name);
|
||||
}
|
||||
|
||||
if (const auto it = data.tables.find(col.table_->name); it != data.tables.end()) {
|
||||
return d->prepare_identifier({it->second, col.name, col.alias});
|
||||
}
|
||||
|
||||
return d->prepare_identifier(col);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_select_part &select_part)
|
||||
{
|
||||
query_.command = sql::sql_command::SQL_CMD_SELECT;
|
||||
query_.sql = dialect_->token_at(sql::dialect_token::SELECT) + " ";
|
||||
|
||||
query_.prototype.clear();
|
||||
|
||||
std::string result;
|
||||
if (const auto &columns = select_part.columns(); columns.size() < 2) {
|
||||
for (const auto &col: columns) {
|
||||
result.append(handle_column(query_, dialect_, *data_, col ));
|
||||
}
|
||||
} else {
|
||||
auto it = columns.begin();
|
||||
result.append(handle_column(query_, dialect_, *data_, *it++));
|
||||
for (; it != columns.end(); ++it) {
|
||||
result.append(", ");
|
||||
result.append(handle_column(query_, dialect_, *data_, *it));
|
||||
}
|
||||
}
|
||||
|
||||
query_.sql += result;
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_from_part &from_part)
|
||||
{
|
||||
query_.table = from_part.table();
|
||||
query_.sql += " " + query_compiler::build_table_name(from_part.token(), *dialect_, query_.table);
|
||||
query_.table_aliases.insert({query_.table.name, query_.table.alias});
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_join_part &join_part)
|
||||
{
|
||||
query_.sql += " " + query_compiler::build_table_name(join_part.token(), *dialect_, join_part.table());
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_on_part &on_part)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::ON) +
|
||||
" " + on_part.condition().evaluate(*dialect_, query_);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_where_part &where_part)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::WHERE) +
|
||||
" " + where_part.condition().evaluate(*dialect_, query_);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_group_by_part &group_by_part)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::GROUP_BY) + " " + dialect_->prepare_identifier(group_by_part.column());
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_order_by_part &order_by_part)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::ORDER_BY) +
|
||||
" " + dialect_->prepare_condition(order_by_part.column());
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_order_by_asc_part &/*order_by_asc_part*/)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::ASC);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_order_by_desc_part &/*order_by_desc_part*/)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::DESC);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_offset_part &offset_part)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::OFFSET) + " " + std::to_string(offset_part.offset());
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_limit_part &limit_part)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::LIMIT) + " " + std::to_string(limit_part.limit());
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_insert_part &/*insert_part*/)
|
||||
{
|
||||
query_.command = sql::sql_command::SQL_CMD_INSERT;
|
||||
query_.sql = dialect_->token_at(sql::dialect_token::INSERT);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_into_part &into_part)
|
||||
{
|
||||
query_.table = into_part.table();
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::INTO) +
|
||||
" " + dialect_->prepare_identifier_string(into_part.table().name);
|
||||
|
||||
std::string result{"("};
|
||||
if (into_part.columns().size() < 2) {
|
||||
for (const auto &col: into_part.columns()) {
|
||||
result.append(dialect_->prepare_identifier_string(col.name));
|
||||
}
|
||||
} else {
|
||||
auto it = into_part.columns().begin();
|
||||
result.append(dialect_->prepare_identifier_string((it++)->name));
|
||||
for (; it != into_part.columns().end(); ++it) {
|
||||
result.append(", ");
|
||||
result.append(dialect_->prepare_identifier_string(it->name));
|
||||
}
|
||||
}
|
||||
result += (")");
|
||||
query_.sql += " " + result;
|
||||
}
|
||||
|
||||
struct value_visitor {
|
||||
value_visitor(attribute_string_writer &w, sql::query_context &ctx)
|
||||
: value_to_string_visitor(w, ctx) {}
|
||||
|
||||
void operator()(const utils::database_type &val) {
|
||||
std::visit(value_to_string_visitor, val);
|
||||
|
||||
}
|
||||
void operator()(const utils::placeholder &/*val*/) {
|
||||
value_to_string_visitor.query.bind_vars.emplace_back("unknown");
|
||||
value_to_string_visitor.result = value_to_string_visitor.writer->dialect().next_placeholder(value_to_string_visitor.query.bind_vars);
|
||||
}
|
||||
|
||||
internal::basic_type_to_string_visitor value_to_string_visitor;
|
||||
};
|
||||
|
||||
void query_compiler::visit(internal::query_values_part &values_part)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::VALUES);
|
||||
|
||||
attribute_string_writer writer(*dialect_, connection_);
|
||||
|
||||
value_visitor visitor(writer, query_);
|
||||
std::string result{"("};
|
||||
if (values_part.values().size() < 2) {
|
||||
for (const auto& val: values_part.values()) {
|
||||
std::visit(visitor, val);
|
||||
result.append(visitor.value_to_string_visitor.result);
|
||||
}
|
||||
} else {
|
||||
auto it = values_part.values().begin();
|
||||
auto val = *it++;
|
||||
std::visit(visitor, val);
|
||||
result.append(visitor.value_to_string_visitor.result);
|
||||
for (; it != values_part.values().end(); ++it) {
|
||||
result.append(", ");
|
||||
val = *it;
|
||||
std::visit(visitor, val);
|
||||
result.append(visitor.value_to_string_visitor.result);
|
||||
}
|
||||
}
|
||||
result += (")");
|
||||
|
||||
query_.sql += " " + result;
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_update_part &update_part)
|
||||
{
|
||||
query_.command = sql::sql_command::SQL_CMD_UPDATE;
|
||||
query_.table = update_part.table();
|
||||
query_.sql += query_compiler::build_table_name(update_part.token(), *dialect_, query_.table);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_delete_part &/*delete_part*/)
|
||||
{
|
||||
query_.command = sql::sql_command::SQL_CMD_DELETE;
|
||||
query_.sql = dialect_->token_at(sql::dialect_token::REMOVE);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_delete_from_part &delete_from_part)
|
||||
{
|
||||
query_.table = delete_from_part.table();
|
||||
query_.sql += " " + query_compiler::build_table_name(delete_from_part.token(), *dialect_, query_.table);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_create_part &/*create_part*/)
|
||||
{
|
||||
query_.command = sql::sql_command::SQL_CMD_CREATE;
|
||||
query_.sql = dialect_->token_at(sql::dialect_token::CREATE);
|
||||
}
|
||||
|
||||
struct fk_context
|
||||
{
|
||||
std::string column;
|
||||
std::string ref_table;
|
||||
std::string ref_column;
|
||||
};
|
||||
|
||||
struct column_context
|
||||
{
|
||||
std::vector<std::string> primary_keys;
|
||||
std::vector<fk_context> foreign_contexts;
|
||||
};
|
||||
|
||||
std::string build_create_column(const sql::column_definition &col, const sql::dialect &d, column_context &context);
|
||||
|
||||
void query_compiler::visit(internal::query_create_table_part &create_table_part)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::TABLE) + " " + dialect_->prepare_identifier_string(create_table_part.table().name) + " ";
|
||||
query_.table = create_table_part.table();
|
||||
|
||||
std::string result = "(";
|
||||
|
||||
column_context context;
|
||||
|
||||
if (create_table_part.columns().size() < 2) {
|
||||
for (const auto &col: create_table_part.columns()) {
|
||||
result.append(build_create_column(col, *dialect_, context));
|
||||
}
|
||||
} else {
|
||||
auto it = create_table_part.columns().begin();
|
||||
result.append(build_create_column(*it++, *dialect_, context));
|
||||
for (; it != create_table_part.columns().end(); ++it) {
|
||||
result.append(", ");
|
||||
result.append(build_create_column(*it, *dialect_, context));
|
||||
}
|
||||
}
|
||||
|
||||
if (!context.primary_keys.empty()) {
|
||||
result.append(", CONSTRAINT PK_" + create_table_part.table().name + " PRIMARY KEY (" + utils::join(context.primary_keys, ", ") + ")");
|
||||
}
|
||||
for (const auto &fk: context.foreign_contexts) {
|
||||
result += ", CONSTRAINT FK_" + create_table_part.table().name;
|
||||
result += "_" + fk.column;
|
||||
result += " FOREIGN KEY (" + fk.column + ")";
|
||||
result += " REFERENCES " + fk.ref_table + "(" + fk.ref_column + ")";
|
||||
}
|
||||
|
||||
result += ")";
|
||||
query_.sql += result;
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_drop_part &/*drop_part*/)
|
||||
{
|
||||
query_.command = sql::sql_command::SQL_CMD_DROP;
|
||||
query_.sql = dialect_->token_at(sql::dialect_token::DROP);
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_set_part &set_part)
|
||||
{
|
||||
query_.sql += " " + dialect_->token_at(sql::dialect_token::SET) + " ";
|
||||
|
||||
attribute_string_writer writer(*dialect_, connection_);
|
||||
internal::basic_type_to_string_visitor value_to_string(writer, query_);
|
||||
std::string result;
|
||||
if (set_part.key_values().size() < 2) {
|
||||
for (const auto &col: set_part.key_values()) {
|
||||
result.append(dialect_->prepare_identifier_string(col.name()) + "=");
|
||||
auto var = col.value();
|
||||
std::visit(value_to_string, var);
|
||||
result.append(value_to_string.result);
|
||||
}
|
||||
} else {
|
||||
auto it = set_part.key_values().begin();
|
||||
result.append(dialect_->prepare_identifier_string(it->name()) + "=");
|
||||
auto var = (it++)->value();
|
||||
std::visit(value_to_string, var);
|
||||
result.append(value_to_string.result);
|
||||
for (; it != set_part.key_values().end(); ++it) {
|
||||
result.append(", ");
|
||||
result.append(dialect_->prepare_identifier_string(it->name()) + "=");
|
||||
var = it->value();
|
||||
std::visit(value_to_string, var);
|
||||
result.append(value_to_string.result);
|
||||
}
|
||||
}
|
||||
|
||||
query_.sql += result;
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_drop_table_part &drop_table_part)
|
||||
{
|
||||
query_.table = drop_table_part.table();
|
||||
query_.sql += " " + query_compiler::build_table_name(drop_table_part.token(), *dialect_, query_.table);
|
||||
}
|
||||
|
||||
std::string build_create_column(const sql::column_definition &col, const sql::dialect &d, column_context &context)
|
||||
{
|
||||
std::string result = d.prepare_identifier_string(col.name()) + " " + d.data_type_at(col.type());
|
||||
if (col.attributes().size() > 0) {
|
||||
result.append("(" + std::to_string(col.attributes().size()) + ")");
|
||||
}
|
||||
if (!col.is_nullable()) {
|
||||
result.append(" NOT NULL");
|
||||
}
|
||||
if (is_constraint_set(col.attributes().options(), utils::constraints::UNIQUE)) {
|
||||
result.append(" UNIQUE");
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
std::string query_compiler::build_table_name(const sql::dialect_token token, const sql::dialect &d, const sql::table& t)
|
||||
{
|
||||
return d.token_at(token) + " " +
|
||||
(!d.default_schema_name().empty() ? d.prepare_identifier_string(d.default_schema_name()) + "." : "") +
|
||||
d.prepare_identifier_string(t.name) +
|
||||
(t.alias.empty() ? "" : " " + d.prepare_identifier_string(t.alias));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "matador/query/query_part.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_part::query_part(const sql::dialect_token token)
|
||||
: token_(token) {}
|
||||
|
||||
sql::dialect_token query_part::token() const {
|
||||
return token_;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#include "matador/query/intermediates/query_update_intermediate.hpp"
|
||||
|
||||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
query_update_intermediate::query_update_intermediate(const sql::table& table)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_update_part>(table));
|
||||
}
|
||||
|
||||
query_set_intermediate query_update_intermediate::set(std::initializer_list<internal::key_value_pair> columns)
|
||||
{
|
||||
return set(std::vector<internal::key_value_pair>{columns});
|
||||
}
|
||||
|
||||
query_set_intermediate query_update_intermediate::set(std::vector<internal::key_value_pair> &&columns)
|
||||
{
|
||||
context_->parts.push_back(std::make_unique<internal::query_set_part>(std::move(columns)));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
#include "matador/query/value_extractor.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
value_extractor::value_extractor(std::vector<utils::database_type> &values)
|
||||
: values_(values)
|
||||
{}
|
||||
|
||||
void value_extractor::on_primary_key(const char *, std::string &pk, size_t s)
|
||||
{
|
||||
utils::data_type_traits<std::string>::bind_value(*this, 0, pk, s);
|
||||
}
|
||||
|
||||
void value_extractor::on_revision(const char *, uint64_t &rev)
|
||||
{
|
||||
utils::data_type_traits<uint64_t>::bind_value(*this, 0, rev);
|
||||
}
|
||||
|
||||
void value_extractor::on_attribute(const char *, char *x, const utils::field_attributes &attr)
|
||||
{
|
||||
utils::data_type_traits<char*>::bind_value(*this, 0, x, attr.size());
|
||||
}
|
||||
|
||||
void value_extractor::on_attribute(const char *, std::string &x, const utils::field_attributes &attr)
|
||||
{
|
||||
utils::data_type_traits<std::string>::bind_value(*this, 0, x, attr.size());
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const int8_t &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const int16_t &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const int32_t &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const int64_t &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const uint8_t &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const uint16_t &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const uint32_t &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const uint64_t &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const bool &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const float &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const double &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const time &/*x*/)
|
||||
{
|
||||
// values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const date &/*x*/)
|
||||
{
|
||||
// values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const char *x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const char *x, size_t /*size*/)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const std::string &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const std::string &x, size_t /*size*/)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const utils::blob &x)
|
||||
{
|
||||
values_.emplace_back(x);
|
||||
}
|
||||
|
||||
void value_extractor::write_value(size_t /*pos*/, const utils::value &/*x*/, size_t /*size*/)
|
||||
{
|
||||
// values_.emplace_back(x);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user