fixed schema creation

This commit is contained in:
Sascha Kühl 2025-12-04 16:06:39 +01:00
parent 19eb54df8d
commit 980cabe94f
12 changed files with 152 additions and 95 deletions

View File

@ -111,10 +111,10 @@ utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> postgres_co
std::string postgres_connection::generate_statement_name(const sql::query_context &query) { std::string postgres_connection::generate_statement_name(const sql::query_context &query) {
std::stringstream name; std::stringstream name;
name << query.table_name << "_" << query.command_name; name << query.table_name << "_" << query.command_name;
auto result = postgres_connection::statement_name_map_.find(name.str()); auto result = statement_name_map_.find(name.str());
if (result == postgres_connection::statement_name_map_.end()) { if (result == statement_name_map_.end()) {
result = postgres_connection::statement_name_map_.insert(std::make_pair(name.str(), 0)).first; result = statement_name_map_.insert(std::make_pair(name.str(), 0)).first;
} }
name << "_" << ++result->second; name << "_" << ++result->second;
@ -123,7 +123,7 @@ std::string postgres_connection::generate_statement_name(const sql::query_contex
} }
utils::result<std::unique_ptr<sql::statement_impl>, utils::error> postgres_connection::prepare(const sql::query_context &context) { utils::result<std::unique_ptr<sql::statement_impl>, utils::error> postgres_connection::prepare(const sql::query_context &context) {
auto statement_name = postgres_connection::generate_statement_name(context); auto statement_name = generate_statement_name(context);
const PGresult *result = PQprepare(conn_, statement_name.c_str(), context.sql.c_str(), const PGresult *result = PQprepare(conn_, statement_name.c_str(), context.sql.c_str(),
static_cast<int>(context.bind_vars.size()), nullptr); static_cast<int>(context.bind_vars.size()), nullptr);

View File

@ -33,6 +33,8 @@ public:
[[nodiscard]] const utils::identifier& primary_key() const; [[nodiscard]] const utils::identifier& primary_key() const;
[[nodiscard]] attribute* primary_key_attribute() const; [[nodiscard]] attribute* primary_key_attribute() const;
void update_name(const std::string& name);
endpoint_iterator register_relation_endpoint(const std::type_index &type, const std::shared_ptr<relation_endpoint> &endpoint); endpoint_iterator register_relation_endpoint(const std::type_index &type, const std::shared_ptr<relation_endpoint> &endpoint);
void unregister_relation_endpoint(const std::type_index &type); void unregister_relation_endpoint(const std::type_index &type);

View File

@ -3,6 +3,8 @@
#include "matador/object/repository.hpp" #include "matador/object/repository.hpp"
#include "matador/sql/query_context.hpp"
namespace matador::sql { namespace matador::sql {
class connection_pool; class connection_pool;
} }
@ -49,6 +51,10 @@ public:
[[nodiscard]] utils::result<std::vector<object::attribute>, utils::error> describe_table(const std::string &table_name) const; [[nodiscard]] utils::result<std::vector<object::attribute>, utils::error> describe_table(const std::string &table_name) const;
[[nodiscard]] utils::result<bool, utils::error> table_exists(const std::string &table_name) const; [[nodiscard]] utils::result<bool, utils::error> table_exists(const std::string &table_name) const;
private:
sql::query_context build_add_constraint_context( const object::repository_node& node, const class object::constraint& cons ) const;
sql::query_context build_drop_constraint_context( const object::repository_node& node, const class object::constraint& cons ) const;
private: private:
object::repository repo_; object::repository repo_;
sql::connection_pool &pool_; sql::connection_pool &pool_;

View File

@ -2,10 +2,11 @@
#define MATADOR_QUERY_ALTER_TABLE_INTERMEDIATE_HPP #define MATADOR_QUERY_ALTER_TABLE_INTERMEDIATE_HPP
#include "executable_query.hpp" #include "executable_query.hpp"
#include "matador/object/constraint.hpp"
#include "matador/query/intermediates/query_intermediate.hpp" #include "matador/query/intermediates/query_intermediate.hpp"
namespace matador::query { namespace matador::query {
class query_add_primary_key_constraint_intermediate final : public query_intermediate { class query_add_primary_key_constraint_intermediate final : public executable_query {
public: public:
}; };
@ -35,6 +36,7 @@ public:
using query_intermediate::query_intermediate; using query_intermediate::query_intermediate;
query_add_key_constraint_intermediate add_constraint(const std::string& name); 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); executable_query drop_constraint(const std::string& name);
}; };
} }

