Compare commits
No commits in common. "905ee019d7465d89fcd23bea62c95eac542b1c14" and "6423bd505b2249293d8979da73a20af2219b968c" have entirely different histories.
905ee019d7
...
6423bd505b
|
|
@ -37,9 +37,6 @@ set(TEST_SOURCES
|
|||
../../../test/backends/SequenceFixture.hpp
|
||||
../../../test/backends/SequenceFixture.cpp
|
||||
../../../test/backends/SequenceTest.cpp
|
||||
../../../test/backends/TableSequenceFixture.hpp
|
||||
../../../test/backends/TableSequenceFixture.cpp
|
||||
../../../test/backends/TableSequenceTest.cpp
|
||||
)
|
||||
|
||||
set(LIBRARY_TEST_TARGET PostgresTests)
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ struct LoginHistory : core::Model {
|
|||
template<typename Operator>
|
||||
void process( Operator& op ) {
|
||||
namespace field = matador::access;
|
||||
field::process_base<Model>( op, *this );
|
||||
field::process( op, *matador::base_class<Model>( this ) );
|
||||
field::belongs_to( op, "client", client, matador::utils::CascadeAllFetchLazy );
|
||||
field::belongs_to( op, "scenario", scenario, matador::utils::CascadeAllFetchLazy );
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
namespace matador::query {
|
||||
|
||||
class table;
|
||||
class column_expression;
|
||||
|
||||
// ReSharper disable CppNonExplicitConvertingConstructor
|
||||
class table_column {
|
||||
|
|
@ -36,7 +35,6 @@ public:
|
|||
|
||||
|
||||
table_column(const std::shared_ptr<abstract_column_expression>& expression) noexcept;
|
||||
table_column(column_expression&& expression) noexcept;
|
||||
table_column& operator=(const table_column& other);
|
||||
table_column(const table_column& other) = default;
|
||||
table_column(table_column&& other) noexcept = default;
|
||||
|
|
|
|||
|
|
@ -25,20 +25,6 @@ void process(Operator &op, const Type &object) {
|
|||
process(op, const_cast<Type &>(object));
|
||||
}
|
||||
|
||||
template<class Base, class Derived, class Operator>
|
||||
void process_base(Operator &op, const Derived &object) {
|
||||
static_assert(!std::is_same_v<Base, Derived>, "class Base must not be of same type as class Derived");
|
||||
static_assert(std::is_base_of_v<Base, Derived>, "class Base must be base of class Derived");
|
||||
process(op, static_cast<const Base&>(object));
|
||||
}
|
||||
|
||||
template<class Base, class Derived, class Operator>
|
||||
void process_base(Operator &op, Derived &object) {
|
||||
static_assert(!std::is_same_v<Base, Derived>, "class Base must not be of same type as class Derived");
|
||||
static_assert(std::is_base_of_v<Base, Derived>, "class Base must be base of class Derived");
|
||||
process(op, static_cast<Base&>(object));
|
||||
}
|
||||
|
||||
template< class Operator, class Type >
|
||||
void primary_key(Operator &op, const char *id, Type &value, const utils::primary_key_attribute &attr) {
|
||||
op.on_primary_key(id, value, attr);
|
||||
|
|
|
|||
|
|
@ -8,31 +8,33 @@ namespace matador {
|
|||
/**
|
||||
* @brief Safely casts a given derived class to its base class
|
||||
*
|
||||
* @tparam Base The base class type
|
||||
* @tparam Derived The class type of the derived class
|
||||
* @tparam B The base class type
|
||||
* @tparam D The class type of the derived class
|
||||
* @param derived The derived object
|
||||
* @return The cast object
|
||||
*/
|
||||
template < class Base, class Derived>
|
||||
const Base* base_class(const Derived *derived) {
|
||||
static_assert(!std::is_same_v<Base, Derived>, "class Base must not be of same type as class Derived");
|
||||
static_assert(std::is_base_of_v<Base, Derived>, "class Base must be base of class Derived");
|
||||
return static_cast<const Base*>(derived);
|
||||
template < class B, class D>
|
||||
const B* base_class(const D *derived)
|
||||
{
|
||||
static_assert(!std::is_same_v<B, D>, "class B must not be of same type as class D");
|
||||
static_assert(std::is_base_of_v<B, D>, "class B must be base of class D");
|
||||
return static_cast<const B*>(derived);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Safely casts a given derived class to its base class
|
||||
*
|
||||
* @tparam Base The base class type
|
||||
* @tparam Derived The class type of the derived class
|
||||
* @tparam B The base class type
|
||||
* @tparam D The class type of the derived class
|
||||
* @param derived The derived object
|
||||
* @return The cast object
|
||||
*/
|
||||
template < class Base, class Derived>
|
||||
Base* base_class(Derived *derived) {
|
||||
static_assert(!std::is_same_v<Base, Derived>, "class Base must not be of same type as class Derived");
|
||||
static_assert(std::is_base_of_v<Base, Derived>, "class Base must be base of class Derived");
|
||||
return static_cast<Base*>(derived);
|
||||
template < class B, class D>
|
||||
B* base_class(D *derived)
|
||||
{
|
||||
static_assert(!std::is_same_v<B, D>, "class B must not be of same type as class D");
|
||||
static_assert(std::is_base_of_v<B, D>, "class B must be base of class D");
|
||||
return static_cast<B*>(derived);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,105 +0,0 @@
|
|||
#ifndef MATADOR_PRIMARY_KEY_ACCESSOR_HPP
|
||||
#define MATADOR_PRIMARY_KEY_ACCESSOR_HPP
|
||||
|
||||
#include "matador/utils/field_attributes.hpp"
|
||||
#include "matador/utils/primary_key_attribute.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace matador::utils {
|
||||
class foreign_attributes;
|
||||
namespace detail {
|
||||
template < typename PrimaryKeyType >
|
||||
class primary_key_setter {
|
||||
public:
|
||||
explicit primary_key_setter(const std::string &name, const PrimaryKeyType& value)
|
||||
: name_(name)
|
||||
, value_(value){}
|
||||
|
||||
void on_primary_key(const char *id, PrimaryKeyType &pk, const utils::primary_key_attribute & = utils::default_pk_attributes) {
|
||||
if (id != nullptr && name_ == id) {
|
||||
pk = static_cast<PrimaryKeyType>(value_);
|
||||
}
|
||||
}
|
||||
template<typename ValueType>
|
||||
static void on_primary_key(const char * /*id*/, ValueType & /*pk*/, const utils::primary_key_attribute & = utils::default_pk_attributes) {}
|
||||
static void on_revision(const char * /*id*/, uint64_t & /*rev*/) {}
|
||||
template<typename T>
|
||||
static void on_attribute(const char * /*id*/, T &, const utils::field_attributes & = utils::null_attributes) {}
|
||||
template<class P>
|
||||
static void on_belongs_to(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||
template<class P>
|
||||
static void on_has_one(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||
template<class C>
|
||||
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const utils::foreign_attributes & ) {}
|
||||
template<class C>
|
||||
static void on_has_many_to_many(const char * /*id*/, C &, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes & ) {}
|
||||
template<class C>
|
||||
static void on_has_many_to_many(const char * /*id*/, C &, const utils::foreign_attributes & ) {}
|
||||
|
||||
private:
|
||||
const std::string &name_;
|
||||
PrimaryKeyType value_{};
|
||||
};
|
||||
|
||||
struct pk_unset_checker {
|
||||
const std::string &name;
|
||||
bool unset{true};
|
||||
|
||||
template<class V>
|
||||
void on_primary_key(const char *id, V &pk, const utils::primary_key_attribute & = utils::default_pk_attributes) {
|
||||
if (id != nullptr && name == id) {
|
||||
// Your convention: 0 means unset for integer PKs
|
||||
unset = (static_cast<std::uint64_t>(pk) == 0ULL);
|
||||
}
|
||||
}
|
||||
static void on_revision(const char * /*id*/, uint64_t & /*rev*/) {}
|
||||
template<typename T>
|
||||
static void on_attribute(const char * /*id*/, T &, const utils::field_attributes & = utils::null_attributes) {}
|
||||
template<class P>
|
||||
static void on_belongs_to(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||
template<class P>
|
||||
static void on_has_one(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||
template<class C>
|
||||
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const utils::foreign_attributes & ) {}
|
||||
template<class C>
|
||||
static void on_has_many_to_many(const char * /*id*/, C &, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes & ) {}
|
||||
template<class C>
|
||||
static void on_has_many_to_many(const char * /*id*/, C &, const utils::foreign_attributes & ) {}
|
||||
};
|
||||
|
||||
struct pk_value_extractor {
|
||||
std::uint64_t value{0};
|
||||
|
||||
template<class V>
|
||||
void on_primary_key(const char * /*id*/, V &pk, const utils::primary_key_attribute & = utils::default_pk_attributes) {
|
||||
value = static_cast<std::uint64_t>(pk);
|
||||
}
|
||||
static void on_revision(const char * /*id*/, uint64_t & /*rev*/) {}
|
||||
template<typename T>
|
||||
static void on_attribute(const char * /*id*/, T &, const utils::field_attributes & = utils::null_attributes) {}
|
||||
template<class P>
|
||||
static void on_belongs_to(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||
template<class P>
|
||||
static void on_has_one(const char * /*id*/, P &, const utils::foreign_attributes & ) {}
|
||||
template<class C>
|
||||
static void on_has_many(const char * /*id*/, C &, const char * /*join_column*/, const utils::foreign_attributes & ) {}
|
||||
template<class C>
|
||||
static void on_has_many_to_many(const char * /*id*/, C &, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes & ) {}
|
||||
template<class C>
|
||||
static void on_has_many_to_many(const char * /*id*/, C &, const utils::foreign_attributes & ) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename PrimaryKeyType>
|
||||
class primary_key_accessor {
|
||||
public:
|
||||
|
||||
PrimaryKeyType get() const;
|
||||
PrimaryKeyType
|
||||
};
|
||||
}
|
||||
|
||||
#endif //MATADOR_PRIMARY_KEY_ACCESSOR_HPP
|
||||
|
|
@ -124,7 +124,6 @@ add_library(matador-core STATIC
|
|||
object/collection_utils.cpp
|
||||
../../include/matador/object/pk_field_locator.hpp
|
||||
../../include/matador/object/object_cache.hpp
|
||||
../../include/matador/utils/primary_key_accessor.hpp
|
||||
)
|
||||
|
||||
target_link_libraries(matador-core ${CMAKE_DL_LIBS})
|
||||
|
|
|
|||
|
|
@ -17,15 +17,16 @@
|
|||
#include "matador/sql/dialect.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
sql::query_context query_builder::compile(const query_data& data,
|
||||
const sql::dialect& d,
|
||||
const std::optional<std::reference_wrapper<const sql::connection_impl>>
|
||||
conn) {
|
||||
|
||||
sql::query_context query_builder::compile(const query_data &data,
|
||||
const sql::dialect &d,
|
||||
const std::optional<std::reference_wrapper<const sql::connection_impl>> conn)
|
||||
{
|
||||
data_ = &data;
|
||||
dialect_ = &d;
|
||||
connection_ = conn;
|
||||
query_ = {};
|
||||
for (const auto& part : data.parts) {
|
||||
for (const auto &part: data.parts) {
|
||||
part->accept(*this);
|
||||
}
|
||||
finisher_(query_);
|
||||
|
|
@ -36,10 +37,10 @@ sql::query_context query_builder::compile(const query_data& data,
|
|||
return {query_};
|
||||
}
|
||||
|
||||
void build_columns_with_name_only(std::string& out, const std::vector<table_column>& cols, const sql::dialect& d);
|
||||
void build_columns(std::string& out, const std::vector<table_column>& cols, const sql::dialect& d);
|
||||
void build_fetchable_columns(sql::query_context& ctx, const std::vector<table_column>& cols, const sql::dialect& d);
|
||||
void prepare_prototype(std::vector<object::attribute>& prototype, const table_column& col);
|
||||
void build_columns_with_name_only(std::string &out, const std::vector<table_column> &cols, const sql::dialect &d);
|
||||
void build_columns(std::string &out, const std::vector<table_column> &cols, const sql::dialect &d);
|
||||
void build_fetchable_columns(sql::query_context &ctx, const std::vector<table_column> &cols, const sql::dialect &d);
|
||||
void prepare_prototype(std::vector<object::attribute> &prototype, const table_column &col);
|
||||
|
||||
void query_builder::visit(internal::query_alter_part& part) {
|
||||
query_.sql = dialect_->token_at(part.token());
|
||||
|
|
@ -48,7 +49,7 @@ void query_builder::visit(internal::query_alter_part& part) {
|
|||
void query_builder::visit(internal::query_alter_table_part& part) {
|
||||
query_.command = sql::sql_command::AlterTable;
|
||||
query_.sql += " " + dialect_->token_at(part.token()) + " " +
|
||||
dialect_->prepare_identifier_string(part.table().name());
|
||||
dialect_->prepare_identifier_string(part.table().name());
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_add_key_constraint_part& part) {
|
||||
|
|
@ -73,7 +74,7 @@ void query_builder::visit(internal::query_add_foreign_key_reference_part& part)
|
|||
query_.sql += ")";
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_add_constraint_part_by_constraint& part) {
|
||||
void query_builder::visit(internal::query_add_constraint_part_by_constraint &part) {
|
||||
query_.sql += build_add_constraint_string(part.constraint());
|
||||
}
|
||||
|
||||
|
|
@ -85,7 +86,7 @@ void query_builder::visit(internal::query_drop_key_constraint_part_by_constraint
|
|||
query_.sql += " " + build_drop_constraint_string(part.constraint());
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_select_part& part) {
|
||||
void query_builder::visit(internal::query_select_part &part) {
|
||||
query_.command = sql::sql_command::Select;
|
||||
query_.sql = dialect_->select() + " ";
|
||||
|
||||
|
|
@ -108,11 +109,11 @@ void query_builder::visit(internal::query_select_currval_part& part) {
|
|||
prepare_prototype(query_.prototype, part.sequence_name());
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_from_part& part) {
|
||||
void query_builder::visit(internal::query_from_part &part) {
|
||||
query_.table_name = part.tables().front().name();
|
||||
query_.sql += " " + dialect_->from() + " ";
|
||||
if (const auto& tables = part.tables(); tables.size() < 2) {
|
||||
for (const auto& tab : tables) {
|
||||
if (const auto &tables = part.tables(); tables.size() < 2) {
|
||||
for (const auto &tab: tables) {
|
||||
query_.sql += build_table_name(*dialect_, tab);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -125,30 +126,30 @@ void query_builder::visit(internal::query_from_part& part) {
|
|||
}
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_join_table_part& part) {
|
||||
void query_builder::visit(internal::query_join_table_part &part) {
|
||||
query_.sql += " " + build_table_name(part.token(), *dialect_, part.table());
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_join_query_part& part) {
|
||||
void query_builder::visit(internal::query_join_query_part &part) {
|
||||
query_.sql += " " + dialect_->join() + " (" + part.query().str(*dialect_) + ")";
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_on_part& part) {
|
||||
void query_builder::visit(internal::query_on_part &part) {
|
||||
criteria_evaluator evaluator(*dialect_, query_);
|
||||
query_.sql += " " + dialect_->on() +
|
||||
" " + evaluator.evaluate(part.condition());
|
||||
" " + evaluator.evaluate(part.condition());
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_where_part& part) {
|
||||
void query_builder::visit(internal::query_where_part &part) {
|
||||
criteria_evaluator evaluator(*dialect_, query_);
|
||||
query_.sql += " " + dialect_->where() +
|
||||
" " + evaluator.evaluate(part.condition());
|
||||
" " + evaluator.evaluate(part.condition());
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_group_by_part& part) {
|
||||
void query_builder::visit(internal::query_group_by_part &part) {
|
||||
query_.sql += " " + dialect_->group_by() + " ";
|
||||
if (part.columns().size() < 2) {
|
||||
for (const auto& col : part.columns()) {
|
||||
for (const auto &col: part.columns()) {
|
||||
query_.sql.append(dialect_->prepare_identifier_string(col.name()));
|
||||
}
|
||||
} else {
|
||||
|
|
@ -161,10 +162,10 @@ void query_builder::visit(internal::query_group_by_part& part) {
|
|||
}
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_order_by_part& part) {
|
||||
void query_builder::visit(internal::query_order_by_part &part) {
|
||||
query_.sql += " " + dialect_->order_by() + " ";
|
||||
if (part.columns().size() < 2) {
|
||||
for (const auto& col : part.columns()) {
|
||||
for (const auto &col: part.columns()) {
|
||||
query_.sql.append(dialect_->prepare_identifier_string(col.canonical_name()));
|
||||
}
|
||||
} else {
|
||||
|
|
@ -177,72 +178,66 @@ void query_builder::visit(internal::query_order_by_part& part) {
|
|||
}
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_order_by_asc_part&/*order_by_asc_part*/) {
|
||||
void query_builder::visit(internal::query_order_by_asc_part &/*order_by_asc_part*/) {
|
||||
query_.sql += " " + dialect_->asc();
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_order_by_desc_part&/*order_by_desc_part*/) {
|
||||
void query_builder::visit(internal::query_order_by_desc_part &/*order_by_desc_part*/) {
|
||||
query_.sql += " " + dialect_->desc();
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_offset_part& part) {
|
||||
void query_builder::visit(internal::query_offset_part &part) {
|
||||
query_.sql += " " + dialect_->offset() + " " + std::to_string(part.offset());
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_limit_part& part) {
|
||||
void query_builder::visit(internal::query_limit_part &part) {
|
||||
query_.sql += " " + dialect_->limit() + " " + std::to_string(part.limit());
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_insert_part&/*insert_part*/) {
|
||||
void query_builder::visit(internal::query_insert_part &/*insert_part*/) {
|
||||
query_.command = sql::sql_command::Insert;
|
||||
query_.sql = dialect_->insert();
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_into_part& part) {
|
||||
void query_builder::visit(internal::query_into_part &part) {
|
||||
query_.table_name = part.table().name();
|
||||
query_.sql += " " + dialect_->into() +
|
||||
" " + dialect_->prepare_identifier_string(part.table().name()) + " (";
|
||||
" " + dialect_->prepare_identifier_string(part.table().name()) + " (";
|
||||
|
||||
build_columns_with_name_only(query_.sql, part.columns(), *dialect_);
|
||||
query_.sql += ")"/* + result*/;
|
||||
}
|
||||
|
||||
struct value_visitor
|
||||
{
|
||||
value_visitor(attribute_string_writer& w, sql::query_context& ctx)
|
||||
: value_to_string_visitor(w, ctx) {
|
||||
}
|
||||
struct value_visitor {
|
||||
value_visitor(attribute_string_writer &w, sql::query_context &ctx)
|
||||
: value_to_string_visitor(w, ctx) {}
|
||||
|
||||
void operator()(const utils::database_type& val) {
|
||||
void operator()(const utils::database_type &val) {
|
||||
std::visit(value_to_string_visitor, val);
|
||||
}
|
||||
|
||||
void operator()(const utils::placeholder&/*val*/) {
|
||||
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);
|
||||
}
|
||||
void operator()(const utils::placeholder &/*val*/) {
|
||||
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);
|
||||
}
|
||||
|
||||
internal::basic_type_to_string_visitor value_to_string_visitor;
|
||||
};
|
||||
|
||||
std::string query_builder::determine_value(const sql::dialect& d, sql::query_context& ctx,
|
||||
const abstract_column_expression& exp) {
|
||||
attribute_string_writer writer(d, {});
|
||||
expression_evaluator v(d, ctx);
|
||||
exp.accept(v);
|
||||
std::string query_builder::determine_value(const sql::dialect &d, sql::query_context& ctx, const abstract_column_expression &exp) {
|
||||
attribute_string_writer writer(d, {});
|
||||
expression_evaluator v(d, ctx);
|
||||
exp.accept(v);
|
||||
|
||||
return v.result();
|
||||
return v.result();
|
||||
}
|
||||
|
||||
std::string query_builder::determine_value(value_visitor& visitor,
|
||||
const std::variant<utils::placeholder, utils::database_type>& val) {
|
||||
std::visit(visitor, val);
|
||||
return visitor.value_to_string_visitor.result;
|
||||
std::string query_builder::determine_value(value_visitor &visitor, const std::variant<utils::placeholder, utils::database_type> &val) {
|
||||
std::visit(visitor, val);
|
||||
return visitor.value_to_string_visitor.result;
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_values_part& part) {
|
||||
void query_builder::visit(internal::query_values_part &part) {
|
||||
query_.sql += " " + dialect_->values();
|
||||
|
||||
attribute_string_writer writer(*dialect_, connection_);
|
||||
|
|
@ -250,13 +245,13 @@ void query_builder::visit(internal::query_values_part& part) {
|
|||
value_visitor visitor(writer, query_);
|
||||
std::string result{"("};
|
||||
if (part.values().size() < 2) {
|
||||
for (const auto& val : part.values()) {
|
||||
for (const auto& val: part.values()) {
|
||||
result.append(determine_value(visitor, val));
|
||||
}
|
||||
} else {
|
||||
auto it = part.values().begin();
|
||||
auto val = *it++;
|
||||
result.append(determine_value(visitor, val));
|
||||
result.append(determine_value(visitor, val));
|
||||
for (; it != part.values().end(); ++it) {
|
||||
result.append(", ");
|
||||
val = *it;
|
||||
|
|
@ -268,42 +263,45 @@ void query_builder::visit(internal::query_values_part& part) {
|
|||
query_.sql += " " + result;
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_returning_part& part) {
|
||||
void query_builder::visit(internal::query_returning_part &part) {
|
||||
query_.mode = sql::return_mode::Rows;
|
||||
query_.sql += " " + dialect_->returning() + " ";
|
||||
|
||||
build_fetchable_columns(query_, part.columns(), *dialect_);
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_update_part& part) {
|
||||
void query_builder::visit(internal::query_update_part &part) {
|
||||
query_.command = sql::sql_command::Update;
|
||||
query_.table_name = part.table().name();
|
||||
query_.sql += build_table_name(part.token(), *dialect_, query_.table_name);
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_delete_part&/*delete_part*/) {
|
||||
void query_builder::visit(internal::query_delete_part &/*delete_part*/) {
|
||||
query_.command = sql::sql_command::Delete;
|
||||
query_.sql = dialect_->remove();
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_delete_from_part& part) {
|
||||
void query_builder::visit(internal::query_delete_from_part &part)
|
||||
{
|
||||
query_.table_name = part.table().name();
|
||||
query_.sql += " " + build_table_name(part.token(), *dialect_, query_.table_name);
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_create_part&/*create_part*/) {
|
||||
void query_builder::visit(internal::query_create_part &/*create_part*/)
|
||||
{
|
||||
query_.command = sql::sql_command::CreateTable;
|
||||
query_.sql = dialect_->create();
|
||||
}
|
||||
|
||||
void build_create_column(std::string& out, const table_column& col, const sql::dialect& d);
|
||||
std::string build_constraint(const table_constraint& cons, const sql::dialect& d);
|
||||
void build_create_column(std::string &out, const table_column &col, const sql::dialect &d);
|
||||
std::string build_constraint(const table_constraint &cons, const sql::dialect &d);
|
||||
|
||||
void query_builder::visit(internal::query_create_table_part& part) {
|
||||
void query_builder::visit(internal::query_create_table_part &part)
|
||||
{
|
||||
query_.sql += " " + dialect_->table() + " " + dialect_->prepare_identifier_string(part.table().name()) + " (";
|
||||
query_.table_name = part.table().name();
|
||||
|
||||
finisher_ = [](sql::query_context& ctx) { ctx.sql += ")"; };
|
||||
finisher_ = [](sql::query_context &ctx) { ctx.sql += ")"; };
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_create_table_columns_part& part) {
|
||||
|
|
@ -331,22 +329,22 @@ void query_builder::visit(internal::query_create_sequence_part& part) {
|
|||
query_.sql += " " + dialect_->sequence() + " " + dialect_->prepare_identifier_string(part.sequence_name());
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_create_schema_part& part) {
|
||||
void query_builder::visit( internal::query_create_schema_part& part ) {
|
||||
query_.command = sql::sql_command::CreateSchema;
|
||||
query_.sql += " " + dialect_->schema() + " " + dialect_->prepare_identifier_string(part.schema());
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_drop_part& part) {
|
||||
void query_builder::visit(internal::query_drop_part &part) {
|
||||
query_.command = sql::sql_command::DropTable;
|
||||
query_.sql = dialect_->token_at(part.token());
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_drop_schema_part& part) {
|
||||
void query_builder::visit( internal::query_drop_schema_part& part ) {
|
||||
query_.sql += " " + dialect_->drop() + " " +
|
||||
dialect_->schema() + " " + dialect_->prepare_identifier_string(part.schema());
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_set_part& part) {
|
||||
void query_builder::visit(internal::query_set_part &part) {
|
||||
query_.sql += " " + dialect_->set() + " ";
|
||||
|
||||
attribute_string_writer writer(*dialect_, connection_);
|
||||
|
|
@ -356,10 +354,10 @@ void query_builder::visit(internal::query_set_part& part) {
|
|||
bool first = true;
|
||||
for (const auto& column_value : part.column_values()) {
|
||||
if (!first) {
|
||||
query_.sql.append(", ");
|
||||
query_.sql.append(", ");
|
||||
}
|
||||
query_.sql.append(dialect_->prepare_identifier_string(column_value.col().name()) + "=");
|
||||
query_.sql.append(determine_value(*dialect_, query_, column_value.expression()));
|
||||
query_.sql.append(determine_value(*dialect_,query_, column_value.expression()));
|
||||
first = false;
|
||||
}
|
||||
|
||||
|
|
@ -387,12 +385,12 @@ void query_builder::visit(internal::query_drop_sequence_part& part) {
|
|||
query_.sql += " " + dialect_->sequence() + " " + dialect_->prepare_identifier_string(part.sequence_name());
|
||||
}
|
||||
|
||||
void query_builder::visit(internal::query_drop_table_part& part) {
|
||||
void query_builder::visit(internal::query_drop_table_part &part) {
|
||||
query_.table_name = part.table().name();
|
||||
query_.sql += " " + build_table_name(part.token(), *dialect_, query_.table_name);
|
||||
}
|
||||
|
||||
void build_create_column(std::string& out, const table_column& col, const sql::dialect& d) {
|
||||
void build_create_column(std::string &out, const table_column &col, const sql::dialect &d) {
|
||||
prepare_identifier_string_append(out, col.canonical_name(), d);
|
||||
out += " " + d.data_type_at(col.type());
|
||||
if (col.attributes().size() > 0) {
|
||||
|
|
@ -412,7 +410,7 @@ void build_create_column(std::string& out, const table_column& col, const sql::d
|
|||
}
|
||||
}
|
||||
|
||||
void build_columns_with_name_only(std::string& out, const std::vector<table_column>& cols, const sql::dialect& d) {
|
||||
void build_columns_with_name_only(std::string &out, const std::vector<table_column> &cols, const sql::dialect &d) {
|
||||
bool first = true;
|
||||
for (const auto& col : cols) {
|
||||
if (!first) {
|
||||
|
|
@ -423,7 +421,7 @@ void build_columns_with_name_only(std::string& out, const std::vector<table_colu
|
|||
}
|
||||
}
|
||||
|
||||
void build_columns(std::string& out, const std::vector<table_column>& cols, const sql::dialect& d) {
|
||||
void build_columns(std::string &out, const std::vector<table_column> &cols, const sql::dialect &d) {
|
||||
bool first = true;
|
||||
for (const auto& col : cols) {
|
||||
if (!first) {
|
||||
|
|
@ -434,7 +432,7 @@ void build_columns(std::string& out, const std::vector<table_column>& cols, cons
|
|||
}
|
||||
}
|
||||
|
||||
void build_fetchable_columns(sql::query_context& ctx, const std::vector<table_column>& cols, const sql::dialect& d) {
|
||||
void build_fetchable_columns(sql::query_context &ctx, const std::vector<table_column> &cols, const sql::dialect &d) {
|
||||
bool first = true;
|
||||
for (const auto& col : cols) {
|
||||
if (!first) {
|
||||
|
|
@ -446,7 +444,7 @@ void build_fetchable_columns(sql::query_context& ctx, const std::vector<table_co
|
|||
}
|
||||
}
|
||||
|
||||
void prepare_prototype(std::vector<object::attribute>& prototype, const table_column& col) {
|
||||
void prepare_prototype(std::vector<object::attribute> &prototype, const table_column &col) {
|
||||
if (col.is_function()) {
|
||||
prototype.emplace_back(col.has_alias() ? col.alias() : col.canonical_name());
|
||||
prototype.back().change_type(utils::basic_type::Int32);
|
||||
|
|
@ -456,62 +454,60 @@ void prepare_prototype(std::vector<object::attribute>& prototype, const table_co
|
|||
}
|
||||
|
||||
std::string build_constraint(const table_constraint& cons, const sql::dialect& d) {
|
||||
std::string result;
|
||||
if (!cons.name().empty()) {
|
||||
result.append(d.constraint()).append(" ").append(cons.name()).append(" ");
|
||||
}
|
||||
if (cons.is_primary_key_constraint()) {
|
||||
result
|
||||
.append(d.primary_key())
|
||||
.append(" (")
|
||||
.append(cons.column_name())
|
||||
.append(")");
|
||||
} else if (cons.is_foreign_key_constraint()) {
|
||||
result
|
||||
.append(d.foreign_key())
|
||||
.append(" (")
|
||||
.append(cons.column_name())
|
||||
.append(") ")
|
||||
.append(d.references()).append(" ")
|
||||
.append(cons.referenced_table())
|
||||
.append(" (")
|
||||
.append(cons.referenced_column())
|
||||
.append(")");
|
||||
} else {
|
||||
// handle error
|
||||
}
|
||||
return result;
|
||||
std::string result;
|
||||
if (!cons.name().empty()) {
|
||||
result.append(d.constraint()).append(" ").append(cons.name()).append(" ");
|
||||
}
|
||||
if (cons.is_primary_key_constraint()) {
|
||||
result
|
||||
.append(d.primary_key())
|
||||
.append(" (")
|
||||
.append(cons.column_name())
|
||||
.append(")");
|
||||
} else if (cons.is_foreign_key_constraint()) {
|
||||
result
|
||||
.append(d.foreign_key())
|
||||
.append(" (")
|
||||
.append(cons.column_name())
|
||||
.append(") ")
|
||||
.append(d.references()).append(" ")
|
||||
.append(cons.referenced_table())
|
||||
.append(" (")
|
||||
.append(cons.referenced_column())
|
||||
.append(")");
|
||||
} else {
|
||||
// handle error
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string query_builder::build_table_name(const sql::dialect_token token, const sql::dialect& d, const table& t) {
|
||||
std::string query_builder::build_table_name(const sql::dialect_token token, const sql::dialect &d, const table& t) {
|
||||
return d.token_at(token) + " " + build_table_name(d, t);
|
||||
}
|
||||
|
||||
std::string query_builder::build_table_name(const sql::dialect& d, const table& t) {
|
||||
std::string query_builder::build_table_name(const sql::dialect &d, const table& t) {
|
||||
return (!d.default_schema_name().empty() ? d.prepare_identifier_string(d.default_schema_name()) + "." : "") +
|
||||
d.prepare_identifier_string(t.table_name()) +
|
||||
(!t.has_alias() ? "" : " " + d.prepare_identifier_string(t.name()));
|
||||
}
|
||||
|
||||
std::string query_builder::build_add_constraint_string(const table_constraint& c) const {
|
||||
std::string query_builder::build_add_constraint_string(const table_constraint &c) const {
|
||||
std::string result = " " + dialect_->add_constraint() + " " + build_constraint_name(c) + " ";
|
||||
if (c.is_primary_key_constraint()) {
|
||||
result.append(dialect_->primary_key()).append(" (").append(c.column_name()).append(")");
|
||||
} else if (c.is_foreign_key_constraint()) {
|
||||
result.append(dialect_->foreign_key()).append(" (").append(c.column_name()).append(") ").
|
||||
append(dialect_->references()).append(" ").append(c.referenced_table()).append(" (").append(
|
||||
c.referenced_column()).append(")");
|
||||
result.append(dialect_->foreign_key()).append(" (").append(c.column_name()).append(") ").append(dialect_->references()).append(" ").append(c.referenced_table()).append(" (").append(c.referenced_column()).append(")");
|
||||
} else if (c.is_unique_constraint()) {
|
||||
result.append(dialect_->unique()).append(" (").append(c.column_name()).append(")");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string query_builder::build_drop_constraint_string(const table_constraint& c) const {
|
||||
std::string query_builder::build_drop_constraint_string(const table_constraint &c) const {
|
||||
return dialect_->drop_constraint() + " " + build_constraint_name(c);
|
||||
}
|
||||
|
||||
std::string query_builder::build_constraint_name(const table_constraint& c) {
|
||||
std::string query_builder::build_constraint_name(const table_constraint &c) {
|
||||
if (c.is_primary_key_constraint()) {
|
||||
return "PK_" + c.table_name();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ void prepare_column(sql::query_context& ctx, const sql::dialect& d, const table_
|
|||
attribute_string_writer writer(d, {});
|
||||
expression_evaluator v(d, ctx);
|
||||
col.expression()->accept(v);
|
||||
ctx.sql += v.result();
|
||||
|
||||
if (col.has_alias()) {
|
||||
ctx.sql.append(" ").append(d.as()).append(" ").append(col.alias());
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@
|
|||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
#include "matador/query/expression/column_expression.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
|
||||
table_column operator ""_col(const char *name, const size_t len) {
|
||||
|
|
@ -69,10 +67,6 @@ table_column::table_column(const class table* tab,
|
|||
table_column::table_column(const std::shared_ptr<abstract_column_expression>& expression) noexcept
|
||||
: table_column(nullptr, "", "", utils::basic_type::Unknown, {}, sql::sql_function_t::None, expression) {}
|
||||
|
||||
table_column::table_column(column_expression&& expression) noexcept
|
||||
: table_column(std::shared_ptr(expression.release())) {
|
||||
}
|
||||
|
||||
table_column & table_column::operator=(const table_column &other) {
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
|
|
@ -101,7 +95,7 @@ bool table_column::equals(const table_column &x) const {
|
|||
}
|
||||
|
||||
table_column table_column::as(const std::string& alias) const {
|
||||
return {table_, column_name_, alias, type_, attributes_, function_, expression_};
|
||||
return {table_, column_name_, alias, type_, attributes_, function_};
|
||||
}
|
||||
|
||||
const std::string& table_column::name() const {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef MATADOR_SEQUENCE_FIXTURE_HPP
|
||||
#define MATADOR_SEQUENCE_FIXTURE_HPP
|
||||
|
||||
#include "matador/query/schema.hpp"
|
||||
|
||||
#include "matador/sql/connection.hpp"
|
||||
|
||||
#include <stack>
|
||||
|
|
@ -8,18 +10,18 @@
|
|||
namespace matador::test {
|
||||
class SequenceFixture {
|
||||
public:
|
||||
SequenceFixture();
|
||||
~SequenceFixture();
|
||||
SequenceFixture();
|
||||
~SequenceFixture();
|
||||
|
||||
void check_sequence_exists(const std::string &sequence_name) const;
|
||||
void check_sequence_not_exists(const std::string &sequence_name) const;
|
||||
void check_sequence_exists(const std::string &sequence_name) const;
|
||||
void check_sequence_not_exists(const std::string &sequence_name) const;
|
||||
|
||||
protected:
|
||||
sql::connection db;
|
||||
std::stack <std::string> sequences_to_drop;
|
||||
sql::connection db;
|
||||
std::stack <std::string> sequences_to_drop;
|
||||
|
||||
private:
|
||||
void drop_sequence_if_exists(const std::string &sequence_name) const;
|
||||
void drop_sequence_if_exists(const std::string &sequence_name) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
#include "TableSequenceFixture.hpp"
|
||||
|
||||
#include "matador/query/query.hpp"
|
||||
#include "matador/query/builder.hpp"
|
||||
|
||||
#include "connection.hpp"
|
||||
|
||||
#include "catch2/catch_test_macros.hpp"
|
||||
|
||||
namespace matador::test {
|
||||
TableSequenceFixture::TableSequenceFixture()
|
||||
: db(connection::dns) {
|
||||
REQUIRE(db.open());
|
||||
|
||||
REQUIRE(query::query::create()
|
||||
.table(sequence_table_name)
|
||||
.columns({
|
||||
query::column("name", utils::basic_type::Varchar, 255),
|
||||
query::column("next_id", utils::basic_type::Int64)
|
||||
})
|
||||
.execute(db));
|
||||
}
|
||||
|
||||
TableSequenceFixture::~TableSequenceFixture() {
|
||||
REQUIRE(query::query::drop()
|
||||
.table(sequence_table_name)
|
||||
.execute(db));
|
||||
REQUIRE(db.close());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
#ifndef MATADOR_TABLE_SEQUENCE_FIXTURE_HPP
|
||||
#define MATADOR_TABLE_SEQUENCE_FIXTURE_HPP
|
||||
|
||||
#include "matador/sql/connection.hpp"
|
||||
|
||||
namespace matador::test {
|
||||
class TableSequenceFixture {
|
||||
public:
|
||||
TableSequenceFixture();
|
||||
~TableSequenceFixture();
|
||||
|
||||
protected:
|
||||
sql::connection db;
|
||||
std::string sequence_table_name{"test_seq_table"};
|
||||
};
|
||||
}
|
||||
|
||||
#endif //MATADOR_TABLE_SEQUENCE_FIXTURE_HPP
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
#include "catch2/catch_test_macros.hpp"
|
||||
|
||||
#include "matador/query/criteria.hpp"
|
||||
#include "matador/query/expression/expression_operators.hpp"
|
||||
#include "matador/query/query.hpp"
|
||||
#include "matador/query/table_column.hpp"
|
||||
|
||||
#include "TableSequenceFixture.hpp"
|
||||
|
||||
using namespace matador::query;
|
||||
using namespace matador::test;
|
||||
|
||||
TEST_CASE_METHOD(TableSequenceFixture, "test create and drop table sequence", "[table_sequence][create][drop]") {
|
||||
const auto next_id_col = "next_id"_col;
|
||||
auto result = query::query::insert()
|
||||
.into(sequence_table_name, { "name", next_id_col})
|
||||
.values({ "test_seq", 1 })
|
||||
.execute(db);
|
||||
REQUIRE(result);
|
||||
REQUIRE(result->affected_rows == 1);
|
||||
|
||||
table_column exp(next_id_col - 1);
|
||||
auto id_result = query::query::update(sequence_table_name)
|
||||
.set(next_id_col, next_id_col + 1)
|
||||
.where("name"_col == "test_seq")
|
||||
.returning((next_id_col - 1).as("id"))
|
||||
.fetch_value<int64_t>(db);
|
||||
|
||||
REQUIRE(id_result);
|
||||
REQUIRE(id_result->has_value());
|
||||
REQUIRE(id_result->value() == 1);
|
||||
|
||||
id_result = query::query::select({next_id_col})
|
||||
.from(sequence_table_name)
|
||||
.where("name"_col == "test_seq")
|
||||
.fetch_value<int64_t>(db);
|
||||
REQUIRE(id_result);
|
||||
REQUIRE(id_result->has_value());
|
||||
REQUIRE(id_result->value() == 2);
|
||||
}
|
||||
Loading…
Reference in New Issue