From d1731a7f154f9de2d50698c7a52ccaddd2794206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sascha=20K=C3=BChl?= Date: Fri, 14 Nov 2025 16:16:07 +0100 Subject: [PATCH] some sql classes refactorings like column and table structs to classes --- include/matador/sql/column.hpp | 29 ++- include/matador/sql/dialect.hpp | 70 +++++- include/matador/sql/query_context.hpp | 1 + include/matador/sql/record.hpp | 4 +- include/matador/sql/table.hpp | 25 +- source/orm/orm/schema.cpp | 3 + source/orm/orm/session.cpp | 6 +- source/orm/orm/session_query_builder.cpp | 6 +- source/orm/query/criteria_evaluator.cpp | 8 +- .../query_insert_intermediate.cpp | 5 +- .../query_select_intermediate.cpp | 2 +- source/orm/query/query.cpp | 2 +- source/orm/query/query_compiler.cpp | 63 +++-- source/orm/sql/column.cpp | 34 ++- source/orm/sql/connection.cpp | 2 +- source/orm/sql/dialect.cpp | 229 +++++++++++++++++- source/orm/sql/record.cpp | 6 +- source/orm/sql/table.cpp | 35 ++- test/backends/SchemaTest.cpp | 2 +- test/orm/orm/SessionQueryBuilderTest.cpp | 22 +- test/orm/query/CriteriaTests.cpp | 2 +- test/orm/sql/ColumnGeneratorTest.cpp | 2 +- 22 files changed, 428 insertions(+), 130 deletions(-) diff --git a/include/matador/sql/column.hpp b/include/matador/sql/column.hpp index 2fdfba3..df60064 100644 --- a/include/matador/sql/column.hpp +++ b/include/matador/sql/column.hpp @@ -7,22 +7,23 @@ namespace matador::sql { -struct table; +class table; enum class sql_function_t { - NONE, - COUNT, - AVG, - SUM, - MIN, - MAX + None, + Count, + Avg, + Sum, + Min, + Max }; -struct column { +class column { +public: column(const char *name, const std::string& as = ""); // NOLINT(*-explicit-constructor) - explicit column(std::string name, std::string as = ""); // NOLINT(*-explicit-constructor) + explicit column(std::string name, std::string as = ""); column(sql_function_t func, std::string name); // NOLINT(*-explicit-constructor) - column(const struct table &tab, std::string name, std::string as = ""); + column(const class table &tab, std::string name, std::string as = ""); column(const std::shared_ptr &t, std::string name, std::string as = ""); [[nodiscard]] bool equals(const column &x) const; @@ -33,13 +34,17 @@ struct column { [[nodiscard]] std::string full_name() const; [[nodiscard]] const std::string& alias_name() const; [[nodiscard]] bool is_function() const; + [[nodiscard]] sql_function_t function() const; [[nodiscard]] bool has_alias() const; + [[nodiscard]] std::string alias() const; [[nodiscard]] std::shared_ptr table() const; + void table(const std::shared_ptr& t); +private: std::shared_ptr table_; std::string name; - std::string alias; - sql_function_t function_{sql_function_t::NONE}; + std::string alias_; + sql_function_t function_{sql_function_t::None}; }; column operator ""_col(const char *name, size_t len); diff --git a/include/matador/sql/dialect.hpp b/include/matador/sql/dialect.hpp index 22efd2b..7570114 100644 --- a/include/matador/sql/dialect.hpp +++ b/include/matador/sql/dialect.hpp @@ -54,6 +54,7 @@ public: [[nodiscard]] std::string prepare_identifier(const column &col) const; [[nodiscard]] std::string prepare_identifier_string(const std::string &col) const; [[nodiscard]] std::string prepare_condition(const column &col) const; + [[nodiscard]] std::string table_name(const std::string &table, const std::string &schema_name) const; [[nodiscard]] const std::string& to_string(bool val) const; @@ -124,6 +125,56 @@ public: */ [[nodiscard]] std::string default_schema_name() const; + [[nodiscard]] const std::string& add_constraint() const; + [[nodiscard]] const std::string& alter() const; + [[nodiscard]] const std::string& and_() const; + [[nodiscard]] const std::string& as() const; + [[nodiscard]] const std::string& asc() const; + [[nodiscard]] const std::string& begin() const; + [[nodiscard]] const std::string& asterisk() const; + [[nodiscard]] const std::string& begin_binary_data() const; + [[nodiscard]] const std::string& begin_string_data() const; + [[nodiscard]] const std::string& between() const; + [[nodiscard]] const std::string& column() const; + [[nodiscard]] const std::string& columns() const; + [[nodiscard]] const std::string& commit() const; + [[nodiscard]] const std::string& create() const; + [[nodiscard]] const std::string& desc() const; + [[nodiscard]] const std::string& distinct() const; + [[nodiscard]] const std::string& drop() const; + [[nodiscard]] const std::string& drop_constraint() const; + [[nodiscard]] const std::string& end_binary_data() const; + [[nodiscard]] const std::string& end_quote() const; + [[nodiscard]] const std::string& end_string_data() const; + [[nodiscard]] const std::string& foreign_key() const; + [[nodiscard]] const std::string& from() const; + [[nodiscard]] const std::string& group_by() const; + [[nodiscard]] const std::string& in() const; + [[nodiscard]] const std::string& insert() const; + [[nodiscard]] const std::string& into() const; + [[nodiscard]] const std::string& join() const; + [[nodiscard]] const std::string& like() const; + [[nodiscard]] const std::string& limit() const; + [[nodiscard]] const std::string& not_() const; + [[nodiscard]] const std::string& not_null() const; + [[nodiscard]] const std::string& offset() const; + [[nodiscard]] const std::string& on() const; + [[nodiscard]] const std::string& or_() const; + [[nodiscard]] const std::string& order_by() const; + [[nodiscard]] const std::string& primary_key() const; + [[nodiscard]] const std::string& references() const; + [[nodiscard]] const std::string& remove() const; + [[nodiscard]] const std::string& rollback() const; + [[nodiscard]] const std::string& schema() const; + [[nodiscard]] const std::string& select() const; + [[nodiscard]] const std::string& set() const; + [[nodiscard]] const std::string& start_quote() const; + [[nodiscard]] const std::string& string_quote() const; + [[nodiscard]] const std::string& table() const; + [[nodiscard]] const std::string& update() const; + [[nodiscard]] const std::string& values() const; + [[nodiscard]] const std::string& where() const; + private: dialect() = default; @@ -170,15 +221,16 @@ private: {dialect_token::Limit, "LIMIT"}, {dialect_token::None, ""}, {dialect_token::Not, "NOT"}, - {dialect_token::NotNull, "NOT NULL"}, + {dialect_token::NotNull, "NOT NULL"}, {dialect_token::Offset, "OFFSET"}, {dialect_token::On, "ON"}, {dialect_token::Or, "OR"}, {dialect_token::OrderBy, "ORDER BY"}, - {dialect_token::PrimaryKey, "PRIMARY KEY"}, - {dialect_token::References, "REFERENCES"}, + {dialect_token::PrimaryKey, "PRIMARY KEY"}, + {dialect_token::References, "REFERENCES"}, {dialect_token::Remove, "DELETE"}, {dialect_token::Rollback, "ROLLBACK TRANSACTION"}, + {dialect_token::Schema, "SCHEMA"}, {dialect_token::Select, "SELECT"}, {dialect_token::Set, "SET"}, {dialect_token::StartQuote, "\""}, @@ -210,12 +262,12 @@ private: }; sql_func_to_string_map sql_func_map_ { - {sql_function_t::NONE, "NONE" }, - {sql_function_t::COUNT, "COUNT" }, - {sql_function_t::AVG, "AVG" }, - {sql_function_t::SUM, "SUM" }, - {sql_function_t::MIN, "MIN" }, - {sql_function_t::MAX, "MAX" }, + {sql_function_t::None, "NONE" }, + {sql_function_t::Count, "COUNT" }, + {sql_function_t::Avg, "AVG" }, + {sql_function_t::Sum, "SUM" }, + {sql_function_t::Min, "MIN" }, + {sql_function_t::Max, "MAX" }, }; std::array bool_strings_ { diff --git a/include/matador/sql/query_context.hpp b/include/matador/sql/query_context.hpp index 856ee3c..2b5c902 100644 --- a/include/matador/sql/query_context.hpp +++ b/include/matador/sql/query_context.hpp @@ -34,6 +34,7 @@ struct query_context { std::string sql; sql_command command{}; std::string command_name{}; + std::string schema_name{}; sql::table table{""}; std::vector prototype{}; std::vector result_vars{}; diff --git a/include/matador/sql/record.hpp b/include/matador/sql/record.hpp index 1cf17c9..0e7b573 100644 --- a/include/matador/sql/record.hpp +++ b/include/matador/sql/record.hpp @@ -8,7 +8,7 @@ namespace matador::sql { -struct column; +class column; class record final { private: @@ -41,7 +41,7 @@ public: [[nodiscard]] const std::vector& columns() const; - [[nodiscard]] const field& at(const column &col) const; + [[nodiscard]] const field& at(const sql::column &col) const; [[nodiscard]] const field& at(size_t index) const; template std::optional at(const column &col) const { diff --git a/include/matador/sql/table.hpp b/include/matador/sql/table.hpp index 729673f..e000680 100644 --- a/include/matador/sql/table.hpp +++ b/include/matador/sql/table.hpp @@ -8,18 +8,16 @@ namespace matador::sql { -struct column; +class column; -struct table { +class table { +public: table() = default; table(const char *name); // NOLINT(*-explicit-constructor) table(std::string name); // NOLINT(*-explicit-constructor) table(const char *name, std::string as); // NOLINT(*-explicit-constructor) table(std::string name, std::string as); // NOLINT(*-explicit-constructor) - table(std::string name, std::string as, const std::vector &columns) - : name(std::move(name)) - , alias(std::move(as)) - , columns(columns) {} + table(std::string name, std::string as, const std::vector &columns); table& as(const std::string &a); @@ -29,13 +27,20 @@ struct table { [[nodiscard]] bool has_alias() const; - std::string name; - std::string alias; + [[nodiscard]] const std::string& name() const; + [[nodiscard]] const std::string& alias() const; + [[nodiscard]] const std::vector& columns() const; +private: + friend class column; - std::vector columns; + std::string name_; + std::string alias_; + + std::string schema_name_; + std::vector columns_; }; -table operator "" _tab(const char *name, size_t len); +table operator ""_tab(const char *name, size_t len); } diff --git a/source/orm/orm/schema.cpp b/source/orm/orm/schema.cpp index c9b824e..9506003 100644 --- a/source/orm/orm/schema.cpp +++ b/source/orm/orm/schema.cpp @@ -52,6 +52,9 @@ matador::utils::result matador::orm::schema::create std::vector fk_sql_commands; auto c = pool_.acquire(); + + // auto result = query::query::create().schema( repo_.name() ).compile( *c ); + // std::cout << result.sql << std::endl; for (const auto &node: repo_) { auto ctx = query::query::create() .table(node->name(), node->info().definition().columns()) diff --git a/source/orm/orm/session.cpp b/source/orm/orm/session.cpp index 26ec5b6..f3ddc07 100644 --- a/source/orm/orm/session.cpp +++ b/source/orm/orm/session.cpp @@ -90,13 +90,13 @@ utils::result, utils::error> session::fetch_all(c if (!c.valid()) { return utils::failure(make_error(error_code::NoConnectionAvailable, "Failed to acquire connection.")); } - auto it = prototypes_.find(q.table.name); + auto it = prototypes_.find(q.table.name()); if (it == prototypes_.end()) { - auto result = c->describe(q.table.name); + auto result = c->describe(q.table.name()); if (!result) { return utils::failure(result.err()); } - it = prototypes_.emplace(q.table.name, *result).first; + it = prototypes_.emplace(q.table.name(), *result).first; } // adjust columns from given query for (auto &col: q.prototype) { diff --git a/source/orm/orm/session_query_builder.cpp b/source/orm/orm/session_query_builder.cpp index 63954e7..d00e1f9 100644 --- a/source/orm/orm/session_query_builder.cpp +++ b/source/orm/orm/session_query_builder.cpp @@ -39,12 +39,12 @@ void criteria_transformer::visit( const query::not_criteria& node ) { } void criteria_transformer::update_criteria_column(const query::abstract_column_criteria& node) const { - const auto it = tables_by_name_.find(node.column().table()->name); + const auto it = tables_by_name_.find(node.column().table()->name()); if (it == tables_by_name_.end()) { return; } - const_cast(node.column()).table_ = it->second; + const_cast(node.column()).table(it->second); } void session_query_builder::on_revision(const char *id, uint64_t &/*rev*/) { @@ -73,7 +73,7 @@ std::string session_query_builder::build_alias(const char prefix, const unsigned void session_query_builder::append_join(const sql::column &left, const sql::column &right) { using namespace matador::query; entity_query_data_.joins.push_back({ - {right.table_}, + {right.table()}, std::make_unique(left, binary_operator::EQUALS, right) }); } diff --git a/source/orm/query/criteria_evaluator.cpp b/source/orm/query/criteria_evaluator.cpp index 02428b9..1ab3d69 100644 --- a/source/orm/query/criteria_evaluator.cpp +++ b/source/orm/query/criteria_evaluator.cpp @@ -38,8 +38,8 @@ std::string criteria_evaluator::evaluate(const abstract_criteria &node) { } void criteria_evaluator::visit(const between_criteria &node) { - query_.bind_vars.emplace_back(node.column().name); - query_.bind_vars.emplace_back(node.column().name); + query_.bind_vars.emplace_back(node.column().column_name()); + query_.bind_vars.emplace_back(node.column().column_name()); clause_ += dialect_.prepare_identifier(node.column()) + " " + dialect_.token_at(sql::dialect_token::Between) + " "; evaluate_value(node.minimum()); clause_ += " " + dialect_.token_at(sql::dialect_token::And) + " "; @@ -50,7 +50,7 @@ template struct overload : Ts... { using Ts::operator()...; }; template overload(Ts...) -> overload; void criteria_evaluator::visit(const binary_criteria &node) { - query_.bind_vars.emplace_back(node.column().name); + query_.bind_vars.emplace_back(node.column().column_name()); clause_ += dialect_.prepare_condition(node.column()) + " " + detail::BinaryOperatorEnum.to_string(node.operand()) + " "; evaluate_value(node.value()); @@ -63,7 +63,7 @@ void criteria_evaluator::visit( const binary_column_criteria& node ) { void criteria_evaluator::visit(const collection_criteria &node) { const auto count = node.values().size(); for (size_t i = 0; i < count; ++i) { - query_.bind_vars.emplace_back(node.column().name); + query_.bind_vars.emplace_back(node.column().column_name()); } clause_ += dialect_.prepare_identifier(node.column()) + diff --git a/source/orm/query/intermediates/query_insert_intermediate.cpp b/source/orm/query/intermediates/query_insert_intermediate.cpp index 39ee71d..f48a695 100644 --- a/source/orm/query/intermediates/query_insert_intermediate.cpp +++ b/source/orm/query/intermediates/query_insert_intermediate.cpp @@ -31,9 +31,8 @@ query_into_intermediate query_insert_intermediate::into(const sql::table &table, return into(table, std::move(columns)); } -query_into_intermediate query_insert_intermediate::into(const sql::table &table) -{ - context_->parts.push_back(std::make_unique(table, table.columns)); +query_into_intermediate query_insert_intermediate::into(const sql::table &table) { + context_->parts.push_back(std::make_unique(table, table.columns())); return {context_}; } diff --git a/source/orm/query/intermediates/query_select_intermediate.cpp b/source/orm/query/intermediates/query_select_intermediate.cpp index d588586..029ffc4 100644 --- a/source/orm/query/intermediates/query_select_intermediate.cpp +++ b/source/orm/query/intermediates/query_select_intermediate.cpp @@ -14,7 +14,7 @@ query_select_intermediate::query_select_intermediate(const std::vectorparts.push_back(std::make_unique(t)); - context_->tables.insert({t.name, t}); + context_->tables.insert({t.name(), t}); return {context_}; } diff --git a/source/orm/query/query.cpp b/source/orm/query/query.cpp index 6249e2a..dd6f74f 100644 --- a/source/orm/query/query.cpp +++ b/source/orm/query/query.cpp @@ -15,7 +15,7 @@ sql::column alias(sql::column &&col, const std::string &as) sql::column count(const std::string &column) { - return {sql::sql_function_t::COUNT, column}; + return {sql::sql_function_t::Count, column}; } sql::column count_all() diff --git a/source/orm/query/query_compiler.cpp b/source/orm/query/query_compiler.cpp index f3f524d..5f4dfdd 100644 --- a/source/orm/query/query_compiler.cpp +++ b/source/orm/query/query_compiler.cpp @@ -16,8 +16,8 @@ namespace matador::query { sql::query_context query_compiler::compile(const query_data &data, - const sql::dialect &d, - const std::optional> conn) + const sql::dialect &d, + const std::optional> conn) { data_ = &data; dialect_ = &d; @@ -34,18 +34,18 @@ 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 sql::column &col) { - ctx.result_vars.emplace_back(col.name); - const auto& column_table = col.table_.get(); - ctx.column_aliases.insert({column_table->has_alias() ? column_table->alias : column_table->name + "." + col.name, col.alias}); + 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.name); + ctx.prototype.emplace_back(col.has_alias() ? col.alias() : col.column_name()); ctx.prototype.back().type(utils::basic_type::type_int32); } else { - ctx.prototype.emplace_back(col.name); + ctx.prototype.emplace_back(col.column_name()); } - if (const auto it = data.tables.find(col.table_->name); it != data.tables.end()) { - return d->prepare_identifier({it->second, col.name, col.alias}); + if (const auto it = data.tables.find(col.table()->name()); it != data.tables.end()) { + return d->prepare_identifier({it->second, col.column_name(), col.alias()}); } return d->prepare_identifier(col); @@ -58,7 +58,7 @@ void query_compiler::visit(internal::query_alter_part& part) { void query_compiler::visit(internal::query_alter_table_part& part) { query_.command = sql::sql_command::SQL_ALTER_TABLE; query_.sql += " " + dialect_->token_at(part.token()) + " " + - dialect_->prepare_identifier_string(part.table().name); + dialect_->prepare_identifier_string(part.table().name()); } void query_compiler::visit(internal::query_add_key_constraint_part& part) { @@ -70,13 +70,13 @@ void query_compiler::visit(internal::query_add_foreign_key_constraint_part& part if (part.columns().size() < 2) { for (const auto &col: part.columns()) { - query_.sql += dialect_->prepare_identifier_string(col.name); + query_.sql += dialect_->prepare_identifier_string(col.column_name()); } } else { auto it = part.columns().begin(); - query_.sql += dialect_->prepare_identifier_string(it->name); + query_.sql += dialect_->prepare_identifier_string(it->column_name()); for (; it != part.columns().end(); ++it) { - query_.sql += ", " + dialect_->prepare_identifier_string(it->name); + query_.sql += ", " + dialect_->prepare_identifier_string(it->column_name()); } } query_.sql += ")"; @@ -85,18 +85,17 @@ void query_compiler::visit(internal::query_add_foreign_key_constraint_part& part void query_compiler::visit(internal::query_add_primary_key_constraint_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() + " ("; if (part.columns().size() < 2) { for (const auto &col: part.columns()) { - query_.sql += dialect_->prepare_identifier_string(col.name); + query_.sql += dialect_->prepare_identifier_string(col.column_name()); } } else { auto it = part.columns().begin(); - query_.sql += dialect_->prepare_identifier_string(it->name); + query_.sql += dialect_->prepare_identifier_string(it->column_name()); for (; it != part.columns().end(); ++it) { - query_.sql += ", " + dialect_->prepare_identifier_string(it->name); + query_.sql += ", " + dialect_->prepare_identifier_string(it->column_name()); } } query_.sql += ")"; @@ -139,7 +138,7 @@ void query_compiler::visit(internal::query_from_part &part) { query_.table = part.table(); query_.sql += " " + build_table_name(part.token(), *dialect_, query_.table); - query_.table_aliases.insert({query_.table.name, query_.table.alias}); + query_.table_aliases.insert({query_.table.name(), query_.table.alias()}); } void query_compiler::visit(internal::query_join_part &part) @@ -199,19 +198,19 @@ void query_compiler::visit(internal::query_into_part &part) { query_.table = part.table(); query_.sql += " " + dialect_->token_at(sql::dialect_token::Into) + - " " + dialect_->prepare_identifier_string(part.table().name); + " " + dialect_->prepare_identifier_string(part.table().name()); std::string result{"("}; if (part.columns().size() < 2) { for (const auto &col: part.columns()) { - result.append(dialect_->prepare_identifier_string(col.name)); + result.append(dialect_->prepare_identifier_string(col.column_name())); } } else { auto it = part.columns().begin(); - result.append(dialect_->prepare_identifier_string((it++)->name)); + result.append(dialect_->prepare_identifier_string((it++)->column_name())); for (; it != part.columns().end(); ++it) { result.append(", "); - result.append(dialect_->prepare_identifier_string(it->name)); + result.append(dialect_->prepare_identifier_string(it->column_name())); } } result += (")"); @@ -305,7 +304,7 @@ std::string build_create_column(const object::attribute_definition &col, const s 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_->token_at(sql::dialect_token::Table) + " " + dialect_->prepare_identifier_string(part.table().name()) + " "; query_.table = part.table(); std::string result = "("; @@ -326,12 +325,12 @@ void query_compiler::visit(internal::query_create_table_part &part) } if (!context.primary_keys.empty()) { - result.append(", CONSTRAINT PK_" + part.table().name + " PRIMARY KEY (" + utils::join(context.primary_keys, ", ") + ")"); + 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; + 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() + ")"; @@ -365,16 +364,16 @@ void query_compiler::visit(internal::query_set_part &part) { value_visitor visitor(writer, query_); if (part.column_values().size() < 2) { for (const auto &column_value: part.column_values()) { - result.append(dialect_->prepare_identifier_string(column_value.col().name) + "="); + result.append(dialect_->prepare_identifier_string(column_value.col().column_name()) + "="); result.append(determine_value(visitor, column_value.value())); } } else { auto it = part.column_values().begin(); - result.append(dialect_->prepare_identifier_string(it->col().name) + "="); + result.append(dialect_->prepare_identifier_string(it->col().column_name()) + "="); result.append(determine_value(visitor, (it++)->value())); for (; it != part.column_values().end(); ++it) { result.append(", "); - result.append(dialect_->prepare_identifier_string(it->col().name) + "="); + result.append(dialect_->prepare_identifier_string(it->col().column_name()) + "="); result.append(determine_value(visitor, it->value())); } } @@ -414,8 +413,8 @@ std::string query_compiler::build_table_name(const sql::dialect_token token, con { return d.token_at(token) + " " + (!d.default_schema_name().empty() ? d.prepare_identifier_string(d.default_schema_name()) + "." : "") + - d.prepare_identifier_string(t.name) + - (t.alias.empty() ? "" : " " + d.prepare_identifier_string(t.alias)); + d.prepare_identifier_string(t.name()) + + (t.alias().empty() ? "" : " " + d.prepare_identifier_string(t.alias())); } } \ No newline at end of file diff --git a/source/orm/sql/column.cpp b/source/orm/sql/column.cpp index f5a6345..9983e8e 100644 --- a/source/orm/sql/column.cpp +++ b/source/orm/sql/column.cpp @@ -29,7 +29,7 @@ column::column(const char *name, const std::string& as) column::column(std::string name, std::string as) : table_(std::make_shared()) , name(std::move(name)) -, alias(std::move(as)) {} +, alias_(std::move(as)) {} column::column(const sql_function_t func, std::string name) : table_(std::make_shared()) @@ -39,25 +39,25 @@ column::column(const sql_function_t func, std::string name) column::column(const sql::table& tab, std::string name, std::string as) : table_(std::make_shared(tab)) , name(std::move(name)) -, alias(std::move(as)) { - table_->columns.push_back(*this); +, alias_(std::move(as)) { + table_->columns_.push_back(*this); } column::column(const std::shared_ptr& t, std::string name, std::string as) : table_(t) , name(std::move(name)) -, alias(std::move(as)) { +, alias_(std::move(as)) { } bool column::equals(const column &x) const { return *table_ == *x.table_ && name == x.name && - alias == x.alias && + alias_ == x.alias_ && function_ == x.function_; } column &column::as(std::string a) { - alias = std::move(a); + alias_ = std::move(a); return *this; } @@ -66,25 +66,37 @@ const std::string& column::column_name() const { } std::string column::full_name() const { - if (table_ && !table_->name.empty()) { - return table_->name + "." + name; + if (table_ && !table_->name().empty()) { + return table_->name() + "." + name; } return name; } const std::string& column::alias_name() const { - return alias; + return alias_; } bool column::is_function() const { - return function_ != sql_function_t::NONE; + return function_ != sql_function_t::None; +} + +sql_function_t column::function() const { + return function_; } bool column::has_alias() const { - return !alias.empty(); + return !alias_.empty(); +} + +std::string column::alias() const { + return alias_; } std::shared_ptr
column::table() const { return table_; } + +void column::table( const std::shared_ptr& t ) { + table_ = t; +} } \ No newline at end of file diff --git a/source/orm/sql/connection.cpp b/source/orm/sql/connection.cpp index a940d31..92a5b93 100644 --- a/source/orm/sql/connection.cpp +++ b/source/orm/sql/connection.cpp @@ -221,7 +221,7 @@ const class dialect &connection::dialect() const utils::result, utils::error> connection::perform_prepare(const query_context& ctx) const { if (ctx.command != sql_command::SQL_CREATE_TABLE && (ctx.prototype.empty() || has_unknown_columns(ctx.prototype))) { - if (const auto result = describe(ctx.table.name); result.is_ok()) { + if (const auto result = describe(ctx.table.name()); result.is_ok()) { for (auto &col: ctx.prototype) { const auto rit = std::find_if( std::begin(*result), diff --git a/source/orm/sql/dialect.cpp b/source/orm/sql/dialect.cpp index e86b736..533bd99 100644 --- a/source/orm/sql/dialect.cpp +++ b/source/orm/sql/dialect.cpp @@ -16,37 +16,47 @@ const std::string &dialect::data_type_at(const utils::basic_type type) const return data_types_.at(type); } -std::string dialect::prepare_identifier(const column &col) const +std::string dialect::prepare_identifier(const sql::column &col) const { std::string result; if (!col.is_function()) { - if (!col.table_->name.empty()) { - result = prepare_identifier_string(col.table_->has_alias() ? col.table_->alias : col.table_->name) + "."; + if (!col.table()->name().empty()) { + result = prepare_identifier_string(col.table()->has_alias() ? col.table()->alias() : col.table()->name()) + "."; } - result += prepare_identifier_string(col.name); + result += prepare_identifier_string(col.column_name()); } else { - result = sql_func_map_.at(col.function_) + "(" + col.name + ")"; + result = sql_func_map_.at(col.function()) + "(" + col.column_name() + ")"; } - if (!col.alias.empty()) { - result += " AS " + col.alias; + if (!col.alias().empty()) { + result += " AS " + col.alias(); } return result; } -std::string dialect::prepare_condition(const column& col) const +std::string dialect::table_name( const std::string& table, const std::string& schema_name ) const { + if ( schema_name.empty() && default_schema_name_.empty()) { + return prepare_identifier_string( table ); + } + if ( schema_name.empty() ) { + return prepare_identifier_string( default_schema_name_ ) + "." + prepare_identifier_string( table ); + } + return prepare_identifier_string( schema_name ) + "." + prepare_identifier_string( table ); +} + +std::string dialect::prepare_condition(const sql::column& col) const { std::string result; if (!col.is_function()) { // if (!col.alias.empty()) { // result = col.alias; // } else { - if (!col.table_->name.empty()) { - result = prepare_identifier_string(col.table_->has_alias() ? col.table_->alias : col.table_->name) + "."; + if (!col.table()->name().empty()) { + result = prepare_identifier_string(col.table()->has_alias() ? col.table()->alias() : col.table()->name()) + "."; } - result += prepare_identifier_string(col.name); + result += prepare_identifier_string(col.column_name()); // } } else { - result = sql_func_map_.at(col.function_) + "(" + col.name + ")"; + result = sql_func_map_.at(col.function()) + "(" + col.column_name() + ")"; } return result; @@ -143,4 +153,199 @@ std::string dialect::default_schema_name() const return default_schema_name_; } +const std::string& dialect::add_constraint() const { + return token_at(dialect_token::AddConstraint); +} + +const std::string& dialect::alter() const { + return token_at(dialect_token::Alter); +} + +const std::string& dialect::and_() const { + return token_at(dialect_token::And); +} + +const std::string& dialect::as() const { + return token_at(dialect_token::As); +} + +const std::string& dialect::asc() const { + return token_at(dialect_token::Asc); +} + +const std::string& dialect::begin() const { + return token_at(dialect_token::Begin); +} + +const std::string& dialect::asterisk() const { + return token_at(dialect_token::Asterisk); +} + +const std::string& dialect::begin_binary_data() const { + return token_at(dialect_token::BeginBinaryData); +} + +const std::string& dialect::begin_string_data() const { + return token_at(dialect_token::BeginStringData); +} + +const std::string& dialect::between() const { + return token_at(dialect_token::Between); +} + +const std::string& dialect::column() const { + return token_at(dialect_token::Column); +} + +const std::string& dialect::columns() const { + return token_at(dialect_token::Columns); +} + +const std::string& dialect::commit() const { + return token_at(dialect_token::Commit); +} + +const std::string& dialect::create() const { + return token_at(dialect_token::Create); +} + +const std::string& dialect::drop() const { + return token_at(dialect_token::Drop); +} + +const std::string& dialect::end_binary_data() const { + return token_at(dialect_token::EndBinaryData); +} + +const std::string& dialect::end_string_data() const { + return token_at(dialect_token::EndStringData); +} + +const std::string& dialect::from() const { + return token_at(dialect_token::From); +} + +const std::string& dialect::in() const { + return token_at(dialect_token::In); +} + +const std::string& dialect::desc() const { + return token_at(dialect_token::Desc); +} + +const std::string& dialect::distinct() const { + return token_at(dialect_token::Distinct); +} + +const std::string& dialect::drop_constraint() const { + return token_at(dialect_token::DropConstraint); +} + +const std::string& dialect::end_quote() const { + return token_at(dialect_token::EndQuote); +} + +const std::string& dialect::foreign_key() const { + return token_at(dialect_token::ForeignKey); +} + +const std::string& dialect::group_by() const { + return token_at(dialect_token::GroupBy); +} + +const std::string& dialect::insert() const { + return token_at(dialect_token::Insert); +} + +const std::string& dialect::into() const { + return token_at(dialect_token::Into); +} + +const std::string& dialect::join() const { + return token_at(dialect_token::Join); +} + +const std::string& dialect::like() const { + return token_at(dialect_token::Like); +} + +const std::string& dialect::limit() const { + return token_at(dialect_token::Limit); +} + +const std::string& dialect::not_() const { + return token_at(dialect_token::Not); +} + +const std::string& dialect::not_null() const { + return token_at(dialect_token::NotNull); +} + +const std::string& dialect::offset() const { + return token_at(dialect_token::Offset); +} + +const std::string& dialect::on() const { + return token_at(dialect_token::On); +} + +const std::string& dialect::or_() const { + return token_at(dialect_token::Or); +} + +const std::string& dialect::order_by() const { + return token_at(dialect_token::OrderBy); +} + +const std::string& dialect::primary_key() const { + return token_at(dialect_token::PrimaryKey); +} + +const std::string& dialect::references() const { + return token_at(dialect_token::References); +} + +const std::string& dialect::remove() const { + return token_at(dialect_token::Remove); +} + +const std::string& dialect::rollback() const { + return token_at(dialect_token::Rollback); +} + +const std::string& dialect::schema() const { + return token_at(dialect_token::Schema); +} + +const std::string& dialect::select() const { + return token_at(dialect_token::Select); +} + +const std::string& dialect::set() const { + return token_at(dialect_token::Set); +} + +const std::string& dialect::start_quote() const { + return token_at(dialect_token::StartQuote); +} + +const std::string& dialect::string_quote() const { + return token_at(dialect_token::StringQuote); +} + +const std::string& dialect::table() const { + return token_at(dialect_token::Table); +} + +const std::string& dialect::update() const { + return token_at(dialect_token::Update); +} + +const std::string& dialect::values() const { + return token_at(dialect_token::Values); +} + +const std::string& dialect::where() const { + return token_at(dialect_token::Where); +} } diff --git a/source/orm/sql/record.cpp b/source/orm/sql/record.cpp index 25f7b29..bf4863e 100644 --- a/source/orm/sql/record.cpp +++ b/source/orm/sql/record.cpp @@ -67,14 +67,14 @@ const std::vector &record::columns() const // return columns_[pk_index_]; //} -const field &record::at(const column &col) const +const field &record::at(const sql::column &col) const { - const auto &res = fields_by_name_.at(col.name); + const auto &res = fields_by_name_.at(col.column_name()); const auto &f = res.first; return f; } -const field &record::at(size_t index) const +const field &record::at(const size_t index) const { return fields_.at(index); } diff --git a/source/orm/sql/table.cpp b/source/orm/sql/table.cpp index 6e8312a..ef2dafa 100644 --- a/source/orm/sql/table.cpp +++ b/source/orm/sql/table.cpp @@ -7,34 +7,51 @@ table::table(const char* name) {} table::table(std::string name) -: name(std::move(name)) +: name_(std::move(name)) {} table::table(const char *name, std::string as) -: name(name) -, alias(std::move(as)) +: name_(name) +, alias_(std::move(as)) {} table::table(std::string name, std::string as) -: name(std::move(name)) -, alias(std::move(as)) +: name_(std::move(name)) +, alias_(std::move(as)) {} +table::table( std::string name, std::string as, const std::vector& columns ) +: name_(std::move(name)) +, alias_(std::move(as)) +, columns_(columns) {} + bool table::operator==( const table& x ) const { - return name == x.name; + return name_ == x.name_; } table & table::as(const std::string &a) { - alias = a; + alias_ = a; return *this; } table table::as(const std::string &a) const { - return { name, a, columns }; + return { name_, a, columns_ }; } bool table::has_alias() const { - return !alias.empty(); + return !alias_.empty(); +} + +const std::string& table::name() const { + return name_; +} + +const std::string& table::alias() const { + return alias_; +} + +const std::vector& table::columns() const { + return columns_; } table operator ""_tab(const char *name, size_t len) { diff --git a/test/backends/SchemaTest.cpp b/test/backends/SchemaTest.cpp index c284748..369ffed 100644 --- a/test/backends/SchemaTest.cpp +++ b/test/backends/SchemaTest.cpp @@ -14,7 +14,7 @@ using namespace matador::test; TEST_CASE_METHOD(SchemaFixture, "Test schema one-two-many", "[schema]") { using namespace matador::test; - matador::orm::schema repo(pool/*, "NoopSchema"*/); + orm::schema repo(pool, "NoopSchema"); auto result = repo.attach("departments") .and_then( [&repo] { return repo.attach("employees"); } ); diff --git a/test/orm/orm/SessionQueryBuilderTest.cpp b/test/orm/orm/SessionQueryBuilderTest.cpp index e505dac..16fbbc0 100644 --- a/test/orm/orm/SessionQueryBuilderTest.cpp +++ b/test/orm/orm/SessionQueryBuilderTest.cpp @@ -44,7 +44,7 @@ TEST_CASE("Create sql query data for entity with eager has one", "[query][entity auto data = eqb.build("flights.id"_col == _); REQUIRE(data.is_ok()); - REQUIRE(data->root_table->name == "flights"); + REQUIRE(data->root_table->name() == "flights"); REQUIRE(data->joins.size() == 1); const std::vector expected_columns { { "flights", "id", "c01" }, @@ -66,7 +66,7 @@ TEST_CASE("Create sql query data for entity with eager has one", "[query][entity size_t index{0}; criteria_evaluator evaluator(db.dialect(), qc); for (const auto &[join_table, condition] : data->joins) { - REQUIRE(join_table->name == expected_join_data[index].first); + REQUIRE(join_table->name() == expected_join_data[index].first); REQUIRE(evaluator.evaluate(*condition) == expected_join_data[index].second); ++index; } @@ -90,7 +90,7 @@ TEST_CASE("Create sql query data for entity with eager belongs to", "[query][ent auto data = eqb.build("books.id"_col == _); REQUIRE(data.is_ok()); - REQUIRE(data->root_table->name == "books"); + REQUIRE(data->root_table->name() == "books"); REQUIRE(data->joins.size() == 1); const std::vector expected_columns { { "books", "id", "c01" }, @@ -116,7 +116,7 @@ TEST_CASE("Create sql query data for entity with eager belongs to", "[query][ent size_t index{0}; criteria_evaluator evaluator(db.dialect(), qc); for (const auto & [join_table, clause] : data->joins) { - REQUIRE(join_table->name == expected_join_data[index].first); + REQUIRE(join_table->name() == expected_join_data[index].first); REQUIRE(evaluator.evaluate(*clause) == expected_join_data[index].second); ++index; } @@ -126,7 +126,7 @@ TEST_CASE("Create sql query data for entity with eager belongs to", "[query][ent REQUIRE(cond == R"("t01"."id" = ?)"); auto q = matador::query::query::select(data->columns) - .from(data->root_table->name); + .from(data->root_table->name()); for (auto &jd : data->joins) { q.join_left(*jd.join_table) @@ -154,7 +154,7 @@ TEST_CASE("Create sql query data for entity with eager has many belongs to", "[q auto data = eqb.build("orders.order_id"_col == _); REQUIRE(data.is_ok()); - REQUIRE(data->root_table->name == "orders"); + REQUIRE(data->root_table->name() == "orders"); REQUIRE(data->joins.size() == 1); const std::vector expected_columns = { { "orders", "order_id", "c01" }, @@ -186,7 +186,7 @@ TEST_CASE("Create sql query data for entity with eager has many belongs to", "[q size_t index{0}; criteria_evaluator evaluator(db.dialect(), qc); for (const auto &jd : data->joins) { - REQUIRE(jd.join_table->name == expected_join_data[index].first); + REQUIRE(jd.join_table->name() == expected_join_data[index].first); REQUIRE(evaluator.evaluate(*jd.condition) == expected_join_data[index].second); ++index; } @@ -210,7 +210,7 @@ TEST_CASE("Create sql query data for entity with eager many to many", "[query][e auto data = eqb.build("ingredients.id"_col == _); REQUIRE(data.is_ok()); - REQUIRE(data->root_table->name == "ingredients"); + REQUIRE(data->root_table->name() == "ingredients"); REQUIRE(data->joins.size() == 2); const std::vector expected_columns { { "ingredients", "id", "c01" }, @@ -232,7 +232,7 @@ TEST_CASE("Create sql query data for entity with eager many to many", "[query][e size_t index{0}; criteria_evaluator evaluator(db.dialect(), qc); for (const auto &jd : data->joins) { - REQUIRE(jd.join_table->name == expected_join_data[index].first); + REQUIRE(jd.join_table->name() == expected_join_data[index].first); REQUIRE(evaluator.evaluate(*jd.condition) == expected_join_data[index].second); ++index; } @@ -256,7 +256,7 @@ TEST_CASE("Create sql query data for entity with eager many to many (inverse par auto data = eqb.build("courses.id"_col == _); REQUIRE(data.is_ok()); - REQUIRE(data->root_table->name == "courses"); + REQUIRE(data->root_table->name() == "courses"); REQUIRE(data->joins.size() == 2); const std::vector expected_columns { { "courses", "id", "c01" }, @@ -278,7 +278,7 @@ TEST_CASE("Create sql query data for entity with eager many to many (inverse par size_t index{0}; criteria_evaluator evaluator(db.dialect(), qc); for (const auto &jd : data->joins) { - REQUIRE(jd.join_table->name == expected_join_data[index].first); + REQUIRE(jd.join_table->name() == expected_join_data[index].first); REQUIRE(evaluator.evaluate(*jd.condition) == expected_join_data[index].second); ++index; } diff --git a/test/orm/query/CriteriaTests.cpp b/test/orm/query/CriteriaTests.cpp index 4953e7e..407fd0e 100644 --- a/test/orm/query/CriteriaTests.cpp +++ b/test/orm/query/CriteriaTests.cpp @@ -23,7 +23,7 @@ protected: TEST_CASE_METHOD(CriteriaFixture, "Test binary criteria", "[criteria][binary]") { const auto name_col = "name"_col; - REQUIRE(name_col.name == "name"); + REQUIRE(name_col.column_name() == "name"); auto clause = name_col != "george"; diff --git a/test/orm/sql/ColumnGeneratorTest.cpp b/test/orm/sql/ColumnGeneratorTest.cpp index cddc10f..a26d963 100644 --- a/test/orm/sql/ColumnGeneratorTest.cpp +++ b/test/orm/sql/ColumnGeneratorTest.cpp @@ -37,7 +37,7 @@ TEST_CASE("Generate columns from object", "[column][generator]") { REQUIRE(columns.size() == expected_columns.size()); for (size_t i = 0; i != expected_columns.size(); ++i) { - REQUIRE(expected_columns[i] == columns[i].name); + REQUIRE(expected_columns[i] == columns[i].column_name()); } }