View File

@ -23,7 +23,9 @@ enum class sql_command {
SQL_DROP_TABLE, SQL_DROP_TABLE,
SQL_DROP_SCHEMA, SQL_DROP_SCHEMA,
SQL_DROP_DATABASE, SQL_DROP_DATABASE,
SQL_ALTER_TABLE SQL_ALTER,
SQL_ALTER_TABLE,
SQL_ALTER_SCHEMA
}; };
struct sql_command_info { struct sql_command_info {
@ -38,14 +40,12 @@ struct query_context {
std::string schema_name{}; std::string schema_name{};
std::string table_name{}; std::string table_name{};
std::vector<object::attribute> prototype{}; std::vector<object::attribute> prototype{};
std::vector<std::string> result_vars{}; // std::vector<std::string> result_vars{};
std::vector<std::string> bind_vars{}; std::vector<std::string> bind_vars{};
std::vector<utils::database_type> bind_types{}; std::vector<utils::database_type> bind_types{};
std::unordered_map<std::string, std::string> column_aliases{}; // std::unordered_map<std::string, std::string> column_aliases{};
std::unordered_map<std::string, std::string> table_aliases{}; // std::unordered_map<std::string, std::string> table_aliases{};
std::vector<sql_command_info> additional_commands{};
}; };
} }

View File

@ -52,6 +52,10 @@ attribute* basic_object_info::primary_key_attribute() const {
return object_->primary_key_attribute(); return object_->primary_key_attribute();
} }
void basic_object_info::update_name(const std::string& name) {
object_->update_name(name);
}
basic_object_info::endpoint_iterator basic_object_info::register_relation_endpoint(const std::type_index &type, const std::shared_ptr<relation_endpoint> &endpoint) { basic_object_info::endpoint_iterator basic_object_info::register_relation_endpoint(const std::type_index &type, const std::shared_ptr<relation_endpoint> &endpoint) {
return relation_endpoints_.insert(std::make_pair(type, endpoint)).first; return relation_endpoints_.insert(std::make_pair(type, endpoint)).first;
} }

View File

