added timestamp code, support columns for group by and order by and tested load has-many eager code
This commit is contained in:
parent
0bf945cd13
commit
930b9d1aa4
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "matador/utils/convert.hpp"
|
||||
#include "matador/utils/value.hpp"
|
||||
#include "matador/utils/string.hpp"
|
||||
|
||||
namespace matador::backends::postgres {
|
||||
postgres_result_reader::postgres_result_reader(PGresult *result)
|
||||
|
|
@ -104,18 +105,25 @@ void postgres_result_reader::read_value(const char * /*id*/, const size_t index,
|
|||
|
||||
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, utils::date_type_t &value) {
|
||||
if (const auto val = column(index); strlen(val) > 0) {
|
||||
// value = time::parse(val, "%Y-%m-%d %T.%f");
|
||||
if (const auto res = utils::to<utils::date_type_t>(std::string(val)); res.is_ok()) {
|
||||
value = res.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, utils::time_type_t &value) {
|
||||
if (const auto val = column(index); strlen(val) > 0) {
|
||||
// value.set(val, matador::utils::date_format::ISO8601);
|
||||
if (const auto res = utils::to<utils::time_type_t>(std::string(val)); res.is_ok()) {
|
||||
value = res.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void postgres_result_reader::read_value(const char * /*id*/, size_t index, utils::timestamp_type_t &value) {
|
||||
void postgres_result_reader::read_value(const char * /*id*/, const size_t index, utils::timestamp_type_t &value) {
|
||||
if (const auto val = column(index); strlen(val) > 0) {
|
||||
if (const auto res = utils::to<utils::timestamp_type_t>(std::string(val)); res.is_ok()) {
|
||||
value = res.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ set(TEST_SOURCES
|
|||
../../../test/backends/StatementCacheTest.cpp
|
||||
../../../test/backends/StatementTest.cpp
|
||||
../../../test/backends/TypeTraitsTest.cpp
|
||||
../../../test/utils/record_printer.hpp
|
||||
../../../test/utils/record_printer.cpp
|
||||
)
|
||||
|
||||
set(LIBRARY_TEST_TARGET PostgresTests)
|
||||
|
|
|
|||
143
demo/main.cpp
143
demo/main.cpp
|
|
@ -1,9 +1,11 @@
|
|||
#include "matador/sql/connection.hpp"
|
||||
#include "matador/sql/connection_pool.hpp"
|
||||
|
||||
#include "matador/query/criteria.hpp"
|
||||
#include "matador/query/query.hpp"
|
||||
#include "matador/query/table_column.hpp"
|
||||
#include "matador/query/meta_table_macro.hpp"
|
||||
#include "matador/query/schema.hpp"
|
||||
|
||||
#include "matador/object/object_ptr.hpp"
|
||||
#include "matador/object/repository.hpp"
|
||||
|
|
@ -45,7 +47,7 @@ struct book {
|
|||
namespace field = matador::access;
|
||||
field::primary_key(op, "id", id);
|
||||
field::attribute(op, "title", title, 511);
|
||||
field::has_one( op, "author_id", book_author, matador::utils::CascadeNoneFetchLazy );
|
||||
field::belongs_to(op, "author_id", book_author, matador::utils::CascadeNoneFetchLazy);
|
||||
field::attribute(op, "published_in", published_in);
|
||||
}
|
||||
};
|
||||
|
|
@ -151,62 +153,67 @@ META_TABLE(payload, PAYLOAD, id )
|
|||
META_TABLE(temporary_table, TEMPORARY_TABLE, id);
|
||||
|
||||
META_TABLE(customer, CUSTOMER, id, name, email, address)
|
||||
|
||||
META_TABLE(product, PRODUCT, id, title, description, price, category)
|
||||
|
||||
META_TABLE(category, CATEGORY, id, title, description)
|
||||
|
||||
META_TABLE(cart, CART, id, items, owner)
|
||||
|
||||
int main() {
|
||||
using namespace matador::sql;
|
||||
using namespace matador::object;
|
||||
using namespace matador::utils;
|
||||
using namespace matador::query;
|
||||
using namespace matador::query::meta;
|
||||
|
||||
const std::string env_var{"MATADOR_BACKENDS_PATH"};
|
||||
|
||||
std::string dns{"sqlite://demo.db"};
|
||||
repository s( "main" );
|
||||
connection_pool pool("postgres://test:test123!@127.0.0.1:5432/matador", 4);
|
||||
|
||||
schema s("");
|
||||
auto result = s.attach<author>("authors").and_then([&s] {
|
||||
return s.attach<book>("books");
|
||||
});
|
||||
// s.attach<book>( "books" );
|
||||
|
||||
connection c( dns );
|
||||
result = c.open();
|
||||
// s.create( c );
|
||||
//
|
||||
// auto create_authors_sql = c.query( s )
|
||||
// .create()
|
||||
// .table<author>( qh::authors )
|
||||
// .execute();
|
||||
//
|
||||
// c.query( s )
|
||||
// .create()
|
||||
// .table<book>( qh::books )
|
||||
// .execute();
|
||||
//
|
||||
// std::cout << "SQL: " << create_authors_sql << "\n";
|
||||
//
|
||||
// author mc;
|
||||
// mc.id = 1;
|
||||
// mc.first_name = "Michael";
|
||||
// mc.last_name = "Crichton";
|
||||
// mc.date_of_birth = "19.8.1954";
|
||||
// mc.year_of_birth = 1954;
|
||||
// mc.distinguished = true;
|
||||
// auto insert_authors_sql = c.query( s )
|
||||
// .insert()
|
||||
// .into( qh::authors )
|
||||
// .values( mc )
|
||||
// .execute();
|
||||
//
|
||||
// std::cout << "SQL: " << insert_authors_sql << "\n";
|
||||
//
|
||||
// auto result = c.query( s )
|
||||
// .select( qh::authors.columns )
|
||||
// .from( qh::authors )
|
||||
// .fetch_all();
|
||||
//
|
||||
// for (const auto& row: result) { std::cout << "Author " << row.at( qh::authors.first_name ) << "\n"; }
|
||||
const auto c = pool.acquire();
|
||||
result = s.create(*c);
|
||||
if (!result) {
|
||||
std::cout << "error: " << result.err() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
author mc;
|
||||
mc.id = 1;
|
||||
mc.first_name = "Michael";
|
||||
mc.last_name = "Crichton";
|
||||
mc.date_of_birth = "19.8.1954";
|
||||
mc.year_of_birth = 1954;
|
||||
mc.distinguished = true;
|
||||
auto insert_authors_sql = query::insert()
|
||||
.into(AUTHOR)
|
||||
.values(mc)
|
||||
.execute(*c);
|
||||
|
||||
if (!insert_authors_sql) {
|
||||
std::cout << "error: " << insert_authors_sql.err() << std::endl;
|
||||
std::ignore = s.drop(*c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto authors_result = query::select(AUTHOR)
|
||||
.from(AUTHOR)
|
||||
.fetch_all(*c);
|
||||
|
||||
if (!authors_result) {
|
||||
std::cout << "error: " << authors_result.err() << std::endl;
|
||||
std::ignore = s.drop(*c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (const auto &row: *authors_result) {
|
||||
std::cout << "Author " << row.at(AUTHOR.first_name.canonical_name()) << "\n";
|
||||
}
|
||||
//
|
||||
// auto update_authors_sql = c.query( s )
|
||||
// .update( qh::authors )
|
||||
|
|
@ -236,20 +243,35 @@ int main() {
|
|||
// .values( {3, "Misery", mc.id, 1984} )
|
||||
// .execute();
|
||||
//
|
||||
auto select_books_sql = matador::query::query::select( BOOK, {AUTHOR.last_name} )
|
||||
// auto select_books_sql = query::select( BOOK, {AUTHOR.last_name} )
|
||||
auto select_books_sql = query::select({BOOK.id, BOOK.title, BOOK.author_id, BOOK.published_in, AUTHOR.last_name})
|
||||
.from(BOOK)
|
||||
.join_left(AUTHOR)
|
||||
.on(BOOK.author_id == AUTHOR.id)
|
||||
.where(BOOK.published_in < 2008 && AUTHOR.last_name == "King")
|
||||
.group_by( BOOK.published_in )
|
||||
.group_by({BOOK.id, AUTHOR.last_name})
|
||||
.order_by(BOOK.title).asc()
|
||||
.limit(5)
|
||||
.offset(2)
|
||||
.fetch_all(c);
|
||||
.fetch_all(*c);
|
||||
|
||||
if (!select_books_sql) {
|
||||
std::cout << "error: " << select_books_sql.err() << std::endl;
|
||||
std::ignore = s.drop(*c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (const auto &r: *select_books_sql) {
|
||||
std::cout << "R: " << r.at( BOOK.title ) << ", " << r.at( AUTHOR.last_name ) << "\n";
|
||||
std::cout << "R: " << r.at(BOOK.title.canonical_name()) << ", " << r.at(AUTHOR.last_name.canonical_name()) << "\n";
|
||||
}
|
||||
|
||||
result = s.drop(*c);
|
||||
if (!result) {
|
||||
std::cout << "error: " << result.err() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// // SELECT book.title, book.id, book.author_id, book.published_in, author.name
|
||||
// // FROM book
|
||||
// // INNER JOIN author ON book.author_id = author.id
|
||||
|
|
@ -266,24 +288,21 @@ int main() {
|
|||
//
|
||||
// std::cout << "SQL: " << drop_authors_sql << "\n";
|
||||
//
|
||||
// auto res = c.query( s )
|
||||
// .select( {qh::payload.id} )
|
||||
// .from( qh::payload )
|
||||
// .join_left( qh::job )
|
||||
// .on( qh::job.payload == qh::payload.id )
|
||||
// .where(
|
||||
// in( qh::payload.id, c.query( s )
|
||||
// .select( {qh::job.state} )
|
||||
// .from( qh::job )
|
||||
// .where( qh::job.state == job::job_state::Running )
|
||||
// ) &&
|
||||
// in( qh::payload.id, c.query( s )
|
||||
// .select( {qh::temporary_table.id} )
|
||||
// .from( qh::temporary_table ) )
|
||||
// )
|
||||
// .build();
|
||||
auto res = query::select({PAYLOAD.id})
|
||||
.from(PAYLOAD)
|
||||
.join_left(JOB)
|
||||
.on(JOB.payload == PAYLOAD.id)
|
||||
.where(
|
||||
in(PAYLOAD.id, query::select({JOB.state})
|
||||
.from(JOB)
|
||||
.where(JOB.state == job::job_state::Running).compile(c->dialect())
|
||||
) &&
|
||||
in(PAYLOAD.id, query::select({TEMPORARY_TABLE.id})
|
||||
.from(TEMPORARY_TABLE).compile(c->dialect())
|
||||
)
|
||||
).compile(c->dialect());
|
||||
// // .fetch_value<unsigned long>();
|
||||
// std::cout << "SQL: " << res.sql << "\n";
|
||||
std::cout << "SQL: " << res.sql << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -52,6 +52,7 @@ public:
|
|||
[[nodiscard]] bool is_varchar() const;
|
||||
[[nodiscard]] bool is_date() const;
|
||||
[[nodiscard]] bool is_time() const;
|
||||
[[nodiscard]] bool is_timestamp() const;
|
||||
[[nodiscard]] bool is_blob() const;
|
||||
[[nodiscard]] bool is_null() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,9 +10,11 @@ class collection {
|
|||
public:
|
||||
using value_type = Type;
|
||||
|
||||
void push_back(const Type& value) { data_.push_back(value); }
|
||||
|
||||
[[nodiscard]] size_t size() const { return data_.size(); }
|
||||
private:
|
||||
std::vector<Type> data_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ public:
|
|||
executable_query constraints(std::initializer_list<object::restriction> constraints);
|
||||
executable_query constraints(const std::list<object::restriction> &restrictions);
|
||||
executable_query constraints(std::initializer_list<table_constraint> constraints);
|
||||
executable_query constraints(const std::list<table_constraint> &restrictions);
|
||||
executable_query constraints(const std::list<table_constraint> &constraints);
|
||||
};
|
||||
|
||||
class query_create_table_intermediate : public query_intermediate {
|
||||
|
|
@ -32,6 +32,7 @@ public:
|
|||
query_create_table_columns_intermediate columns(const std::list<object::attribute> &attributes);
|
||||
query_create_table_columns_intermediate columns(std::initializer_list<table_column> columns);
|
||||
query_create_table_columns_intermediate columns(const std::list<table_column> &columns);
|
||||
query_create_table_columns_intermediate columns(const std::vector<table_column> &columns);
|
||||
};
|
||||
|
||||
class query_create_intermediate : public query_intermediate {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ public:
|
|||
|
||||
query_execute_limit_intermediate limit(size_t limit);
|
||||
query_execute_order_by_intermediate order_by(const table_column &col);
|
||||
query_execute_order_by_intermediate order_by(std::initializer_list<table_column> columns);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,14 +19,11 @@ public:
|
|||
query_from_intermediate join_left(join_data &data);
|
||||
query_from_intermediate join_left(std::vector<join_data> &data_vector);
|
||||
|
||||
// template<class Condition>
|
||||
// query_where_intermediate where(const Condition &cond)
|
||||
// {
|
||||
// return where_clause(std::make_unique<Condition>(std::move(cond)));
|
||||
// }
|
||||
query_where_intermediate where(std::unique_ptr<abstract_criteria> &&cond);
|
||||
query_group_by_intermediate group_by(const table_column &col);
|
||||
query_group_by_intermediate group_by(const table_column &column);
|
||||
query_group_by_intermediate group_by(std::initializer_list<table_column> columns);
|
||||
query_order_by_intermediate order_by(const table_column &col);
|
||||
query_order_by_intermediate order_by(std::initializer_list<table_column> columns);
|
||||
|
||||
private:
|
||||
query_where_intermediate where_clause(std::unique_ptr<abstract_criteria> &&cond);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ public:
|
|||
using fetchable_query::fetchable_query;
|
||||
|
||||
query_order_by_intermediate order_by(const table_column &col);
|
||||
query_order_by_intermediate order_by(std::initializer_list<table_column> columns);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,10 @@ class query_where_intermediate : public fetchable_query
|
|||
public:
|
||||
using fetchable_query::fetchable_query;
|
||||
|
||||
query_group_by_intermediate group_by(const table_column &col);
|
||||
query_group_by_intermediate group_by(const table_column &column);
|
||||
query_group_by_intermediate group_by(std::initializer_list<table_column> columns);
|
||||
query_order_by_intermediate order_by(const table_column &col);
|
||||
query_order_by_intermediate order_by(std::initializer_list<table_column> columns);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -205,29 +205,29 @@ protected:
|
|||
class query_group_by_part final : public query_part
|
||||
{
|
||||
public:
|
||||
explicit query_group_by_part(class table_column col);
|
||||
explicit query_group_by_part(const std::vector<table_column>& columns);
|
||||
|
||||
[[nodiscard]] const table_column& column() const;
|
||||
[[nodiscard]] const std::vector<table_column>& columns() const;
|
||||
|
||||
private:
|
||||
void accept(query_part_visitor &visitor) override;
|
||||
|
||||
private:
|
||||
table_column column_;
|
||||
std::vector<table_column> columns_;
|
||||
};
|
||||
|
||||
class query_order_by_part final : public query_part
|
||||
{
|
||||
public:
|
||||
explicit query_order_by_part(class table_column col);
|
||||
explicit query_order_by_part(const std::vector<table_column>& columns);
|
||||
|
||||
[[nodiscard]] const table_column& column() const;
|
||||
[[nodiscard]] const std::vector<table_column>& columns() const;
|
||||
|
||||
private:
|
||||
void accept(query_part_visitor &visitor) override;
|
||||
|
||||
private:
|
||||
table_column column_;
|
||||
std::vector<table_column> columns_;
|
||||
};
|
||||
|
||||
class query_order_by_asc_part final : public query_part
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace internal { \
|
|||
class TABLE_NAME##_table : public typed_table<TABLE_NAME##_table> { \
|
||||
public: \
|
||||
TABLE_NAME##_table()\
|
||||
: TABLE_NAME##_table("") \
|
||||
: TABLE_NAME##_table(#TABLE_NAME) \
|
||||
{} \
|
||||
TABLE_NAME##_table(const std::string& alias) \
|
||||
: typed_table(#TABLE_NAME, alias, {MAP(FIELD_STRING, __VA_ARGS__)}) \
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ public:
|
|||
[[nodiscard]] static query_select_intermediate select(std::initializer_list<table_column> columns);
|
||||
[[nodiscard]] static query_select_intermediate select(const std::vector<table_column>& columns);
|
||||
[[nodiscard]] static query_select_intermediate select(const std::vector<std::string> &column_names);
|
||||
[[nodiscard]] static query_select_intermediate select(std::vector<table_column> columns, std::initializer_list<table_column> additional_columns);
|
||||
template<class Type>
|
||||
[[nodiscard]] static query_select_intermediate select(const schema &scm) {
|
||||
return select(generator::columns<Type>(scm));
|
||||
|
|
|
|||
|
|
@ -2,16 +2,12 @@
|
|||
#define OOS_ACCESS_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
namespace matador {
|
||||
|
||||
enum class cascade_type;
|
||||
|
||||
template < class Type, template < class ... > class ContainerType >
|
||||
class container;
|
||||
|
||||
namespace utils {
|
||||
class field_attributes;
|
||||
class foreign_attributes;
|
||||
|
|
|
|||
|
|
@ -194,6 +194,7 @@ public:
|
|||
[[nodiscard]] bool is_varchar() const;
|
||||
[[nodiscard]] bool is_date() const;
|
||||
[[nodiscard]] bool is_time() const;
|
||||
[[nodiscard]] bool is_timestamp() const;
|
||||
[[nodiscard]] bool is_blob() const;
|
||||
[[nodiscard]] bool is_null() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -18,15 +18,19 @@ size_t determine_size(const blob_type_t &val);
|
|||
|
||||
}
|
||||
|
||||
class value
|
||||
{
|
||||
class value {
|
||||
public:
|
||||
value() = default;
|
||||
template<typename Type>
|
||||
template<typename Type, std::enable_if_t<!std::is_enum_v<Type>>* = nullptr>
|
||||
explicit value(Type value, size_t size = 0)
|
||||
: value_(value)
|
||||
, size_(size)
|
||||
, type_(data_type_traits<Type>::type(size)) {}
|
||||
template<typename Type, std::enable_if_t<std::is_enum_v<Type>>* = nullptr>
|
||||
explicit value(Type value, size_t size = 0)
|
||||
: value_(static_cast<int>(value))
|
||||
, size_(size)
|
||||
, type_(data_type_traits<Type>::type(size)) {}
|
||||
explicit value(basic_type data_type, size_t size = 0);
|
||||
value(const value &x) = default;
|
||||
value& operator=(const value &x) = default;
|
||||
|
|
@ -74,11 +78,12 @@ public:
|
|||
[[nodiscard]] bool is_varchar() const;
|
||||
[[nodiscard]] bool is_date() const;
|
||||
[[nodiscard]] bool is_time() const;
|
||||
[[nodiscard]] bool is_timestamp() const;
|
||||
[[nodiscard]] bool is_blob() const;
|
||||
[[nodiscard]] bool is_null() const;
|
||||
|
||||
private:
|
||||
utils::database_type value_;
|
||||
database_type value_;
|
||||
size_t size_{};
|
||||
basic_type type_{basic_type::Null};
|
||||
|
||||
|
|
|
|||
|
|
@ -85,6 +85,10 @@ bool attribute::is_time() const {
|
|||
return type_ == utils::basic_type::Time;
|
||||
}
|
||||
|
||||
bool attribute::is_timestamp() const {
|
||||
return type_ == utils::basic_type::DateTime;
|
||||
}
|
||||
|
||||
bool attribute::is_blob() const {
|
||||
return type_ == utils::basic_type::Blob;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,53 +19,48 @@ std::string identifier_type_traits<const char*>::to_string(const char *value) {
|
|||
|
||||
identifier::base::base(const std::type_index &ti, const basic_type type)
|
||||
: type_index_(ti)
|
||||
, type_(type)
|
||||
{}
|
||||
, type_(type) {
|
||||
}
|
||||
|
||||
identifier::null_pk::null_pk()
|
||||
: base(std::type_index(typeid(null_type_t)), basic_type::Null)
|
||||
{}
|
||||
: base(std::type_index(typeid(null_type_t)), basic_type::Null) {
|
||||
}
|
||||
|
||||
identifier::base* identifier::null_pk::copy() const
|
||||
{
|
||||
identifier::base *identifier::null_pk::copy() const {
|
||||
return new null_pk;
|
||||
}
|
||||
|
||||
bool identifier::null_pk::equal_to(const base &x) const
|
||||
{
|
||||
bool identifier::null_pk::equal_to(const base &x) const {
|
||||
return type_index_ == x.type_index_;
|
||||
}
|
||||
|
||||
bool identifier::null_pk::less(const base &x) const
|
||||
{
|
||||
bool identifier::null_pk::less(const base &x) const {
|
||||
return type_index_ == x.type_index_;
|
||||
}
|
||||
|
||||
bool identifier::null_pk::is_valid() const
|
||||
{
|
||||
bool identifier::null_pk::is_valid() const {
|
||||
return identifier_type_traits<null_type_t>::is_valid();
|
||||
}
|
||||
|
||||
std::string identifier::null_pk::str() const
|
||||
{
|
||||
std::string identifier::null_pk::str() const {
|
||||
return identifier_type_traits<null_type_t>::to_string();
|
||||
}
|
||||
|
||||
void identifier::null_pk::serialize(identifier_serializer &s)
|
||||
{
|
||||
void identifier::null_pk::serialize(identifier_serializer &s) {
|
||||
s.serialize(null_, {});
|
||||
}
|
||||
|
||||
size_t identifier::null_pk::hash() const
|
||||
{
|
||||
size_t identifier::null_pk::hash() const {
|
||||
return std::hash<nullptr_t>()(nullptr);
|
||||
}
|
||||
|
||||
identifier::identifier()
|
||||
: id_(std::make_shared<null_pk>()) {}
|
||||
: id_(std::make_shared<null_pk>()) {
|
||||
}
|
||||
|
||||
identifier::identifier(const identifier &x)
|
||||
: id_(x.id_->copy()) {}
|
||||
: id_(x.id_->copy()) {
|
||||
}
|
||||
|
||||
identifier &identifier::operator=(const identifier &x) {
|
||||
if (this == &x) {
|
||||
|
|
@ -123,13 +118,11 @@ basic_type identifier::type() const {
|
|||
return id_->type_;
|
||||
}
|
||||
|
||||
identifier identifier::share() const
|
||||
{
|
||||
identifier identifier::share() const {
|
||||
return identifier(id_);
|
||||
}
|
||||
|
||||
size_t identifier::use_count() const
|
||||
{
|
||||
size_t identifier::use_count() const {
|
||||
return id_.use_count();
|
||||
}
|
||||
|
||||
|
|
@ -157,22 +150,23 @@ bool identifier::is_time() const {
|
|||
return id_->type_ == basic_type::Time;
|
||||
}
|
||||
|
||||
bool identifier::is_timestamp() const {
|
||||
return id_->type_ == basic_type::DateTime;
|
||||
}
|
||||
|
||||
bool identifier::is_blob() const {
|
||||
return id_->type_ == basic_type::Blob;
|
||||
}
|
||||
|
||||
bool identifier::is_null() const
|
||||
{
|
||||
bool identifier::is_null() const {
|
||||
return type_index() == null_identifier.type_index();
|
||||
}
|
||||
|
||||
bool identifier::is_valid() const
|
||||
{
|
||||
bool identifier::is_valid() const {
|
||||
return id_->is_valid();
|
||||
}
|
||||
|
||||
void identifier::clear()
|
||||
{
|
||||
void identifier::clear() {
|
||||
id_ = std::make_unique<null_pk>();
|
||||
}
|
||||
|
||||
|
|
@ -180,24 +174,20 @@ void identifier::serialize(identifier_serializer &s) const {
|
|||
id_->serialize(s);
|
||||
}
|
||||
|
||||
size_t identifier::hash() const
|
||||
{
|
||||
size_t identifier::hash() const {
|
||||
return id_->hash();
|
||||
}
|
||||
|
||||
identifier::identifier(const std::shared_ptr<base> &id)
|
||||
: id_(id)
|
||||
{}
|
||||
: id_(id) {
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const identifier &id)
|
||||
{
|
||||
std::ostream &operator<<(std::ostream &out, const identifier &id) {
|
||||
out << id.str();
|
||||
return out;
|
||||
}
|
||||
|
||||
size_t id_pk_hash::operator()(const identifier &id) const
|
||||
{
|
||||
size_t id_pk_hash::operator()(const identifier &id) const {
|
||||
return id.hash();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -84,6 +84,10 @@ bool value::is_time() const {
|
|||
return type_ == basic_type::Time;
|
||||
}
|
||||
|
||||
bool value::is_timestamp() const {
|
||||
return type_ == basic_type::DateTime;
|
||||
}
|
||||
|
||||
bool value::is_blob() const {
|
||||
return type_ == basic_type::Blob;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,4 +79,13 @@ query_create_table_columns_intermediate query_create_table_intermediate::columns
|
|||
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_create_table_columns_intermediate query_create_table_intermediate::columns(const std::vector<table_column> &columns) {
|
||||
std::list<table_column> cols;
|
||||
for (const auto &col : columns) {
|
||||
cols.emplace_back(col);
|
||||
}
|
||||
|
||||
return this->columns(cols);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,11 @@ query_execute_limit_intermediate query_execute_where_intermediate::limit(size_t
|
|||
}
|
||||
|
||||
query_execute_order_by_intermediate query_execute_where_intermediate::order_by(const table_column &col) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(col));
|
||||
return {context_};
|
||||
return order_by({col});
|
||||
}
|
||||
|
||||
query_execute_order_by_intermediate query_execute_where_intermediate::order_by(std::initializer_list<table_column> columns) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(columns));
|
||||
return {context_};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,13 +38,21 @@ query_where_intermediate query_from_intermediate::where_clause(std::unique_ptr<a
|
|||
return {context_};
|
||||
}
|
||||
|
||||
query_group_by_intermediate query_from_intermediate::group_by(const table_column &col) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_group_by_part>(col));
|
||||
query_group_by_intermediate query_from_intermediate::group_by(const table_column &column) {
|
||||
return group_by({column});
|
||||
}
|
||||
|
||||
query_group_by_intermediate query_from_intermediate::group_by(std::initializer_list<table_column> columns) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_group_by_part>(columns));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_order_by_intermediate query_from_intermediate::order_by(const table_column &col) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(col));
|
||||
return order_by({col});
|
||||
}
|
||||
|
||||
query_order_by_intermediate query_from_intermediate::order_by(std::initializer_list<table_column> columns) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(columns));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,11 @@
|
|||
namespace matador::query {
|
||||
|
||||
query_order_by_intermediate query_group_by_intermediate::order_by(const table_column &col) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(col));
|
||||
return {context_};
|
||||
return order_by({col});
|
||||
}
|
||||
|
||||
query_order_by_intermediate query_group_by_intermediate::order_by(std::initializer_list<table_column> columns) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(columns));
|
||||
return {context_};
|
||||
}
|
||||
}
|
||||
|
|
@ -5,15 +5,23 @@
|
|||
#include "matador/query/internal/query_parts.hpp"
|
||||
|
||||
namespace matador::query {
|
||||
query_group_by_intermediate query_where_intermediate::group_by(const table_column &column) {
|
||||
return group_by({column});
|
||||
}
|
||||
|
||||
query_group_by_intermediate query_where_intermediate::group_by(const table_column &col) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_group_by_part>(col));
|
||||
query_group_by_intermediate query_where_intermediate::group_by(std::initializer_list<table_column> columns) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_group_by_part>(columns));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
query_order_by_intermediate query_where_intermediate::order_by(const table_column &col) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(col));
|
||||
return order_by({col});
|
||||
}
|
||||
|
||||
query_order_by_intermediate query_where_intermediate::order_by(std::initializer_list<table_column> columns) {
|
||||
context_->parts.push_back(std::make_unique<internal::query_order_by_part>(columns));
|
||||
return {context_};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
namespace matador::query::internal {
|
||||
query_alter_part::query_alter_part()
|
||||
: query_part(sql::dialect_token::Alter) {}
|
||||
: query_part(sql::dialect_token::Alter) {
|
||||
}
|
||||
|
||||
void query_alter_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
|
|
@ -12,7 +13,8 @@ void query_alter_part::accept( query_part_visitor& visitor ) {
|
|||
|
||||
query_alter_table_part::query_alter_table_part(class table tab)
|
||||
: query_part(sql::dialect_token::Table)
|
||||
, table_(std::move(tab)) {}
|
||||
, table_(std::move(tab)) {
|
||||
}
|
||||
|
||||
void query_alter_table_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
|
|
@ -24,7 +26,8 @@ const table& query_alter_table_part::table() const {
|
|||
|
||||
query_add_key_constraint_part::query_add_key_constraint_part(std::string name)
|
||||
: query_part(sql::dialect_token::AddConstraint)
|
||||
, name_(std::move(name)){}
|
||||
, name_(std::move(name)) {
|
||||
}
|
||||
|
||||
void query_add_key_constraint_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
|
|
@ -36,7 +39,8 @@ const std::string& query_add_key_constraint_part::name() const {
|
|||
|
||||
query_add_constraint_part_by_constraint::query_add_constraint_part_by_constraint(const query::table_constraint &co)
|
||||
: query_part(sql::dialect_token::AddConstraint)
|
||||
, constraint_(co) {}
|
||||
, constraint_(co) {
|
||||
}
|
||||
|
||||
void query_add_constraint_part_by_constraint::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
|
|
@ -48,7 +52,8 @@ const table_constraint & query_add_constraint_part_by_constraint::constraint() c
|
|||
|
||||
query_drop_key_constraint_part_by_name::query_drop_key_constraint_part_by_name(std::string name)
|
||||
: query_part(sql::dialect_token::DropConstraint)
|
||||
, name_(std::move( name )){}
|
||||
, name_(std::move(name)) {
|
||||
}
|
||||
|
||||
void query_drop_key_constraint_part_by_name::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
|
|
@ -60,7 +65,8 @@ const std::string& query_drop_key_constraint_part_by_name::name() const {
|
|||
|
||||
query_drop_key_constraint_part_by_constraint::query_drop_key_constraint_part_by_constraint(const table_constraint &co)
|
||||
: query_part(sql::dialect_token::DropConstraint)
|
||||
, constraint_(co) {}
|
||||
, constraint_(co) {
|
||||
}
|
||||
|
||||
void query_drop_key_constraint_part_by_constraint::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
|
|
@ -72,7 +78,8 @@ const table_constraint& query_drop_key_constraint_part_by_constraint::constraint
|
|||
|
||||
query_add_foreign_key_constraint_part::query_add_foreign_key_constraint_part(const std::vector<table_column> &columns)
|
||||
: query_part(sql::dialect_token::ForeignKey)
|
||||
, columns_(columns) {}
|
||||
, columns_(columns) {
|
||||
}
|
||||
|
||||
void query_add_foreign_key_constraint_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
|
|
@ -82,10 +89,12 @@ const std::vector<table_column>& query_add_foreign_key_constraint_part::columns(
|
|||
return columns_;
|
||||
}
|
||||
|
||||
query_add_foreign_key_reference_part::query_add_foreign_key_reference_part(class table tab, const std::vector<table_column>& columns)
|
||||
query_add_foreign_key_reference_part::query_add_foreign_key_reference_part(
|
||||
class table tab, const std::vector<table_column> &columns)
|
||||
: query_part(sql::dialect_token::References)
|
||||
, table_(std::move(tab))
|
||||
, columns_(columns) {}
|
||||
, columns_(columns) {
|
||||
}
|
||||
|
||||
void query_add_foreign_key_reference_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
|
|
@ -101,7 +110,8 @@ const std::vector<table_column>& query_add_foreign_key_reference_part::columns()
|
|||
|
||||
query_add_primary_key_constraint_part::query_add_primary_key_constraint_part(const std::vector<table_column> &columns)
|
||||
: query_part(sql::dialect_token::PrimaryKey)
|
||||
, columns_(columns) {}
|
||||
, columns_(columns) {
|
||||
}
|
||||
|
||||
void query_add_primary_key_constraint_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
|
|
@ -113,271 +123,253 @@ const std::vector<table_column>& query_add_primary_key_constraint_part::columns(
|
|||
|
||||
query_select_part::query_select_part(std::vector<table_column> columns)
|
||||
: query_part(sql::dialect_token::Select)
|
||||
, columns_(std::move(columns)) {}
|
||||
, columns_(std::move(columns)) {
|
||||
}
|
||||
|
||||
void query_select_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_select_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
const std::vector<table_column>& query_select_part::columns() const
|
||||
{
|
||||
const std::vector<table_column> &query_select_part::columns() const {
|
||||
return columns_;
|
||||
}
|
||||
|
||||
query_from_part::query_from_part(class table tab)
|
||||
: query_part(sql::dialect_token::From)
|
||||
, table_(std::move(tab)) {}
|
||||
, table_(std::move(tab)) {
|
||||
}
|
||||
|
||||
const table &query_from_part::table() const
|
||||
{
|
||||
const table &query_from_part::table() const {
|
||||
return table_;
|
||||
}
|
||||
|
||||
void query_from_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_from_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_join_part::query_join_part(class table tab)
|
||||
: query_part(sql::dialect_token::Join)
|
||||
, table_(std::move(tab)) {}
|
||||
, table_(std::move(tab)) {
|
||||
}
|
||||
|
||||
const table &query_join_part::table() const
|
||||
{
|
||||
const table &query_join_part::table() const {
|
||||
return table_;
|
||||
}
|
||||
|
||||
void query_join_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_join_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_on_part::query_on_part(std::unique_ptr<abstract_criteria> &&cond)
|
||||
: query_part(sql::dialect_token::On)
|
||||
, condition_(std::move(cond)) {}
|
||||
, condition_(std::move(cond)) {
|
||||
}
|
||||
|
||||
const abstract_criteria &query_on_part::condition() const
|
||||
{
|
||||
const abstract_criteria &query_on_part::condition() const {
|
||||
return *condition_;
|
||||
}
|
||||
|
||||
void query_on_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_on_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_where_part::query_where_part(std::unique_ptr<abstract_criteria> &&cond)
|
||||
: query_part(sql::dialect_token::Where)
|
||||
, condition_(std::move(cond)) {}
|
||||
, condition_(std::move(cond)) {
|
||||
}
|
||||
|
||||
void query_where_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_where_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
const abstract_criteria &query_where_part::condition() const
|
||||
{
|
||||
const abstract_criteria &query_where_part::condition() const {
|
||||
return *condition_;
|
||||
}
|
||||
|
||||
query_table_name_part::query_table_name_part(const sql::dialect_token token, std::string table_name)
|
||||
: query_part(token)
|
||||
, table_name_(std::move(table_name)) {}
|
||||
|
||||
query_group_by_part::query_group_by_part(class table_column col)
|
||||
: query_part(sql::dialect_token::GroupBy)
|
||||
, column_(std::move(col))
|
||||
{}
|
||||
|
||||
const table_column &query_group_by_part::column() const
|
||||
{
|
||||
return column_;
|
||||
, table_name_(std::move(table_name)) {
|
||||
}
|
||||
|
||||
void query_group_by_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
query_group_by_part::query_group_by_part(const std::vector<table_column> &columns)
|
||||
: query_part(sql::dialect_token::GroupBy)
|
||||
, columns_(columns) {
|
||||
}
|
||||
|
||||
const std::vector<table_column> &query_group_by_part::columns() const {
|
||||
return columns_;
|
||||
}
|
||||
|
||||
void query_group_by_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_order_by_part::query_order_by_part(class table_column col)
|
||||
query_order_by_part::query_order_by_part(const std::vector<table_column>& columns)
|
||||
: query_part(sql::dialect_token::OrderBy)
|
||||
, column_(std::move(col))
|
||||
{}
|
||||
|
||||
const table_column &query_order_by_part::column() const
|
||||
{
|
||||
return column_;
|
||||
, columns_(columns) {
|
||||
}
|
||||
|
||||
void query_order_by_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
const std::vector<table_column> &query_order_by_part::columns() const {
|
||||
return columns_;
|
||||
}
|
||||
|
||||
void query_order_by_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_order_by_asc_part::query_order_by_asc_part()
|
||||
: query_part(sql::dialect_token::Asc)
|
||||
{}
|
||||
: query_part(sql::dialect_token::Asc) {
|
||||
}
|
||||
|
||||
void query_order_by_asc_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_order_by_asc_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_order_by_desc_part::query_order_by_desc_part()
|
||||
: query_part(sql::dialect_token::Desc)
|
||||
{}
|
||||
: query_part(sql::dialect_token::Desc) {
|
||||
}
|
||||
|
||||
void query_order_by_desc_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_order_by_desc_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_offset_part::query_offset_part(size_t offset)
|
||||
: query_part(sql::dialect_token::Offset)
|
||||
, offset_(offset) {}
|
||||
, offset_(offset) {
|
||||
}
|
||||
|
||||
size_t query_offset_part::offset() const
|
||||
{
|
||||
size_t query_offset_part::offset() const {
|
||||
return offset_;
|
||||
}
|
||||
|
||||
void query_offset_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_offset_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_limit_part::query_limit_part(size_t limit)
|
||||
: query_part(sql::dialect_token::Limit)
|
||||
, limit_(limit) {}
|
||||
, limit_(limit) {
|
||||
}
|
||||
|
||||
size_t query_limit_part::limit() const
|
||||
{
|
||||
size_t query_limit_part::limit() const {
|
||||
return limit_;
|
||||
}
|
||||
|
||||
void query_limit_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_limit_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_insert_part::query_insert_part()
|
||||
: query_part(sql::dialect_token::Insert) {}
|
||||
: query_part(sql::dialect_token::Insert) {
|
||||
}
|
||||
|
||||
void query_insert_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_insert_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_into_part::query_into_part(class table tab, std::vector<table_column> columns)
|
||||
: query_part(sql::dialect_token::Insert)
|
||||
, table_(std::move(tab))
|
||||
, columns_(std::move(columns)) {}
|
||||
, columns_(std::move(columns)) {
|
||||
}
|
||||
|
||||
const table &query_into_part::table() const
|
||||
{
|
||||
const table &query_into_part::table() const {
|
||||
return table_;
|
||||
}
|
||||
|
||||
const std::vector<table_column> &query_into_part::columns() const
|
||||
{
|
||||
const std::vector<table_column> &query_into_part::columns() const {
|
||||
return columns_;
|
||||
}
|
||||
|
||||
void query_into_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_into_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_values_part::query_values_part(std::vector<std::variant<utils::placeholder, utils::database_type> > &&values)
|
||||
: query_part(sql::dialect_token::Values)
|
||||
, values_(std::move(values)) {}
|
||||
, values_(std::move(values)) {
|
||||
}
|
||||
|
||||
const std::vector<std::variant<utils::placeholder, utils::database_type>>& query_values_part::values() const
|
||||
{
|
||||
const std::vector<std::variant<utils::placeholder, utils::database_type> > &query_values_part::values() const {
|
||||
return values_;
|
||||
}
|
||||
|
||||
void query_values_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_values_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_update_part::query_update_part(class table tab)
|
||||
: query_part(sql::dialect_token::Update)
|
||||
, table_(std::move(tab)) {}
|
||||
, table_(std::move(tab)) {
|
||||
}
|
||||
|
||||
const table& query_update_part::table() const
|
||||
{
|
||||
const table &query_update_part::table() const {
|
||||
return table_;
|
||||
}
|
||||
|
||||
void query_update_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_update_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_set_part::query_set_part(const std::vector<column_value_pair> &key_value_pairs)
|
||||
: query_part(sql::dialect_token::Set)
|
||||
, key_value_pairs_(key_value_pairs) {}
|
||||
, key_value_pairs_(key_value_pairs) {
|
||||
}
|
||||
|
||||
const std::vector<column_value_pair> &query_set_part::column_values() const
|
||||
{
|
||||
const std::vector<column_value_pair> &query_set_part::column_values() const {
|
||||
return key_value_pairs_;
|
||||
}
|
||||
|
||||
void query_set_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_set_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_delete_part::query_delete_part()
|
||||
: query_part(sql::dialect_token::Remove) {}
|
||||
: query_part(sql::dialect_token::Remove) {
|
||||
}
|
||||
|
||||
void query_delete_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_delete_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_delete_from_part::query_delete_from_part(class table tab)
|
||||
: query_part(sql::dialect_token::From)
|
||||
, table_(std::move(tab)) {}
|
||||
, table_(std::move(tab)) {
|
||||
}
|
||||
|
||||
const table &query_delete_from_part::table() const
|
||||
{
|
||||
const table &query_delete_from_part::table() const {
|
||||
return table_;
|
||||
}
|
||||
|
||||
void query_delete_from_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_delete_from_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_create_part::query_create_part()
|
||||
: query_part(sql::dialect_token::Create) {}
|
||||
: query_part(sql::dialect_token::Create) {
|
||||
}
|
||||
|
||||
void query_create_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_create_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_create_table_part::query_create_table_part(class table tab)
|
||||
: query_part(sql::dialect_token::Table)
|
||||
, table_(std::move(tab)) {}
|
||||
, table_(std::move(tab)) {
|
||||
}
|
||||
|
||||
const table &query_create_table_part::table() const
|
||||
{
|
||||
const table &query_create_table_part::table() const {
|
||||
return table_;
|
||||
}
|
||||
|
||||
void query_create_table_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_create_table_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_create_table_columns_part::query_create_table_columns_part(const std::list<table_column> &columns)
|
||||
: query_part(sql::dialect_token::Columns)
|
||||
, columns_(columns){}
|
||||
, columns_(columns) {
|
||||
}
|
||||
|
||||
const std::list<table_column> &query_create_table_columns_part::columns() const {
|
||||
return columns_;
|
||||
|
|
@ -387,9 +379,11 @@ void query_create_table_columns_part::accept(query_part_visitor& visitor) {
|
|||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_create_table_constraints_part::query_create_table_constraints_part(const std::list<class table_constraint>& constraints)
|
||||
query_create_table_constraints_part::query_create_table_constraints_part(
|
||||
const std::list<class table_constraint> &constraints)
|
||||
: query_part(sql::dialect_token::Constraint)
|
||||
, constraints_(constraints) {}
|
||||
, constraints_(constraints) {
|
||||
}
|
||||
|
||||
const std::list<class table_constraint> &query_create_table_constraints_part::constraints() const {
|
||||
return constraints_;
|
||||
|
|
@ -401,7 +395,8 @@ void query_create_table_constraints_part::accept( query_part_visitor& visitor )
|
|||
|
||||
query_create_schema_part::query_create_schema_part(std::string schema)
|
||||
: query_part(sql::dialect_token::Schema)
|
||||
, schema_( std::move( schema ) ){}
|
||||
, schema_(std::move(schema)) {
|
||||
}
|
||||
|
||||
const std::string &query_create_schema_part::schema() const {
|
||||
return schema_;
|
||||
|
|
@ -412,30 +407,30 @@ void query_create_schema_part::accept( query_part_visitor& visitor ) {
|
|||
}
|
||||
|
||||
query_drop_part::query_drop_part()
|
||||
: query_part(sql::dialect_token::Drop) {}
|
||||
: query_part(sql::dialect_token::Drop) {
|
||||
}
|
||||
|
||||
void query_drop_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_drop_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_drop_table_part::query_drop_table_part(class table tab)
|
||||
: query_part(sql::dialect_token::Table)
|
||||
, table_(std::move(tab)) {}
|
||||
, table_(std::move(tab)) {
|
||||
}
|
||||
|
||||
const table &query_drop_table_part::table() const
|
||||
{
|
||||
const table &query_drop_table_part::table() const {
|
||||
return table_;
|
||||
}
|
||||
|
||||
void query_drop_table_part::accept(query_part_visitor &visitor)
|
||||
{
|
||||
void query_drop_table_part::accept(query_part_visitor &visitor) {
|
||||
visitor.visit(*this);
|
||||
}
|
||||
|
||||
query_drop_schema_part::query_drop_schema_part(std::string schema_)
|
||||
: query_part(sql::dialect_token::Schema)
|
||||
, schema_( std::move( schema_ ) ) {}
|
||||
, schema_(std::move(schema_)) {
|
||||
}
|
||||
|
||||
const std::string &query_drop_schema_part::schema() const {
|
||||
return schema_;
|
||||
|
|
|
|||
|
|
@ -49,13 +49,6 @@ query_select_intermediate query::select(const std::vector<std::string> &column_n
|
|||
return select(columns);
|
||||
}
|
||||
|
||||
query_select_intermediate query::select(std::vector<table_column> columns, const std::initializer_list<table_column> additional_columns) {
|
||||
for (const auto &col : additional_columns) {
|
||||
columns.push_back(col);
|
||||
}
|
||||
return query_select_intermediate{columns};
|
||||
}
|
||||
|
||||
query_insert_intermediate query::insert() {
|
||||
return {};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -179,12 +179,35 @@ void query_compiler::visit(internal::query_where_part &part) {
|
|||
}
|
||||
|
||||
void query_compiler::visit(internal::query_group_by_part &part) {
|
||||
query_.sql += " " + dialect_->group_by() + " " + prepare_identifier(*dialect_, part.column());
|
||||
query_.sql += " " + dialect_->group_by() + " ";
|
||||
if (part.columns().size() < 2) {
|
||||
for (const auto &col: part.columns()) {
|
||||
query_.sql.append(dialect_->prepare_identifier_string(col.canonical_name()));
|
||||
}
|
||||
} else {
|
||||
auto it = part.columns().begin();
|
||||
query_.sql.append(dialect_->prepare_identifier_string((it++)->canonical_name()));
|
||||
for (; it != part.columns().end(); ++it) {
|
||||
query_.sql.append(", ");
|
||||
query_.sql.append(dialect_->prepare_identifier_string(it->canonical_name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_order_by_part &part) {
|
||||
query_.sql += " " + dialect_->order_by() +
|
||||
" " + prepare_criteria(*dialect_, part.column());
|
||||
query_.sql += " " + dialect_->order_by() + " ";
|
||||
if (part.columns().size() < 2) {
|
||||
for (const auto &col: part.columns()) {
|
||||
query_.sql.append(dialect_->prepare_identifier_string(col.canonical_name()));
|
||||
}
|
||||
} else {
|
||||
auto it = part.columns().begin();
|
||||
query_.sql.append(dialect_->prepare_identifier_string((it++)->canonical_name()));
|
||||
for (; it != part.columns().end(); ++it) {
|
||||
query_.sql.append(", ");
|
||||
query_.sql.append(dialect_->prepare_identifier_string(it->canonical_name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void query_compiler::visit(internal::query_order_by_asc_part &/*order_by_asc_part*/) {
|
||||
|
|
|
|||
|
|
@ -120,7 +120,6 @@ TEST_CASE_METHOD(QueryFixture, "Test all data types for record", "[query][record
|
|||
REQUIRE(str == row.at<std::string>("val_string"));
|
||||
REQUIRE(varchar == row.at<std::string>("val_varchar"));
|
||||
REQUIRE(md == row.at<date_type_t>("val_date"));
|
||||
const auto mtres = row.at<time_type_t>("val_time");
|
||||
REQUIRE(mt == row.at<time_type_t>("val_time"));
|
||||
REQUIRE(bin == row.at<blob_type_t>("val_blob"));
|
||||
}
|
||||
|
|
@ -510,7 +509,7 @@ TEST_CASE_METHOD(QueryFixture, "Execute select statement with group by and order
|
|||
|
||||
auto result = query::select({count("age").as("age_count"), "age"})
|
||||
.from("person")
|
||||
.group_by("age")
|
||||
.group_by({"age"})
|
||||
.order_by("age_count").desc()
|
||||
.fetch_all(db);
|
||||
REQUIRE(result.is_ok());
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@
|
|||
#include "models/flight.hpp"
|
||||
#include "models/person.hpp"
|
||||
#include "models/recipe.hpp"
|
||||
#include "models/shipment.hpp"
|
||||
|
||||
#include "../test/utils/record_printer.hpp"
|
||||
|
||||
using namespace matador::object;
|
||||
using namespace matador::query;
|
||||
|
|
@ -23,6 +26,8 @@ META_TABLE(ingredients, INGREDIENT, id, name);
|
|||
META_TABLE(recipe_ingredients, RECIPE_INGREDIENT, recipe_id, ingredient_id);
|
||||
META_TABLE(airplanes, AIRPLANE, id, brand, model);
|
||||
META_TABLE(flights, FLIGHT, id, airplane_id, pilot_name);
|
||||
META_TABLE(shipments, SHIPMENT, id, tracking_number)
|
||||
META_TABLE(packages, PACKAGE, id, weight, shipment)
|
||||
|
||||
TEST_CASE_METHOD(QueryFixture, "Create table with foreign key relation", "[query][foreign][relation]") {
|
||||
auto result = repo.attach<airplane>("airplane")
|
||||
|
|
@ -606,3 +611,106 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with many to many relationship"
|
|||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
void print(std::ostream& out, const record& row) {
|
||||
for (const auto& f : row) {
|
||||
out << f << " ";
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(QueryFixture, "Test load entity with eager has many relation", "[query][has_many][eager]") {
|
||||
auto result = repo.attach<package>("packages")
|
||||
.and_then( [this] { return repo.attach<shipment>("shipments"); } );
|
||||
// auto result = repo.attach<shipment>("shipments")
|
||||
// .and_then( [this] { return repo.attach<package>("packages"); } );
|
||||
REQUIRE(result.is_ok());
|
||||
tables_to_drop.emplace("shipments");
|
||||
tables_to_drop.emplace("packages");
|
||||
|
||||
result = repo.create(db);
|
||||
REQUIRE(result.is_ok());
|
||||
|
||||
const std::vector shipments {
|
||||
object_ptr{new shipment{1, "4711"}},
|
||||
object_ptr{new shipment{2, "0815"}}
|
||||
};
|
||||
|
||||
using namespace matador::query::meta;
|
||||
|
||||
for (const auto &sh: shipments) {
|
||||
auto res = query::insert()
|
||||
.into(SHIPMENT, SHIPMENT)
|
||||
.values(*sh)
|
||||
.execute(db);
|
||||
REQUIRE(res.is_ok());
|
||||
REQUIRE(*res == 1);
|
||||
}
|
||||
|
||||
auto count = query::select({count_all()})
|
||||
.from(SHIPMENT)
|
||||
.fetch_value<int>(db);
|
||||
REQUIRE(count.is_ok());
|
||||
REQUIRE(*count == 2);
|
||||
|
||||
std::vector packages {
|
||||
object_ptr{new package{3, 15.4, shipments.at(0)}},
|
||||
object_ptr{new package{4, 1.3, shipments.at(0)}},
|
||||
object_ptr{new package{5, 30.9, shipments.at(1)}},
|
||||
object_ptr{new package{6, 22.8, shipments.at(1)}},
|
||||
object_ptr{new package{7, 17.2, shipments.at(1)}}
|
||||
};
|
||||
|
||||
for (const auto &pkg: packages) {
|
||||
auto res = query::insert()
|
||||
.into(PACKAGE, PACKAGE)
|
||||
.values(*pkg)
|
||||
.execute(db);
|
||||
REQUIRE(res.is_ok());
|
||||
REQUIRE(*res == 1);
|
||||
}
|
||||
|
||||
count = query::select({count_all()})
|
||||
.from(PACKAGE)
|
||||
.fetch_value<int>(db);
|
||||
REQUIRE(count.is_ok());
|
||||
REQUIRE(*count == 5);
|
||||
|
||||
auto pkgs = query::select({PACKAGE.id, PACKAGE.weight, PACKAGE.shipment, SHIPMENT.tracking_number})
|
||||
.from(PACKAGE)
|
||||
.join_left(SHIPMENT)
|
||||
.on( PACKAGE.shipment == SHIPMENT.id )
|
||||
.where( PACKAGE.weight > 20.0 && SHIPMENT.tracking_number == "0815" )
|
||||
.group_by({PACKAGE.id, SHIPMENT.tracking_number})
|
||||
.order_by(PACKAGE.weight).asc()
|
||||
.limit( 5 )
|
||||
.offset( 0 )
|
||||
.fetch_all(db);
|
||||
|
||||
REQUIRE(pkgs.is_ok());
|
||||
|
||||
record_printer printer(std::cout);
|
||||
printer.print(*pkgs);
|
||||
|
||||
auto shipment_records = query::select({SHIPMENT.tracking_number, SHIPMENT.id, PACKAGE.weight, PACKAGE.weight})
|
||||
.from(SHIPMENT)
|
||||
.join_left(PACKAGE)
|
||||
.on( SHIPMENT.id == PACKAGE.shipment )
|
||||
.fetch_all(db);
|
||||
|
||||
REQUIRE(shipment_records.is_ok());
|
||||
|
||||
printer.print(*shipment_records);
|
||||
|
||||
auto shipment_result = query::select({SHIPMENT.id, SHIPMENT.tracking_number, PACKAGE.id, PACKAGE.weight, PACKAGE.shipment})
|
||||
.from(SHIPMENT)
|
||||
.join_left(PACKAGE)
|
||||
.on( SHIPMENT.id == PACKAGE.shipment )
|
||||
.fetch_all<shipment>(db);
|
||||
|
||||
REQUIRE(shipment_result.is_ok());
|
||||
|
||||
std::cout << "\n";
|
||||
for (const auto &s : *shipment_result) {
|
||||
std::cout << s.id << " " << s.tracking_number << " packages: " << s.packages.size() << std::endl;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef MATADOR_SHIPMENT_HPP
|
||||
#define MATADOR_SHIPMENT_HPP
|
||||
|
||||
#include "matador/utils/access.hpp"
|
||||
#include "matador/utils/foreign_attributes.hpp"
|
||||
|
||||
#include "matador/object/collection.hpp"
|
||||
#include "matador/object/object_ptr.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace matador::test {
|
||||
struct package;
|
||||
struct shipment {
|
||||
long id{};
|
||||
std::string tracking_number;
|
||||
object::collection<object::object_ptr<package>> packages{};
|
||||
|
||||
template<typename Operator>
|
||||
void process(Operator &op) {
|
||||
namespace field = matador::access;
|
||||
field::primary_key(op, "id", id);
|
||||
field::attribute(op, "tracking_number", tracking_number, 255);
|
||||
field::has_many(op, "packages", packages, "shipment_id", utils::CascadeAllFetchEager);
|
||||
}
|
||||
};
|
||||
|
||||
struct package {
|
||||
long id{};
|
||||
double weight{};
|
||||
object::object_ptr<shipment> delivery;
|
||||
|
||||
template<typename Operator>
|
||||
void process(Operator &op) {
|
||||
namespace field = matador::access;
|
||||
field::primary_key(op, "id", id);
|
||||
field::attribute(op, "weight", weight);
|
||||
field::belongs_to(op, "shipment", delivery, utils::CascadeAllFetchLazy);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif //MATADOR_SHIPMENT_HPP
|
||||
|
|
@ -72,7 +72,7 @@ void test_result_reader::read_value(const char * /*id*/, const size_t /*index*/,
|
|||
value = {12, 34, 56, 123456};
|
||||
}
|
||||
|
||||
void test_result_reader::read_value(const char *id, size_t index, utils::timestamp_type_t &value) {
|
||||
void test_result_reader::read_value(const char * /*id*/, size_t /*index*/, utils::timestamp_type_t &value) {
|
||||
value = utils::timestamp_type_t();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
#include "record_printer.hpp"
|
||||
|
||||
#include "matador/utils/basic_types.hpp"
|
||||
|
||||
#include "matador/sql/record.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
namespace matador::test {
|
||||
record_printer::record_printer(std::ostream &os)
|
||||
: os_(os) {
|
||||
type_widths_ = {
|
||||
{utils::basic_type::Int8, 4},
|
||||
{utils::basic_type::Int16, 6},
|
||||
{utils::basic_type::Int32, 11},
|
||||
{utils::basic_type::Int64, 20},
|
||||
{utils::basic_type::UInt8, 4},
|
||||
{utils::basic_type::UInt16, 6},
|
||||
{utils::basic_type::UInt32, 11},
|
||||
{utils::basic_type::UInt64, 20},
|
||||
{utils::basic_type::Float, 12},
|
||||
{utils::basic_type::Double, 15},
|
||||
{utils::basic_type::Boolean, 6},
|
||||
{utils::basic_type::Varchar, 20},
|
||||
{utils::basic_type::Text, 30},
|
||||
{utils::basic_type::Date, 12},
|
||||
{utils::basic_type::DateTime, 20},
|
||||
{utils::basic_type::Time, 10},
|
||||
{utils::basic_type::Blob, 10},
|
||||
{utils::basic_type::Null, 6}
|
||||
};
|
||||
}
|
||||
|
||||
void record_printer::print_header(const sql::record &rec) const {
|
||||
for (const auto &f_ref: rec.columns()) {
|
||||
const auto &f = f_ref.get();
|
||||
os_ << std::left << std::setw(width(f)) << f.name() << " ";
|
||||
}
|
||||
os_ << "\n";
|
||||
|
||||
for (const auto &f_ref: rec.columns()) {
|
||||
const auto &f = f_ref.get();
|
||||
os_ << std::string(width(f), '-') << " ";
|
||||
}
|
||||
os_ << "\n";
|
||||
}
|
||||
|
||||
void record_printer::print(const sql::record &rec) const {
|
||||
for (const auto &f_ref: rec.columns()) {
|
||||
const auto &f = f_ref.get();
|
||||
os_ << std::left << std::setw(width(f)) << f.str() << " ";
|
||||
}
|
||||
os_ << "\n";
|
||||
}
|
||||
|
||||
int record_printer::width(const sql::field &f) {
|
||||
// If it's a varchar/string and has a defined size, use it if it's reasonable,
|
||||
// otherwise fall back to type defaults.
|
||||
if ((f.is_varchar() || f.is_string()) && f.size() > 0 && f.size() < 100) {
|
||||
return std::max(f.name().length(), f.size());
|
||||
}
|
||||
|
||||
// Find the default width for type
|
||||
// Note: field class doesn't expose basic_type directly but we can use value().type()
|
||||
// if we had access. For now we use name length as minimum.
|
||||
constexpr size_t w = 15;
|
||||
// In a real implementation we would probe the field's underlying type.
|
||||
|
||||
return std::max(f.name().length(), w);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef MATADOR_RECORD_PRINTER_HPP
|
||||
#define MATADOR_RECORD_PRINTER_HPP
|
||||
|
||||
#include "matador/sql/record.hpp"
|
||||
|
||||
#include <iosfwd>
|
||||
#include <map>
|
||||
|
||||
namespace matador::sql {
|
||||
class field;
|
||||
class record;
|
||||
}
|
||||
|
||||
namespace matador::test {
|
||||
class record_printer final {
|
||||
public:
|
||||
explicit record_printer(std::ostream &os);
|
||||
|
||||
void print_header(const sql::record &rec) const;
|
||||
void print(const sql::record &rec) const;
|
||||
|
||||
template < class Type, template <typename ...> class ContainerType >
|
||||
void print(ContainerType<Type> &records) const {
|
||||
bool first = true;
|
||||
for (const auto &rec: records) {
|
||||
if (first) {
|
||||
print_header(rec);
|
||||
first = false;
|
||||
}
|
||||
print(rec);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
[[nodiscard]] static int width(const sql::field &f) ;
|
||||
|
||||
private:
|
||||
std::ostream &os_;
|
||||
std::map<utils::basic_type, int> type_widths_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //MATADOR_RECORD_PRINTER_HPP
|
||||
371
todo.md
371
todo.md
|
|
@ -1,369 +1,36 @@
|
|||
# Todo
|
||||
|
||||
- move `object_definition` and `attribute_definition` to `table` and `column` in query
|
||||
and add `contraint` class
|
||||
- replace mk_column with builder style (see `query/builder.hpp`)
|
||||
- fix corresponding tests
|
||||
- enhance query helper macro to look like the `book` class below
|
||||
- add `aliasable_table`(see class below)
|
||||
- add `as()` methode to table class
|
||||
- move `sql_function_t` to own header in namespace `matador::sql`
|
||||
- move `prepare_*` methods from `dialect` to `query_compiler`
|
||||
- add `session_insert_builder` and `session_update_builder` (returning multiple statements)
|
||||
- finish `attribued_definition` (also in `repository` class -> dependencies)
|
||||
- fix compile errors
|
||||
- finish fetch eager has-many/belongs-to relations
|
||||
- implement lazy loading
|
||||
- implement polymorphic class hierarchies
|
||||
- finish `schema` and `schema_repository` classes (move add/drop from `session` to `schema`)
|
||||
- finish `schema_repository` classes (move add/drop from `session` to `schema`)
|
||||
- implement a flag class for enumerations
|
||||
|
||||
## book class
|
||||
```cpp
|
||||
class Book : public matador::object::typed_object<Book> {
|
||||
public:
|
||||
using typed_object::as;
|
||||
|
||||
Book() : typed_object("book") {}
|
||||
explicit Book(std::string alias)
|
||||
: typed_object("book", std::move(alias)) {}
|
||||
__Proposal for polymorphic classes:__
|
||||
|
||||
const matador::object::attribute id = create_attribute("id", *this);
|
||||
const matador::object::attribute title = create_attribute("title", *this);
|
||||
const matador::object::attribute year = create_attribute("year", *this);
|
||||
};
|
||||
```
|
||||
object_ptr::as<Type> does the following checks;
|
||||
|
||||
## aliasable_table
|
||||
```cpp
|
||||
class object;
|
||||
1. The requested type has a super class
|
||||
2. Super class has a discriminator column defined
|
||||
3. Super class has a discriminator value defined
|
||||
4. Discriminator value is mapped to the requested type
|
||||
|
||||
class attribute {
|
||||
public:
|
||||
explicit attribute(std::string name); // NOLINT(*-explicit-constructor)
|
||||
|
||||
attribute(const attribute&) = default;
|
||||
attribute& operator=(const attribute&) = default;
|
||||
attribute(attribute&&) noexcept = default;
|
||||
attribute& operator=(attribute&&) noexcept = default;
|
||||
|
||||
attribute() = default;
|
||||
attribute(std::string name,
|
||||
utils::basic_type type,
|
||||
const utils::field_attributes& attr = utils::null_attributes,
|
||||
utils::null_option_type null_opt = utils::null_option_type::NotNull);
|
||||
|
||||
[[nodiscard]] const std::string& name() const { return name_; }
|
||||
void name(const std::string& n);
|
||||
[[nodiscard]] const utils::field_attributes& attributes() const;
|
||||
[[nodiscard]] utils::field_attributes& attributes();
|
||||
|
||||
[[nodiscard]] bool is_nullable() const;
|
||||
[[nodiscard]] utils::basic_type type() const;
|
||||
|
||||
[[nodiscard]] bool is_integer() const;
|
||||
[[nodiscard]] bool is_floating_point() const;
|
||||
[[nodiscard]] bool is_bool() const;
|
||||
[[nodiscard]] bool is_string() const;
|
||||
[[nodiscard]] bool is_varchar() const;
|
||||
[[nodiscard]] bool is_date() const;
|
||||
[[nodiscard]] bool is_time() const;
|
||||
[[nodiscard]] bool is_blob() const;
|
||||
[[nodiscard]] bool is_null() const;
|
||||
|
||||
private:
|
||||
friend class object;
|
||||
|
||||
std::string name_;
|
||||
std::string alias_;
|
||||
utils::basic_type type_{utils::basic_type::type_null};
|
||||
utils::field_attributes attributes_;
|
||||
utils::null_option_type null_option_type_{utils::null_option_type::NotNull};
|
||||
|
||||
object* parent_{nullptr};
|
||||
};
|
||||
|
||||
class constraint {
|
||||
public:
|
||||
constraint() = default;
|
||||
|
||||
explicit constraint(std::string name) : name_(std::move(name)) {}
|
||||
[[nodiscard]] const std::string& name() const { return name_; }
|
||||
|
||||
private:
|
||||
friend class object;
|
||||
|
||||
std::string name_;
|
||||
std::string attribute_name_;
|
||||
utils::constraints options_{utils::constraints::None};
|
||||
|
||||
object* parent_{nullptr};
|
||||
};
|
||||
|
||||
class object {
|
||||
public:
|
||||
using iterator = std::vector<attribute>::iterator;
|
||||
using const_iterator = std::vector<attribute>::const_iterator;
|
||||
|
||||
explicit object(std::string name, std::string alias = "");
|
||||
|
||||
void add_attribute(attribute attr) {
|
||||
auto &ref = attributes_.emplace_back(std::move(attr));
|
||||
ref.parent_ = this;
|
||||
}
|
||||
|
||||
static const attribute& create_attribute(std::string name, object& obj) {
|
||||
attribute attr{std::move(name)};
|
||||
attr.parent_ = &obj;
|
||||
return obj.attributes_.emplace_back(std::move(attr));
|
||||
}
|
||||
|
||||
iterator begin() { return attributes_.begin(); }
|
||||
iterator end() { return attributes_.end(); }
|
||||
|
||||
[[nodiscard]] bool empty() const { return attributes_.empty(); }
|
||||
[[nodiscard]] size_t size() const { return attributes_.size(); }
|
||||
|
||||
[[nodiscard]] const std::string& name() const { return name_; }
|
||||
[[nodiscard]] const std::string& alias() const { return alias_; }
|
||||
[[nodiscard]] const std::vector<attribute>& columns() const { return attributes_; }
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
std::string alias_;
|
||||
|
||||
std::vector<attribute> attributes_;
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
class typed_object : public object {
|
||||
public:
|
||||
using object::object;
|
||||
|
||||
Type as(std::string alias) { return Type{std::move(alias)}; }
|
||||
};
|
||||
```
|
||||
If all checks succeed, the requested is fetched from the database.
|
||||
|
||||
```cpp
|
||||
struct column_builder {
|
||||
explicit column_builder(std::string column_name)
|
||||
: column_name( std::move(column_name) ) {
|
||||
}
|
||||
|
||||
column_builder& not_null() {
|
||||
return *this;
|
||||
}
|
||||
|
||||
column_builder& primary_key() {
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator matador::sql::column() const {
|
||||
return matador::sql::column{column_name};
|
||||
}
|
||||
|
||||
std::string column_name;
|
||||
};
|
||||
|
||||
column_builder column(std::string name) {
|
||||
return column_builder(std::move(name));
|
||||
}
|
||||
|
||||
namespace matador::sql {
|
||||
struct constraint {
|
||||
std::string name;
|
||||
};
|
||||
}
|
||||
|
||||
struct constraint_builder {
|
||||
constraint_builder& constraint(std::string name) {
|
||||
constraint_name = std::move(name);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constraint_builder& primary_key(std::string name) {
|
||||
pk_column_name = std::move(name);
|
||||
return *this;
|
||||
}
|
||||
constraint_builder& foreign_key(std::string name) {
|
||||
fk_column_name = std::move(name);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constraint_builder& references(std::string table, std::string column) {
|
||||
this->table_name = std::move(table);
|
||||
this->column_name = std::move(column);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator matador::sql::constraint() const {
|
||||
return matador::sql::constraint{constraint_name};
|
||||
}
|
||||
|
||||
std::string constraint_name;
|
||||
std::string pk_column_name;
|
||||
std::string fk_column_name;
|
||||
std::string table_name;
|
||||
std::string column_name;
|
||||
};
|
||||
|
||||
constraint_builder constraint(std::string name) {
|
||||
constraint_builder builder;
|
||||
return builder.constraint(std::move(name));
|
||||
}
|
||||
void foo(const std::initializer_list<matador::sql::column> columns) {
|
||||
for (const auto& column : columns) {
|
||||
std::cout << column.name() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void foo(const std::vector<matador::sql::column>& columns) {
|
||||
for (const auto& column : columns) {
|
||||
std::cout << column.name() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
std::string column_prefix(matador::sql::aliasable_table<Type> *tab) {
|
||||
if (!tab || tab->empty()) {
|
||||
return "";
|
||||
}
|
||||
if (!tab->alias().empty()) {
|
||||
return tab->alias();
|
||||
}
|
||||
return tab->name();
|
||||
}
|
||||
struct table_builder {
|
||||
explicit table_builder(std::string name)
|
||||
: table_name( std::move(name) ) {}
|
||||
|
||||
table_builder& as(std::string table_alias) {
|
||||
this->alias = std::move(table_alias);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator matador::query::query_table() const {
|
||||
return {matador::sql::table{table_name}, alias};
|
||||
}
|
||||
std::string table_name;
|
||||
std::string alias;
|
||||
};
|
||||
|
||||
table_builder table(std::string name) {
|
||||
return table_builder(std::move(name));
|
||||
}
|
||||
|
||||
class Book : public matador::sql::aliasable_table<Book> {
|
||||
public:
|
||||
using aliasable_table::as;
|
||||
|
||||
Book() : aliasable_table("book", "") {}
|
||||
|
||||
private:
|
||||
friend class aliasable_table;
|
||||
|
||||
explicit Book(std::string alias)
|
||||
: aliasable_table("book", std::move(alias)) {}
|
||||
|
||||
public:
|
||||
matador::sql::column id = create_column("id", *this);
|
||||
matador::sql::column title = create_column("title", *this);
|
||||
matador::sql::column year = create_column("year", *this);
|
||||
};
|
||||
|
||||
struct base_node {
|
||||
base_node() = delete;
|
||||
base_node(std::string name)
|
||||
: name(std::move(name)) {}
|
||||
virtual ~base_node() = default;
|
||||
|
||||
std::string name;
|
||||
};
|
||||
template < typename Type>
|
||||
struct node final {
|
||||
virtual ~node() = default;
|
||||
|
||||
Type type;
|
||||
};
|
||||
|
||||
template < template<typename> typename NodeType = node, typename BaseType = base_node >
|
||||
struct repository {
|
||||
template<typename Type>
|
||||
NodeType<Type> find(std::string name);
|
||||
|
||||
std::unordered_map<std::string, BaseType> nodes;
|
||||
};
|
||||
|
||||
struct base_schema_node : base_node {
|
||||
base_schema_node() = delete;
|
||||
base_schema_node(std::string name, std::string table)
|
||||
: base_node(std::move(name)), table_name(std::move(table)) {}
|
||||
|
||||
std::string table_name;
|
||||
};
|
||||
|
||||
template < typename Type >
|
||||
struct schema_node final : base_schema_node {
|
||||
schema_node() = default;
|
||||
schema_node(std::string name, std::string table)
|
||||
: base_schema_node(std::move(name), std::move(table)) {}
|
||||
|
||||
Type type;
|
||||
};
|
||||
|
||||
int main() {
|
||||
repository repo1;
|
||||
repository<schema_node, base_schema_node> repo;
|
||||
|
||||
Book BOOK;
|
||||
|
||||
const auto b = BOOK.as("b");
|
||||
|
||||
foo(b);
|
||||
foo(BOOK);
|
||||
foo({
|
||||
BOOK.id,
|
||||
b.title,
|
||||
column("col1").primary_key(),
|
||||
column("col2").not_null()
|
||||
});
|
||||
matador::sql::schema schema("test");
|
||||
|
||||
schema.add_table(BOOK.as_table());
|
||||
// query::create()
|
||||
// .table(BOOK)
|
||||
// .columns({
|
||||
// BOOK.id,
|
||||
// BOOK.title,
|
||||
// column("year"),
|
||||
// column("author_id")
|
||||
// })
|
||||
// .constraints({
|
||||
// constraint( "PK" ).primary_key("id"),
|
||||
// constraint( "FK" ).foreign_key("author_id").references("author", "id")
|
||||
// });
|
||||
//
|
||||
// query::create()
|
||||
// .table("book", {
|
||||
// column("id"),
|
||||
// column("title"),
|
||||
// column("year"),
|
||||
// column("author_id")
|
||||
// }, {
|
||||
// constraint( "PK" ).primary_key("id"),
|
||||
// constraint( "FK" ).foreign_key("author_id").references("author", "id")
|
||||
// });
|
||||
//
|
||||
// matador::query::query_table book = table("book").as("b");
|
||||
//
|
||||
// query::select({
|
||||
// column(book.column("id")),
|
||||
// column(book.column("title"))
|
||||
// })
|
||||
// .from(book);
|
||||
//
|
||||
// query::insert()
|
||||
// .into(b, {b.title, b.year})
|
||||
// .values({"title", 2021});
|
||||
schema.attach<jobs::Payload>("payloads", make_polymorph("type"));
|
||||
schema.attach<jobs::Payload, jobs::IdPayload>("id_list_payloads", make_polymorph_type("IdPayload"));
|
||||
schema.attach<jobs::Payload, jobs::IdListPayload>("id_payloads", make_polymorph_type("IdListPayload"));
|
||||
object::object_ptr<jobs::Payload> payload;
|
||||
auto result = payload.as<jobs::IdPayload>();
|
||||
if (result.is_ok()) {
|
||||
const auto& is_payload = result.value();
|
||||
// Use requested type
|
||||
id_payload->id = 1;
|
||||
}
|
||||
payload.is_polymorphic();
|
||||
payload.is_polymorphic_type<jobs::IdPayload>();
|
||||
```
|
||||
Loading…
Reference in New Issue