startet with connection query intermediates
This commit is contained in:
parent
487dfb2eb4
commit
7b6cc121da
|
|
@ -4,11 +4,14 @@
|
||||||
#include "matador/sql/basic_condition.hpp"
|
#include "matador/sql/basic_condition.hpp"
|
||||||
#include "matador/sql/dialect.hpp"
|
#include "matador/sql/dialect.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
|
struct placeholder {};
|
||||||
|
|
||||||
|
const placeholder _;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class condition
|
* @class condition
|
||||||
* @brief Represents a sql query condition
|
* @brief Represents a sql query condition
|
||||||
|
|
@ -29,6 +32,17 @@ class query;
|
||||||
template<class L, class R, class Enabled = void>
|
template<class L, class R, class Enabled = void>
|
||||||
class condition;
|
class condition;
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class condition<column, placeholder, typename std::enable_if<true>::type> : public basic_column_condition
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
condition(const column &fld, basic_condition::operand_t op, const placeholder &val);
|
||||||
|
|
||||||
|
placeholder value;
|
||||||
|
|
||||||
|
std::string evaluate(dialect &d) const override;
|
||||||
|
};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
class condition<column, T, typename std::enable_if<
|
class condition<column, T, typename std::enable_if<
|
||||||
std::is_scalar<T>::value &&
|
std::is_scalar<T>::value &&
|
||||||
|
|
@ -46,13 +60,7 @@ public:
|
||||||
std::string evaluate(dialect &d) const override
|
std::string evaluate(dialect &d) const override
|
||||||
{
|
{
|
||||||
d.add_host_var(field_.name());
|
d.add_host_var(field_.name());
|
||||||
std::stringstream str;
|
return d.prepare_identifier(field_.name()) + " " + operand + " " + std::to_string(value);
|
||||||
if (d.compile_type() == dialect::compile_type_t::DIRECT) {
|
|
||||||
str << d.prepare_identifier(field_.name()) << " " << operand << " " << value;
|
|
||||||
} else {
|
|
||||||
str << d.prepare_identifier(field_.name()) << " " << operand << " " << d.next_placeholder();
|
|
||||||
}
|
|
||||||
return str.str();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -72,13 +80,7 @@ public:
|
||||||
std::string evaluate(dialect &d) const override
|
std::string evaluate(dialect &d) const override
|
||||||
{
|
{
|
||||||
d.add_host_var(field_.name());
|
d.add_host_var(field_.name());
|
||||||
std::stringstream str;
|
return d.prepare_identifier(field_.name()) + " " + operand + " '" + value + "'";
|
||||||
if (d.compile_type() == dialect::compile_type_t::DIRECT) {
|
|
||||||
str << d.prepare_identifier(field_.name()) << " " << operand << " '" << value << "'";
|
|
||||||
} else {
|
|
||||||
str << d.prepare_identifier(field_.name()) << " " << operand << " " << d.next_placeholder();
|
|
||||||
}
|
|
||||||
return str.str();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -98,9 +100,7 @@ public:
|
||||||
|
|
||||||
std::string evaluate(dialect &d) const override
|
std::string evaluate(dialect &d) const override
|
||||||
{
|
{
|
||||||
std::stringstream str;
|
return std::to_string(value) + " " + operand + " " + d.prepare_identifier(field_.name());
|
||||||
str << value << " " << operand << " " << d.prepare_identifier(field_.name());
|
|
||||||
return str.str();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -119,9 +119,7 @@ public:
|
||||||
|
|
||||||
std::string evaluate(dialect &d) const override
|
std::string evaluate(dialect &d) const override
|
||||||
{
|
{
|
||||||
std::stringstream str;
|
return "'" + std::to_string(value) + "' " + operand + " " + d.prepare_identifier(field_.name());
|
||||||
str << "'" << value << "' " << operand << " " << d.prepare_identifier(field_.name());
|
|
||||||
return str.str();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -138,74 +136,62 @@ public:
|
||||||
* @endcode
|
* @endcode
|
||||||
*/
|
*/
|
||||||
template < class V >
|
template < class V >
|
||||||
class condition<column, std::initializer_list<V>> : public basic_in_condition
|
class condition<column, std::initializer_list<V>> : public basic_in_condition {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Creates an IN condition
|
* @brief Creates an IN condition
|
||||||
*
|
*
|
||||||
* Creates an IN condition for the given column and
|
* Creates an IN condition for the given column and
|
||||||
* the given list of arguments.
|
* the given list of arguments.
|
||||||
*
|
*
|
||||||
* @param col Column for the IN condition
|
* @param col Column for the IN condition
|
||||||
* @param args List of arguments
|
* @param args List of arguments
|
||||||
*/
|
*/
|
||||||
condition(const column &col, const std::initializer_list<V> &args)
|
condition(const column &col, const std::initializer_list<V> &args)
|
||||||
: basic_in_condition(col)
|
: basic_in_condition(col), args_(args) {}
|
||||||
, args_(args)
|
|
||||||
{}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Evaluates the condition
|
* @brief Evaluates the condition
|
||||||
*
|
*
|
||||||
* Evaluates the condition to a part of the
|
* Evaluates the condition to a part of the
|
||||||
* query string based on the given compile type
|
* query string based on the given compile type
|
||||||
*
|
*
|
||||||
* @param d The d used to evaluate
|
* @param d The d used to evaluate
|
||||||
* @return A condition IN part of the query
|
* @return A condition IN part of the query
|
||||||
*/
|
*/
|
||||||
std::string evaluate(dialect &d) const override
|
std::string evaluate(dialect &d) const override {
|
||||||
{
|
auto count = size();
|
||||||
auto count = size();
|
for (size_t i = 0; i < count; ++i) {
|
||||||
for (size_t i = 0; i < count; ++i) {
|
d.add_host_var(field_.name());
|
||||||
d.add_host_var(field_.name());
|
}
|
||||||
}
|
|
||||||
std::stringstream str;
|
|
||||||
str << d.prepare_identifier(field_.name()) << " IN (";
|
std::string result = d.prepare_identifier(field_.name()) + " IN (";
|
||||||
if (args_.size() > 1) {
|
if (args_.size() < 2) {
|
||||||
auto first = args_.begin();
|
for (const auto &val : args_) {
|
||||||
auto last = args_.end() - 1;
|
result.append(std::to_string(val));
|
||||||
while (first != last) {
|
}
|
||||||
if (d.compile_type() == dialect::compile_type_t::DIRECT) {
|
} else {
|
||||||
str << *first++ << ",";
|
auto it = args_.begin();
|
||||||
} else {
|
result.append(std::to_string(*it++));
|
||||||
++first;
|
for(; it != args_.end(); ++it) {
|
||||||
str << d.next_placeholder() << ",";
|
result.append(", " + std::to_string(*it));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
result += ")";
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
if (!args_.empty()) {
|
|
||||||
if (d.compile_type() == dialect::compile_type_t::DIRECT) {
|
|
||||||
str << args_.back();
|
|
||||||
} else {
|
|
||||||
str << d.next_placeholder();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
str << ")";
|
|
||||||
return str.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the number of arguments in the list
|
* @brief Returns the number of arguments in the list
|
||||||
* @return The number of arguments in the list
|
* @return The number of arguments in the list
|
||||||
*/
|
*/
|
||||||
size_t size() const override
|
[[nodiscard]] size_t size() const override {
|
||||||
{
|
return args_.size();
|
||||||
return args_.size();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<V> args_;
|
std::vector<V> args_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -244,23 +230,12 @@ public:
|
||||||
* @param d The d used to evaluate
|
* @param d The d used to evaluate
|
||||||
* @return A condition IN part of the query
|
* @return A condition IN part of the query
|
||||||
*/
|
*/
|
||||||
std::string evaluate(dialect &d) const override
|
std::string evaluate(dialect &d) const override;
|
||||||
{
|
|
||||||
std::string result(d.prepare_identifier(field_.name()) + " " + operand + " (");
|
|
||||||
// result += d.continue_build(const_cast<query&>(query_), d.compile_type());
|
|
||||||
result += (")");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
query &query_;
|
query &query_;
|
||||||
};
|
};
|
||||||
|
|
||||||
condition<column, query>::condition(column col, basic_condition::operand_t op, query &q)
|
|
||||||
: basic_column_condition(std::move(col), op)
|
|
||||||
, query_(q)
|
|
||||||
{}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Between condition.
|
* @brief Between condition.
|
||||||
*
|
*
|
||||||
|
|
@ -270,43 +245,35 @@ condition<column, query>::condition(column col, basic_condition::operand_t op, q
|
||||||
* @tparam T The type of the boundary values
|
* @tparam T The type of the boundary values
|
||||||
*/
|
*/
|
||||||
template < class T >
|
template < class T >
|
||||||
class condition<column, std::pair<T, T>> : public basic_condition
|
class condition<column, std::pair<T, T>> : public basic_condition {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Create a new between condition
|
* @brief Create a new between condition
|
||||||
*
|
*
|
||||||
* @param col The column for the range check
|
* @param col The column for the range check
|
||||||
* @param range The boundary values defining the range
|
* @param range The boundary values defining the range
|
||||||
*/
|
*/
|
||||||
condition(column col, const std::pair<T, T> &range)
|
condition(column col, const std::pair<T, T> &range)
|
||||||
: field_(std::move(col)), range_(range) { }
|
: field_(std::move(col)), range_(range) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Evaluates the condition
|
* @brief Evaluates the condition
|
||||||
*
|
*
|
||||||
* Evaluates the condition to a between part
|
* Evaluates the condition to a between part
|
||||||
* based on the given compile type
|
* based on the given compile type
|
||||||
*
|
*
|
||||||
* @param d The d used to evaluate
|
* @param d The d used to evaluate
|
||||||
* @return A condition BETWEEN part of the query
|
* @return A condition BETWEEN part of the query
|
||||||
*/
|
*/
|
||||||
std::string evaluate(dialect &d) const override
|
std::string evaluate(dialect &d) const override {
|
||||||
{
|
d.add_host_var(field_.name());
|
||||||
d.add_host_var(field_.name());
|
d.add_host_var(field_.name());
|
||||||
d.add_host_var(field_.name());
|
return d.prepare_identifier(field_.name()) + " BETWEEN " + std::to_string(range_.first) + " AND " + std::to_string(range_.second);
|
||||||
std::stringstream str;
|
}
|
||||||
if (d.compile_type() == dialect::compile_type_t::DIRECT) {
|
|
||||||
str << d.prepare_identifier(field_.name()) << " BETWEEN " << range_.first << " AND " << range_.second;
|
|
||||||
} else {
|
|
||||||
str << d.prepare_identifier(field_.name()) << " BETWEEN " << d.next_placeholder() << " AND " << d.next_placeholder();
|
|
||||||
}
|
|
||||||
return str.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
column field_;
|
column field_;
|
||||||
std::pair<T, T> range_;
|
std::pair<T, T> range_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -331,7 +298,6 @@ public:
|
||||||
* @param r right hand operator of the condition
|
* @param r right hand operator of the condition
|
||||||
* @param op The operand (AND or OR)
|
* @param op The operand (AND or OR)
|
||||||
*/
|
*/
|
||||||
// condition(const condition<L1, R1> &l, const condition<L2, R2> &r, basic_condition::operand_t op)
|
|
||||||
condition(condition<L1, R1> &&l, condition<L2, R2> &&r, basic_condition::operand_t op)
|
condition(condition<L1, R1> &&l, condition<L2, R2> &&r, basic_condition::operand_t op)
|
||||||
: left(std::move(l)), right(std::move(r)), operand(op) { }
|
: left(std::move(l)), right(std::move(r)), operand(op) { }
|
||||||
|
|
||||||
|
|
@ -343,16 +309,14 @@ public:
|
||||||
*/
|
*/
|
||||||
std::string evaluate(dialect &d) const override
|
std::string evaluate(dialect &d) const override
|
||||||
{
|
{
|
||||||
std::stringstream str;
|
|
||||||
// ensure the numbering order for host vars
|
// ensure the numbering order for host vars
|
||||||
auto cl = left.evaluate(d);
|
auto cl = left.evaluate(d);
|
||||||
auto cr = right.evaluate(d);
|
auto cr = right.evaluate(d);
|
||||||
if (operand == basic_condition::operand_t::AND) {
|
if (operand == basic_condition::operand_t::AND) {
|
||||||
str << "(" << cl << " " << basic_condition::operands[operand] << " " << cr << ")";
|
return "(" + cl + " " + basic_condition::operands[operand] + " " + cr + ")";
|
||||||
} else {
|
} else {
|
||||||
str << cl << " " << basic_condition::operands[operand] << " " << cr;
|
return cl + " " + basic_condition::operands[operand] + " " + cr;
|
||||||
}
|
}
|
||||||
return str.str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -388,9 +352,7 @@ public:
|
||||||
*/
|
*/
|
||||||
std::string evaluate(dialect &d) const override
|
std::string evaluate(dialect &d) const override
|
||||||
{
|
{
|
||||||
std::stringstream str;
|
return operand + " (" + cond.evaluate(d) + ")";
|
||||||
str << operand << " (" << cond.evaluate(d) << ")";
|
|
||||||
return str.str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -466,7 +428,6 @@ condition<column, std::pair<T, T>> between(const column &col, T low, T high)
|
||||||
* @return The like condition object
|
* @return The like condition object
|
||||||
*/
|
*/
|
||||||
condition<column, std::string> like(const column &col, const std::string &val);
|
condition<column, std::string> like(const column &col, const std::string &val);
|
||||||
//OOS_SQL_API condition<column, std::string> like(const matador::column &col, const std::string &val);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Condition equality operator for a column and a value
|
* @brief Condition equality operator for a column and a value
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef QUERY_CONNECTION_HPP
|
||||||
|
#define QUERY_CONNECTION_HPP
|
||||||
|
|
||||||
|
#include "matador/sql/connection_intermediates.hpp"
|
||||||
|
#include "matador/sql/dialect.hpp"
|
||||||
|
#include "matador/sql/query_builder.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
class connection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
connection();
|
||||||
|
query_select_intermediate select(std::initializer_list<std::string> column_names);
|
||||||
|
|
||||||
|
result execute(const std::string &sql);
|
||||||
|
|
||||||
|
private:
|
||||||
|
dialect dialect_;
|
||||||
|
query_builder query_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //QUERY_CONNECTION_HPP
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
#ifndef QUERY_CONNECTION_INTERMEDIATES_HPP
|
||||||
|
#define QUERY_CONNECTION_INTERMEDIATES_HPP
|
||||||
|
|
||||||
|
#include "matador/sql/result.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
class basic_condition;
|
||||||
|
class connection;
|
||||||
|
class query_builder;
|
||||||
|
|
||||||
|
struct query_intermediate
|
||||||
|
{
|
||||||
|
query_intermediate(connection &db, query_builder &query);
|
||||||
|
|
||||||
|
connection &db;
|
||||||
|
query_builder &query;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct query_finish : query_intermediate
|
||||||
|
{
|
||||||
|
using query_intermediate::query_intermediate;
|
||||||
|
|
||||||
|
result fetch_all();
|
||||||
|
result fetch_one();
|
||||||
|
result fetch_value();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct query_order_direction_intermediate : query_finish
|
||||||
|
{
|
||||||
|
using query_finish::query_finish;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct query_group_by_intermediate : query_finish
|
||||||
|
{
|
||||||
|
using query_finish::query_finish;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
struct query_order_by_intermediate : query_intermediate
|
||||||
|
{
|
||||||
|
using query_intermediate::query_intermediate;
|
||||||
|
query_order_direction_intermediate asc();
|
||||||
|
query_order_direction_intermediate desc();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct query_where_intermediate : query_finish
|
||||||
|
{
|
||||||
|
using query_finish::query_finish;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct query_from_intermediate : query_finish
|
||||||
|
{
|
||||||
|
using query_finish::query_finish;
|
||||||
|
|
||||||
|
query_where_intermediate where(const basic_condition &cond);
|
||||||
|
query_group_by_intermediate group_by(const std::string &name);
|
||||||
|
query_order_by_intermediate order_by(const std::string &name);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct query_select_intermediate : query_intermediate
|
||||||
|
{
|
||||||
|
using query_intermediate::query_intermediate;
|
||||||
|
|
||||||
|
query_from_intermediate from(const std::string &table, const std::string &as = "");
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //QUERY_CONNECTION_INTERMEDIATES_HPP
|
||||||
|
|
@ -23,7 +23,6 @@ public:
|
||||||
SELECT,
|
SELECT,
|
||||||
TABLE,
|
TABLE,
|
||||||
VALUES,
|
VALUES,
|
||||||
VALUE,
|
|
||||||
COLUMNS,
|
COLUMNS,
|
||||||
COLUMN,
|
COLUMN,
|
||||||
FROM,
|
FROM,
|
||||||
|
|
@ -36,11 +35,10 @@ public:
|
||||||
GROUP_BY,
|
GROUP_BY,
|
||||||
ASC,
|
ASC,
|
||||||
DESC,
|
DESC,
|
||||||
TOP,
|
LIMIT,
|
||||||
AS,
|
AS,
|
||||||
OFFSET,
|
OFFSET,
|
||||||
DISTINCT,
|
DISTINCT,
|
||||||
CONDITION,
|
|
||||||
SET,
|
SET,
|
||||||
NOT_NULL,
|
NOT_NULL,
|
||||||
PRIMARY_KEY,
|
PRIMARY_KEY,
|
||||||
|
|
@ -53,14 +51,6 @@ public:
|
||||||
NONE
|
NONE
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Enum representing the compile type
|
|
||||||
*/
|
|
||||||
enum class compile_type_t : uint8_t {
|
|
||||||
PREPARED, /**< Compile type for prepared statements */
|
|
||||||
DIRECT /**< Compile type for direct execute statements */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holding enums concerning escaping identifiers
|
* Holding enums concerning escaping identifiers
|
||||||
*/
|
*/
|
||||||
|
|
@ -127,7 +117,6 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual std::string next_placeholder() const;
|
virtual std::string next_placeholder() const;
|
||||||
|
|
||||||
compile_type_t compile_type() const;
|
|
||||||
void add_host_var(const std::string &host_var);
|
void add_host_var(const std::string &host_var);
|
||||||
void add_column(const std::string &column);
|
void add_column(const std::string &column);
|
||||||
|
|
||||||
|
|
@ -137,41 +126,41 @@ public:
|
||||||
private:
|
private:
|
||||||
using token_to_string_map = std::unordered_map<token_t, std::string>;
|
using token_to_string_map = std::unordered_map<token_t, std::string>;
|
||||||
|
|
||||||
compile_type_t compile_type_ = compile_type_t::DIRECT;
|
|
||||||
std::vector<std::string> host_vars_;
|
std::vector<std::string> host_vars_;
|
||||||
std::vector<std::string> columns_;
|
std::vector<std::string> columns_;
|
||||||
|
|
||||||
token_to_string_map tokens_ {
|
token_to_string_map tokens_ {
|
||||||
{token_t::CREATE, "CREATE"},
|
{token_t::CREATE, "CREATE"},
|
||||||
{token_t::DROP, "DROP"},
|
{token_t::DROP, "DROP"},
|
||||||
{token_t::REMOVE, "DELETE"},
|
{token_t::REMOVE, "DELETE"},
|
||||||
{token_t::INSERT, "INSERT"},
|
{token_t::INSERT, "INSERT"},
|
||||||
{token_t::TABLE, "TABLE"},
|
{token_t::TABLE, "TABLE"},
|
||||||
{token_t::INTO, "INTO"},
|
{token_t::INTO, "INTO"},
|
||||||
{token_t::VALUES, "VALUES"},
|
{token_t::VALUES, "VALUES"},
|
||||||
{token_t::UPDATE, "UPDATE"},
|
{token_t::UPDATE, "UPDATE"},
|
||||||
{token_t::SELECT, "SELECT"},
|
{token_t::SELECT, "SELECT"},
|
||||||
{token_t::COLUMNS, "COLUMNS"},
|
{token_t::COLUMNS, "COLUMNS"},
|
||||||
{token_t::COLUMN, "COLUMN"},
|
{token_t::COLUMN, "COLUMN"},
|
||||||
{token_t::FROM, "FROM"},
|
{token_t::FROM, "FROM"},
|
||||||
{token_t::WHERE, "WHERE"},
|
{token_t::WHERE, "WHERE"},
|
||||||
{token_t::AND, "AND"},
|
{token_t::AND, "AND"},
|
||||||
{token_t::OR, "OR"},
|
{token_t::OR, "OR"},
|
||||||
{token_t::LIKE, "LIKE"},
|
{token_t::LIKE, "LIKE"},
|
||||||
{token_t::ORDER_BY, "ORDER BY"},
|
{token_t::ORDER_BY, "ORDER BY"},
|
||||||
{token_t::GROUP_BY, "GROUP BY"},
|
{token_t::GROUP_BY, "GROUP BY"},
|
||||||
{token_t::ASC, "ASC"},
|
{token_t::ASC, "ASC"},
|
||||||
{token_t::DESC, "DESC"},
|
{token_t::DESC, "DESC"},
|
||||||
{token_t::TOP, "LIMIT"},
|
{token_t::OFFSET, "OFFSET"},
|
||||||
{token_t::AS, "AS"},
|
{token_t::LIMIT, "LIMIT"},
|
||||||
{token_t::OFFSET, "OFFSET"},
|
{token_t::AS, "AS"},
|
||||||
{token_t::DISTINCT, "DISTINCT"},
|
{token_t::OFFSET, "OFFSET"},
|
||||||
{token_t::SET, "SET"},
|
{token_t::DISTINCT, "DISTINCT"},
|
||||||
{token_t::NOT_NULL, "NOT NULL"},
|
{token_t::SET, "SET"},
|
||||||
|
{token_t::NOT_NULL, "NOT NULL"},
|
||||||
{token_t::PRIMARY_KEY, "PRIMARY KEY"},
|
{token_t::PRIMARY_KEY, "PRIMARY KEY"},
|
||||||
{token_t::BEGIN, "BEGIN TRANSACTION"},
|
{token_t::BEGIN, "BEGIN TRANSACTION"},
|
||||||
{token_t::COMMIT, "COMMIT TRANSACTION"},
|
{token_t::COMMIT, "COMMIT TRANSACTION"},
|
||||||
{token_t::ROLLBACK, "ROLLBACK TRANSACTION"},
|
{token_t::ROLLBACK, "ROLLBACK TRANSACTION"},
|
||||||
{token_t::START_QUOTE, "\""},
|
{token_t::START_QUOTE, "\""},
|
||||||
{token_t::END_QUOTE, "\""},
|
{token_t::END_QUOTE, "\""},
|
||||||
{token_t::STRING_QUOTE, "'"},
|
{token_t::STRING_QUOTE, "'"},
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
@startuml
|
||||||
|
|
||||||
|
scale 800 width
|
||||||
|
state Query
|
||||||
|
|
||||||
|
state Create
|
||||||
|
Create : Create database table
|
||||||
|
state Drop
|
||||||
|
Drop : Drop database table
|
||||||
|
state Select
|
||||||
|
Select: Query rows
|
||||||
|
Select: Add columns
|
||||||
|
state Insert
|
||||||
|
Insert: Insert rows
|
||||||
|
state Update
|
||||||
|
Update: Update rows
|
||||||
|
Update: Set table name
|
||||||
|
state Delete
|
||||||
|
Delete: Delete items from table
|
||||||
|
|
||||||
|
state Table
|
||||||
|
Table: Set table name
|
||||||
|
state Into
|
||||||
|
Into: Set table name
|
||||||
|
Into: Add columns
|
||||||
|
state From
|
||||||
|
From: Set table name
|
||||||
|
|
||||||
|
state Join
|
||||||
|
Join: Set table
|
||||||
|
Join: Set join type (inner left, right, outer)
|
||||||
|
state Where
|
||||||
|
Where: Add where clause
|
||||||
|
state Set
|
||||||
|
Set: Set column value pairs
|
||||||
|
state Values
|
||||||
|
Values: Set values
|
||||||
|
|
||||||
|
state On:
|
||||||
|
On: Set Expression
|
||||||
|
|
||||||
|
state GroupBy
|
||||||
|
GroupBy: Add column names
|
||||||
|
state OrderBy
|
||||||
|
OrderBy: Add expression
|
||||||
|
state Limit
|
||||||
|
Limit: Add number of max result elements
|
||||||
|
|
||||||
|
[*] --> Query
|
||||||
|
Query --> Create
|
||||||
|
Query --> Drop
|
||||||
|
Query --> Select
|
||||||
|
Query --> Insert
|
||||||
|
Query --> Update
|
||||||
|
Query --> Delete
|
||||||
|
|
||||||
|
Create --> Table
|
||||||
|
Drop --> Table
|
||||||
|
Select --> From
|
||||||
|
Insert --> Into
|
||||||
|
Delete --> From
|
||||||
|
|
||||||
|
Into --> Values
|
||||||
|
Update --> Set
|
||||||
|
Set -> Where
|
||||||
|
From --> Where
|
||||||
|
From --> OrderBy
|
||||||
|
From --> GroupBy
|
||||||
|
From --> Join
|
||||||
|
Join --> On
|
||||||
|
On --> Where
|
||||||
|
|
||||||
|
Where --> GroupBy
|
||||||
|
Where --> OrderBy
|
||||||
|
Where --> Limit
|
||||||
|
|
||||||
|
GroupBy --> OrderBy
|
||||||
|
OrderBy --> Limit
|
||||||
|
|
||||||
|
Table --> [*]
|
||||||
|
Values ---> [*]
|
||||||
|
Where --> [*]
|
||||||
|
Set --> [*]
|
||||||
|
From --> [*]
|
||||||
|
Limit --> [*]
|
||||||
|
OrderBy --> [*]
|
||||||
|
GroupBy --> [*]
|
||||||
|
|
||||||
|
@enduml
|
||||||
|
|
@ -17,7 +17,7 @@ class dialect;
|
||||||
namespace detail {
|
namespace detail {
|
||||||
struct any_type_to_string_visitor
|
struct any_type_to_string_visitor
|
||||||
{
|
{
|
||||||
any_type_to_string_visitor(const dialect &d) : d(d) {}
|
explicit any_type_to_string_visitor(const dialect &d) : d(d) {}
|
||||||
|
|
||||||
void operator()(char &x) { to_string(x); }
|
void operator()(char &x) { to_string(x); }
|
||||||
void operator()(short &x) { to_string(x); }
|
void operator()(short &x) { to_string(x); }
|
||||||
|
|
@ -49,6 +49,10 @@ struct any_type_to_string_visitor
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class join_type_t {
|
||||||
|
INNER, OUTER, LEFT, RIGHT
|
||||||
|
};
|
||||||
|
|
||||||
class query_builder
|
class query_builder
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
@ -70,6 +74,7 @@ private:
|
||||||
QUERY_ORDER_BY,
|
QUERY_ORDER_BY,
|
||||||
QUERY_ORDER_DIRECTION,
|
QUERY_ORDER_DIRECTION,
|
||||||
QUERY_GROUP_BY,
|
QUERY_GROUP_BY,
|
||||||
|
QUERY_OFFSET,
|
||||||
QUERY_LIMIT,
|
QUERY_LIMIT,
|
||||||
QUERY_FINISH
|
QUERY_FINISH
|
||||||
};
|
};
|
||||||
|
|
@ -87,20 +92,28 @@ private:
|
||||||
public:
|
public:
|
||||||
explicit query_builder(const dialect &d);
|
explicit query_builder(const dialect &d);
|
||||||
|
|
||||||
query_builder create();
|
query_builder& create();
|
||||||
query_builder drop();
|
query_builder& drop();
|
||||||
query_builder select(std::initializer_list<std::string> column_names);
|
query_builder& select(std::initializer_list<std::string> column_names);
|
||||||
query_builder insert();
|
query_builder& insert();
|
||||||
query_builder update(const std::string &table);
|
query_builder& update(const std::string &table);
|
||||||
query_builder remove();
|
query_builder& remove();
|
||||||
|
|
||||||
query_builder& table(const std::string &table, std::initializer_list<column> columns);
|
query_builder& table(const std::string &table, std::initializer_list<column> columns);
|
||||||
query_builder& table(const std::string &table);
|
query_builder& table(const std::string &table);
|
||||||
query_builder& into(const std::string &table, std::initializer_list<std::string> column_names);
|
query_builder& into(const std::string &table, std::initializer_list<std::string> column_names);
|
||||||
query_builder& values(std::initializer_list<any_type> values);
|
query_builder& values(std::initializer_list<any_type> values);
|
||||||
query_builder& from(const std::string &table, const std::string &as = "");
|
query_builder& from(const std::string &table, const std::string &as = "");
|
||||||
|
query_builder& join(const std::string &table, join_type_t);
|
||||||
|
query_builder& on(const std::string &column, const std::string &join_column);
|
||||||
query_builder& set(std::initializer_list<key_value_pair> key_values);
|
query_builder& set(std::initializer_list<key_value_pair> key_values);
|
||||||
query_builder& where(const basic_condition &cond);
|
query_builder& where(const basic_condition &cond);
|
||||||
|
query_builder& order_by(const std::string &column);
|
||||||
|
query_builder& group_by(const std::string &column);
|
||||||
|
query_builder& asc();
|
||||||
|
query_builder& desc();
|
||||||
|
query_builder& offset(size_t count);
|
||||||
|
query_builder& limit(size_t count);
|
||||||
|
|
||||||
std::string compile();
|
std::string compile();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef QUERY_RESULT_HPP
|
||||||
|
#define QUERY_RESULT_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
struct result
|
||||||
|
{
|
||||||
|
std::string sql;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //QUERY_RESULT_HPP
|
||||||
|
|
@ -3,7 +3,9 @@ set(SQL_SOURCES
|
||||||
sql/query_builder.cpp
|
sql/query_builder.cpp
|
||||||
sql/column.cpp
|
sql/column.cpp
|
||||||
sql/key_value_pair.cpp
|
sql/key_value_pair.cpp
|
||||||
sql/basic_condition.cpp)
|
sql/basic_condition.cpp
|
||||||
|
sql/connection.cpp
|
||||||
|
sql/connection_intermediates.cpp)
|
||||||
|
|
||||||
set(SQL_HEADER
|
set(SQL_HEADER
|
||||||
../include/matador/sql/dialect.hpp
|
../include/matador/sql/dialect.hpp
|
||||||
|
|
@ -12,7 +14,10 @@ set(SQL_HEADER
|
||||||
../include/matador/sql/types.hpp
|
../include/matador/sql/types.hpp
|
||||||
../include/matador/sql/key_value_pair.hpp
|
../include/matador/sql/key_value_pair.hpp
|
||||||
../include/matador/sql/basic_condition.hpp
|
../include/matador/sql/basic_condition.hpp
|
||||||
../include/matador/sql/condition.hpp)
|
../include/matador/sql/condition.hpp
|
||||||
|
../include/matador/sql/connection.hpp
|
||||||
|
../include/matador/sql/connection_intermediates.hpp
|
||||||
|
../include/matador/sql/result.hpp)
|
||||||
|
|
||||||
set(UTILS_HEADER
|
set(UTILS_HEADER
|
||||||
../include/matador/utils/field_attributes.hpp
|
../include/matador/utils/field_attributes.hpp
|
||||||
|
|
@ -21,7 +26,8 @@ set(UTILS_HEADER
|
||||||
|
|
||||||
set(UTILS_SOURCES
|
set(UTILS_SOURCES
|
||||||
utils/field_attributes.cpp
|
utils/field_attributes.cpp
|
||||||
utils/string.cpp)
|
utils/string.cpp
|
||||||
|
sql/condition.cpp)
|
||||||
|
|
||||||
add_library(matador STATIC ${SQL_SOURCES} ${SQL_HEADER} ${UTILS_SOURCES} ${UTILS_HEADER})
|
add_library(matador STATIC ${SQL_SOURCES} ${SQL_HEADER} ${UTILS_SOURCES} ${UTILS_HEADER})
|
||||||
set_target_properties(matador PROPERTIES LINKER_LANGUAGE CXX)
|
set_target_properties(matador PROPERTIES LINKER_LANGUAGE CXX)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
#include "matador/sql/condition.hpp"
|
||||||
|
|
||||||
|
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)
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::string condition<column, query>::evaluate(dialect &d) const {
|
||||||
|
std::string result(d.prepare_identifier(field_.name()) + " " + operand + " (");
|
||||||
|
result += (")");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include "matador/sql/connection.hpp"
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
|
||||||
|
connection::connection()
|
||||||
|
: query_(dialect_) {}
|
||||||
|
|
||||||
|
result connection::execute(const std::string &sql) {
|
||||||
|
return {sql};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
#include "matador/sql/connection_intermediates.hpp"
|
||||||
|
#include "matador/sql/connection.hpp"
|
||||||
|
#include "matador/sql/query_builder.hpp"
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
result query_finish::fetch_all()
|
||||||
|
{
|
||||||
|
return db.execute(query.compile());
|
||||||
|
}
|
||||||
|
|
||||||
|
result query_finish::fetch_one()
|
||||||
|
{
|
||||||
|
return db.execute(query.compile());
|
||||||
|
}
|
||||||
|
|
||||||
|
result query_finish::fetch_value()
|
||||||
|
{
|
||||||
|
return db.execute(query.compile());
|
||||||
|
}
|
||||||
|
|
||||||
|
query_intermediate::query_intermediate(connection &db, query_builder &query)
|
||||||
|
: db(db), query(query) {}
|
||||||
|
|
||||||
|
query_order_direction_intermediate query_order_by_intermediate::asc()
|
||||||
|
{
|
||||||
|
return {db, query.asc()};
|
||||||
|
}
|
||||||
|
|
||||||
|
query_order_direction_intermediate query_order_by_intermediate::desc()
|
||||||
|
{
|
||||||
|
return {db, query.desc()};
|
||||||
|
}
|
||||||
|
|
||||||
|
query_group_by_intermediate query_from_intermediate::group_by(const std::string &name)
|
||||||
|
{
|
||||||
|
return {db, query.group_by(name)};
|
||||||
|
}
|
||||||
|
|
||||||
|
query_order_by_intermediate query_from_intermediate::order_by(const std::string &name)
|
||||||
|
{
|
||||||
|
return {db, query.order_by(name)};
|
||||||
|
}
|
||||||
|
|
||||||
|
query_where_intermediate query_from_intermediate::where(const basic_condition &cond)
|
||||||
|
{
|
||||||
|
return query_where_intermediate{db, query.where(cond)};
|
||||||
|
}
|
||||||
|
|
||||||
|
query_from_intermediate query_select_intermediate::from(const std::string &table, const std::string &as)
|
||||||
|
{
|
||||||
|
return {db, query.from(table, as)};
|
||||||
|
}
|
||||||
|
|
||||||
|
query_select_intermediate connection::select(std::initializer_list<std::string> column_names)
|
||||||
|
{
|
||||||
|
return query_select_intermediate{*this, query_.select(column_names)};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -62,11 +62,6 @@ std::string dialect::next_placeholder() const
|
||||||
return "?";
|
return "?";
|
||||||
}
|
}
|
||||||
|
|
||||||
dialect::compile_type_t dialect::compile_type() const
|
|
||||||
{
|
|
||||||
return compile_type_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dialect::add_host_var(const std::string &host_var)
|
void dialect::add_host_var(const std::string &host_var)
|
||||||
{
|
{
|
||||||
host_vars_.emplace_back(host_var);
|
host_vars_.emplace_back(host_var);
|
||||||
|
|
|
||||||
|
|
@ -32,13 +32,14 @@ query_builder::query_state_transition_map query_builder::transitions_{
|
||||||
{state_t::QUERY_DELETE, {state_t::QUERY_FROM}},
|
{state_t::QUERY_DELETE, {state_t::QUERY_FROM}},
|
||||||
{state_t::QUERY_TABLE_CREATE, {state_t::QUERY_FINISH}},
|
{state_t::QUERY_TABLE_CREATE, {state_t::QUERY_FINISH}},
|
||||||
{state_t::QUERY_TABLE_DROP, {state_t::QUERY_FINISH}},
|
{state_t::QUERY_TABLE_DROP, {state_t::QUERY_FINISH}},
|
||||||
{state_t::QUERY_FROM, {state_t::QUERY_WHERE, state_t::QUERY_ORDER_BY, state_t::QUERY_GROUP_BY, 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_SET, {state_t::QUERY_WHERE, state_t::QUERY_FINISH}},
|
||||||
{state_t::QUERY_INTO, {state_t::QUERY_VALUES}},
|
{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_LIMIT, state_t::QUERY_FINISH}},
|
{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_BY, {state_t::QUERY_ORDER_DIRECTION}},
|
||||||
{state_t::QUERY_ORDER_DIRECTION, {state_t::QUERY_LIMIT, state_t::QUERY_FINISH}},
|
{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_FINISH}},
|
{state_t::QUERY_GROUP_BY, {state_t::QUERY_FINISH}},
|
||||||
|
{state_t::QUERY_OFFSET, {state_t::QUERY_LIMIT}},
|
||||||
{state_t::QUERY_LIMIT, {state_t::QUERY_FINISH}},
|
{state_t::QUERY_LIMIT, {state_t::QUERY_FINISH}},
|
||||||
{state_t::QUERY_VALUES, {state_t::QUERY_FINISH}},
|
{state_t::QUERY_VALUES, {state_t::QUERY_FINISH}},
|
||||||
{state_t::QUERY_FINISH, {}},
|
{state_t::QUERY_FINISH, {}},
|
||||||
|
|
@ -60,6 +61,7 @@ query_builder::query_state_to_string_map query_builder::state_strings_ {
|
||||||
{ state_t::QUERY_WHERE, "where" },
|
{ state_t::QUERY_WHERE, "where" },
|
||||||
{ state_t::QUERY_ORDER_BY, "order_by" },
|
{ state_t::QUERY_ORDER_BY, "order_by" },
|
||||||
{ state_t::QUERY_GROUP_BY, "group_by" },
|
{ state_t::QUERY_GROUP_BY, "group_by" },
|
||||||
|
{ state_t::QUERY_OFFSET, "offset" },
|
||||||
{ state_t::QUERY_LIMIT, "limit" },
|
{ state_t::QUERY_LIMIT, "limit" },
|
||||||
{ state_t::QUERY_FINISH, "finish" },
|
{ state_t::QUERY_FINISH, "finish" },
|
||||||
};
|
};
|
||||||
|
|
@ -78,7 +80,7 @@ query_builder::query_builder(const dialect &d)
|
||||||
: dialect_(d)
|
: dialect_(d)
|
||||||
, value_to_string_(d) {}
|
, value_to_string_(d) {}
|
||||||
|
|
||||||
query_builder query_builder::create() {
|
query_builder& query_builder::create() {
|
||||||
initialize(command_t::CREATE, state_t::QUERY_CREATE);
|
initialize(command_t::CREATE, state_t::QUERY_CREATE);
|
||||||
|
|
||||||
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::CREATE));
|
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::CREATE));
|
||||||
|
|
@ -86,7 +88,7 @@ query_builder query_builder::create() {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_builder query_builder::drop() {
|
query_builder& query_builder::drop() {
|
||||||
initialize(command_t::DROP, state_t::QUERY_DROP);
|
initialize(command_t::DROP, state_t::QUERY_DROP);
|
||||||
|
|
||||||
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::DROP));
|
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::DROP));
|
||||||
|
|
@ -94,7 +96,7 @@ query_builder query_builder::drop() {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_builder query_builder::select(std::initializer_list<std::string> column_names) {
|
query_builder& query_builder::select(std::initializer_list<std::string> column_names) {
|
||||||
initialize(command_t::SELECT, state_t::QUERY_SELECT);
|
initialize(command_t::SELECT, state_t::QUERY_SELECT);
|
||||||
|
|
||||||
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::SELECT) + " ");
|
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::SELECT) + " ");
|
||||||
|
|
@ -107,7 +109,7 @@ query_builder query_builder::select(std::initializer_list<std::string> column_na
|
||||||
} else {
|
} else {
|
||||||
auto it = column_names.begin();
|
auto it = column_names.begin();
|
||||||
result.append(dialect_.prepare_identifier(*it++));
|
result.append(dialect_.prepare_identifier(*it++));
|
||||||
for (it; it != column_names.end(); ++it) {
|
for (; it != column_names.end(); ++it) {
|
||||||
result.append(", ");
|
result.append(", ");
|
||||||
result.append(dialect_.prepare_identifier(*it));
|
result.append(dialect_.prepare_identifier(*it));
|
||||||
}
|
}
|
||||||
|
|
@ -117,7 +119,7 @@ query_builder query_builder::select(std::initializer_list<std::string> column_na
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_builder query_builder::insert() {
|
query_builder& query_builder::insert() {
|
||||||
initialize(command_t::INSERT, state_t::QUERY_INSERT);
|
initialize(command_t::INSERT, state_t::QUERY_INSERT);
|
||||||
|
|
||||||
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::INSERT));
|
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::INSERT));
|
||||||
|
|
@ -125,7 +127,7 @@ query_builder query_builder::insert() {
|
||||||
return *this;
|
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);
|
initialize(command_t::UPDATE, state_t::QUERY_UPDATE);
|
||||||
|
|
||||||
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::UPDATE) + " " + dialect_.prepare_identifier(table));
|
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::UPDATE) + " " + dialect_.prepare_identifier(table));
|
||||||
|
|
@ -133,7 +135,7 @@ query_builder query_builder::update(const std::string &table) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_builder query_builder::remove() {
|
query_builder& query_builder::remove() {
|
||||||
initialize(command_t::REMOVE, state_t::QUERY_DELETE);
|
initialize(command_t::REMOVE, state_t::QUERY_DELETE);
|
||||||
|
|
||||||
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::REMOVE));
|
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::REMOVE));
|
||||||
|
|
@ -141,7 +143,7 @@ query_builder query_builder::remove() {
|
||||||
return *this;
|
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) {
|
||||||
transition_to(state_t::QUERY_TABLE_CREATE);
|
transition_to(state_t::QUERY_TABLE_CREATE);
|
||||||
|
|
||||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::TABLE) + " " + dialect_.prepare_identifier(table) + " ");
|
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::TABLE) + " " + dialect_.prepare_identifier(table) + " ");
|
||||||
|
|
@ -155,7 +157,7 @@ query_builder &query_builder::table(const std::string &table, std::initializer_l
|
||||||
} else {
|
} else {
|
||||||
auto it = columns.begin();
|
auto it = columns.begin();
|
||||||
result.append(build_create_column(*it++, dialect_));
|
result.append(build_create_column(*it++, dialect_));
|
||||||
for (it; it != columns.end(); ++it) {
|
for (; it != columns.end(); ++it) {
|
||||||
result.append(", ");
|
result.append(", ");
|
||||||
result.append(build_create_column(*it, dialect_));
|
result.append(build_create_column(*it, dialect_));
|
||||||
}
|
}
|
||||||
|
|
@ -166,7 +168,7 @@ query_builder &query_builder::table(const std::string &table, std::initializer_l
|
||||||
return *this;
|
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);
|
transition_to(state_t::QUERY_TABLE_DROP);
|
||||||
|
|
||||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::TABLE) + " " + dialect_.prepare_identifier(table));
|
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::TABLE) + " " + dialect_.prepare_identifier(table));
|
||||||
|
|
@ -174,7 +176,7 @@ query_builder &query_builder::table(const std::string &table) {
|
||||||
return *this;
|
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) {
|
||||||
transition_to(state_t::QUERY_INTO);
|
transition_to(state_t::QUERY_INTO);
|
||||||
|
|
||||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::INTO) + " " + dialect_.prepare_identifier(table) + " ");
|
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::INTO) + " " + dialect_.prepare_identifier(table) + " ");
|
||||||
|
|
@ -187,7 +189,7 @@ query_builder &query_builder::into(const std::string &table, std::initializer_li
|
||||||
} else {
|
} else {
|
||||||
auto it = column_names.begin();
|
auto it = column_names.begin();
|
||||||
result.append(dialect_.prepare_identifier(*it++));
|
result.append(dialect_.prepare_identifier(*it++));
|
||||||
for (it; it != column_names.end(); ++it) {
|
for (; it != column_names.end(); ++it) {
|
||||||
result.append(", ");
|
result.append(", ");
|
||||||
result.append(dialect_.prepare_identifier(*it));
|
result.append(dialect_.prepare_identifier(*it));
|
||||||
}
|
}
|
||||||
|
|
@ -198,7 +200,7 @@ query_builder &query_builder::into(const std::string &table, std::initializer_li
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_builder &query_builder::values(std::initializer_list<any_type> values) {
|
query_builder& query_builder::values(std::initializer_list<any_type> values) {
|
||||||
transition_to(state_t::QUERY_VALUES);
|
transition_to(state_t::QUERY_VALUES);
|
||||||
|
|
||||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::VALUES) + " ");
|
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::VALUES) + " ");
|
||||||
|
|
@ -227,7 +229,7 @@ query_builder &query_builder::values(std::initializer_list<any_type> values) {
|
||||||
return *this;
|
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);
|
transition_to(state_t::QUERY_FROM);
|
||||||
|
|
||||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::FROM) + " " + dialect_.prepare_identifier(table) + (as.empty() ? "" : " " + as));
|
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::FROM) + " " + dialect_.prepare_identifier(table) + (as.empty() ? "" : " " + as));
|
||||||
|
|
@ -235,7 +237,17 @@ query_builder &query_builder::from(const std::string &table, const std::string &
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_builder &query_builder::set(std::initializer_list<key_value_pair> key_values) {
|
query_builder &query_builder::join(const std::string &table, join_type_t)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
query_builder &query_builder::on(const std::string &column, const std::string &join_column)
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
query_builder& query_builder::set(std::initializer_list<key_value_pair> key_values) {
|
||||||
transition_to(state_t::QUERY_SET);
|
transition_to(state_t::QUERY_SET);
|
||||||
|
|
||||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::SET) + " ");
|
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::SET) + " ");
|
||||||
|
|
@ -267,7 +279,7 @@ query_builder &query_builder::set(std::initializer_list<key_value_pair> key_valu
|
||||||
return *this;
|
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);
|
transition_to(state_t::QUERY_WHERE);
|
||||||
|
|
||||||
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::WHERE) + " ");
|
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::WHERE) + " ");
|
||||||
|
|
@ -276,6 +288,53 @@ query_builder &query_builder::where(const basic_condition &cond) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
query_builder& query_builder::asc() {
|
||||||
|
transition_to(state_t::QUERY_ORDER_DIRECTION);
|
||||||
|
|
||||||
|
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::ASC));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
query_builder& query_builder::desc() {
|
||||||
|
transition_to(state_t::QUERY_ORDER_DIRECTION);
|
||||||
|
|
||||||
|
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::DESC));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
std::string query_builder::compile() {
|
std::string query_builder::compile() {
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ FetchContent_Declare(
|
||||||
|
|
||||||
FetchContent_MakeAvailable(Catch2)
|
FetchContent_MakeAvailable(Catch2)
|
||||||
|
|
||||||
add_executable(tests builder.cpp)
|
add_executable(tests builder.cpp
|
||||||
|
connection.cpp)
|
||||||
target_link_libraries(tests PRIVATE Catch2::Catch2WithMain matador)
|
target_link_libraries(tests PRIVATE Catch2::Catch2WithMain matador)
|
||||||
target_include_directories(tests PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>/include)
|
target_include_directories(tests PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>/include)
|
||||||
|
|
@ -66,12 +66,53 @@ TEST_CASE("Delete", "[query]") {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Where", "[query]") {
|
TEST_CASE("Where", "[query]") {
|
||||||
|
dialect d;
|
||||||
|
query_builder query(d);
|
||||||
|
auto sql = query.select({"id", "name", "age"})
|
||||||
|
.from("person")
|
||||||
|
.where("id"_col == 8 && "age"_col > 50)
|
||||||
|
.compile();
|
||||||
|
|
||||||
|
REQUIRE(sql == R"(SELECT "id", "name", "age" FROM "person" WHERE ("id" = 8 AND "age" > 50))");
|
||||||
|
|
||||||
|
sql = query.select({"id", "name", "age"})
|
||||||
|
.from("person")
|
||||||
|
.where("id"_col == _ && "age"_col > 50)
|
||||||
|
.compile();
|
||||||
|
|
||||||
|
REQUIRE(sql == R"(SELECT "id", "name", "age" FROM "person" WHERE ("id" = ? AND "age" > 50))");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("OrderBy", "[query]") {
|
||||||
|
dialect d;
|
||||||
|
query_builder query(d);
|
||||||
|
const auto sql = query.select({"id", "name", "age"})
|
||||||
|
.from("person")
|
||||||
|
.order_by("name").asc()
|
||||||
|
.compile();
|
||||||
|
|
||||||
|
REQUIRE(sql == R"(SELECT "id", "name", "age" FROM "person" ORDER BY "name" ASC)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("GroupBy", "[query]") {
|
||||||
|
dialect d;
|
||||||
|
query_builder query(d);
|
||||||
|
const auto sql = query.select({"id", "name", "age"})
|
||||||
|
.from("person")
|
||||||
|
.group_by("age")
|
||||||
|
.compile();
|
||||||
|
|
||||||
|
REQUIRE(sql == R"(SELECT "id", "name", "age" FROM "person" GROUP BY "age")");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Limit", "[query]") {
|
||||||
dialect d;
|
dialect d;
|
||||||
query_builder query(d);
|
query_builder query(d);
|
||||||
const auto sql = query.select({"id", "name", "age"})
|
const auto sql = query.select({"id", "name", "age"})
|
||||||
.from("person")
|
.from("person")
|
||||||
.where("id"_col == 8)
|
.offset(10)
|
||||||
|
.limit(20)
|
||||||
.compile();
|
.compile();
|
||||||
|
|
||||||
REQUIRE(sql == R"(SELECT "id", "name", "age" FROM "person" WHERE "id" = 8)");
|
REQUIRE(sql == R"(SELECT "id", "name", "age" FROM "person" OFFSET 10 LIMIT 20)");
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
|
#include <matador/sql/column.hpp>
|
||||||
|
#include <matador/sql/condition.hpp>
|
||||||
|
#include <matador/sql/connection.hpp>
|
||||||
|
|
||||||
|
using namespace matador::sql;
|
||||||
|
|
||||||
|
TEST_CASE("CSelect", "[connection]") {
|
||||||
|
connection c;
|
||||||
|
|
||||||
|
auto res = c.select({"id", "name", "color"})
|
||||||
|
.from("person")
|
||||||
|
.where("id"_col == 8)
|
||||||
|
.fetch_all();
|
||||||
|
|
||||||
|
REQUIRE(res.sql == R"(SELECT "id", "name", "color" FROM "person" WHERE "id" = 8)");
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue