added alter table command to fluent query builder

This commit is contained in:
Sascha Kühl 2025-11-05 11:05:03 +01:00
parent c87a4c29b4
commit 4b51ad21da
27 changed files with 343 additions and 282 deletions

View File

@ -79,10 +79,11 @@ int main() {
object::repository repo("Administration"); object::repository repo("Administration");
auto result = repo.attach<admin::CollectionCenter>("collection_centers"); auto result = repo.attach<admin::CollectionCenter>("collection_centers");
repo.create(pool); // repo.create(pool);
repo.drop(pool); // repo.drop(pool);
orm::session ses(pool); utils::message_bus bus;
orm::session ses({bus, pool});
result = ses.attach<admin::CollectionCenter>("collection_centers") result = ses.attach<admin::CollectionCenter>("collection_centers")
.and_then([&ses] { return ses.attach<admin::UserDirectory>("user_directories"); }) .and_then([&ses] { return ses.attach<admin::UserDirectory>("user_directories"); })

View File

@ -77,7 +77,7 @@ public:
[[nodiscard]] utils::result<sql::statement, utils::error> prepare(sql::executor &exec) const; [[nodiscard]] utils::result<sql::statement, utils::error> prepare(sql::executor &exec) const;
[[nodiscard]] std::string str(const sql::executor &exec) const; [[nodiscard]] std::string str(const sql::executor &exec) const;
[[nodiscard]] sql::query_context compile(const sql::dialect &d, query_mode mode) const; [[nodiscard]] sql::query_context compile(const sql::dialect &d) const;
private: private:
[[nodiscard]] utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetch(const sql::executor &exec) const; [[nodiscard]] utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetch(const sql::executor &exec) const;

View File

@ -9,8 +9,7 @@
namespace matador::query { namespace matador::query {
class query_create_intermediate : public query_intermediate class query_create_intermediate : public query_intermediate {
{
public: public:
query_create_intermediate(); query_create_intermediate();
@ -20,6 +19,7 @@ public:
executable_query table(const sql::table &table, const object::repository &schema) { executable_query table(const sql::table &table, const object::repository &schema) {
return this->table(table, object::attribute_definition_generator::generate<Type>(schema)); return this->table(table, object::attribute_definition_generator::generate<Type>(schema));
} }
executable_query schema(const std::string &schema_name);
}; };
} }

View File

@ -5,12 +5,12 @@
namespace matador::query { namespace matador::query {
class query_drop_intermediate : query_intermediate class query_drop_intermediate : query_intermediate {
{
public: public:
query_drop_intermediate(); query_drop_intermediate();
executable_query table(const sql::table &table); executable_query table(const sql::table &table);
executable_query schema(const std::string &schema_name);
}; };
} }

View File

@ -3,6 +3,7 @@
#include "matador/sql/column.hpp" #include "matador/sql/column.hpp"
#include "matador/utils/placeholder.hpp"
#include "matador/utils/types.hpp" #include "matador/utils/types.hpp"
namespace matador::query::internal { namespace matador::query::internal {
@ -12,13 +13,14 @@ public:
key_value_pair(const sql::column &col, utils::database_type value); key_value_pair(const sql::column &col, utils::database_type value);
key_value_pair(std::string name, utils::database_type value); key_value_pair(std::string name, utils::database_type value);
key_value_pair(const char *name, utils::database_type value); key_value_pair(const char *name, utils::database_type value);
key_value_pair(const char *name, utils::placeholder p);
[[nodiscard]] const std::string& name() const; [[nodiscard]] const std::string& name() const;
[[nodiscard]] const utils::database_type& value() const; [[nodiscard]] const std::variant<utils::placeholder, utils::database_type>& value() const;
private: private:
std::string name_; std::string name_;
utils::database_type value_; std::variant<utils::placeholder, utils::database_type> value_;
}; };
} }

View File

@ -91,7 +91,7 @@ private:
class query_drop_foreign_key_constraint_part final : public query_part { class query_drop_foreign_key_constraint_part final : public query_part {
public: public:
explicit query_drop_foreign_key_constraint_part( const std::vector<sql::column>& columns); query_drop_foreign_key_constraint_part();
void accept(query_part_visitor &visitor) override; void accept(query_part_visitor &visitor) override;
}; };
@ -377,6 +377,19 @@ private:
std::vector<object::attribute_definition> columns_; std::vector<object::attribute_definition> columns_;
}; };
class query_create_schema_part final : public query_part {
public:
explicit query_create_schema_part(std::string schema);
[[nodiscard]] const std::string& schema() const;
private:
void accept(query_part_visitor &visitor) override;
private:
std::string schema_;
};
class query_drop_part final : public query_part class query_drop_part final : public query_part
{ {
public: public:
@ -400,5 +413,18 @@ private:
sql::table table_; sql::table table_;
}; };
class query_drop_schema_part final : public query_part {
public:
explicit query_drop_schema_part(std::string schema_);
[[nodiscard]] const std::string& schema() const;
private:
void accept(query_part_visitor &visitor) override;
private:
std::string schema_;
};
} }
#endif //QUERY_QUERY_PARTS_HPP #endif //QUERY_QUERY_PARTS_HPP

View File

@ -20,6 +20,7 @@ class query
public: public:
[[nodiscard]] static query_create_intermediate create(); [[nodiscard]] static query_create_intermediate create();
[[nodiscard]] static query_drop_intermediate drop(); [[nodiscard]] static query_drop_intermediate drop();
[[nodiscard]] static query_select_intermediate select();
[[nodiscard]] static query_select_intermediate select(std::initializer_list<sql::column> columns); [[nodiscard]] static query_select_intermediate select(std::initializer_list<sql::column> columns);
[[nodiscard]] static query_select_intermediate select(const std::vector<sql::column>& columns); [[nodiscard]] static query_select_intermediate select(const std::vector<sql::column>& columns);
[[nodiscard]] static query_select_intermediate select(const std::vector<std::string> &column_names); [[nodiscard]] static query_select_intermediate select(const std::vector<std::string> &column_names);

View File

@ -22,8 +22,7 @@ struct basic_type_to_string_visitor;
struct query_data; struct query_data;
struct value_visitor; struct value_visitor;
class query_compiler final : public query_part_visitor class query_compiler final : public query_part_visitor {
{
public: public:
sql::query_context compile(const query_data &data, sql::query_context compile(const query_data &data,
const sql::dialect &d, const sql::dialect &d,
@ -33,42 +32,45 @@ protected:
void visit(internal::query_alter_part& part) override; void visit(internal::query_alter_part& part) override;
void visit(internal::query_alter_table_part& part) override; void visit(internal::query_alter_table_part& part) override;
void visit(internal::query_add_key_constraint_part& part) override; void visit(internal::query_add_key_constraint_part& part) override;
void visit( internal::query_add_foreign_key_constraint_part& part ) override; void visit(internal::query_add_foreign_key_constraint_part& part) override;
void visit( internal::query_add_primary_key_constraint_part& part ) override; void visit(internal::query_add_primary_key_constraint_part& part) override;
void visit( internal::query_add_foreign_key_reference_part& part ) override; void visit(internal::query_add_foreign_key_reference_part& part) override;
void visit(internal::query_drop_key_constraint_part& part) override; void visit(internal::query_drop_key_constraint_part& part) override;
void visit(internal::query_drop_foreign_key_constraint_part& part) override;
void visit(internal::query_select_part &select_part) override; protected:
void visit(internal::query_from_part &from_part) override; void visit(internal::query_select_part &part) override;
void visit(internal::query_join_part &join_part) override; void visit(internal::query_from_part &part) override;
void visit(internal::query_on_part &on_part) override; void visit(internal::query_join_part &part) override;
void visit(internal::query_where_part &where_part) override; void visit(internal::query_on_part &part) override;
void visit(internal::query_group_by_part &group_by_part) override; void visit(internal::query_where_part &part) override;
void visit(internal::query_order_by_part &order_by_part) override; void visit(internal::query_group_by_part &part) override;
void visit(internal::query_order_by_asc_part &order_by_asc_part) override; void visit(internal::query_order_by_part &part) override;
void visit(internal::query_order_by_desc_part &order_by_desc_part) override; void visit(internal::query_order_by_asc_part &part) override;
void visit(internal::query_offset_part &offset_part) override; void visit(internal::query_order_by_desc_part &part) override;
void visit(internal::query_limit_part &limit_part) override; void visit(internal::query_offset_part &part) override;
void visit(internal::query_insert_part &insert_part) override; void visit(internal::query_limit_part &part) override;
void visit(internal::query_into_part &into_part) override; void visit(internal::query_insert_part &part) override;
void visit(internal::query_values_part &values_part) override; void visit(internal::query_into_part &part) override;
void visit(internal::query_values_part &part) override;
void visit(internal::query_update_part &update_part) override; void visit(internal::query_update_part &part) override;
void visit(internal::query_set_part &set_part) override; void visit(internal::query_set_part &part) override;
void visit(internal::query_delete_part &delete_part) override; void visit(internal::query_delete_part &part) override;
void visit(internal::query_delete_from_part &delete_from_part) override; void visit(internal::query_delete_from_part &part) override;
void visit(internal::query_create_part &create_part) override; void visit(internal::query_create_part &part) override;
void visit(internal::query_create_table_part &create_table_part) override; void visit(internal::query_create_table_part &part) override;
void visit(internal::query_create_schema_part& part) override;
void visit(internal::query_drop_part &drop_part) override; void visit(internal::query_drop_part &part) override;
void visit(internal::query_drop_table_part &drop_table_part) override; void visit(internal::query_drop_table_part &part) override;
void visit(internal::query_drop_schema_part& part) override;
static std::string build_table_name(sql::dialect_token token, const sql::dialect &d, const sql::table& t); static std::string build_table_name(sql::dialect_token token, const sql::dialect &d, const sql::table& t);
std::string determine_value(value_visitor &visitor, const std::variant<utils::placeholder, utils::database_type> &val); static std::string determine_value(value_visitor &visitor, const std::variant<utils::placeholder, utils::database_type> &val);
std::string determine_set_value(internal::basic_type_to_string_visitor &visitor, const utils::database_type &val);
protected: protected:
const query_data *data_{}; const query_data *data_{};

View File

@ -12,16 +12,10 @@
namespace matador::query { namespace matador::query {
enum struct query_mode {
Direct = 0,
Prepared = 1
};
struct query_data { struct query_data {
std::vector<std::unique_ptr<query_part>> parts{}; std::vector<std::unique_ptr<query_part>> parts{};
std::vector<object::attribute_definition> columns{}; std::vector<object::attribute_definition> columns{};
std::unordered_map<std::string, sql::table> tables{}; std::unordered_map<std::string, sql::table> tables{};
query_mode mode = query_mode::Direct;
}; };
} }

View File

@ -8,6 +8,7 @@ class query_alter_part;
class query_alter_table_part; class query_alter_table_part;
class query_add_key_constraint_part; class query_add_key_constraint_part;
class query_drop_key_constraint_part; class query_drop_key_constraint_part;
class query_drop_foreign_key_constraint_part;
class query_add_foreign_key_constraint_part; class query_add_foreign_key_constraint_part;
class query_add_foreign_key_reference_part; class query_add_foreign_key_reference_part;
class query_add_primary_key_constraint_part; class query_add_primary_key_constraint_part;
@ -31,8 +32,10 @@ class query_delete_part;
class query_delete_from_part; class query_delete_from_part;
class query_create_part; class query_create_part;
class query_create_table_part; class query_create_table_part;
class query_create_schema_part;
class query_drop_part; class query_drop_part;
class query_drop_table_part; class query_drop_table_part;
class query_drop_schema_part;
} }
class query_part_visitor { class query_part_visitor {
@ -46,34 +49,37 @@ public:
virtual void visit(internal::query_add_primary_key_constraint_part &part) = 0; virtual void visit(internal::query_add_primary_key_constraint_part &part) = 0;
virtual void visit(internal::query_add_foreign_key_reference_part &part) = 0; virtual void visit(internal::query_add_foreign_key_reference_part &part) = 0;
virtual void visit(internal::query_drop_key_constraint_part &part) = 0; virtual void visit(internal::query_drop_key_constraint_part &part) = 0;
virtual void visit(internal::query_drop_foreign_key_constraint_part &part) = 0;
virtual void visit(internal::query_select_part &select_part) = 0; virtual void visit(internal::query_select_part &part) = 0;
virtual void visit(internal::query_from_part &from_part) = 0; virtual void visit(internal::query_from_part &part) = 0;
virtual void visit(internal::query_join_part &join_part) = 0; virtual void visit(internal::query_join_part &part) = 0;
virtual void visit(internal::query_on_part &on_part) = 0; virtual void visit(internal::query_on_part &part) = 0;
virtual void visit(internal::query_where_part &where_part) = 0; virtual void visit(internal::query_where_part &part) = 0;
virtual void visit(internal::query_group_by_part &group_by_part) = 0; virtual void visit(internal::query_group_by_part &part) = 0;
virtual void visit(internal::query_order_by_part &order_by_part) = 0; virtual void visit(internal::query_order_by_part &part) = 0;
virtual void visit(internal::query_order_by_asc_part &order_by_asc_part) = 0; virtual void visit(internal::query_order_by_asc_part &part) = 0;
virtual void visit(internal::query_order_by_desc_part &order_by_desc_part) = 0; virtual void visit(internal::query_order_by_desc_part &part) = 0;
virtual void visit(internal::query_offset_part &offset_part) = 0; virtual void visit(internal::query_offset_part &part) = 0;
virtual void visit(internal::query_limit_part &limit_part) = 0; virtual void visit(internal::query_limit_part &part) = 0;
virtual void visit(internal::query_insert_part &insert_part) = 0; virtual void visit(internal::query_insert_part &part) = 0;
virtual void visit(internal::query_into_part &into_part) = 0; virtual void visit(internal::query_into_part &part) = 0;
virtual void visit(internal::query_values_part &values_part) = 0; virtual void visit(internal::query_values_part &part) = 0;
virtual void visit(internal::query_update_part &update_part) = 0; virtual void visit(internal::query_update_part &part) = 0;
virtual void visit(internal::query_set_part &set_part) = 0; virtual void visit(internal::query_set_part &part) = 0;
virtual void visit(internal::query_delete_part &delete_part) = 0; virtual void visit(internal::query_delete_part &part) = 0;
virtual void visit(internal::query_delete_from_part &delete_from_part) = 0; virtual void visit(internal::query_delete_from_part &part) = 0;
virtual void visit(internal::query_create_part &create_part) = 0; virtual void visit(internal::query_create_part &part) = 0;
virtual void visit(internal::query_create_table_part &create_table_part) = 0; virtual void visit(internal::query_create_table_part &part) = 0;
virtual void visit(internal::query_create_schema_part &part) = 0;
virtual void visit(internal::query_drop_part &drop_part) = 0; virtual void visit(internal::query_drop_part &part) = 0;
virtual void visit(internal::query_drop_table_part &drop_table_part) = 0; virtual void visit(internal::query_drop_table_part &part) = 0;
virtual void visit(internal::query_drop_schema_part &part) = 0;
}; };
} }

View File

@ -136,58 +136,57 @@ private:
escape_identifier_t identifier_escape_type_ = escape_identifier_t::ESCAPE_BOTH_SAME; escape_identifier_t identifier_escape_type_ = escape_identifier_t::ESCAPE_BOTH_SAME;
std::string default_schema_name_; std::string default_schema_name_;
// std::unique_ptr<query_compiler> compiler_;
token_to_string_map tokens_ { token_to_string_map tokens_ {
{dialect_token::Create, "CREATE"},
{dialect_token::Drop, "DROP"},
{dialect_token::Remove, "DELETE"},
{dialect_token::Insert, "INSERT"},
{dialect_token::Alter, "ALTER"},
{dialect_token::Table, "TABLE"},
{dialect_token::Into, "INTO"},
{dialect_token::Values, "VALUES"},
{dialect_token::Update, "UPDATE"},
{dialect_token::Select, "SELECT"},
{dialect_token::Columns, "COLUMNS"},
{dialect_token::Column, "COLUMN"},
{dialect_token::From, "FROM"},
{dialect_token::Join, "LEFT JOIN"},
{dialect_token::On, "ON"},
{dialect_token::Where, "WHERE"},
{dialect_token::And, "AND"},
{dialect_token::Or, "OR"},
{dialect_token::Not, "NOT"},
{dialect_token::Like, "LIKE"},
{dialect_token::Between, "BETWEEN"},
{dialect_token::In, "IN"},
{dialect_token::OrderBy, "ORDER BY"},
{dialect_token::GroupBy, "GROUP BY"},
{dialect_token::Asc, "ASC"},
{dialect_token::Desc, "DESC"},
{dialect_token::Offset, "OFFSET"},
{dialect_token::Limit, "LIMIT"},
{dialect_token::As, "AS"},
{dialect_token::Offset, "OFFSET"},
{dialect_token::Distinct, "DISTINCT"},
{dialect_token::Set, "SET"},
{dialect_token::NotNull, "NOT NULL"},
{dialect_token::PrimaryKey, "PRIMARY KEY"},
{dialect_token::ForeignKey, "FOREIGN KEY"},
{dialect_token::References, "REFERENCES"},
{dialect_token::AddConstraint, "ADD CONSTRAINT"}, {dialect_token::AddConstraint, "ADD CONSTRAINT"},
{dialect_token::DropConstraint, "DROP CONSTRAINT"}, {dialect_token::Alter, "ALTER"},
{dialect_token::And, "AND"},
{dialect_token::As, "AS"},
{dialect_token::Asc, "ASC"},
{dialect_token::Asterisk, "*"},
{dialect_token::Begin, "BEGIN TRANSACTION"}, {dialect_token::Begin, "BEGIN TRANSACTION"},
{dialect_token::Commit, "COMMIT TRANSACTION"},
{dialect_token::Rollback, "ROLLBACK TRANSACTION"},
{dialect_token::StartQuote, "\""},
{dialect_token::EndQuote, "\""},
{dialect_token::StringQuote, "'"},
{dialect_token::BeginBinaryData, "X'"}, {dialect_token::BeginBinaryData, "X'"},
{dialect_token::EndBinaryData, "'"},
{dialect_token::BeginStringData, "'"}, {dialect_token::BeginStringData, "'"},
{dialect_token::Between, "BETWEEN"},
{dialect_token::Column, "COLUMN"},
{dialect_token::Columns, "COLUMNS"},
{dialect_token::Commit, "COMMIT TRANSACTION"},
{dialect_token::Create, "CREATE"},
{dialect_token::Desc, "DESC"},
{dialect_token::Distinct, "DISTINCT"},
{dialect_token::Drop, "DROP"},
{dialect_token::DropConstraint, "DROP CONSTRAINT"},
{dialect_token::EndBinaryData, "'"},
{dialect_token::EndQuote, "\""},
{dialect_token::EndStringData, "'"}, {dialect_token::EndStringData, "'"},
{dialect_token::None, ""} {dialect_token::ForeignKey, "FOREIGN KEY"},
{dialect_token::From, "FROM"},
{dialect_token::GroupBy, "GROUP BY"},
{dialect_token::In, "IN"},
{dialect_token::Insert, "INSERT"},
{dialect_token::Into, "INTO"},
{dialect_token::Join, "LEFT JOIN"},
{dialect_token::Like, "LIKE"},
{dialect_token::Limit, "LIMIT"},
{dialect_token::None, ""},
{dialect_token::Not, "NOT"},
{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::Remove, "DELETE"},
{dialect_token::Rollback, "ROLLBACK TRANSACTION"},
{dialect_token::Select, "SELECT"},
{dialect_token::Set, "SET"},
{dialect_token::StartQuote, "\""},
{dialect_token::StringQuote, "'"},
{dialect_token::Table, "TABLE"},
{dialect_token::Update, "UPDATE"},
{dialect_token::Values, "VALUES"},
{dialect_token::Where, "WHERE"}
}; };
data_type_to_string_map data_types_ { data_type_to_string_map data_types_ {

View File

@ -6,59 +6,57 @@
namespace matador::sql { namespace matador::sql {
enum class dialect_token : uint8_t { enum class dialect_token : uint8_t {
Create = 0, AddConstraint = 0,
Drop,
Remove,
Insert,
Update,
Select,
Alter, Alter,
ForeignKey,
PrimaryKey,
AddConstraint,
DropConstraint,
References,
Schema,
Database,
Table,
Values,
InsertValues,
Columns,
Column,
From,
Join,
On,
Into,
Where,
WhereClause,
And, And,
Or,
Not,
Like,
Between,
In,
OrderBy,
GroupBy,
Asc,
Desc,
Limit,
As, As,
Offset, Asc,
Distinct, Asterisk,
Set,
UpdateValues,
NotNull,
Begin, Begin,
Commit,
Rollback,
StartQuote,
EndQuote,
StringQuote,
BeginBinaryData, BeginBinaryData,
EndBinaryData,
BeginStringData, BeginStringData,
Between,
Column,
Columns,
Commit,
Create,
Database,
Desc,
Distinct,
Drop,
DropConstraint,
EndBinaryData,
EndQuote,
EndStringData, EndStringData,
None ForeignKey,
From,
GroupBy,
In,
Insert,
Into,
Join,
Like,
Limit,
None,
Not,
NotNull,
Offset,
On,
Or,
OrderBy,
PrimaryKey,
References,
Remove,
Rollback,
Schema,
Select,
Set,
StartQuote,
StringQuote,
Table,
Update,
Values,
Where
}; };
} }

View File

@ -10,6 +10,7 @@ namespace matador::sql {
enum class sql_command { enum class sql_command {
SQL_UNKNOWN, SQL_UNKNOWN,
SQL_CREATE,
SQL_CREATE_TABLE, SQL_CREATE_TABLE,
SQL_CREATE_SCHEMA, SQL_CREATE_SCHEMA,
SQL_CREATE_DATABASE, SQL_CREATE_DATABASE,
@ -17,6 +18,7 @@ enum class sql_command {
SQL_INSERT, SQL_INSERT,
SQL_DELETE, SQL_DELETE,
SQL_SELECT, SQL_SELECT,
SQL_DROP,
SQL_DROP_TABLE, SQL_DROP_TABLE,
SQL_DROP_SCHEMA, SQL_DROP_SCHEMA,
SQL_DROP_DATABASE, SQL_DROP_DATABASE,

View File

@ -10,8 +10,7 @@ namespace matador::sql {
struct column; struct column;
class record class record final {
{
private: private:
using field_ref = std::reference_wrapper<field>; using field_ref = std::reference_wrapper<field>;
using field_by_index = std::vector<field_ref>; using field_by_index = std::vector<field_ref>;
@ -45,13 +44,11 @@ public:
[[nodiscard]] const field& at(const column &col) const; [[nodiscard]] const field& at(const 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 {
{
return at(col).as<Type>(); return at(col).as<Type>();
} }
template<class Type> template<class Type>
std::optional<Type> at(size_t index) const std::optional<Type> at(const size_t index) const {
{
return at(index).as<Type>(); return at(index).as<Type>();
} }
@ -70,8 +67,6 @@ public:
[[nodiscard]] bool empty() const; [[nodiscard]] bool empty() const;
void clear(); void clear();
// [[nodiscard]] bool unknown() const;
private: private:
void init(); void init();
void add_to_map(field &col, size_t index); void add_to_map(field &col, size_t index);
@ -79,8 +74,6 @@ private:
private: private:
field_by_index fields_; field_by_index fields_;
field_by_name_map fields_by_name_; field_by_name_map fields_by_name_;
// int pk_index_{-1};
}; };
} }

View File

@ -68,7 +68,7 @@ public:
return bus_.subscribe<EventType>(handler); return bus_.subscribe<EventType>(handler);
} }
connection_pool& pool() const; [[nodiscard]] connection_pool& pool() const;
private: private:
size_t max_size_{}; size_t max_size_{};

View File

@ -19,6 +19,7 @@ add_library(matador-orm STATIC
../../include/matador/query/intermediates/executable_query.hpp ../../include/matador/query/intermediates/executable_query.hpp
../../include/matador/query/intermediates/fetchable_query.hpp ../../include/matador/query/intermediates/fetchable_query.hpp
../../include/matador/query/intermediates/query_alter_intermediate.hpp ../../include/matador/query/intermediates/query_alter_intermediate.hpp
../../include/matador/query/intermediates/query_alter_table_intermediate.hpp
../../include/matador/query/intermediates/query_create_intermediate.hpp ../../include/matador/query/intermediates/query_create_intermediate.hpp
../../include/matador/query/intermediates/query_delete_from_intermediate.hpp ../../include/matador/query/intermediates/query_delete_from_intermediate.hpp
../../include/matador/query/intermediates/query_delete_intermediate.hpp ../../include/matador/query/intermediates/query_delete_intermediate.hpp
@ -97,6 +98,7 @@ add_library(matador-orm STATIC
query/intermediates/executable_query.cpp query/intermediates/executable_query.cpp
query/intermediates/fetchable_query.cpp query/intermediates/fetchable_query.cpp
query/intermediates/query_alter_intermediate.cpp query/intermediates/query_alter_intermediate.cpp
query/intermediates/query_alter_table_intermediate.cpp
query/intermediates/query_create_intermediate.cpp query/intermediates/query_create_intermediate.cpp
query/intermediates/query_delete_from_intermediate.cpp query/intermediates/query_delete_from_intermediate.cpp
query/intermediates/query_delete_intermediate.cpp query/intermediates/query_delete_intermediate.cpp
@ -118,6 +120,7 @@ add_library(matador-orm STATIC
query/intermediates/query_order_direction_intermediate.cpp query/intermediates/query_order_direction_intermediate.cpp
query/intermediates/query_select_intermediate.cpp query/intermediates/query_select_intermediate.cpp
query/intermediates/query_set_intermediate.cpp query/intermediates/query_set_intermediate.cpp
query/intermediates/query_update_intermediate.cpp
query/intermediates/query_where_intermediate.cpp query/intermediates/query_where_intermediate.cpp
query/internal/basic_type_to_string_visitor.cpp query/internal/basic_type_to_string_visitor.cpp
query/internal/key_value_pair.cpp query/internal/key_value_pair.cpp
@ -127,7 +130,6 @@ add_library(matador-orm STATIC
query/query.cpp query/query.cpp
query/query_compiler.cpp query/query_compiler.cpp
query/query_part.cpp query/query_part.cpp
query/query_update_intermediate.cpp
query/value_extractor.cpp query/value_extractor.cpp
sql/backend_provider.cpp sql/backend_provider.cpp
sql/column.cpp sql/column.cpp
@ -152,8 +154,6 @@ add_library(matador-orm STATIC
sql/statement.cpp sql/statement.cpp
sql/statement_cache.cpp sql/statement_cache.cpp
sql/table.cpp sql/table.cpp
../../include/matador/query/intermediates/query_alter_table_intermediate.hpp
query/intermediates/query_alter_table_intermediate.cpp
) )
target_include_directories(matador-orm target_include_directories(matador-orm

View File

@ -8,25 +8,21 @@ namespace matador::query {
utils::result<size_t, utils::error> executable_query::execute(const sql::executor &exec) const { utils::result<size_t, utils::error> executable_query::execute(const sql::executor &exec) const {
query_compiler compiler; query_compiler compiler;
context_->mode = query_mode::Direct;
return exec.execute(compiler.compile(*context_, exec.dialect(), std::nullopt)); return exec.execute(compiler.compile(*context_, exec.dialect(), std::nullopt));
} }
utils::result<sql::statement, utils::error> executable_query::prepare(sql::executor &exec) const { utils::result<sql::statement, utils::error> executable_query::prepare(sql::executor &exec) const {
query_compiler compiler; query_compiler compiler;
context_->mode = query_mode::Prepared;
return exec.prepare(compiler.compile(*context_, exec.dialect(), std::nullopt)); return exec.prepare(compiler.compile(*context_, exec.dialect(), std::nullopt));
} }
sql::query_context executable_query::compile( const sql::executor& exec ) const { sql::query_context executable_query::compile( const sql::executor& exec ) const {
query_compiler compiler; query_compiler compiler;
context_->mode = query_mode::Prepared;
return compiler.compile(*context_, exec.dialect(), std::nullopt); return compiler.compile(*context_, exec.dialect(), std::nullopt);
} }
std::string executable_query::str(const sql::executor &exec) const { std::string executable_query::str(const sql::executor &exec) const {
query_compiler compiler; query_compiler compiler;
context_->mode = query_mode::Direct;
return exec.str(compiler.compile(*context_, exec.dialect(), std::nullopt)); return exec.str(compiler.compile(*context_, exec.dialect(), std::nullopt));
} }

View File

@ -34,7 +34,6 @@ sql::record *create_prototype(const std::vector<object::attribute_definition> &p
} }
utils::result<sql::query_result<sql::record>, utils::error> fetchable_query::fetch_all(const sql::executor &exec) const { utils::result<sql::query_result<sql::record>, utils::error> fetchable_query::fetch_all(const sql::executor &exec) const {
query_compiler compiler; query_compiler compiler;
context_->mode = query_mode::Direct;
const auto ctx = compiler.compile(*context_, exec.dialect(), std::nullopt); const auto ctx = compiler.compile(*context_, exec.dialect(), std::nullopt);
return exec.fetch(ctx) return exec.fetch(ctx)
.and_then([](auto &&res) { .and_then([](auto &&res) {
@ -47,7 +46,6 @@ utils::result<sql::query_result<sql::record>, utils::error> fetchable_query::fet
utils::result<std::optional<sql::record>, utils::error> fetchable_query::fetch_one(const sql::executor &exec) const { utils::result<std::optional<sql::record>, utils::error> fetchable_query::fetch_one(const sql::executor &exec) const {
query_compiler compiler; query_compiler compiler;
context_->mode = query_mode::Direct;
auto result = exec.fetch(compiler.compile(*context_, exec.dialect(), std::nullopt)); auto result = exec.fetch(compiler.compile(*context_, exec.dialect(), std::nullopt));
if (!result.is_ok()) { if (!result.is_ok()) {
return utils::failure(result.err()); return utils::failure(result.err());
@ -66,21 +64,20 @@ utils::result<std::optional<sql::record>, utils::error> fetchable_query::fetch_o
} }
std::string fetchable_query::str(const sql::executor &exec) const { std::string fetchable_query::str(const sql::executor &exec) const {
return exec.str(compile(exec.dialect(), query_mode::Direct)); return exec.str(compile(exec.dialect()));
} }
sql::query_context fetchable_query::compile(const sql::dialect &d, const query_mode mode) const { sql::query_context fetchable_query::compile(const sql::dialect &d) const {
query_compiler compiler; query_compiler compiler;
context_->mode = mode;
return compiler.compile(*context_, d, std::nullopt); return compiler.compile(*context_, d, std::nullopt);
} }
utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetchable_query::fetch(const sql::executor &exec) const { utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> fetchable_query::fetch(const sql::executor &exec) const {
return exec.fetch(compile(exec.dialect(), query_mode::Direct)); return exec.fetch(compile(exec.dialect()));
} }
utils::result<sql::statement, utils::error> fetchable_query::prepare(sql::executor &exec) const { utils::result<sql::statement, utils::error> fetchable_query::prepare(sql::executor &exec) const {
return exec.prepare(compile(exec.dialect(), query_mode::Prepared)); return exec.prepare(compile(exec.dialect()));
} }
} }

View File

@ -4,20 +4,21 @@
namespace matador::query { namespace matador::query {
query_create_intermediate::query_create_intermediate() query_create_intermediate::query_create_intermediate() {
{
context_->parts.push_back(std::make_unique<internal::query_create_part>()); context_->parts.push_back(std::make_unique<internal::query_create_part>());
} }
executable_query query_create_intermediate::table(const sql::table &table, const std::initializer_list<object::attribute_definition> columns) executable_query query_create_intermediate::table(const sql::table &table, const std::initializer_list<object::attribute_definition> columns) {
{
return this->table(table, std::vector<object::attribute_definition>{columns}); return this->table(table, std::vector<object::attribute_definition>{columns});
} }
executable_query query_create_intermediate::table(const sql::table &table, const std::vector<object::attribute_definition> &columns) executable_query query_create_intermediate::table(const sql::table &table, const std::vector<object::attribute_definition> &columns) {
{
context_->parts.push_back(std::make_unique<internal::query_create_table_part>(table, columns)); context_->parts.push_back(std::make_unique<internal::query_create_table_part>(table, columns));
return {context_}; return {context_};
} }
executable_query query_create_intermediate::schema( const std::string& schema_name ) {
context_->parts.push_back(std::make_unique<internal::query_create_schema_part>(schema_name));
return {context_};
}
} }

View File

@ -4,13 +4,11 @@
namespace matador::query { namespace matador::query {
query_drop_intermediate::query_drop_intermediate() query_drop_intermediate::query_drop_intermediate() {
{
context_->parts.push_back(std::make_unique<internal::query_drop_part>()); context_->parts.push_back(std::make_unique<internal::query_drop_part>());
} }
executable_query query_drop_intermediate::table(const sql::table &table) executable_query query_drop_intermediate::table(const sql::table &table) {
{
context_->parts.push_back(std::make_unique<internal::query_drop_table_part>(table)); context_->parts.push_back(std::make_unique<internal::query_drop_table_part>(table));
return {context_}; return {context_};
} }

View File

@ -15,15 +15,19 @@ key_value_pair::key_value_pair(const sql::column &col, utils::database_type valu
} }
key_value_pair::key_value_pair(const char *name, utils::database_type value) key_value_pair::key_value_pair(const char *name, utils::database_type value)
: name_(name) : name_(name)
, value_(std::move(value)) { , value_(std::move(value)) {
} }
key_value_pair::key_value_pair( const char* name, utils::placeholder p )
: name_(name)
, value_(p) {}
const std::string &key_value_pair::name() const { const std::string &key_value_pair::name() const {
return name_; return name_;
} }
const utils::database_type& key_value_pair::value() const { const std::variant<utils::placeholder, utils::database_type>& key_value_pair::value() const {
return value_; return value_;
} }
} }

View File

@ -46,6 +46,13 @@ const std::string& query_drop_key_constraint_part::name() const {
return name_; return name_;
} }
query_drop_foreign_key_constraint_part::query_drop_foreign_key_constraint_part()
: query_part( sql::dialect_token::DropConstraint ) {}
void query_drop_foreign_key_constraint_part::accept( query_part_visitor& visitor ) {
visitor.visit(*this);
}
query_add_foreign_key_constraint_part::query_add_foreign_key_constraint_part(const std::vector<sql::column>& columns) query_add_foreign_key_constraint_part::query_add_foreign_key_constraint_part(const std::vector<sql::column>& columns)
: query_part(sql::dialect_token::ForeignKey) : query_part(sql::dialect_token::ForeignKey)
, columns_(columns) {} , columns_(columns) {}
@ -357,6 +364,18 @@ void query_create_table_part::accept(query_part_visitor &visitor)
visitor.visit(*this); visitor.visit(*this);
} }
query_create_schema_part::query_create_schema_part(std::string schema)
: query_part( sql::dialect_token::Schema )
, schema_( std::move( schema ) ){}
const std::string& query_create_schema_part::schema() const {
return schema_;
}
void query_create_schema_part::accept( query_part_visitor& visitor ) {
visitor.visit(*this);
}
query_drop_part::query_drop_part() query_drop_part::query_drop_part()
: query_part(sql::dialect_token::Drop) {} : query_part(sql::dialect_token::Drop) {}
@ -379,4 +398,15 @@ void query_drop_table_part::accept(query_part_visitor &visitor)
visitor.visit(*this); visitor.visit(*this);
} }
query_drop_schema_part::query_drop_schema_part(std::string schema_)
: query_part( sql::dialect_token::Schema )
, schema_( std::move( schema_ ) ) {}
const std::string& query_drop_schema_part::schema() const {
return schema_;
}
void query_drop_schema_part::accept( query_part_visitor& visitor ) {
visitor.visit(*this);
}
} }

View File

@ -32,6 +32,10 @@ query_drop_intermediate query::drop() {
return {}; return {};
} }
query_select_intermediate query::select() {
return query_select_intermediate{{}};
}
query_select_intermediate query::select( const std::initializer_list<sql::column> columns) { query_select_intermediate query::select( const std::initializer_list<sql::column> columns) {
return select(std::vector<sql::column>{columns}); return select(std::vector<sql::column>{columns});
} }

View File

@ -65,7 +65,7 @@ void query_compiler::visit(internal::query_add_key_constraint_part& part) {
query_.sql += " " + dialect_->token_at(sql::dialect_token::AddConstraint) + " " + part.name(); query_.sql += " " + dialect_->token_at(sql::dialect_token::AddConstraint) + " " + part.name();
} }
void query_compiler::visit( internal::query_add_foreign_key_constraint_part& part ) { void query_compiler::visit(internal::query_add_foreign_key_constraint_part& part) {
query_.sql += " " + dialect_->token_at(part.token()) + " ("; query_.sql += " " + dialect_->token_at(part.token()) + " (";
if (part.columns().size() < 2) { if (part.columns().size() < 2) {
@ -82,9 +82,9 @@ void query_compiler::visit( internal::query_add_foreign_key_constraint_part& par
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) {}
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 + " (";
@ -106,7 +106,10 @@ void query_compiler::visit(internal::query_drop_key_constraint_part& part) {
query_.sql += " " + dialect_->token_at(part.token()) + " " + part.name(); query_.sql += " " + dialect_->token_at(part.token()) + " " + part.name();
} }
void query_compiler::visit(internal::query_select_part &select_part) void query_compiler::visit(internal::query_drop_foreign_key_constraint_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_->token_at(sql::dialect_token::Select) + " ";
@ -114,7 +117,9 @@ void query_compiler::visit(internal::query_select_part &select_part)
query_.prototype.clear(); query_.prototype.clear();
std::string result; std::string result;
if (const auto &columns = select_part.columns(); columns.size() < 2) { if (part.columns().empty()) {
result = dialect_->token_at(sql::dialect_token::Asterisk);
} 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 ));
} }
@ -130,38 +135,38 @@ void query_compiler::visit(internal::query_select_part &select_part)
query_.sql += result; query_.sql += result;
} }
void query_compiler::visit(internal::query_from_part &from_part) void query_compiler::visit(internal::query_from_part &part)
{ {
query_.table = from_part.table(); query_.table = part.table();
query_.sql += " " + build_table_name(from_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 &join_part) void query_compiler::visit(internal::query_join_part &part)
{ {
query_.sql += " " + query_compiler::build_table_name(join_part.token(), *dialect_, join_part.table()); query_.sql += " " + query_compiler::build_table_name(part.token(), *dialect_, part.table());
} }
void query_compiler::visit(internal::query_on_part &on_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_->token_at(sql::dialect_token::On) +
" " + evaluator.evaluate(on_part.condition()); " " + evaluator.evaluate(part.condition());
} }
void query_compiler::visit(internal::query_where_part &where_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_->token_at(sql::dialect_token::Where) +
" " + evaluator.evaluate(where_part.condition()); " " + evaluator.evaluate(part.condition());
} }
void query_compiler::visit(internal::query_group_by_part &group_by_part) { void query_compiler::visit(internal::query_group_by_part &part) {
query_.sql += " " + dialect_->token_at(sql::dialect_token::GroupBy) + " " + dialect_->prepare_identifier(group_by_part.column()); query_.sql += " " + dialect_->token_at(sql::dialect_token::GroupBy) + " " + dialect_->prepare_identifier(part.column());
} }
void query_compiler::visit(internal::query_order_by_part &order_by_part) void query_compiler::visit(internal::query_order_by_part &part)
{ {
query_.sql += " " + dialect_->token_at(sql::dialect_token::OrderBy) + query_.sql += " " + dialect_->token_at(sql::dialect_token::OrderBy) +
" " + dialect_->prepare_condition(order_by_part.column()); " " + dialect_->prepare_condition(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*/)
@ -174,14 +179,14 @@ void query_compiler::visit(internal::query_order_by_desc_part &/*order_by_desc_p
query_.sql += " " + dialect_->token_at(sql::dialect_token::Desc); query_.sql += " " + dialect_->token_at(sql::dialect_token::Desc);
} }
void query_compiler::visit(internal::query_offset_part &offset_part) void query_compiler::visit(internal::query_offset_part &part)
{ {
query_.sql += " " + dialect_->token_at(sql::dialect_token::Offset) + " " + std::to_string(offset_part.offset()); query_.sql += " " + dialect_->token_at(sql::dialect_token::Offset) + " " + std::to_string(part.offset());
} }
void query_compiler::visit(internal::query_limit_part &limit_part) void query_compiler::visit(internal::query_limit_part &part)
{ {
query_.sql += " " + dialect_->token_at(sql::dialect_token::Limit) + " " + std::to_string(limit_part.limit()); query_.sql += " " + dialect_->token_at(sql::dialect_token::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*/)
@ -190,21 +195,21 @@ void query_compiler::visit(internal::query_insert_part &/*insert_part*/)
query_.sql = dialect_->token_at(sql::dialect_token::Insert); query_.sql = dialect_->token_at(sql::dialect_token::Insert);
} }
void query_compiler::visit(internal::query_into_part &into_part) void query_compiler::visit(internal::query_into_part &part)
{ {
query_.table = into_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(into_part.table().name); " " + dialect_->prepare_identifier_string(part.table().name);
std::string result{"("}; std::string result{"("};
if (into_part.columns().size() < 2) { if (part.columns().size() < 2) {
for (const auto &col: into_part.columns()) { for (const auto &col: part.columns()) {
result.append(dialect_->prepare_identifier_string(col.name)); result.append(dialect_->prepare_identifier_string(col.name));
} }
} else { } else {
auto it = into_part.columns().begin(); auto it = part.columns().begin();
result.append(dialect_->prepare_identifier_string((it++)->name)); result.append(dialect_->prepare_identifier_string((it++)->name));
for (; it != into_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->name));
} }
@ -222,7 +227,7 @@ struct value_visitor {
} }
void operator()(const utils::placeholder &/*val*/) { void operator()(const utils::placeholder &/*val*/) {
value_to_string_visitor.query.bind_vars.emplace_back("unknown"); value_to_string_visitor.query.bind_vars.emplace_back(std::string("value_") + std::to_string(value_to_string_visitor.query.bind_vars.size() + 1));
value_to_string_visitor.result = value_to_string_visitor.writer->dialect().next_placeholder(value_to_string_visitor.query.bind_vars); value_to_string_visitor.result = value_to_string_visitor.writer->dialect().next_placeholder(value_to_string_visitor.query.bind_vars);
} }
@ -230,31 +235,26 @@ struct value_visitor {
}; };
std::string query_compiler::determine_value(value_visitor &visitor, const std::variant<utils::placeholder, utils::database_type> &val) { std::string query_compiler::determine_value(value_visitor &visitor, const std::variant<utils::placeholder, utils::database_type> &val) {
if (data_->mode == query_mode::Direct) { std::visit(visitor, val);
std::visit(visitor, val); return visitor.value_to_string_visitor.result;
return visitor.value_to_string_visitor.result;
}
query_.bind_vars.emplace_back(std::string("value_") + std::to_string(query_.bind_vars.size() + 1));
return dialect_->next_placeholder(query_.bind_vars);
} }
void query_compiler::visit(internal::query_values_part &values_part) { void query_compiler::visit(internal::query_values_part &part) {
query_.sql += " " + dialect_->token_at(sql::dialect_token::Values); query_.sql += " " + dialect_->token_at(sql::dialect_token::Values);
attribute_string_writer writer(*dialect_, connection_); attribute_string_writer writer(*dialect_, connection_);
value_visitor visitor(writer, query_); value_visitor visitor(writer, query_);
std::string result{"("}; std::string result{"("};
if (values_part.values().size() < 2) { if (part.values().size() < 2) {
for (const auto& val: values_part.values()) { for (const auto& val: part.values()) {
result.append(determine_value(visitor, val)); result.append(determine_value(visitor, val));
} }
} else { } else {
auto it = values_part.values().begin(); auto it = part.values().begin();
auto val = *it++; auto val = *it++;
result.append(determine_value(visitor, val)); result.append(determine_value(visitor, val));
for (; it != values_part.values().end(); ++it) { for (; it != part.values().end(); ++it) {
result.append(", "); result.append(", ");
val = *it; val = *it;
result.append(determine_value(visitor, val)); result.append(determine_value(visitor, val));
@ -265,11 +265,11 @@ void query_compiler::visit(internal::query_values_part &values_part) {
query_.sql += " " + result; query_.sql += " " + result;
} }
void query_compiler::visit(internal::query_update_part &update_part) void query_compiler::visit(internal::query_update_part &part)
{ {
query_.command = sql::sql_command::SQL_UPDATE; query_.command = sql::sql_command::SQL_UPDATE;
query_.table = update_part.table(); query_.table = part.table();
query_.sql += query_compiler::build_table_name(update_part.token(), *dialect_, query_.table); query_.sql += query_compiler::build_table_name(part.token(), *dialect_, query_.table);
} }
void query_compiler::visit(internal::query_delete_part &/*delete_part*/) void query_compiler::visit(internal::query_delete_part &/*delete_part*/)
@ -278,10 +278,10 @@ void query_compiler::visit(internal::query_delete_part &/*delete_part*/)
query_.sql = dialect_->token_at(sql::dialect_token::Remove); query_.sql = dialect_->token_at(sql::dialect_token::Remove);
} }
void query_compiler::visit(internal::query_delete_from_part &delete_from_part) void query_compiler::visit(internal::query_delete_from_part &part)
{ {
query_.table = delete_from_part.table(); query_.table = part.table();
query_.sql += " " + build_table_name(delete_from_part.token(), *dialect_, query_.table); query_.sql += " " + build_table_name(part.token(), *dialect_, query_.table);
} }
void query_compiler::visit(internal::query_create_part &/*create_part*/) void query_compiler::visit(internal::query_create_part &/*create_part*/)
@ -303,30 +303,30 @@ struct column_context
std::string build_create_column(const object::attribute_definition &col, const sql::dialect &d, column_context &context); std::string build_create_column(const object::attribute_definition &col, const sql::dialect &d, column_context &context);
void query_compiler::visit(internal::query_create_table_part &create_table_part) void query_compiler::visit(internal::query_create_table_part &part)
{ {
query_.sql += " " + dialect_->token_at(sql::dialect_token::Table) + " " + dialect_->prepare_identifier_string(create_table_part.table().name) + " "; query_.sql += " " + dialect_->token_at(sql::dialect_token::Table) + " " + dialect_->prepare_identifier_string(part.table().name) + " ";
query_.table = create_table_part.table(); query_.table = part.table();
std::string result = "("; std::string result = "(";
column_context context; column_context context;
if (create_table_part.columns().size() < 2) { if (part.columns().size() < 2) {
for (const auto &col: create_table_part.columns()) { for (const auto &col: part.columns()) {
result.append(build_create_column(col, *dialect_, context)); result.append(build_create_column(col, *dialect_, context));
} }
} else { } else {
auto it = create_table_part.columns().begin(); auto it = part.columns().begin();
result.append(build_create_column(*it++, *dialect_, context)); result.append(build_create_column(*it++, *dialect_, context));
for (; it != create_table_part.columns().end(); ++it) { for (; it != part.columns().end(); ++it) {
result.append(", "); result.append(", ");
result.append(build_create_column(*it, *dialect_, context)); result.append(build_create_column(*it, *dialect_, context));
} }
} }
if (!context.primary_keys.empty()) { if (!context.primary_keys.empty()) {
result.append(", CONSTRAINT PK_" + create_table_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);
@ -342,52 +342,50 @@ void query_compiler::visit(internal::query_create_table_part &create_table_part)
query_.sql += result; query_.sql += result;
} }
void query_compiler::visit(internal::query_drop_part &/*drop_part*/) void query_compiler::visit( internal::query_create_schema_part& part ) {
{ query_.sql += " " + dialect_->token_at(sql::dialect_token::Create) + " " +
dialect_->token_at(sql::dialect_token::Schema) + " " + dialect_->prepare_identifier_string(part.schema());
}
void query_compiler::visit(internal::query_drop_part &part) {
query_.command = sql::sql_command::SQL_DROP_TABLE; query_.command = sql::sql_command::SQL_DROP_TABLE;
query_.sql = dialect_->token_at(sql::dialect_token::Drop); query_.sql = dialect_->token_at(part.token());
} }
std::string query_compiler::determine_set_value(internal::basic_type_to_string_visitor &visitor, const utils::database_type &val) { void query_compiler::visit( internal::query_drop_schema_part& part ) {
if (data_->mode == query_mode::Direct) { query_.sql += " " + dialect_->token_at(sql::dialect_token::Drop) + " " +
std::visit(visitor, val); dialect_->token_at(sql::dialect_token::Schema) + " " + dialect_->prepare_identifier_string(part.schema());
return visitor.result;
}
query_.bind_vars.emplace_back(std::string("value_") + std::to_string(query_.bind_vars.size() + 1));
return dialect_->next_placeholder(query_.bind_vars);
} }
void query_compiler::visit(internal::query_set_part &set_part) void query_compiler::visit(internal::query_set_part &part) {
{
query_.sql += " " + dialect_->token_at(sql::dialect_token::Set) + " "; query_.sql += " " + dialect_->token_at(sql::dialect_token::Set) + " ";
attribute_string_writer writer(*dialect_, connection_); attribute_string_writer writer(*dialect_, connection_);
internal::basic_type_to_string_visitor visitor(writer, query_);
std::string result; std::string result;
if (set_part.key_values().size() < 2) {
for (const auto &col: set_part.key_values()) { value_visitor visitor(writer, query_); if (part.key_values().size() < 2) {
for (const auto &col: part.key_values()) {
result.append(dialect_->prepare_identifier_string(col.name()) + "="); result.append(dialect_->prepare_identifier_string(col.name()) + "=");
result.append(determine_set_value(visitor, col.value())); result.append(determine_value(visitor, col.value()));
} }
} else { } else {
auto it = set_part.key_values().begin(); auto it = part.key_values().begin();
result.append(dialect_->prepare_identifier_string(it->name()) + "="); result.append(dialect_->prepare_identifier_string(it->name()) + "=");
result.append(determine_set_value(visitor, (it++)->value())); result.append(determine_value(visitor, (it++)->value()));
for (; it != set_part.key_values().end(); ++it) { for (; it != part.key_values().end(); ++it) {
result.append(", "); result.append(", ");
result.append(dialect_->prepare_identifier_string(it->name()) + "="); result.append(dialect_->prepare_identifier_string(it->name()) + "=");
result.append(determine_set_value(visitor, it->value())); result.append(determine_value(visitor, it->value()));
} }
} }
query_.sql += result; query_.sql += result;
} }
void query_compiler::visit(internal::query_drop_table_part &drop_table_part) void query_compiler::visit(internal::query_drop_table_part &part)
{ {
query_.table = drop_table_part.table(); query_.table = part.table();
query_.sql += " " + query_compiler::build_table_name(drop_table_part.token(), *dialect_, query_.table); query_.sql += " " + query_compiler::build_table_name(part.token(), *dialect_, query_.table);
} }
std::string build_create_column(const object::attribute_definition &col, const sql::dialect &d, column_context &context) std::string build_create_column(const object::attribute_definition &col, const sql::dialect &d, column_context &context)

View File

@ -66,6 +66,14 @@ TEST_CASE_METHOD(QueryFixture, "Test drop table sql statement string", "[query]"
REQUIRE(result == R"(DROP TABLE "person")"); REQUIRE(result == R"(DROP TABLE "person")");
} }
TEST_CASE_METHOD(QueryFixture, "Test select all columns with asterisk", "[query][select][asterisk]") {
const auto result = query::select()
.from("person")
.str(*db);
REQUIRE(result == R"(SELECT * FROM "person")");
}
TEST_CASE_METHOD(QueryFixture, "Test select sql statement string", "[query]") { TEST_CASE_METHOD(QueryFixture, "Test select sql statement string", "[query]") {
const auto result = query::select({"id", "name", "age"}) const auto result = query::select({"id", "name", "age"})
.from("person") .from("person")

View File

@ -172,11 +172,11 @@ TEST_CASE("Test LRU cache evicts oldest entries", "[statement][cache][evict]") {
result = cache.acquire({"SELECT title FROM book"}); result = cache.acquire({"SELECT title FROM book"});
REQUIRE(result); REQUIRE(result);
auto stmt2 = result.value(); auto stmt2 = result.value();
result = cache.acquire({"SELECT name FROM author"}); // Should evict first statement result = cache.acquire({"SELECT name FROM author"}); // Should evict the first statement
REQUIRE(result); REQUIRE(result);
auto stmt3 = result.value(); auto stmt3 = result.value();
// Trigger re-prepare of evicted statement // Trigger re-prepares of an evicted statement
result = cache.acquire({"SELECT 1"}); result = cache.acquire({"SELECT 1"});
REQUIRE(result); REQUIRE(result);
auto stmt4 = result.value(); auto stmt4 = result.value();
@ -317,6 +317,7 @@ TEST_CASE("Race condition simulation with mixed access", "[statement_cache][race
}; };
std::vector<std::thread> jobs; std::vector<std::thread> jobs;
jobs.reserve(threads);
for (int i = 0; i < threads; ++i) { for (int i = 0; i < threads; ++i) {
jobs.emplace_back(task, i); jobs.emplace_back(task, i);
} }