query compiler progress

This commit is contained in:
2024-02-18 18:12:00 +01:00
parent b966a7a1a7
commit a3f467a5a8
62 changed files with 1934 additions and 641 deletions
+25 -154
View File
@@ -1,174 +1,45 @@
#ifndef QUERY_COLUMN_HPP
#define QUERY_COLUMN_HPP
#include "matador/sql/any_type.hpp"
#include "matador/sql/any_type_to_visitor.hpp"
#include "matador/sql/data_type_traits.hpp"
#include "matador/utils/field_attributes.hpp"
#include <optional>
#include <vector>
#include <string>
namespace matador::sql {
enum class null_option : uint8_t {
NULLABLE, NOT_NULL
enum class sql_function_t {
NONE,
COUNT,
AVG,
SUM,
MIN,
MAX
};
class column {
public:
column(sql_function_t func, std::string name);
column(const char *name, std::string alias = ""); // NOLINT(*-explicit-constructor)
column(std::string name, std::string alias = ""); // NOLINT(*-explicit-constructor)
struct column
{
column(const char *name) : name(name) {} // NOLINT(*-explicit-constructor)
column(std::string name) : name(std::move(name)) {} // NOLINT(*-explicit-constructor)
column(sql_function_t func, std::string name) : name(std::move(name)), function_(func) {} // NOLINT(*-explicit-constructor)
column(std::string table_name, std::string name, std::string as)
: table(std::move(table_name))
, name(std::move(name))
, alias(std::move(as)) {} // NOLINT(*-explicit-constructor)
column(const column&) = default;
column& operator=(const column&) = default;
column(column&&) noexcept = default;
column& operator=(column&&) noexcept = default;
template<typename Type>
explicit column(std::string name, utils::field_attributes attr)
: column(std::move(name), data_type_traits<Type>::builtin_type(attr.size()), attr)
{}
template<typename Type>
column(std::string name, const Type &, utils::field_attributes attr, null_option null_opt)
: column(std::move(name), data_type_traits<Type>::builtin_type(attr.size()), attr, null_opt)
{}
column(std::string name, data_type_t type, utils::field_attributes attr, null_option null_opt, size_t index = 0);
template<typename Type>
column(std::string name, std::string ref_table, std::string ref_column, utils::field_attributes attr, null_option null_opt)
: column(std::move(name), data_type_traits<Type>::builtin_type(attr.size()), ref_table, ref_column, attr, null_opt)
{}
column(std::string name, data_type_t type, size_t index, std::string ref_table, std::string ref_column, utils::field_attributes attr, null_option null_opt);
[[nodiscard]] const std::string& name() const;
[[nodiscard]] size_t index() const;
[[nodiscard]] const utils::field_attributes& attributes() const;
[[nodiscard]] bool is_nullable() const;
[[nodiscard]] data_type_t type() const;
[[nodiscard]] const std::string& alias() const;
[[nodiscard]] const std::string& ref_table() const;
[[nodiscard]] const std::string& ref_column() const;
void type(data_type_t type);
void alias(const std::string &as);
template< typename Type >
[[nodiscard]] bool is_type_of() const {
return std::holds_alternative<Type>(value_);
column& as(std::string a) {
alias = std::move(a);
return *this;
}
[[nodiscard]] std::string str() const;
template<typename Type>
void set(const Type &value, const utils::field_attributes &attr = utils::null_attributes)
{
type_ = data_type_traits<Type>::builtin_type(attr.size());
attributes_ = attr;
value_ = value;
[[nodiscard]] bool is_function() const {
return function_ != sql_function_t::NONE;
}
void set(const std::string &value, const utils::field_attributes &attr)
{
type_ = data_type_traits<std::string>::builtin_type(attr.size());
attributes_ = attr;
value_ = value;
}
void set(const char *value, const utils::field_attributes &attr)
{
type_ = data_type_traits<std::string>::builtin_type(attr.size());
attributes_ = attr;
value_ = value;
}
template<class Type>
Type as() const
{
const Type* ptr= std::get_if<Type>(&value_);
if (ptr) {
return *ptr;
}
any_type_to_visitor<Type> visitor;
std::visit(visitor, const_cast<any_type&>(value_));
return visitor.result;
}
[[nodiscard]] bool is_function() const;
[[nodiscard]] sql_function_t function() const;
private:
template<class Operator>
void process(Operator &op)
{
op.on_attribute(name_.c_str(), value_, type_, attributes_);
}
using data_type_index = std::vector<data_type_t>;
private:
friend class record;
static const data_type_index data_type_index_;
std::string name_;
size_t index_{};
utils::field_attributes attributes_;
null_option null_option_{null_option::NOT_NULL};
data_type_t type_{data_type_t::type_unknown};
any_type value_;
std::string table;
std::string name;
std::string alias;
sql_function_t function_{sql_function_t::NONE};
std::string alias_;
std::string ref_table_;
std::string ref_column_;
};
/**
* User defined literal to have a shortcut creating a column object
* @param name Name of the column
* @param len Length of the column name
* @return A column object with given name
*/
column operator "" _col(const char *name, size_t len);
column make_column(const std::string &name, data_type_t type, utils::field_attributes attr = utils::null_attributes, null_option null_opt = null_option::NOT_NULL);
template < typename Type >
column make_column(const std::string &name, utils::field_attributes attr = utils::null_attributes, null_option null_opt = null_option::NOT_NULL)
{
return make_column(name, data_type_traits<Type>::builtin_type(0), attr, null_opt);
}
template <>
column make_column<std::string>(const std::string &name, utils::field_attributes attr, null_option null_opt);
template < typename Type >
column make_pk_column(const std::string &name, size_t size = 0)
{
return make_column<Type>(name, { size, utils::constraints::PRIMARY_KEY });
}
template <>
column make_pk_column<std::string>(const std::string &name, size_t size);
template < typename Type >
column make_fk_column(const std::string &name, size_t size, const std::string &ref_table, const std::string &ref_column)
{
return {name, data_type_traits<Type>::builtin_type(size), ref_table, ref_column, { size, utils::constraints::FOREIGN_KEY }};
}
template < typename Type >
[[maybe_unused]] column make_fk_column(const std::string &name, const std::string &ref_table, const std::string &ref_column)
{
return {name, data_type_traits<Type>::builtin_type(0), 0, ref_table, ref_column, { 0, utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL};
}
template <>
column make_fk_column<std::string>(const std::string &name, size_t size, const std::string &ref_table, const std::string &ref_column);
}
#endif //QUERY_COLUMN_HPP
+164
View File
@@ -0,0 +1,164 @@
#ifndef QUERY_COLUMN_DEFINITION_HPP
#define QUERY_COLUMN_DEFINITION_HPP
#include "matador/sql/any_type.hpp"
#include "matador/sql/any_type_to_visitor.hpp"
#include "matador/sql/data_type_traits.hpp"
#include "matador/utils/field_attributes.hpp"
#include <optional>
#include <vector>
namespace matador::sql {
enum class null_option : uint8_t {
NULLABLE, NOT_NULL
};
class column_definition {
public:
explicit column_definition(const char *name); // NOLINT(*-explicit-constructor)
explicit column_definition(std::string name); // NOLINT(*-explicit-constructor)
column_definition(const column_definition&) = default;
column_definition& operator=(const column_definition&) = default;
column_definition(column_definition&&) noexcept = default;
column_definition& operator=(column_definition&&) noexcept = default;
template<typename Type>
explicit column_definition(std::string name, utils::field_attributes attr)
: column_definition(std::move(name), data_type_traits<Type>::builtin_type(attr.size()), attr)
{}
template<typename Type>
column_definition(std::string name, const Type &, utils::field_attributes attr, null_option null_opt)
: column_definition(std::move(name), data_type_traits<Type>::builtin_type(attr.size()), attr, null_opt)
{}
column_definition(std::string name, data_type_t type, utils::field_attributes attr, null_option null_opt, size_t index = 0);
template<typename Type>
column_definition(std::string name, std::string ref_table, std::string ref_column, utils::field_attributes attr, null_option null_opt)
: column_definition(std::move(name), data_type_traits<Type>::builtin_type(attr.size()), ref_table, ref_column, attr, null_opt)
{}
column_definition(std::string name, data_type_t type, size_t index, std::string ref_table, std::string ref_column, utils::field_attributes attr, null_option null_opt);
[[nodiscard]] const std::string& name() const;
[[nodiscard]] size_t index() const;
[[nodiscard]] const utils::field_attributes& attributes() const;
[[nodiscard]] bool is_nullable() const;
[[nodiscard]] data_type_t type() const;
[[nodiscard]] const std::string& ref_table() const;
[[nodiscard]] const std::string& ref_column() const;
void type(data_type_t type);
template< typename Type >
[[nodiscard]] bool is_type_of() const {
return std::holds_alternative<Type>(value_);
}
[[nodiscard]] std::string str() const;
template<typename Type>
void set(const Type &value, const utils::field_attributes &attr = utils::null_attributes)
{
type_ = data_type_traits<Type>::builtin_type(attr.size());
attributes_ = attr;
value_ = value;
}
void set(const std::string &value, const utils::field_attributes &attr)
{
type_ = data_type_traits<std::string>::builtin_type(attr.size());
attributes_ = attr;
value_ = value;
}
void set(const char *value, const utils::field_attributes &attr)
{
type_ = data_type_traits<std::string>::builtin_type(attr.size());
attributes_ = attr;
value_ = value;
}
template<class Type>
Type as() const
{
const Type* ptr= std::get_if<Type>(&value_);
if (ptr) {
return *ptr;
}
any_type_to_visitor<Type> visitor;
std::visit(visitor, const_cast<any_type&>(value_));
return visitor.result;
}
private:
template<class Operator>
void process(Operator &op)
{
op.on_attribute(name_.c_str(), value_, type_, attributes_);
}
using data_type_index = std::vector<data_type_t>;
private:
friend class record;
static const data_type_index data_type_index_;
std::string name_;
size_t index_{};
utils::field_attributes attributes_;
null_option null_option_{null_option::NOT_NULL};
data_type_t type_{data_type_t::type_unknown};
any_type value_;
std::string ref_table_;
std::string ref_column_;
};
/**
* User defined literal to have a shortcut creating a column object
* @param name Name of the column
* @param len Length of the column name
* @return A column object with given name
*/
column_definition make_column(const std::string &name, data_type_t type, utils::field_attributes attr = utils::null_attributes, null_option null_opt = null_option::NOT_NULL);
template < typename Type >
column_definition make_column(const std::string &name, utils::field_attributes attr = utils::null_attributes, null_option null_opt = null_option::NOT_NULL)
{
return make_column(name, data_type_traits<Type>::builtin_type(0), attr, null_opt);
}
template <>
column_definition make_column<std::string>(const std::string &name, utils::field_attributes attr, null_option null_opt);
template < typename Type >
column_definition make_pk_column(const std::string &name, size_t size = 0)
{
return make_column<Type>(name, { size, utils::constraints::PRIMARY_KEY });
}
template <>
column_definition make_pk_column<std::string>(const std::string &name, size_t size);
template < typename Type >
column_definition make_fk_column(const std::string &name, size_t size, const std::string &ref_table, const std::string &ref_column)
{
return {name, data_type_traits<Type>::builtin_type(size), ref_table, ref_column, { size, utils::constraints::FOREIGN_KEY }};
}
template < typename Type >
[[maybe_unused]] column_definition make_fk_column(const std::string &name, const std::string &ref_table, const std::string &ref_column)
{
return {name, data_type_traits<Type>::builtin_type(0), 0, ref_table, ref_column, { 0, utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL};
}
template <>
column_definition make_fk_column<std::string>(const std::string &name, size_t size, const std::string &ref_table, const std::string &ref_column);
}
#endif //QUERY_COLUMN_DEFINITION_HPP
+7 -7
View File
@@ -1,7 +1,7 @@
#ifndef QUERY_COLUMN_GENERATOR_HPP
#define QUERY_COLUMN_GENERATOR_HPP
#include "matador/sql/column.hpp"
#include "matador/sql/column_definition.hpp"
#include "matador/sql/data_type_traits.hpp"
#include "matador/utils/access.hpp"
@@ -21,10 +21,10 @@ public:
fk_column_generator() = default;
template<class Type>
column generate(const char *id, Type &x, const std::string &ref_table, const std::string &ref_column)
column_definition generate(const char *id, Type &x, const std::string &ref_table, const std::string &ref_column)
{
utils::access::process(*this, x);
return column{id, type_, 0, ref_table, ref_column, { utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL};
return column_definition{id, type_, 0, ref_table, ref_column, {utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL};
}
template<typename ValueType>
@@ -53,15 +53,15 @@ private:
class column_generator
{
private:
column_generator(std::vector<column> &columns, const schema &repo);
column_generator(std::vector<column_definition> &columns, const schema &repo);
public:
~column_generator() = default;
template < class Type >
static std::vector<column> generate(const schema &repo)
static std::vector<column_definition> generate(const schema &repo)
{
std::vector<column> columns;
std::vector<column_definition> columns;
column_generator gen(columns, repo);
Type obj;
matador::utils::access::process(gen, obj);
@@ -101,7 +101,7 @@ private:
private:
size_t index_ = 0;
std::vector<column> &columns_;
std::vector<column_definition> &columns_;
const schema &repo_;
fk_column_generator fk_column_generator_;
+5 -11
View File
@@ -5,6 +5,7 @@
#include "matador/utils/field_attributes.hpp"
#include "matador/utils/foreign_attributes.hpp"
#include "matador/sql/column.hpp"
#include "matador/sql/schema.hpp"
#include <string>
@@ -13,29 +14,22 @@
namespace matador::sql {
struct column_info
{
std::string table;
std::string name;
std::string alias;
};
class column_name_generator
{
private:
column_name_generator(std::vector<column_info> &column_infos, const sql::schema &ts, const std::string &table_name);
column_name_generator(std::vector<column> &column_infos, const sql::schema &ts, const std::string &table_name);
public:
~column_name_generator() = default;
template < class Type >
static std::vector<column_info> generate(const sql::schema &ts)
static std::vector<column> generate(const sql::schema &ts)
{
const auto info = ts.info<Type>();
if (!info) {
return {};
}
std::vector<column_info> columns;
std::vector<column> columns;
column_name_generator gen(columns, ts, info.value().name);
Type obj;
matador::utils::access::process(gen, obj);
@@ -93,7 +87,7 @@ private:
private:
std::stack<std::string> table_name_stack_;
std::vector<column_info> &column_infos_;
std::vector<column> &column_infos_;
const sql::schema &table_schema_;
int column_index{0};
};
+36 -11
View File
@@ -7,6 +7,7 @@
#include "matador/sql/query_context.hpp"
#include <memory>
#include <utility>
namespace matador::sql {
@@ -55,8 +56,8 @@ public:
std::string evaluate(dialect &d, query_context &query) const override
{
query.bind_vars.emplace_back(field_.name());
return d.prepare_identifier(field_.name()) + " " + operand + " " + std::to_string(value);
query.bind_vars.emplace_back(field_.name);
return d.prepare_identifier(field_.name) + " " + operand + " " + std::to_string(value);
}
};
@@ -75,8 +76,8 @@ public:
std::string evaluate(dialect &d, query_context &query) const override
{
query.bind_vars.emplace_back(field_.name());
return d.prepare_identifier(field_.name()) + " " + operand + " '" + value + "'";
query.bind_vars.emplace_back(field_.name);
return d.prepare_identifier(field_.name) + " " + operand + " '" + value + "'";
}
};
@@ -96,7 +97,7 @@ public:
std::string evaluate(dialect &d, query_context &query) const override
{
return std::to_string(value) + " " + operand + " " + d.prepare_identifier(field_.name());
return std::to_string(value) + " " + operand + " " + d.prepare_identifier(field_.name);
}
};
@@ -115,7 +116,7 @@ public:
std::string evaluate(dialect &d, query_context &query) const override
{
return "'" + std::to_string(value) + "' " + operand + " " + d.prepare_identifier(field_.name());
return "'" + std::to_string(value) + "' " + operand + " " + d.prepare_identifier(field_.name);
}
};
@@ -158,10 +159,10 @@ public:
std::string evaluate(dialect &d, query_context &query) const override {
auto count = size();
for (size_t i = 0; i < count; ++i) {
query.bind_vars.emplace_back(field_.name());
query.bind_vars.emplace_back(field_.name);
}
std::string result = d.prepare_identifier(field_.name()) + " IN (";
std::string result = d.prepare_identifier(field_.name) + " IN (";
if (args_.size() < 2) {
for (const auto &val : args_) {
result.append(std::to_string(val));
@@ -261,9 +262,9 @@ public:
* @return A condition BETWEEN part of the query
*/
std::string evaluate(dialect &d, query_context &query) const override {
query.bind_vars.emplace_back(field_.name());
query.bind_vars.emplace_back(field_.name());
return d.prepare_identifier(field_.name()) + " BETWEEN " + std::to_string(range_.first) + " AND " + std::to_string(range_.second);
query.bind_vars.emplace_back(field_.name);
query.bind_vars.emplace_back(field_.name);
return d.prepare_identifier(field_.name) + " BETWEEN " + std::to_string(range_.first) + " AND " + std::to_string(range_.second);
}
private:
@@ -355,6 +356,28 @@ private:
std::string operand;
};
template<>
class condition<column, column> : public basic_column_condition
{
public:
condition(const column &a, basic_condition::operand_t op, column b)
: basic_column_condition(a, op)
, other_column_(std::move(b)) {}
/**
* @brief Evaluates the condition
*
* @param d The d used to evaluate
* @return The evaluated string based on the compile type
*/
std::string evaluate(dialect &d, query_context &query) const override
{
return d.prepare_identifier(field_.name) + " " + operand + " " + d.prepare_identifier(other_column_.name);
}
private:
column other_column_;
};
/**
* @file condition.hpp
* @brief Contains functions to create query conditions
@@ -441,6 +464,8 @@ condition<column, T> operator==(const column &col, T val)
return condition<column, T>(col, basic_condition::operand_t::EQUAL, val);
}
condition<column, column> operator==(const column &a, const column &b);
/**
* @brief Condition equality method for a column and a query
*
+8 -20
View File
@@ -4,11 +4,12 @@
#include "matador/sql/connection_info.hpp"
#include "matador/sql/connection_impl.hpp"
#include "matador/sql/dialect.hpp"
#include "matador/sql/query_intermediates.hpp"
#include "matador/sql/query.hpp"
#include "matador/sql/query_context.hpp"
#include "matador/sql/query_result.hpp"
#include "matador/sql/record.hpp"
#include "matador/sql/statement.hpp"
#include "matador/sql/schema.hpp"
#include "matador/utils/logger.hpp"
@@ -19,8 +20,8 @@ namespace matador::sql {
class connection
{
public:
explicit connection(connection_info info, const std::shared_ptr<schema> &repo = std::make_shared<schema>());
explicit connection(const std::string& dns, const std::shared_ptr<schema> &repo = std::make_shared<schema>());
explicit connection(connection_info info, const std::shared_ptr<schema> &repo = std::make_shared<sql::schema>());
explicit connection(const std::string& dns, const std::shared_ptr<schema> &repo = std::make_shared<sql::schema>());
connection(const connection &x);
connection& operator=(const connection &x);
connection(connection &&x) noexcept = default;
@@ -31,19 +32,12 @@ public:
[[nodiscard]] bool is_open() const;
[[nodiscard]] const connection_info& info() const;
query_create_intermediate create();
query_drop_intermediate drop();
template < class Type >
query_select_intermediate select();
query_select_intermediate select(std::initializer_list<column> columns);
query_insert_intermediate insert();
query_update_intermediate update(const std::string &table);
query_delete_intermediate remove();
[[nodiscard]] record describe(const std::string &table_name) const;
[[nodiscard]] bool exists(const std::string &schema_name, const std::string &table_name) const;
[[nodiscard]] bool exists(const std::string &table_name) const;
sql::query query() const;
query_result<record> fetch(const query_context &q) const;
[[nodiscard]] std::unique_ptr<query_result_impl> fetch(const std::string &sql) const;
[[nodiscard]] size_t execute(const std::string &sql) const;
@@ -51,21 +45,15 @@ public:
statement prepare(query_context &&query) const;
const class dialect& dialect() const;
std::shared_ptr<schema> tables() const;
std::shared_ptr<sql::schema> schema() const;
private:
connection_info connection_info_;
std::unique_ptr<connection_impl> connection_;
utils::logger logger_;
const class dialect &dialect_;
std::shared_ptr<schema> schema_;
std::shared_ptr<sql::schema> schema_;
};
template<class Type>
query_select_intermediate connection::select()
{
return query_select_intermediate{*this, column_generator::generate<Type>(*schema_)};
}
}
#endif //QUERY_CONNECTION_HPP
-10
View File
@@ -41,16 +41,6 @@ enum class data_type_t : uint8_t {
type_unknown /*!< Data type unknown */
};
enum class sql_function_t {
NONE,
COUNT,
AVG,
SUM,
MIN,
MAX
};
/**
* @tparam T The type of the traits
* @brief Type traits for database types
+1 -2
View File
@@ -1,6 +1,7 @@
#ifndef QUERY_DIALECT_HPP
#define QUERY_DIALECT_HPP
#include "matador/sql/column.hpp"
#include "matador/sql/data_type_traits.hpp"
#include <cstdint>
@@ -11,8 +12,6 @@
namespace matador::sql {
class column;
class dialect final
{
public:
+48
View File
@@ -0,0 +1,48 @@
#ifndef QUERY_QUERY_HPP
#define QUERY_QUERY_HPP
#include "matador/sql/query_intermediates.hpp"
namespace matador::sql {
class connection;
class query
{
public:
explicit query(connection &c);
query(const query &) = delete;
query& operator=(const query &) = delete;
query_create_intermediate create();
query_drop_intermediate drop();
template < class Type >
query_select_intermediate select();
template < class Type >
query_select_intermediate select(std::initializer_list<column> columns);
query_select_intermediate select(std::initializer_list<column> columns);
query_insert_intermediate insert();
query_update_intermediate update(const std::string &table);
query_delete_intermediate remove();
private:
[[nodiscard]] const sql::schema& schema() const;
private:
connection &connection_;
};
template<class Type>
query_select_intermediate query::select()
{
return query_select_intermediate{connection_, column_name_generator::generate<Type>(this->schema())};
}
template<class Type>
query_select_intermediate query::select(std::initializer_list<column> columns)
{
return query_select_intermediate{connection_, column_name_generator::generate<Type>(this->schema())};
}
}
#endif //QUERY_QUERY_HPP
+5 -4
View File
@@ -2,6 +2,7 @@
#define QUERY_QUERY_BUILDER_HPP
#include "matador/sql/basic_condition.hpp"
#include "matador/sql/column_definition.hpp"
#include "matador/sql/column.hpp"
#include "matador/sql/dialect.hpp"
#include "matador/sql/key_value_pair.hpp"
@@ -123,11 +124,11 @@ public:
query_builder& update(const std::string &table);
query_builder& remove();
query_builder& table(const std::string &table, std::initializer_list<column> columns);
query_builder& table(const std::string &table, const std::vector<column> &columns);
query_builder& table(const std::string &table, std::initializer_list<column_definition> columns);
query_builder& table(const std::string &table, const std::vector<column_definition> &columns);
query_builder& table(const std::string &table);
query_builder& into(const std::string &table, std::initializer_list<column_info> column_names);
query_builder& into(const std::string &table, const std::vector<column_info> &column_names);
query_builder& into(const std::string &table, std::initializer_list<column> column_names);
query_builder& into(const std::string &table, const std::vector<column> &column_names);
query_builder& values(std::initializer_list<any_type> values);
query_builder& values(const std::vector<any_type> &values);
query_builder& from(const std::string &table, const std::string &as = "");
+51
View File
@@ -0,0 +1,51 @@
#ifndef QUERY_QUERY_COMPILER_HPP
#define QUERY_QUERY_COMPILER_HPP
#include "matador/sql/query_part_visitor.hpp"
#include "matador/sql/query_parts.hpp"
#include "matador/sql/query_context.hpp"
#include <typeindex>
#include <string>
namespace matador::sql {
class dialect;
struct query_data;
class query_compiler : public query_part_visitor
{
public:
explicit query_compiler(const sql::dialect& d);
query_context compile(const query_data *data);
private:
void visit(query_select_part &select_part) override;
void visit(query_from_part &from_part) override;
void visit(query_where_part &where_part) override;
void visit(query_group_by_part &group_by_part) override;
void visit(query_order_by_part &order_by_part) override;
void visit(query_order_by_asc_part &order_by_asc_part) override;
void visit(query_order_by_desc_part &order_by_desc_part) override;
void visit(query_insert_part &insert_part) override;
void visit(query_values_part &values_part) override;
void visit(query_update_part &update_part) override;
void visit(query_delete_part &delete_part) override;
void visit(query_create_part &create_part) override;
void visit(query_drop_part &drop_part) override;
private:
const sql::dialect &dialect_;
query_context query_;
};
}
#endif //QUERY_QUERY_COMPILER_HPP
+24
View File
@@ -0,0 +1,24 @@
#ifndef QUERY_QUERY_DATA_HPP
#define QUERY_QUERY_DATA_HPP
#include "matador/sql/query_parts.hpp"
#include "matador/sql/table.hpp"
#include <memory>
#include <vector>
namespace matador::sql {
struct query_data
{
// SqlCommands command;
std::vector<std::unique_ptr<query_part>> parts;
std::vector<column_definition> columns;
std::unordered_map<std::type_index, table> table_map_by_index;
using table_ref = std::reference_wrapper<table>;
std::unordered_map<std::string, table_ref> table_map_by_name;
};
}
#endif //QUERY_QUERY_DATA_HPP
+25 -18
View File
@@ -1,14 +1,14 @@
#ifndef QUERY_QUERY_INTERMEDIATES_HPP
#define QUERY_QUERY_INTERMEDIATES_HPP
#include "matador/sql/column.hpp"
#include "matador/sql/column_definition.hpp"
#include "matador/sql/column_generator.hpp"
#include "matador/sql/column_name_generator.hpp"
#include "matador/sql/key_value_generator.hpp"
#include "matador/sql/key_value_pair.hpp"
#include "matador/sql/placeholder_generator.hpp"
#include "matador/sql/query_builder.hpp"
#include "matador/sql/query_result.hpp"
#include "matador/sql/query_data.hpp"
#include "matador/sql/record.hpp"
#include "matador/sql/statement.hpp"
#include "matador/sql/schema.hpp"
@@ -36,10 +36,10 @@ protected:
class query_intermediate : public basic_query_intermediate
{
public:
query_intermediate(connection &db, query_builder &query);
query_intermediate(connection &db, query_data &data);
protected:
query_builder &builder_;
query_data &data_;
};
class query_execute_finish : public query_intermediate
@@ -146,7 +146,7 @@ class query_join_intermediate : public query_intermediate
public:
using query_intermediate::query_intermediate;
query_on_intermediate on(const std::string &column, const std::string &join_column);
query_on_intermediate on(const basic_condition &cond);
};
class query_from_intermediate : public query_select_finish
@@ -154,7 +154,7 @@ class query_from_intermediate : public query_select_finish
public:
using query_select_finish::query_select_finish;
query_join_intermediate join(const std::string &join_table_name, const std::string &as);
query_join_intermediate join_left(const std::string &join_table_name, const std::string &as = "");
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);
@@ -163,10 +163,10 @@ public:
class query_start_intermediate : public basic_query_intermediate
{
public:
explicit query_start_intermediate(connection &s);
explicit query_start_intermediate(connection &db);
protected:
query_builder builder_;
query_data data_;
};
class query_select_intermediate : public query_start_intermediate
@@ -192,16 +192,19 @@ public:
using query_intermediate::query_intermediate;
query_execute_finish values(std::initializer_list<any_type> values);
query_execute_finish values(const std::vector<any_type>& values);
template<class Type>
query_execute_finish values()
{
Type obj;
return {connection_, builder_.values(as_placeholder(obj))};
return {connection_, data_};
// return {connection_, builder_.values(as_placeholder(obj))};
}
template<class Type>
query_execute_finish values(const Type &obj)
{
return {connection_, builder_.values(value_extractor::extract(obj))};
return {connection_, data_};
// return {connection_, builder_.values(value_extractor::extract(obj))};
}
};
@@ -210,15 +213,16 @@ class query_create_intermediate : public query_start_intermediate
public:
explicit query_create_intermediate(connection &db);
query_execute_finish table(const std::string &table_name, std::initializer_list<column> columns);
query_execute_finish table(const std::string &table_name, const std::vector<column> &columns);
query_execute_finish table(const std::string &table_name, std::initializer_list<column_definition> columns);
query_execute_finish table(const std::string &table_name, const std::vector<column_definition> &columns);
template<class Type>
query_execute_finish table(const std::string &table_name)
{
if (!tables()->exists<Type>()) {
tables()->attach<Type>(table_name);
}
return {connection_, builder_.table(table_name, column_generator::generate<Type>(*tables()))};
return {connection_, data_};
// return {connection_, builder_.table(table_name, column_generator::generate<Type>(*tables()))};
}
};
@@ -235,17 +239,19 @@ class query_insert_intermediate : public query_start_intermediate
public:
explicit query_insert_intermediate(connection &s);
query_into_intermediate into(const std::string &table, std::initializer_list<column_info> column_names);
query_into_intermediate into(const std::string &table, std::initializer_list<column> column_names);
template<class Type>
query_into_intermediate into(const std::string &table)
{
return {connection_, builder_.into(table, column_name_generator::generate<Type>(*tables()))};
return {connection_, data_};
// return {connection_, builder_.into(table, column_name_generator::generate<Type>(*tables()))};
}
template<class Type>
query_execute_finish into(const std::string &table, const Type &obj)
{
return {connection_, builder_.into(table, column_name_generator::generate<Type>(*tables()))
.values(value_extractor::extract(obj))};
return {connection_, data_};
// return {connection_, builder_.into(table, column_name_generator::generate<Type>(*tables()))
// .values(value_extractor::extract(obj))};
}
};
@@ -274,7 +280,8 @@ public:
template<class Type>
query_set_intermediate set(const Type &obj)
{
return {connection_, builder_.set(key_value_generator::generate(obj))};
return {connection_, data_};
// return {connection_, builder_.set(key_value_generator::generate(obj))};
}
};
@@ -0,0 +1,46 @@
#ifndef QUERY_QUERY_PART_VISITOR_HPP
#define QUERY_QUERY_PART_VISITOR_HPP
namespace matador::sql {
class query_select_part;
class query_from_part;
class query_where_part;
class query_group_by_part;
class query_order_by_part;
class query_order_by_asc_part;
class query_order_by_desc_part;
class query_insert_part;
class query_values_part;
class query_update_part;
class query_delete_part;
class query_create_part;
class query_drop_part;
class query_part_visitor
{
public:
virtual ~query_part_visitor() = default;
virtual void visit(query_select_part &select_part) = 0;
virtual void visit(query_from_part &from_part) = 0;
virtual void visit(query_where_part &where_part) = 0;
virtual void visit(query_group_by_part &group_by_part) = 0;
virtual void visit(query_order_by_part &order_by_part) = 0;
virtual void visit(query_order_by_asc_part &order_by_asc_part) = 0;
virtual void visit(query_order_by_desc_part &order_by_desc_part) = 0;
virtual void visit(query_insert_part &insert_part) = 0;
virtual void visit(query_values_part &values_part) = 0;
virtual void visit(query_update_part &update_part) = 0;
virtual void visit(query_delete_part &delete_part) = 0;
virtual void visit(query_create_part &create_part) = 0;
virtual void visit(query_drop_part &drop_part) = 0;
};
}
#endif //QUERY_QUERY_PART_VISITOR_HPP
+181
View File
@@ -0,0 +1,181 @@
#ifndef QUERY_QUERY_PARTS_HPP
#define QUERY_QUERY_PARTS_HPP
#include "matador/sql/query_part_visitor.hpp"
#include "matador/sql/column.hpp"
#include "matador/sql/column_definition.hpp"
#include "matador/sql/dialect.hpp"
#include <memory>
namespace matador::sql {
class basic_condition;
class query_part
{
protected:
explicit query_part(sql::dialect::token_t token);
public:
virtual ~query_part() = default;
virtual void accept(query_part_visitor &visitor) = 0;
protected:
sql::dialect::token_t token_;
};
/**
* Represents the SQL SELECT part
*/
class query_select_part : public query_part
{
public:
explicit query_select_part(std::vector<column> columns);
void accept(query_part_visitor &visitor) override;
[[nodiscard]] const std::vector<column>& columns() const;
private:
std::vector<column> columns_;
};
/**
* Represents the SQL FROM part
*/
class query_from_part : public query_part
{
public:
explicit query_from_part(std::string table_name);
query_from_part(std::string table_name, std::string as);
private:
void accept(query_part_visitor &visitor) override;
private:
std::string table_;
std::string alias_;
};
class query_where_part : public query_part
{
public:
template < class Condition >
explicit query_where_part(const Condition &cond)
: query_part(dialect::token_t::WHERE)
, condition_(new Condition(cond)) {}
private:
void accept(query_part_visitor &visitor) override;
private:
std::unique_ptr<basic_condition> condition_;
};
class query_table_name_part : public query_part
{
protected:
explicit query_table_name_part(sql::dialect::token_t token, std::string table_name);
protected:
std::string table_name_;
};
class query_group_by_part : public query_table_name_part
{
public:
explicit query_group_by_part(const std::string &table_name);
private:
void accept(query_part_visitor &visitor) override;
};
class query_order_by_part : public query_table_name_part
{
public:
explicit query_order_by_part(const std::string &table_name);
private:
void accept(query_part_visitor &visitor) override;
};
class query_order_by_asc_part : public query_part
{
public:
query_order_by_asc_part();
private:
void accept(query_part_visitor &visitor) override;
};
class query_order_by_desc_part : public query_part
{
public:
query_order_by_desc_part();
private:
void accept(query_part_visitor &visitor) override;
};
class query_insert_part : public query_part
{
public:
query_insert_part();
private:
void accept(query_part_visitor &visitor) override;
};
/**
* Represents the SQL VALUES part
*/
class query_values_part : public query_part
{
public:
query_values_part(std::initializer_list<any_type> values);
private:
void accept(query_part_visitor &visitor) override;
private:
std::vector<any_type> values_;
};
class query_update_part : public query_table_name_part
{
public:
explicit query_update_part(const std::string &table_name);
private:
void accept(query_part_visitor &visitor) override;
};
class query_delete_part : public query_part
{
public:
query_delete_part();
private:
void accept(query_part_visitor &visitor) override;
};
class query_create_part : public query_part
{
public:
query_create_part();
private:
void accept(query_part_visitor &visitor) override;
};
class query_drop_part : public query_part
{
public:
query_drop_part();
private:
void accept(query_part_visitor &visitor) override;
};
}
#endif //QUERY_QUERY_PARTS_HPP
+11 -11
View File
@@ -3,7 +3,7 @@
#include "matador/utils/access.hpp"
#include "matador/sql/column.hpp"
#include "matador/sql/column_definition.hpp"
#include <vector>
#include <unordered_map>
@@ -13,8 +13,8 @@ namespace matador::sql {
class record
{
private:
using column_by_index = std::vector<column>;
using column_index_pair = std::pair<std::reference_wrapper<column>, size_t>;
using column_by_index = std::vector<column_definition>;
using column_index_pair = std::pair<std::reference_wrapper<column_definition>, size_t>;
using column_by_name_map = std::unordered_map<std::string, column_index_pair>;
public:
@@ -22,8 +22,8 @@ public:
using const_iterator = column_by_index::const_iterator;
record() = default;
record(std::initializer_list<column> columns);
explicit record(const std::vector<column> &columns);
record(std::initializer_list<column_definition> columns);
explicit record(const std::vector<column_definition> &columns);
record(const record &x);
record& operator=(const record &x);
record(record&&) noexcept = default;
@@ -43,15 +43,15 @@ public:
append(make_column<Type>(name, size));
}
void append(column col);
void append(column_definition col);
[[nodiscard]] bool has_primary_key() const;
[[nodiscard]] const column& primary_key() const;
[[nodiscard]] const column_definition& primary_key() const;
[[nodiscard]] const std::vector<column>& columns() const;
[[nodiscard]] const std::vector<column_definition>& columns() const;
[[nodiscard]] const column& at(const std::string &name) const;
[[nodiscard]] const column& at(size_t index) const;
[[nodiscard]] const column_definition& at(const std::string &name) const;
[[nodiscard]] const column_definition& at(size_t index) const;
iterator find(const std::string &column_name);
[[nodiscard]] const_iterator find(const std::string &column_name) const;
@@ -72,7 +72,7 @@ public:
private:
void init();
void add_to_map(column &col, size_t index);
void add_to_map(column_definition &col, size_t index);
private:
column_by_index columns_;
+3
View File
@@ -28,6 +28,8 @@ public:
using iterator = repository::iterator;
using const_iterator = repository::const_iterator;
std::string name() const;
template<typename Type>
const table_info& attach(const std::string &table_name)
{
@@ -68,6 +70,7 @@ public:
[[nodiscard]] bool empty() const;
private:
std::string name_;
repository repository_;
};
+1 -1
View File
@@ -74,7 +74,7 @@ entity<Type> session::insert(Type *obj)
if (!info) {
return {};
}
c->insert().into<Type>(info->name).values(*obj).execute();
c->query().insert().into<Type>(info->name).values(*obj).execute();
return entity{obj};
}
+17
View File
@@ -0,0 +1,17 @@
#ifndef QUERY_TABLE_HPP
#define QUERY_TABLE_HPP
#include <typeindex>
#include <string>
namespace matador::sql {
struct table
{
std::type_index index;
std::string name;
};
}
#endif //QUERY_TABLE_HPP