diff --git a/backends/postgres/src/postgres_connection.cpp b/backends/postgres/src/postgres_connection.cpp index 8870dc1..9aacd21 100644 --- a/backends/postgres/src/postgres_connection.cpp +++ b/backends/postgres/src/postgres_connection.cpp @@ -234,7 +234,7 @@ utils::result, utils::error> postgres_connection: } char *end = nullptr; // Todo: Handle error - auto index = strtoul(reader.column(0), &end, 10) - 1; + // auto index = strtoul(reader.column(0), &end, 10) - 1; std::string name = reader.column(1); // Todo: extract size diff --git a/include/matador/orm/session.hpp b/include/matador/orm/session.hpp index 6007c1c..d3e0f7e 100644 --- a/include/matador/orm/session.hpp +++ b/include/matador/orm/session.hpp @@ -99,6 +99,7 @@ public: [[nodiscard]] utils::result attach(const std::string &table_name) const; utils::result create_schema() const; + utils::result drop_schema() const; /** * Insert the given object into the session. @@ -144,6 +145,7 @@ private: friend class query_select; static query::fetchable_query build_select_query(entity_query_data &&data); + static sql::query_context build_add_constraint_context(const std::string& table_name, const class object::constraint& cons, const sql::connection_ptr &conn) ; private: mutable sql::statement_cache cache_; diff --git a/include/matador/query/intermediates/query_alter_intermediate.hpp b/include/matador/query/intermediates/query_alter_intermediate.hpp index b09fc6c..7d98ba4 100644 --- a/include/matador/query/intermediates/query_alter_intermediate.hpp +++ b/include/matador/query/intermediates/query_alter_intermediate.hpp @@ -9,7 +9,7 @@ class query_alter_intermediate : public query_intermediate { public: query_alter_intermediate(); - query_alter_table_intermediate table(const table &tab) const; + [[nodiscard]] query_alter_table_intermediate table(const table &tab) const; }; } diff --git a/include/matador/query/intermediates/query_alter_table_intermediate.hpp b/include/matador/query/intermediates/query_alter_table_intermediate.hpp index e515f1d..0ce1f25 100644 --- a/include/matador/query/intermediates/query_alter_table_intermediate.hpp +++ b/include/matador/query/intermediates/query_alter_table_intermediate.hpp @@ -36,7 +36,6 @@ public: using query_intermediate::query_intermediate; query_add_key_constraint_intermediate add_constraint(const std::string& name); - executable_query add_constraint(const class object::constraint& constraint); executable_query drop_constraint(const std::string& name); }; } diff --git a/source/orm/orm/schema.cpp b/source/orm/orm/schema.cpp index 2722ff6..5711811 100644 --- a/source/orm/orm/schema.cpp +++ b/source/orm/orm/schema.cpp @@ -84,38 +84,34 @@ utils::result schema::create() const { } utils::result schema::drop() const { - std::vector drop_sql_commands; auto c = pool_.acquire(); + // drop table constraints for (const auto &node: repo_) { - auto ctx = query::query::drop() - .table(node->name()) - .compile(*c); + for (const auto& cons : node->info().constraints()) { + auto ctx = query::query::alter() + .table(node->name()) + .drop_constraint(cons.name()) + .compile(*c); - drop_sql_commands.push_back(ctx.sql); - // determine constraints and drop them - for (auto it = node->info().endpoint_begin(); it != node->info().endpoint_end(); ++it) { - const auto& endpoint = *(it->second); - if (endpoint.type() == object::relation_type::BELONGS_TO) { - continue; - } - const auto drop_fk_ctx = query::query::alter() - .table( endpoint.node().name() ) - .drop_constraint( "FK_" + endpoint.node().name() + "_" + endpoint.foreign_endpoint()->field_name() ) - .compile(*c); - std::cout << drop_fk_ctx.sql << std::endl; - if (auto result = c->execute(drop_fk_ctx.sql); !result) { + std::cout << ctx.sql << std::endl; + if (auto result = c->execute(ctx.sql); !result) { return utils::failure(result.err()); } } } - // execute additional commands (e.g. ALTER TABLE ADD FK) - for (const auto &sql: drop_sql_commands) { - std::cout << sql << std::endl; - if (auto result = c->execute(sql); !result) { + // drop table + for (const auto &node: repo_) { + auto ctx = query::query::drop() + .table(node->name()) + .compile(*c); + + std::cout << ctx.sql << std::endl; + if (auto result = c->execute(ctx.sql); !result) { return utils::failure(result.err()); } } + return utils::ok(); } diff --git a/source/orm/orm/session.cpp b/source/orm/orm/session.cpp index eafd836..e3cae40 100644 --- a/source/orm/orm/session.cpp +++ b/source/orm/orm/session.cpp @@ -20,59 +20,110 @@ session::session(session_context&& ctx) utils::result session::create_schema() const { // Step 1: Build dependency graph - std::unordered_map > dependency_graph; - std::unordered_map> in_degree; + // std::unordered_map > dependency_graph; + // std::unordered_map> in_degree; - for (const auto &node: *schema_) { - for (auto it = node->info().endpoint_begin(); it != node->info().endpoint_end(); ++it) { - dependency_graph[node->name()].push_back(it->second->node().name()); + // for (const auto &node: *schema_) { + // for (auto it = node->info().endpoint_begin(); it != node->info().endpoint_end(); ++it) { + // dependency_graph[node->name()].push_back(it->second->node().name()); + // + // if (const auto dit = in_degree.find(it->second->node().name()); dit == in_degree.end()) { + // in_degree[it->second->node().name()] = std::make_pair(1, it->second->node_ptr()); + // } else { + // in_degree[it->second->node().name()].first++; + // } + // } + // + // // Ensure the current node exists in the graph representation + // if (in_degree.find(node->name()) == in_degree.end()) { + // in_degree[node->name()] = std::make_pair(0, node); + // } + // } + // + // for (const auto &it : dependency_graph) { + // std::cout << "Dependency graph " << it.first << std::endl; + // for (const auto &neighbor: it.second) { + // std::cout << " " << neighbor << std::endl; + // } + // std::cout << std::endl; + // } - if (const auto dit = in_degree.find(it->second->node().name()); dit == in_degree.end()) { - in_degree[it->second->node().name()] = std::make_pair(1, it->second->node_ptr()); - } else { - in_degree[it->second->node().name()].first++; - } - } - - // Ensure the current node exists in the graph representation - if (in_degree.find(node->name()) == in_degree.end()) { - in_degree[node->name()] = std::make_pair(0, node); - } - } - - for (const auto &it : dependency_graph) { - std::cout << "Dependency graph " << it.first << std::endl; - for (const auto &neighbor: it.second) { - std::cout << " " << neighbor << std::endl; - } - std::cout << std::endl; - } - - std::vector fk_sql_commands; auto c = cache_.pool().acquire(); for (const auto &node: *schema_) { auto ctx = query::query::create() .table(node->name()) .columns(node->info().attributes()) - .constraints(node->info().constraints()) .compile(*c); - // for ( const auto& [sql, command] : ctx.additional_commands ) { - // fk_sql_commands.push_back( sql ); - // } std::cout << ctx.sql << std::endl; if (auto result = c->execute(ctx.sql); !result) { return utils::failure(result.err()); } } - // execute additional commands (e.g. ALTER TABLE ADD FK) - for (const auto &sql: fk_sql_commands) { - std::cout << sql << std::endl; - if (auto result = c->execute(sql); !result) { + // create table constraints + for (const auto &node: *schema_) { + for (const auto& cons : node->info().constraints()) { + auto ctx = build_add_constraint_context(node->name(), cons, c); + + std::cout << ctx.sql << std::endl; + if (auto result = c->execute(ctx.sql); !result) { + return utils::failure(result.err()); + } + } + } + + return utils::ok(); +} + +sql::query_context session::build_add_constraint_context(const std::string& table_name, const class object::constraint& cons, const sql::connection_ptr &conn) { + if (cons.is_foreign_key_constraint()) { + return query::query::alter() + .table(table_name) + .add_constraint( cons.name() ) + .foreign_key(cons.column_name()) + .references(cons.ref_table_name(), {cons.ref_column_name()}) + .compile(*conn); + } + if (cons.is_primary_key_constraint()) { + return query::query::alter() + .table(table_name) + .add_constraint( cons.name() ) + .primary_key(cons.column_name()) + .compile(*conn); + } + return {}; +} + +utils::result session::drop_schema() const { + auto c = cache_.pool().acquire(); + // drop table constraints + for (const auto &node: *schema_) { + for (const auto& cons : node->info().constraints()) { + auto ctx = query::query::alter() + .table(node->name()) + .drop_constraint(cons.name()) + .compile(*c); + + std::cout << ctx.sql << std::endl; + if (auto result = c->execute(ctx.sql); !result) { + return utils::failure(result.err()); + } + } + } + + // drop table + for (const auto &node: *schema_) { + auto ctx = query::query::drop() + .table(node->name()) + .compile(*c); + + std::cout << ctx.sql << std::endl; + if (auto result = c->execute(ctx.sql); !result) { return utils::failure(result.err()); } } + return utils::ok(); } diff --git a/source/orm/query/intermediates/query_alter_table_intermediate.cpp b/source/orm/query/intermediates/query_alter_table_intermediate.cpp index 1222b02..7d4c0c9 100644 --- a/source/orm/query/intermediates/query_alter_table_intermediate.cpp +++ b/source/orm/query/intermediates/query_alter_table_intermediate.cpp @@ -35,10 +35,6 @@ query_add_key_constraint_intermediate query_alter_table_intermediate::add_constr return {context_}; } -executable_query query_alter_table_intermediate::add_constraint( const class object::constraint& constraint ) { - return {context_}; -} - executable_query query_alter_table_intermediate::drop_constraint( const std::string& name ) { context_->parts.push_back(std::make_unique(name)); return {context_}; diff --git a/source/orm/query/query_compiler.cpp b/source/orm/query/query_compiler.cpp index 45a253a..683b48a 100644 --- a/source/orm/query/query_compiler.cpp +++ b/source/orm/query/query_compiler.cpp @@ -36,9 +36,6 @@ sql::query_context query_compiler::compile(const query_data &data, } std::string handle_column(sql::query_context &ctx, const sql::dialect *d, const query_data &data, const column &col) { - // ctx.result_vars.emplace_back(col.column_name()); - const auto& column_table = col.table().get(); - // ctx.column_aliases.insert({column_table->has_alias() ? column_table->alias() : column_table->name() + "." + col.column_name(), col.alias()}); if (col.is_function()) { ctx.prototype.emplace_back(col.has_alias() ? col.alias() : col.column_name()); ctx.prototype.back().change_type(utils::basic_type::type_int32); @@ -153,7 +150,6 @@ void query_compiler::visit(internal::query_select_part &part) { void query_compiler::visit(internal::query_from_part &part) { query_.table_name = part.table().name(); query_.sql += " " + build_table_name(part.token(), *dialect_, part.table()); - // query_.table_aliases.insert({query_.table_name, part.table().alias()}); } void query_compiler::visit(internal::query_join_part &part) @@ -177,40 +173,33 @@ void query_compiler::visit(internal::query_group_by_part &part) { query_.sql += " " + dialect_->group_by() + " " + prepare_identifier(*dialect_, part.column()); } -void query_compiler::visit(internal::query_order_by_part &part) -{ +void query_compiler::visit(internal::query_order_by_part &part) { query_.sql += " " + dialect_->order_by() + " " + prepare_criteria(*dialect_, part.column()); } -void query_compiler::visit(internal::query_order_by_asc_part &/*order_by_asc_part*/) -{ +void query_compiler::visit(internal::query_order_by_asc_part &/*order_by_asc_part*/) { query_.sql += " " + dialect_->asc(); } -void query_compiler::visit(internal::query_order_by_desc_part &/*order_by_desc_part*/) -{ +void query_compiler::visit(internal::query_order_by_desc_part &/*order_by_desc_part*/) { query_.sql += " " + dialect_->desc(); } -void query_compiler::visit(internal::query_offset_part &part) -{ +void query_compiler::visit(internal::query_offset_part &part) { query_.sql += " " + dialect_->offset() + " " + std::to_string(part.offset()); } -void query_compiler::visit(internal::query_limit_part &part) -{ +void query_compiler::visit(internal::query_limit_part &part) { query_.sql += " " + dialect_->limit() + " " + std::to_string(part.limit()); } -void query_compiler::visit(internal::query_insert_part &/*insert_part*/) -{ +void query_compiler::visit(internal::query_insert_part &/*insert_part*/) { query_.command = sql::sql_command::SQL_INSERT; query_.sql = dialect_->insert(); } -void query_compiler::visit(internal::query_into_part &part) -{ +void query_compiler::visit(internal::query_into_part &part) { query_.table_name = part.table().name(); query_.sql += " " + dialect_->into() + " " + dialect_->prepare_identifier_string(part.table().name()); @@ -383,14 +372,12 @@ void query_compiler::visit(internal::query_set_part &part) { query_.sql += result; } -void query_compiler::visit(internal::query_drop_table_part &part) -{ +void query_compiler::visit(internal::query_drop_table_part &part) { query_.table_name = part.table().name(); query_.sql += " " + build_table_name(part.token(), *dialect_, query_.table_name); } -std::string build_create_column(const object::attribute &col, const sql::dialect &d) -{ +std::string build_create_column(const object::attribute &col, const sql::dialect &d) { std::string result = d.prepare_identifier_string(col.name()) + " " + d.data_type_at(col.type()); if (col.attributes().size() > 0) { result.append("(" + std::to_string(col.attributes().size()) + ")"); @@ -433,8 +420,7 @@ std::string build_constraint(const class object::constraint& cons, const sql::di return result; } -std::string query_compiler::build_table_name(const sql::dialect_token token, const sql::dialect &d, const table& t) -{ +std::string query_compiler::build_table_name(const sql::dialect_token token, const sql::dialect &d, const table& t) { return d.token_at(token) + " " + (!d.default_schema_name().empty() ? d.prepare_identifier_string(d.default_schema_name()) + "." : "") + d.prepare_identifier_string(t.name()) + diff --git a/test/backends/QueryBasicTest.cpp b/test/backends/QueryBasicTest.cpp index 562667d..a1e3ad2 100644 --- a/test/backends/QueryBasicTest.cpp +++ b/test/backends/QueryBasicTest.cpp @@ -50,7 +50,7 @@ TEST_CASE_METHOD( QueryFixture, "Insert and select basic datatypes", "[query][da ullval = (std::numeric_limits::max)(); } bool bval = true; - const char *cstr("Armer schwarzer Kater"); + // const char *cstr("Armer schwarzer Kater"); std::string varcharval("hallo welt"); std::string strval = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam " "nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, " diff --git a/test/backends/SessionFixture.cpp b/test/backends/SessionFixture.cpp index dce6cf3..67b4005 100644 --- a/test/backends/SessionFixture.cpp +++ b/test/backends/SessionFixture.cpp @@ -5,13 +5,12 @@ namespace matador::test { SessionFixture::SessionFixture() - : pool(connection::dns, 4), ses({bus, pool}) {} +: pool(connection::dns, 4) +, ses({bus, pool}) {} SessionFixture::~SessionFixture() { - while (!tables_to_drop.empty()) { - drop_table_if_exists(tables_to_drop.top()); - tables_to_drop.pop(); - } + const auto result = ses.drop_schema(); + REQUIRE(result.is_ok()); } void SessionFixture::drop_table_if_exists(const std::string &table_name) const { diff --git a/test/backends/SessionFixture.hpp b/test/backends/SessionFixture.hpp index b0e6370..4da3120 100644 --- a/test/backends/SessionFixture.hpp +++ b/test/backends/SessionFixture.hpp @@ -18,7 +18,6 @@ public: protected: sql::connection_pool pool; - std::stack tables_to_drop; orm::session ses; utils::message_bus bus; diff --git a/test/backends/SessionTest.cpp b/test/backends/SessionTest.cpp index 6d059b8..83ca9bb 100644 --- a/test/backends/SessionTest.cpp +++ b/test/backends/SessionTest.cpp @@ -20,8 +20,6 @@ TEST_CASE_METHOD(SessionFixture, "Session insert test", "[session][insert]") { .and_then([this] { return ses.create_schema(); } ); REQUIRE(result.is_ok()); - tables_to_drop.emplace("airplanes"); - auto plane = ses.insert(1, "Boeing", "A380"); REQUIRE(plane.is_ok()); @@ -38,8 +36,6 @@ TEST_CASE_METHOD(SessionFixture, "Session update test", "[session][update]") { .and_then([this] { return ses.create_schema(); } ); REQUIRE(res.is_ok()); - tables_to_drop.emplace("airplanes"); - auto result = ses.insert(1, "Boeing", "747"); REQUIRE(result.is_ok()); @@ -70,8 +66,6 @@ TEST_CASE_METHOD(SessionFixture, "Session delete test", "[session][delete]") { .and_then([this] { return ses.create_schema(); } ); REQUIRE(res.is_ok()); - tables_to_drop.emplace("airplanes"); - auto result = ses.insert(1, "Boeing", "747"); REQUIRE(result.is_ok()); @@ -94,9 +88,6 @@ TEST_CASE_METHOD(SessionFixture, "Session relation test", "[session][relation]") .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"); REQUIRE(plane.is_ok()); auto f = ses.insert(2, *plane, "sully"); @@ -118,8 +109,6 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find object with id", "[session .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()); @@ -139,8 +128,6 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects", "[session][f .and_then([this] { return ses.create_schema(); } ); REQUIRE(result.is_ok()); - tables_to_drop.emplace("airplanes"); - std::vector> planes; planes.emplace_back(new airplane(1, "Airbus", "A380")); planes.emplace_back(new airplane(2, "Boeing", "707")); @@ -174,9 +161,6 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-ma .and_then( [this] { return ses.attach("books"); } ) .and_then( [this] { return ses.create_schema(); } ); - tables_to_drop.emplace("authors"); - tables_to_drop.emplace("books"); - 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, {}}); @@ -227,9 +211,6 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with one-to-ma .and_then( [this] { return ses.attach("employees"); } ) .and_then( [this] { return ses.create_schema(); } ); - tables_to_drop.emplace("departments"); - tables_to_drop.emplace("employees"); - std::vector> departments; departments.emplace_back(new department{1, "Insurance", {}}); departments.emplace_back(new department{ 2, "Invoice", {}}); @@ -283,10 +264,6 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find all objects with many-to-m .and_then( [this] { return ses.attach("ingredients"); } ) .and_then( [this] { return ses.create_schema(); } ); - tables_to_drop.emplace("recipes"); - tables_to_drop.emplace("ingredients"); - tables_to_drop.emplace("recipe_ingredients"); - std::vector> ingredients; ingredients.push_back(std::make_unique(1, "Apple")); ingredients.push_back(std::make_unique(2, "Strawberry"));