From 50a0eb580ab3aad732a428e58d68adb83494a3c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sascha=20K=C3=BChl?= Date: Wed, 27 Mar 2024 15:15:45 +0100 Subject: [PATCH] renamed column_generator to column_definition_generator and column_name_generator to column_generator --- include/matador/sql/column.hpp | 27 +-- .../sql/column_definition_generator.hpp | 129 +++++++++++++++ include/matador/sql/column_generator.hpp | 156 ++++++++---------- include/matador/sql/column_name_generator.hpp | 97 ----------- include/matador/sql/query.hpp | 4 +- include/matador/sql/query_intermediates.hpp | 6 +- include/matador/sql/schema.hpp | 4 +- src/CMakeLists.txt | 4 +- src/sql/column.cpp | 34 ++++ src/sql/column_definition_generator.cpp | 31 ++++ src/sql/column_generator.cpp | 28 ++-- src/sql/column_name_generator.cpp | 31 ---- src/sql/query_builder.cpp | 2 +- test/CMakeLists.txt | 2 +- test/ColumnDefinitionGeneratorTest.cpp | 56 +++++++ test/ColumnGeneratorTest.cpp | 100 +++++++---- test/ColumnNameGeneratorTest.cpp | 68 -------- test/models/book.hpp | 2 +- 18 files changed, 429 insertions(+), 352 deletions(-) create mode 100644 include/matador/sql/column_definition_generator.hpp delete mode 100644 include/matador/sql/column_name_generator.hpp create mode 100644 src/sql/column_definition_generator.cpp delete mode 100644 src/sql/column_name_generator.cpp create mode 100644 test/ColumnDefinitionGeneratorTest.cpp delete mode 100644 test/ColumnNameGeneratorTest.cpp diff --git a/include/matador/sql/column.hpp b/include/matador/sql/column.hpp index 73e05f6..06d5e66 100644 --- a/include/matador/sql/column.hpp +++ b/include/matador/sql/column.hpp @@ -16,26 +16,17 @@ enum class sql_function_t { 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)) {} - column(std::string table_name, const char* name, std::string as) - : table(std::move(table_name)) - , name(name) - , alias(std::move(as)) {} + column(const char *name); // NOLINT(*-explicit-constructor) + column(std::string name); // NOLINT(*-explicit-constructor) + column(sql_function_t func, std::string name); // NOLINT(*-explicit-constructor) + column(std::string table_name, std::string name, std::string as); + column(std::string table_name, const char* name, std::string as); - column& as(std::string a) { - alias = std::move(a); - return *this; - } + bool equals(const column &x) const; - [[nodiscard]] bool is_function() const { - return function_ != sql_function_t::NONE; - } + column& as(std::string a); + + [[nodiscard]] bool is_function() const; std::string table; std::string name; diff --git a/include/matador/sql/column_definition_generator.hpp b/include/matador/sql/column_definition_generator.hpp new file mode 100644 index 0000000..9b389d5 --- /dev/null +++ b/include/matador/sql/column_definition_generator.hpp @@ -0,0 +1,129 @@ +#ifndef QUERY_COLUMN_DEFINITION_GENERATOR_HPP +#define QUERY_COLUMN_DEFINITION_GENERATOR_HPP + +#include "matador/sql/column_definition.hpp" +#include "matador/sql/data_type_traits.hpp" + +#include "matador/utils/access.hpp" +#include "matador/utils/field_attributes.hpp" +#include "matador/utils/foreign_attributes.hpp" + +#include +#include + +namespace matador::sql { + +class schema; + +class fk_column_generator +{ +public: + fk_column_generator() = default; + + template + 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_definition{id, type_, 0, ref_table, ref_column, {utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL}; + } + + template + void on_primary_key(const char *, ValueType &/*pk*/, typename std::enable_if::value && !std::is_same::value>::type* = 0) + { + type_ = data_type_traits::builtin_type(0); + } + void on_primary_key(const char * /*id*/, std::string &/*pk*/, size_t size); + void on_revision(const char * /*id*/, unsigned long long &/*rev*/) {} + template < class Type > + void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {} + void on_attribute(const char * /*id*/, char * /*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {} + template + void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {} + template + void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {} + template + void on_has_many(const char *, ContainerType &, const char *, const char *, const utils::foreign_attributes &/*attr*/) {} + template + void on_has_many(const char *, ContainerType &, const utils::foreign_attributes &/*attr*/) {} + +private: + data_type_t type_{}; +}; + +class column_definition_generator +{ +private: + column_definition_generator(std::vector &columns, const schema &repo); + +public: + ~column_definition_generator() = default; + + template < class Type > + static std::vector generate(const schema &repo) + { + std::vector columns; + column_definition_generator gen(columns, repo); + Type obj; + matador::utils::access::process(gen, obj); + return std::move(columns); + } + + template < class V > + void on_primary_key(const char *, V &x, typename std::enable_if::value && !std::is_same::value>::type* = 0); + void on_primary_key(const char *id, std::string &pk, size_t size); + void on_revision(const char *id, unsigned long long &rev); + + template + void on_attribute(const char *id, Type &x, const utils::field_attributes &attr = utils::null_attributes); + + template + void on_attribute(const char *id, std::optional &x, const utils::field_attributes &attr = utils::null_attributes); + + template + void on_belongs_to(const char *id, Pointer &x, const utils::foreign_attributes &/*attr*/) + { + const auto [ref_table, ref_column] = determine_foreign_ref(std::type_index(typeid(typename Pointer::value_type))); + columns_.push_back(fk_column_generator_.generate(id, *x, ref_table, ref_column)); + } + template + void on_has_one(const char *id, Pointer &x, const utils::foreign_attributes &/*attr*/) + { + const auto [ref_table, ref_column] = determine_foreign_ref(std::type_index(typeid(typename Pointer::value_type))); + columns_.push_back(fk_column_generator_.generate(id, *x, ref_table, ref_column)); + } + template + void on_has_many(const char *, ContainerType &, const char *, const char *, const utils::foreign_attributes &/*attr*/) {} + template + void on_has_many(const char *, ContainerType &, const utils::foreign_attributes &/*attr*/) {} + +private: + std::pair determine_foreign_ref(const std::type_index &ti); + +private: + size_t index_ = 0; + std::vector &columns_; + const schema &repo_; + + fk_column_generator fk_column_generator_; +}; + +template +void column_definition_generator::on_primary_key(const char *id, V &x, typename std::enable_if::value && !std::is_same::value>::type*) +{ + on_attribute(id, x, { utils::constraints::PRIMARY_KEY }); +} + +template +void column_definition_generator::on_attribute(const char *id, Type &x, const utils::field_attributes &attr) +{ + columns_.emplace_back(id, x, attr, null_option::NOT_NULL); +} + +template +void column_definition_generator::on_attribute(const char *id, std::optional &x, const utils::field_attributes &attr) +{ + columns_.emplace_back(id, data_type_traits::builtin_type(attr.size()), attr, null_option::NULLABLE); +} + +} +#endif //QUERY_COLUMN_DEFINITION_GENERATOR_HPP diff --git a/include/matador/sql/column_generator.hpp b/include/matador/sql/column_generator.hpp index d18797d..6a629f2 100644 --- a/include/matador/sql/column_generator.hpp +++ b/include/matador/sql/column_generator.hpp @@ -1,129 +1,119 @@ #ifndef QUERY_COLUMN_GENERATOR_HPP #define QUERY_COLUMN_GENERATOR_HPP -#include "matador/sql/column_definition.hpp" -#include "matador/sql/data_type_traits.hpp" - #include "matador/utils/access.hpp" #include "matador/utils/field_attributes.hpp" #include "matador/utils/foreign_attributes.hpp" -#include +#include "matador/sql/column.hpp" +#include "matador/sql/schema.hpp" + +#include #include +#include namespace matador::sql { -class schema; - -class fk_column_generator -{ -public: - fk_column_generator() = default; - - template - 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_definition{id, type_, 0, ref_table, ref_column, {utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL}; - } - - template - void on_primary_key(const char *, ValueType &/*pk*/, typename std::enable_if::value && !std::is_same::value>::type* = 0) - { - type_ = data_type_traits::builtin_type(0); - } - void on_primary_key(const char * /*id*/, std::string &/*pk*/, size_t size); - void on_revision(const char * /*id*/, unsigned long long &/*rev*/) {} - template < class Type > - void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {} - void on_attribute(const char * /*id*/, char * /*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {} - template - void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {} - template - void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {} - template - void on_has_many(const char *, ContainerType &, const char *, const char *, const utils::foreign_attributes &/*attr*/) {} - template - void on_has_many(const char *, ContainerType &, const utils::foreign_attributes &/*attr*/) {} - -private: - data_type_t type_{}; -}; - class column_generator { private: - column_generator(std::vector &columns, const schema &repo); + column_generator(std::vector &column_infos, const sql::schema &ts, const std::string &table_name); public: ~column_generator() = default; template < class Type > - static std::vector generate(const schema &repo) + static std::vector generate(const sql::schema &ts) { - std::vector columns; - column_generator gen(columns, repo); + const auto info = ts.info(); + if (!info) { + return {}; + } + std::vector columns; + column_generator gen(columns, ts, info.value().name); Type obj; matador::utils::access::process(gen, obj); return std::move(columns); } template < class V > - void on_primary_key(const char *, V &x, typename std::enable_if::value && !std::is_same::value>::type* = 0); - void on_primary_key(const char *id, std::string &pk, size_t size); - void on_revision(const char *id, unsigned long long &rev); + void on_primary_key(const char *id, V &, typename std::enable_if::value && !std::is_same::value>::type* = 0) + { + push(id); + } + void on_primary_key(const char *id, std::string &, size_t); + void on_revision(const char *id, unsigned long long &/*rev*/); template - void on_attribute(const char *id, Type &x, const utils::field_attributes &attr = utils::null_attributes); - - template - void on_attribute(const char *id, std::optional &x, const utils::field_attributes &attr = utils::null_attributes); + void on_attribute(const char *id, Type &, const utils::field_attributes &/*attr*/ = utils::null_attributes) + { + push(id); + } template - void on_belongs_to(const char *id, Pointer &x, const utils::foreign_attributes &/*attr*/) + void on_belongs_to(const char *id, Pointer &, const utils::foreign_attributes &attr) { - const auto [ref_table, ref_column] = determine_foreign_ref(std::type_index(typeid(typename Pointer::value_type))); - columns_.push_back(fk_column_generator_.generate(id, *x, ref_table, ref_column)); + if (attr.fetch() == utils::fetch_type::LAZY) { + push(id); + } else { + const auto info = table_schema_.info(); + if (!info) { + return; + } + table_name_stack_.push(info.value().name); + typename Pointer::value_type obj; + matador::utils::access::process(*this, obj); + table_name_stack_.pop(); + } } template - void on_has_one(const char *id, Pointer &x, const utils::foreign_attributes &/*attr*/) + void on_has_one(const char *id, Pointer &, const utils::foreign_attributes &attr) { - const auto [ref_table, ref_column] = determine_foreign_ref(std::type_index(typeid(typename Pointer::value_type))); - columns_.push_back(fk_column_generator_.generate(id, *x, ref_table, ref_column)); + if (attr.fetch() == utils::fetch_type::LAZY) { + push(id); + } else { + const auto info = table_schema_.info(); + if (!info) { + return; + } + table_name_stack_.push(info.value().name); + typename Pointer::value_type obj; + matador::utils::access::process(*this, obj); + table_name_stack_.pop(); + } } template - void on_has_many(const char *, ContainerType &, const char *, const char *, const utils::foreign_attributes &/*attr*/) {} + void on_has_many(const char *, ContainerType &, const char *, const char *, const utils::foreign_attributes &attr) + { + if (attr.fetch() == utils::fetch_type::LAZY) { + return; + } + const auto info = table_schema_.info(); + if (!info) { + return; + } + + table_name_stack_.push(info.value().name); + typename ContainerType::value_type::value_type obj; + matador::utils::access::process(*this, obj); + table_name_stack_.pop(); + } template - void on_has_many(const char *, ContainerType &, const utils::foreign_attributes &/*attr*/) {} + void on_has_many(const char *id, ContainerType &c, const utils::foreign_attributes &attr) + { + on_has_many(id, c, "", "", attr); + } private: - std::pair determine_foreign_ref(const std::type_index &ti); + void push(const std::string &column_name); private: - size_t index_ = 0; - std::vector &columns_; - const schema &repo_; - - fk_column_generator fk_column_generator_; + std::stack table_name_stack_; + std::vector &column_infos_; + const sql::schema &table_schema_; + int column_index{0}; }; -template -void column_generator::on_primary_key(const char *id, V &x, typename std::enable_if::value && !std::is_same::value>::type*) -{ - on_attribute(id, x, { utils::constraints::PRIMARY_KEY }); } -template -void column_generator::on_attribute(const char *id, Type &x, const utils::field_attributes &attr) -{ - columns_.emplace_back(id, x, attr, null_option::NOT_NULL); -} - -template -void column_generator::on_attribute(const char *id, std::optional &x, const utils::field_attributes &attr) -{ - columns_.emplace_back(id, data_type_traits::builtin_type(attr.size()), attr, null_option::NULLABLE); -} - -} #endif //QUERY_COLUMN_GENERATOR_HPP diff --git a/include/matador/sql/column_name_generator.hpp b/include/matador/sql/column_name_generator.hpp deleted file mode 100644 index d0c84b2..0000000 --- a/include/matador/sql/column_name_generator.hpp +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef QUERY_COLUMN_NAME_GENERATOR_HPP -#define QUERY_COLUMN_NAME_GENERATOR_HPP - -#include "matador/utils/access.hpp" -#include "matador/utils/field_attributes.hpp" -#include "matador/utils/foreign_attributes.hpp" - -#include "matador/sql/column.hpp" -#include "matador/sql/schema.hpp" - -#include -#include -#include - -namespace matador::sql { - -class column_name_generator -{ -private: - column_name_generator(std::vector &column_infos, const sql::schema &ts, const std::string &table_name); - -public: - ~column_name_generator() = default; - - template < class Type > - static std::vector generate(const sql::schema &ts) - { - const auto info = ts.info(); - if (!info) { - return {}; - } - std::vector columns; - column_name_generator gen(columns, ts, info.value().name); - Type obj; - matador::utils::access::process(gen, obj); - return std::move(columns); - } - - template < class V > - void on_primary_key(const char *id, V &, typename std::enable_if::value && !std::is_same::value>::type* = 0) - { - push(id); - } - void on_primary_key(const char *id, std::string &, size_t); - void on_revision(const char *id, unsigned long long &/*rev*/); - - template - void on_attribute(const char *id, Type &, const utils::field_attributes &/*attr*/ = utils::null_attributes) - { - push(id); - } - - template - void on_belongs_to(const char *id, Pointer &, const utils::foreign_attributes &/*attr*/) - { - push(id); - } - template - void on_has_one(const char *id, Pointer &, const utils::foreign_attributes &/*attr*/) - { - push(id); - } - template - void on_has_many(const char *, ContainerType &, const char *, const char *, const utils::foreign_attributes &attr) - { - if (attr.fetch() == utils::fetch_type::LAZY) { - return; - } - const auto info = table_schema_.info(); - if (!info) { - return; - } - - table_name_stack_.push(info.value().name); - typename ContainerType::value_type::value_type obj; - matador::utils::access::process(*this, obj); - table_name_stack_.pop(); - } - template - void on_has_many(const char *id, ContainerType &c, const utils::foreign_attributes &attr) - { - on_has_many(id, c, "", "", attr); - } - -private: - void push(const std::string &column_name); - -private: - std::stack table_name_stack_; - std::vector &column_infos_; - const sql::schema &table_schema_; - int column_index{0}; -}; - -} - -#endif //QUERY_COLUMN_NAME_GENERATOR_HPP diff --git a/include/matador/sql/query.hpp b/include/matador/sql/query.hpp index 269c2a0..68cc437 100644 --- a/include/matador/sql/query.hpp +++ b/include/matador/sql/query.hpp @@ -34,13 +34,13 @@ private: template query_select_intermediate query::select() { - return select(column_name_generator::generate(schema_)); + return select(column_generator::generate(schema_)); } template query_select_intermediate query::select(std::initializer_list columns) { - auto cols = column_name_generator::generate(schema_); + auto cols = column_generator::generate(schema_); cols.insert(cols.end(), columns); return select(cols); } diff --git a/include/matador/sql/query_intermediates.hpp b/include/matador/sql/query_intermediates.hpp index fd7b0d0..2dc1c49 100644 --- a/include/matador/sql/query_intermediates.hpp +++ b/include/matador/sql/query_intermediates.hpp @@ -2,8 +2,8 @@ #define QUERY_QUERY_INTERMEDIATES_HPP #include "matador/sql/column_definition.hpp" +#include "matador/sql/column_definition_generator.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" @@ -260,7 +260,7 @@ public: // if (!schema_.exists()) { // schema_.attach(table.name); // } - return this->table(table, column_generator::generate(schema_)); + return this->table(table, column_definition_generator::generate(schema_)); } }; @@ -282,7 +282,7 @@ public: template query_into_intermediate into(const sql::table &table) { - return into(table, column_name_generator::generate(schema_)); + return into(table, column_generator::generate(schema_)); } }; diff --git a/include/matador/sql/schema.hpp b/include/matador/sql/schema.hpp index f3afb44..d6ac930 100644 --- a/include/matador/sql/schema.hpp +++ b/include/matador/sql/schema.hpp @@ -1,7 +1,7 @@ #ifndef QUERY_SCHEMA_HPP #define QUERY_SCHEMA_HPP -#include "matador/sql/column_generator.hpp" +#include "matador/sql/column_definition_generator.hpp" #include "matador/sql/table_definition.hpp" #include @@ -38,7 +38,7 @@ public: template const table_info& attach(const std::string &table_name) { - return attach(std::type_index(typeid(Type)), table_info{table_name, table_definition{column_generator::generate(*this)}}); + return attach(std::type_index(typeid(Type)), table_info{table_name, table_definition{column_definition_generator::generate(*this)}}); } const table_info& attach(std::type_index ti, const table_info& table); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d6e2624..92b9b61 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,8 +12,8 @@ set(SQL_SOURCES sql/session.cpp sql/backend_provider.cpp sql/query_result_impl.cpp + sql/column_definition_generator.cpp sql/column_generator.cpp - sql/column_name_generator.cpp sql/key_value_generator.cpp sql/fk_value_extractor.cpp sql/schema.cpp @@ -57,8 +57,8 @@ set(SQL_HEADER ../include/matador/sql/session.hpp ../include/matador/sql/backend_provider.hpp ../include/matador/sql/query_result_impl.hpp + ../include/matador/sql/column_definition_generator.hpp ../include/matador/sql/column_generator.hpp - ../include/matador/sql/column_name_generator.hpp ../include/matador/sql/value_extractor.hpp ../include/matador/sql/any_type.hpp ../include/matador/sql/key_value_generator.hpp diff --git a/src/sql/column.cpp b/src/sql/column.cpp index 2c98439..9aa6701 100644 --- a/src/sql/column.cpp +++ b/src/sql/column.cpp @@ -7,4 +7,38 @@ column operator ""_col(const char *name, size_t len) return {{name, len}}; } +column::column(const char *name) : name(name) {} + +column::column(std::string name) : name(std::move(name)) {} + +column::column(sql_function_t func, std::string name) : name(std::move(name)), function_(func) {} + +column::column(std::string table_name, std::string name, std::string as) +: table(std::move(table_name)) +, name(std::move(name)) +, alias(std::move(as)) {} + +column::column(std::string table_name, const char *name, std::string as) +: table(std::move(table_name)) +, name(name) +, alias(std::move(as)) {} + +bool column::equals(const column &x) const +{ + return table == x.table && + name == x.name && + alias == x.alias && + function_ == x.function_; +} + +column &column::as(std::string a) +{ + alias = std::move(a); + return *this; +} + +bool column::is_function() const +{ + return function_ != sql_function_t::NONE; +} } \ No newline at end of file diff --git a/src/sql/column_definition_generator.cpp b/src/sql/column_definition_generator.cpp new file mode 100644 index 0000000..1a7068a --- /dev/null +++ b/src/sql/column_definition_generator.cpp @@ -0,0 +1,31 @@ +#include "matador/sql/column_definition_generator.hpp" +#include "matador/sql/schema.hpp" + +namespace matador::sql { + +column_definition_generator::column_definition_generator(std::vector &columns, const schema &repo) +: columns_(columns) +, repo_(repo) +{} + +void column_definition_generator::on_primary_key(const char *id, std::string &pk, size_t size) +{ + on_attribute(id, pk, { size, utils::constraints::PRIMARY_KEY }); +} + +void column_definition_generator::on_revision(const char *id, unsigned long long int &x) +{ + on_attribute(id, x); +} + +std::pair column_definition_generator::determine_foreign_ref(const std::type_index &ti) +{ + return repo_.reference(ti); +} + +void fk_column_generator::on_primary_key(const char *, std::string &, size_t size) +{ + type_ = data_type_traits::builtin_type(size); +} + +} \ No newline at end of file diff --git a/src/sql/column_generator.cpp b/src/sql/column_generator.cpp index ae4472c..176b733 100644 --- a/src/sql/column_generator.cpp +++ b/src/sql/column_generator.cpp @@ -1,31 +1,31 @@ #include "matador/sql/column_generator.hpp" -#include "matador/sql/schema.hpp" namespace matador::sql { -column_generator::column_generator(std::vector &columns, const schema &repo) -: columns_(columns) -, repo_(repo) -{} - -void column_generator::on_primary_key(const char *id, std::string &pk, size_t size) +column_generator::column_generator(std::vector &column_infos, + const sql::schema &ts, + const std::string &table_name) +: column_infos_(column_infos) +, table_schema_(ts) { - on_attribute(id, pk, { size, utils::constraints::PRIMARY_KEY }); + table_name_stack_.push(table_name); } -void column_generator::on_revision(const char *id, unsigned long long int &x) +void column_generator::on_primary_key(const char *id, std::string &, size_t) { - on_attribute(id, x); + push(id); } -std::pair column_generator::determine_foreign_ref(const std::type_index &ti) +void column_generator::on_revision(const char *id, unsigned long long int &) { - return repo_.reference(ti); + push(id); } -void fk_column_generator::on_primary_key(const char *, std::string &, size_t size) +void column_generator::push(const std::string &column_name) { - type_ = data_type_traits::builtin_type(size); + char str[4]; + snprintf(str, 4, "c%02d", ++column_index); + column_infos_.emplace_back(table_name_stack_.top(), column_name, str); } } \ No newline at end of file diff --git a/src/sql/column_name_generator.cpp b/src/sql/column_name_generator.cpp deleted file mode 100644 index d2358a0..0000000 --- a/src/sql/column_name_generator.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "matador/sql/column_name_generator.hpp" - -namespace matador::sql { - -column_name_generator::column_name_generator(std::vector &column_infos, - const sql::schema &ts, - const std::string &table_name) -: column_infos_(column_infos) -, table_schema_(ts) -{ - table_name_stack_.push(table_name); -} - -void column_name_generator::on_primary_key(const char *id, std::string &, size_t) -{ - push(id); -} - -void column_name_generator::on_revision(const char *id, unsigned long long int &) -{ - push(id); -} - -void column_name_generator::push(const std::string &column_name) -{ - char str[4]; - snprintf(str, 4, "c%02d", ++column_index); - column_infos_.emplace_back(table_name_stack_.top(), column_name, str); -} - -} \ No newline at end of file diff --git a/src/sql/query_builder.cpp b/src/sql/query_builder.cpp index 6bec7b3..c867fac 100644 --- a/src/sql/query_builder.cpp +++ b/src/sql/query_builder.cpp @@ -1,5 +1,5 @@ #include "matador/sql/query_builder.hpp" -#include "matador/sql/column_name_generator.hpp" +#include "matador/sql/column_generator.hpp" #include "matador/sql/column.hpp" #include "matador/sql/dialect.hpp" diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f86b434..6ba60d7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -20,8 +20,8 @@ add_executable(tests models/product.hpp models/order.hpp models/order_details.h + ColumnDefinitionGeneratorTest.cpp ColumnGeneratorTest.cpp - ColumnNameGeneratorTest.cpp ValueGeneratorTest.cpp models/category.hpp models/supplier.hpp diff --git a/test/ColumnDefinitionGeneratorTest.cpp b/test/ColumnDefinitionGeneratorTest.cpp new file mode 100644 index 0000000..77aa88d --- /dev/null +++ b/test/ColumnDefinitionGeneratorTest.cpp @@ -0,0 +1,56 @@ +#include + +#include "matador/sql/column_definition_generator.hpp" +#include "matador/sql/schema.hpp" + +#include "models/product.hpp" +#include "models/optional.hpp" + +using namespace matador::sql; +using namespace matador::utils; + +TEST_CASE("Generate columns from object", "[column generator]") { + schema repo("main"); + + auto columns = column_definition_generator::generate(repo); + + const std::vector expected_columns = { + column_definition{"product_name", data_type_t::type_varchar, constraints::PRIMARY_KEY, null_option::NOT_NULL }, + column_definition{"supplier_id", data_type_t::type_unsigned_long, constraints::FOREIGN_KEY, null_option::NOT_NULL }, + column_definition{"category_id", data_type_t::type_unsigned_long, constraints::FOREIGN_KEY, null_option::NOT_NULL }, + column_definition{"quantity_per_unit", data_type_t::type_varchar, null_attributes, null_option::NOT_NULL }, + column_definition{"unit_price", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL }, + column_definition{"units_in_stock", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL }, + column_definition{"units_in_order", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL }, + column_definition{"reorder_level", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL }, + column_definition{"discontinued", data_type_t::type_bool, null_attributes, null_option::NOT_NULL } + }; + REQUIRE(!columns.empty()); + REQUIRE(columns.size() == expected_columns.size()); + + for (size_t i = 0; i != expected_columns.size(); ++i) { + REQUIRE(expected_columns[i].name() == columns[i].name()); + REQUIRE(expected_columns[i].attributes().options() == columns[i].attributes().options() ); + REQUIRE(expected_columns[i].type() == columns[i].type() ); + } +} + +TEST_CASE("Generate columns from object with nullable columns", "[column generator]") { + schema repo("main"); + + auto columns = column_definition_generator::generate(repo); + + const std::vector expected_columns = { + column_definition{"id", data_type_t::type_unsigned_long, constraints::PRIMARY_KEY, null_option::NOT_NULL }, + column_definition{"name", data_type_t::type_varchar, null_attributes, null_option::NOT_NULL }, + column_definition{"age", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL } + }; + REQUIRE(!columns.empty()); + REQUIRE(columns.size() == expected_columns.size()); + + for (size_t i = 0; i != expected_columns.size(); ++i) { + REQUIRE(expected_columns[i].name() == columns[i].name()); + REQUIRE(expected_columns[i].attributes().options() == columns[i].attributes().options() ); + REQUIRE(expected_columns[i].type() == columns[i].type() ); + } +} \ No newline at end of file diff --git a/test/ColumnGeneratorTest.cpp b/test/ColumnGeneratorTest.cpp index b5c7570..ecfd5a0 100644 --- a/test/ColumnGeneratorTest.cpp +++ b/test/ColumnGeneratorTest.cpp @@ -3,54 +3,96 @@ #include "matador/sql/column_generator.hpp" #include "matador/sql/schema.hpp" +#include "models/order.hpp" #include "models/product.hpp" -#include "models/optional.hpp" +#include "models/book.hpp" +#include "models/author.hpp" using namespace matador::sql; -using namespace matador::utils; -TEST_CASE("Generate columns from object", "[column generator]") { - schema repo("main"); +TEST_CASE("Generate columns from object", "[column][generator]") { + using namespace matador::test; + schema s("main"); + s.attach("product"); - auto columns = column_generator::generate(repo); + auto columns = column_generator::generate(s); - const std::vector expected_columns = { - column_definition{"product_name", data_type_t::type_varchar, constraints::PRIMARY_KEY, null_option::NOT_NULL }, - column_definition{"supplier_id", data_type_t::type_unsigned_long, constraints::FOREIGN_KEY, null_option::NOT_NULL }, - column_definition{"category_id", data_type_t::type_unsigned_long, constraints::FOREIGN_KEY, null_option::NOT_NULL }, - column_definition{"quantity_per_unit", data_type_t::type_varchar, null_attributes, null_option::NOT_NULL }, - column_definition{"unit_price", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL }, - column_definition{"units_in_stock", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL }, - column_definition{"units_in_order", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL }, - column_definition{"reorder_level", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL }, - column_definition{"discontinued", data_type_t::type_bool, null_attributes, null_option::NOT_NULL } + const std::vector expected_columns = { + "product_name", + "supplier_id", + "category_id", + "quantity_per_unit", + "unit_price", + "units_in_stock", + "units_in_order", + "reorder_level", + "discontinued" }; REQUIRE(!columns.empty()); REQUIRE(columns.size() == expected_columns.size()); for (size_t i = 0; i != expected_columns.size(); ++i) { - REQUIRE(expected_columns[i].name() == columns[i].name()); - REQUIRE(expected_columns[i].attributes().options() == columns[i].attributes().options() ); - REQUIRE(expected_columns[i].type() == columns[i].type() ); + REQUIRE(expected_columns[i] == columns[i].name); } } -TEST_CASE("Generate columns from object with nullable columns", "[column generator]") { - schema repo("main"); +TEST_CASE("Generate columns for object with has many relation", "[column][generator][relation]") { + using namespace matador::test; + schema s("main"); + s.attach("product"); + s.attach("order_details"); + s.attach("order"); - auto columns = column_generator::generate(repo); + auto columns = column_generator::generate(s); - const std::vector expected_columns = { - column_definition{"id", data_type_t::type_unsigned_long, constraints::PRIMARY_KEY, null_option::NOT_NULL }, - column_definition{"name", data_type_t::type_varchar, null_attributes, null_option::NOT_NULL }, - column_definition{"age", data_type_t::type_unsigned_int, null_attributes, null_option::NOT_NULL } + const std::vector expected_columns = { + { "order", "order_id", "c01" }, + { "order", "order_date", "c02" }, + { "order", "required_date", "c03" }, + { "order", "shipped_date", "c04" }, + { "order", "ship_via", "c05" }, + { "order", "freight", "c06" }, + { "order", "ship_name", "c07" }, + { "order", "ship_address", "c08" }, + { "order", "ship_city", "c09" }, + { "order", "ship_region", "c10" }, + { "order", "ship_postal_code", "c11" }, + { "order", "ship_country", "c12" }, + { "order_details", "order_details_id", "c13" }, + { "order_details", "order_id", "c14" }, + { "order_details", "product_id", "c15" } }; REQUIRE(!columns.empty()); REQUIRE(columns.size() == expected_columns.size()); for (size_t i = 0; i != expected_columns.size(); ++i) { - REQUIRE(expected_columns[i].name() == columns[i].name()); - REQUIRE(expected_columns[i].attributes().options() == columns[i].attributes().options() ); - REQUIRE(expected_columns[i].type() == columns[i].type() ); + REQUIRE(expected_columns[i].equals(columns[i])); } -} \ No newline at end of file + +} + +TEST_CASE("Generate columns for object with eager foreign key relation", "[column][generator][eager]") { + using namespace matador::test; + schema s("main"); + s.attach("books"); + s.attach("authors"); + + const std::vector expected_columns { + { "books", "id", "c01" }, + { "books", "title", "c02" }, + { "authors", "id", "c03" }, + { "authors", "first_name", "c04" }, + { "authors", "last_name", "c05" }, + { "authors", "date_of_birth", "c06" }, + { "authors", "year_of_birth", "c07" }, + { "authors", "distinguished", "c08" }, + { "books", "published_in", "c09" } + }; + auto columns = column_generator::generate(s); + + REQUIRE(!columns.empty()); + REQUIRE(columns.size() == expected_columns.size()); + for (size_t i = 0; i != expected_columns.size(); ++i) { + REQUIRE(expected_columns[i].equals(columns[i])); + } +} diff --git a/test/ColumnNameGeneratorTest.cpp b/test/ColumnNameGeneratorTest.cpp deleted file mode 100644 index c1a3c8e..0000000 --- a/test/ColumnNameGeneratorTest.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include - -#include "matador/sql/column_name_generator.hpp" -#include "matador/sql/schema.hpp" - -#include "models/order.hpp" -#include "models/product.hpp" - -using namespace matador::sql; - -TEST_CASE("Generate column names from object", "[column name generator]") { - schema s("main"); - s.attach("product"); - - auto columns = column_name_generator::generate(s); - - const std::vector expected_columns = { - "product_name", - "supplier_id", - "category_id", - "quantity_per_unit", - "unit_price", - "units_in_stock", - "units_in_order", - "reorder_level", - "discontinued" - }; - REQUIRE(!columns.empty()); - REQUIRE(columns.size() == expected_columns.size()); - - for (size_t i = 0; i != expected_columns.size(); ++i) { - REQUIRE(expected_columns[i] == columns[i].name); - } -} - -TEST_CASE("Generate column names for object with has many relation", "[column][relation]") { - schema s("main"); - s.attach("product"); - s.attach("order_details"); - s.attach("order"); - - auto columns = column_name_generator::generate(s); - - const std::vector expected_columns = { - "order_id", - "order_date", - "required_date", - "shipped_date", - "ship_via", - "freight", - "ship_name", - "ship_address", - "ship_city", - "ship_region", - "ship_postal_code", - "ship_country", - "order_details_id", - "order_id", - "product_id", - }; - REQUIRE(!columns.empty()); - REQUIRE(columns.size() == expected_columns.size()); - - for (size_t i = 0; i != expected_columns.size(); ++i) { - REQUIRE(expected_columns[i] == columns[i].name); - } - -} \ No newline at end of file diff --git a/test/models/book.hpp b/test/models/book.hpp index 41b1217..a3e7401 100644 --- a/test/models/book.hpp +++ b/test/models/book.hpp @@ -25,7 +25,7 @@ struct book namespace field = matador::utils::access; field::primary_key(op, "id", id); field::attribute(op, "title", title, 511); - field::has_one(op, "author_id", book_author, matador::utils::default_foreign_attributes); + field::has_one(op, "author_id", book_author, utils::fetch_type::EAGER); field::attribute(op, "published_in", published_in); } };