From b966a7a1a7ef5dad14b497e3fde0d47073846673 Mon Sep 17 00:00:00 2001 From: Sascha Kuehl Date: Thu, 8 Feb 2024 20:09:24 +0100 Subject: [PATCH] add column info (progress, not compiling) --- backends/postgres/test/CMakeLists.txt | 2 +- backends/tests/QueryTest.cpp | 2 +- include/matador/sql/column_generator.hpp | 8 +-- include/matador/sql/column_name_generator.hpp | 59 +++++++++++++++---- include/matador/sql/connection.hpp | 10 ++-- include/matador/sql/query_builder.hpp | 4 +- include/matador/sql/query_intermediates.hpp | 29 +++++---- .../sql/{table_repository.hpp => schema.hpp} | 18 +++--- include/matador/sql/session.hpp | 12 ++-- include/matador/utils/access.hpp | 14 ++++- src/CMakeLists.txt | 4 +- src/sql/column_generator.cpp | 4 +- src/sql/column_name_generator.cpp | 22 +++++-- src/sql/connection.cpp | 10 ++-- src/sql/query_builder.cpp | 13 ++-- src/sql/query_intermediates.cpp | 18 +++--- src/sql/{table_repository.cpp => schema.cpp} | 20 +++---- src/sql/session.cpp | 6 +- test/CMakeLists.txt | 2 + test/ColumnGeneratorTest.cpp | 6 +- test/ColumnNameGeneratorTest.cpp | 42 ++++++++++++- test/QueryBuilderTest.cpp | 2 +- test/models/order.hpp | 50 ++++++++++++++++ test/models/order_details.h | 28 +++++++++ 24 files changed, 286 insertions(+), 99 deletions(-) rename include/matador/sql/{table_repository.hpp => schema.hpp} (80%) rename src/sql/{table_repository.cpp => schema.cpp} (60%) create mode 100644 test/models/order.hpp create mode 100644 test/models/order_details.h diff --git a/backends/postgres/test/CMakeLists.txt b/backends/postgres/test/CMakeLists.txt index efa28ee..12af877 100644 --- a/backends/postgres/test/CMakeLists.txt +++ b/backends/postgres/test/CMakeLists.txt @@ -12,7 +12,7 @@ list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras) include(CTest) include(Catch) -set(POSTGRES_CONNECTION_STRING "postgres://test:test123@127.0.0.1:5432/matador_test") +set(POSTGRES_CONNECTION_STRING "postgres://test:test123@127.0.0.1:15432/test") configure_file(Connection.hpp.in ${PROJECT_BINARY_DIR}/backends/postgres/test/connection.hpp @ONLY IMMEDIATE) diff --git a/backends/tests/QueryTest.cpp b/backends/tests/QueryTest.cpp index 7830510..d097cb3 100644 --- a/backends/tests/QueryTest.cpp +++ b/backends/tests/QueryTest.cpp @@ -121,7 +121,7 @@ TEST_CASE_METHOD(QueryFixture, " Execute insert statement", "[session]") .execute(); auto res = db.insert() - .into("person", {"id", "name", "color"}) + .into("person", {{"", "id", ""}, {"", "name", ""}, {"", "color", ""}}) .values({7, "george", "green"}) .execute(); diff --git a/include/matador/sql/column_generator.hpp b/include/matador/sql/column_generator.hpp index 4b62609..7d4d499 100644 --- a/include/matador/sql/column_generator.hpp +++ b/include/matador/sql/column_generator.hpp @@ -13,7 +13,7 @@ namespace matador::sql { -class table_repository; +class schema; class fk_column_generator { @@ -53,13 +53,13 @@ private: class column_generator { private: - column_generator(std::vector &columns, const table_repository &repo); + column_generator(std::vector &columns, const schema &repo); public: ~column_generator() = default; template < class Type > - static std::vector generate(const table_repository &repo) + static std::vector generate(const schema &repo) { std::vector columns; column_generator gen(columns, repo); @@ -102,7 +102,7 @@ private: private: size_t index_ = 0; std::vector &columns_; - const table_repository &repo_; + const schema &repo_; fk_column_generator fk_column_generator_; }; diff --git a/include/matador/sql/column_name_generator.hpp b/include/matador/sql/column_name_generator.hpp index 54829a1..c271463 100644 --- a/include/matador/sql/column_name_generator.hpp +++ b/include/matador/sql/column_name_generator.hpp @@ -5,24 +5,38 @@ #include "matador/utils/field_attributes.hpp" #include "matador/utils/foreign_attributes.hpp" +#include "matador/sql/schema.hpp" + #include #include +#include namespace matador::sql { +struct column_info +{ + std::string table; + std::string name; + std::string alias; +}; + class column_name_generator { private: - explicit column_name_generator(std::vector &column_names); + 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() + static std::vector generate(const sql::schema &ts) { - std::vector columns; - column_name_generator gen(columns); + 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); @@ -31,7 +45,7 @@ public: template < class V > void on_primary_key(const char *id, V &, typename std::enable_if::value && !std::is_same::value>::type* = 0) { - column_names_.emplace_back(id); + push(id); } void on_primary_key(const char *id, std::string &, size_t); void on_revision(const char *id, unsigned long long &/*rev*/); @@ -39,26 +53,49 @@ public: template void on_attribute(const char *id, Type &, const utils::field_attributes &/*attr*/ = utils::null_attributes) { - column_names_.emplace_back(id); + push(id); } template void on_belongs_to(const char *id, Pointer &, const utils::foreign_attributes &/*attr*/) { - column_names_.emplace_back(id); + push(id); } template void on_has_one(const char *id, Pointer &, const utils::foreign_attributes &/*attr*/) { - column_names_.emplace_back(id); + push(id); } 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() == 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::vector &column_names_; + 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}; }; } diff --git a/include/matador/sql/connection.hpp b/include/matador/sql/connection.hpp index f2fdef0..60c96a3 100644 --- a/include/matador/sql/connection.hpp +++ b/include/matador/sql/connection.hpp @@ -19,8 +19,8 @@ namespace matador::sql { class connection { public: - explicit connection(connection_info info, const std::shared_ptr &repo = std::make_shared()); - explicit connection(const std::string& dns, const std::shared_ptr &repo = std::make_shared()); + explicit connection(connection_info info, const std::shared_ptr &repo = std::make_shared()); + explicit connection(const std::string& dns, const std::shared_ptr &repo = std::make_shared()); connection(const connection &x); connection& operator=(const connection &x); connection(connection &&x) noexcept = default; @@ -51,20 +51,20 @@ public: statement prepare(query_context &&query) const; const class dialect& dialect() const; - std::shared_ptr tables() const; + std::shared_ptr tables() const; private: connection_info connection_info_; std::unique_ptr connection_; utils::logger logger_; const class dialect &dialect_; - std::shared_ptr table_repository_; + std::shared_ptr schema_; }; template query_select_intermediate connection::select() { - return query_select_intermediate{*this, column_generator::generate(*table_repository_)}; + return query_select_intermediate{*this, column_generator::generate(*schema_)}; } } diff --git a/include/matador/sql/query_builder.hpp b/include/matador/sql/query_builder.hpp index dd2d463..5d4cc5d 100644 --- a/include/matador/sql/query_builder.hpp +++ b/include/matador/sql/query_builder.hpp @@ -126,8 +126,8 @@ public: query_builder& table(const std::string &table, std::initializer_list columns); query_builder& table(const std::string &table, const std::vector &columns); query_builder& table(const std::string &table); - query_builder& into(const std::string &table, std::initializer_list column_names); - query_builder& into(const std::string &table, const std::vector &column_names); + query_builder& into(const std::string &table, std::initializer_list column_names); + query_builder& into(const std::string &table, const std::vector &column_names); query_builder& values(std::initializer_list values); query_builder& values(const std::vector &values); query_builder& from(const std::string &table, const std::string &as = ""); diff --git a/include/matador/sql/query_intermediates.hpp b/include/matador/sql/query_intermediates.hpp index eb6f6ba..151971b 100644 --- a/include/matador/sql/query_intermediates.hpp +++ b/include/matador/sql/query_intermediates.hpp @@ -11,7 +11,7 @@ #include "matador/sql/query_result.hpp" #include "matador/sql/record.hpp" #include "matador/sql/statement.hpp" -#include "matador/sql/table_repository.hpp" +#include "matador/sql/schema.hpp" #include "matador/sql/value_extractor.hpp" #include @@ -21,13 +21,24 @@ namespace matador::sql { class basic_condition; class connection; -class query_intermediate +class basic_query_intermediate +{ +public: + explicit basic_query_intermediate(connection &db); + +protected: + [[nodiscard]] std::shared_ptr tables() const; + +protected: + connection &connection_; +}; + +class query_intermediate : public basic_query_intermediate { public: query_intermediate(connection &db, query_builder &query); protected: - connection &connection_; query_builder &builder_; }; @@ -149,13 +160,12 @@ public: query_order_by_intermediate order_by(const std::string &name); }; -class query_start_intermediate +class query_start_intermediate : public basic_query_intermediate { public: explicit query_start_intermediate(connection &s); protected: - connection &connection_; query_builder builder_; }; @@ -210,9 +220,6 @@ public: } return {connection_, builder_.table(table_name, column_generator::generate(*tables()))}; } - -private: - std::shared_ptr tables() const; }; class query_drop_intermediate : query_start_intermediate @@ -228,16 +235,16 @@ 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_names); + query_into_intermediate into(const std::string &table, std::initializer_list column_names); template query_into_intermediate into(const std::string &table) { - return {connection_, builder_.into(table, column_name_generator::generate())}; + return {connection_, builder_.into(table, column_name_generator::generate(*tables()))}; } template query_execute_finish into(const std::string &table, const Type &obj) { - return {connection_, builder_.into(table, column_name_generator::generate()) + return {connection_, builder_.into(table, column_name_generator::generate(*tables())) .values(value_extractor::extract(obj))}; } }; diff --git a/include/matador/sql/table_repository.hpp b/include/matador/sql/schema.hpp similarity index 80% rename from include/matador/sql/table_repository.hpp rename to include/matador/sql/schema.hpp index e528711..62b5be1 100644 --- a/include/matador/sql/table_repository.hpp +++ b/include/matador/sql/schema.hpp @@ -1,5 +1,5 @@ -#ifndef QUERY_TABLE_REPOSITORY_HPP -#define QUERY_TABLE_REPOSITORY_HPP +#ifndef QUERY_SCHEMA_HPP +#define QUERY_SCHEMA_HPP #include "matador/sql/column_generator.hpp" #include "matador/sql/record.hpp" @@ -21,7 +21,7 @@ struct table_info void drop(connection &conn) const; }; -class table_repository +class schema { public: using repository = std::unordered_map; @@ -37,12 +37,12 @@ public: const table_info& attach(std::type_index ti, const table_info& table); template - std::optional info() + [[nodiscard]] std::optional info() const { return info(std::type_index(typeid(Type))); } - std::optional info(std::type_index ti); + [[nodiscard]] std::optional info(std::type_index ti) const; template [[nodiscard]] std::pair reference() const @@ -61,11 +61,11 @@ public: [[nodiscard]] bool exists(const std::type_index &ti) const; iterator begin(); - const_iterator begin() const; + [[nodiscard]] const_iterator begin() const; iterator end(); - const_iterator end() const; + [[nodiscard]] const_iterator end() const; - bool empty() const; + [[nodiscard]] bool empty() const; private: repository repository_; @@ -73,4 +73,4 @@ private: } -#endif //QUERY_TABLE_REPOSITORY_HPP +#endif //QUERY_SCHEMA_HPP diff --git a/include/matador/sql/session.hpp b/include/matador/sql/session.hpp index eab16de..5522490 100644 --- a/include/matador/sql/session.hpp +++ b/include/matador/sql/session.hpp @@ -5,7 +5,7 @@ #include "matador/sql/connection_pool.hpp" #include "matador/sql/entity.hpp" #include "matador/sql/statement.hpp" -#include "matador/sql/table_repository.hpp" +#include "matador/sql/schema.hpp" #include @@ -43,7 +43,7 @@ public: record describe_table(const std::string &table_name) const; bool table_exists(const std::string &table_name) const; - [[nodiscard]] const table_repository& tables() const; + [[nodiscard]] const schema& tables() const; const class dialect& dialect() const; @@ -56,21 +56,21 @@ private: connection_pool &pool_; const class dialect &dialect_; - table_repository table_repository_; + schema schema_; mutable std::unordered_map prototypes_; }; template void session::attach(const std::string &table_name) { - table_repository_.attach(table_name); + schema_.attach(table_name); } template entity session::insert(Type *obj) { auto c = pool_.acquire(); - auto info = table_repository_.info(); + auto info = schema_.info(); if (!info) { return {}; } @@ -82,7 +82,7 @@ entity session::insert(Type *obj) template void session::drop_table() { - auto info = table_repository_.info(); + auto info = schema_.info(); if (info) { return drop_table(info.name); } diff --git a/include/matador/utils/access.hpp b/include/matador/utils/access.hpp index 7cc3293..ec2bb65 100644 --- a/include/matador/utils/access.hpp +++ b/include/matador/utils/access.hpp @@ -64,13 +64,23 @@ void belongs_to(Operator &op, const char *id, Type &value, const foreign_attribu op.on_belongs_to(id, value, attr); } +//template class ContainerType> +//void has_many(Operator &op, const char *id, container &container, const foreign_attributes &attr) { +// op.on_has_many(id, container, attr); +//} + template class ContainerType> -void has_many(Operator &op, const char *id, container &container, const foreign_attributes &attr) { +void has_many(Operator &op, const char *id, ContainerType &container, const foreign_attributes &attr) { op.on_has_many(id, container, attr); } +//template class ContainerType> +//void has_many(Operator &op, const char *id, container &container, const char *left_column, const char *right_column, const foreign_attributes &attr) { +// op.on_has_many(id, container, left_column, right_column, attr); +//} + template class ContainerType> -void has_many(Operator &op, const char *id, container &container, const char *left_column, const char *right_column, const foreign_attributes &attr) { +void has_many(Operator &op, const char *id, ContainerType &container, const char *left_column, const char *right_column, const foreign_attributes &attr) { op.on_has_many(id, container, left_column, right_column, attr); } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ee52564..b4184b8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,7 +16,7 @@ set(SQL_SOURCES sql/column_name_generator.cpp sql/key_value_generator.cpp sql/fk_value_extractor.cpp - sql/table_repository.cpp + sql/schema.cpp sql/query_result.cpp sql/query_result_reader.cpp sql/statement_cache.cpp @@ -55,7 +55,7 @@ set(SQL_HEADER ../include/matador/sql/key_value_generator.hpp ../include/matador/sql/entity.hpp ../include/matador/sql/fk_value_extractor.hpp - ../include/matador/sql/table_repository.hpp + ../include/matador/sql/schema.hpp ../include/matador/sql/any_type_to_visitor.hpp ../include/matador/sql/query_result_reader.hpp ../include/matador/sql/to_value.hpp diff --git a/src/sql/column_generator.cpp b/src/sql/column_generator.cpp index 56afb2d..8e13720 100644 --- a/src/sql/column_generator.cpp +++ b/src/sql/column_generator.cpp @@ -1,9 +1,9 @@ #include "matador/sql/column_generator.hpp" -#include "matador/sql/table_repository.hpp" +#include "matador/sql/schema.hpp" namespace matador::sql { -column_generator::column_generator(std::vector &columns, const table_repository &repo) +column_generator::column_generator(std::vector &columns, const schema &repo) : columns_(columns) , repo_(repo) {} diff --git a/src/sql/column_name_generator.cpp b/src/sql/column_name_generator.cpp index ac59d78..b10aa69 100644 --- a/src/sql/column_name_generator.cpp +++ b/src/sql/column_name_generator.cpp @@ -2,18 +2,30 @@ namespace matador::sql { -column_name_generator::column_name_generator(std::vector &column_names) -: column_names_(column_names) -{} +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) { - column_names_.emplace_back(id); + push(id); } void column_name_generator::on_revision(const char *id, unsigned long long int &) { - column_names_.emplace_back(id); + 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(column_info{table_name_stack_.top(), column_name, str}); } } \ No newline at end of file diff --git a/src/sql/connection.cpp b/src/sql/connection.cpp index 9f6d83d..579701e 100644 --- a/src/sql/connection.cpp +++ b/src/sql/connection.cpp @@ -8,16 +8,16 @@ namespace matador::sql { -connection::connection(connection_info info, const std::shared_ptr &repo) +connection::connection(connection_info info, const std::shared_ptr &repo) : connection_info_(std::move(info)) , logger_(stdout, "SQL") , dialect_(backend_provider::instance().connection_dialect(connection_info_.type)) -, table_repository_(repo) +, schema_(repo) { connection_.reset(backend_provider::instance().create_connection(connection_info_.type, connection_info_)); } -connection::connection(const std::string& dns, const std::shared_ptr &repo) +connection::connection(const std::string& dns, const std::shared_ptr &repo) : connection(connection_info::parse(dns), repo) {} @@ -160,9 +160,9 @@ const class dialect &connection::dialect() const return dialect_; } -std::shared_ptr connection::tables() const +std::shared_ptr connection::tables() const { - return table_repository_; + return schema_; } } diff --git a/src/sql/query_builder.cpp b/src/sql/query_builder.cpp index d9de6db..7488d42 100644 --- a/src/sql/query_builder.cpp +++ b/src/sql/query_builder.cpp @@ -1,4 +1,5 @@ #include "matador/sql/query_builder.hpp" +#include "matador/sql/column_name_generator.hpp" #include "matador/sql/dialect.hpp" #include "matador/utils/string.hpp" @@ -255,12 +256,12 @@ query_builder &query_builder::table(const std::string &table) return *this; } -query_builder &query_builder::into(const std::string &table, std::initializer_list column_names) +query_builder &query_builder::into(const std::string &table, std::initializer_list column_names) { - return into(table, std::vector{column_names}); + return into(table, std::vector{column_names}); } -query_builder &query_builder::into(const std::string &table, const std::vector &column_names) +query_builder &query_builder::into(const std::string &table, const std::vector &column_names) { transition_to(state_t::QUERY_INTO); @@ -270,14 +271,14 @@ query_builder &query_builder::into(const std::string &table, const std::vectorname)); for (; it != column_names.end(); ++it) { result.append(", "); - result.append(dialect_.prepare_identifier(*it)); + result.append(dialect_.prepare_identifier(it->name)); } } result += (")"); diff --git a/src/sql/query_intermediates.cpp b/src/sql/query_intermediates.cpp index 0902d70..0834549 100644 --- a/src/sql/query_intermediates.cpp +++ b/src/sql/query_intermediates.cpp @@ -2,6 +2,13 @@ #include "matador/sql/session.hpp" namespace matador::sql { +basic_query_intermediate::basic_query_intermediate(connection &db) +: connection_(db) {} + +std::shared_ptr basic_query_intermediate::tables() const +{ + return connection_.tables(); +} query_result query_select_finish::fetch_all() { @@ -24,7 +31,7 @@ statement query_select_finish::prepare() } query_intermediate::query_intermediate(connection &db, query_builder &query) -: connection_(db), builder_(query) {} +: basic_query_intermediate(db), builder_(query) {} query_offset_intermediate query_order_direction_intermediate::offset(size_t offset) { @@ -128,7 +135,7 @@ query_insert_intermediate::query_insert_intermediate(connection &s) builder_.insert(); } -query_into_intermediate query_insert_intermediate::into(const std::string &table, std::initializer_list column_names) +query_into_intermediate query_insert_intermediate::into(const std::string &table, std::initializer_list column_names) { return {connection_, builder_.into(table, column_names)}; } @@ -163,11 +170,6 @@ query_execute_finish query_create_intermediate::table(const std::string &table_n return {connection_, builder_.table(table_name, columns)}; } -std::shared_ptr query_create_intermediate::tables() const -{ - return connection_.tables(); -} - query_drop_intermediate::query_drop_intermediate(connection &s) : query_start_intermediate(s) { @@ -217,7 +219,7 @@ query_delete_from_intermediate query_delete_intermediate::from(const std::string } query_start_intermediate::query_start_intermediate(connection &s) -: connection_(s) +: basic_query_intermediate(s) , builder_(s.dialect()) {} } \ No newline at end of file diff --git a/src/sql/table_repository.cpp b/src/sql/schema.cpp similarity index 60% rename from src/sql/table_repository.cpp rename to src/sql/schema.cpp index 3f9fca9..a48b764 100644 --- a/src/sql/table_repository.cpp +++ b/src/sql/schema.cpp @@ -1,4 +1,4 @@ -#include "matador/sql/table_repository.hpp" +#include "matador/sql/schema.hpp" #include "matador/sql/connection.hpp" #include @@ -15,12 +15,12 @@ void table_info::drop(connection &conn) const conn.drop().table(name).execute(); } -const table_info& table_repository::attach(const std::type_index ti, const table_info& table) +const table_info& schema::attach(const std::type_index ti, const table_info& table) { return repository_.try_emplace(ti, table).first->second; } -std::optional table_repository::info(std::type_index ti) +std::optional schema::info(std::type_index ti) const { const auto it = repository_.find(ti); if (it == repository_.end()) { @@ -29,7 +29,7 @@ std::optional table_repository::info(std::type_index ti) return it->second; } -std::pair table_repository::reference(const std::type_index &ti) const +std::pair schema::reference(const std::type_index &ti) const { const auto it = repository_.find(ti); if (it != repository_.end()) { @@ -42,32 +42,32 @@ std::pair table_repository::reference(const std::type_ return {}; } -bool table_repository::exists(const std::type_index &ti) const +bool schema::exists(const std::type_index &ti) const { return repository_.count(ti) > 0; } -table_repository::iterator table_repository::begin() +schema::iterator schema::begin() { return repository_.begin(); } -table_repository::const_iterator table_repository::begin() const +schema::const_iterator schema::begin() const { return repository_.begin(); } -table_repository::iterator table_repository::end() +schema::iterator schema::end() { return repository_.end(); } -table_repository::const_iterator table_repository::end() const +schema::const_iterator schema::end() const { return repository_.end(); } -bool table_repository::empty() const +bool schema::empty() const { return repository_.empty(); } diff --git a/src/sql/session.cpp b/src/sql/session.cpp index 2fd9ac3..87cdcd1 100644 --- a/src/sql/session.cpp +++ b/src/sql/session.cpp @@ -13,7 +13,7 @@ session::session(connection_pool &pool) void session::create_schema() { auto c = pool_.acquire(); - for (const auto &t : table_repository_) { + for (const auto &t : schema_) { t.second.create(*c); } } @@ -88,9 +88,9 @@ bool session::table_exists(const std::string &table_name) const return c->exists(dialect_.default_schema_name(), table_name); } -const table_repository& session::tables() const +const schema& session::tables() const { - return table_repository_; + return schema_; } const class dialect &session::dialect() const diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ba093c0..1e78372 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -13,6 +13,8 @@ add_executable(tests QueryBuilderTest.cpp ConnectionPoolTest.cpp BackendProviderTest.cpp models/product.hpp + models/order.hpp + models/order_details.h ColumnGeneratorTest.cpp ColumnNameGeneratorTest.cpp ValueGeneratorTest.cpp diff --git a/test/ColumnGeneratorTest.cpp b/test/ColumnGeneratorTest.cpp index 493740b..f826e6a 100644 --- a/test/ColumnGeneratorTest.cpp +++ b/test/ColumnGeneratorTest.cpp @@ -1,7 +1,7 @@ #include #include "matador/sql/column_generator.hpp" -#include "matador/sql/table_repository.hpp" +#include "matador/sql/schema.hpp" #include "models/product.hpp" #include "models/optional.hpp" @@ -10,7 +10,7 @@ using namespace matador::sql; using namespace matador::utils; TEST_CASE("Generate columns from object", "[column generator]") { - table_repository repo; + schema repo; auto columns = column_generator::generate(repo); @@ -36,7 +36,7 @@ TEST_CASE("Generate columns from object", "[column generator]") { } TEST_CASE("Generate columns from object with nullable columns", "[column generator]") { - table_repository repo; + schema repo; auto columns = column_generator::generate(repo); diff --git a/test/ColumnNameGeneratorTest.cpp b/test/ColumnNameGeneratorTest.cpp index 5576f5a..a3c0950 100644 --- a/test/ColumnNameGeneratorTest.cpp +++ b/test/ColumnNameGeneratorTest.cpp @@ -1,14 +1,18 @@ #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; + s.attach("product"); - auto columns = column_name_generator::generate(); + auto columns = column_name_generator::generate(s); const std::vector expected_columns = { "product_name", @@ -25,6 +29,40 @@ TEST_CASE("Generate column names from object", "[column name generator]") { REQUIRE(columns.size() == expected_columns.size()); for (size_t i = 0; i != expected_columns.size(); ++i) { - REQUIRE(expected_columns[i] == columns[i]); + REQUIRE(expected_columns[i] == columns[i].name); } } + +TEST_CASE("Generate column names for object with has many relation", "[column][relation]") { + schema s; + 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/QueryBuilderTest.cpp b/test/QueryBuilderTest.cpp index f90ee1d..bde479c 100644 --- a/test/QueryBuilderTest.cpp +++ b/test/QueryBuilderTest.cpp @@ -164,7 +164,7 @@ TEST_CASE("Create, insert and select a blob column", "[query][blob]") { REQUIRE(q.table_name == "person"); q = query.insert().into("person", { - "id", "name", "data" + {"", "id", ""}, {"", "name", ""}, {"", "data", ""} }).values({7UL, "george", blob{1, 'A', 3, 4}}).compile(); REQUIRE(q.sql == R"(INSERT INTO "person" ("id", "name", "data") VALUES (7, 'george', X'01410304'))"); diff --git a/test/models/order.hpp b/test/models/order.hpp new file mode 100644 index 0000000..f3df99a --- /dev/null +++ b/test/models/order.hpp @@ -0,0 +1,50 @@ +#ifndef QUERY_ORDER_HPP +#define QUERY_ORDER_HPP + +#include "order_details.h" + +#include "matador/utils/access.hpp" + +#include "matador/sql/entity.hpp" + +#include + +namespace matador::test { + +struct order +{ + unsigned long order_id{}; + std::string order_date; + std::string required_date; + std::string shipped_date; + unsigned int ship_via{}; + unsigned int freight{}; + std::string ship_name; + std::string ship_address; + std::string ship_city; + std::string ship_region; + std::string ship_postal_code; + std::string ship_country; + std::vector> order_details_; + + template + void process(Operator &op) { + namespace field = matador::utils::access; + field::primary_key(op, "order_id", order_id); + field::attribute(op, "order_date", order_date, 255); + field::attribute(op, "required_date", required_date, 255); + field::attribute(op, "shipped_date", shipped_date, 255); + field::attribute(op, "ship_via", ship_via); + field::attribute(op, "freight", freight); + field::attribute(op, "ship_name", ship_name, 255); + field::attribute(op, "ship_address", ship_address, 255); + field::attribute(op, "ship_city", ship_city, 255); + field::attribute(op, "ship_region", ship_region, 255); + field::attribute(op, "ship_postal_code", ship_postal_code, 255); + field::attribute(op, "ship_country", ship_country, 255); + field::has_many(op, "order_details", order_details_, fetch_type::EAGER); + } +}; + +} +#endif //QUERY_ORDER_HPP diff --git a/test/models/order_details.h b/test/models/order_details.h new file mode 100644 index 0000000..04be995 --- /dev/null +++ b/test/models/order_details.h @@ -0,0 +1,28 @@ +#ifndef QUERY_ORDER_DETAILS_H +#define QUERY_ORDER_DETAILS_H + +#include "product.hpp" + +#include "matador/sql/entity.hpp" + +namespace matador::test { + +struct order; + +struct order_details +{ + unsigned long order_details_id; + sql::entity order_; + sql::entity product_; + + template + void process(Operator &op) { + namespace field = matador::utils::access; + field::primary_key(op, "order_details_id", order_details_id); + field::belongs_to(op, "order_id", order_, utils::default_foreign_attributes); + field::has_one(op, "product_id", product_, utils::default_foreign_attributes); + } +}; + +} +#endif //QUERY_ORDER_DETAILS_H