@ -43,6 +43,13 @@ const std::string& object::alias() const {
void object::update_name(const std::string& name) { void object::update_name(const std::string& name) {
name_ = name; name_ = name;
for (auto& con : constraints_) {
if (con.is_primary_key_constraint()) {
con.name_ += name;
} else if (con.is_foreign_key_constraint()) {
con.name_ = "FK_" + name + "_" + con.column_name();
}
}
} }
bool object::has_attributes() const { bool object::has_attributes() const {

View File

@ -45,9 +45,7 @@ const basic_object_info &repository_node::info() const {
void repository_node::update_name(const std::string& name) { void repository_node::update_name(const std::string& name) {
name_ = name; name_ = name;
// if (info_->reference_column()) { info_->update_name(name);
// info_->reference_column()->table_name(name);
// }
} }
const repository& repository_node::schema() const { const repository& repository_node::schema() const {

View File

@ -18,9 +18,8 @@ schema::schema(sql::connection_pool& pool)
schema::schema(sql::connection_pool &pool, const std::string& name) schema::schema(sql::connection_pool &pool, const std::string& name)
: repo_(name) : repo_(name)
, pool_(pool) {} , pool_(pool) {}
}
matador::utils::result<void, matador::utils::error> matador::orm::schema::create() const { utils::result<void, utils::error> schema::create() const {
// Step 1: Build dependency graph // Step 1: Build dependency graph
// std::unordered_map<std::string, std::vector<std::string> > dependency_graph; // std::unordered_map<std::string, std::vector<std::string> > dependency_graph;
// std::unordered_map<std::string, std::pair<int,object::repository::node_ptr>> in_degree; // std::unordered_map<std::string, std::pair<int,object::repository::node_ptr>> in_degree;
@ -51,37 +50,40 @@ matador::utils::result<void, matador::utils::error> matador::orm::schema::create
// } // }
std::vector<std::string> fk_sql_commands; std::vector<std::string> fk_sql_commands;
auto c = pool_.acquire(); const auto c = pool_.acquire();
// auto result = query::query::create().schema( repo_.name() ).compile( *c ); const auto q = query::query::create().schema( repo_.name() ).compile( *c );
// std::cout << result.sql << std::endl; std::cout << q.sql << std::endl;
// create plain tables without constraints
for (const auto &node: repo_) { for (const auto &node: repo_) {
auto ctx = query::query::create() auto ctx = query::query::create()
.table(node->name()) .table(node->name())
.columns(node->info().attributes()) .columns(node->info().attributes())
.constraints(node->info().constraints()) // .constraints(node->info().constraints())
.compile(*c); .compile(*c);
for ( const auto& [sql, command] : ctx.additional_commands ) {
fk_sql_commands.push_back( sql );
}
std::cout << ctx.sql << std::endl; std::cout << ctx.sql << std::endl;
if (auto result = c->execute(ctx.sql); !result) { if (auto result = c->execute(ctx.sql); !result) {
return utils::failure(result.err()); return utils::failure(result.err());
} }
} }
// execute additional commands (e.g. ALTER TABLE ADD FK) // create table constraints
for (const auto &sql: fk_sql_commands) { for (const auto &node: repo_) {
std::cout << sql << std::endl; for (const auto& cons : node->info().constraints()) {
if (auto result = c->execute(sql); !result) { auto ctx = build_add_constraint_context(*node, cons);
return utils::failure(result.err());
std::cout << ctx.sql << std::endl;
if (auto result = c->execute(ctx.sql); !result) {
return utils::failure(result.err());
}
} }
} }
return utils::ok<void>(); return utils::ok<void>();
} }
matador::utils::result<void, matador::utils::error> matador::orm::schema::drop() const { utils::result<void, utils::error> schema::drop() const {
std::vector<std::string> drop_sql_commands; std::vector<std::string> drop_sql_commands;
auto c = pool_.acquire(); auto c = pool_.acquire();
for (const auto &node: repo_) { for (const auto &node: repo_) {
@ -117,30 +119,57 @@ matador::utils::result<void, matador::utils::error> matador::orm::schema::drop()
return utils::ok<void>(); return utils::ok<void>();
} }
matador::utils::result<void, matador::utils::error> matador::orm::schema::drop_table(const std::string& table_name) const { utils::result<void, utils::error> schema::drop_table(const std::string& table_name) const {
const auto c = pool_.acquire(); const auto c = pool_.acquire();
auto result = query::query::drop() auto result = query::query::drop()
.table(table_name) .table(table_name)
.execute(*c); .execute(*c);
if (result.is_error()) { if (result.is_error()) {
return utils::failure(result.err()); return utils::failure(result.err());
} }
return utils::ok<void>(); return utils::ok<void>();
} }
matador::utils::result<std::vector<matador::object::attribute>, matador::utils::error> matador::orm::schema::describe_table(const std::string& table_name) const { utils::result<std::vector<object::attribute>, utils::error> schema::describe_table(const std::string& table_name) const {
const auto c = pool_.acquire(); const auto c = pool_.acquire();
if (!c.valid()) { if (!c.valid()) {
return utils::failure(make_error(error_code::NoConnectionAvailable, "Failed to acquire connection.")); return utils::failure(make_error(error_code::NoConnectionAvailable, "Failed to acquire connection."));
} }
return utils::ok(c->describe(table_name).release()); return utils::ok(c->describe(table_name).release());
} }
matador::utils::result<bool, matador::utils::error> matador::orm::schema::table_exists(const std::string& table_name) const { utils::result<bool, utils::error> schema::table_exists(const std::string& table_name) const {
const auto c = pool_.acquire(); const auto c = pool_.acquire();
if (!c.valid()) { if (!c.valid()) {
return utils::failure(make_error(error_code::NoConnectionAvailable, "Failed to acquire connection.")); return utils::failure(make_error(error_code::NoConnectionAvailable, "Failed to acquire connection."));
} }
return c->exists(repo_.name(), table_name); return c->exists(repo_.name(), table_name);
} }
sql::query_context schema::build_add_constraint_context( const object::repository_node& node, const class object::constraint& cons ) const {
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()})
.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())
.compile(*pool_.acquire());
}
return {};
}
sql::query_context schema::build_drop_constraint_context( const object::repository_node& node, const class object::constraint& cons ) const {
return query::query::alter()
.table(node.name())
.drop_constraint(cons.name())
.compile(*pool_.acquire());
}
}

View File

@ -57,9 +57,9 @@ utils::result<void, utils::error> session::create_schema() const {
.constraints(node->info().constraints()) .constraints(node->info().constraints())
.compile(*c); .compile(*c);
for ( const auto& [sql, command] : ctx.additional_commands ) { // for ( const auto& [sql, command] : ctx.additional_commands ) {
fk_sql_commands.push_back( sql ); // fk_sql_commands.push_back( sql );
} // }
std::cout << ctx.sql << std::endl; std::cout << ctx.sql << std::endl;
if (auto result = c->execute(ctx.sql); !result) { if (auto result = c->execute(ctx.sql); !result) {
return utils::failure(result.err()); return utils::failure(result.err());

View File

@ -35,6 +35,10 @@ query_add_key_constraint_intermediate query_alter_table_intermediate::add_constr
return {context_}; 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 ) { executable_query query_alter_table_intermediate::drop_constraint( const std::string& name ) {
context_->parts.push_back(std::make_unique<internal::query_drop_key_constraint_part>(name)); context_->parts.push_back(std::make_unique<internal::query_drop_key_constraint_part>(name));
return {context_}; return {context_};

View File

@ -36,9 +36,9 @@ 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) { 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()); // ctx.result_vars.emplace_back(col.column_name());
const auto& column_table = col.table().get(); 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()}); // ctx.column_aliases.insert({column_table->has_alias() ? column_table->alias() : column_table->name() + "." + col.column_name(), col.alias()});
if (col.is_function()) { if (col.is_function()) {
ctx.prototype.emplace_back(col.has_alias() ? col.alias() : col.column_name()); ctx.prototype.emplace_back(col.has_alias() ? col.alias() : col.column_name());
ctx.prototype.back().change_type(utils::basic_type::type_int32); ctx.prototype.back().change_type(utils::basic_type::type_int32);
@ -64,7 +64,7 @@ void query_compiler::visit(internal::query_alter_table_part& part) {
} }
void query_compiler::visit(internal::query_add_key_constraint_part& part) { 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_->add_constraint() + " " + 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) {
@ -84,7 +84,22 @@ void query_compiler::visit(internal::query_add_foreign_key_constraint_part& part
query_.sql += ")"; query_.sql += ")";
} }
void query_compiler::visit(internal::query_add_primary_key_constraint_part& part) {} void query_compiler::visit(internal::query_add_primary_key_constraint_part& part) {
query_.sql += " " + dialect_->primary_key() + " (";
if (part.columns().size() < 2) {
for (const auto &col: part.columns()) {
query_.sql += dialect_->prepare_identifier_string(col.column_name());
}
} else {
auto it = part.columns().begin();
query_.sql += dialect_->prepare_identifier_string(it->column_name());
for (; it != part.columns().end(); ++it) {
query_.sql += ", " + dialect_->prepare_identifier_string(it->column_name());
}
}
query_.sql += ")";
}
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() + " ("; query_.sql += " " + dialect_->token_at(part.token()) + " " + part.table().name() + " (";
@ -110,16 +125,15 @@ void query_compiler::visit(internal::query_drop_key_constraint_part& part) {
void query_compiler::visit(internal::query_drop_foreign_key_constraint_part& part) { void query_compiler::visit(internal::query_drop_foreign_key_constraint_part& part) {
} }
void query_compiler::visit(internal::query_select_part &part) void query_compiler::visit(internal::query_select_part &part) {
{
query_.command = sql::sql_command::SQL_SELECT; query_.command = sql::sql_command::SQL_SELECT;
query_.sql = dialect_->token_at(sql::dialect_token::Select) + " "; query_.sql = dialect_->select() + " ";
query_.prototype.clear(); query_.prototype.clear();
std::string result; std::string result;
if (part.columns().empty()) { if (part.columns().empty()) {
result = dialect_->token_at(sql::dialect_token::Asterisk); result = dialect_->asterisk();
} else if (const auto &columns = part.columns(); columns.size() < 2) { } else if (const auto &columns = part.columns(); columns.size() < 2) {
for (const auto &col: columns) { for (const auto &col: columns) {
result.append(handle_column(query_, dialect_, *data_, col )); result.append(handle_column(query_, dialect_, *data_, col ));
@ -139,7 +153,7 @@ void query_compiler::visit(internal::query_select_part &part)
void query_compiler::visit(internal::query_from_part &part) { void query_compiler::visit(internal::query_from_part &part) {
query_.table_name = part.table().name(); query_.table_name = part.table().name();
query_.sql += " " + build_table_name(part.token(), *dialect_, part.table()); query_.sql += " " + build_table_name(part.token(), *dialect_, part.table());
query_.table_aliases.insert({query_.table_name, part.table().alias()}); // query_.table_aliases.insert({query_.table_name, part.table().alias()});
} }
void query_compiler::visit(internal::query_join_part &part) void query_compiler::visit(internal::query_join_part &part)
@ -149,56 +163,56 @@ void query_compiler::visit(internal::query_join_part &part)
void query_compiler::visit(internal::query_on_part &part) { void query_compiler::visit(internal::query_on_part &part) {
criteria_evaluator evaluator(*dialect_, query_); criteria_evaluator evaluator(*dialect_, query_);
query_.sql += " " + dialect_->token_at(sql::dialect_token::On) + query_.sql += " " + dialect_->on() +
" " + evaluator.evaluate(part.condition()); " " + evaluator.evaluate(part.condition());
} }
void query_compiler::visit(internal::query_where_part &part) { void query_compiler::visit(internal::query_where_part &part) {
criteria_evaluator evaluator(*dialect_, query_); criteria_evaluator evaluator(*dialect_, query_);
query_.sql += " " + dialect_->token_at(sql::dialect_token::Where) + query_.sql += " " + dialect_->where() +
" " + evaluator.evaluate(part.condition()); " " + evaluator.evaluate(part.condition());
} }
void query_compiler::visit(internal::query_group_by_part &part) { void query_compiler::visit(internal::query_group_by_part &part) {
query_.sql += " " + dialect_->token_at(sql::dialect_token::GroupBy) + " " + prepare_identifier(*dialect_, part.column()); 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_->token_at(sql::dialect_token::OrderBy) + query_.sql += " " + dialect_->order_by() +
" " + prepare_criteria(*dialect_, part.column()); " " + 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_->token_at(sql::dialect_token::Asc); 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_->token_at(sql::dialect_token::Desc); 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_->token_at(sql::dialect_token::Offset) + " " + std::to_string(part.offset()); 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_->token_at(sql::dialect_token::Limit) + " " + std::to_string(part.limit()); 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_.command = sql::sql_command::SQL_INSERT;
query_.sql = dialect_->token_at(sql::dialect_token::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_.table_name = part.table().name();
query_.sql += " " + dialect_->token_at(sql::dialect_token::Into) + query_.sql += " " + dialect_->into() +
" " + dialect_->prepare_identifier_string(part.table().name()); " " + dialect_->prepare_identifier_string(part.table().name());
std::string result{"("}; std::string result{"("};
@ -240,7 +254,7 @@ std::string query_compiler::determine_value(value_visitor &visitor, const std::v
} }
void query_compiler::visit(internal::query_values_part &part) { void query_compiler::visit(internal::query_values_part &part) {
query_.sql += " " + dialect_->token_at(sql::dialect_token::Values); query_.sql += " " + dialect_->values();
attribute_string_writer writer(*dialect_, connection_); attribute_string_writer writer(*dialect_, connection_);
@ -275,7 +289,7 @@ void query_compiler::visit(internal::query_update_part &part)
void query_compiler::visit(internal::query_delete_part &/*delete_part*/) void query_compiler::visit(internal::query_delete_part &/*delete_part*/)
{ {
query_.command = sql::sql_command::SQL_DELETE; query_.command = sql::sql_command::SQL_DELETE;
query_.sql = dialect_->token_at(sql::dialect_token::Remove); query_.sql = dialect_->remove();
} }
void query_compiler::visit(internal::query_delete_from_part &part) void query_compiler::visit(internal::query_delete_from_part &part)
@ -287,7 +301,7 @@ void query_compiler::visit(internal::query_delete_from_part &part)
void query_compiler::visit(internal::query_create_part &/*create_part*/) void query_compiler::visit(internal::query_create_part &/*create_part*/)
{ {
query_.command = sql::sql_command::SQL_CREATE_TABLE; query_.command = sql::sql_command::SQL_CREATE_TABLE;
query_.sql = dialect_->token_at(sql::dialect_token::Create); query_.sql = dialect_->create();
} }
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);
@ -295,22 +309,9 @@ std::string build_constraint(const class object::constraint &cons, const sql::di
void query_compiler::visit(internal::query_create_table_part &part) void query_compiler::visit(internal::query_create_table_part &part)
{ {
query_.sql += " " + dialect_->token_at(sql::dialect_token::Table) + " " + dialect_->prepare_identifier_string(part.table().name()) + " ("; query_.sql += " " + dialect_->table() + " " + dialect_->prepare_identifier_string(part.table().name()) + " (";
query_.table_name = part.table().name(); query_.table_name = part.table().name();
// if (!context.primary_keys.empty()) {
// result.append(", CONSTRAINT PK_" + part.table().name() + " PRIMARY KEY (" + utils::join(context.primary_keys, ", ") + ")");
// }
// for (const auto &[column, reference_column]: context.foreign_contexts) {
// // ALTER TABLE Orders ADD CONSTRAINT FK_PersonOrder FOREIGN KEY (PersonID) REFERENCES Persons(PersonID);
// std::string fk_cmd = "ALTER TABLE " + dialect_->prepare_identifier_string(query_.table_name) + " ADD";
// fk_cmd += " CONSTRAINT FK_" + query_.table_name;
// fk_cmd += "_" + column;
// fk_cmd += " FOREIGN KEY (" + dialect_->prepare_identifier_string(column) + ")";
// fk_cmd += " REFERENCES " + reference_column->table_name() + "(" + reference_column->name() + ")";
// query_.additional_commands.push_back({fk_cmd, sql::sql_command::SQL_ALTER_TABLE});
// }
finisher_ = [](sql::query_context &ctx) { ctx.sql += ")"; }; finisher_ = [](sql::query_context &ctx) { ctx.sql += ")"; };
} }
@ -343,8 +344,8 @@ void query_compiler::visit(internal::query_create_table_constraints_part& part)
} }
void query_compiler::visit( internal::query_create_schema_part& part ) { void query_compiler::visit( internal::query_create_schema_part& part ) {
query_.sql += " " + dialect_->token_at(sql::dialect_token::Create) + " " + query_.sql += " " + dialect_->create() + " " +
dialect_->token_at(sql::dialect_token::Schema) + " " + dialect_->prepare_identifier_string(part.schema()); dialect_->schema() + " " + dialect_->prepare_identifier_string(part.schema());
} }
void query_compiler::visit(internal::query_drop_part &part) { void query_compiler::visit(internal::query_drop_part &part) {
@ -353,12 +354,12 @@ void query_compiler::visit(internal::query_drop_part &part) {
} }
void query_compiler::visit( internal::query_drop_schema_part& part ) { void query_compiler::visit( internal::query_drop_schema_part& part ) {
query_.sql += " " + dialect_->token_at(sql::dialect_token::Drop) + " " + query_.sql += " " + dialect_->drop() + " " +
dialect_->token_at(sql::dialect_token::Schema) + " " + dialect_->prepare_identifier_string(part.schema()); dialect_->schema() + " " + dialect_->prepare_identifier_string(part.schema());
} }
void query_compiler::visit(internal::query_set_part &part) { void query_compiler::visit(internal::query_set_part &part) {
query_.sql += " " + dialect_->token_at(sql::dialect_token::Set) + " "; query_.sql += " " + dialect_->set() + " ";
attribute_string_writer writer(*dialect_, connection_); attribute_string_writer writer(*dialect_, connection_);
std::string result; std::string result;
@ -410,7 +411,11 @@ std::string build_constraint(const class object::constraint& cons, const sql::di
result.append(d.constraint()).append(" ").append(cons.name()).append(" "); result.append(d.constraint()).append(" ").append(cons.name()).append(" ");
} }
if (cons.is_primary_key_constraint()) { if (cons.is_primary_key_constraint()) {
result.append(d.primary_key()).append(" (").append(cons.column_name()).append(")"); result
.append(d.primary_key())
.append(" (")
.append(cons.column_name())
.append(")");
} else if (cons.is_foreign_key_constraint()) { } else if (cons.is_foreign_key_constraint()) {
result result
.append(d.foreign_key()) .append(d.foreign_key())