diff --git a/backends/postgres/test/CMakeLists.txt b/backends/postgres/test/CMakeLists.txt index 96bcda9..1d627ba 100644 --- a/backends/postgres/test/CMakeLists.txt +++ b/backends/postgres/test/CMakeLists.txt @@ -2,8 +2,8 @@ CPMAddPackage("gh:catchorg/Catch2@3.7.1") list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras) -#set(POSTGRES_CONNECTION_STRING "postgres://news:news@127.0.0.1:15432/matador") -set(POSTGRES_CONNECTION_STRING "postgres://test:test123!@127.0.0.1:5432/matador") +set(POSTGRES_CONNECTION_STRING "postgres://test:test123!@127.0.0.1:15442/matador") +#set(POSTGRES_CONNECTION_STRING "postgres://test:test123!@127.0.0.1:5432/matador") configure_file(Connection.hpp.in ${PROJECT_BINARY_DIR}/backends/postgres/test/connection.hpp @ONLY IMMEDIATE) @@ -22,6 +22,7 @@ set(TEST_SOURCES ../../../test/backends/QueryRecordTest.cpp ../../../test/backends/QueryStatementTests.cpp ../../../test/backends/QueryTest.cpp + ../../../test/backends/SchemaTest.cpp ../../../test/backends/SessionFixture.cpp ../../../test/backends/SessionFixture.hpp ../../../test/backends/SessionTest.cpp diff --git a/include/matador/orm/schema.hpp b/include/matador/orm/schema.hpp index 29a9d3c..8f73302 100644 --- a/include/matador/orm/schema.hpp +++ b/include/matador/orm/schema.hpp @@ -9,9 +9,24 @@ class connection_pool; namespace matador::orm { -class schema { +class schema; + +using schema_ref = std::reference_wrapper; + +class schema_repository final { public: - explicit schema(const std::string &name); + utils::result add(const std::string &name, const schema &schema); + utils::result remove(const std::string &name); + + [[nodiscard]] utils::result get(const std::string &name); + +private: + std::unordered_map schema_map_; +}; + +class schema final { +public: + schema(sql::connection_pool &pool, const std::string &name); template [[nodiscard]] utils::result attach(const std::string &name, const std::string &parent = "") { @@ -23,12 +38,30 @@ public: return repo_.attach(name); } - utils::result create(sql::connection_pool &pool) const; + utils::result create() const; utils::result drop() const; + template + utils::result drop_table(); + utils::result drop_table(const std::string &table_name) const; + + [[nodiscard]] utils::result, utils::error> describe_table(const std::string &table_name) const; + [[nodiscard]] utils::result table_exists(const std::string &table_name) const; + private: object::repository repo_; + sql::connection_pool &pool_; }; +template +utils::result schema::drop_table() { + auto info = repo_.info(); + if (info) { + return drop_table(info->get().name()); + } + + return utils::failure(info.err()); +} + } #endif //MATADOR_SCHEMA_HPP \ No newline at end of file diff --git a/include/matador/orm/session_insert_builder.hpp b/include/matador/orm/session_insert_builder.hpp deleted file mode 100644 index 889c49c..0000000 --- a/include/matador/orm/session_insert_builder.hpp +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef SESSION_INSERT_BUILDER_HPP -#define SESSION_INSERT_BUILDER_HPP - -#include "matador/orm/query_builder_exception.hpp" - -#include "matador/query/criteria.hpp" -#include "matador/query/query_intermediates.hpp" - -#include "matador/object/repository.hpp" - -#include "matador/utils/cascade_type.hpp" -#include "matador/utils/primary_key_attribute.hpp" - -namespace matador::orm { -struct entity_insert_data { - sql::table table; - std::vector columns{}; - std::vector values{}; -}; - -enum class insert_build_error : std::uint8_t { - Ok = 0, - UnknownType, - MissingPrimaryKey, - UnexpectedError -}; - -class insert_builder_exception final : public std::exception { -public: - explicit insert_builder_exception(const insert_build_error error) : error_(error) { - } - - [[nodiscard]] insert_build_error error() const { return error_; } - -private: - const insert_build_error error_; -}; - -class session_insert_builder final { -public: - explicit session_insert_builder(const object::repository &scm) - : schema_(scm) { - } - - template - utils::result, insert_build_error> build(const EntityType &obj) { - auto info = schema_.info(); - if (!info) { - return utils::failure(insert_build_error::UnknownType); - } - table_info_stack_.push({info.value()}); - entity_insert_data_ = {{sql::table{info.value().get().name()}}}; - // processed_tables_.insert({info->get().name(), entity_insert_data_.root_table}); - try { - access::process(*this, obj); - - return {utils::ok(std::move(entity_insert_data_))}; - } catch (const insert_builder_exception &ex) { - return {utils::failure(ex.error())}; - } catch (...) { - return {utils::failure(insert_build_error::UnexpectedError)}; - } - } - - template - void on_primary_key(const char *id, V &x, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) { - push(id, x); - } - - void on_revision(const char *id, uint64_t &/*rev*/); - - template - void on_attribute(const char *id, Type &x, const utils::field_attributes &/*attr*/ = utils::null_attributes) { - push(id, x); - } - - template - void on_belongs_to(const char *id, Pointer &obj, const utils::foreign_attributes &attr) { - if (!utils::is_cascade_type_set(attr.cascade(), utils::cascade_type::INSERT)) { - return; - } - - const auto info = schema_.info(); - if (!info) { - throw query_builder_exception{query_build_error::UnknownType}; - } - } - - template - void on_has_one(const char *id, Pointer &obj, const utils::foreign_attributes &attr) { - if (!utils::is_cascade_type_set(attr.cascade(), utils::cascade_type::INSERT)) { - return; - } - - const auto info = schema_.info(); - if (!info) { - throw query_builder_exception{query_build_error::UnknownType}; - } - - } - - template - void on_has_many(const char * /*id*/, ContainerType &, const char *join_column, - const utils::foreign_attributes &attr) { - } - - template - void on_has_many_to_many(const char *id, ContainerType &/*cont*/, const char *join_column, - const char *inverse_join_column, const utils::foreign_attributes &attr) { - } - - template - void on_has_many_to_many(const char *id, ContainerType &/*cont*/, const utils::foreign_attributes &attr) { - } - -private: - void push(const std::string &column_name, const utils::database_type &value); - -private: - struct table_info { - std::reference_wrapper info; - }; - - std::stack table_info_stack_; - std::unordered_map > processed_tables_; - const object::repository &schema_; - std::vector entity_insert_data_; -}; -} - -#endif //SESSION_INSERT_BUILDER_HPP diff --git a/source/orm/CMakeLists.txt b/source/orm/CMakeLists.txt index 39497db..2e54d4c 100644 --- a/source/orm/CMakeLists.txt +++ b/source/orm/CMakeLists.txt @@ -2,7 +2,6 @@ add_library(matador-orm STATIC ../../include/matador/orm/error_code.hpp ../../include/matador/orm/schema.hpp ../../include/matador/orm/session.hpp - ../../include/matador/orm/session_insert_builder.hpp ../../include/matador/orm/session_query_builder.hpp ../../include/matador/query/attribute_string_writer.hpp ../../include/matador/query/criteria/abstract_criteria.hpp @@ -80,7 +79,6 @@ add_library(matador-orm STATIC orm/query_builder_exception.cpp orm/schema.cpp orm/session.cpp - orm/session_insert_builder.cpp orm/session_query_builder.cpp query/attribute_string_writer.cpp query/criteria/between_criteria.cpp diff --git a/source/orm/orm/schema.cpp b/source/orm/orm/schema.cpp index c8121f1..ace9a33 100644 --- a/source/orm/orm/schema.cpp +++ b/source/orm/orm/schema.cpp @@ -1,15 +1,18 @@ #include "matador/orm/schema.hpp" +#include "matador/orm/error_code.hpp" +#include "matador/orm/session.hpp" #include "matador/query/query.hpp" #include "matador/sql/connection_pool.hpp" namespace matador::orm { -schema::schema( const std::string& name ) -: repo_(name){} +schema::schema(sql::connection_pool &pool, const std::string& name) +: repo_(name) +, pool_(pool) {} } -matador::utils::result matador::orm::schema::create(sql::connection_pool &pool) const { +matador::utils::result matador::orm::schema::create() const { // Step 1: Build dependency graph // std::unordered_map > dependency_graph; // std::unordered_map> in_degree; @@ -40,7 +43,7 @@ matador::utils::result matador::orm::schema::create // } std::vector fk_sql_commands; - auto c = pool.acquire(); + auto c = pool_.acquire(); for (const auto &node: repo_) { auto ctx = query::query::create() .table(node->name(), node->info().definition().columns()) @@ -68,3 +71,31 @@ matador::utils::result matador::orm::schema::create matador::utils::result matador::orm::schema::drop() const { return utils::ok(); } + +matador::utils::result matador::orm::schema::drop_table(const std::string& table_name) const { + const auto c = pool_.acquire(); + auto result = query::query::drop() + .table(table_name) + .execute(*c); + if (result.is_error()) { + return utils::failure(result.err()); + } + + return utils::ok(); +} + +matador::utils::result, matador::utils::error> matador::orm::schema::describe_table(const std::string& table_name) const { + const auto c = pool_.acquire(); + if (!c.valid()) { + return utils::failure(make_error(error_code::NoConnectionAvailable, "Failed to acquire connection.")); + } + return utils::ok(c->describe(table_name).release()); +} + +matador::utils::result matador::orm::schema::table_exists(const std::string& table_name) const { + const auto c = pool_.acquire(); + if (!c.valid()) { + return utils::failure(make_error(error_code::NoConnectionAvailable, "Failed to acquire connection.")); + } + return c->exists(repo_.name(), table_name); +} diff --git a/source/orm/orm/session_insert_builder.cpp b/source/orm/orm/session_insert_builder.cpp deleted file mode 100644 index 29b78c6..0000000 --- a/source/orm/orm/session_insert_builder.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "matador/orm/session_insert_builder.hpp" - -namespace matador::orm { -void session_insert_builder::on_revision(const char* id, uint64_t& x) { - push(id, x); -} - -void session_insert_builder::push(const std::string& column_name, const utils::database_type& value) { - entity_insert_data_.back().columns.emplace_back(column_name); - entity_insert_data_.back().values.emplace_back(value); -} -} \ No newline at end of file diff --git a/test/backends/SchemaTest.cpp b/test/backends/SchemaTest.cpp new file mode 100644 index 0000000..f95bf40 --- /dev/null +++ b/test/backends/SchemaTest.cpp @@ -0,0 +1,33 @@ +#include + +#include "matador/sql/backend_provider.hpp" +#include "matador/sql/connection_pool.hpp" + +#include "matador/orm/schema.hpp" + +#include "../orm/backend/test_connection.hpp" +#include "../orm/backend/test_backend_service.hpp" + +#include "../models/department.hpp" + +using namespace matador; + +TEST_CASE("Test schema", "[schema]") { + using namespace matador::test; + sql::backend_provider::instance().register_backend("noop", std::make_unique()); + + sql::connection_pool pool("noop://noop.db", 4); + + matador::orm::schema repo(pool, "NoopSchema"); + + auto result = repo.attach("departments") + .and_then( [&repo] { return repo.attach("employees"); } ); + REQUIRE(result); + + result = repo.create(); + REQUIRE(result); + + const auto exists_result = repo.table_exists("departments"); + REQUIRE(exists_result.is_ok()); + REQUIRE(exists_result.value()); +} \ No newline at end of file diff --git a/test/orm/CMakeLists.txt b/test/orm/CMakeLists.txt index 4a50e2a..ef2f2bf 100644 --- a/test/orm/CMakeLists.txt +++ b/test/orm/CMakeLists.txt @@ -13,21 +13,20 @@ add_executable(OrmTests backend/test_result_reader.hpp backend/test_statement.cpp backend/test_statement.hpp - orm/SessionInsertBuilderTest.cpp orm/SessionQueryBuilderTest.cpp + query/CriteriaTests.cpp query/QueryBuilderTest.cpp query/QueryFixture.cpp query/QueryFixture.hpp query/QueryTest.cpp - sql/ColumnTest.cpp sql/ColumnGeneratorTest.cpp + sql/ColumnTest.cpp + sql/ConnectionPoolFixture.hpp sql/ConnectionPoolTest.cpp sql/FieldTest.cpp + sql/StatementCacheTest.cpp utils/auto_reset_event.cpp utils/auto_reset_event.hpp - sql/StatementCacheTest.cpp - sql/ConnectionPoolFixture.hpp - query/CriteriaTests.cpp ) target_link_libraries(OrmTests matador-orm matador-core Catch2::Catch2WithMain) diff --git a/test/orm/orm/SessionInsertBuilderTest.cpp b/test/orm/orm/SessionInsertBuilderTest.cpp deleted file mode 100644 index dc29f59..0000000 --- a/test/orm/orm/SessionInsertBuilderTest.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include -#include - -#include "matador/sql/backend_provider.hpp" -#include "matador/sql/connection.hpp" -#include "matador/sql/column.hpp" -#include "matador/sql/table.hpp" - -#include "matador/query/query.hpp" - -#include "matador/orm/session_insert_builder.hpp" - -#include "../backend/test_connection.hpp" -#include "../backend/test_backend_service.hpp" - -#include "../../models/airplane.hpp" -#include "../../models/author.hpp" -#include "../../models/department.hpp" -#include "../../models/book.hpp" -#include "../../models/flight.hpp" -#include "../../models/recipe.hpp" -#include "../../models/order.hpp" -#include "../../models/student.hpp" - -using namespace matador::object; -using namespace matador::orm; -using namespace matador::query; -using namespace matador::sql; -using namespace matador::test; - -TEST_CASE("Create sql insert for entity with eager has one", "[query][entity][insert][builder]") { - using namespace matador::test; - backend_provider::instance().register_backend("noop", std::make_unique()); - connection db("noop://noop.db"); - repository scm("noop"); - auto result = scm.attach("airplanes") - .and_then( [&scm] { return scm.attach("flights"); } ); - REQUIRE(result); - - session_insert_builder eib(scm); - - auto b737 = object_ptr(new airplane{0, "Boeing", "737"}); - flight f1{0, b737, "F828"}; - - // auto data = eib.build(f1); - - // REQUIRE(data.is_ok()); -}