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/convert.hpp"
|
||||||
#include "matador/utils/value.hpp"
|
#include "matador/utils/value.hpp"
|
||||||
|
#include "matador/utils/string.hpp"
|
||||||
|
|
||||||
namespace matador::backends::postgres {
|
namespace matador::backends::postgres {
|
||||||
postgres_result_reader::postgres_result_reader(PGresult *result)
|
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) {
|
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) {
|
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) {
|
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) {
|
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 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/StatementCacheTest.cpp
|
||||||
../../../test/backends/StatementTest.cpp
|
../../../test/backends/StatementTest.cpp
|
||||||
../../../test/backends/TypeTraitsTest.cpp
|
../../../test/backends/TypeTraitsTest.cpp
|
||||||
|
../../../test/utils/record_printer.hpp
|
||||||
|
../../../test/utils/record_printer.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIBRARY_TEST_TARGET PostgresTests)
|
set(LIBRARY_TEST_TARGET PostgresTests)
|
||||||
|
|
|
||||||
215
demo/main.cpp
215
demo/main.cpp
|
|
@ -1,9 +1,11 @@
|
||||||
#include "matador/sql/connection.hpp"
|
#include "matador/sql/connection.hpp"
|
||||||
|
#include "matador/sql/connection_pool.hpp"
|
||||||
|
|
||||||
#include "matador/query/criteria.hpp"
|
#include "matador/query/criteria.hpp"
|
||||||
#include "matador/query/query.hpp"
|
#include "matador/query/query.hpp"
|
||||||
#include "matador/query/table_column.hpp"
|
#include "matador/query/table_column.hpp"
|
||||||
#include "matador/query/meta_table_macro.hpp"
|
#include "matador/query/meta_table_macro.hpp"
|
||||||
|
#include "matador/query/schema.hpp"
|
||||||
|
|
||||||
#include "matador/object/object_ptr.hpp"
|
#include "matador/object/object_ptr.hpp"
|
||||||
#include "matador/object/repository.hpp"
|
#include "matador/object/repository.hpp"
|
||||||
|
|
@ -23,14 +25,14 @@ struct author {
|
||||||
bool distinguished{false};
|
bool distinguished{false};
|
||||||
|
|
||||||
template<typename Operator>
|
template<typename Operator>
|
||||||
void process( Operator& op ) {
|
void process(Operator &op) {
|
||||||
namespace field = matador::access;
|
namespace field = matador::access;
|
||||||
field::primary_key( op, "id", id );
|
field::primary_key(op, "id", id);
|
||||||
field::attribute( op, "first_name", first_name, 63 );
|
field::attribute(op, "first_name", first_name, 63);
|
||||||
field::attribute( op, "last_name", last_name, 63 );
|
field::attribute(op, "last_name", last_name, 63);
|
||||||
field::attribute( op, "date_of_birth", date_of_birth, 31 );
|
field::attribute(op, "date_of_birth", date_of_birth, 31);
|
||||||
field::attribute( op, "year_of_birth", year_of_birth );
|
field::attribute(op, "year_of_birth", year_of_birth);
|
||||||
field::attribute( op, "distinguished", distinguished );
|
field::attribute(op, "distinguished", distinguished);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -41,12 +43,12 @@ struct book {
|
||||||
unsigned short published_in{};
|
unsigned short published_in{};
|
||||||
|
|
||||||
template<typename Operator>
|
template<typename Operator>
|
||||||
void process( Operator& op ) {
|
void process(Operator &op) {
|
||||||
namespace field = matador::access;
|
namespace field = matador::access;
|
||||||
field::primary_key( op, "id", id );
|
field::primary_key(op, "id", id);
|
||||||
field::attribute( op, "title", title, 511 );
|
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 );
|
field::attribute(op, "published_in", published_in);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -54,9 +56,9 @@ struct payload {
|
||||||
unsigned int id{};
|
unsigned int id{};
|
||||||
|
|
||||||
template<typename Operator>
|
template<typename Operator>
|
||||||
void process( Operator& op ) {
|
void process(Operator &op) {
|
||||||
namespace field = matador::access;
|
namespace field = matador::access;
|
||||||
field::primary_key( op, "id", id );
|
field::primary_key(op, "id", id);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -82,14 +84,14 @@ struct job {
|
||||||
job_mode mode;
|
job_mode mode;
|
||||||
|
|
||||||
template<typename Operator>
|
template<typename Operator>
|
||||||
void process( Operator& op ) {
|
void process(Operator &op) {
|
||||||
namespace field = matador::access;
|
namespace field = matador::access;
|
||||||
field::primary_key( op, "id", id );
|
field::primary_key(op, "id", id);
|
||||||
field::belongs_to( op, "payload", data, matador::utils::CascadeNoneFetchLazy );
|
field::belongs_to(op, "payload", data, matador::utils::CascadeNoneFetchLazy);
|
||||||
field::attribute( op, "type", type, 511 );
|
field::attribute(op, "type", type, 511);
|
||||||
field::attribute( op, "description", description, 511 );
|
field::attribute(op, "description", description, 511);
|
||||||
field::attribute( op, "state", state );
|
field::attribute(op, "state", state);
|
||||||
field::attribute( op, "mode", mode );
|
field::attribute(op, "mode", mode);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -99,12 +101,12 @@ static const matador::utils::enum_mapper<job::job_state> job_state_enum({
|
||||||
{job::job_state::Succeeded, "Succeeded"},
|
{job::job_state::Succeeded, "Succeeded"},
|
||||||
{job::job_state::Failed, "Failed"},
|
{job::job_state::Failed, "Failed"},
|
||||||
{job::job_state::Canceled, "Canceled"}
|
{job::job_state::Canceled, "Canceled"}
|
||||||
});
|
});
|
||||||
|
|
||||||
static const matador::utils::enum_mapper<job::job_mode> job_mode_enum({
|
static const matador::utils::enum_mapper<job::job_mode> job_mode_enum({
|
||||||
{job::job_mode::Foreground, "Foreground"},
|
{job::job_mode::Foreground, "Foreground"},
|
||||||
{job::job_mode::Background, "Background"}
|
{job::job_mode::Background, "Background"}
|
||||||
});
|
});
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct matador::utils::data_type_traits<job::job_state, void> {
|
struct matador::utils::data_type_traits<job::job_state, void> {
|
||||||
|
|
@ -125,7 +127,7 @@ struct matador::utils::data_type_traits<job::job_state, void> {
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct matador::utils::data_type_traits<job::job_mode, void> {
|
struct matador::utils::data_type_traits<job::job_mode, void> {
|
||||||
static basic_type type( const std::size_t size) { return data_type_traits<std::string>::type(size); }
|
static basic_type type(const std::size_t size) { return data_type_traits<std::string>::type(size); }
|
||||||
|
|
||||||
static void read_value(attribute_reader &reader, const char *id, const size_t index, job::job_mode &value) {
|
static void read_value(attribute_reader &reader, const char *id, const size_t index, job::job_mode &value) {
|
||||||
std::string enum_string;
|
std::string enum_string;
|
||||||
|
|
@ -146,67 +148,72 @@ META_TABLE(books, BOOK, id, author_id, title, published_in)
|
||||||
|
|
||||||
META_TABLE(job, JOB, id, payload, type, description, state, mode)
|
META_TABLE(job, JOB, id, payload, type, description, state, mode)
|
||||||
|
|
||||||
META_TABLE(payload, PAYLOAD, id )
|
META_TABLE(payload, PAYLOAD, id)
|
||||||
|
|
||||||
META_TABLE(temporary_table, TEMPORARY_TABLE, id );
|
META_TABLE(temporary_table, TEMPORARY_TABLE, id);
|
||||||
|
|
||||||
META_TABLE(customer, CUSTOMER, id, name, email, address)
|
META_TABLE(customer, CUSTOMER, id, name, email, address)
|
||||||
|
|
||||||
META_TABLE(product, PRODUCT, id, title, description, price, category)
|
META_TABLE(product, PRODUCT, id, title, description, price, category)
|
||||||
|
|
||||||
META_TABLE(category, CATEGORY, id, title, description)
|
META_TABLE(category, CATEGORY, id, title, description)
|
||||||
|
|
||||||
META_TABLE(cart, CART, id, items, owner)
|
META_TABLE(cart, CART, id, items, owner)
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
using namespace matador::sql;
|
using namespace matador::sql;
|
||||||
using namespace matador::object;
|
using namespace matador::object;
|
||||||
using namespace matador::utils;
|
using namespace matador::utils;
|
||||||
|
using namespace matador::query;
|
||||||
using namespace matador::query::meta;
|
using namespace matador::query::meta;
|
||||||
|
|
||||||
const std::string env_var{"MATADOR_BACKENDS_PATH"};
|
const std::string env_var{"MATADOR_BACKENDS_PATH"};
|
||||||
|
|
||||||
std::string dns{"sqlite://demo.db"};
|
connection_pool pool("postgres://test:test123!@127.0.0.1:5432/matador", 4);
|
||||||
repository s( "main" );
|
|
||||||
auto result = s.attach<author>( "authors" ).and_then( [&s] {
|
|
||||||
return s.attach<book>( "books" );
|
|
||||||
} );
|
|
||||||
// s.attach<book>( "books" );
|
|
||||||
|
|
||||||
connection c( dns );
|
schema s("");
|
||||||
result = c.open();
|
auto result = s.attach<author>("authors").and_then([&s] {
|
||||||
// s.create( c );
|
return s.attach<book>("books");
|
||||||
//
|
});
|
||||||
// auto create_authors_sql = c.query( s )
|
|
||||||
// .create()
|
const auto c = pool.acquire();
|
||||||
// .table<author>( qh::authors )
|
result = s.create(*c);
|
||||||
// .execute();
|
if (!result) {
|
||||||
//
|
std::cout << "error: " << result.err() << std::endl;
|
||||||
// c.query( s )
|
return 0;
|
||||||
// .create()
|
}
|
||||||
// .table<book>( qh::books )
|
|
||||||
// .execute();
|
author mc;
|
||||||
//
|
mc.id = 1;
|
||||||
// std::cout << "SQL: " << create_authors_sql << "\n";
|
mc.first_name = "Michael";
|
||||||
//
|
mc.last_name = "Crichton";
|
||||||
// author mc;
|
mc.date_of_birth = "19.8.1954";
|
||||||
// mc.id = 1;
|
mc.year_of_birth = 1954;
|
||||||
// mc.first_name = "Michael";
|
mc.distinguished = true;
|
||||||
// mc.last_name = "Crichton";
|
auto insert_authors_sql = query::insert()
|
||||||
// mc.date_of_birth = "19.8.1954";
|
.into(AUTHOR)
|
||||||
// mc.year_of_birth = 1954;
|
.values(mc)
|
||||||
// mc.distinguished = true;
|
.execute(*c);
|
||||||
// auto insert_authors_sql = c.query( s )
|
|
||||||
// .insert()
|
if (!insert_authors_sql) {
|
||||||
// .into( qh::authors )
|
std::cout << "error: " << insert_authors_sql.err() << std::endl;
|
||||||
// .values( mc )
|
std::ignore = s.drop(*c);
|
||||||
// .execute();
|
return 0;
|
||||||
//
|
}
|
||||||
// std::cout << "SQL: " << insert_authors_sql << "\n";
|
|
||||||
//
|
auto authors_result = query::select(AUTHOR)
|
||||||
// auto result = c.query( s )
|
.from(AUTHOR)
|
||||||
// .select( qh::authors.columns )
|
.fetch_all(*c);
|
||||||
// .from( qh::authors )
|
|
||||||
// .fetch_all();
|
if (!authors_result) {
|
||||||
//
|
std::cout << "error: " << authors_result.err() << std::endl;
|
||||||
// for (const auto& row: result) { std::cout << "Author " << row.at( qh::authors.first_name ) << "\n"; }
|
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 )
|
// auto update_authors_sql = c.query( s )
|
||||||
// .update( qh::authors )
|
// .update( qh::authors )
|
||||||
|
|
@ -236,20 +243,35 @@ int main() {
|
||||||
// .values( {3, "Misery", mc.id, 1984} )
|
// .values( {3, "Misery", mc.id, 1984} )
|
||||||
// .execute();
|
// .execute();
|
||||||
//
|
//
|
||||||
auto select_books_sql = matador::query::query::select( BOOK, {AUTHOR.last_name} )
|
// auto select_books_sql = query::select( BOOK, {AUTHOR.last_name} )
|
||||||
.from( BOOK )
|
auto select_books_sql = query::select({BOOK.id, BOOK.title, BOOK.author_id, BOOK.published_in, AUTHOR.last_name})
|
||||||
.join_left( AUTHOR )
|
.from(BOOK)
|
||||||
.on( BOOK.author_id == AUTHOR.id )
|
.join_left(AUTHOR)
|
||||||
.where( BOOK.published_in < 2008 && AUTHOR.last_name == "King" )
|
.on(BOOK.author_id == AUTHOR.id)
|
||||||
.group_by( BOOK.published_in )
|
.where(BOOK.published_in < 2008 && AUTHOR.last_name == "King")
|
||||||
.order_by( BOOK.title ).asc()
|
.group_by({BOOK.id, AUTHOR.last_name})
|
||||||
.limit( 5 )
|
.order_by(BOOK.title).asc()
|
||||||
.offset( 2 )
|
.limit(5)
|
||||||
.fetch_all(c);
|
.offset(2)
|
||||||
|
.fetch_all(*c);
|
||||||
|
|
||||||
for (const auto& r: *select_books_sql) {
|
if (!select_books_sql) {
|
||||||
std::cout << "R: " << r.at( BOOK.title ) << ", " << r.at( AUTHOR.last_name ) << "\n";
|
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.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
|
// // SELECT book.title, book.id, book.author_id, book.published_in, author.name
|
||||||
// // FROM book
|
// // FROM book
|
||||||
// // INNER JOIN author ON book.author_id = author.id
|
// // INNER JOIN author ON book.author_id = author.id
|
||||||
|
|
@ -266,24 +288,21 @@ int main() {
|
||||||
//
|
//
|
||||||
// std::cout << "SQL: " << drop_authors_sql << "\n";
|
// std::cout << "SQL: " << drop_authors_sql << "\n";
|
||||||
//
|
//
|
||||||
// auto res = c.query( s )
|
auto res = query::select({PAYLOAD.id})
|
||||||
// .select( {qh::payload.id} )
|
.from(PAYLOAD)
|
||||||
// .from( qh::payload )
|
.join_left(JOB)
|
||||||
// .join_left( qh::job )
|
.on(JOB.payload == PAYLOAD.id)
|
||||||
// .on( qh::job.payload == qh::payload.id )
|
.where(
|
||||||
// .where(
|
in(PAYLOAD.id, query::select({JOB.state})
|
||||||
// in( qh::payload.id, c.query( s )
|
.from(JOB)
|
||||||
// .select( {qh::job.state} )
|
.where(JOB.state == job::job_state::Running).compile(c->dialect())
|
||||||
// .from( qh::job )
|
) &&
|
||||||
// .where( qh::job.state == job::job_state::Running )
|
in(PAYLOAD.id, query::select({TEMPORARY_TABLE.id})
|
||||||
// ) &&
|
.from(TEMPORARY_TABLE).compile(c->dialect())
|
||||||
// in( qh::payload.id, c.query( s )
|
)
|
||||||
// .select( {qh::temporary_table.id} )
|
).compile(c->dialect());
|
||||||
// .from( qh::temporary_table ) )
|
|
||||||
// )
|
|
||||||
// .build();
|
|
||||||
// // .fetch_value<unsigned long>();
|
// // .fetch_value<unsigned long>();
|
||||||
// std::cout << "SQL: " << res.sql << "\n";
|
std::cout << "SQL: " << res.sql << "\n";
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -52,6 +52,7 @@ public:
|
||||||
[[nodiscard]] bool is_varchar() const;
|
[[nodiscard]] bool is_varchar() const;
|
||||||
[[nodiscard]] bool is_date() const;
|
[[nodiscard]] bool is_date() const;
|
||||||
[[nodiscard]] bool is_time() const;
|
[[nodiscard]] bool is_time() const;
|
||||||
|
[[nodiscard]] bool is_timestamp() const;
|
||||||
[[nodiscard]] bool is_blob() const;
|
[[nodiscard]] bool is_blob() const;
|
||||||
[[nodiscard]] bool is_null() const;
|
[[nodiscard]] bool is_null() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,11 @@ class collection {
|
||||||
public:
|
public:
|
||||||
using value_type = Type;
|
using value_type = Type;
|
||||||
|
|
||||||
|
void push_back(const Type& value) { data_.push_back(value); }
|
||||||
|
|
||||||
|
[[nodiscard]] size_t size() const { return data_.size(); }
|
||||||
private:
|
private:
|
||||||
std::vector<Type> data_;
|
std::vector<Type> data_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ public:
|
||||||
executable_query constraints(std::initializer_list<object::restriction> constraints);
|
executable_query constraints(std::initializer_list<object::restriction> constraints);
|
||||||
executable_query constraints(const std::list<object::restriction> &restrictions);
|
executable_query constraints(const std::list<object::restriction> &restrictions);
|
||||||
executable_query constraints(std::initializer_list<table_constraint> constraints);
|
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 {
|
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(const std::list<object::attribute> &attributes);
|
||||||
query_create_table_columns_intermediate columns(std::initializer_list<table_column> columns);
|
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::list<table_column> &columns);
|
||||||
|
query_create_table_columns_intermediate columns(const std::vector<table_column> &columns);
|
||||||
};
|
};
|
||||||
|
|
||||||
class query_create_intermediate : public query_intermediate {
|
class query_create_intermediate : public query_intermediate {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ public:
|
||||||
|
|
||||||
query_execute_limit_intermediate limit(size_t limit);
|
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(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(join_data &data);
|
||||||
query_from_intermediate join_left(std::vector<join_data> &data_vector);
|
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_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(const table_column &col);
|
||||||
|
query_order_by_intermediate order_by(std::initializer_list<table_column> columns);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
query_where_intermediate where_clause(std::unique_ptr<abstract_criteria> &&cond);
|
query_where_intermediate where_clause(std::unique_ptr<abstract_criteria> &&cond);
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ public:
|
||||||
using fetchable_query::fetchable_query;
|
using fetchable_query::fetchable_query;
|
||||||
|
|
||||||
query_order_by_intermediate order_by(const table_column &col);
|
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:
|
public:
|
||||||
using fetchable_query::fetchable_query;
|
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(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
|
class query_group_by_part final : public query_part
|
||||||
{
|
{
|
||||||
public:
|
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:
|
private:
|
||||||
void accept(query_part_visitor &visitor) override;
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
table_column column_;
|
std::vector<table_column> columns_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class query_order_by_part final : public query_part
|
class query_order_by_part final : public query_part
|
||||||
{
|
{
|
||||||
public:
|
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:
|
private:
|
||||||
void accept(query_part_visitor &visitor) override;
|
void accept(query_part_visitor &visitor) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
table_column column_;
|
std::vector<table_column> columns_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class query_order_by_asc_part final : public query_part
|
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> { \
|
class TABLE_NAME##_table : public typed_table<TABLE_NAME##_table> { \
|
||||||
public: \
|
public: \
|
||||||
TABLE_NAME##_table()\
|
TABLE_NAME##_table()\
|
||||||
: TABLE_NAME##_table("") \
|
: TABLE_NAME##_table(#TABLE_NAME) \
|
||||||
{} \
|
{} \
|
||||||
TABLE_NAME##_table(const std::string& alias) \
|
TABLE_NAME##_table(const std::string& alias) \
|
||||||
: typed_table(#TABLE_NAME, alias, {MAP(FIELD_STRING, __VA_ARGS__)}) \
|
: 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(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<table_column>& columns);
|
||||||
[[nodiscard]] static query_select_intermediate select(const std::vector<std::string> &column_names);
|
[[nodiscard]] static query_select_intermediate select(const std::vector<std::string> &column_names);
|
||||||
[[nodiscard]] static query_select_intermediate select(std::vector<table_column> columns, std::initializer_list<table_column> additional_columns);
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
[[nodiscard]] static query_select_intermediate select(const schema &scm) {
|
[[nodiscard]] static query_select_intermediate select(const schema &scm) {
|
||||||
return select(generator::columns<Type>(scm));
|
return select(generator::columns<Type>(scm));
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,12 @@
|
||||||
#define OOS_ACCESS_HPP
|
#define OOS_ACCESS_HPP
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
namespace matador {
|
namespace matador {
|
||||||
|
|
||||||
enum class cascade_type;
|
enum class cascade_type;
|
||||||
|
|
||||||
template < class Type, template < class ... > class ContainerType >
|
|
||||||
class container;
|
|
||||||
|
|
||||||
namespace utils {
|
namespace utils {
|
||||||
class field_attributes;
|
class field_attributes;
|
||||||
class foreign_attributes;
|
class foreign_attributes;
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,7 @@ public:
|
||||||
[[nodiscard]] bool is_varchar() const;
|
[[nodiscard]] bool is_varchar() const;
|
||||||
[[nodiscard]] bool is_date() const;
|
[[nodiscard]] bool is_date() const;
|
||||||
[[nodiscard]] bool is_time() const;
|
[[nodiscard]] bool is_time() const;
|
||||||
|
[[nodiscard]] bool is_timestamp() const;
|
||||||
[[nodiscard]] bool is_blob() const;
|
[[nodiscard]] bool is_blob() const;
|
||||||
[[nodiscard]] bool is_null() const;
|
[[nodiscard]] bool is_null() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,19 @@ size_t determine_size(const blob_type_t &val);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class value
|
class value {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
value() = default;
|
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)
|
explicit value(Type value, size_t size = 0)
|
||||||
: value_(value)
|
: value_(value)
|
||||||
, size_(size)
|
, size_(size)
|
||||||
, type_(data_type_traits<Type>::type(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);
|
explicit value(basic_type data_type, size_t size = 0);
|
||||||
value(const value &x) = default;
|
value(const value &x) = default;
|
||||||
value& operator=(const value &x) = default;
|
value& operator=(const value &x) = default;
|
||||||
|
|
@ -74,11 +78,12 @@ public:
|
||||||
[[nodiscard]] bool is_varchar() const;
|
[[nodiscard]] bool is_varchar() const;
|
||||||
[[nodiscard]] bool is_date() const;
|
[[nodiscard]] bool is_date() const;
|
||||||
[[nodiscard]] bool is_time() const;
|
[[nodiscard]] bool is_time() const;
|
||||||
|
[[nodiscard]] bool is_timestamp() const;
|
||||||
[[nodiscard]] bool is_blob() const;
|
[[nodiscard]] bool is_blob() const;
|
||||||
[[nodiscard]] bool is_null() const;
|
[[nodiscard]] bool is_null() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
utils::database_type value_;
|
database_type value_;
|
||||||
size_t size_{};
|
size_t size_{};
|
||||||
basic_type type_{basic_type::Null};
|
basic_type type_{basic_type::Null};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,10 @@ bool attribute::is_time() const {
|
||||||
return type_ == utils::basic_type::Time;
|
return type_ == utils::basic_type::Time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool attribute::is_timestamp() const {
|
||||||
|
return type_ == utils::basic_type::DateTime;
|
||||||
|
}
|
||||||
|
|
||||||
bool attribute::is_blob() const {
|
bool attribute::is_blob() const {
|
||||||
return type_ == utils::basic_type::Blob;
|
return type_ == utils::basic_type::Blob;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,63 +9,58 @@ size_t detail::hash(const char *value) {
|
||||||
return std::hash<std::string_view>()(std::string_view(value, std::strlen(value)));
|
return std::hash<std::string_view>()(std::string_view(value, std::strlen(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool identifier_type_traits<const char*>::is_valid(const char *value) {
|
bool identifier_type_traits<const char *>::is_valid(const char *value) {
|
||||||
return value != nullptr && strlen(value) > 0;
|
return value != nullptr && strlen(value) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string identifier_type_traits<const char*>::to_string(const char *value) {
|
std::string identifier_type_traits<const char *>::to_string(const char *value) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
identifier::base::base(const std::type_index &ti, const basic_type type)
|
identifier::base::base(const std::type_index &ti, const basic_type type)
|
||||||
: type_index_(ti)
|
: type_index_(ti)
|
||||||
, type_(type)
|
, type_(type) {
|
||||||
{}
|
}
|
||||||
|
|
||||||
identifier::null_pk::null_pk()
|
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;
|
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_;
|
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_;
|
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();
|
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();
|
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_, {});
|
s.serialize(null_, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t identifier::null_pk::hash() const
|
size_t identifier::null_pk::hash() const {
|
||||||
{
|
|
||||||
return std::hash<nullptr_t>()(nullptr);
|
return std::hash<nullptr_t>()(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
identifier::identifier()
|
identifier::identifier()
|
||||||
: id_(std::make_shared<null_pk>()) {}
|
: id_(std::make_shared<null_pk>()) {
|
||||||
|
}
|
||||||
|
|
||||||
identifier::identifier(const identifier &x)
|
identifier::identifier(const identifier &x)
|
||||||
: id_(x.id_->copy()) {}
|
: id_(x.id_->copy()) {
|
||||||
|
}
|
||||||
|
|
||||||
identifier &identifier::operator=(const identifier &x) {
|
identifier &identifier::operator=(const identifier &x) {
|
||||||
if (this == &x) {
|
if (this == &x) {
|
||||||
|
|
@ -123,13 +118,11 @@ basic_type identifier::type() const {
|
||||||
return id_->type_;
|
return id_->type_;
|
||||||
}
|
}
|
||||||
|
|
||||||
identifier identifier::share() const
|
identifier identifier::share() const {
|
||||||
{
|
|
||||||
return identifier(id_);
|
return identifier(id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t identifier::use_count() const
|
size_t identifier::use_count() const {
|
||||||
{
|
|
||||||
return id_.use_count();
|
return id_.use_count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -157,22 +150,23 @@ bool identifier::is_time() const {
|
||||||
return id_->type_ == basic_type::Time;
|
return id_->type_ == basic_type::Time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool identifier::is_timestamp() const {
|
||||||
|
return id_->type_ == basic_type::DateTime;
|
||||||
|
}
|
||||||
|
|
||||||
bool identifier::is_blob() const {
|
bool identifier::is_blob() const {
|
||||||
return id_->type_ == basic_type::Blob;
|
return id_->type_ == basic_type::Blob;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool identifier::is_null() const
|
bool identifier::is_null() const {
|
||||||
{
|
|
||||||
return type_index() == null_identifier.type_index();
|
return type_index() == null_identifier.type_index();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool identifier::is_valid() const
|
bool identifier::is_valid() const {
|
||||||
{
|
|
||||||
return id_->is_valid();
|
return id_->is_valid();
|
||||||
}
|
}
|
||||||
|
|
||||||
void identifier::clear()
|
void identifier::clear() {
|
||||||
{
|
|
||||||
id_ = std::make_unique<null_pk>();
|
id_ = std::make_unique<null_pk>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -180,24 +174,20 @@ void identifier::serialize(identifier_serializer &s) const {
|
||||||
id_->serialize(s);
|
id_->serialize(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t identifier::hash() const
|
size_t identifier::hash() const {
|
||||||
{
|
|
||||||
return id_->hash();
|
return id_->hash();
|
||||||
}
|
}
|
||||||
|
|
||||||
identifier::identifier(const std::shared_ptr<base> &id)
|
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();
|
out << id.str();
|
||||||
return out;
|
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();
|
return id.hash();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -84,6 +84,10 @@ bool value::is_time() const {
|
||||||
return type_ == basic_type::Time;
|
return type_ == basic_type::Time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool value::is_timestamp() const {
|
||||||
|
return type_ == basic_type::DateTime;
|
||||||
|
}
|
||||||
|
|
||||||
bool value::is_blob() const {
|
bool value::is_blob() const {
|
||||||
return type_ == basic_type::Blob;
|
return type_ == basic_type::Blob;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,4 +79,13 @@ query_create_table_columns_intermediate query_create_table_intermediate::columns
|
||||||
|
|
||||||
return {context_};
|
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) {
|
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 order_by({col});
|
||||||
return {context_};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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_};
|
return {context_};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_group_by_intermediate query_from_intermediate::group_by(const table_column &col) {
|
query_group_by_intermediate query_from_intermediate::group_by(const table_column &column) {
|
||||||
context_->parts.push_back(std::make_unique<internal::query_group_by_part>(col));
|
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_};
|
return {context_};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_order_by_intermediate query_from_intermediate::order_by(const table_column &col) {
|
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_};
|
return {context_};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,11 @@
|
||||||
namespace matador::query {
|
namespace matador::query {
|
||||||
|
|
||||||
query_order_by_intermediate query_group_by_intermediate::order_by(const table_column &col) {
|
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 order_by({col});
|
||||||
return {context_};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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"
|
#include "matador/query/internal/query_parts.hpp"
|
||||||
|
|
||||||
namespace matador::query {
|
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) {
|
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>(col));
|
context_->parts.push_back(std::make_unique<internal::query_group_by_part>(columns));
|
||||||
return {context_};
|
return {context_};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_order_by_intermediate query_where_intermediate::order_by(const table_column &col) {
|
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_};
|
return {context_};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -4,444 +4,439 @@
|
||||||
|
|
||||||
namespace matador::query::internal {
|
namespace matador::query::internal {
|
||||||
query_alter_part::query_alter_part()
|
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 ) {
|
void query_alter_part::accept(query_part_visitor &visitor) {
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_alter_table_part::query_alter_table_part(class table tab)
|
query_alter_table_part::query_alter_table_part(class table tab)
|
||||||
: query_part(sql::dialect_token::Table)
|
: query_part(sql::dialect_token::Table)
|
||||||
, table_(std::move(tab)) {}
|
, table_(std::move(tab)) {
|
||||||
|
}
|
||||||
|
|
||||||
void query_alter_table_part::accept(query_part_visitor& visitor) {
|
void query_alter_table_part::accept(query_part_visitor &visitor) {
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const table& query_alter_table_part::table() const {
|
const table &query_alter_table_part::table() const {
|
||||||
return table_;
|
return table_;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_add_key_constraint_part::query_add_key_constraint_part(std::string name)
|
query_add_key_constraint_part::query_add_key_constraint_part(std::string name)
|
||||||
: query_part(sql::dialect_token::AddConstraint)
|
: 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 ) {
|
void query_add_key_constraint_part::accept(query_part_visitor &visitor) {
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& query_add_key_constraint_part::name() const {
|
const std::string &query_add_key_constraint_part::name() const {
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_add_constraint_part_by_constraint::query_add_constraint_part_by_constraint(const query::table_constraint &co)
|
query_add_constraint_part_by_constraint::query_add_constraint_part_by_constraint(const query::table_constraint &co)
|
||||||
: query_part(sql::dialect_token::AddConstraint)
|
: query_part(sql::dialect_token::AddConstraint)
|
||||||
, constraint_(co) {}
|
, constraint_(co) {
|
||||||
|
}
|
||||||
|
|
||||||
void query_add_constraint_part_by_constraint::accept(query_part_visitor &visitor) {
|
void query_add_constraint_part_by_constraint::accept(query_part_visitor &visitor) {
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const table_constraint & query_add_constraint_part_by_constraint::constraint() const {
|
const table_constraint &query_add_constraint_part_by_constraint::constraint() const {
|
||||||
return constraint_;
|
return constraint_;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_drop_key_constraint_part_by_name::query_drop_key_constraint_part_by_name(std::string name)
|
query_drop_key_constraint_part_by_name::query_drop_key_constraint_part_by_name(std::string name)
|
||||||
: query_part( sql::dialect_token::DropConstraint )
|
: 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) {
|
void query_drop_key_constraint_part_by_name::accept(query_part_visitor &visitor) {
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& query_drop_key_constraint_part_by_name::name() const {
|
const std::string &query_drop_key_constraint_part_by_name::name() const {
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_drop_key_constraint_part_by_constraint::query_drop_key_constraint_part_by_constraint(const table_constraint &co)
|
query_drop_key_constraint_part_by_constraint::query_drop_key_constraint_part_by_constraint(const table_constraint &co)
|
||||||
: query_part( sql::dialect_token::DropConstraint )
|
: query_part(sql::dialect_token::DropConstraint)
|
||||||
, constraint_(co) {}
|
, constraint_(co) {
|
||||||
|
}
|
||||||
|
|
||||||
void query_drop_key_constraint_part_by_constraint::accept(query_part_visitor& visitor) {
|
void query_drop_key_constraint_part_by_constraint::accept(query_part_visitor &visitor) {
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const table_constraint& query_drop_key_constraint_part_by_constraint::constraint() const {
|
const table_constraint &query_drop_key_constraint_part_by_constraint::constraint() const {
|
||||||
return constraint_;
|
return constraint_;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_add_foreign_key_constraint_part::query_add_foreign_key_constraint_part(const std::vector<table_column>& columns)
|
query_add_foreign_key_constraint_part::query_add_foreign_key_constraint_part(const std::vector<table_column> &columns)
|
||||||
: query_part(sql::dialect_token::ForeignKey)
|
: query_part(sql::dialect_token::ForeignKey)
|
||||||
, columns_(columns) {}
|
, columns_(columns) {
|
||||||
|
}
|
||||||
|
|
||||||
void query_add_foreign_key_constraint_part::accept( query_part_visitor& visitor ) {
|
void query_add_foreign_key_constraint_part::accept(query_part_visitor &visitor) {
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<table_column>& query_add_foreign_key_constraint_part::columns() const {
|
const std::vector<table_column> &query_add_foreign_key_constraint_part::columns() const {
|
||||||
return 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)
|
: query_part(sql::dialect_token::References)
|
||||||
, table_(std::move(tab))
|
, table_(std::move(tab))
|
||||||
, columns_(columns) {}
|
, columns_(columns) {
|
||||||
|
}
|
||||||
|
|
||||||
void query_add_foreign_key_reference_part::accept( query_part_visitor& visitor ) {
|
void query_add_foreign_key_reference_part::accept(query_part_visitor &visitor) {
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const table& query_add_foreign_key_reference_part::table() const {
|
const table &query_add_foreign_key_reference_part::table() const {
|
||||||
return table_;
|
return table_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<table_column>& query_add_foreign_key_reference_part::columns() const {
|
const std::vector<table_column> &query_add_foreign_key_reference_part::columns() const {
|
||||||
return columns_;
|
return columns_;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_add_primary_key_constraint_part::query_add_primary_key_constraint_part(const std::vector<table_column>& 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)
|
: query_part(sql::dialect_token::PrimaryKey)
|
||||||
, columns_(columns) {}
|
, columns_(columns) {
|
||||||
|
}
|
||||||
|
|
||||||
void query_add_primary_key_constraint_part::accept( query_part_visitor& visitor ) {
|
void query_add_primary_key_constraint_part::accept(query_part_visitor &visitor) {
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<table_column>& query_add_primary_key_constraint_part::columns() const {
|
const std::vector<table_column> &query_add_primary_key_constraint_part::columns() const {
|
||||||
return columns_;
|
return columns_;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_select_part::query_select_part(std::vector<table_column> columns)
|
query_select_part::query_select_part(std::vector<table_column> columns)
|
||||||
: query_part(sql::dialect_token::Select)
|
: 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);
|
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_;
|
return columns_;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_from_part::query_from_part(class table tab)
|
query_from_part::query_from_part(class table tab)
|
||||||
: query_part(sql::dialect_token::From)
|
: 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_;
|
return table_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void query_from_part::accept(query_part_visitor &visitor)
|
void query_from_part::accept(query_part_visitor &visitor) {
|
||||||
{
|
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_join_part::query_join_part(class table tab)
|
query_join_part::query_join_part(class table tab)
|
||||||
: query_part(sql::dialect_token::Join)
|
: 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_;
|
return table_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void query_join_part::accept(query_part_visitor &visitor)
|
void query_join_part::accept(query_part_visitor &visitor) {
|
||||||
{
|
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_on_part::query_on_part(std::unique_ptr<abstract_criteria> &&cond)
|
query_on_part::query_on_part(std::unique_ptr<abstract_criteria> &&cond)
|
||||||
: query_part(sql::dialect_token::On)
|
: 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_;
|
return *condition_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void query_on_part::accept(query_part_visitor &visitor)
|
void query_on_part::accept(query_part_visitor &visitor) {
|
||||||
{
|
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_where_part::query_where_part(std::unique_ptr<abstract_criteria> &&cond)
|
query_where_part::query_where_part(std::unique_ptr<abstract_criteria> &&cond)
|
||||||
: query_part(sql::dialect_token::Where)
|
: 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);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const abstract_criteria &query_where_part::condition() const
|
const abstract_criteria &query_where_part::condition() const {
|
||||||
{
|
|
||||||
return *condition_;
|
return *condition_;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_table_name_part::query_table_name_part(const sql::dialect_token token, std::string table_name)
|
query_table_name_part::query_table_name_part(const sql::dialect_token token, std::string table_name)
|
||||||
: query_part(token)
|
: query_part(token)
|
||||||
, table_name_(std::move(table_name)) {}
|
, 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_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
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)
|
: query_part(sql::dialect_token::OrderBy)
|
||||||
, column_(std::move(col))
|
, columns_(columns) {
|
||||||
{}
|
|
||||||
|
|
||||||
const table_column &query_order_by_part::column() const
|
|
||||||
{
|
|
||||||
return column_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_order_by_asc_part::query_order_by_asc_part()
|
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);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_order_by_desc_part::query_order_by_desc_part()
|
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);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_offset_part::query_offset_part(size_t offset)
|
query_offset_part::query_offset_part(size_t offset)
|
||||||
: query_part(sql::dialect_token::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_;
|
return offset_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void query_offset_part::accept(query_part_visitor &visitor)
|
void query_offset_part::accept(query_part_visitor &visitor) {
|
||||||
{
|
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_limit_part::query_limit_part(size_t limit)
|
query_limit_part::query_limit_part(size_t limit)
|
||||||
: query_part(sql::dialect_token::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_;
|
return limit_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void query_limit_part::accept(query_part_visitor &visitor)
|
void query_limit_part::accept(query_part_visitor &visitor) {
|
||||||
{
|
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_insert_part::query_insert_part()
|
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);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_into_part::query_into_part(class table tab, std::vector<table_column> columns)
|
query_into_part::query_into_part(class table tab, std::vector<table_column> columns)
|
||||||
: query_part(sql::dialect_token::Insert)
|
: query_part(sql::dialect_token::Insert)
|
||||||
, table_(std::move(tab))
|
, 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_;
|
return table_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<table_column> &query_into_part::columns() const
|
const std::vector<table_column> &query_into_part::columns() const {
|
||||||
{
|
|
||||||
return columns_;
|
return columns_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void query_into_part::accept(query_part_visitor &visitor)
|
void query_into_part::accept(query_part_visitor &visitor) {
|
||||||
{
|
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_values_part::query_values_part(std::vector<std::variant<utils::placeholder, utils::database_type>> &&values)
|
query_values_part::query_values_part(std::vector<std::variant<utils::placeholder, utils::database_type> > &&values)
|
||||||
: query_part(sql::dialect_token::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_;
|
return values_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void query_values_part::accept(query_part_visitor &visitor)
|
void query_values_part::accept(query_part_visitor &visitor) {
|
||||||
{
|
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_update_part::query_update_part(class table tab)
|
query_update_part::query_update_part(class table tab)
|
||||||
: query_part(sql::dialect_token::Update)
|
: 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_;
|
return table_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void query_update_part::accept(query_part_visitor &visitor)
|
void query_update_part::accept(query_part_visitor &visitor) {
|
||||||
{
|
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_set_part::query_set_part(const std::vector<column_value_pair>& key_value_pairs)
|
query_set_part::query_set_part(const std::vector<column_value_pair> &key_value_pairs)
|
||||||
: query_part(sql::dialect_token::Set)
|
: 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_;
|
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);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_delete_part::query_delete_part()
|
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);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_delete_from_part::query_delete_from_part(class table tab)
|
query_delete_from_part::query_delete_from_part(class table tab)
|
||||||
: query_part(sql::dialect_token::From)
|
: 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_;
|
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);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_create_part::query_create_part()
|
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);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_create_table_part::query_create_table_part(class table tab)
|
query_create_table_part::query_create_table_part(class table tab)
|
||||||
: query_part(sql::dialect_token::Table)
|
: 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_;
|
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);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_create_table_columns_part::query_create_table_columns_part(const std::list<table_column>& columns)
|
query_create_table_columns_part::query_create_table_columns_part(const std::list<table_column> &columns)
|
||||||
: query_part( sql::dialect_token::Columns )
|
: query_part(sql::dialect_token::Columns)
|
||||||
, columns_(columns){}
|
, columns_(columns) {
|
||||||
|
}
|
||||||
|
|
||||||
const std::list<table_column>& query_create_table_columns_part::columns() const {
|
const std::list<table_column> &query_create_table_columns_part::columns() const {
|
||||||
return columns_;
|
return columns_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void query_create_table_columns_part::accept(query_part_visitor& visitor) {
|
void query_create_table_columns_part::accept(query_part_visitor &visitor) {
|
||||||
visitor.visit(*this);
|
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(
|
||||||
: query_part( sql::dialect_token::Constraint )
|
const std::list<class table_constraint> &constraints)
|
||||||
, constraints_(constraints) {}
|
: query_part(sql::dialect_token::Constraint)
|
||||||
|
, constraints_(constraints) {
|
||||||
|
}
|
||||||
|
|
||||||
const std::list<class table_constraint>& query_create_table_constraints_part::constraints() const {
|
const std::list<class table_constraint> &query_create_table_constraints_part::constraints() const {
|
||||||
return constraints_;
|
return constraints_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void query_create_table_constraints_part::accept( query_part_visitor& visitor ) {
|
void query_create_table_constraints_part::accept(query_part_visitor &visitor) {
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_create_schema_part::query_create_schema_part(std::string schema)
|
query_create_schema_part::query_create_schema_part(std::string schema)
|
||||||
: query_part( sql::dialect_token::Schema )
|
: query_part(sql::dialect_token::Schema)
|
||||||
, schema_( std::move( schema ) ){}
|
, schema_(std::move(schema)) {
|
||||||
|
}
|
||||||
|
|
||||||
const std::string& query_create_schema_part::schema() const {
|
const std::string &query_create_schema_part::schema() const {
|
||||||
return schema_;
|
return schema_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void query_create_schema_part::accept( query_part_visitor& visitor ) {
|
void query_create_schema_part::accept(query_part_visitor &visitor) {
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_drop_part::query_drop_part()
|
query_drop_part::query_drop_part()
|
||||||
: query_part(sql::dialect_token::Drop) {}
|
: query_part(sql::dialect_token::Drop) {
|
||||||
|
}
|
||||||
|
|
||||||
void query_drop_part::accept(query_part_visitor &visitor)
|
void query_drop_part::accept(query_part_visitor &visitor) {
|
||||||
{
|
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_drop_table_part::query_drop_table_part(class table tab)
|
query_drop_table_part::query_drop_table_part(class table tab)
|
||||||
: query_part(sql::dialect_token::Table)
|
: 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_;
|
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);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_drop_schema_part::query_drop_schema_part(std::string schema_)
|
query_drop_schema_part::query_drop_schema_part(std::string schema_)
|
||||||
: query_part( sql::dialect_token::Schema )
|
: query_part(sql::dialect_token::Schema)
|
||||||
, schema_( std::move( schema_ ) ) {}
|
, schema_(std::move(schema_)) {
|
||||||
|
}
|
||||||
|
|
||||||
const std::string& query_drop_schema_part::schema() const {
|
const std::string &query_drop_schema_part::schema() const {
|
||||||
return schema_;
|
return schema_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void query_drop_schema_part::accept( query_part_visitor& visitor ) {
|
void query_drop_schema_part::accept(query_part_visitor &visitor) {
|
||||||
visitor.visit(*this);
|
visitor.visit(*this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -49,13 +49,6 @@ query_select_intermediate query::select(const std::vector<std::string> &column_n
|
||||||
return select(columns);
|
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() {
|
query_insert_intermediate query::insert() {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -179,12 +179,35 @@ void query_compiler::visit(internal::query_where_part &part) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void query_compiler::visit(internal::query_group_by_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) {
|
void query_compiler::visit(internal::query_order_by_part &part) {
|
||||||
query_.sql += " " + dialect_->order_by() +
|
query_.sql += " " + dialect_->order_by() + " ";
|
||||||
" " + prepare_criteria(*dialect_, part.column());
|
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*/) {
|
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(str == row.at<std::string>("val_string"));
|
||||||
REQUIRE(varchar == row.at<std::string>("val_varchar"));
|
REQUIRE(varchar == row.at<std::string>("val_varchar"));
|
||||||
REQUIRE(md == row.at<date_type_t>("val_date"));
|
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(mt == row.at<time_type_t>("val_time"));
|
||||||
REQUIRE(bin == row.at<blob_type_t>("val_blob"));
|
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"})
|
auto result = query::select({count("age").as("age_count"), "age"})
|
||||||
.from("person")
|
.from("person")
|
||||||
.group_by("age")
|
.group_by({"age"})
|
||||||
.order_by("age_count").desc()
|
.order_by("age_count").desc()
|
||||||
.fetch_all(db);
|
.fetch_all(db);
|
||||||
REQUIRE(result.is_ok());
|
REQUIRE(result.is_ok());
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,9 @@
|
||||||
#include "models/flight.hpp"
|
#include "models/flight.hpp"
|
||||||
#include "models/person.hpp"
|
#include "models/person.hpp"
|
||||||
#include "models/recipe.hpp"
|
#include "models/recipe.hpp"
|
||||||
|
#include "models/shipment.hpp"
|
||||||
|
|
||||||
|
#include "../test/utils/record_printer.hpp"
|
||||||
|
|
||||||
using namespace matador::object;
|
using namespace matador::object;
|
||||||
using namespace matador::query;
|
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(recipe_ingredients, RECIPE_INGREDIENT, recipe_id, ingredient_id);
|
||||||
META_TABLE(airplanes, AIRPLANE, id, brand, model);
|
META_TABLE(airplanes, AIRPLANE, id, brand, model);
|
||||||
META_TABLE(flights, FLIGHT, id, airplane_id, pilot_name);
|
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]") {
|
TEST_CASE_METHOD(QueryFixture, "Create table with foreign key relation", "[query][foreign][relation]") {
|
||||||
auto result = repo.attach<airplane>("airplane")
|
auto result = repo.attach<airplane>("airplane")
|
||||||
|
|
@ -606,3 +611,106 @@ TEST_CASE_METHOD(QueryFixture, "Select statement with many to many relationship"
|
||||||
++index;
|
++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};
|
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();
|
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
|
# 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`
|
- move `prepare_*` methods from `dialect` to `query_compiler`
|
||||||
- add `session_insert_builder` and `session_update_builder` (returning multiple statements)
|
- 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
|
- finish fetch eager has-many/belongs-to relations
|
||||||
- implement lazy loading
|
- implement lazy loading
|
||||||
- implement polymorphic class hierarchies
|
- 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
|
- 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") {}
|
__Proposal for polymorphic classes:__
|
||||||
explicit Book(std::string alias)
|
|
||||||
: typed_object("book", std::move(alias)) {}
|
|
||||||
|
|
||||||
const matador::object::attribute id = create_attribute("id", *this);
|
object_ptr::as<Type> does the following checks;
|
||||||
const matador::object::attribute title = create_attribute("title", *this);
|
|
||||||
const matador::object::attribute year = create_attribute("year", *this);
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## aliasable_table
|
1. The requested type has a super class
|
||||||
```cpp
|
2. Super class has a discriminator column defined
|
||||||
class object;
|
3. Super class has a discriminator value defined
|
||||||
|
4. Discriminator value is mapped to the requested type
|
||||||
|
|
||||||
class attribute {
|
If all checks succeed, the requested is fetched from the database.
|
||||||
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)}; }
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
struct column_builder {
|
schema.attach<jobs::Payload>("payloads", make_polymorph("type"));
|
||||||
explicit column_builder(std::string column_name)
|
schema.attach<jobs::Payload, jobs::IdPayload>("id_list_payloads", make_polymorph_type("IdPayload"));
|
||||||
: column_name( std::move(column_name) ) {
|
schema.attach<jobs::Payload, jobs::IdListPayload>("id_payloads", make_polymorph_type("IdListPayload"));
|
||||||
}
|
object::object_ptr<jobs::Payload> payload;
|
||||||
|
auto result = payload.as<jobs::IdPayload>();
|
||||||
column_builder& not_null() {
|
if (result.is_ok()) {
|
||||||
return *this;
|
const auto& is_payload = result.value();
|
||||||
}
|
// Use requested type
|
||||||
|
id_payload->id = 1;
|
||||||
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});
|
|
||||||
}
|
}
|
||||||
|
payload.is_polymorphic();
|
||||||
|
payload.is_polymorphic_type<jobs::IdPayload>();
|
||||||
```
|
```
|
||||||
Loading…
Reference in New Issue