From c87a4c29b44e735d529206d51a2bbc064c502d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sascha=20K=C3=BChl?= Date: Tue, 4 Nov 2025 16:24:43 +0100 Subject: [PATCH] added alter table command to fluent query builder (progress) --- .../query_alter_table_intermediate.hpp | 12 +---- include/matador/sql/dialect.hpp | 7 +-- .../query_alter_table_intermediate.cpp | 10 +---- source/orm/query/query_compiler.cpp | 45 ++++++++++++++++--- test/orm/query/QueryBuilderTest.cpp | 17 +++++++ 5 files changed, 62 insertions(+), 29 deletions(-) diff --git a/include/matador/query/intermediates/query_alter_table_intermediate.hpp b/include/matador/query/intermediates/query_alter_table_intermediate.hpp index 0e66157..14f5da2 100644 --- a/include/matador/query/intermediates/query_alter_table_intermediate.hpp +++ b/include/matador/query/intermediates/query_alter_table_intermediate.hpp @@ -30,22 +30,12 @@ public: query_add_foreign_key_constraint_intermediate foreign_keys(const std::vector& columns) const; }; -class query_drop_key_constraint_intermediate final : public query_intermediate { -public: - using query_intermediate::query_intermediate; - - void constraint(const std::string& name); - void primary_key(); - void foreign_key(const std::string& name); - void foreign_keys(const std::vector& names); -}; - class query_alter_table_intermediate final : public query_intermediate { public: using query_intermediate::query_intermediate; query_add_key_constraint_intermediate add_constraint(const std::string& name); - query_drop_key_constraint_intermediate drop_constraint(const std::string& name); + executable_query drop_constraint(const std::string& name); }; } diff --git a/include/matador/sql/dialect.hpp b/include/matador/sql/dialect.hpp index 6baa362..9dab6a4 100644 --- a/include/matador/sql/dialect.hpp +++ b/include/matador/sql/dialect.hpp @@ -161,8 +161,8 @@ private: {dialect_token::Like, "LIKE"}, {dialect_token::Between, "BETWEEN"}, {dialect_token::In, "IN"}, - {dialect_token::OrderBy, "ORDER BY"}, - {dialect_token::GroupBy, "GROUP BY"}, + {dialect_token::OrderBy, "ORDER BY"}, + {dialect_token::GroupBy, "GROUP BY"}, {dialect_token::Asc, "ASC"}, {dialect_token::Desc, "DESC"}, {dialect_token::Offset, "OFFSET"}, @@ -174,7 +174,8 @@ private: {dialect_token::NotNull, "NOT NULL"}, {dialect_token::PrimaryKey, "PRIMARY KEY"}, {dialect_token::ForeignKey, "FOREIGN KEY"}, - {dialect_token::AddConstraint, "Add CONSTRAINT"}, + {dialect_token::References, "REFERENCES"}, + {dialect_token::AddConstraint, "ADD CONSTRAINT"}, {dialect_token::DropConstraint, "DROP CONSTRAINT"}, {dialect_token::Begin, "BEGIN TRANSACTION"}, {dialect_token::Commit, "COMMIT TRANSACTION"}, diff --git a/source/orm/query/intermediates/query_alter_table_intermediate.cpp b/source/orm/query/intermediates/query_alter_table_intermediate.cpp index ebfcccd..2baa17f 100644 --- a/source/orm/query/intermediates/query_alter_table_intermediate.cpp +++ b/source/orm/query/intermediates/query_alter_table_intermediate.cpp @@ -29,21 +29,13 @@ query_add_foreign_key_constraint_intermediate query_add_key_constraint_intermedi return {context_}; } -void query_drop_key_constraint_intermediate::constraint( const std::string& name ) {} - -void query_drop_key_constraint_intermediate::primary_key() {} - -void query_drop_key_constraint_intermediate::foreign_key( const std::string& name ) {} - -void query_drop_key_constraint_intermediate::foreign_keys( const std::vector& names ) {} - 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_}; } -query_drop_key_constraint_intermediate query_alter_table_intermediate::drop_constraint( const std::string& name ) { +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 c777519..9cb8216 100644 --- a/source/orm/query/query_compiler.cpp +++ b/source/orm/query/query_compiler.cpp @@ -52,26 +52,59 @@ std::string handle_column(sql::query_context &ctx, const sql::dialect *d, const } void query_compiler::visit(internal::query_alter_part& part) { - query_.sql = dialect_->token_at(sql::dialect_token::Create); + query_.sql = dialect_->token_at(part.token()); } void query_compiler::visit(internal::query_alter_table_part& part) { query_.command = sql::sql_command::SQL_ALTER_TABLE; - query_.sql += " " + dialect_->token_at(sql::dialect_token::Table) + " " + + query_.sql += " " + dialect_->token_at(part.token()) + " " + dialect_->prepare_identifier_string(part.table().name); } void query_compiler::visit(internal::query_add_key_constraint_part& part) { - query_.sql += " " + dialect_->token_at(sql::dialect_token::AddConstraint) + " " + part.name(); + query_.sql += " " + dialect_->token_at(sql::dialect_token::AddConstraint) + " " + part.name(); } -void query_compiler::visit( internal::query_add_foreign_key_constraint_part& part ) {} +void query_compiler::visit( internal::query_add_foreign_key_constraint_part& part ) { + query_.sql += " " + dialect_->token_at(part.token()) + " ("; + + if (part.columns().size() < 2) { + for (const auto &col: part.columns()) { + query_.sql += dialect_->prepare_identifier_string(col.name); + } + } else { + auto it = part.columns().begin(); + query_.sql += dialect_->prepare_identifier_string(it->name); + for (; it != part.columns().end(); ++it) { + query_.sql += ", " + dialect_->prepare_identifier_string(it->name); + } + } + query_.sql += ")"; +} void query_compiler::visit( internal::query_add_primary_key_constraint_part& part ) {} -void query_compiler::visit( internal::query_add_foreign_key_reference_part& part ) {} +void query_compiler::visit( internal::query_add_foreign_key_reference_part& part ) { + query_.sql += " " + dialect_->token_at(part.token()) + " " + + part.table().name + " ("; -void query_compiler::visit(internal::query_drop_key_constraint_part& part) {} + if (part.columns().size() < 2) { + for (const auto &col: part.columns()) { + query_.sql += dialect_->prepare_identifier_string(col.name); + } + } else { + auto it = part.columns().begin(); + query_.sql += dialect_->prepare_identifier_string(it->name); + for (; it != part.columns().end(); ++it) { + query_.sql += ", " + dialect_->prepare_identifier_string(it->name); + } + } + 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_select_part &select_part) { diff --git a/test/orm/query/QueryBuilderTest.cpp b/test/orm/query/QueryBuilderTest.cpp index 0e105ea..0427e38 100644 --- a/test/orm/query/QueryBuilderTest.cpp +++ b/test/orm/query/QueryBuilderTest.cpp @@ -18,6 +18,23 @@ using namespace matador::sql; using namespace matador::query; using namespace matador::utils; +TEST_CASE_METHOD(QueryFixture, "Test alter table sql statement", "[query][alter][table]") { + auto result = query::alter() + .table("employees") + .add_constraint("FK_employees_dep_id") + .foreign_key("dep_id"_col) + .references("departments", {"id"_col}) + .str(*db); + + REQUIRE(result == R"(ALTER TABLE "employees" ADD CONSTRAINT FK_employees_dep_id FOREIGN KEY ("dep_id") REFERENCES departments ("id"))"); + result = query::alter() + .table("employees") + .drop_constraint("FK_employees_dep_id") + .str(*db); + + REQUIRE(result == R"(ALTER TABLE "employees" DROP CONSTRAINT FK_employees_dep_id)"); +} + TEST_CASE_METHOD(QueryFixture, "Test create table sql statement string", "[query]") { auto result = query::create() .table({"person"}, {