added where condition

This commit is contained in:
2023-11-02 20:15:13 +01:00
parent b9d9609c28
commit 487dfb2eb4
15 changed files with 1276 additions and 34 deletions
+7 -2
View File
@@ -1,13 +1,18 @@
set(SQL_SOURCES
sql/dialect.cpp
sql/query_builder.cpp
sql/column.cpp)
sql/column.cpp
sql/key_value_pair.cpp
sql/basic_condition.cpp)
set(SQL_HEADER
../include/matador/sql/dialect.hpp
../include/matador/sql/query_builder.hpp
../include/matador/sql/column.hpp
../include/matador/sql/types.hpp)
../include/matador/sql/types.hpp
../include/matador/sql/key_value_pair.hpp
../include/matador/sql/basic_condition.hpp
../include/matador/sql/condition.hpp)
set(UTILS_HEADER
../include/matador/utils/field_attributes.hpp
+26
View File
@@ -0,0 +1,26 @@
#include "matador/sql/basic_condition.hpp"
namespace matador::sql {
std::unordered_map<basic_condition::operand_t, std::string> basic_condition::operands{
{operand_t::EQUAL, "="},
{operand_t::NOT_EQUAL, "<>"},
{operand_t::LESS, "<"},
{operand_t::LESS_EQUAL, "<="},
{operand_t::GREATER, ">"},
{operand_t::GREATER_EQUAL, ">="},
{operand_t::OR, "OR"},
{operand_t::AND, "AND"},
{operand_t::NOT, "NOT"},
{operand_t::IN_LIST, "IN"},
{operand_t::LIKE, "LIKE"}
};
basic_column_condition::basic_column_condition(column fld, basic_condition::operand_t op)
: field_(std::move(fld)), operand(basic_condition::operands[op])
{ }
basic_in_condition::basic_in_condition(column fld)
: field_(std::move(fld))
{ }
}
+24
View File
@@ -20,4 +20,28 @@ data_type_t column::type() const {
return type_;
}
column operator "" _col(const char *name, size_t len)
{
return column(std::string(name, len));
}
column make_column( const std::string& name, data_type_t type, utils::field_attributes attr )
{
return {name, type, attr};
}
template<>
column make_column<std::string>( const std::string& name, utils::field_attributes attr ) {
return make_column(name, data_type_traits<std::string>::builtin_type(attr.size()), attr);
}
template<>
column make_fk_column<std::string>( const std::string& name, size_t size ) {
return make_column<std::string>(name, { size, utils::constraints::FOREIGN_KEY });
}
template<>
column make_pk_column<std::string>( const std::string& name, size_t size ) {
return make_column<std::string>(name, { size, utils::constraints::PRIMARY_KEY | utils::constraints::NOT_NULL});
}
}
+32 -1
View File
@@ -52,8 +52,39 @@ void dialect::escape_quotes_in_literals(std::string &str) const
utils::replace_all(str, single_quote, double_quote);
}
dialect::escape_identifier_t dialect::identifier_escape_type() const {
dialect::escape_identifier_t dialect::identifier_escape_type() const
{
return dialect::escape_identifier_t::ESCAPE_BOTH_SAME;
}
std::string dialect::next_placeholder() const
{
return "?";
}
dialect::compile_type_t dialect::compile_type() const
{
return compile_type_;
}
void dialect::add_host_var(const std::string &host_var)
{
host_vars_.emplace_back(host_var);
}
void dialect::add_column(const std::string &column)
{
columns_.emplace_back(column);
}
const std::vector<std::string> &dialect::host_vars() const
{
return host_vars_;
}
const std::vector<std::string> &dialect::columns() const
{
return columns_;
}
}
+21
View File
@@ -0,0 +1,21 @@
#include "matador/sql/key_value_pair.hpp"
namespace matador::sql {
key_value_pair::key_value_pair(const std::string &name, any_type value)
: name_(name)
, value_(std::move(value)) {
}
key_value_pair::key_value_pair(const char *name, any_type value)
: name_(name)
, value_(std::move(value)) {
}
const std::string &key_value_pair::name() const {
return name_;
}
const any_type& key_value_pair::value() const {
return value_;
}
}
+207 -25
View File
@@ -5,17 +5,33 @@
namespace matador::sql {
namespace detail {
void any_type_to_string_visitor::to_string(const char *val)
{
result = "'" + d.prepare_literal(val) + "'";
}
void any_type_to_string_visitor::to_string(std::string &val)
{
result = "'" + d.prepare_literal(val) + "'";
}
}
std::string build_create_column(const column &col, const dialect &d);
// poor mens state machine
// but does the job for query
query_builder::query_state_transition_map query_builder::transitions_{
{state_t::QUERY_INIT, {state_t::QUERY_CREATE, state_t::QUERY_DROP, state_t::QUERY_SELECT, state_t::QUERY_INSERT, state_t::QUERY_UPDATE, state_t::QUERY_DELETE}},
{state_t::QUERY_CREATE, {state_t::QUERY_TABLE}},
{state_t::QUERY_DROP, {state_t::QUERY_TABLE}},
{state_t::QUERY_CREATE, {state_t::QUERY_TABLE_CREATE}},
{state_t::QUERY_DROP, {state_t::QUERY_TABLE_DROP}},
{state_t::QUERY_SELECT, {state_t::QUERY_FROM}},
{state_t::QUERY_INSERT, {state_t::QUERY_INTO}},
{state_t::QUERY_UPDATE, {state_t::QUERY_SET}},
{state_t::QUERY_DELETE, {state_t::QUERY_FROM}},
{state_t::QUERY_TABLE, {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_FROM, {state_t::QUERY_WHERE, state_t::QUERY_ORDER_BY, state_t::QUERY_GROUP_BY, state_t::QUERY_FINISH}},
{state_t::QUERY_SET, {state_t::QUERY_WHERE, state_t::QUERY_FINISH}},
{state_t::QUERY_INTO, {state_t::QUERY_VALUES}},
@@ -36,7 +52,8 @@ query_builder::query_state_to_string_map query_builder::state_strings_ {
{ state_t::QUERY_INSERT, "insert" },
{ state_t::QUERY_UPDATE, "update" },
{ state_t::QUERY_DELETE, "delete" },
{ state_t::QUERY_TABLE, "table" },
{ state_t::QUERY_TABLE_CREATE, "table" },
{ state_t::QUERY_TABLE_DROP, "table" },
{ state_t::QUERY_FROM, "from" },
{ state_t::QUERY_SET, "set" },
{ state_t::QUERY_INTO, "into" },
@@ -58,35 +75,90 @@ query_builder::query_command_to_string_map query_builder::command_strings_ {
};
query_builder::query_builder(const dialect &d)
: dialect_(d) {}
: dialect_(d)
, value_to_string_(d) {}
query_builder &query_builder::create() {
query_builder query_builder::create() {
initialize(command_t::CREATE, state_t::QUERY_CREATE);
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::CREATE) + " ");
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::CREATE));
return *this;
}
query_builder query_builder::drop() {
initialize(command_t::DROP, state_t::QUERY_DROP);
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::DROP));
return *this;
}
query_builder query_builder::select(std::initializer_list<std::string> column_names) {
initialize(command_t::SELECT, state_t::QUERY_SELECT);
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::SELECT) + " ");
std::string result;
if (column_names.size() < 2) {
for (const auto &col : column_names) {
result.append(dialect_.prepare_identifier(col));
}
} else {
auto it = column_names.begin();
result.append(dialect_.prepare_identifier(*it++));
for (it; it != column_names.end(); ++it) {
result.append(", ");
result.append(dialect_.prepare_identifier(*it));
}
}
query_parts_.emplace_back(result);
return *this;
}
query_builder query_builder::insert() {
initialize(command_t::INSERT, state_t::QUERY_INSERT);
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::INSERT));
return *this;
}
query_builder query_builder::update(const std::string &table) {
initialize(command_t::UPDATE, state_t::QUERY_UPDATE);
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::UPDATE) + " " + dialect_.prepare_identifier(table));
return *this;
}
query_builder query_builder::remove() {
initialize(command_t::REMOVE, state_t::QUERY_DELETE);
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::REMOVE));
return *this;
}
query_builder &query_builder::table(const std::string &table, std::initializer_list<column> columns) {
transition_to(state_t::QUERY_TABLE);
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) + " ");
std::string result = "(";
for (const auto &col : columns) {
result.append(dialect_.prepare_identifier(col.name()) + " " + dialect_.data_type_at(col.type()));
if (col.attributes().size() > 0) {
result.append("(" + std::to_string(col.attributes().size()) +")");
}
if (is_constraint_set(col.attributes().options(), utils::constraints::NOT_NULL)) {
result.append(" NOT NULL");
}
if (is_constraint_set(col.attributes().options(), utils::constraints::PRIMARY_KEY)) {
result.append(" PRIMARY KEY");
}
result.append(", ");
if (columns.size() < 2) {
for (const auto &col : columns) {
result.append(build_create_column(col, dialect_));
}
} else {
auto it = columns.begin();
result.append(build_create_column(*it++, dialect_));
for (it; it != columns.end(); ++it) {
result.append(", ");
result.append(build_create_column(*it, dialect_));
}
}
result += ")";
@@ -94,22 +166,117 @@ query_builder &query_builder::table(const std::string &table, std::initializer_l
return *this;
}
query_builder &query_builder::select(std::initializer_list<std::string> column_names) {
initialize(command_t::SELECT, state_t::QUERY_SELECT);
query_builder &query_builder::table(const std::string &table) {
transition_to(state_t::QUERY_TABLE_DROP);
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::SELECT) + " ");
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::TABLE) + " " + dialect_.prepare_identifier(table));
return *this;
}
query_builder &query_builder::into(const std::string &table, std::initializer_list<std::string> column_names) {
transition_to(state_t::QUERY_INTO);
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::INTO) + " " + dialect_.prepare_identifier(table) + " ");
std::string result{"("};
if (column_names.size() < 2) {
for (const auto &col : column_names) {
result.append(dialect_.prepare_identifier(col));
}
} else {
auto it = column_names.begin();
result.append(dialect_.prepare_identifier(*it++));
for (it; it != column_names.end(); ++it) {
result.append(", ");
result.append(dialect_.prepare_identifier(*it));
}
}
result += (")");
query_parts_.emplace_back(result);
return *this;
}
query_builder &query_builder::values(std::initializer_list<any_type> values) {
transition_to(state_t::QUERY_VALUES);
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::VALUES) + " ");
std::string result{"("};
if (values.size() < 2) {
for (auto val : values) {
std::visit(value_to_string_, val);
result.append(value_to_string_.result);
}
} else {
auto it = values.begin();
auto val = *it++;
std::visit(value_to_string_, val);
result.append(value_to_string_.result);
for (; it != values.end(); ++it) {
result.append(", ");
val = *it;
std::visit(value_to_string_, val);
result.append(value_to_string_.result);
}
}
result += (")");
query_parts_.emplace_back(result);
return *this;
}
query_builder &query_builder::from(const std::string &table, const std::string &as) {
transition_to(state_t::QUERY_FROM);
query_parts_.emplace_back(dialect_.token_at(dialect::token_t::TABLE) + " " + (as.empty() ? "" : as + " "));
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::FROM) + " " + dialect_.prepare_identifier(table) + (as.empty() ? "" : " " + as));
return *this;
}
query_builder &query_builder::set(std::initializer_list<key_value_pair> key_values) {
transition_to(state_t::QUERY_SET);
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::SET) + " ");
std::string result;
if (key_values.size() < 2) {
for (const auto &col : key_values) {
result.append(dialect_.prepare_identifier(col.name()) + "=");
auto var = col.value();
std::visit(value_to_string_, var);
result.append(value_to_string_.result);
}
} else {
auto it = key_values.begin();
result.append(dialect_.prepare_identifier(it->name()) + "=");
auto var = (it++)->value();
std::visit(value_to_string_, var);
result.append(value_to_string_.result);
for (; it != key_values.end(); ++it) {
result.append(", ");
result.append(dialect_.prepare_identifier((*it).name()) + "=");
var = it->value();
std::visit(value_to_string_, var);
result.append(value_to_string_.result);
}
}
query_parts_.emplace_back(result);
return *this;
}
query_builder &query_builder::where(const basic_condition &cond) {
transition_to(state_t::QUERY_WHERE);
query_parts_.emplace_back(" " + dialect_.token_at(dialect::token_t::WHERE) + " ");
query_parts_.emplace_back(cond.evaluate(const_cast<dialect &>(dialect_)));
return *this;
}
std::string query_builder::compile() {
std::string result;
for (const auto &part : query_parts_) {
@@ -133,4 +300,19 @@ void query_builder::initialize(query_builder::command_t cmd, query_builder::stat
query_parts_.clear();
}
std::string build_create_column(const column &col, const dialect &d) {
std::string result = d.prepare_identifier(col.name()) + " " + d.data_type_at(col.type());
if (col.attributes().size() > 0) {
result.append("(" + std::to_string(col.attributes().size()) +")");
}
if (is_constraint_set(col.attributes().options(), utils::constraints::NOT_NULL)) {
result.append(" NOT NULL");
}
if (is_constraint_set(col.attributes().options(), utils::constraints::PRIMARY_KEY)) {
result.append(" PRIMARY KEY");
}
return result;
}
}