diff --git a/include/matador/object/object_ptr.hpp b/include/matador/object/object_ptr.hpp index 15de234..d75306f 100644 --- a/include/matador/object/object_ptr.hpp +++ b/include/matador/object/object_ptr.hpp @@ -1,16 +1,38 @@ #ifndef OBJECT_PTR_HPP #define OBJECT_PTR_HPP +#include "matador/utils/identifier.hpp" + +#include + namespace matador::object { template class object_ptr { public: - using value_type = Type; - Type* operator->() { return ptr; }; - Type& operator*() { return *ptr; }; + object_ptr() = default; + object_ptr(Type *obj) : ptr_(obj) {} + explicit object_ptr(std::shared_ptr obj) : ptr_(obj) {} + object_ptr(const object_ptr &other) : ptr_(other.ptr_) {} + object_ptr(object_ptr &&other) noexcept : ptr_(std::move(other.ptr_)) {} + object_ptr &operator=(const object_ptr &other) = default; + object_ptr &operator=(object_ptr &&other) = default; + using value_type = Type; + Type* operator->() { return ptr_.get(); } + Type& operator*() const { return *ptr_; } + + [[nodiscard]] bool empty() const { return ptr_ == nullptr; } + + Type* get() { return ptr_.get(); } + const Type* get() const { return ptr_.get(); } + operator bool() { return valid(); } + bool valid() { return ptr_ != nullptr; } + + [[nodiscard]] const utils::identifier& primary_key() const { return pk_; } + void primary_key(const utils::identifier &pk) { pk_ = pk; } private: - Type* ptr{nullptr}; + std::shared_ptr ptr_{}; + utils::identifier pk_; }; } diff --git a/include/matador/orm/error_code.hpp b/include/matador/orm/error_code.hpp new file mode 100644 index 0000000..69e396f --- /dev/null +++ b/include/matador/orm/error_code.hpp @@ -0,0 +1,33 @@ +#ifndef ERROR_CODE_HPP +#define ERROR_CODE_HPP + +#include +#include + +namespace matador::orm { + +enum class error_code : uint8_t { + Ok = 0, + NoConnectionAvailable, + UnknownType, + FailedToBuildQuery, + FailedToFindObject +}; + +class orm_category_impl final : public std::error_category +{ +public: + [[nodiscard]] const char* name() const noexcept override; + [[nodiscard]] std::string message(int ev) const override; +}; + +const std::error_category& orm_category(); +std::error_code make_error_code(error_code e); +std::error_condition make_error_condition(error_code e); + +} + +template <> +struct std::is_error_code_enum : true_type {}; + +#endif //ERROR_CODE_HPP diff --git a/include/matador/orm/session.hpp b/include/matador/orm/session.hpp index 9f5903e..4a31448 100644 --- a/include/matador/orm/session.hpp +++ b/include/matador/orm/session.hpp @@ -1,6 +1,7 @@ #ifndef QUERY_SESSION_HPP #define QUERY_SESSION_HPP +#include "matador/orm/error_code.hpp" #include "matador/orm/session_query_builder.hpp" #include "matador/query/query.hpp" @@ -18,16 +19,9 @@ namespace matador::orm { -enum class session_error { - Ok = 0, - NoConnectionAvailable, - UnknownType, - FailedToBuildQuery, - FailedToFindObject -}; +utils::error make_error(error_code ec, const std::string &msg); -class session -{ +class session final { public: explicit session(sql::connection_pool &pool); @@ -37,81 +31,81 @@ public: utils::result create_schema() const; template - object::object_ptr insert(Type *obj); + utils::result, utils::error> insert(Type *obj); template< class Type, typename... Args > - object::object_ptr insert(Args&&... args) { + utils::result, utils::error> insert(Args&&... args) { return insert(new Type(std::forward(args)...)); } template - utils::result, session_error> find(const PrimaryKeyType &pk) { + utils::result, utils::error> find(const PrimaryKeyType &pk) { auto c = pool_.acquire(); if (!c.valid()) { - return utils::failure(session_error::NoConnectionAvailable); + return utils::failure(make_error(error_code::NoConnectionAvailable, "Failed to acquire connection.")); } auto info = schema_->info(); if (!info) { - return utils::failure(session_error::UnknownType); + return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type.")); } session_query_builder eqb(*schema_); auto data = eqb.build(pk); if (!data.is_ok()) { - return utils::failure(session_error::FailedToBuildQuery); + return utils::failure(make_error(error_code::FailedToBuildQuery, "Failed to build query for type " + info->get().name() + ".")); } - auto obj = build_select_query(c, data.release()).template fetch_one(); + auto obj = build_select_query(data.release()).template fetch_one(*c); if (!obj) { - return utils::failure(session_error::FailedToFindObject); + return utils::failure(make_error(error_code::FailedToFindObject, "Failed to find object of type " + info->get().name() + " with primary key " + std::to_string(pk) + ".")); } return utils::ok(object::object_ptr{ obj.release() }); } template - utils::result, session_error> find() { + utils::result, utils::error> find() { auto c = pool_.acquire(); if (!c.valid()) { - return utils::failure(session_error::NoConnectionAvailable); + return utils::failure(make_error(error_code::NoConnectionAvailable, "Failed to acquire connection.")); } auto info = schema_->info(); if (!info) { - return utils::failure(session_error::UnknownType); + return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type.")); } session_query_builder eqb(*schema_); auto data = eqb.build(); if (!data.is_ok()) { - return utils::failure(session_error::FailedToBuildQuery); + return utils::failure(make_error(error_code::FailedToBuildQuery, "Failed to build query for type " + info->get().name() + ".")); } - return utils::ok(build_select_query(c, data.release()).template fetch_all()); + return build_select_query(data.release()).template fetch_all(*c); } template - utils::result select() { + utils::result select() { auto c = pool_.acquire(); if (!c.valid()) { - return utils::failure(session_error::NoConnectionAvailable); + return utils::failure(make_error(error_code::NoConnectionAvailable, "Failed to acquire connection.")); } auto info = schema_->info(); if (!info) { - return utils::failure(session_error::UnknownType); + return utils::failure(make_error(error_code::UnknownType, "Failed to determine requested type.")); } session_query_builder eqb(*schema_); auto data = eqb.build(); if (!data.is_ok()) { - return utils::failure(session_error::FailedToBuildQuery); + return utils::failure(make_error(error_code::FailedToBuildQuery, "Failed to build query for type " + info->get().name() + ".")); } - return utils::ok(build_select_query(c, data.release()).template fetch_all()); + return utils::ok(build_select_query(data.release()).template fetch_all(*c)); } template void drop_table(); - void drop_table(const std::string &table_name); + void drop_table(const std::string &table_name) const; [[nodiscard]] utils::result, utils::error> fetch(const sql::query_context &q) const; // [[nodiscard]] query_result fetch(const std::string &sql) const; @@ -128,7 +122,7 @@ private: // [[nodiscard]] std::unique_ptr fetch(const std::string &sql) const; - static query::fetchable_query build_select_query(sql::connection_ptr &conn, entity_query_data &&data); + static query::fetchable_query build_select_query(entity_query_data &&data); private: sql::connection_pool &pool_; @@ -145,20 +139,23 @@ template } template -object::object_ptr session::insert(Type *obj) +utils::result, utils::error> session::insert(Type *obj) { auto c = pool_.acquire(); auto info = schema_->info(); if (!info) { - return {}; + return utils::failure(info.err()); } - query::query::insert() - .into(info->name, sql::column_generator::generate(*schema_, true)) + auto res = query::query::insert() + .into(info->get().name(), sql::column_generator::generate(*schema_, true)) .values(*obj) - .execute(); + .execute(*c); + if (!res) { + return utils::failure(res.err()); + } - return object::object_ptr{obj}; + return utils::ok(object::object_ptr{obj}); } template diff --git a/include/matador/orm/session_query_builder.hpp b/include/matador/orm/session_query_builder.hpp index 3f6a11a..e7cd14b 100644 --- a/include/matador/orm/session_query_builder.hpp +++ b/include/matador/orm/session_query_builder.hpp @@ -121,9 +121,9 @@ public: } pk_ = nullptr; table_info_stack_.push(info.value()); - entity_query_data_ = { info->name() }; + entity_query_data_ = { info->get().name() }; try { - access::process(*this, info->prototype()); + access::process(*this, info->get().prototype()); return {utils::ok(std::move(entity_query_data_))}; } catch (const query_builder_exception &ex) { diff --git a/include/matador/query/intermediates/fetchable_query.hpp b/include/matador/query/intermediates/fetchable_query.hpp index 23c1848..e565e97 100644 --- a/include/matador/query/intermediates/fetchable_query.hpp +++ b/include/matador/query/intermediates/fetchable_query.hpp @@ -25,11 +25,10 @@ protected: public: template < class Type > - utils::result, utils::error> fetch_all(sql::executor &exec) - { + utils::result, utils::error> fetch_all(sql::executor &exec) { auto result = fetch(exec); if (!result.is_ok()) { - return utils::error(result.err()); + return utils::failure(result.err()); } return utils::ok(sql::query_result(result.release())); @@ -41,7 +40,7 @@ public: { auto result = fetch(exec); if (!result.is_ok()) { - return utils::error(result.err()); + return utils::failure(result.err()); } auto objects = sql::query_result(result.release()); diff --git a/include/matador/query/intermediates/query_create_intermediate.hpp b/include/matador/query/intermediates/query_create_intermediate.hpp index 287421a..5d2d590 100644 --- a/include/matador/query/intermediates/query_create_intermediate.hpp +++ b/include/matador/query/intermediates/query_create_intermediate.hpp @@ -5,6 +5,8 @@ #include "matador/query/intermediates/executable_query.hpp" +#include "matador/object/attribute_definition_generator.hpp" + namespace matador::query { class query_create_intermediate : public query_intermediate @@ -14,11 +16,10 @@ public: executable_query table(const sql::table &table, std::initializer_list columns); executable_query table(const sql::table &table, const std::vector &columns); - // template - // executable_query table(const sql::table &table, const sql::schema &schema) - // { - // return this->table(table, column_definition_generator::generate(schema)); - // } + template + executable_query table(const sql::table &table, const object::schema &schema) { + return this->table(table, object::attribute_definition_generator::generate(schema)); + } }; } diff --git a/include/matador/query/intermediates/query_insert_intermediate.hpp b/include/matador/query/intermediates/query_insert_intermediate.hpp index b3d53b6..e397404 100644 --- a/include/matador/query/intermediates/query_insert_intermediate.hpp +++ b/include/matador/query/intermediates/query_insert_intermediate.hpp @@ -2,20 +2,21 @@ #define QUERY_INSERT_INTERMEDIATE_HPP #include "matador/query/intermediates/query_intermediate.hpp" +#include "matador/query/intermediates/query_into_intermediate.hpp" + +#include "matador/sql/column_generator.hpp" namespace matador::query { -class query_into_intermediate; - class query_insert_intermediate : public query_intermediate { public: query_insert_intermediate(); - // template - // query_into_intermediate into(const sql::table &table, const sql::schema &schema) { - // return into(table, column_generator::generate(schema)); - // } + template + query_into_intermediate into(const sql::table &table, const object::schema &schema) { + return into(table, sql::column_generator::generate(schema)); + } query_into_intermediate into(const sql::table &table, std::initializer_list columns); query_into_intermediate into(const sql::table &table, std::vector &&columns); query_into_intermediate into(const sql::table &table, const std::vector &column_names); diff --git a/include/matador/query/intermediates/query_into_intermediate.hpp b/include/matador/query/intermediates/query_into_intermediate.hpp index 340470d..5c47f15 100644 --- a/include/matador/query/intermediates/query_into_intermediate.hpp +++ b/include/matador/query/intermediates/query_into_intermediate.hpp @@ -9,15 +9,6 @@ namespace matador::query { -// template < class Type > -// std::vector as_placeholder(const Type &obj) -// { - // placeholder_generator generator; - // access::process(generator, obj); - - // return generator.placeholder_values; -// \} - class query_into_intermediate : public query_intermediate { public: @@ -25,16 +16,15 @@ public: executable_query values(std::initializer_list> values); executable_query values(std::vector> &&values); - // template - // executable_query values() - // { - // Type obj; - // return values(std::move(as_placeholder(obj))); - // } + executable_query values(std::vector &&values); template - executable_query values(const Type &obj) - { - return values(std::move(value_extractor::extract(obj))); + executable_query values() { + Type obj; + return values(obj); + } + template + executable_query values(const Type &obj) { + return values(value_extractor::extract(obj)); } }; diff --git a/include/matador/query/intermediates/query_update_intermediate.hpp b/include/matador/query/intermediates/query_update_intermediate.hpp index 99b9d96..208526f 100644 --- a/include/matador/query/intermediates/query_update_intermediate.hpp +++ b/include/matador/query/intermediates/query_update_intermediate.hpp @@ -11,31 +11,19 @@ namespace matador::query { -// template < class Type > -// std::vector as_key_value_placeholder(const Type &obj) -// { -// placeholder_key_value_generator generator; -// access::process(generator, obj); -// -// return generator.placeholder_values; -// } - -class query_update_intermediate : public query_intermediate -{ +class query_update_intermediate : public query_intermediate { public: explicit query_update_intermediate(const sql::table& table); query_set_intermediate set(std::initializer_list columns); query_set_intermediate set(std::vector &&columns); - // template - // query_set_intermediate set() - // { - // Type obj; - // return set(std::move(as_key_value_placeholder(obj))); - // } template - query_set_intermediate set(const Type &obj) - { + query_set_intermediate set() { + Type obj; + return set(obj); + } + template + query_set_intermediate set(const Type &obj) { return set(key_value_generator::generate(obj)); } }; diff --git a/include/matador/query/query.hpp b/include/matador/query/query.hpp index 182b774..257b43c 100644 --- a/include/matador/query/query.hpp +++ b/include/matador/query/query.hpp @@ -3,6 +3,8 @@ #include "matador/query/query_intermediates.hpp" +#include "matador/sql/column_generator.hpp" + namespace matador::sql { class connection; } @@ -22,10 +24,10 @@ public: [[nodiscard]] static query_select_intermediate select(const std::vector& columns); [[nodiscard]] static query_select_intermediate select(const std::vector &column_names); [[nodiscard]] static query_select_intermediate select(std::vector columns, std::initializer_list additional_columns); - // template - // [[nodiscard]] static query_select_intermediate select(const sql::schema &schema) { - // return select(sql::column_generator::generate(schema)); - // } + template + [[nodiscard]] static query_select_intermediate select(const object::schema &schema) { + return select(sql::column_generator::generate(schema)); + } [[nodiscard]] static query_insert_intermediate insert(); [[nodiscard]] static query_update_intermediate update(const sql::table &table); [[nodiscard]] static query_delete_intermediate remove(); diff --git a/include/matador/query/value_extractor.hpp b/include/matador/query/value_extractor.hpp index 4ac88d2..46567a6 100644 --- a/include/matador/query/value_extractor.hpp +++ b/include/matador/query/value_extractor.hpp @@ -17,8 +17,7 @@ private: public: template < class Type > - static std::vector extract(const Type &type) - { + static std::vector extract(const Type &type) { std::vector values; value_extractor gen(values); access::process(gen, type); diff --git a/include/matador/sql/connection.hpp b/include/matador/sql/connection.hpp index a76564f..8969b99 100644 --- a/include/matador/sql/connection.hpp +++ b/include/matador/sql/connection.hpp @@ -1,8 +1,9 @@ #ifndef QUERY_CONNECTION_HPP #define QUERY_CONNECTION_HPP -#include "matador/sql/abstract_sql_logger.hpp" #include "matador/object/attribute_definition.hpp" + +#include "matador/sql/abstract_sql_logger.hpp" #include "matador/sql/connection_info.hpp" #include "matador/sql/executor.hpp" #include "matador/sql/statement.hpp" @@ -51,7 +52,7 @@ public: * * @param x The connection to copy move */ - connection(connection &&x) noexcept = default; + connection(connection &&x) noexcept; /** * Assigns moves from the given connection * diff --git a/include/matador/sql/connection_info.hpp b/include/matador/sql/connection_info.hpp index 68192e1..4442402 100644 --- a/include/matador/sql/connection_info.hpp +++ b/include/matador/sql/connection_info.hpp @@ -29,8 +29,7 @@ struct connection_info { std::string driver{}; /**< Driver to use. This is used by th mssql/odbc backends. */ template < class Operator > - void process(Operator &op) - { + void process(Operator &op) { namespace field = matador::access; field::attribute(op, "type", type); field::attribute(op, "user", user); diff --git a/include/matador/sql/connection_pool.hpp b/include/matador/sql/connection_pool.hpp index c829250..2911fb2 100644 --- a/include/matador/sql/connection_pool.hpp +++ b/include/matador/sql/connection_pool.hpp @@ -81,7 +81,8 @@ public: connection_repo_.emplace_back(count, info_); auto &conn = connection_repo_.back(); idle_connections_.emplace(conn.first, &conn); - conn.second.open(); + // Todo: handle result + std::ignore = conn.second.open(); --count; } } diff --git a/include/matador/sql/interface/statement_impl.hpp b/include/matador/sql/interface/statement_impl.hpp index a7e5e82..5d168b3 100644 --- a/include/matador/sql/interface/statement_impl.hpp +++ b/include/matador/sql/interface/statement_impl.hpp @@ -33,8 +33,7 @@ public: } template < class Type > - void bind(const size_t pos, Type &val) - { + void bind(const size_t pos, Type &val) { utils::data_type_traits::bind_value(binder(), adjust_index(pos), val); } diff --git a/source/core/utils/library.cpp b/source/core/utils/library.cpp index a986e72..75b6d86 100644 --- a/source/core/utils/library.cpp +++ b/source/core/utils/library.cpp @@ -9,13 +9,11 @@ library::library(std::string lib) : lib_(std::move(lib)) {} -library::~library() -{ +library::~library() { unload(); } -bool library::load() -{ +bool library::load() { auto path = os::getenv("MATADOR_BACKENDS_PATH"); #if defined(_MSC_VER) || defined(__MINGW32__) auto cookie = AddDllDirectory(std::wstring(path.begin(), path.end()).c_str()); diff --git a/source/orm/CMakeLists.txt b/source/orm/CMakeLists.txt index 71a8c2c..c432dd9 100644 --- a/source/orm/CMakeLists.txt +++ b/source/orm/CMakeLists.txt @@ -40,6 +40,7 @@ add_library(matador-orm STATIC ../../include/matador/query/query_intermediates.hpp ../../include/matador/query/query_part.hpp ../../include/matador/query/value_extractor.hpp + ../../include/matador/orm/error_code.hpp ../../include/matador/orm/session.hpp ../../include/matador/orm/session_query_builder.hpp ../../include/matador/sql/abstract_sql_logger.hpp @@ -104,6 +105,7 @@ add_library(matador-orm STATIC query/query_part.cpp query/query_update_intermediate.cpp query/value_extractor.cpp + orm/error_code.cpp orm/session.cpp orm/session_query_builder.cpp sql/backend_provider.cpp diff --git a/source/orm/orm/error_code.cpp b/source/orm/orm/error_code.cpp new file mode 100644 index 0000000..febd8d9 --- /dev/null +++ b/source/orm/orm/error_code.cpp @@ -0,0 +1,39 @@ +#include "matador/orm/error_code.hpp" + +namespace matador::orm { + +const char * orm_category_impl::name() const noexcept { + return "orm"; +} + +std::string orm_category_impl::message(const int ev) const { + switch (static_cast(ev)) { + case error_code::Ok: + return "OK"; + case error_code::NoConnectionAvailable: + return "No connection available"; + case error_code::UnknownType: + return "Unknown type"; + case error_code::FailedToBuildQuery: + return "Failed to build query"; + case error_code::FailedToFindObject: + return "Failed to find object"; + default: + return "Unknown error"; + } +} + +const std::error_category & orm_category() { + static orm_category_impl instance; + return instance; +} + +std::error_code make_error_code(error_code e) { + return {static_cast(e), orm_category()}; +} + +std::error_condition make_error_condition(error_code e) { + return {static_cast(e), orm_category()}; +} + +} \ No newline at end of file diff --git a/source/orm/orm/session.cpp b/source/orm/orm/session.cpp index 9812230..597aff2 100644 --- a/source/orm/orm/session.cpp +++ b/source/orm/orm/session.cpp @@ -8,6 +8,10 @@ namespace matador::orm { +utils::error make_error( const error_code ec, const std::string& msg ) { + return utils::error(ec, msg); +} + session::session(sql::connection_pool &pool) : pool_(pool) , dialect_(sql::backend_provider::instance().connection_dialect(pool_.info().type)) @@ -26,8 +30,7 @@ utils::result session::create_schema() const { return utils::ok(); } -void session::drop_table(const std::string &table_name) -{ +void session::drop_table(const std::string &table_name) const { auto c = pool_.acquire(); if (!c.valid()) { throw std::logic_error("no database connection available"); @@ -114,7 +117,7 @@ const class sql::dialect &session::dialect() const // return c->fetch(sql); // } -query::fetchable_query session::build_select_query(sql::connection_ptr &conn, entity_query_data &&data) { +query::fetchable_query session::build_select_query(entity_query_data &&data) { return query::query::select(data.columns) .from(data.root_table_name) .join_left(data.joins) diff --git a/source/orm/query/intermediates/query_into_intermediate.cpp b/source/orm/query/intermediates/query_into_intermediate.cpp index 2f14235..2e85e79 100644 --- a/source/orm/query/intermediates/query_into_intermediate.cpp +++ b/source/orm/query/intermediates/query_into_intermediate.cpp @@ -14,4 +14,11 @@ executable_query query_into_intermediate::values(std::vector&& values ) { + std::vector> transformed_values; + for (auto&& val : values) { + transformed_values.emplace_back(val); + } + return this->values(std::move(transformed_values)); +} } // namespace matador::query diff --git a/source/orm/sql/connection.cpp b/source/orm/sql/connection.cpp index 5b602d4..5dd2386 100644 --- a/source/orm/sql/connection.cpp +++ b/source/orm/sql/connection.cpp @@ -45,6 +45,11 @@ connection &connection::operator=(const connection &x) { return *this; } +connection::connection( connection&& x ) noexcept +: connection_info_(std::move(x.connection_info_)) +, connection_(std::move(x.connection_)) +, logger_(std::move(x.logger_)) {} + connection & connection::operator=(connection &&x) noexcept { connection_info_ = std::move(x.connection_info_); connection_ = std::move(x.connection_); diff --git a/test/backends/ColorEnumTraits.cpp b/test/backends/ColorEnumTraits.cpp index f94dc23..097e78c 100644 --- a/test/backends/ColorEnumTraits.cpp +++ b/test/backends/ColorEnumTraits.cpp @@ -5,9 +5,7 @@ namespace matador::utils { -void data_type_traits::read_value(attribute_reader &reader, const char *id, size_t index, - test::Color &value) -{ +void data_type_traits::read_value(attribute_reader &reader, const char *id, const size_t index, test::Color &value) { std::string enum_string; reader.read_value(id, index, enum_string, 64); if (const auto enum_opt = color_enum.to_enum(enum_string)) { @@ -15,8 +13,7 @@ void data_type_traits::read_value(attribute_reader &reader, c } } -void data_type_traits::bind_value(attribute_writer &binder, const size_t index, const test::Color &value) -{ +void data_type_traits::bind_value(attribute_writer &binder, const size_t index, const test::Color &value) { binder.write_value(index, color_enum.to_string(value)); } diff --git a/test/backends/QueryBasicTest.cpp b/test/backends/QueryBasicTest.cpp index 11b29dd..681ca05 100644 --- a/test/backends/QueryBasicTest.cpp +++ b/test/backends/QueryBasicTest.cpp @@ -1,13 +1,15 @@ #include "catch2/catch_test_macros.hpp" #include "catch2/matchers/catch_matchers_string.hpp" -#include "matador/sql/column_definition.hpp" +#include "matador/object/attribute_definition.hpp" +#include "matador/object/schema.hpp" + #include "matador/sql/connection.hpp" +#include "matador/sql/column_generator.hpp" + #include "matador/query/condition.hpp" #include "matador/query/query.hpp" -#include "matador/sql/schema.hpp" - #include "matador/utils/basic_types.hpp" #include "matador/utils/string.hpp" @@ -15,12 +17,15 @@ #include "QueryFixture.hpp" +#include + using namespace matador::test; using namespace matador::sql; +using namespace matador::object; using namespace matador::query; TEST_CASE_METHOD( QueryFixture, "Insert and select basic datatypes", "[query][datatypes]" ) { - schema.attach("types"); + REQUIRE(schema.attach("types")); auto res = query::create() .table("types", schema) .execute(db); @@ -30,18 +35,15 @@ TEST_CASE_METHOD( QueryFixture, "Insert and select basic datatypes", "[query][da float float_value = 2.44557f; double double_value = 11111.23433345; - char cval = 'c'; + int8_t cval = 'c'; short sval = (std::numeric_limits::min)(); int ival = (std::numeric_limits::min)(); - long lval = (std::numeric_limits::min)(); long long llval = (std::numeric_limits::max)(); unsigned char ucval = (std::numeric_limits::max)(); unsigned short usval = (std::numeric_limits::max)(); unsigned int uival = (std::numeric_limits::max)(); - unsigned long ulval = (std::numeric_limits::max)(); unsigned long long ullval = (std::numeric_limits::max)(); if (db.type() == "sqlite" || db.type() == "postgres") { - ulval = (std::numeric_limits::max)(); ullval = (std::numeric_limits::max)(); } bool bval = true; @@ -55,19 +57,19 @@ TEST_CASE_METHOD( QueryFixture, "Insert and select basic datatypes", "[query][da "eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. " "At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd " "gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."; - matador::date date_val(15, 3, 2015); - auto time_val = matador::time(2015, 3, 15, 13, 56, 23, 123); + // matador::date date_val(15, 3, 2015); + // auto time_val = matador::time(2015, 3, 15, 13, 56, 23, 123); matador::utils::blob blob_val {1,2,3,4,5,6,7,8}; types t { 1, - cval, sval, ival, lval, llval, - ucval, usval, uival, ulval, ullval, + cval, sval, ival, llval, + ucval, usval, uival, ullval, float_value, double_value, bval, "Armer schwarzer Kater", strval, varcharval, - date_val, time_val, + // date_val, time_val, blob_val }; @@ -88,12 +90,10 @@ TEST_CASE_METHOD( QueryFixture, "Insert and select basic datatypes", "[query][da REQUIRE((*result)->char_ == cval); REQUIRE((*result)->short_ == sval); REQUIRE((*result)->int_ == ival); - REQUIRE((*result)->long_ == lval); REQUIRE((*result)->long64_ == llval); REQUIRE((*result)->unsigned_char_ == ucval); REQUIRE((*result)->unsigned_short_ == usval); REQUIRE((*result)->unsigned_int_ == uival); - REQUIRE((*result)->unsigned_long_ == ulval); REQUIRE((*result)->unsigned_long64_ == ullval); REQUIRE((*result)->float_ == float_value); REQUIRE((*result)->double_ == double_value); @@ -101,8 +101,8 @@ TEST_CASE_METHOD( QueryFixture, "Insert and select basic datatypes", "[query][da REQUIRE((*result)->bool_ == bval); REQUIRE((*result)->varchar_ == varcharval); REQUIRE((*result)->string_ == strval); - REQUIRE((*result)->date_ == date_val); - REQUIRE((*result)->time_ == time_val); + // REQUIRE((*result)->date_ == date_val); + // REQUIRE((*result)->time_ == time_val); REQUIRE((*result)->binary_ == blob_val); } @@ -121,7 +121,7 @@ TEST_CASE_METHOD( QueryFixture, "Test quoted identifier", "[query][quotes][ident // check table description std::vector column_names = { "from", "to"}; - std::vector types = {matador::data_type::type_varchar, matador::data_type::type_varchar}; + std::vector types = {matador::utils::basic_type::type_varchar, matador::utils::basic_type::type_varchar}; const auto columns = db.describe("quotes"); REQUIRE(columns.is_ok()); @@ -194,7 +194,7 @@ TEST_CASE_METHOD( QueryFixture, "Test quoted column names", "[query][quotes][col for (const auto &col : *columns) { REQUIRE(col.name() == name); - REQUIRE(col.type() == matador::data_type::type_varchar); + REQUIRE(col.type() == matador::utils::basic_type::type_varchar); } res = query::drop() @@ -278,7 +278,7 @@ TEST_CASE_METHOD(QueryFixture, "Test quoted literals", "[query][quotes][literals TEST_CASE_METHOD(QueryFixture, "Test describe table", "[query][describe][table]") { using namespace matador::sql; - schema.attach("types"); + REQUIRE(schema.attach("types")); const auto res = query::create() .table("types", schema) .execute(db); @@ -293,29 +293,30 @@ TEST_CASE_METHOD(QueryFixture, "Test describe table", "[query][describe][table]" "val_char", "val_float", "val_double", "val_short", "val_int", "val_long", "val_long_long", "val_unsigned_char", "val_unsigned_short", "val_unsigned_int", "val_unsigned_long", "val_unsigned_long_long", - "val_bool", "val_cstr", "val_string", "val_varchar", "val_date", "val_time", + "val_bool", "val_cstr", "val_string", "val_varchar", + // "val_date", "val_time", "val_binary"}; - const std::vector> type_check = { - [](const column_definition &cf) { return cf.is_integer(); }, - [](const column_definition &cf) { return cf.is_integer(); }, - [](const column_definition &cf) { return cf.is_floating_point(); }, - [](const column_definition &cf) { return cf.is_floating_point(); }, - [](const column_definition &cf) { return cf.is_integer(); }, - [](const column_definition &cf) { return cf.is_integer(); }, - [](const column_definition &cf) { return cf.is_integer(); }, - [](const column_definition &cf) { return cf.is_integer(); }, - [](const column_definition &cf) { return cf.is_integer(); }, - [](const column_definition &cf) { return cf.is_integer(); }, - [](const column_definition &cf) { return cf.is_integer(); }, - [](const column_definition &cf) { return cf.is_integer(); }, - [](const column_definition &cf) { return cf.is_integer(); }, - [](const column_definition &cf) { return cf.is_bool(); }, - [](const column_definition &cf) { return cf.is_varchar(); }, - [](const column_definition &cf) { return cf.is_string(); }, - [](const column_definition &cf) { return cf.is_varchar(); }, - [](const column_definition &cf) { return cf.is_date(); }, - [](const column_definition &cf) { return cf.is_time(); }, - [](const column_definition &cf) { return cf.is_blob(); } + const std::vector> type_check = { + [](const attribute_definition &cf) { return cf.is_integer(); }, + [](const attribute_definition &cf) { return cf.is_integer(); }, + [](const attribute_definition &cf) { return cf.is_floating_point(); }, + [](const attribute_definition &cf) { return cf.is_floating_point(); }, + [](const attribute_definition &cf) { return cf.is_integer(); }, + [](const attribute_definition &cf) { return cf.is_integer(); }, + [](const attribute_definition &cf) { return cf.is_integer(); }, + [](const attribute_definition &cf) { return cf.is_integer(); }, + [](const attribute_definition &cf) { return cf.is_integer(); }, + [](const attribute_definition &cf) { return cf.is_integer(); }, + [](const attribute_definition &cf) { return cf.is_integer(); }, + [](const attribute_definition &cf) { return cf.is_integer(); }, + [](const attribute_definition &cf) { return cf.is_integer(); }, + [](const attribute_definition &cf) { return cf.is_bool(); }, + [](const attribute_definition &cf) { return cf.is_varchar(); }, + [](const attribute_definition &cf) { return cf.is_string(); }, + [](const attribute_definition &cf) { return cf.is_varchar(); }, + // [](const attribute_definition &cf) { return cf.is_date(); }, + // [](const attribute_definition &cf) { return cf.is_time(); }, + [](const attribute_definition &cf) { return cf.is_blob(); } }; const auto &cols = columns.value(); @@ -341,7 +342,7 @@ struct pk { matador::access::attribute(op, "name", name, 255); } - unsigned long id{}; + uint32_t id{}; std::string name; }; } @@ -350,7 +351,7 @@ TEST_CASE_METHOD(QueryFixture, "Test primary key", "[query][primary key]") { using namespace matador::test::temporary; using namespace matador::sql; - schema.attach("pk"); + REQUIRE(schema.attach("pk")); auto res = query::create() .table("pk", schema) .execute(db); @@ -379,7 +380,7 @@ TEST_CASE_METHOD(QueryFixture, "Test primary key prepared", "[query][primary key using namespace matador::test::temporary; using namespace matador::sql; - schema.attach("pk"); + REQUIRE(schema.attach("pk")); auto res = query::create() .table("pk", schema) .execute(db); @@ -393,8 +394,9 @@ TEST_CASE_METHOD(QueryFixture, "Test primary key prepared", "[query][primary key .into("pk", column_generator::generate(schema)) .values() .prepare(db); +REQUIRE(stmt); - res = stmt.bind(pk1) + res = stmt->bind(pk1) .execute(); REQUIRE(res.is_ok()); REQUIRE(*res == 1); @@ -402,150 +404,151 @@ TEST_CASE_METHOD(QueryFixture, "Test primary key prepared", "[query][primary key stmt = query::select(schema) .from("pk") .prepare(db); + REQUIRE(stmt); - auto row = stmt.fetch_one(); + auto row = stmt->fetch_one(); REQUIRE(row.is_ok()); REQUIRE(*row != nullptr); REQUIRE(row.value()->id > 0); REQUIRE(row.value()->name == "george"); } -namespace matador::test::temporary { -struct appointment -{ - unsigned long id{}; - std::string name; - matador::time time_point{}; - matador::date date_point{}; - - template < class Operator > - void process(Operator &op) - { - matador::access::primary_key(op, "id", id); - matador::access::attribute(op, "name", name, 255); - matador::access::attribute(op, "time_point", time_point); - matador::access::attribute(op, "date_point", date_point); - } -}; - -} -TEST_CASE_METHOD(QueryFixture, "Test select time and date", "[query][select][time]") { - using namespace matador::test::temporary; - using namespace matador::sql; - schema.attach("appointment"); - auto res = query::create() - .table("appointment", schema) - .execute(db); - REQUIRE(res.is_ok()); - REQUIRE(*res == 0); - tables_to_drop.emplace("appointment"); - - auto dinner = appointment{ 1, "dinner" }; - auto time_str = matador::utils::to_string(dinner.time_point); - auto date_str = matador::utils::to_string(dinner.date_point); - - res = query::insert() - .into("appointment", column_generator::generate(schema)) - .values(dinner) - .execute(db); - REQUIRE(res.is_ok()); - REQUIRE(*res == 1); - - auto row = query::select(schema) - .from("appointment") - .fetch_one(db); - REQUIRE(row.is_ok()); - - REQUIRE(*row != nullptr); - REQUIRE(matador::utils::to_string(row.value()->time_point) == time_str); - REQUIRE(matador::utils::to_string(row.value()->date_point) == date_str); -} - -TEST_CASE_METHOD(QueryFixture, "Test null column", "[query][select][null]") { - using namespace matador::sql; - - auto res = query::create() - .table("person", { - make_pk_column("id"), - make_column("first_name", 255, null_option::NULLABLE), - make_column("last_name", 255, null_option::NULLABLE) - }) - .execute(db); - REQUIRE(res.is_ok()); - REQUIRE(*res == 0); - tables_to_drop.emplace("person"); - - res = query::insert() - .into("person", {"id", "first_name"}) - .values({1, "george"}) - .execute(db); - REQUIRE(res.is_ok()); - REQUIRE(*res == 1); - - res = query::insert() - .into("person", {"id", "last_name"}) - .values({2, "clooney"}) - .execute(db); - REQUIRE(res.is_ok()); - REQUIRE(*res == 1); - - auto result = query::select({"id", "first_name", "last_name"}) - .from("person") - .fetch_all(db); - REQUIRE(result.is_ok()); - - std::vector expected_first_names{"george", ""}; - std::vector expected_last_names{"", "clooney"}; - size_t index{0}; - for (const auto& row : *result) { - auto first_name = row.at("first_name"); - auto last_name = row.at("last_name"); - std::cout << "first name " << first_name.value() << " last name " << last_name.value() << std::endl; - REQUIRE(first_name == expected_first_names[index]); - REQUIRE(last_name == expected_last_names[index++]); - } -} - -TEST_CASE_METHOD(QueryFixture, "Test null column prepared", "[query][select][null][prepared]") { - using namespace matador::sql; - - auto res = query::create() - .table("person", { - make_pk_column("id"), - make_column("first_name", 255, null_option::NULLABLE), - make_column("last_name", 255, null_option::NULLABLE) - }) - .execute(db); - REQUIRE(res.is_ok()); - REQUIRE(*res == 0); - tables_to_drop.emplace("person"); - - res = query::insert() - .into("person", {"id", "first_name"}) - .values({1, "george"}) - .execute(db); - REQUIRE(res.is_ok()); - REQUIRE(*res == 1); - - res = query::insert() - .into("person", {"id", "last_name"}) - .values({2, "clooney"}) - .execute(db); - REQUIRE(res.is_ok()); - REQUIRE(*res == 1); - - auto result = query::select({"id", "first_name", "last_name"}) - .from("person") - .fetch_all(db); - REQUIRE(result.is_ok()); - - std::vector expected_first_names{"george", ""}; - std::vector expected_last_names{"", "clooney"}; - size_t index{0}; - for (const auto& row : *result) { - auto first_name = row.at("first_name").as(); - auto last_name = row.at("last_name").as(); - REQUIRE(first_name == expected_first_names[index]); - REQUIRE(last_name == expected_last_names[index++]); - } -} \ No newline at end of file +// namespace matador::test::temporary { +// struct appointment +// { +// unsigned long id{}; +// std::string name; +// matador::time time_point{}; +// matador::date date_point{}; +// +// template < class Operator > +// void process(Operator &op) +// { +// matador::access::primary_key(op, "id", id); +// matador::access::attribute(op, "name", name, 255); +// matador::access::attribute(op, "time_point", time_point); +// matador::access::attribute(op, "date_point", date_point); +// } +// }; +// +// } +// TEST_CASE_METHOD(QueryFixture, "Test select time and date", "[query][select][time]") { +// using namespace matador::test::temporary; +// using namespace matador::sql; +// REQUIRE(schema.attach("appointment")); +// auto res = query::create() +// .table("appointment", schema) +// .execute(db); +// REQUIRE(res.is_ok()); +// REQUIRE(*res == 0); +// tables_to_drop.emplace("appointment"); +// +// auto dinner = appointment{ 1, "dinner" }; +// auto time_str = matador::utils::to_string(dinner.time_point); +// auto date_str = matador::utils::to_string(dinner.date_point); +// +// res = query::insert() +// .into("appointment", column_generator::generate(schema)) +// .values(dinner) +// .execute(db); +// REQUIRE(res.is_ok()); +// REQUIRE(*res == 1); +// +// auto row = query::select(schema) +// .from("appointment") +// .fetch_one(db); +// REQUIRE(row.is_ok()); +// +// REQUIRE(*row != nullptr); +// REQUIRE(matador::utils::to_string(row.value()->time_point) == time_str); +// REQUIRE(matador::utils::to_string(row.value()->date_point) == date_str); +// } +// +// TEST_CASE_METHOD(QueryFixture, "Test null column", "[query][select][null]") { +// using namespace matador::sql; +// +// auto res = query::create() +// .table("person", { +// make_pk_column("id"), +// make_column("first_name", 255, null_option::NULLABLE), +// make_column("last_name", 255, null_option::NULLABLE) +// }) +// .execute(db); +// REQUIRE(res.is_ok()); +// REQUIRE(*res == 0); +// tables_to_drop.emplace("person"); +// +// res = query::insert() +// .into("person", {"id", "first_name"}) +// .values({1, "george"}) +// .execute(db); +// REQUIRE(res.is_ok()); +// REQUIRE(*res == 1); +// +// res = query::insert() +// .into("person", {"id", "last_name"}) +// .values({2, "clooney"}) +// .execute(db); +// REQUIRE(res.is_ok()); +// REQUIRE(*res == 1); +// +// auto result = query::select({"id", "first_name", "last_name"}) +// .from("person") +// .fetch_all(db); +// REQUIRE(result.is_ok()); +// +// std::vector expected_first_names{"george", ""}; +// std::vector expected_last_names{"", "clooney"}; +// size_t index{0}; +// for (const auto& row : *result) { +// auto first_name = row.at("first_name"); +// auto last_name = row.at("last_name"); +// std::cout << "first name " << first_name.value() << " last name " << last_name.value() << std::endl; +// REQUIRE(first_name == expected_first_names[index]); +// REQUIRE(last_name == expected_last_names[index++]); +// } +// } +// +// TEST_CASE_METHOD(QueryFixture, "Test null column prepared", "[query][select][null][prepared]") { +// using namespace matador::sql; +// +// auto res = query::create() +// .table("person", { +// make_pk_column("id"), +// make_column("first_name", 255, null_option::NULLABLE), +// make_column("last_name", 255, null_option::NULLABLE) +// }) +// .execute(db); +// REQUIRE(res.is_ok()); +// REQUIRE(*res == 0); +// tables_to_drop.emplace("person"); +// +// res = query::insert() +// .into("person", {"id", "first_name"}) +// .values({1, "george"}) +// .execute(db); +// REQUIRE(res.is_ok()); +// REQUIRE(*res == 1); +// +// res = query::insert() +// .into("person", {"id", "last_name"}) +// .values({2, "clooney"}) +// .execute(db); +// REQUIRE(res.is_ok()); +// REQUIRE(*res == 1); +// +// auto result = query::select({"id", "first_name", "last_name"}) +// .from("person") +// .fetch_all(db); +// REQUIRE(result.is_ok()); +// +// std::vector expected_first_names{"george", ""}; +// std::vector expected_last_names{"", "clooney"}; +// size_t index{0}; +// for (const auto& row : *result) { +// auto first_name = row.at("first_name").as(); +// auto last_name = row.at("last_name").as(); +// REQUIRE(first_name == expected_first_names[index]); +// REQUIRE(last_name == expected_last_names[index++]); +// } +// } \ No newline at end of file diff --git a/test/backends/QueryFixture.cpp b/test/backends/QueryFixture.cpp index 8cc6efe..32f9b23 100644 --- a/test/backends/QueryFixture.cpp +++ b/test/backends/QueryFixture.cpp @@ -1,6 +1,8 @@ #include "QueryFixture.hpp" -#include "matador/sql/query.hpp" +#include "matador/query/query.hpp" + +#include "matador/sql/dialect.hpp" #include "catch2/catch_test_macros.hpp" @@ -10,7 +12,7 @@ QueryFixture::QueryFixture() : db(connection::dns) , schema(db.dialect().default_schema_name()) { - db.open(); + REQUIRE(db.open()); } QueryFixture::~QueryFixture() { @@ -37,7 +39,7 @@ void QueryFixture::check_table_not_exists(const std::string &table_name) const void QueryFixture::drop_table_if_exists(const std::string &table_name) const { const auto result = db.exists(table_name).and_then([&table_name, this](bool exists) { if (exists) { - if (sql::query::drop() + if (query::query::drop() .table(table_name) .execute(db).is_ok()) { this->check_table_not_exists(table_name); diff --git a/test/backends/QueryFixture.hpp b/test/backends/QueryFixture.hpp index 04dbe27..d1c84bf 100644 --- a/test/backends/QueryFixture.hpp +++ b/test/backends/QueryFixture.hpp @@ -21,8 +21,8 @@ public: protected: sql::connection db; - sql::schema schema; std::stack tables_to_drop; + object::schema schema; private: void drop_table_if_exists(const std::string &table_name) const; diff --git a/test/backends/QueryRecordTest.cpp b/test/backends/QueryRecordTest.cpp index 8751c57..bbf7619 100644 --- a/test/backends/QueryRecordTest.cpp +++ b/test/backends/QueryRecordTest.cpp @@ -1,9 +1,10 @@ #include #include "matador/sql/column.hpp" -#include "matador/sql/condition.hpp" #include "matador/sql/connection.hpp" -#include "matador/sql/query.hpp" + +#include "matador/query/condition.hpp" +#include "matador/query/query.hpp" #include "matador/utils/types.hpp" #include "matador/utils/string.hpp" @@ -13,6 +14,8 @@ #include #include +using namespace matador::object; +using namespace matador::query; using namespace matador::sql; using namespace matador::test; @@ -21,24 +24,22 @@ TEST_CASE_METHOD(QueryFixture, "Test all data types for record", "[query][record auto res = query::create() .table("types", { - make_pk_column("id"), - make_column("val_char"), - make_column("val_short"), - make_column("val_int"), - make_column("val_long"), - make_column("val_long_long"), - make_column("val_uchar"), - make_column("val_ushort"), - make_column("val_uint"), - make_column("val_ulong"), - make_column("val_ulong_long"), + make_pk_column("id"), + make_column("val_char"), + make_column("val_short"), + make_column("val_int"), + make_column("val_long_long"), + make_column("val_uchar"), + make_column("val_ushort"), + make_column("val_uint"), + make_column("val_ulong_long"), make_column("val_bool"), make_column("val_float"), make_column("val_double"), make_column("val_string"), make_column("val_varchar", 63), - make_column("val_date"), - make_column("val_time"), + // make_column("val_date"), + // make_column("val_time"), make_column("val_blob"), }) .execute(db); @@ -54,7 +55,8 @@ TEST_CASE_METHOD(QueryFixture, "Test all data types for record", "[query][record "val_bool", "val_float", "val_double", "val_string", "val_varchar", - "val_date", "val_time", "val_blob"}; + // "val_date", "val_time", + "val_blob"}; const auto fields = db.describe("types"); REQUIRE(fields.is_ok()); @@ -62,29 +64,27 @@ TEST_CASE_METHOD(QueryFixture, "Test all data types for record", "[query][record REQUIRE(std::find(cols.begin(), cols.end(), fld.name()) != cols.end()); } - unsigned long id{1}; - char c{-11}; - short s{-256}; - int i{-123456}; - long l{-9876543}; - long long ll{-987654321}; - unsigned char uc{13}; - unsigned short us{1024}; - unsigned int ui{654321}; - unsigned long ul{12345678}; - unsigned long long ull{1234567890}; + uint32_t id{1}; + int8_t c{-11}; + int16_t s{-256}; + int32_t i{-123456}; + int64_t ll{-987654321}; + uint8_t uc{13}; + uint16_t us{1024}; + uint32_t ui{654321}; + uint64_t ull{1234567890}; bool b{true}; float f{3.1415f}; double d{2.71828}; std::string str{"long text"}; std::string varchar{"good day"}; - auto md{matador::date()}; - auto mt{matador::time::now()}; + // auto md{matador::date()}; + // auto mt{matador::time::now()}; matador::utils::blob bin{0x01,0x02,0x03,0x04}; res = query::insert() .into("types", cols) - .values({id, c, s, i, l, ll, uc, us, ui, ul, ull, b, f, d, str, varchar, md, mt, bin}) + .values({id, c, s, i, ll, uc, us, ui, ull, b, f, d, str, varchar, /*md, mt, */bin}) .execute(db); REQUIRE(res.is_ok()); REQUIRE(res.value() == 1); @@ -96,24 +96,22 @@ TEST_CASE_METHOD(QueryFixture, "Test all data types for record", "[query][record REQUIRE(row.is_ok()); REQUIRE(row.value().has_value()); - REQUIRE(id == (*row)->at("id")); - REQUIRE(c == (*row)->at("val_char")); - REQUIRE(s == (*row)->at("val_short")); - REQUIRE(i == (*row)->at("val_int")); - REQUIRE(l == (*row)->at("val_long")); - REQUIRE(ll == (*row)->at("val_long_long")); - REQUIRE(uc == (*row)->at("val_uchar")); + REQUIRE(id == (*row)->at("id")); + REQUIRE(c == (*row)->at("val_char")); + REQUIRE(s == (*row)->at("val_short")); + REQUIRE(i == (*row)->at("val_int")); + REQUIRE(ll == (*row)->at("val_long_long")); + REQUIRE(uc == (*row)->at("val_uchar")); REQUIRE(us == (*row)->at("val_ushort")); REQUIRE(ui == (*row)->at("val_uint")); - REQUIRE(ul == (*row)->at("val_ulong")); - REQUIRE(ull == (*row)->at("val_ulong_long")); + REQUIRE(ull == (*row)->at("val_ulong_long")); REQUIRE((*row)->at("val_bool")); REQUIRE(f == (*row)->at("val_float")); REQUIRE(d == (*row)->at("val_double")); REQUIRE(str == (*row)->at("val_string")); REQUIRE(varchar == (*row)->at("val_varchar")); - REQUIRE(md == (*row)->at("val_date")); - REQUIRE(mt == (*row)->at("val_time")); + // REQUIRE(md == (*row)->at("val_date")); + // REQUIRE(mt == (*row)->at("val_time")); REQUIRE(bin == (*row)->at("val_blob")); } @@ -122,7 +120,7 @@ TEST_CASE_METHOD(QueryFixture, "Create and drop table statement", "[query][recor check_table_not_exists("person"); auto res = query::create() .table("person", { - make_pk_column("id"), + make_pk_column("id"), make_column("name", 255), make_column("age") }) @@ -146,7 +144,7 @@ TEST_CASE_METHOD(QueryFixture, "Create and drop table statement with foreign key { auto res = query::create() .table("airplane", { - make_pk_column("id"), + make_pk_column("id"), make_column("brand", 255), make_column("model", 255), }) @@ -159,8 +157,8 @@ TEST_CASE_METHOD(QueryFixture, "Create and drop table statement with foreign key res = query::create() .table("flight", { - make_pk_column("id"), - make_fk_column("airplane_id", "airplane", "id"), + make_pk_column("id"), + make_fk_column("airplane_id", "airplane", "id"), make_column("pilot_name", 255), }) .execute(db); @@ -191,7 +189,7 @@ TEST_CASE_METHOD(QueryFixture, "Execute insert record statement", "[query][recor { auto res = query::create() .table("person", { - make_pk_column("id"), + make_pk_column("id"), make_column("name", 255), make_column("age") }) @@ -230,7 +228,7 @@ TEST_CASE_METHOD(QueryFixture, "Execute insert record statement with foreign key { auto res = query::create() .table("airplane", { - make_pk_column("id"), + make_pk_column("id"), make_column("brand", 255), make_column("model", 255), }) @@ -241,8 +239,8 @@ TEST_CASE_METHOD(QueryFixture, "Execute insert record statement with foreign key res = query::create() .table("flight", { - make_pk_column("id"), - make_fk_column("airplane_id", "airplane", "id"), + make_pk_column("id"), + make_fk_column("airplane_id", "airplane", "id"), make_column("pilot_name", 255), }) .execute(db); @@ -250,7 +248,7 @@ TEST_CASE_METHOD(QueryFixture, "Execute insert record statement with foreign key REQUIRE(res.value() == 0); tables_to_drop.emplace("flight"); - std::vector> values_list{ + std::vector> values_list{ {1, "Airbus", "A380"}, {2, "Boeing", "707"}, {3, "Boeing", "747"} @@ -284,7 +282,7 @@ TEST_CASE_METHOD(QueryFixture, "Execute update record statement", "[query][recor { auto res = query::create() .table("person", { - make_pk_column("id"), + make_pk_column("id"), make_column("name", 255), make_column("age") }) @@ -333,7 +331,7 @@ TEST_CASE_METHOD(QueryFixture, "Execute select statement", "[query][record]") { auto res = query::create() .table("person", { - make_pk_column("id"), + make_pk_column("id"), make_column("name", 255), make_column("age") }) @@ -342,7 +340,7 @@ TEST_CASE_METHOD(QueryFixture, "Execute select statement", "[query][record]") REQUIRE(res.value() == 0); tables_to_drop.emplace("person"); - std::vector> values_list{ + std::vector> values_list{ {1, "george", 45}, {2, "jane", 32}, {3, "michael", 67}, @@ -389,7 +387,7 @@ TEST_CASE_METHOD(QueryFixture, "Execute select statement with order by", "[query { auto res = query::create() .table("person", { - make_pk_column("id"), + make_pk_column("id"), make_column("name", 255), make_column("age") }) @@ -398,7 +396,7 @@ TEST_CASE_METHOD(QueryFixture, "Execute select statement with order by", "[query REQUIRE(res.value() == 0); tables_to_drop.emplace("person"); - std::vector> values_list{ + std::vector> values_list{ {1, "george", 45}, {2, "jane", 32}, {3, "michael", 67}, @@ -432,7 +430,7 @@ TEST_CASE_METHOD(QueryFixture, "Execute select statement with group by and order { auto res = query::create() .table("person", { - make_pk_column("id"), + make_pk_column("id"), make_column("name", 255), make_column("age") }) @@ -441,7 +439,7 @@ TEST_CASE_METHOD(QueryFixture, "Execute select statement with group by and order REQUIRE(*res == 0); tables_to_drop.emplace("person"); - std::vector> values_list{ + std::vector> values_list{ {1, "george", 45}, {2, "jane", 45}, {3, "joe", 45}, @@ -482,7 +480,7 @@ TEST_CASE_METHOD(QueryFixture, "Execute delete statement", "[query][record]") { auto res = query::create() .table("person", { - make_pk_column("id"), + make_pk_column("id"), make_column("name", 255), make_column("age") }).execute(db); @@ -537,9 +535,9 @@ TEST_CASE_METHOD(QueryFixture, "Test quoted identifier record", "[query][record] // check table description std::vector columns = { "from", "to"}; - std::vector types = { - matador::data_type::type_varchar, - matador::data_type::type_varchar + std::vector types = { + matador::utils::basic_type::type_varchar, + matador::utils::basic_type::type_varchar }; auto fields = db.describe("quotes"); REQUIRE(fields.is_ok()); @@ -585,7 +583,7 @@ TEST_CASE_METHOD(QueryFixture, "Test create record", "[query][record][create]") check_table_not_exists("person"); auto res = query::create() .table("person", { - make_pk_column("id"), + make_pk_column("id"), make_column("name", 255), make_column("age") }) @@ -608,7 +606,7 @@ TEST_CASE_METHOD(QueryFixture, "Test insert record", "[query][record][insert]") check_table_not_exists("person"); auto res = query::create() .table("person", { - make_pk_column("id"), + make_pk_column("id"), make_column("name", 255), make_column("age") }) @@ -632,7 +630,7 @@ TEST_CASE_METHOD(QueryFixture, "Test insert record", "[query][record][insert]") REQUIRE(row.is_ok()); REQUIRE(row->has_value()); - REQUIRE((*row)->at("id").as() == 1); + REQUIRE((*row)->at("id").as() == 1); REQUIRE((*row)->at("name").as() == "hans"); REQUIRE((*row)->at("age").as() == 45); } @@ -641,7 +639,7 @@ TEST_CASE_METHOD(QueryFixture, "Test update record", "[query][record][update]") check_table_not_exists("person"); auto res = query::create() .table("person", { - make_pk_column("id"), + make_pk_column("id"), make_column("name", 255), make_column("age") }) @@ -665,7 +663,7 @@ TEST_CASE_METHOD(QueryFixture, "Test update record", "[query][record][update]") REQUIRE(row.is_ok()); REQUIRE(row->has_value()); - REQUIRE((*row)->at("id").as() == 1); + REQUIRE((*row)->at("id").as() == 1); REQUIRE((*row)->at("name").as() == "hans"); REQUIRE((*row)->at("age").as() == 45); @@ -682,7 +680,7 @@ TEST_CASE_METHOD(QueryFixture, "Test update record", "[query][record][update]") REQUIRE(row.is_ok()); REQUIRE(row->has_value()); - REQUIRE((*row)->at("id").as() == 1); + REQUIRE((*row)->at("id").as() == 1); REQUIRE((*row)->at("name").as() == "jane"); REQUIRE((*row)->at("age").as() == 47); } @@ -691,14 +689,15 @@ TEST_CASE_METHOD(QueryFixture, "Test prepared record statement", "[query][record check_table_not_exists("person"); auto stmt = query::create() .table("person", { - make_pk_column("id"), + make_pk_column("id"), make_column("name", 255), make_column("age") }) .prepare(db); + REQUIRE(stmt.is_ok()); tables_to_drop.emplace("person"); - auto res = stmt.execute(); + auto res = stmt->execute(); REQUIRE(res.is_ok()); REQUIRE(*res == 0); check_table_exists("person"); @@ -716,7 +715,7 @@ TEST_CASE_METHOD(QueryFixture, "Test scalar result", "[query][record][scalar][re check_table_not_exists("person"); auto res = query::create() .table("person", { - make_pk_column("id"), + make_pk_column("id"), }) .execute(db); REQUIRE(res.is_ok()); @@ -725,7 +724,7 @@ TEST_CASE_METHOD(QueryFixture, "Test scalar result", "[query][record][scalar][re check_table_exists("person"); tables_to_drop.emplace("person"); - std::vector ids({ 1,2,3,4 }); + std::vector ids({ 1,2,3,4 }); for(auto id : ids) { res = query::insert() @@ -740,33 +739,34 @@ TEST_CASE_METHOD(QueryFixture, "Test scalar result", "[query][record][scalar][re .from("person") .order_by("id"_col).asc() .prepare(db); + REQUIRE(stmt); - auto rows = stmt.fetch(); + auto rows = stmt->fetch(); REQUIRE(rows.is_ok()); size_t index{0}; for (const auto &row : *rows) { - REQUIRE(row.at("id").as() == ids[index]); + REQUIRE(row.at("id").as() == ids[index]); ++index; } REQUIRE(index == 4); - stmt.reset(); + stmt->reset(); - rows = stmt.fetch(); + rows = stmt->fetch(); REQUIRE(rows.is_ok()); index = 0; for (const auto &row : *rows) { - REQUIRE(row.at("id").as() == ids[index]); + REQUIRE(row.at("id").as() == ids[index]); ++index; } REQUIRE(index == 4); - stmt.reset(); + stmt->reset(); - auto row = stmt.fetch_one(); + auto row = stmt->fetch_one(); REQUIRE(row.is_ok()); REQUIRE(row->has_value()); - REQUIRE(row.value()->at("id").as() == ids[0]); + REQUIRE(row.value()->at("id").as() == ids[0]); } \ No newline at end of file diff --git a/test/backends/QueryStatementTests.cpp b/test/backends/QueryStatementTests.cpp index fe384a5..d68a801 100644 --- a/test/backends/QueryStatementTests.cpp +++ b/test/backends/QueryStatementTests.cpp @@ -1,9 +1,10 @@ #include #include "matador/sql/column.hpp" -#include "matador/sql/condition.hpp" #include "matador/sql/connection.hpp" -#include "matador/sql/query.hpp" + +#include "matador/query/condition.hpp" +#include "matador/query/query.hpp" #include "models/person.hpp" @@ -13,15 +14,18 @@ #include using namespace matador::sql; +using namespace matador::object; +using namespace matador::query; using namespace matador::test; TEST_CASE_METHOD(QueryFixture, "Test create statement", "[query][statement][create]") { - schema.attach("person"); + REQUIRE(schema.attach("person")); auto stmt = query::create() .table("person", schema) .prepare(db); + REQUIRE(stmt); - auto res = stmt.execute(); + auto res = stmt->execute(); REQUIRE(res.is_ok()); REQUIRE(*res == 0); tables_to_drop.emplace("person"); @@ -39,12 +43,13 @@ TEST_CASE_METHOD(QueryFixture, "Test create statement", "[query][statement][crea TEST_CASE_METHOD(QueryFixture, "Test insert statement", "[query][statement][insert]") { using namespace matador::test; - schema.attach("person"); + REQUIRE(schema.attach("person")); auto stmt = query::create() .table("person", schema) .prepare(db); + REQUIRE(stmt); - auto res = stmt.execute(); + auto res = stmt->execute(); REQUIRE(res.is_ok()); REQUIRE(*res == 0); tables_to_drop.emplace("person"); @@ -57,8 +62,9 @@ TEST_CASE_METHOD(QueryFixture, "Test insert statement", "[query][statement][inse .into("person", schema) .values() .prepare(db); + REQUIRE(stmt); - res = stmt.bind(george) + res = stmt->bind(george) .execute(); REQUIRE(res.is_ok()); REQUIRE(*res == 1); @@ -79,12 +85,13 @@ TEST_CASE_METHOD(QueryFixture, "Test update statement", "[query][statement][upda using namespace matador::test; using namespace matador::utils; - schema.attach("person"); + REQUIRE(schema.attach("person")); auto stmt = query::create() .table("person", schema) .prepare(db); + REQUIRE(stmt); - auto res = stmt.execute(); + auto res = stmt->execute(); REQUIRE(res.is_ok()); REQUIRE(*res == 0); tables_to_drop.emplace("person"); @@ -97,8 +104,9 @@ TEST_CASE_METHOD(QueryFixture, "Test update statement", "[query][statement][upda .into("person", schema) .values() .prepare(db); + REQUIRE(stmt); - res = stmt.bind(george) + res = stmt->bind(george) .execute(); REQUIRE(res.is_ok()); REQUIRE(*res == 1); @@ -120,8 +128,9 @@ TEST_CASE_METHOD(QueryFixture, "Test update statement", "[query][statement][upda .set() .where("id"_col == _) .prepare(db); + REQUIRE(stmt); - res = stmt.bind(george) + res = stmt->bind(george) .bind(4, george.id) .execute(); REQUIRE(res.is_ok()); @@ -142,12 +151,13 @@ TEST_CASE_METHOD(QueryFixture, "Test update statement", "[query][statement][upda TEST_CASE_METHOD(QueryFixture, "Test delete statement", "[query][statement][delete]") { using namespace matador::test; - schema.attach("person"); + REQUIRE(schema.attach("person")); auto stmt = query::create() .table("person", schema) .prepare(db); + REQUIRE(stmt); - auto res = stmt.execute(); + auto res = stmt->execute(); REQUIRE(res.is_ok()); REQUIRE(*res == 0); tables_to_drop.emplace("person"); @@ -158,6 +168,7 @@ TEST_CASE_METHOD(QueryFixture, "Test delete statement", "[query][statement][dele .into("person", schema) .values() .prepare(db); + REQUIRE(stmt); std::vector peoples { {1,"george", 45, {1,2,3,4}}, @@ -167,20 +178,20 @@ TEST_CASE_METHOD(QueryFixture, "Test delete statement", "[query][statement][dele }; for (const auto &p : peoples) { - res = stmt.bind(p) + res = stmt->bind(p) .execute(); REQUIRE(res.is_ok()); REQUIRE(*res == 1); - stmt.reset(); + stmt->reset(); } auto select_stmt = query::select(schema) .from("person") .where("name"_col == matador::utils::_) .prepare(db); + REQUIRE(select_stmt); - auto rows = select_stmt - .bind(0, "jane") + auto rows = select_stmt->bind(0, "jane") .fetch(); REQUIRE(rows.is_ok()); @@ -196,30 +207,28 @@ TEST_CASE_METHOD(QueryFixture, "Test delete statement", "[query][statement][dele .from("person") .where("name"_col == matador::utils::_) .prepare(db); + REQUIRE(stmt); - res = stmt.bind(0, "jane") + res = stmt->bind(0, "jane") .execute(); REQUIRE(res.is_ok()); REQUIRE(*res == 1); - select_stmt.reset(); - auto row = select_stmt - .bind(0, "jane") + select_stmt->reset(); + auto row = select_stmt->bind(0, "jane") .fetch_one(); REQUIRE(row.is_ok()); REQUIRE(*row == nullptr); - stmt.reset(); - res = stmt - .bind(0, "merlin") + stmt->reset(); + res = stmt->bind(0, "merlin") .execute(); REQUIRE(res.is_ok()); REQUIRE(*res == 1); - select_stmt.reset(); - row = select_stmt - .bind(0, "merlin") + select_stmt->reset(); + row = select_stmt->bind(0, "merlin") .fetch_one(); REQUIRE(row.is_ok()); @@ -229,12 +238,13 @@ TEST_CASE_METHOD(QueryFixture, "Test delete statement", "[query][statement][dele TEST_CASE_METHOD(QueryFixture, "Test reuse prepared statement", "[query][statement][reuse]") { using namespace matador::test; - schema.attach("person"); + REQUIRE(schema.attach("person")); auto stmt = query::create() .table("person", schema) .prepare(db); + REQUIRE(stmt); - auto res = stmt.execute(); + auto res = stmt->execute(); REQUIRE(res.is_ok()); REQUIRE(*res == 0); tables_to_drop.emplace("person"); @@ -245,6 +255,7 @@ TEST_CASE_METHOD(QueryFixture, "Test reuse prepared statement", "[query][stateme .into("person", schema) .values() .prepare(db); + REQUIRE(stmt); std::vector peoples { {1,"george", 45, {1,2,3,4}}, @@ -254,18 +265,19 @@ TEST_CASE_METHOD(QueryFixture, "Test reuse prepared statement", "[query][stateme }; for (const auto &p : peoples) { - res = stmt.bind(p) + res = stmt->bind(p) .execute(); REQUIRE(res.is_ok()); REQUIRE(*res == 1); - stmt.reset(); + stmt->reset(); } stmt = query::select(schema) .from("person") .prepare(db); + REQUIRE(stmt); - auto rows = stmt.fetch(); + auto rows = stmt->fetch(); REQUIRE(rows.is_ok()); size_t index = 0; @@ -277,9 +289,9 @@ TEST_CASE_METHOD(QueryFixture, "Test reuse prepared statement", "[query][stateme ++index; } - stmt.reset(); + stmt->reset(); - rows = stmt.fetch(); + rows = stmt->fetch(); REQUIRE(rows.is_ok()); index = 0; diff --git a/test/backends/QueryTest.cpp b/test/backends/QueryTest.cpp index ed13bf0..bdb8123 100644 --- a/test/backends/QueryTest.cpp +++ b/test/backends/QueryTest.cpp @@ -2,6 +2,8 @@ #include "matador/object/attribute_definition.hpp" +#include "matador/sql/column_generator.hpp" + #include "matador/query/condition.hpp" #include "matador/query/query.hpp" @@ -12,13 +14,16 @@ #include "models/person.hpp" #include "models/recipe.hpp" +using namespace matador::object; +using namespace matador::query; using namespace matador::sql; using namespace matador::test; -using namespace matador::query; TEST_CASE_METHOD(QueryFixture, "Create table with foreign key relation", "[query][foreign][relation]") { - schema.attach("airplane"); - schema.attach("flight"); + auto result = schema.attach("airplane") + .and_then( [this] { return schema.attach("flight");} ); + REQUIRE(result.is_ok()); + auto res = query::create() .table("airplane", schema) .execute(db); @@ -38,9 +43,8 @@ TEST_CASE_METHOD(QueryFixture, "Create table with foreign key relation", "[query tables_to_drop.emplace("flight"); } -TEST_CASE_METHOD(QueryFixture, "Execute select statement with where clause", "[query][where]") -{ - schema.attach("person"); +TEST_CASE_METHOD(QueryFixture, "Execute select statement with where clause", "[query][where]") { + REQUIRE(schema.attach("person")); auto res = query::create() .table("person", schema) .execute(db); @@ -94,11 +98,10 @@ TEST_CASE_METHOD(QueryFixture, "Execute select statement with where clause", "[q } } -TEST_CASE_METHOD(QueryFixture, "Execute insert statement", "[query][insert]") -{ +TEST_CASE_METHOD(QueryFixture, "Execute insert statement", "[query][insert]") { auto res = query::create() .table("person", { - make_pk_column("id"), + make_pk_column("id"), make_column("name", 255), make_column("color", 63) }) @@ -127,7 +130,7 @@ TEST_CASE_METHOD(QueryFixture, "Execute insert statement", "[query][insert]") REQUIRE(i.size() == 3); REQUIRE(i.at(0).name() == "id"); REQUIRE(i.at(0).is_integer()); - REQUIRE(i.at(0).as() == 7); + REQUIRE(i.at(0).as() == 7); REQUIRE(i.at(1).name() == "name"); REQUIRE(i.at(1).is_varchar()); REQUIRE(i.at(1).as() == "george"); @@ -137,10 +140,11 @@ TEST_CASE_METHOD(QueryFixture, "Execute insert statement", "[query][insert]") } } -TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key", "[query][foreign]") -{ - schema.attach("airplane"); - schema.attach("flight"); +TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key", "[query][foreign]") { + auto result = schema.attach("airplane") + .and_then( [this] { return schema.attach("flight");} ); + REQUIRE(result.is_ok()); + auto res = query::create() .table("airplane", schema) .execute(db); @@ -159,10 +163,10 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key", "[query][for REQUIRE(db.exists("flight")); tables_to_drop.emplace("flight"); - std::vector> planes{ - matador::object_ptr(new airplane{1, "Airbus", "A380"}), - matador::object_ptr(new airplane{2, "Boeing", "707"}), - matador::object_ptr(new airplane{3, "Boeing", "747"}) + std::vector planes{ + object_ptr(new airplane{1, "Airbus", "A380"}), + object_ptr(new airplane{2, "Boeing", "707"}), + object_ptr(new airplane{3, "Boeing", "747"}) }; for (const auto &plane: planes) { @@ -194,15 +198,16 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key", "[query][for .fetch_one(db); REQUIRE(f.is_ok()); - REQUIRE(f.value()->at(0).as() == 4); - REQUIRE(f.value()->at(1).as() == 2); + REQUIRE(f.value()->at(0).as() == 4); + REQUIRE(f.value()->at(1).as() == 2); REQUIRE(f.value()->at(2).as() == "hans"); } -TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and join_left", "[query][foreign][join_left]") -{ - schema.attach("airplane"); - schema.attach("flight"); +TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and join_left", "[query][foreign][join_left]") { + auto result = schema.attach("airplane") + .and_then( [this] { return schema.attach("flight");} ); + REQUIRE(result.is_ok()); + auto res = query::create() .table("airplane", schema) .execute(db); @@ -221,10 +226,10 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and join_left" REQUIRE(db.exists("flight")); tables_to_drop.emplace("flight"); - std::vector> planes{ - matador::object_ptr(new airplane{1, "Airbus", "A380"}), - matador::object_ptr(new airplane{2, "Boeing", "707"}), - matador::object_ptr(new airplane{3, "Boeing", "747"}) + std::vector planes{ + object_ptr(new airplane{1, "Airbus", "A380"}), + object_ptr(new airplane{2, "Boeing", "707"}), + object_ptr(new airplane{3, "Boeing", "747"}) }; for (const auto &plane: planes) { @@ -241,11 +246,11 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and join_left" .fetch_value(db).value(); REQUIRE(count == 3); - std::vector> flights{ - matador::object_ptr(new flight{4, planes.at(0), "hans"}), - matador::object_ptr(new flight{5, planes.at(0), "otto"}), - matador::object_ptr(new flight{6, planes.at(1), "george"}), - matador::object_ptr(new flight{7, planes.at(2), "paul"}) + std::vector flights{ + object_ptr(new flight{4, planes.at(0), "hans"}), + object_ptr(new flight{5, planes.at(0), "otto"}), + object_ptr(new flight{6, planes.at(1), "george"}), + object_ptr(new flight{7, planes.at(2), "paul"}) }; for (const auto &f: flights) { @@ -262,35 +267,37 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and join_left" .fetch_one(db); REQUIRE(f.is_ok()); REQUIRE(f->has_value()); - REQUIRE(f.value()->at(0).as() == 4); - REQUIRE(f.value()->at(1).as() == 1); + REQUIRE(f.value()->at(0).as() == 4); + REQUIRE(f.value()->at(1).as() == 1); REQUIRE(f.value()->at(2).as() == "hans"); - auto result = query::select({"f.id", "ap.brand", "ap.model", "f.pilot_name"}) + auto select_result = query::select({"f.id", "ap.brand", "ap.model", "f.pilot_name"}) .from({"flight", "f"}) .join_left({"airplane", "ap"}) .on("f.airplane_id"_col == "ap.id"_col) .order_by("f.id").asc() .fetch_all(db); - REQUIRE(result.is_ok()); + REQUIRE(select_result.is_ok()); - std::vector> expected_result { + std::vector> expected_result { {4, "hans"}, {5, "otto"}, {6, "george"}, {7, "paul"} }; size_t index{0}; - for (const auto &r: *result) { + for (const auto &r: *select_result) { REQUIRE(r.size() == 4); - REQUIRE(r.at(0).as() == expected_result[index].first); + REQUIRE(r.at(0).as() == expected_result[index].first); REQUIRE(r.at(3).as() == expected_result[index++].second); } } TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and for single entity", "[query][join_left][find]") { - schema.attach("airplane"); - schema.attach("flight"); + auto result = schema.attach("airplane") + .and_then( [this] { return schema.attach("flight");} ); + REQUIRE(result.is_ok()); + auto res = query::create() .table("airplane", schema) .execute(db); @@ -309,10 +316,10 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and for single REQUIRE(db.exists("flight")); tables_to_drop.emplace("flight"); - std::vector> planes{ - matador::object_ptr(new airplane{1, "Airbus", "A380"}), - matador::object_ptr(new airplane{2, "Boeing", "707"}), - matador::object_ptr(new airplane{3, "Boeing", "747"}) + std::vector planes{ + object_ptr(new airplane{1, "Airbus", "A380"}), + object_ptr(new airplane{2, "Boeing", "707"}), + object_ptr(new airplane{3, "Boeing", "747"}) }; for (const auto &plane: planes) { @@ -331,11 +338,11 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and for single REQUIRE(count->has_value()); REQUIRE(count->value() == 3); - std::vector> flights{ - matador::object_ptr(new flight{4, planes.at(0), "hans"}), - matador::object_ptr(new flight{5, planes.at(0), "otto"}), - matador::object_ptr(new flight{6, planes.at(1), "george"}), - matador::object_ptr(new flight{7, planes.at(2), "paul"}) + std::vector flights{ + object_ptr(new flight{4, planes.at(0), "hans"}), + object_ptr(new flight{5, planes.at(0), "otto"}), + object_ptr(new flight{6, planes.at(1), "george"}), + object_ptr(new flight{7, planes.at(2), "paul"}) }; for (const auto &f: flights) { @@ -352,11 +359,11 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and for single .fetch_one(db); REQUIRE(f.is_ok()); REQUIRE(f->has_value()); - REQUIRE(f.value()->at(0).as() == 4); - REQUIRE(f.value()->at(1).as() == 1); + REQUIRE(f.value()->at(0).as() == 4); + REQUIRE(f.value()->at(1).as() == 1); REQUIRE(f.value()->at(2).as() == "hans"); - auto result = query::select({"f.id", "f.airplane_id", "ap.brand", "ap.model", "f.pilot_name"}) + auto select_result = query::select({"f.id", "f.airplane_id", "ap.brand", "ap.model", "f.pilot_name"}) .from({"flight", "f"}) .join_left({"airplane", "ap"}) .on("f.airplane_id"_col == "ap.id"_col) @@ -365,20 +372,22 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with foreign key and for single auto expected_flight = flights[0]; - REQUIRE(result.is_ok()); - REQUIRE(*result); - REQUIRE(result.value()->id == expected_flight->id); - REQUIRE(result.value()->pilot_name == expected_flight->pilot_name); - REQUIRE(result.value()->airplane.get()); - REQUIRE(result.value()->airplane->id == 1); - REQUIRE(result.value()->airplane->model == "A380"); - REQUIRE(result.value()->airplane->brand == "Airbus"); + REQUIRE(select_result.is_ok()); + REQUIRE(*select_result); + auto f1 = select_result.release(); + REQUIRE(f1->id == expected_flight->id); + REQUIRE(f1->pilot_name == expected_flight->pilot_name); + REQUIRE(f1->airplane.get()); + REQUIRE(f1->airplane->id == 1); + REQUIRE(f1->airplane->model == "A380"); + REQUIRE(f1->airplane->brand == "Airbus"); } TEST_CASE_METHOD(QueryFixture, "Select statement with many to many relationship", "[query][join][many_to_many]") { - schema.attach("recipes"); - schema.attach("ingredients"); - schema.attach("recipe_ingredients"); + auto result = schema.attach("recipes") + .and_then( [this] { return schema.attach("ingredients"); } ) + .and_then( [this] { return schema.attach("recipe_ingredients"); } ); + auto res = query::create() .table("recipes", schema) .execute(db); @@ -460,14 +469,14 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with many to many relationship" REQUIRE(*res == 1); } - auto result = query::select({"r.id", "r.name", "ri.ingredient_id"}) + auto select_result = query::select({"r.id", "r.name", "ri.ingredient_id"}) .from({"recipes", "r"}) .join_left({"recipe_ingredients", "ri"}) .on("r.id"_col == "ri.recipe_id"_col) .fetch_all(db); - REQUIRE(result.is_ok()); + REQUIRE(select_result.is_ok()); - std::vector> expected_result_one_join { + std::vector> expected_result_one_join { {7, "Apple Crumble", 1}, {7, "Apple Crumble", 4}, {7, "Apple Crumble", 5}, @@ -478,22 +487,22 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with many to many relationship" {9, "Fruit Salad", 3} }; size_t index{0}; - for (const auto &r: *result) { + for (const auto &r: *select_result) { REQUIRE(r.size() == 3); - REQUIRE(r.at(0).as().value() == std::get<0>(expected_result_one_join[index])); + REQUIRE(r.at(0).as().value() == std::get<0>(expected_result_one_join[index])); REQUIRE(r.at(1).as().value() == std::get<1>(expected_result_one_join[index])); - REQUIRE(r.at(2).as().value() == std::get<2>(expected_result_one_join[index])); + REQUIRE(r.at(2).as().value() == std::get<2>(expected_result_one_join[index])); ++index; } - result = query::select({"r.id", "r.name", "ri.ingredient_id", "i.name"}) + select_result = query::select({"r.id", "r.name", "ri.ingredient_id", "i.name"}) .from({"recipes", "r"}) .join_left({"recipe_ingredients", "ri"}).on("r.id"_col == "ri.recipe_id"_col) .join_left({"ingredients", "i"}).on("ri.ingredient_id"_col == "i.id"_col) .fetch_all(db); REQUIRE(result.is_ok()); - std::vector> expected_result_two_joins { + std::vector> expected_result_two_joins { {7, "Apple Crumble", 1, "Apple"}, {7, "Apple Crumble", 4, "Sugar"}, {7, "Apple Crumble", 5, "Flour"}, @@ -504,16 +513,16 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with many to many relationship" {9, "Fruit Salad", 3, "Pineapple"} }; index = 0; - for (const auto &r: *result) { + for (const auto &r: *select_result) { REQUIRE(r.size() == 4); - REQUIRE(r.at(0).as().value() == std::get<0>(expected_result_two_joins[index])); + REQUIRE(r.at(0).as().value() == std::get<0>(expected_result_two_joins[index])); REQUIRE(r.at(1).as().value() == std::get<1>(expected_result_two_joins[index])); - REQUIRE(r.at(2).as().value() == std::get<2>(expected_result_two_joins[index])); + REQUIRE(r.at(2).as().value() == std::get<2>(expected_result_two_joins[index])); REQUIRE(r.at(3).as().value() == std::get<3>(expected_result_two_joins[index])); ++index; } - result = query::select({"r.id", "r.name", "ri.ingredient_id", "i.name"}) + select_result = query::select({"r.id", "r.name", "ri.ingredient_id", "i.name"}) .from({"recipes", "r"}) .join_left({"recipe_ingredients", "ri"}).on("r.id"_col == "ri.recipe_id"_col) .join_left({"ingredients", "i"}).on("ri.ingredient_id"_col == "i.id"_col) @@ -522,11 +531,11 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with many to many relationship" REQUIRE(result.is_ok()); index = 3; - for (const auto &r: *result) { + for (const auto &r: *select_result) { REQUIRE(r.size() == 4); - REQUIRE(r.at(0).as().value() == std::get<0>(expected_result_two_joins[index])); + REQUIRE(r.at(0).as().value() == std::get<0>(expected_result_two_joins[index])); REQUIRE(r.at(1).as().value() == std::get<1>(expected_result_two_joins[index])); - REQUIRE(r.at(2).as().value() == std::get<2>(expected_result_two_joins[index])); + REQUIRE(r.at(2).as().value() == std::get<2>(expected_result_two_joins[index])); REQUIRE(r.at(3).as().value() == std::get<3>(expected_result_two_joins[index])); ++index; } diff --git a/test/backends/SessionTest.cpp b/test/backends/SessionTest.cpp index f6f33eb..0194c7e 100644 --- a/test/backends/SessionTest.cpp +++ b/test/backends/SessionTest.cpp @@ -7,52 +7,62 @@ #include "models/book.hpp" #include "models/flight.hpp" +#include + using namespace matador; +using namespace matador::object; using namespace matador::test; TEST_CASE_METHOD(SessionFixture, "Session relation test", "[session][relation]") { - ses.attach("airplanes"); - ses.attach("flights"); - ses.create_schema(); + const auto result = ses.attach("airplanes") + .and_then([this] { return ses.attach("flights"); } ) + .and_then([this] { return ses.create_schema(); } ); + REQUIRE(result.is_ok()); tables_to_drop.emplace("airplanes"); tables_to_drop.emplace("flights"); auto plane = ses.insert(1, "Boeing", "A380"); - auto f = ses.insert(2, plane, "sully"); + REQUIRE(plane.is_ok()); + auto f = ses.insert(2, *plane, "sully"); + REQUIRE(f.is_ok()); - const auto result = ses.find(2); - REQUIRE(result.is_ok()); - REQUIRE(result->get()->id == f->id); - REQUIRE(result->get()->pilot_name == f->pilot_name); - REQUIRE(result->get()->airplane); - REQUIRE(result->get()->airplane->id == plane->id); - REQUIRE(result->get()->airplane->brand == plane->brand); - REQUIRE(result->get()->airplane->model == plane->model); + const auto res = ses.find(2); + REQUIRE(res.is_ok()); + auto rf = *res; + REQUIRE(rf->id == (*f)->id); + REQUIRE(rf->pilot_name == (*f)->pilot_name); + REQUIRE(rf->airplane); + REQUIRE(rf->airplane->id == (*plane)->id); + REQUIRE(rf->airplane->brand == (*plane)->brand); + REQUIRE(rf->airplane->model == (*plane)->model); } TEST_CASE_METHOD(SessionFixture, "Use session to find object with id", "[session][find]") { - ses.attach("airplanes"); - ses.create_schema(); + const auto result = ses.attach("airplanes") + .and_then([this] { return ses.create_schema(); } ); + REQUIRE(result.is_ok()); tables_to_drop.emplace("airplanes"); auto a380 = ses.insert(1, "Boeing", "A380"); + REQUIRE(a380.is_ok()); - auto result = ses.find(2); + auto res = ses.find(2); REQUIRE(!result.is_ok()); - REQUIRE((result.err().ec() == sql::session_error_code::FailedToFindObject)); + REQUIRE((result.err().ec() == orm::error_code::FailedToFindObject)); - result = ses.find(1); + auto find_result = ses.find(1); - REQUIRE(result); - auto read_a380 = result.value(); - REQUIRE(a380->id == read_a380->id); + REQUIRE(find_result); + auto read_a380 = find_result.value(); + REQUIRE((*a380)->id == read_a380->id); } TEST_CASE_METHOD(SessionFixture, "Use session to find all objects", "[session][find]") { - ses.attach("airplanes"); - ses.create_schema(); + const auto result = ses.attach("airplanes") + .and_then([this] { return ses.create_schema(); } ); + REQUIRE(result.is_ok()); tables_to_drop.emplace("airplanes"); @@ -62,18 +72,19 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects", "[session][f planes.emplace_back(new airplane(3, "Boeing", "747")); for (auto &&plane: planes) { - ses.insert(plane.release()); + auto res = ses.insert(plane.release()); + REQUIRE(res.is_ok()); } - auto result = ses.find(); + auto find_result = ses.find(); std::vector> expected_result { {1, "Airbus", "A380"}, {2, "Boeing", "707"}, {3, "Boeing", "747"} }; - REQUIRE(result); - auto all_planes = result.release(); + REQUIRE(find_result); + auto all_planes = find_result.release(); size_t index {0}; for (const auto &i: all_planes) { REQUIRE(i.id == std::get<0>(expected_result[index])); @@ -84,25 +95,25 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects", "[session][f } TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-many relation", "[session][find][one-to-many]") { - ses.attach("authors"); - ses.attach("books"); + auto result = ses.attach("authors") + .and_then( [this] { return ses.attach("books"); } ) + .and_then( [this] { return ses.create_schema(); } ); tables_to_drop.emplace("authors"); tables_to_drop.emplace("books"); - ses.create_schema(); - std::vector> authors; authors.emplace_back(new author{1, "Michael", "Crichton", "23.10.1942", 1975, true, {}}); authors.emplace_back(new author{ 2, "Steven", "King", "21.9.1947", 1956, false, {}}); for (auto &&a: authors) { - ses.insert(a.release()); + auto res = ses.insert(a.release()); + REQUIRE(res.is_ok()); } - auto result = ses.find(); - REQUIRE(result.is_ok()); - auto all_authors = result.release(); + auto find_result = ses.find(); + REQUIRE(find_result.is_ok()); + auto all_authors = find_result.release(); std::vector> author_repo; for (auto it = all_authors.begin(); it != all_authors.end(); ++it) { std::cout << "author: " << it->first_name << " (books: " << it->books.size() << ")\n"; @@ -123,13 +134,14 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-ma books.emplace_back( new book{12, "The Dark Tower: The Gunslinger", author_repo[1], 1982} ); for (auto &&b: books) { - ses.insert(b.release()); + auto res = ses.insert(b.release()); + REQUIRE(res.is_ok()); } - result = ses.find(); - REQUIRE(result); + find_result = ses.find(); + REQUIRE(find_result); - all_authors = result.release(); + all_authors = find_result.release(); for (auto it = all_authors.begin(); it != all_authors.end(); ++it) { std::cout << "author: " << it->first_name << " (books: " << it->books.size() << ")\n"; } diff --git a/test/backends/StatementCacheTest.cpp b/test/backends/StatementCacheTest.cpp index 0e2124e..2959ac8 100644 --- a/test/backends/StatementCacheTest.cpp +++ b/test/backends/StatementCacheTest.cpp @@ -2,8 +2,9 @@ #include "matador/sql/connection_info.hpp" #include "matador/sql/connection_pool.hpp" -#include "matador/sql/session.hpp" -#include "matador/sql/statement_cache.hpp" +#include "matador/orm/session.hpp" + +// #include "matador/sql/statement_cache.hpp" #include "connection.hpp" #include "matador/sql/dialect_builder.hpp" @@ -14,13 +15,13 @@ class StatementCacheFixture { public: StatementCacheFixture() - : pool(matador::test::connection::dns, 4), ses(pool) + : pool(test::connection::dns, 4), ses(pool) {} ~StatementCacheFixture() = default; protected: - matador::sql::connection_pool pool; - matador::sql::session ses; + sql::connection_pool pool; + orm::session ses; }; TEST_CASE_METHOD(StatementCacheFixture, "Acquire prepared statement", "[statement cache]") { diff --git a/test/backends/StatementTest.cpp b/test/backends/StatementTest.cpp index cb64f23..7b5c3a7 100644 --- a/test/backends/StatementTest.cpp +++ b/test/backends/StatementTest.cpp @@ -1,9 +1,12 @@ #include -#include "matador/sql/column_definition.hpp" -#include "matador/sql/condition.hpp" +#include "matador/object/attribute_definition.hpp" + #include "matador/sql/connection.hpp" -#include "matador/sql/query.hpp" +#include "matador/sql/column_generator.hpp" + +#include "matador/query/condition.hpp" +#include "matador/query/query.hpp" #include "matador/object/object_ptr.hpp" @@ -12,6 +15,8 @@ #include "models/airplane.hpp" using namespace matador::sql; +using namespace matador::object; +using namespace matador::query; using namespace matador::test; namespace matador::test::detail { @@ -35,29 +40,29 @@ public: } protected: - std::vector> planes{ + std::vector> planes{ matador::test::detail::make_object_ptr(1, "Airbus", "A380"), matador::test::detail::make_object_ptr(2, "Boeing", "707"), matador::test::detail::make_object_ptr(3, "Boeing", "747") }; }; -TEST_CASE_METHOD(StatementTestFixture, "Create prepared statement", "[statement]") -{ +TEST_CASE_METHOD(StatementTestFixture, "Create prepared statement", "[statement]") { using namespace matador::utils; - schema.attach("airplane"); + REQUIRE(schema.attach("airplane")); table ap{"airplane"}; SECTION("Insert with prepared statement and placeholder") { auto stmt = query::insert() .into("airplane", column_generator::generate(schema, true)) .values() .prepare(db); + REQUIRE(stmt.is_ok()); for (const auto &plane: planes) { - auto res = stmt.bind(*plane).execute(); + auto res = stmt->bind(*plane).execute(); REQUIRE(res.is_ok()); REQUIRE(*res == 1); - stmt.reset(); + stmt->reset(); } auto result = query::select(column_generator::generate(schema, true)) @@ -87,8 +92,9 @@ TEST_CASE_METHOD(StatementTestFixture, "Create prepared statement", "[statement] .from(ap) .where("brand"_col == _) .prepare(db); + REQUIRE(stmt.is_ok()); - auto result = stmt.bind(0, "Airbus") + auto result = stmt->bind(0, "Airbus") .fetch(); REQUIRE(result.is_ok()); @@ -98,9 +104,9 @@ TEST_CASE_METHOD(StatementTestFixture, "Create prepared statement", "[statement] REQUIRE(i.model == planes[0]->model); } - stmt.reset(); + stmt->reset(); - result = stmt.bind(0, "Boeing") + result = stmt->bind(0, "Boeing") .fetch(); size_t index{1}; diff --git a/test/backends/TypeTraitsTest.cpp b/test/backends/TypeTraitsTest.cpp index 7ab1a2f..4abf7d9 100644 --- a/test/backends/TypeTraitsTest.cpp +++ b/test/backends/TypeTraitsTest.cpp @@ -4,21 +4,21 @@ #include "matador/sql/connection.hpp" #include "matador/sql/column_generator.hpp" -#include "matador/sql/query.hpp" +#include "matador/query/query.hpp" #include "QueryFixture.hpp" #include "models/location.hpp" +using namespace matador::query; using namespace matador::sql; using namespace matador::test; class TypeTraitsTestFixture : public QueryFixture { public: - TypeTraitsTestFixture() - { - db.open(); + TypeTraitsTestFixture() { + REQUIRE(db.open()); const auto res = query::create() .table("location", schema) .execute(db); @@ -26,9 +26,8 @@ public: } }; -TEST_CASE_METHOD(TypeTraitsTestFixture, "Special handling of attributes with type traits", "[typetraits]") -{ - schema.attach("location"); +TEST_CASE_METHOD(TypeTraitsTestFixture, "Special handling of attributes with type traits", "[typetraits]") { + REQUIRE(schema.attach("location")); SECTION("Insert and select with direct execution") { location loc{1, "center", {1, 2, 3}, Color::Black}; @@ -58,9 +57,8 @@ TEST_CASE_METHOD(TypeTraitsTestFixture, "Special handling of attributes with typ .into("location", column_generator::generate(schema, true)) .values() .prepare(db); - - auto res = stmt - .bind(loc) + REQUIRE(stmt); + auto res = stmt->bind(loc) .execute(); REQUIRE(res.is_ok()); REQUIRE(*res == 1); diff --git a/test/models/book.hpp b/test/models/book.hpp index ba5610e..3800c10 100644 --- a/test/models/book.hpp +++ b/test/models/book.hpp @@ -14,8 +14,8 @@ struct author; struct book { unsigned int id{}; - matador::object::object_ptr book_author; std::string title; + object::object_ptr book_author; unsigned short published_in{}; template diff --git a/test/models/flight.hpp b/test/models/flight.hpp index 4a8e7f5..b01da0c 100644 --- a/test/models/flight.hpp +++ b/test/models/flight.hpp @@ -21,7 +21,7 @@ struct flight : id(id), airplane(plane), pilot_name(std::move(name)) {} unsigned int id{}; - object::object_ptr airplane; + object::object_ptr airplane; std::string pilot_name; template diff --git a/test/models/person.hpp b/test/models/person.hpp new file mode 100644 index 0000000..be894bd --- /dev/null +++ b/test/models/person.hpp @@ -0,0 +1,30 @@ +#ifndef QUERY_PERSON_HPP +#define QUERY_PERSON_HPP + +#include "matador/utils/access.hpp" +#include "matador/utils/field_attributes.hpp" +#include "matador/utils/types.hpp" + +#include + +namespace matador::test { + +struct person { + unsigned int id{}; + std::string name; + unsigned int age{}; + utils::blob image; + + template + void process(Operator &op) { + namespace field = matador::access; + using namespace matador::utils; + field::primary_key(op, "id", id); + field::attribute(op, "name", name, 255); + field::attribute(op, "age", age); + field::attribute(op, "image", image); + } +}; + +} +#endif //QUERY_PERSON_HPP diff --git a/test/models/types.hpp b/test/models/types.hpp index f4e6a77..e8e2b0a 100644 --- a/test/models/types.hpp +++ b/test/models/types.hpp @@ -11,15 +11,13 @@ struct types enum { CSTR_LEN=255 }; unsigned int id_ = 0; - char char_ = 'c'; + int8_t char_ = 'c'; short short_ = -127; int int_ = -65000; - long long_ = -128000; long long long64_ = -1234567890; unsigned char unsigned_char_ = 'H'; unsigned short unsigned_short_ = 128; unsigned int unsigned_int_ = 65000; - unsigned long unsigned_long_ = 128000; unsigned long long unsigned_long64_ = 1234567890; float float_ = 3.1415f; double double_ = 1.1414; @@ -42,19 +40,17 @@ struct types field::attribute(op, "val_double", double_); field::attribute(op, "val_short", short_); field::attribute(op, "val_int", int_); - field::attribute(op, "val_long", long_); field::attribute(op, "val_long_long", long64_); field::attribute(op, "val_unsigned_char", unsigned_char_); field::attribute(op, "val_unsigned_short", unsigned_short_); field::attribute(op, "val_unsigned_int", unsigned_int_); - field::attribute(op, "val_unsigned_long", unsigned_long_); field::attribute(op, "val_unsigned_long_long", unsigned_long64_); field::attribute(op, "val_bool", bool_); field::attribute(op, "val_cstr", cstr_, CSTR_LEN); field::attribute(op, "val_string", string_); field::attribute(op, "val_varchar", varchar_, 63); - field::attribute(op, "val_date", date_); - field::attribute(op, "val_time", time_); + // field::attribute(op, "val_date", date_); + // field::attribute(op, "val_time", time_); field::attribute(op, "val_binary", binary_); } };