diff --git a/include/matador/query/constraint.hpp b/include/matador/query/constraint.hpp index 293dcbc..bb03e8b 100644 --- a/include/matador/query/constraint.hpp +++ b/include/matador/query/constraint.hpp @@ -11,9 +11,11 @@ namespace matador::query { class constraint { public: constraint() = default; - constraint(std::string column_name, utils::constraints type, std::string referenced_table, std::string referenced_column); + constraint(std::string column_name, std::string table_name, utils::constraints type); + constraint(std::string column_name, std::string table_name, utils::constraints type, std::string referenced_table, std::string referenced_column); [[nodiscard]] std::string column_name() const; + [[nodiscard]] std::string table_name() const; [[nodiscard]] const utils::constraints& type() const; [[nodiscard]] bool is_primary_key_constraint() const; [[nodiscard]] bool is_foreign_key_constraint() const; @@ -23,6 +25,7 @@ public: private: std::string column_name_; + std::string table_name_; utils::constraints type_{}; std::string referenced_table_; std::string referenced_column_; diff --git a/include/matador/query/intermediates/query_alter_table_intermediate.hpp b/include/matador/query/intermediates/query_alter_table_intermediate.hpp index 2d2683e..acba449 100644 --- a/include/matador/query/intermediates/query_alter_table_intermediate.hpp +++ b/include/matador/query/intermediates/query_alter_table_intermediate.hpp @@ -1,9 +1,11 @@ #ifndef MATADOR_QUERY_ALTER_TABLE_INTERMEDIATE_HPP #define MATADOR_QUERY_ALTER_TABLE_INTERMEDIATE_HPP -#include "executable_query.hpp" -#include "matador/object/restriction.hpp" +#include "matador/query/intermediates/executable_query.hpp" #include "matador/query/intermediates/query_intermediate.hpp" +#include "matador/query/constraint.hpp" + +#include "matador/object/restriction.hpp" namespace matador::query { class query_add_primary_key_constraint_intermediate final : public executable_query { @@ -35,7 +37,9 @@ class query_alter_table_intermediate final : public query_intermediate { public: using query_intermediate::query_intermediate; + executable_query add_constraint(const object::restriction& rest); query_add_key_constraint_intermediate add_constraint(const std::string& name); + executable_query drop_constraint(const object::restriction& rest); executable_query drop_constraint(const std::string& name); }; } diff --git a/include/matador/query/internal/query_parts.hpp b/include/matador/query/internal/query_parts.hpp index 3c70fc4..9724e77 100644 --- a/include/matador/query/internal/query_parts.hpp +++ b/include/matador/query/internal/query_parts.hpp @@ -15,6 +15,8 @@ #include #include +#include "matador/object/restriction.hpp" + namespace matador::query::internal { class query_alter_part final : public query_part { @@ -46,9 +48,19 @@ private: std::string name_; }; -class query_drop_key_constraint_part final : public query_part { +class query_add_constraint_part_by_constraint final : public query_part { public: - explicit query_drop_key_constraint_part(std::string name); + explicit query_add_constraint_part_by_constraint(const constraint& co); + void accept(query_part_visitor &visitor) override; + + [[nodiscard]] const class constraint& constraint() const; +private: + class constraint constraint_; +}; + +class query_drop_key_constraint_part_by_name final : public query_part { +public: + explicit query_drop_key_constraint_part_by_name(std::string name); void accept(query_part_visitor &visitor) override; [[nodiscard]] const std::string& name() const; @@ -56,6 +68,16 @@ private: std::string name_; }; +class query_drop_key_constraint_part_by_constraint final : public query_part { +public: + explicit query_drop_key_constraint_part_by_constraint(const constraint& co); + void accept(query_part_visitor &visitor) override; + + [[nodiscard]] const class constraint& constraint() const; +private: + class constraint constraint_; +}; + class query_add_foreign_key_constraint_part final : public query_part { public: explicit query_add_foreign_key_constraint_part( const std::vector& columns); @@ -89,12 +111,6 @@ private: std::vector columns_; }; -class query_drop_foreign_key_constraint_part final : public query_part { -public: - query_drop_foreign_key_constraint_part(); - void accept(query_part_visitor &visitor) override; -}; - /** * Represents the SQL SELECT part */ diff --git a/include/matador/query/query_compiler.hpp b/include/matador/query/query_compiler.hpp index 5df35e1..aa97f8b 100644 --- a/include/matador/query/query_compiler.hpp +++ b/include/matador/query/query_compiler.hpp @@ -38,8 +38,9 @@ protected: void visit(internal::query_add_foreign_key_constraint_part& part) override; void visit(internal::query_add_primary_key_constraint_part& part) override; void visit(internal::query_add_foreign_key_reference_part& part) override; - void visit(internal::query_drop_key_constraint_part& part) override; - void visit(internal::query_drop_foreign_key_constraint_part& part) override; + void visit(internal::query_add_constraint_part_by_constraint &part) override; + void visit(internal::query_drop_key_constraint_part_by_name &part) override; + void visit(internal::query_drop_key_constraint_part_by_constraint &part) override; protected: void visit(internal::query_select_part &part) override; @@ -76,6 +77,10 @@ protected: static std::string build_table_name(sql::dialect_token token, const sql::dialect &d, const table& t); static std::string determine_value(value_visitor &visitor, const std::variant &val); + std::string build_add_constraint_string(const class constraint& c); + std::string build_drop_constraint_string(const class constraint& c); + std::string build_constraint_name(const class constraint& c); + protected: const query_data *data_{}; sql::query_context query_; diff --git a/include/matador/query/query_part_visitor.hpp b/include/matador/query/query_part_visitor.hpp index be9e192..e0d2bbc 100644 --- a/include/matador/query/query_part_visitor.hpp +++ b/include/matador/query/query_part_visitor.hpp @@ -7,9 +7,10 @@ namespace internal { class query_alter_part; class query_alter_table_part; class query_add_key_constraint_part; -class query_drop_key_constraint_part; -class query_drop_foreign_key_constraint_part; +class query_drop_key_constraint_part_by_name; +class query_drop_key_constraint_part_by_constraint; class query_add_foreign_key_constraint_part; +class query_add_constraint_part_by_constraint; class query_add_foreign_key_reference_part; class query_add_primary_key_constraint_part; class query_select_part; @@ -48,10 +49,11 @@ public: virtual void visit(internal::query_alter_table_part &part) = 0; virtual void visit(internal::query_add_key_constraint_part &part) = 0; virtual void visit(internal::query_add_foreign_key_constraint_part &part) = 0; + virtual void visit(internal::query_add_constraint_part_by_constraint &part) = 0; virtual void visit(internal::query_add_primary_key_constraint_part &part) = 0; virtual void visit(internal::query_add_foreign_key_reference_part &part) = 0; - virtual void visit(internal::query_drop_key_constraint_part &part) = 0; - virtual void visit(internal::query_drop_foreign_key_constraint_part &part) = 0; + virtual void visit(internal::query_drop_key_constraint_part_by_name &part) = 0; + virtual void visit(internal::query_drop_key_constraint_part_by_constraint &part) = 0; virtual void visit(internal::query_select_part &part) = 0; virtual void visit(internal::query_from_part &part) = 0; diff --git a/include/matador/sql/dialect.hpp b/include/matador/sql/dialect.hpp index fb6bb35..53277a6 100644 --- a/include/matador/sql/dialect.hpp +++ b/include/matador/sql/dialect.hpp @@ -171,6 +171,7 @@ public: [[nodiscard]] const std::string& start_quote() const; [[nodiscard]] const std::string& string_quote() const; [[nodiscard]] const std::string& table() const; + [[nodiscard]] const std::string& unique() const; [[nodiscard]] const std::string& update() const; [[nodiscard]] const std::string& values() const; [[nodiscard]] const std::string& where() const; @@ -237,6 +238,7 @@ private: {dialect_token::StartQuote, "\""}, {dialect_token::StringQuote, "'"}, {dialect_token::Table, "TABLE"}, + {dialect_token::Unique, "UNIQUE"}, {dialect_token::Update, "UPDATE"}, {dialect_token::Values, "VALUES"}, {dialect_token::Where, "WHERE"} diff --git a/include/matador/sql/dialect_token.hpp b/include/matador/sql/dialect_token.hpp index bc4a46f..f7e7384 100644 --- a/include/matador/sql/dialect_token.hpp +++ b/include/matador/sql/dialect_token.hpp @@ -55,6 +55,7 @@ enum class dialect_token : uint8_t { StartQuote, StringQuote, Table, + Unique, Update, Values, Where diff --git a/source/orm/orm/schema.cpp b/source/orm/orm/schema.cpp index dd71be9..34d3aef 100644 --- a/source/orm/orm/schema.cpp +++ b/source/orm/orm/schema.cpp @@ -110,7 +110,7 @@ utils::result schema::drop() const { } auto ctx = query::query::alter() .table(node->name()) - .drop_constraint("cons.name()") + .drop_constraint(cons) .compile(*c); std::cout << ctx.sql << std::endl; @@ -128,7 +128,7 @@ utils::result schema::drop() const { } auto ctx = query::query::alter() .table(node->name()) - .drop_constraint("cons.name()") + .drop_constraint(cons) .compile(*c); std::cout << ctx.sql << std::endl; @@ -185,16 +185,13 @@ sql::query_context schema::build_add_constraint_context( const object::repositor if (cons.is_foreign_key_constraint()) { return query::query::alter() .table(node.name()) - .add_constraint("cons.name()") - .foreign_key(cons.column_name()) - .references(cons.ref_table_name(), {cons.ref_column_name()}) + .add_constraint(cons) .compile(*pool_.acquire()); } if (cons.is_primary_key_constraint()) { return query::query::alter() .table(node.name()) - .add_constraint("cons.name()") - .primary_key(cons.column_name()) + .add_constraint(cons) .compile(*pool_.acquire()); } return {}; @@ -203,7 +200,7 @@ sql::query_context schema::build_add_constraint_context( const object::repositor sql::query_context schema::build_drop_constraint_context( const object::repository_node& node, const class object::restriction& cons ) const { return query::query::alter() .table(node.name()) - .drop_constraint("cons.name()") + .drop_constraint(cons) .compile(*pool_.acquire()); } } \ No newline at end of file diff --git a/source/orm/orm/session.cpp b/source/orm/orm/session.cpp index a577984..3ebbcfe 100644 --- a/source/orm/orm/session.cpp +++ b/source/orm/orm/session.cpp @@ -80,16 +80,13 @@ sql::query_context session::build_add_constraint_context(const std::string& tabl 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()}) + .add_constraint(cons) .compile(*conn); } if (cons.is_primary_key_constraint()) { return query::query::alter() .table(table_name) - .add_constraint("cons.name()") - .primary_key(cons.column_name()) + .add_constraint(cons) .compile(*conn); } return {}; @@ -102,7 +99,7 @@ utils::result session::drop_schema() const { for (const auto& cons : node->info().constraints()) { auto ctx = query::query::alter() .table(node->name()) - .drop_constraint("cons.name()") + .drop_constraint(cons) .compile(*c); std::cout << ctx.sql << std::endl; diff --git a/source/orm/query/constraint.cpp b/source/orm/query/constraint.cpp index 7f7d76f..2bbf90e 100644 --- a/source/orm/query/constraint.cpp +++ b/source/orm/query/constraint.cpp @@ -3,8 +3,14 @@ #include "matador/utils/constraints.hpp" namespace matador::query { -constraint::constraint(std::string column_name, utils::constraints type, std::string referenced_table, std::string referenced_column) +constraint::constraint(std::string column_name, std::string table_name, utils::constraints type) : column_name_(std::move(column_name)) +, table_name_(std::move(table_name)) +, type_(type) {} + +constraint::constraint(std::string column_name, std::string table_name, utils::constraints type, std::string referenced_table, std::string referenced_column) +: column_name_(std::move(column_name)) +, table_name_(std::move(table_name)) , type_(type) , referenced_table_(std::move(referenced_table)) , referenced_column_(std::move(referenced_column)) {} @@ -13,6 +19,10 @@ std::string constraint::column_name() const { return column_name_; } +std::string constraint::table_name() const { + return table_name_; +} + const utils::constraints& constraint::type() const { return type_; } diff --git a/source/orm/query/intermediates/query_alter_table_intermediate.cpp b/source/orm/query/intermediates/query_alter_table_intermediate.cpp index 7d4c0c9..aa3781e 100644 --- a/source/orm/query/intermediates/query_alter_table_intermediate.cpp +++ b/source/orm/query/intermediates/query_alter_table_intermediate.cpp @@ -1,5 +1,6 @@ #include "matador/query/intermediates/query_alter_table_intermediate.hpp" +#include "matador/object/object.hpp" #include "matador/query/internal/query_parts.hpp" namespace matador::query { @@ -29,14 +30,29 @@ query_add_foreign_key_constraint_intermediate query_add_key_constraint_intermedi return {context_}; } -query_add_key_constraint_intermediate query_alter_table_intermediate::add_constraint( const std::string& name ) { +executable_query query_alter_table_intermediate::add_constraint(const object::restriction &rest) { + context_->parts.push_back(std::make_unique( + constraint{rest.column_name(), rest.owner()->name(), rest.attribute().attributes().options(), rest.ref_table_name(), rest.ref_column_name()} + )); + + return {context_}; +} + +query_add_key_constraint_intermediate query_alter_table_intermediate::add_constraint(const std::string& name) { context_->parts.push_back(std::make_unique(name)); return {context_}; } -executable_query query_alter_table_intermediate::drop_constraint( const std::string& name ) { - context_->parts.push_back(std::make_unique(name)); +executable_query query_alter_table_intermediate::drop_constraint(const object::restriction &rest) { + context_->parts.push_back(std::make_unique( + constraint{rest.column_name(), rest.owner()->name(), rest.attribute().attributes().options(), rest.ref_table_name(), rest.ref_column_name()}) + ); + return {context_}; +} + +executable_query query_alter_table_intermediate::drop_constraint(const std::string& name) { + context_->parts.push_back(std::make_unique(name)); return {context_}; } } \ No newline at end of file diff --git a/source/orm/query/internal/query_parts.cpp b/source/orm/query/internal/query_parts.cpp index a0194f2..bf710c9 100644 --- a/source/orm/query/internal/query_parts.cpp +++ b/source/orm/query/internal/query_parts.cpp @@ -34,25 +34,42 @@ const std::string& query_add_key_constraint_part::name() const { return name_; } -query_drop_key_constraint_part::query_drop_key_constraint_part(std::string name) -: query_part( sql::dialect_token::DropConstraint ) -, name_(std::move( name )){} +query_add_constraint_part_by_constraint::query_add_constraint_part_by_constraint(const query::constraint &co) +: query_part(sql::dialect_token::AddConstraint) +, constraint_(co) {} -void query_drop_key_constraint_part::accept( query_part_visitor& visitor ) { +void query_add_constraint_part_by_constraint::accept(query_part_visitor &visitor) { visitor.visit(*this); } -const std::string& query_drop_key_constraint_part::name() const { +const class constraint & query_add_constraint_part_by_constraint::constraint() const { + return constraint_; +} + +query_drop_key_constraint_part_by_name::query_drop_key_constraint_part_by_name(std::string name) +: query_part( sql::dialect_token::DropConstraint ) +, name_(std::move( name )){} + +void query_drop_key_constraint_part_by_name::accept(query_part_visitor& visitor) { + visitor.visit(*this); +} + +const std::string& query_drop_key_constraint_part_by_name::name() const { return name_; } -query_drop_foreign_key_constraint_part::query_drop_foreign_key_constraint_part() -: query_part( sql::dialect_token::DropConstraint ) {} +query_drop_key_constraint_part_by_constraint::query_drop_key_constraint_part_by_constraint(const class constraint &co) +: query_part( sql::dialect_token::DropConstraint ) +, constraint_(co) {} -void query_drop_foreign_key_constraint_part::accept( query_part_visitor& visitor ) { +void query_drop_key_constraint_part_by_constraint::accept(query_part_visitor& visitor) { visitor.visit(*this); } +const class constraint& query_drop_key_constraint_part_by_constraint::constraint() const { + return constraint_; +} + query_add_foreign_key_constraint_part::query_add_foreign_key_constraint_part(const std::vector& columns) : query_part(sql::dialect_token::ForeignKey) , columns_(columns) {} diff --git a/source/orm/query/query_compiler.cpp b/source/orm/query/query_compiler.cpp index 7624fe4..1b14fc8 100644 --- a/source/orm/query/query_compiler.cpp +++ b/source/orm/query/query_compiler.cpp @@ -117,11 +117,15 @@ void query_compiler::visit(internal::query_add_foreign_key_reference_part& part) query_.sql += ")"; } -void query_compiler::visit(internal::query_drop_key_constraint_part& part) { - query_.sql += " " + dialect_->token_at(part.token()) + " " + part.name(); +void query_compiler::visit(internal::query_add_constraint_part_by_constraint &part) { + query_.sql += build_add_constraint_string(part.constraint()); } -void query_compiler::visit(internal::query_drop_foreign_key_constraint_part& part) { +void query_compiler::visit(internal::query_drop_key_constraint_part_by_name& part) { + query_.sql += " " + dialect_->token_at(part.token()) + " " + part.name(); +} + +void query_compiler::visit(internal::query_drop_key_constraint_part_by_constraint& part) { } void query_compiler::visit(internal::query_select_part &part) { @@ -385,10 +389,13 @@ std::string build_create_column(const column &col, const sql::dialect &d) { result.append("(" + std::to_string(col.attributes().size()) + ")"); } if (!col.is_nullable()) { - result.append(" NOT NULL"); + result.append(" ").append(d.not_null()); } if (is_constraint_set(col.attributes().options(), utils::constraints::Unique)) { - result.append(" UNIQUE"); + result.append(" ").append(d.unique()); + } + if (is_constraint_set(col.attributes().options(), utils::constraints::PrimaryKey)) { + result.append(" ").append(d.primary_key()); } return result; @@ -429,4 +436,32 @@ std::string query_compiler::build_table_name(const sql::dialect_token token, con (t.alias().empty() ? "" : " " + d.prepare_identifier_string(t.alias())); } -} \ No newline at end of file +std::string query_compiler::build_add_constraint_string(const class constraint &c) { + std::string result = dialect_->add_constraint() + " " + build_constraint_name(c) + " "; + if (c.is_primary_key_constraint()) { + result.append(dialect_->primary_key()).append(" (").append(c.column_name()).append(")"); + } else if (c.is_foreign_key_constraint()) { + result.append(dialect_->foreign_key()).append(" (").append(c.column_name()).append(") ").append(dialect_->references()).append(" ").append(c.referenced_table()).append(" (").append(c.referenced_column()).append(")"); + } else if (c.is_unique_constraint()) { + result.append(dialect_->unique()).append(" (").append(c.column_name()).append(")"); + } + return result; +} + +std::string query_compiler::build_drop_constraint_string(const class constraint &c) { + +} + +std::string query_compiler::build_constraint_name(const class constraint &c) { + if (c.is_primary_key_constraint()) { + return "PK_" + c.table_name(); + } + if (c.is_foreign_key_constraint()) { + return "FK_" + c.column_name() + "_" + c.table_name(); + } + if (c.is_unique_constraint()) { + return "UK_" + c.column_name() + "_" + c.table_name(); + } + return ""; +} +} diff --git a/source/orm/sql/dialect.cpp b/source/orm/sql/dialect.cpp index 970a890..ede0d4b 100644 --- a/source/orm/sql/dialect.cpp +++ b/source/orm/sql/dialect.cpp @@ -308,6 +308,10 @@ const std::string& dialect::table() const { return token_at(dialect_token::Table); } +const std::string & dialect::unique() const { + return token_at(dialect_token::Unique); +} + const std::string& dialect::update() const { return token_at(dialect_token::Update); }