added timestamp code, support columns for group by and order by and tested load has-many eager code
This commit is contained in:
+237
-218
@@ -1,9 +1,11 @@
|
||||
#include "matador/sql/connection.hpp"
|
||||
#include "matador/sql/connection_pool.hpp"
|
||||
|
||||
#include "matador/query/criteria.hpp"
|
||||
#include "matador/query/query.hpp"
|
||||
#include "matador/query/table_column.hpp"
|
||||
#include "matador/query/meta_table_macro.hpp"
|
||||
#include "matador/query/schema.hpp"
|
||||
|
||||
#include "matador/object/object_ptr.hpp"
|
||||
#include "matador/object/repository.hpp"
|
||||
@@ -15,129 +17,129 @@
|
||||
#include <iostream>
|
||||
|
||||
struct author {
|
||||
unsigned int id{};
|
||||
std::string first_name;
|
||||
std::string last_name;
|
||||
std::string date_of_birth;
|
||||
unsigned short year_of_birth{};
|
||||
bool distinguished{false};
|
||||
unsigned int id{};
|
||||
std::string first_name;
|
||||
std::string last_name;
|
||||
std::string date_of_birth;
|
||||
unsigned short year_of_birth{};
|
||||
bool distinguished{false};
|
||||
|
||||
template<typename Operator>
|
||||
void process( Operator& op ) {
|
||||
namespace field = matador::access;
|
||||
field::primary_key( op, "id", id );
|
||||
field::attribute( op, "first_name", first_name, 63 );
|
||||
field::attribute( op, "last_name", last_name, 63 );
|
||||
field::attribute( op, "date_of_birth", date_of_birth, 31 );
|
||||
field::attribute( op, "year_of_birth", year_of_birth );
|
||||
field::attribute( op, "distinguished", distinguished );
|
||||
}
|
||||
template<typename Operator>
|
||||
void process(Operator &op) {
|
||||
namespace field = matador::access;
|
||||
field::primary_key(op, "id", id);
|
||||
field::attribute(op, "first_name", first_name, 63);
|
||||
field::attribute(op, "last_name", last_name, 63);
|
||||
field::attribute(op, "date_of_birth", date_of_birth, 31);
|
||||
field::attribute(op, "year_of_birth", year_of_birth);
|
||||
field::attribute(op, "distinguished", distinguished);
|
||||
}
|
||||
};
|
||||
|
||||
struct book {
|
||||
unsigned int id{};
|
||||
matador::object::object_ptr<author> book_author;
|
||||
std::string title;
|
||||
unsigned short published_in{};
|
||||
unsigned int id{};
|
||||
matador::object::object_ptr<author> book_author;
|
||||
std::string title;
|
||||
unsigned short published_in{};
|
||||
|
||||
template<typename Operator>
|
||||
void process( Operator& op ) {
|
||||
namespace field = matador::access;
|
||||
field::primary_key( op, "id", id );
|
||||
field::attribute( op, "title", title, 511 );
|
||||
field::has_one( op, "author_id", book_author, matador::utils::CascadeNoneFetchLazy );
|
||||
field::attribute( op, "published_in", published_in );
|
||||
}
|
||||
template<typename Operator>
|
||||
void process(Operator &op) {
|
||||
namespace field = matador::access;
|
||||
field::primary_key(op, "id", id);
|
||||
field::attribute(op, "title", title, 511);
|
||||
field::belongs_to(op, "author_id", book_author, matador::utils::CascadeNoneFetchLazy);
|
||||
field::attribute(op, "published_in", published_in);
|
||||
}
|
||||
};
|
||||
|
||||
struct payload {
|
||||
unsigned int id{};
|
||||
unsigned int id{};
|
||||
|
||||
template<typename Operator>
|
||||
void process( Operator& op ) {
|
||||
namespace field = matador::access;
|
||||
field::primary_key( op, "id", id );
|
||||
}
|
||||
template<typename Operator>
|
||||
void process(Operator &op) {
|
||||
namespace field = matador::access;
|
||||
field::primary_key(op, "id", id);
|
||||
}
|
||||
};
|
||||
|
||||
struct job {
|
||||
enum class job_state {
|
||||
Pending,
|
||||
Running,
|
||||
Succeeded,
|
||||
Failed,
|
||||
Canceled
|
||||
};
|
||||
enum class job_state {
|
||||
Pending,
|
||||
Running,
|
||||
Succeeded,
|
||||
Failed,
|
||||
Canceled
|
||||
};
|
||||
|
||||
enum class job_mode {
|
||||
Foreground,
|
||||
Background
|
||||
};
|
||||
enum class job_mode {
|
||||
Foreground,
|
||||
Background
|
||||
};
|
||||
|
||||
unsigned int id{};
|
||||
matador::object::object_ptr<payload> data;
|
||||
std::string type;
|
||||
std::string description;
|
||||
job_state state;
|
||||
job_mode mode;
|
||||
unsigned int id{};
|
||||
matador::object::object_ptr<payload> data;
|
||||
std::string type;
|
||||
std::string description;
|
||||
job_state state;
|
||||
job_mode mode;
|
||||
|
||||
template<typename Operator>
|
||||
void process( Operator& op ) {
|
||||
namespace field = matador::access;
|
||||
field::primary_key( op, "id", id );
|
||||
field::belongs_to( op, "payload", data, matador::utils::CascadeNoneFetchLazy );
|
||||
field::attribute( op, "type", type, 511 );
|
||||
field::attribute( op, "description", description, 511 );
|
||||
field::attribute( op, "state", state );
|
||||
field::attribute( op, "mode", mode );
|
||||
}
|
||||
template<typename Operator>
|
||||
void process(Operator &op) {
|
||||
namespace field = matador::access;
|
||||
field::primary_key(op, "id", id);
|
||||
field::belongs_to(op, "payload", data, matador::utils::CascadeNoneFetchLazy);
|
||||
field::attribute(op, "type", type, 511);
|
||||
field::attribute(op, "description", description, 511);
|
||||
field::attribute(op, "state", state);
|
||||
field::attribute(op, "mode", mode);
|
||||
}
|
||||
};
|
||||
|
||||
static const matador::utils::enum_mapper<job::job_state> job_state_enum({
|
||||
{job::job_state::Pending, "Pending"},
|
||||
{job::job_state::Running, "Running"},
|
||||
{job::job_state::Succeeded, "Succeeded"},
|
||||
{job::job_state::Failed, "Failed"},
|
||||
{job::job_state::Canceled, "Canceled"}
|
||||
});
|
||||
{job::job_state::Pending, "Pending"},
|
||||
{job::job_state::Running, "Running"},
|
||||
{job::job_state::Succeeded, "Succeeded"},
|
||||
{job::job_state::Failed, "Failed"},
|
||||
{job::job_state::Canceled, "Canceled"}
|
||||
});
|
||||
|
||||
static const matador::utils::enum_mapper<job::job_mode> job_mode_enum({
|
||||
{job::job_mode::Foreground, "Foreground"},
|
||||
{job::job_mode::Background, "Background"}
|
||||
});
|
||||
{job::job_mode::Foreground, "Foreground"},
|
||||
{job::job_mode::Background, "Background"}
|
||||
});
|
||||
|
||||
template<>
|
||||
struct matador::utils::data_type_traits<job::job_state, 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_state &value) {
|
||||
std::string enum_string;
|
||||
reader.read_value(id, index, enum_string, 64);
|
||||
if (const auto enum_opt = job_state_enum.to_enum(enum_string)) {
|
||||
value = enum_opt.value();
|
||||
}
|
||||
static void read_value(attribute_reader &reader, const char *id, const size_t index, job::job_state &value) {
|
||||
std::string enum_string;
|
||||
reader.read_value(id, index, enum_string, 64);
|
||||
if (const auto enum_opt = job_state_enum.to_enum(enum_string)) {
|
||||
value = enum_opt.value();
|
||||
}
|
||||
}
|
||||
|
||||
static void write_value(attribute_writer &binder, const size_t index, const job::job_state &value) {
|
||||
binder.write_value(index, job_state_enum.to_string(value));
|
||||
}
|
||||
static void write_value(attribute_writer &binder, const size_t index, const job::job_state &value) {
|
||||
binder.write_value(index, job_state_enum.to_string(value));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
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) {
|
||||
std::string enum_string;
|
||||
reader.read_value(id, index, enum_string, 64);
|
||||
if (const auto enum_opt = job_mode_enum.to_enum(enum_string)) {
|
||||
value = enum_opt.value();
|
||||
}
|
||||
static void read_value(attribute_reader &reader, const char *id, const size_t index, job::job_mode &value) {
|
||||
std::string enum_string;
|
||||
reader.read_value(id, index, enum_string, 64);
|
||||
if (const auto enum_opt = job_mode_enum.to_enum(enum_string)) {
|
||||
value = enum_opt.value();
|
||||
}
|
||||
}
|
||||
|
||||
static void bind_value(attribute_writer &binder, const size_t index, const job::job_mode &value) {
|
||||
binder.write_value(index, job_mode_enum.to_string(value));
|
||||
}
|
||||
static void bind_value(attribute_writer &binder, const size_t index, const job::job_mode &value) {
|
||||
binder.write_value(index, job_mode_enum.to_string(value));
|
||||
}
|
||||
};
|
||||
|
||||
META_TABLE(authors, AUTHOR, id, first_name, last_name, date_of_birth, year_of_birth, distinguished)
|
||||
@@ -146,144 +148,161 @@ META_TABLE(books, BOOK, id, author_id, title, published_in)
|
||||
|
||||
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(product, PRODUCT, id, title, description, price, category)
|
||||
|
||||
META_TABLE(category, CATEGORY, id, title, description)
|
||||
|
||||
META_TABLE(cart, CART, id, items, owner)
|
||||
|
||||
int main() {
|
||||
using namespace matador::sql;
|
||||
using namespace matador::object;
|
||||
using namespace matador::utils;
|
||||
using namespace matador::query::meta;
|
||||
using namespace matador::sql;
|
||||
using namespace matador::object;
|
||||
using namespace matador::utils;
|
||||
using namespace matador::query;
|
||||
using namespace matador::query::meta;
|
||||
|
||||
const std::string env_var{"MATADOR_BACKENDS_PATH"};
|
||||
const std::string env_var{"MATADOR_BACKENDS_PATH"};
|
||||
|
||||
std::string dns{"sqlite://demo.db"};
|
||||
repository s( "main" );
|
||||
auto result = s.attach<author>( "authors" ).and_then( [&s] {
|
||||
return s.attach<book>( "books" );
|
||||
} );
|
||||
// s.attach<book>( "books" );
|
||||
connection_pool pool("postgres://test:test123!@127.0.0.1:5432/matador", 4);
|
||||
|
||||
connection c( dns );
|
||||
result = c.open();
|
||||
// s.create( c );
|
||||
//
|
||||
// auto create_authors_sql = c.query( s )
|
||||
// .create()
|
||||
// .table<author>( qh::authors )
|
||||
// .execute();
|
||||
//
|
||||
// c.query( s )
|
||||
// .create()
|
||||
// .table<book>( qh::books )
|
||||
// .execute();
|
||||
//
|
||||
// std::cout << "SQL: " << create_authors_sql << "\n";
|
||||
//
|
||||
// author mc;
|
||||
// mc.id = 1;
|
||||
// mc.first_name = "Michael";
|
||||
// mc.last_name = "Crichton";
|
||||
// mc.date_of_birth = "19.8.1954";
|
||||
// mc.year_of_birth = 1954;
|
||||
// mc.distinguished = true;
|
||||
// auto insert_authors_sql = c.query( s )
|
||||
// .insert()
|
||||
// .into( qh::authors )
|
||||
// .values( mc )
|
||||
// .execute();
|
||||
//
|
||||
// std::cout << "SQL: " << insert_authors_sql << "\n";
|
||||
//
|
||||
// auto result = c.query( s )
|
||||
// .select( qh::authors.columns )
|
||||
// .from( qh::authors )
|
||||
// .fetch_all();
|
||||
//
|
||||
// for (const auto& row: result) { std::cout << "Author " << row.at( qh::authors.first_name ) << "\n"; }
|
||||
//
|
||||
// auto update_authors_sql = c.query( s )
|
||||
// .update( qh::authors )
|
||||
// .set( {{qh::authors.first_name, "Stephen"},
|
||||
// {qh::authors.last_name, "King"}} )
|
||||
// .where( qh::authors.last_name == "Crichton" )
|
||||
// .execute();
|
||||
//
|
||||
// std::cout << "SQL: " << update_authors_sql << "\n";
|
||||
//
|
||||
// auto authors = c.query( s )
|
||||
// .select( qh::authors.columns )
|
||||
// .from( qh::authors )
|
||||
// .fetch_all<author>();
|
||||
//
|
||||
// for (const auto& a: authors) { std::cout << "Author " << a.first_name << "\n"; }
|
||||
//
|
||||
// c.query( s )
|
||||
// .insert()
|
||||
// .into( qh::books )
|
||||
// .values( {2, "It", mc.id, 1980} )
|
||||
// .execute();
|
||||
//
|
||||
// c.query( s )
|
||||
// .insert()
|
||||
// .into( qh::books )
|
||||
// .values( {3, "Misery", mc.id, 1984} )
|
||||
// .execute();
|
||||
//
|
||||
auto select_books_sql = matador::query::query::select( BOOK, {AUTHOR.last_name} )
|
||||
.from( BOOK )
|
||||
.join_left( AUTHOR )
|
||||
.on( BOOK.author_id == AUTHOR.id )
|
||||
.where( BOOK.published_in < 2008 && AUTHOR.last_name == "King" )
|
||||
.group_by( BOOK.published_in )
|
||||
.order_by( BOOK.title ).asc()
|
||||
.limit( 5 )
|
||||
.offset( 2 )
|
||||
.fetch_all(c);
|
||||
|
||||
for (const auto& r: *select_books_sql) {
|
||||
std::cout << "R: " << r.at( BOOK.title ) << ", " << r.at( AUTHOR.last_name ) << "\n";
|
||||
}
|
||||
// // SELECT book.title, book.id, book.author_id, book.published_in, author.name
|
||||
// // FROM book
|
||||
// // INNER JOIN author ON book.author_id = author.id
|
||||
// // WHERE book.published_in < 2008 AND author.name = "Michael Crichton"
|
||||
// // ORDER BY "book.title" ASC
|
||||
// // OFFSET 2 LIMIT 5
|
||||
//
|
||||
// c.query( s ).drop().table( qh::books ).execute();
|
||||
//
|
||||
// auto drop_authors_sql = c.query( s )
|
||||
// .drop()
|
||||
// .table( qh::authors )
|
||||
// .execute();
|
||||
//
|
||||
// std::cout << "SQL: " << drop_authors_sql << "\n";
|
||||
//
|
||||
// auto res = c.query( s )
|
||||
// .select( {qh::payload.id} )
|
||||
// .from( qh::payload )
|
||||
// .join_left( qh::job )
|
||||
// .on( qh::job.payload == qh::payload.id )
|
||||
// .where(
|
||||
// in( qh::payload.id, c.query( s )
|
||||
// .select( {qh::job.state} )
|
||||
// .from( qh::job )
|
||||
// .where( qh::job.state == job::job_state::Running )
|
||||
// ) &&
|
||||
// in( qh::payload.id, c.query( s )
|
||||
// .select( {qh::temporary_table.id} )
|
||||
// .from( qh::temporary_table ) )
|
||||
// )
|
||||
// .build();
|
||||
// // .fetch_value<unsigned long>();
|
||||
// std::cout << "SQL: " << res.sql << "\n";
|
||||
schema s("");
|
||||
auto result = s.attach<author>("authors").and_then([&s] {
|
||||
return s.attach<book>("books");
|
||||
});
|
||||
|
||||
const auto c = pool.acquire();
|
||||
result = s.create(*c);
|
||||
if (!result) {
|
||||
std::cout << "error: " << result.err() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
author mc;
|
||||
mc.id = 1;
|
||||
mc.first_name = "Michael";
|
||||
mc.last_name = "Crichton";
|
||||
mc.date_of_birth = "19.8.1954";
|
||||
mc.year_of_birth = 1954;
|
||||
mc.distinguished = true;
|
||||
auto insert_authors_sql = query::insert()
|
||||
.into(AUTHOR)
|
||||
.values(mc)
|
||||
.execute(*c);
|
||||
|
||||
if (!insert_authors_sql) {
|
||||
std::cout << "error: " << insert_authors_sql.err() << std::endl;
|
||||
std::ignore = s.drop(*c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto authors_result = query::select(AUTHOR)
|
||||
.from(AUTHOR)
|
||||
.fetch_all(*c);
|
||||
|
||||
if (!authors_result) {
|
||||
std::cout << "error: " << authors_result.err() << std::endl;
|
||||
std::ignore = s.drop(*c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (const auto &row: *authors_result) {
|
||||
std::cout << "Author " << row.at(AUTHOR.first_name.canonical_name()) << "\n";
|
||||
}
|
||||
//
|
||||
// auto update_authors_sql = c.query( s )
|
||||
// .update( qh::authors )
|
||||
// .set( {{qh::authors.first_name, "Stephen"},
|
||||
// {qh::authors.last_name, "King"}} )
|
||||
// .where( qh::authors.last_name == "Crichton" )
|
||||
// .execute();
|
||||
//
|
||||
// std::cout << "SQL: " << update_authors_sql << "\n";
|
||||
//
|
||||
// auto authors = c.query( s )
|
||||
// .select( qh::authors.columns )
|
||||
// .from( qh::authors )
|
||||
// .fetch_all<author>();
|
||||
//
|
||||
// for (const auto& a: authors) { std::cout << "Author " << a.first_name << "\n"; }
|
||||
//
|
||||
// c.query( s )
|
||||
// .insert()
|
||||
// .into( qh::books )
|
||||
// .values( {2, "It", mc.id, 1980} )
|
||||
// .execute();
|
||||
//
|
||||
// c.query( s )
|
||||
// .insert()
|
||||
// .into( qh::books )
|
||||
// .values( {3, "Misery", mc.id, 1984} )
|
||||
// .execute();
|
||||
//
|
||||
// auto select_books_sql = query::select( BOOK, {AUTHOR.last_name} )
|
||||
auto select_books_sql = query::select({BOOK.id, BOOK.title, BOOK.author_id, BOOK.published_in, AUTHOR.last_name})
|
||||
.from(BOOK)
|
||||
.join_left(AUTHOR)
|
||||
.on(BOOK.author_id == AUTHOR.id)
|
||||
.where(BOOK.published_in < 2008 && AUTHOR.last_name == "King")
|
||||
.group_by({BOOK.id, AUTHOR.last_name})
|
||||
.order_by(BOOK.title).asc()
|
||||
.limit(5)
|
||||
.offset(2)
|
||||
.fetch_all(*c);
|
||||
|
||||
if (!select_books_sql) {
|
||||
std::cout << "error: " << select_books_sql.err() << std::endl;
|
||||
std::ignore = s.drop(*c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (const auto &r: *select_books_sql) {
|
||||
std::cout << "R: " << r.at(BOOK.title.canonical_name()) << ", " << r.at(AUTHOR.last_name.canonical_name()) << "\n";
|
||||
}
|
||||
|
||||
result = s.drop(*c);
|
||||
if (!result) {
|
||||
std::cout << "error: " << result.err() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// // SELECT book.title, book.id, book.author_id, book.published_in, author.name
|
||||
// // FROM book
|
||||
// // INNER JOIN author ON book.author_id = author.id
|
||||
// // WHERE book.published_in < 2008 AND author.name = "Michael Crichton"
|
||||
// // ORDER BY "book.title" ASC
|
||||
// // OFFSET 2 LIMIT 5
|
||||
//
|
||||
// c.query( s ).drop().table( qh::books ).execute();
|
||||
//
|
||||
// auto drop_authors_sql = c.query( s )
|
||||
// .drop()
|
||||
// .table( qh::authors )
|
||||
// .execute();
|
||||
//
|
||||
// std::cout << "SQL: " << drop_authors_sql << "\n";
|
||||
//
|
||||
auto res = query::select({PAYLOAD.id})
|
||||
.from(PAYLOAD)
|
||||
.join_left(JOB)
|
||||
.on(JOB.payload == PAYLOAD.id)
|
||||
.where(
|
||||
in(PAYLOAD.id, query::select({JOB.state})
|
||||
.from(JOB)
|
||||
.where(JOB.state == job::job_state::Running).compile(c->dialect())
|
||||
) &&
|
||||
in(PAYLOAD.id, query::select({TEMPORARY_TABLE.id})
|
||||
.from(TEMPORARY_TABLE).compile(c->dialect())
|
||||
)
|
||||
).compile(c->dialect());
|
||||
// // .fetch_value<unsigned long>();
|
||||
std::cout << "SQL: " << res.sql << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user