some sql classes refactorings like column and table structs to classes

This commit is contained in:
Sascha Kühl 2025-11-14 16:16:07 +01:00
parent 34e6d41554
commit d1731a7f15
22 changed files with 428 additions and 130 deletions

View File

@ -7,22 +7,23 @@
namespace matador::sql { namespace matador::sql {
struct table; class table;
enum class sql_function_t { enum class sql_function_t {
NONE, None,
COUNT, Count,
AVG, Avg,
SUM, Sum,
MIN, Min,
MAX Max
}; };
struct column { class column {
public:
column(const char *name, const std::string& as = ""); // NOLINT(*-explicit-constructor) 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(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<table> &t, std::string name, std::string as = ""); column(const std::shared_ptr<table> &t, std::string name, std::string as = "");
[[nodiscard]] bool equals(const column &x) const; [[nodiscard]] bool equals(const column &x) const;
@ -33,13 +34,17 @@ struct column {
[[nodiscard]] std::string full_name() const; [[nodiscard]] std::string full_name() const;
[[nodiscard]] const std::string& alias_name() const; [[nodiscard]] const std::string& alias_name() const;
[[nodiscard]] bool is_function() const; [[nodiscard]] bool is_function() const;
[[nodiscard]] sql_function_t function() const;
[[nodiscard]] bool has_alias() const; [[nodiscard]] bool has_alias() const;
[[nodiscard]] std::string alias() const;
[[nodiscard]] std::shared_ptr<sql::table> table() const; [[nodiscard]] std::shared_ptr<sql::table> table() const;
void table(const std::shared_ptr<sql::table>& t);
private:
std::shared_ptr<sql::table> table_; std::shared_ptr<sql::table> table_;
std::string name; std::string name;
std::string alias; std::string alias_;
sql_function_t function_{sql_function_t::NONE}; sql_function_t function_{sql_function_t::None};
}; };
column operator ""_col(const char *name, size_t len); column operator ""_col(const char *name, size_t len);

View File

@ -54,6 +54,7 @@ public:
[[nodiscard]] std::string prepare_identifier(const column &col) const; [[nodiscard]] std::string prepare_identifier(const column &col) const;
[[nodiscard]] std::string prepare_identifier_string(const std::string &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 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; [[nodiscard]] const std::string& to_string(bool val) const;
@ -124,6 +125,56 @@ public:
*/ */
[[nodiscard]] std::string default_schema_name() const; [[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: private:
dialect() = default; dialect() = default;
@ -179,6 +230,7 @@ private:
{dialect_token::References, "REFERENCES"}, {dialect_token::References, "REFERENCES"},
{dialect_token::Remove, "DELETE"}, {dialect_token::Remove, "DELETE"},
{dialect_token::Rollback, "ROLLBACK TRANSACTION"}, {dialect_token::Rollback, "ROLLBACK TRANSACTION"},
{dialect_token::Schema, "SCHEMA"},
{dialect_token::Select, "SELECT"}, {dialect_token::Select, "SELECT"},
{dialect_token::Set, "SET"}, {dialect_token::Set, "SET"},
{dialect_token::StartQuote, "\""}, {dialect_token::StartQuote, "\""},
@ -210,12 +262,12 @@ private:
}; };
sql_func_to_string_map sql_func_map_ { sql_func_to_string_map sql_func_map_ {
{sql_function_t::NONE, "NONE" }, {sql_function_t::None, "NONE" },
{sql_function_t::COUNT, "COUNT" }, {sql_function_t::Count, "COUNT" },
{sql_function_t::AVG, "AVG" }, {sql_function_t::Avg, "AVG" },
{sql_function_t::SUM, "SUM" }, {sql_function_t::Sum, "SUM" },
{sql_function_t::MIN, "MIN" }, {sql_function_t::Min, "MIN" },
{sql_function_t::MAX, "MAX" }, {sql_function_t::Max, "MAX" },
}; };
std::array<std::string, 2> bool_strings_ { std::array<std::string, 2> bool_strings_ {

View File

@ -34,6 +34,7 @@ struct query_context {
std::string sql; std::string sql;
sql_command command{}; sql_command command{};
std::string command_name{}; std::string command_name{};
std::string schema_name{};
sql::table table{""}; sql::table table{""};
std::vector<object::attribute_definition> prototype{}; std::vector<object::attribute_definition> prototype{};
std::vector<std::string> result_vars{}; std::vector<std::string> result_vars{};

View File

@ -8,7 +8,7 @@
namespace matador::sql { namespace matador::sql {
struct column; class column;
class record final { class record final {
private: private:
@ -41,7 +41,7 @@ public:
[[nodiscard]] const std::vector<field_ref>& columns() const; [[nodiscard]] const std::vector<field_ref>& 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; [[nodiscard]] const field& at(size_t index) const;
template<class Type> template<class Type>
std::optional<Type> at(const column &col) const { std::optional<Type> at(const column &col) const {

View File

@ -8,18 +8,16 @@
namespace matador::sql { namespace matador::sql {
struct column; class column;
struct table { class table {
public:
table() = default; table() = default;
table(const char *name); // NOLINT(*-explicit-constructor) table(const char *name); // NOLINT(*-explicit-constructor)
table(std::string name); // NOLINT(*-explicit-constructor) table(std::string name); // NOLINT(*-explicit-constructor)
table(const char *name, std::string as); // 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); // NOLINT(*-explicit-constructor)
table(std::string name, std::string as, const std::vector<column> &columns) table(std::string name, std::string as, const std::vector<column> &columns);
: name(std::move(name))
, alias(std::move(as))
, columns(columns) {}
table& as(const std::string &a); table& as(const std::string &a);
@ -29,13 +27,20 @@ struct table {
[[nodiscard]] bool has_alias() const; [[nodiscard]] bool has_alias() const;
std::string name; [[nodiscard]] const std::string& name() const;
std::string alias; [[nodiscard]] const std::string& alias() const;
[[nodiscard]] const std::vector<column>& columns() const;
private:
friend class column;
std::vector<column> columns; std::string name_;
std::string alias_;
std::string schema_name_;
std::vector<column> columns_;
}; };
table operator "" _tab(const char *name, size_t len); table operator ""_tab(const char *name, size_t len);
} }

View File

@ -52,6 +52,9 @@ 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(); 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_) { for (const auto &node: repo_) {
auto ctx = query::query::create() auto ctx = query::query::create()
.table(node->name(), node->info().definition().columns()) .table(node->name(), node->info().definition().columns())

View File

@ -90,13 +90,13 @@ utils::result<sql::query_result<sql::record>, utils::error> session::fetch_all(c
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."));
} }
auto it = prototypes_.find(q.table.name); auto it = prototypes_.find(q.table.name());
if (it == prototypes_.end()) { if (it == prototypes_.end()) {
auto result = c->describe(q.table.name); auto result = c->describe(q.table.name());
if (!result) { if (!result) {
return utils::failure(result.err()); 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 // adjust columns from given query
for (auto &col: q.prototype) { for (auto &col: q.prototype) {

View File

@ -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 { 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()) { if (it == tables_by_name_.end()) {
return; return;
} }
const_cast<sql::column&>(node.column()).table_ = it->second; const_cast<sql::column&>(node.column()).table(it->second);
} }
void session_query_builder::on_revision(const char *id, uint64_t &/*rev*/) { 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) { void session_query_builder::append_join(const sql::column &left, const sql::column &right) {
using namespace matador::query; using namespace matador::query;
entity_query_data_.joins.push_back({ entity_query_data_.joins.push_back({
{right.table_}, {right.table()},
std::make_unique<binary_column_criteria>(left, binary_operator::EQUALS, right) std::make_unique<binary_column_criteria>(left, binary_operator::EQUALS, right)
}); });
} }

View File

@ -38,8 +38,8 @@ std::string criteria_evaluator::evaluate(const abstract_criteria &node) {
} }
void criteria_evaluator::visit(const between_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().column_name());
query_.bind_vars.emplace_back(node.column().name); query_.bind_vars.emplace_back(node.column().column_name());
clause_ += dialect_.prepare_identifier(node.column()) + " " + dialect_.token_at(sql::dialect_token::Between) + " "; clause_ += dialect_.prepare_identifier(node.column()) + " " + dialect_.token_at(sql::dialect_token::Between) + " ";
evaluate_value(node.minimum()); evaluate_value(node.minimum());
clause_ += " " + dialect_.token_at(sql::dialect_token::And) + " "; clause_ += " " + dialect_.token_at(sql::dialect_token::And) + " ";
@ -50,7 +50,7 @@ template<class... Ts> struct overload : Ts... { using Ts::operator()...; };
template<class... Ts> overload(Ts...) -> overload<Ts...>; template<class... Ts> overload(Ts...) -> overload<Ts...>;
void criteria_evaluator::visit(const binary_criteria &node) { 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()) + " "; clause_ += dialect_.prepare_condition(node.column()) + " " + detail::BinaryOperatorEnum.to_string(node.operand()) + " ";
evaluate_value(node.value()); 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) { void criteria_evaluator::visit(const collection_criteria &node) {
const auto count = node.values().size(); const auto count = node.values().size();
for (size_t i = 0; i < count; ++i) { 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()) + clause_ += dialect_.prepare_identifier(node.column()) +

View File

@ -31,9 +31,8 @@ query_into_intermediate query_insert_intermediate::into(const sql::table &table,
return into(table, std::move(columns)); return into(table, std::move(columns));
} }
query_into_intermediate query_insert_intermediate::into(const sql::table &table) query_into_intermediate query_insert_intermediate::into(const sql::table &table) {
{ context_->parts.push_back(std::make_unique<internal::query_into_part>(table, table.columns()));
context_->parts.push_back(std::make_unique<internal::query_into_part>(table, table.columns));
return {context_}; return {context_};
} }

View File

@ -14,7 +14,7 @@ query_select_intermediate::query_select_intermediate(const std::vector<sql::colu
query_from_intermediate query_select_intermediate::from(const sql::table& t) query_from_intermediate query_select_intermediate::from(const sql::table& t)
{ {
context_->parts.push_back(std::make_unique<internal::query_from_part>(t)); context_->parts.push_back(std::make_unique<internal::query_from_part>(t));
context_->tables.insert({t.name, t}); context_->tables.insert({t.name(), t});
return {context_}; return {context_};
} }

View File

@ -15,7 +15,7 @@ sql::column alias(sql::column &&col, const std::string &as)
sql::column count(const std::string &column) 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() sql::column count_all()

View File

@ -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) { 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); 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.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.name); ctx.prototype.emplace_back(col.has_alias() ? col.alias() : col.column_name());
ctx.prototype.back().type(utils::basic_type::type_int32); ctx.prototype.back().type(utils::basic_type::type_int32);
} else { } 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()) { if (const auto it = data.tables.find(col.table()->name()); it != data.tables.end()) {
return d->prepare_identifier({it->second, col.name, col.alias}); return d->prepare_identifier({it->second, col.column_name(), col.alias()});
} }
return d->prepare_identifier(col); 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) { void query_compiler::visit(internal::query_alter_table_part& part) {
query_.command = sql::sql_command::SQL_ALTER_TABLE; query_.command = sql::sql_command::SQL_ALTER_TABLE;
query_.sql += " " + dialect_->token_at(part.token()) + " " + 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) { 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) { if (part.columns().size() < 2) {
for (const auto &col: part.columns()) { for (const auto &col: part.columns()) {
query_.sql += dialect_->prepare_identifier_string(col.name); query_.sql += dialect_->prepare_identifier_string(col.column_name());
} }
} else { } else {
auto it = part.columns().begin(); 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) { 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 += ")"; 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_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()) + " " + query_.sql += " " + dialect_->token_at(part.token()) + " " + part.table().name() + " (";
part.table().name + " (";
if (part.columns().size() < 2) { if (part.columns().size() < 2) {
for (const auto &col: part.columns()) { for (const auto &col: part.columns()) {
query_.sql += dialect_->prepare_identifier_string(col.name); query_.sql += dialect_->prepare_identifier_string(col.column_name());
} }
} else { } else {
auto it = part.columns().begin(); 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) { 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 += ")"; query_.sql += ")";
@ -139,7 +138,7 @@ void query_compiler::visit(internal::query_from_part &part)
{ {
query_.table = part.table(); query_.table = part.table();
query_.sql += " " + build_table_name(part.token(), *dialect_, query_.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) 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_.table = part.table();
query_.sql += " " + dialect_->token_at(sql::dialect_token::Into) + 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{"("}; std::string result{"("};
if (part.columns().size() < 2) { if (part.columns().size() < 2) {
for (const auto &col: part.columns()) { for (const auto &col: part.columns()) {
result.append(dialect_->prepare_identifier_string(col.name)); result.append(dialect_->prepare_identifier_string(col.column_name()));
} }
} else { } else {
auto it = part.columns().begin(); 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) { for (; it != part.columns().end(); ++it) {
result.append(", "); result.append(", ");
result.append(dialect_->prepare_identifier_string(it->name)); result.append(dialect_->prepare_identifier_string(it->column_name()));
} }
} }
result += (")"); 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) 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(); query_.table = part.table();
std::string result = "("; std::string result = "(";
@ -326,12 +325,12 @@ void query_compiler::visit(internal::query_create_table_part &part)
} }
if (!context.primary_keys.empty()) { 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) { for (const auto &[column, reference_column]: context.foreign_contexts) {
// ALTER TABLE Orders ADD CONSTRAINT FK_PersonOrder FOREIGN KEY (PersonID) REFERENCES Persons(PersonID); // 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"; std::string fk_cmd = "ALTER TABLE " + dialect_->prepare_identifier_string(query_.table.name()) + " ADD";
fk_cmd += " CONSTRAINT FK_" + query_.table.name; fk_cmd += " CONSTRAINT FK_" + query_.table.name();
fk_cmd += "_" + column; fk_cmd += "_" + column;
fk_cmd += " FOREIGN KEY (" + dialect_->prepare_identifier_string(column) + ")"; fk_cmd += " FOREIGN KEY (" + dialect_->prepare_identifier_string(column) + ")";
fk_cmd += " REFERENCES " + reference_column->table_name() + "(" + reference_column->name() + ")"; 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) { value_visitor visitor(writer, query_); if (part.column_values().size() < 2) {
for (const auto &column_value: part.column_values()) { 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())); result.append(determine_value(visitor, column_value.value()));
} }
} else { } else {
auto it = part.column_values().begin(); 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())); result.append(determine_value(visitor, (it++)->value()));
for (; it != part.column_values().end(); ++it) { for (; it != part.column_values().end(); ++it) {
result.append(", "); 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())); 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) + " " + return d.token_at(token) + " " +
(!d.default_schema_name().empty() ? d.prepare_identifier_string(d.default_schema_name()) + "." : "") + (!d.default_schema_name().empty() ? d.prepare_identifier_string(d.default_schema_name()) + "." : "") +
d.prepare_identifier_string(t.name) + d.prepare_identifier_string(t.name()) +
(t.alias.empty() ? "" : " " + d.prepare_identifier_string(t.alias)); (t.alias().empty() ? "" : " " + d.prepare_identifier_string(t.alias()));
} }
} }

View File

@ -29,7 +29,7 @@ column::column(const char *name, const std::string& as)
column::column(std::string name, std::string as) column::column(std::string name, std::string as)
: table_(std::make_shared<sql::table>()) : table_(std::make_shared<sql::table>())
, name(std::move(name)) , name(std::move(name))
, alias(std::move(as)) {} , alias_(std::move(as)) {}
column::column(const sql_function_t func, std::string name) column::column(const sql_function_t func, std::string name)
: table_(std::make_shared<sql::table>()) : table_(std::make_shared<sql::table>())
@ -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) column::column(const sql::table& tab, std::string name, std::string as)
: table_(std::make_shared<sql::table>(tab)) : table_(std::make_shared<sql::table>(tab))
, name(std::move(name)) , name(std::move(name))
, alias(std::move(as)) { , alias_(std::move(as)) {
table_->columns.push_back(*this); table_->columns_.push_back(*this);
} }
column::column(const std::shared_ptr<sql::table>& t, std::string name, std::string as) column::column(const std::shared_ptr<sql::table>& t, std::string name, std::string as)
: table_(t) : table_(t)
, name(std::move(name)) , name(std::move(name))
, alias(std::move(as)) { , alias_(std::move(as)) {
} }
bool column::equals(const column &x) const { bool column::equals(const column &x) const {
return *table_ == *x.table_ && return *table_ == *x.table_ &&
name == x.name && name == x.name &&
alias == x.alias && alias_ == x.alias_ &&
function_ == x.function_; function_ == x.function_;
} }
column &column::as(std::string a) { column &column::as(std::string a) {
alias = std::move(a); alias_ = std::move(a);
return *this; return *this;
} }
@ -66,25 +66,37 @@ const std::string& column::column_name() const {
} }
std::string column::full_name() const { std::string column::full_name() const {
if (table_ && !table_->name.empty()) { if (table_ && !table_->name().empty()) {
return table_->name + "." + name; return table_->name() + "." + name;
} }
return name; return name;
} }
const std::string& column::alias_name() const { const std::string& column::alias_name() const {
return alias; return alias_;
} }
bool column::is_function() const { 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 { bool column::has_alias() const {
return !alias.empty(); return !alias_.empty();
}
std::string column::alias() const {
return alias_;
} }
std::shared_ptr<table> column::table() const { std::shared_ptr<table> column::table() const {
return table_; return table_;
} }
void column::table( const std::shared_ptr<sql::table>& t ) {
table_ = t;
}
} }

View File

@ -221,7 +221,7 @@ const class dialect &connection::dialect() const
utils::result<std::unique_ptr<statement_impl>, utils::error> connection::perform_prepare(const query_context& ctx) const { utils::result<std::unique_ptr<statement_impl>, 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 (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) { for (auto &col: ctx.prototype) {
const auto rit = std::find_if( const auto rit = std::find_if(
std::begin(*result), std::begin(*result),

View File

@ -16,37 +16,47 @@ const std::string &dialect::data_type_at(const utils::basic_type type) const
return data_types_.at(type); 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; std::string result;
if (!col.is_function()) { if (!col.is_function()) {
if (!col.table_->name.empty()) { if (!col.table()->name().empty()) {
result = prepare_identifier_string(col.table_->has_alias() ? col.table_->alias : col.table_->name) + "."; 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 { } else {
result = sql_func_map_.at(col.function_) + "(" + col.name + ")"; result = sql_func_map_.at(col.function()) + "(" + col.column_name() + ")";
} }
if (!col.alias.empty()) { if (!col.alias().empty()) {
result += " AS " + col.alias; result += " AS " + col.alias();
} }
return result; 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; std::string result;
if (!col.is_function()) { if (!col.is_function()) {
// if (!col.alias.empty()) { // if (!col.alias.empty()) {
// result = col.alias; // result = col.alias;
// } else { // } else {
if (!col.table_->name.empty()) { if (!col.table()->name().empty()) {
result = prepare_identifier_string(col.table_->has_alias() ? col.table_->alias : col.table_->name) + "."; 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 { } else {
result = sql_func_map_.at(col.function_) + "(" + col.name + ")"; result = sql_func_map_.at(col.function()) + "(" + col.column_name() + ")";
} }
return result; return result;
@ -143,4 +153,199 @@ std::string dialect::default_schema_name() const
return default_schema_name_; 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);
}
} }

View File

@ -67,14 +67,14 @@ const std::vector<record::field_ref> &record::columns() const
// return columns_[pk_index_]; // 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; const auto &f = res.first;
return f; return f;
} }
const field &record::at(size_t index) const const field &record::at(const size_t index) const
{ {
return fields_.at(index); return fields_.at(index);
} }

View File

@ -7,34 +7,51 @@ table::table(const char* name)
{} {}
table::table(std::string name) table::table(std::string name)
: name(std::move(name)) : name_(std::move(name))
{} {}
table::table(const char *name, std::string as) table::table(const char *name, std::string as)
: name(name) : name_(name)
, alias(std::move(as)) , alias_(std::move(as))
{} {}
table::table(std::string name, std::string as) table::table(std::string name, std::string as)
: name(std::move(name)) : name_(std::move(name))
, alias(std::move(as)) , alias_(std::move(as))
{} {}
table::table( std::string name, std::string as, const std::vector<column>& columns )
: name_(std::move(name))
, alias_(std::move(as))
, columns_(columns) {}
bool table::operator==( const table& x ) const { bool table::operator==( const table& x ) const {
return name == x.name; return name_ == x.name_;
} }
table & table::as(const std::string &a) { table & table::as(const std::string &a) {
alias = a; alias_ = a;
return *this; return *this;
} }
table table::as(const std::string &a) const { table table::as(const std::string &a) const {
return { name, a, columns }; return { name_, a, columns_ };
} }
bool table::has_alias() const { 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<column>& table::columns() const {
return columns_;
} }
table operator ""_tab(const char *name, size_t len) { table operator ""_tab(const char *name, size_t len) {

View File

@ -14,7 +14,7 @@ using namespace matador::test;
TEST_CASE_METHOD(SchemaFixture, "Test schema one-two-many", "[schema]") { TEST_CASE_METHOD(SchemaFixture, "Test schema one-two-many", "[schema]") {
using namespace matador::test; using namespace matador::test;
matador::orm::schema repo(pool/*, "NoopSchema"*/); orm::schema repo(pool, "NoopSchema");
auto result = repo.attach<department>("departments") auto result = repo.attach<department>("departments")
.and_then( [&repo] { return repo.attach<employee>("employees"); } ); .and_then( [&repo] { return repo.attach<employee>("employees"); } );

View File

@ -44,7 +44,7 @@ TEST_CASE("Create sql query data for entity with eager has one", "[query][entity
auto data = eqb.build<flight>("flights.id"_col == _); auto data = eqb.build<flight>("flights.id"_col == _);
REQUIRE(data.is_ok()); REQUIRE(data.is_ok());
REQUIRE(data->root_table->name == "flights"); REQUIRE(data->root_table->name() == "flights");
REQUIRE(data->joins.size() == 1); REQUIRE(data->joins.size() == 1);
const std::vector<column> expected_columns { const std::vector<column> expected_columns {
{ "flights", "id", "c01" }, { "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}; size_t index{0};
criteria_evaluator evaluator(db.dialect(), qc); criteria_evaluator evaluator(db.dialect(), qc);
for (const auto &[join_table, condition] : data->joins) { 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); REQUIRE(evaluator.evaluate(*condition) == expected_join_data[index].second);
++index; ++index;
} }
@ -90,7 +90,7 @@ TEST_CASE("Create sql query data for entity with eager belongs to", "[query][ent
auto data = eqb.build<book>("books.id"_col == _); auto data = eqb.build<book>("books.id"_col == _);
REQUIRE(data.is_ok()); REQUIRE(data.is_ok());
REQUIRE(data->root_table->name == "books"); REQUIRE(data->root_table->name() == "books");
REQUIRE(data->joins.size() == 1); REQUIRE(data->joins.size() == 1);
const std::vector<column> expected_columns { const std::vector<column> expected_columns {
{ "books", "id", "c01" }, { "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}; size_t index{0};
criteria_evaluator evaluator(db.dialect(), qc); criteria_evaluator evaluator(db.dialect(), qc);
for (const auto & [join_table, clause] : data->joins) { 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); REQUIRE(evaluator.evaluate(*clause) == expected_join_data[index].second);
++index; ++index;
} }
@ -126,7 +126,7 @@ TEST_CASE("Create sql query data for entity with eager belongs to", "[query][ent
REQUIRE(cond == R"("t01"."id" = ?)"); REQUIRE(cond == R"("t01"."id" = ?)");
auto q = matador::query::query::select(data->columns) auto q = matador::query::query::select(data->columns)
.from(data->root_table->name); .from(data->root_table->name());
for (auto &jd : data->joins) { for (auto &jd : data->joins) {
q.join_left(*jd.join_table) 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<order>("orders.order_id"_col == _); auto data = eqb.build<order>("orders.order_id"_col == _);
REQUIRE(data.is_ok()); REQUIRE(data.is_ok());
REQUIRE(data->root_table->name == "orders"); REQUIRE(data->root_table->name() == "orders");
REQUIRE(data->joins.size() == 1); REQUIRE(data->joins.size() == 1);
const std::vector<column> expected_columns = { const std::vector<column> expected_columns = {
{ "orders", "order_id", "c01" }, { "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}; size_t index{0};
criteria_evaluator evaluator(db.dialect(), qc); criteria_evaluator evaluator(db.dialect(), qc);
for (const auto &jd : data->joins) { 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); REQUIRE(evaluator.evaluate(*jd.condition) == expected_join_data[index].second);
++index; ++index;
} }
@ -210,7 +210,7 @@ TEST_CASE("Create sql query data for entity with eager many to many", "[query][e
auto data = eqb.build<ingredient>("ingredients.id"_col == _); auto data = eqb.build<ingredient>("ingredients.id"_col == _);
REQUIRE(data.is_ok()); REQUIRE(data.is_ok());
REQUIRE(data->root_table->name == "ingredients"); REQUIRE(data->root_table->name() == "ingredients");
REQUIRE(data->joins.size() == 2); REQUIRE(data->joins.size() == 2);
const std::vector<column> expected_columns { const std::vector<column> expected_columns {
{ "ingredients", "id", "c01" }, { "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}; size_t index{0};
criteria_evaluator evaluator(db.dialect(), qc); criteria_evaluator evaluator(db.dialect(), qc);
for (const auto &jd : data->joins) { 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); REQUIRE(evaluator.evaluate(*jd.condition) == expected_join_data[index].second);
++index; ++index;
} }
@ -256,7 +256,7 @@ TEST_CASE("Create sql query data for entity with eager many to many (inverse par
auto data = eqb.build<course>("courses.id"_col == _); auto data = eqb.build<course>("courses.id"_col == _);
REQUIRE(data.is_ok()); REQUIRE(data.is_ok());
REQUIRE(data->root_table->name == "courses"); REQUIRE(data->root_table->name() == "courses");
REQUIRE(data->joins.size() == 2); REQUIRE(data->joins.size() == 2);
const std::vector<column> expected_columns { const std::vector<column> expected_columns {
{ "courses", "id", "c01" }, { "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}; size_t index{0};
criteria_evaluator evaluator(db.dialect(), qc); criteria_evaluator evaluator(db.dialect(), qc);
for (const auto &jd : data->joins) { 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); REQUIRE(evaluator.evaluate(*jd.condition) == expected_join_data[index].second);
++index; ++index;
} }

View File

@ -23,7 +23,7 @@ protected:
TEST_CASE_METHOD(CriteriaFixture, "Test binary criteria", "[criteria][binary]") { TEST_CASE_METHOD(CriteriaFixture, "Test binary criteria", "[criteria][binary]") {
const auto name_col = "name"_col; const auto name_col = "name"_col;
REQUIRE(name_col.name == "name"); REQUIRE(name_col.column_name() == "name");
auto clause = name_col != "george"; auto clause = name_col != "george";

View File

@ -37,7 +37,7 @@ TEST_CASE("Generate columns from object", "[column][generator]") {
REQUIRE(columns.size() == expected_columns.size()); REQUIRE(columns.size() == expected_columns.size());
for (size_t i = 0; i != expected_columns.size(); ++i) { 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());
} }
} }