Compare commits
8
Commits
4199c5029c
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19de5714f4 | ||
|
|
484c2d8b05 | ||
|
|
43d2f81b95 | ||
|
|
27f6c81da2 | ||
|
|
12e5b27a8c | ||
|
|
ff3a2e4217 | ||
|
|
ac8b2ed4e4 | ||
|
|
38da76bfb3 |
@@ -1,3 +1,4 @@
|
|||||||
.idea
|
.idea
|
||||||
cmake-build-debug
|
cmake-build-debug
|
||||||
Testing
|
Testing
|
||||||
|
debug
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ find_package(SQLite3 REQUIRED)
|
|||||||
find_package(PostgreSQL REQUIRED)
|
find_package(PostgreSQL REQUIRED)
|
||||||
find_package(MySQL REQUIRED)
|
find_package(MySQL REQUIRED)
|
||||||
|
|
||||||
|
message(STATUS "Found ODBC config ${ODBC_CONFIG}")
|
||||||
|
message(STATUS "Adding ODBC include directory: ${ODBC_INCLUDE_DIRS}")
|
||||||
|
message(STATUS "Adding ODBC libs: ${ODBC_LIBRARIES}")
|
||||||
|
|
||||||
message(STATUS "Found SQLite3 ${SQLite3_VERSION}")
|
message(STATUS "Found SQLite3 ${SQLite3_VERSION}")
|
||||||
message(STATUS "Adding SQLite3 include directory: ${SQLite3_INCLUDE_DIRS}")
|
message(STATUS "Adding SQLite3 include directory: ${SQLite3_INCLUDE_DIRS}")
|
||||||
message(STATUS "Adding SQLite3 libs: ${SQLite3_LIBRARIES}")
|
message(STATUS "Adding SQLite3 libs: ${SQLite3_LIBRARIES}")
|
||||||
|
|||||||
@@ -52,38 +52,32 @@ static const matador::utils::enum_mapper<Color> color_enum({
|
|||||||
{Color::Brown, "brown"}
|
{Color::Brown, "brown"}
|
||||||
});
|
});
|
||||||
|
|
||||||
namespace matador::sql {
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct data_type_traits<Color, void>
|
struct matador::sql::data_type_traits<Color, void>
|
||||||
{
|
{
|
||||||
inline static data_type_t builtin_type(std::size_t size)
|
inline static data_type_t builtin_type(std::size_t size)
|
||||||
{ return data_type_traits<std::string>::builtin_type(size); }
|
{ return data_type_traits<std::string>::builtin_type(size); }
|
||||||
|
|
||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, Color &value)
|
static void read_value(query_result_reader &reader, const char *id, size_t index, Color &value)
|
||||||
{
|
{
|
||||||
std::string enum_string;
|
std::string enum_string;
|
||||||
reader.read_value(id, index, enum_string, 64);
|
reader.read_value(id, index, enum_string, 64);
|
||||||
auto enum_opt = color_enum.to_enum(enum_string);
|
if (const auto enum_opt = color_enum.to_enum(enum_string)) {
|
||||||
if (enum_opt) {
|
value = enum_opt.value();
|
||||||
value = enum_opt.value();
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static any_type create_value(Color &value)
|
static any_type create_value(const Color &value)
|
||||||
{
|
{
|
||||||
return color_enum.to_string(value);
|
return color_enum.to_string(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bind_value(parameter_binder &binder, size_t index, Color &value)
|
static void bind_value(parameter_binder &binder, size_t index, Color &value)
|
||||||
{
|
{
|
||||||
binder.bind(index, color_enum.to_string(value));
|
binder.bind(index, color_enum.to_string(value));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE_METHOD(TypeTraitsTestFixture, "Special handling of attributes with type traits", "[typetraits]")
|
TEST_CASE_METHOD(TypeTraitsTestFixture, "Special handling of attributes with type traits", "[typetraits]")
|
||||||
{
|
{
|
||||||
schema.attach<location>("location");
|
schema.attach<location>("location");
|
||||||
|
|||||||
+251
-126
@@ -5,166 +5,291 @@
|
|||||||
#include "matador/sql/entity.hpp"
|
#include "matador/sql/entity.hpp"
|
||||||
|
|
||||||
#include "matador/utils/access.hpp"
|
#include "matador/utils/access.hpp"
|
||||||
|
#include "matador/utils/enum_mapper.hpp"
|
||||||
|
|
||||||
#include "matador/sql/query_helper.hpp"
|
#include "matador/sql/query_helper.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
struct author
|
struct author {
|
||||||
{
|
unsigned long id{};
|
||||||
unsigned long id{};
|
std::string first_name;
|
||||||
std::string first_name;
|
std::string last_name;
|
||||||
std::string last_name;
|
std::string date_of_birth;
|
||||||
std::string date_of_birth;
|
unsigned short year_of_birth{};
|
||||||
unsigned short year_of_birth{};
|
bool distinguished{false};
|
||||||
bool distinguished{false};
|
|
||||||
|
|
||||||
template<typename Operator>
|
template<typename Operator>
|
||||||
void process(Operator &op)
|
void process( Operator& op ) {
|
||||||
{
|
namespace field = matador::utils::access;
|
||||||
namespace field = matador::utils::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);
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct book
|
struct book {
|
||||||
{
|
unsigned long id{};
|
||||||
unsigned long id{};
|
matador::sql::entity<author> book_author;
|
||||||
matador::sql::entity<author> book_author;
|
std::string title;
|
||||||
std::string title;
|
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::utils::access;
|
||||||
namespace field = matador::utils::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::default_foreign_attributes );
|
||||||
field::has_one(op, "author_id", book_author, matador::utils::default_foreign_attributes);
|
field::attribute( op, "published_in", published_in );
|
||||||
field::attribute(op, "published_in", published_in);
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QUERY_HELPER(authors, id, first_name, last_name, date_of_birth, year_of_birth, distinguished)
|
struct payload {
|
||||||
QUERY_HELPER(books, id, author_id, title, published_in)
|
unsigned long id{};
|
||||||
|
|
||||||
int main()
|
template<typename Operator>
|
||||||
|
void process( Operator& op ) {
|
||||||
|
namespace field = matador::utils::access;
|
||||||
|
field::primary_key( op, "id", id );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct job {
|
||||||
|
enum class job_state {
|
||||||
|
Pending,
|
||||||
|
Running,
|
||||||
|
Succeeded,
|
||||||
|
Failed,
|
||||||
|
Canceled
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class job_mode {
|
||||||
|
Foreground,
|
||||||
|
Background
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned long id{};
|
||||||
|
matador::sql::entity<payload> payload;
|
||||||
|
std::string type;
|
||||||
|
std::string description;
|
||||||
|
job_state state;
|
||||||
|
job_mode mode;
|
||||||
|
|
||||||
|
template<typename Operator>
|
||||||
|
void process( Operator& op ) {
|
||||||
|
namespace field = matador::utils::access;
|
||||||
|
field::primary_key( op, "id", id );
|
||||||
|
field::belongs_to( op, "payload", payload, matador::utils::default_foreign_attributes );
|
||||||
|
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"}
|
||||||
|
});
|
||||||
|
|
||||||
|
static const matador::utils::enum_mapper<job::job_mode> job_mode_enum({
|
||||||
|
{job::job_mode::Foreground, "Foreground"},
|
||||||
|
{job::job_mode::Background, "Background"}
|
||||||
|
});
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct matador::sql::data_type_traits<job::job_state, void>
|
||||||
{
|
{
|
||||||
using namespace matador::sql;
|
inline static data_type_t builtin_type(std::size_t size)
|
||||||
using namespace matador;
|
{ return data_type_traits<std::string>::builtin_type(size); }
|
||||||
|
|
||||||
const std::string env_var{"MATADOR_BACKENDS_PATH"};
|
static void read_value(query_result_reader &reader, const char *id, 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string dns{"sqlite://demo.db"};
|
static any_type create_value(const job::job_state &value)
|
||||||
schema s("main");
|
{
|
||||||
s.attach<author>("authors");
|
return job_state_enum.to_string(value);
|
||||||
s.attach<book>("books");
|
}
|
||||||
|
|
||||||
connection c(dns);
|
static void bind_value(parameter_binder &binder, size_t index, job::job_state &value)
|
||||||
c.open();
|
{
|
||||||
|
binder.bind(index, job_state_enum.to_string(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
auto create_authors_sql = c.query(s)
|
template<>
|
||||||
.create()
|
struct matador::sql::data_type_traits<job::job_mode, void>
|
||||||
.table<author>(qh::authors)
|
{
|
||||||
.execute();
|
inline static data_type_t builtin_type(std::size_t size)
|
||||||
|
{ return data_type_traits<std::string>::builtin_type(size); }
|
||||||
|
|
||||||
c.query(s)
|
static void read_value(query_result_reader &reader, const char *id, size_t index, job::job_mode &value)
|
||||||
.create()
|
{
|
||||||
.table<book>(qh::books)
|
std::string enum_string;
|
||||||
.execute();
|
reader.read_value(id, index, enum_string, 64);
|
||||||
|
if (const auto enum_opt = job_mode_enum.to_enum(enum_string)) {
|
||||||
|
value = enum_opt.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::cout << "SQL: " << create_authors_sql << "\n";
|
static any_type create_value(const job::job_mode &value)
|
||||||
|
{
|
||||||
|
return job_mode_enum.to_string(value);
|
||||||
|
}
|
||||||
|
|
||||||
author mc;
|
static void bind_value(parameter_binder &binder, size_t index, job::job_mode &value)
|
||||||
mc.id = 1;
|
{
|
||||||
mc.first_name = "Michael";
|
binder.bind(index, job_mode_enum.to_string(value));
|
||||||
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";
|
QUERY_HELPER( authors, id, first_name, last_name, date_of_birth, year_of_birth, distinguished )
|
||||||
|
|
||||||
auto result = c.query(s)
|
QUERY_HELPER( books, id, author_id, title, published_in )
|
||||||
.select(qh::authors.columns)
|
|
||||||
.from(qh::authors)
|
|
||||||
.fetch_all();
|
|
||||||
|
|
||||||
for (const auto &row: result) {
|
QUERY_HELPER( job, id, payload, type, description, state, mode )
|
||||||
std::cout << "Author " << row.at(qh::authors.first_name) << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
auto update_authors_sql = c.query(s)
|
QUERY_HELPER( payload, id )
|
||||||
.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";
|
QUERY_HELPER( temporary_table, id );
|
||||||
|
|
||||||
auto authors = c.query(s)
|
int main() {
|
||||||
.select(qh::authors.columns)
|
using namespace matador::sql;
|
||||||
.from(qh::authors)
|
using namespace matador;
|
||||||
.fetch_all<author>();
|
|
||||||
|
|
||||||
for (const auto &a: authors) {
|
const std::string env_var{"MATADOR_BACKENDS_PATH"};
|
||||||
std::cout << "Author " << a.first_name << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
c.query(s)
|
std::string dns{"sqlite://demo.db"};
|
||||||
.insert()
|
schema s( "main" );
|
||||||
.into(qh::books)
|
s.attach<author>( "authors" );
|
||||||
.values({2, "It", mc.id, 1980})
|
s.attach<book>( "books" );
|
||||||
.execute();
|
|
||||||
|
|
||||||
c.query(s)
|
connection c( dns );
|
||||||
.insert()
|
c.open();
|
||||||
.into(qh::books)
|
s.create( c );
|
||||||
.values({3, "Misery", mc.id, 1984})
|
|
||||||
.execute();
|
|
||||||
|
|
||||||
auto select_books_sql = c.query(s)
|
auto create_authors_sql = c.query( s )
|
||||||
.select(qh::books.columns, {qh::authors.last_name})
|
.create()
|
||||||
.from(qh::books)
|
.table<author>( qh::authors )
|
||||||
.join_left(qh::authors)
|
.execute();
|
||||||
.on(qh::books.author_id == qh::authors.id)
|
|
||||||
.where(qh::books.published_in < 2008 && qh::authors.last_name == "King")
|
|
||||||
.group_by(qh::books.published_in)
|
|
||||||
.order_by(qh::books.title).asc()
|
|
||||||
.limit(5)
|
|
||||||
.offset(2)
|
|
||||||
.fetch_all();
|
|
||||||
|
|
||||||
for (const auto &r: select_books_sql) {
|
c.query( s )
|
||||||
std::cout << "R: " << r.at(qh::books.title) << ", " << r.at(qh::authors.last_name) << "\n";
|
.create()
|
||||||
}
|
.table<book>( qh::books )
|
||||||
// SELECT book.title, book.id, book.author_id, book.published_in, author.name
|
.execute();
|
||||||
// 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();
|
std::cout << "SQL: " << create_authors_sql << "\n";
|
||||||
|
|
||||||
auto drop_authors_sql = c.query(s)
|
author mc;
|
||||||
.drop()
|
mc.id = 1;
|
||||||
.table(qh::authors)
|
mc.first_name = "Michael";
|
||||||
.execute();
|
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: " << drop_authors_sql << "\n";
|
std::cout << "SQL: " << insert_authors_sql << "\n";
|
||||||
|
|
||||||
return 0;
|
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 = c.query( s )
|
||||||
|
.select( qh::books.columns, {qh::authors.last_name} )
|
||||||
|
.from( qh::books )
|
||||||
|
.join_left( qh::authors )
|
||||||
|
.on( qh::books.author_id == qh::authors.id )
|
||||||
|
.where( qh::books.published_in < 2008 && qh::authors.last_name == "King" )
|
||||||
|
.group_by( qh::books.published_in )
|
||||||
|
.order_by( qh::books.title ).asc()
|
||||||
|
.limit( 5 )
|
||||||
|
.offset( 2 )
|
||||||
|
.fetch_all();
|
||||||
|
|
||||||
|
for (const auto& r: select_books_sql) { std::cout << "R: " << r.at( qh::books.title ) << ", " << r.at( qh::authors.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";
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
#ifndef QUERY_CONDITION_HPP
|
#ifndef QUERY_CONDITION_HPP
|
||||||
#define QUERY_CONDITION_HPP
|
#define QUERY_CONDITION_HPP
|
||||||
|
|
||||||
|
#include "matador/sql/any_type_to_string_visitor.hpp"
|
||||||
|
#include "matador/sql/query_result.hpp"
|
||||||
#include "matador/sql/basic_condition.hpp"
|
#include "matador/sql/basic_condition.hpp"
|
||||||
#include "matador/sql/dialect.hpp"
|
#include "matador/sql/dialect.hpp"
|
||||||
#include "matador/sql/placeholder.hpp"
|
#include "matador/sql/placeholder.hpp"
|
||||||
@@ -26,6 +28,8 @@ namespace matador::sql {
|
|||||||
|
|
||||||
/// @cond MATADOR_DEV
|
/// @cond MATADOR_DEV
|
||||||
|
|
||||||
|
class query_select;
|
||||||
|
|
||||||
template<class L, class R, class Enabled = void>
|
template<class L, class R, class Enabled = void>
|
||||||
class condition;
|
class condition;
|
||||||
|
|
||||||
@@ -43,6 +47,7 @@ public:
|
|||||||
template<class T>
|
template<class T>
|
||||||
class condition<column, T, typename std::enable_if<
|
class condition<column, T, typename std::enable_if<
|
||||||
std::is_scalar<T>::value &&
|
std::is_scalar<T>::value &&
|
||||||
|
!std::is_enum<T>::value &&
|
||||||
!std::is_same<std::string, T>::value &&
|
!std::is_same<std::string, T>::value &&
|
||||||
!std::is_same<const char*, T>::value>::type> : public basic_column_condition
|
!std::is_same<const char*, T>::value>::type> : public basic_column_condition
|
||||||
{
|
{
|
||||||
@@ -82,10 +87,32 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
class condition<T, column, typename std::enable_if<
|
class condition<column, T, std::enable_if_t<std::is_enum_v<T>>> final : public basic_column_condition
|
||||||
std::is_scalar<T>::value &&
|
{
|
||||||
!std::is_same<std::string, T>::value &&
|
public:
|
||||||
!std::is_same<const char*, T>::value>::type> : public basic_column_condition
|
condition(const column &fld, basic_condition::operand_t op, T val)
|
||||||
|
: basic_column_condition(fld, op)
|
||||||
|
, value(val)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
T value;
|
||||||
|
|
||||||
|
std::string evaluate(const dialect &d, query_context &query) const override
|
||||||
|
{
|
||||||
|
auto at = data_type_traits<T>::create_value(value);
|
||||||
|
any_type_to_string_visitor value_to_string(d, query);
|
||||||
|
std::visit(value_to_string, at);
|
||||||
|
return value_to_string.result + " " + operand + " " + d.prepare_identifier(field_);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class condition<T, column, std::enable_if_t<
|
||||||
|
std::is_scalar_v<T> &&
|
||||||
|
!std::is_same_v<std::string, T> &&
|
||||||
|
!std::is_same_v<const char*, T>>> final : public basic_column_condition
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
condition(T val, basic_condition::operand_t op, const column &fld)
|
condition(T val, basic_condition::operand_t op, const column &fld)
|
||||||
@@ -215,7 +242,7 @@ public:
|
|||||||
* @param op Operand of the condition
|
* @param op Operand of the condition
|
||||||
* @param q The query to be evaluated to the IN arguments
|
* @param q The query to be evaluated to the IN arguments
|
||||||
*/
|
*/
|
||||||
condition(column col, basic_condition::operand_t op, query_context &q);
|
condition(column col, basic_condition::operand_t op, const query_context &q);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Evaluates the condition
|
* @brief Evaluates the condition
|
||||||
@@ -229,7 +256,7 @@ public:
|
|||||||
std::string evaluate(const dialect &d, query_context &query) const override;
|
std::string evaluate(const dialect &d, query_context &query) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
query_context &query_;
|
query_context query_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -415,7 +442,8 @@ condition<column, std::initializer_list<V>> in(const column &col, std::initializ
|
|||||||
* @param q The query to be executes as sub select
|
* @param q The query to be executes as sub select
|
||||||
* @return The condition object
|
* @return The condition object
|
||||||
*/
|
*/
|
||||||
condition<column, query_context> in(const column &col, query_context &&q);
|
condition<column, query_context> in(const column &col, const query_context &q);
|
||||||
|
condition<column, query_context> in(const column &col, const query_select &q);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a between condition.
|
* @brief Creates a between condition.
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ template <> struct data_type_traits<nullptr_t, void>
|
|||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, nullptr_t &/*value*/);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, nullptr_t &/*value*/);
|
||||||
static void bind_value(parameter_binder &binder, size_t index, nullptr_t &/*value*/);
|
static void bind_value(parameter_binder &binder, size_t index, nullptr_t &/*value*/);
|
||||||
static void bind_result_value(result_parameter_binder &binder, size_t index, nullptr_t &/*value*/);
|
static void bind_result_value(result_parameter_binder &binder, size_t index, nullptr_t &/*value*/);
|
||||||
inline static any_type create_value(char &value) { return value; }
|
inline static any_type create_value(const char &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<char, void>
|
template <> struct data_type_traits<char, void>
|
||||||
@@ -68,7 +68,7 @@ template <> struct data_type_traits<char, void>
|
|||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, char &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, char &value);
|
||||||
static void bind_value(parameter_binder &binder, size_t index, char &value);
|
static void bind_value(parameter_binder &binder, size_t index, char &value);
|
||||||
static void bind_result_value(result_parameter_binder &binder, size_t index, char &value);
|
static void bind_result_value(result_parameter_binder &binder, size_t index, char &value);
|
||||||
inline static any_type create_value(char &value) { return value; }
|
inline static any_type create_value(const char &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<short, void>
|
template <> struct data_type_traits<short, void>
|
||||||
@@ -77,7 +77,7 @@ template <> struct data_type_traits<short, void>
|
|||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, short &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, short &value);
|
||||||
static void bind_value(parameter_binder &binder, size_t index, short &value);
|
static void bind_value(parameter_binder &binder, size_t index, short &value);
|
||||||
static void bind_result_value(result_parameter_binder &binder, size_t index, short &value);
|
static void bind_result_value(result_parameter_binder &binder, size_t index, short &value);
|
||||||
inline static any_type create_value(short &value) { return value; }
|
inline static any_type create_value(const short &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<int, void>
|
template <> struct data_type_traits<int, void>
|
||||||
@@ -86,7 +86,7 @@ template <> struct data_type_traits<int, void>
|
|||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, int &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, int &value);
|
||||||
static void bind_value(parameter_binder &binder, size_t index, int &value);
|
static void bind_value(parameter_binder &binder, size_t index, int &value);
|
||||||
static void bind_result_value(result_parameter_binder &binder, size_t index, int &value);
|
static void bind_result_value(result_parameter_binder &binder, size_t index, int &value);
|
||||||
inline static any_type create_value(int &value) { return value; }
|
inline static any_type create_value(const int &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<long, void>
|
template <> struct data_type_traits<long, void>
|
||||||
@@ -95,7 +95,7 @@ template <> struct data_type_traits<long, void>
|
|||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, long &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, long &value);
|
||||||
static void bind_value(parameter_binder &binder, size_t index, long &value);
|
static void bind_value(parameter_binder &binder, size_t index, long &value);
|
||||||
static void bind_result_value(result_parameter_binder &binder, size_t index, long &value);
|
static void bind_result_value(result_parameter_binder &binder, size_t index, long &value);
|
||||||
inline static any_type create_value(long &value) { return value; }
|
inline static any_type create_value(const long &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<long long, void>
|
template <> struct data_type_traits<long long, void>
|
||||||
@@ -104,7 +104,7 @@ template <> struct data_type_traits<long long, void>
|
|||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, long long &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, long long &value);
|
||||||
static void bind_value(parameter_binder &binder, size_t index, long long &value);
|
static void bind_value(parameter_binder &binder, size_t index, long long &value);
|
||||||
static void bind_result_value(result_parameter_binder &binder, size_t index, long long &value);
|
static void bind_result_value(result_parameter_binder &binder, size_t index, long long &value);
|
||||||
inline static any_type create_value(long long &value) { return value; }
|
inline static any_type create_value(const long long &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<unsigned char, void>
|
template <> struct data_type_traits<unsigned char, void>
|
||||||
@@ -113,7 +113,7 @@ template <> struct data_type_traits<unsigned char, void>
|
|||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned char &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned char &value);
|
||||||
static void bind_value(parameter_binder &binder, size_t index, unsigned char &value);
|
static void bind_value(parameter_binder &binder, size_t index, unsigned char &value);
|
||||||
static void bind_result_value(result_parameter_binder &binder, size_t index, unsigned char &value);
|
static void bind_result_value(result_parameter_binder &binder, size_t index, unsigned char &value);
|
||||||
inline static any_type create_value(unsigned char &value) { return value; }
|
inline static any_type create_value(const unsigned char &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<unsigned short, void>
|
template <> struct data_type_traits<unsigned short, void>
|
||||||
@@ -122,7 +122,7 @@ template <> struct data_type_traits<unsigned short, void>
|
|||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned short &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned short &value);
|
||||||
static void bind_value(parameter_binder &binder, size_t index, unsigned short &value);
|
static void bind_value(parameter_binder &binder, size_t index, unsigned short &value);
|
||||||
static void bind_result_value(result_parameter_binder &binder, size_t index, unsigned short &value);
|
static void bind_result_value(result_parameter_binder &binder, size_t index, unsigned short &value);
|
||||||
inline static any_type create_value(unsigned short &value) { return value; }
|
inline static any_type create_value(const unsigned short &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<unsigned int, void>
|
template <> struct data_type_traits<unsigned int, void>
|
||||||
@@ -131,7 +131,7 @@ template <> struct data_type_traits<unsigned int, void>
|
|||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned int &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned int &value);
|
||||||
static void bind_value(parameter_binder &binder, size_t index, unsigned int &value);
|
static void bind_value(parameter_binder &binder, size_t index, unsigned int &value);
|
||||||
static void bind_result_value(result_parameter_binder &binder, size_t index, unsigned int &value);
|
static void bind_result_value(result_parameter_binder &binder, size_t index, unsigned int &value);
|
||||||
inline static any_type create_value(unsigned int &value) { return value; }
|
inline static any_type create_value(const unsigned int &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<unsigned long, void>
|
template <> struct data_type_traits<unsigned long, void>
|
||||||
@@ -140,7 +140,7 @@ template <> struct data_type_traits<unsigned long, void>
|
|||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned long &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned long &value);
|
||||||
static void bind_value(parameter_binder &binder, size_t index, unsigned long &value);
|
static void bind_value(parameter_binder &binder, size_t index, unsigned long &value);
|
||||||
static void bind_result_value(result_parameter_binder &binder, size_t index, unsigned long &value);
|
static void bind_result_value(result_parameter_binder &binder, size_t index, unsigned long &value);
|
||||||
inline static any_type create_value(unsigned long &value) { return value; }
|
inline static any_type create_value(const unsigned long &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<unsigned long long, void>
|
template <> struct data_type_traits<unsigned long long, void>
|
||||||
@@ -149,7 +149,7 @@ template <> struct data_type_traits<unsigned long long, void>
|
|||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned long long &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, unsigned long long &value);
|
||||||
static void bind_value(parameter_binder &binder, size_t index, unsigned long long &value);
|
static void bind_value(parameter_binder &binder, size_t index, unsigned long long &value);
|
||||||
static void bind_result_value(result_parameter_binder &binder, size_t index, unsigned long long &value);
|
static void bind_result_value(result_parameter_binder &binder, size_t index, unsigned long long &value);
|
||||||
inline static any_type create_value(unsigned long long &value) { return value; }
|
inline static any_type create_value(const unsigned long long &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<bool, void>
|
template <> struct data_type_traits<bool, void>
|
||||||
@@ -158,7 +158,7 @@ template <> struct data_type_traits<bool, void>
|
|||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, bool &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, bool &value);
|
||||||
static void bind_value(parameter_binder &binder, size_t index, bool &value);
|
static void bind_value(parameter_binder &binder, size_t index, bool &value);
|
||||||
static void bind_result_value(result_parameter_binder &binder, size_t index, bool &value);
|
static void bind_result_value(result_parameter_binder &binder, size_t index, bool &value);
|
||||||
inline static any_type create_value(bool &value) { return value; }
|
inline static any_type create_value(const bool &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<float, void>
|
template <> struct data_type_traits<float, void>
|
||||||
@@ -167,7 +167,7 @@ template <> struct data_type_traits<float, void>
|
|||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, float &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, float &value);
|
||||||
static void bind_result_value(result_parameter_binder &binder, size_t index, float &value);
|
static void bind_result_value(result_parameter_binder &binder, size_t index, float &value);
|
||||||
static void bind_value(parameter_binder &binder, size_t index, float &value);
|
static void bind_value(parameter_binder &binder, size_t index, float &value);
|
||||||
inline static any_type create_value(float &value) { return value; }
|
inline static any_type create_value(const float &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<double, void>
|
template <> struct data_type_traits<double, void>
|
||||||
@@ -176,7 +176,7 @@ template <> struct data_type_traits<double, void>
|
|||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, double &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, double &value);
|
||||||
static void bind_result_value(result_parameter_binder &binder, size_t index, double &value);
|
static void bind_result_value(result_parameter_binder &binder, size_t index, double &value);
|
||||||
static void bind_value(parameter_binder &binder, size_t index, double &value);
|
static void bind_value(parameter_binder &binder, size_t index, double &value);
|
||||||
inline static any_type create_value(double &value) { return value; }
|
inline static any_type create_value(const double &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<const char*, void>
|
template <> struct data_type_traits<const char*, void>
|
||||||
@@ -203,7 +203,7 @@ template <> struct data_type_traits<std::string, void>
|
|||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, std::string &value, size_t size);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, std::string &value, size_t size);
|
||||||
static void bind_value(parameter_binder &binder, size_t index, std::string &value, size_t size = 0);
|
static void bind_value(parameter_binder &binder, size_t index, std::string &value, size_t size = 0);
|
||||||
static void bind_result_value(result_parameter_binder &binder, size_t index, std::string &value, size_t size = 0);
|
static void bind_result_value(result_parameter_binder &binder, size_t index, std::string &value, size_t size = 0);
|
||||||
inline static any_type create_value(std::string &value) { return value; }
|
inline static any_type create_value(const std::string &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct data_type_traits<utils::blob, void>
|
template <> struct data_type_traits<utils::blob, void>
|
||||||
@@ -212,7 +212,7 @@ template <> struct data_type_traits<utils::blob, void>
|
|||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, utils::blob &value);
|
static void read_value(query_result_reader &reader, const char *id, size_t index, utils::blob &value);
|
||||||
static void bind_value(parameter_binder &binder, size_t index, utils::blob &value);
|
static void bind_value(parameter_binder &binder, size_t index, utils::blob &value);
|
||||||
static void bind_result_value(result_parameter_binder &binder, size_t index, utils::blob &value);
|
static void bind_result_value(result_parameter_binder &binder, size_t index, utils::blob &value);
|
||||||
inline static any_type create_value(utils::blob &value) { return value; }
|
inline static any_type create_value(const utils::blob &value) { return value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
//template <> struct data_type_traits<matador::date>
|
//template <> struct data_type_traits<matador::date>
|
||||||
@@ -232,7 +232,7 @@ template <> struct data_type_traits<utils::blob, void>
|
|||||||
//};
|
//};
|
||||||
|
|
||||||
template < typename EnumType >
|
template < typename EnumType >
|
||||||
struct data_type_traits<EnumType, typename std::enable_if<std::is_enum<EnumType>::value>::type>
|
struct data_type_traits<EnumType, std::enable_if_t<std::is_enum_v<EnumType>>>
|
||||||
{
|
{
|
||||||
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_int; }
|
inline static data_type_t builtin_type(std::size_t /*size*/) { return data_type_t::type_int; }
|
||||||
static void read_value(query_result_reader &reader, const char *id, size_t index, EnumType &value)
|
static void read_value(query_result_reader &reader, const char *id, size_t index, EnumType &value)
|
||||||
@@ -241,13 +241,15 @@ struct data_type_traits<EnumType, typename std::enable_if<std::is_enum<EnumType>
|
|||||||
}
|
}
|
||||||
static void bind_value(parameter_binder &binder, size_t index, EnumType &value)
|
static void bind_value(parameter_binder &binder, size_t index, EnumType &value)
|
||||||
{
|
{
|
||||||
data_type_traits<int>::bind_value(binder, index, (int&)value);
|
data_type_traits<int>::bind_value(binder, index, static_cast<int&>(value));
|
||||||
}
|
}
|
||||||
static void bind_result_value(result_parameter_binder &binder, size_t index, EnumType &value)
|
static void bind_result_value(result_parameter_binder &binder, size_t index, EnumType &value)
|
||||||
{
|
{
|
||||||
data_type_traits<int>::bind_result_value(binder, index, (int&)value);
|
data_type_traits<int>::bind_result_value(binder, index, static_cast<int&>(value));
|
||||||
|
}
|
||||||
|
static any_type create_value(const EnumType &value) {
|
||||||
|
return static_cast<int>(value);
|
||||||
}
|
}
|
||||||
inline static any_type create_value(EnumType &value) { return (int)value; }
|
|
||||||
};
|
};
|
||||||
/// @endcond
|
/// @endcond
|
||||||
|
|
||||||
|
|||||||
@@ -57,14 +57,10 @@ public:
|
|||||||
private:
|
private:
|
||||||
join_columns join_columns_;
|
join_columns join_columns_;
|
||||||
};
|
};
|
||||||
struct join_data
|
|
||||||
{
|
|
||||||
table join_table;
|
|
||||||
std::unique_ptr<basic_condition> condition;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct entity_query_data {
|
struct entity_query_data {
|
||||||
std::string root_table_name;
|
std::string root_table_name;
|
||||||
|
std::string pk_column_;
|
||||||
std::vector<column> columns;
|
std::vector<column> columns;
|
||||||
std::vector<join_data> joins;
|
std::vector<join_data> joins;
|
||||||
std::unique_ptr<basic_condition> where_clause;
|
std::unique_ptr<basic_condition> where_clause;
|
||||||
@@ -140,8 +136,14 @@ public:
|
|||||||
void on_primary_key(const char *id, V &, typename std::enable_if<std::is_integral<V>::value && !std::is_same<bool, V>::value>::type* = 0)
|
void on_primary_key(const char *id, V &, typename std::enable_if<std::is_integral<V>::value && !std::is_same<bool, V>::value>::type* = 0)
|
||||||
{
|
{
|
||||||
push(id);
|
push(id);
|
||||||
if (is_root_entity() && pk_.is_integer()) {
|
if (!is_root_entity()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pk_.is_null()) {
|
||||||
|
entity_query_data_.pk_column_ = id;
|
||||||
|
} else if (pk_.is_integer()) {
|
||||||
entity_query_data_.where_clause = make_condition(column{table_info_stack_.top().name, id, ""} == *pk_.as<V>());
|
entity_query_data_.where_clause = make_condition(column{table_info_stack_.top().name, id, ""} == *pk_.as<V>());
|
||||||
|
entity_query_data_.pk_column_ = id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -150,12 +150,21 @@ public:
|
|||||||
|
|
||||||
class query_join_intermediate;
|
class query_join_intermediate;
|
||||||
|
|
||||||
class query_on_intermediate : public query_select
|
struct join_data
|
||||||
|
{
|
||||||
|
table join_table;
|
||||||
|
std::unique_ptr<basic_condition> condition;
|
||||||
|
};
|
||||||
|
|
||||||
|
class query_from_intermediate : public query_select
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using query_select::query_select;
|
using query_select::query_select;
|
||||||
|
|
||||||
query_join_intermediate join_left(const table &t);
|
query_join_intermediate join_left(const table &t);
|
||||||
|
query_from_intermediate join_left(join_data &data);
|
||||||
|
query_from_intermediate join_left(std::vector<join_data> &data_vector);
|
||||||
|
|
||||||
template<class Condition>
|
template<class Condition>
|
||||||
query_where_intermediate where(const Condition &cond)
|
query_where_intermediate where(const Condition &cond)
|
||||||
{
|
{
|
||||||
@@ -172,6 +181,8 @@ private:
|
|||||||
query_where_intermediate where_clause(std::unique_ptr<basic_condition> &&cond);
|
query_where_intermediate where_clause(std::unique_ptr<basic_condition> &&cond);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using query_on_intermediate = query_from_intermediate;
|
||||||
|
|
||||||
class query_join_intermediate : public query_intermediate
|
class query_join_intermediate : public query_intermediate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -191,28 +202,6 @@ private:
|
|||||||
query_on_intermediate on_clause(std::unique_ptr<basic_condition> &&cond);
|
query_on_intermediate on_clause(std::unique_ptr<basic_condition> &&cond);
|
||||||
};
|
};
|
||||||
|
|
||||||
class query_from_intermediate : public query_select
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using query_select::query_select;
|
|
||||||
|
|
||||||
query_join_intermediate join_left(const table &t);
|
|
||||||
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<basic_condition> &&cond)
|
|
||||||
{
|
|
||||||
return where_clause(std::move(cond));
|
|
||||||
}
|
|
||||||
query_group_by_intermediate group_by(const column &col);
|
|
||||||
query_order_by_intermediate order_by(const column &col);
|
|
||||||
|
|
||||||
private:
|
|
||||||
query_where_intermediate where_clause(std::unique_ptr<basic_condition> &&cond);
|
|
||||||
};
|
|
||||||
|
|
||||||
class query_start_intermediate : public basic_query_intermediate
|
class query_start_intermediate : public basic_query_intermediate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ struct column;
|
|||||||
class record
|
class record
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using field_by_index = std::vector<field>;
|
using field_ref = std::reference_wrapper<field>;
|
||||||
using field_index_pair = std::pair<std::reference_wrapper<field>, field_by_index::difference_type>;
|
using field_by_index = std::vector<field_ref>;
|
||||||
|
using field_index_pair = std::pair<field, field_by_index::difference_type>;
|
||||||
using field_by_name_map = std::unordered_map<std::string, field_index_pair>;
|
using field_by_name_map = std::unordered_map<std::string, field_index_pair>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -36,13 +37,13 @@ public:
|
|||||||
void process(Operator &op)
|
void process(Operator &op)
|
||||||
{
|
{
|
||||||
for(auto &f : fields_) {
|
for(auto &f : fields_) {
|
||||||
f.process(op);
|
f.get().process(op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(field col);
|
void append(const field &col);
|
||||||
|
|
||||||
[[nodiscard]] const std::vector<field>& columns() const;
|
[[nodiscard]] const std::vector<field_ref>& columns() const;
|
||||||
|
|
||||||
[[nodiscard]] const field& at(const column &col) const;
|
[[nodiscard]] const field& at(const column &col) const;
|
||||||
[[nodiscard]] const field& at(size_t index) const;
|
[[nodiscard]] const field& at(size_t index) const;
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] std::string name() const;
|
[[nodiscard]] std::string name() const;
|
||||||
|
|
||||||
|
void create(connection &c);
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
const table_info& attach(const std::string &table_name)
|
const table_info& attach(const std::string &table_name)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,13 +14,22 @@ struct table
|
|||||||
table(const char *name, std::string as = "") // NOLINT(*-explicit-constructor)
|
table(const char *name, std::string as = "") // NOLINT(*-explicit-constructor)
|
||||||
: name(name), alias(std::move(as)) {}
|
: name(name), alias(std::move(as)) {}
|
||||||
table(std::string name, std::string as = "") // NOLINT(*-explicit-constructor)
|
table(std::string name, std::string as = "") // NOLINT(*-explicit-constructor)
|
||||||
: name(std::move(name)), alias(std::move(as)) {}
|
: name(std::move(name))
|
||||||
|
, alias(std::move(as)) {}
|
||||||
|
table(std::string name, std::string as, const std::vector<column> &columns)
|
||||||
|
: name(std::move(name))
|
||||||
|
, alias(std::move(as))
|
||||||
|
, columns(columns) {}
|
||||||
|
|
||||||
table& as(const std::string &a) {
|
table& as(const std::string &a) {
|
||||||
alias = a;
|
alias = a;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] table as(const std::string &a) const {
|
||||||
|
return { name, a, columns };
|
||||||
|
}
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string alias;
|
std::string alias;
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "matador/sql/noop_connection.hpp"
|
#include "matador/sql/noop_connection.hpp"
|
||||||
#include "matador/sql/dialect_builder.hpp"
|
#include "matador/sql/dialect_builder.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|||||||
+20
-2
@@ -1,5 +1,7 @@
|
|||||||
#include "matador/sql/condition.hpp"
|
#include "matador/sql/condition.hpp"
|
||||||
|
|
||||||
|
#include "matador/sql/query_intermediates.hpp"
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
condition<column, placeholder, std::enable_if<true>::type>::condition(const column &fld, basic_condition::operand_t op, const placeholder &val)
|
condition<column, placeholder, std::enable_if<true>::type>::condition(const column &fld, basic_condition::operand_t op, const placeholder &val)
|
||||||
@@ -12,17 +14,33 @@ std::string condition<column, placeholder, std::enable_if<true>::type>::evaluate
|
|||||||
return d.prepare_identifier(field_) + " " + operand + " " + d.next_placeholder(query.bind_vars);
|
return d.prepare_identifier(field_) + " " + operand + " " + d.next_placeholder(query.bind_vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
condition<column, query_context>::condition(column col, basic_condition::operand_t op, query_context &q)
|
condition<column, query_context>::condition(column col, basic_condition::operand_t op, const query_context &q)
|
||||||
: basic_column_condition(std::move(col), op), query_(q)
|
: basic_column_condition(std::move(col), op), query_(q)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
std::string condition<column, query_context>::evaluate(const dialect &d, query_context &query) const
|
std::string condition<column, query_context>::evaluate(const dialect &d, query_context &query) const
|
||||||
{
|
{
|
||||||
std::string result(d.prepare_identifier(field_) + " " + operand + " (");
|
std::string result(d.prepare_identifier(field_) + " " + operand + " (");
|
||||||
result += (")");
|
result += query_.sql + (")");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
condition<column, query_context> in( const column& col, const query_context &q ) {
|
||||||
|
return {col, basic_condition::operand_t::IN_LIST, q};
|
||||||
|
}
|
||||||
|
|
||||||
|
condition<column, query_context> in( const column& col, const query_select& q ) {
|
||||||
|
return in(col, q.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
condition<column, std::string> like( const column& col, const std::string& val ) {
|
||||||
|
return {col, basic_condition::operand_t::LIKE, val};
|
||||||
|
}
|
||||||
|
|
||||||
|
condition<column, query_context> equals( const column& col, query_context& q ) {
|
||||||
|
return {col, basic_condition::operand_t::EQUAL, q};
|
||||||
|
}
|
||||||
|
|
||||||
condition<column, column> operator==(const column &a, const column &b)
|
condition<column, column> operator==(const column &a, const column &b)
|
||||||
{
|
{
|
||||||
return {a, basic_condition::operand_t::EQUAL, b};
|
return {a, basic_condition::operand_t::EQUAL, b};
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ size_t connection::execute(const std::string &sql) const
|
|||||||
return connection_->execute(sql);
|
return connection_->execute(sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
sql::query connection::query(const sql::schema &schema) const
|
sql::query connection::query(const schema &schema) const
|
||||||
{
|
{
|
||||||
return sql::query(*const_cast<connection*>(this), schema);
|
return sql::query(*const_cast<connection*>(this), schema);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -51,8 +51,8 @@ std::string dialect::prepare_literal(const std::string &str) const
|
|||||||
|
|
||||||
void dialect::quote_identifier(std::string &str) const
|
void dialect::quote_identifier(std::string &str) const
|
||||||
{
|
{
|
||||||
str.insert(0, token_at(token_t::START_QUOTE));
|
// str.insert(0, token_at(token_t::START_QUOTE));
|
||||||
str += token_at(token_t::END_QUOTE);
|
// str += token_at(token_t::END_QUOTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dialect::escape_quotes_in_identifier(std::string &str) const
|
void dialect::escape_quotes_in_identifier(std::string &str) const
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ void query_compiler::visit(query_select_part &select_part)
|
|||||||
void query_compiler::visit(query_from_part &from_part)
|
void query_compiler::visit(query_from_part &from_part)
|
||||||
{
|
{
|
||||||
query_.table = from_part.table();
|
query_.table = from_part.table();
|
||||||
if (dialect_.default_schema_name().empty()) {
|
if (!dialect_.default_schema_name().empty()) {
|
||||||
query_.sql += " " + dialect_.token_at(dialect::token_t::FROM) +
|
query_.sql += " " + dialect_.token_at(dialect::token_t::FROM) +
|
||||||
" " + dialect_.prepare_identifier(from_part.table().name) +
|
" " + dialect_.prepare_identifier(from_part.table().name) +
|
||||||
(from_part.table().alias.empty() ? "" : " AS " +
|
(from_part.table().alias.empty() ? "" : " AS " +
|
||||||
|
|||||||
@@ -85,7 +85,9 @@ query_order_direction_intermediate query_order_by_intermediate::desc()
|
|||||||
|
|
||||||
query_where_intermediate query_from_intermediate::where_clause(std::unique_ptr<basic_condition> &&cond)
|
query_where_intermediate query_from_intermediate::where_clause(std::unique_ptr<basic_condition> &&cond)
|
||||||
{
|
{
|
||||||
data_->parts.push_back(std::make_unique<query_where_part>(std::move(cond)));
|
if (cond) {
|
||||||
|
data_->parts.push_back(std::make_unique<query_where_part>(std::move(cond)));
|
||||||
|
}
|
||||||
return {connection_, schema_, data_};
|
return {connection_, schema_, data_};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,30 +115,6 @@ query_order_by_intermediate query_where_intermediate::order_by(const column &col
|
|||||||
return {connection_, schema_, data_};
|
return {connection_, schema_, data_};
|
||||||
}
|
}
|
||||||
|
|
||||||
query_join_intermediate query_on_intermediate::join_left(const table &t)
|
|
||||||
{
|
|
||||||
data_->parts.push_back(std::make_unique<query_join_part>(t));
|
|
||||||
return {connection_, schema_, data_};
|
|
||||||
}
|
|
||||||
|
|
||||||
query_where_intermediate query_on_intermediate::where_clause(std::unique_ptr<basic_condition> &&cond)
|
|
||||||
{
|
|
||||||
data_->parts.push_back(std::make_unique<query_where_part>(std::move(cond)));
|
|
||||||
return {connection_, schema_, data_};
|
|
||||||
}
|
|
||||||
|
|
||||||
query_group_by_intermediate query_on_intermediate::group_by(const column &col)
|
|
||||||
{
|
|
||||||
data_->parts.push_back(std::make_unique<query_group_by_part>(col));
|
|
||||||
return {connection_, schema_, data_};
|
|
||||||
}
|
|
||||||
|
|
||||||
query_order_by_intermediate query_on_intermediate::order_by(const column &col)
|
|
||||||
{
|
|
||||||
data_->parts.push_back(std::make_unique<query_order_by_part>(col));
|
|
||||||
return {connection_, schema_, data_};
|
|
||||||
}
|
|
||||||
|
|
||||||
query_on_intermediate query_join_intermediate::on_clause(std::unique_ptr<basic_condition> &&cond)
|
query_on_intermediate query_join_intermediate::on_clause(std::unique_ptr<basic_condition> &&cond)
|
||||||
{
|
{
|
||||||
data_->parts.push_back(std::make_unique<query_on_part>(std::move(cond)));
|
data_->parts.push_back(std::make_unique<query_on_part>(std::move(cond)));
|
||||||
@@ -149,6 +127,22 @@ query_join_intermediate query_from_intermediate::join_left(const table &t)
|
|||||||
return {connection_, schema_, data_};
|
return {connection_, schema_, data_};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query_from_intermediate query_from_intermediate::join_left(join_data &data)
|
||||||
|
{
|
||||||
|
data_->parts.push_back(std::make_unique<query_join_part>(data.join_table));
|
||||||
|
data_->parts.push_back(std::make_unique<query_on_part>(std::move(data.condition)));
|
||||||
|
return {connection_, schema_, data_};
|
||||||
|
}
|
||||||
|
|
||||||
|
query_from_intermediate query_from_intermediate::join_left(std::vector<join_data> &data_vector)
|
||||||
|
{
|
||||||
|
for (auto &data : data_vector) {
|
||||||
|
data_->parts.push_back(std::make_unique<query_join_part>(data.join_table));
|
||||||
|
data_->parts.push_back(std::make_unique<query_on_part>(std::move(data.condition)));
|
||||||
|
}
|
||||||
|
return {connection_, schema_, data_};
|
||||||
|
}
|
||||||
|
|
||||||
query_select_intermediate::query_select_intermediate(connection &db, const sql::schema &schema, const std::vector<column>& columns)
|
query_select_intermediate::query_select_intermediate(connection &db, const sql::schema &schema, const std::vector<column>& columns)
|
||||||
: query_start_intermediate(db, schema)
|
: query_start_intermediate(db, schema)
|
||||||
{
|
{
|
||||||
|
|||||||
+22
-16
@@ -7,23 +7,27 @@
|
|||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
record::record(std::initializer_list<field> columns)
|
record::record(std::initializer_list<field> columns)
|
||||||
: fields_(columns)
|
|
||||||
{
|
{
|
||||||
init();
|
for (auto &&col :columns) {
|
||||||
|
const auto it = fields_by_name_.emplace(col.name(), field_index_pair {col, fields_.size()});
|
||||||
|
fields_.push_back(std::ref(it.first->second.first));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
record::record(const std::vector<field> &columns)
|
record::record(const std::vector<field> &columns)
|
||||||
: fields_(columns)
|
|
||||||
{
|
{
|
||||||
init();
|
for (auto &&col :columns) {
|
||||||
|
const auto it = fields_by_name_.emplace(col.name(), field_index_pair {col, fields_.size()});
|
||||||
|
fields_.push_back(std::ref(it.first->second.first));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
record::record(const record &x)
|
record::record(const record &x)
|
||||||
: fields_(x.fields_)
|
: fields_by_name_(x.fields_by_name_)
|
||||||
//, pk_index_(x.pk_index_)
|
//, pk_index_(x.pk_index_)
|
||||||
{
|
{
|
||||||
for (auto& col : fields_) {
|
for (auto& col : fields_by_name_) {
|
||||||
add_to_map(col, col.index());
|
fields_.push_back(std::ref(col.second.first));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,16 +37,16 @@ record &record::operator=(const record &x)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
fields_ = x.fields_;
|
fields_by_name_ = x.fields_by_name_;
|
||||||
fields_by_name_.clear();
|
fields_.clear();
|
||||||
// pk_index_ = x.pk_index_;
|
// pk_index_ = x.pk_index_;
|
||||||
for (auto& col : fields_) {
|
for (auto& col : fields_by_name_) {
|
||||||
add_to_map(col, col.index());
|
fields_.push_back(std::ref(col.second.first));
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<field> &record::columns() const
|
const std::vector<record::field_ref> &record::columns() const
|
||||||
{
|
{
|
||||||
return fields_;
|
return fields_;
|
||||||
}
|
}
|
||||||
@@ -63,7 +67,9 @@ const std::vector<field> &record::columns() const
|
|||||||
|
|
||||||
const field &record::at(const column &col) const
|
const field &record::at(const column &col) const
|
||||||
{
|
{
|
||||||
return fields_by_name_.at(col.name).first;
|
const auto &res = fields_by_name_.at(col.name);
|
||||||
|
const auto &f = res.first;
|
||||||
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
const field &record::at(size_t index) const
|
const field &record::at(size_t index) const
|
||||||
@@ -82,10 +88,10 @@ record::const_iterator record::find(const std::string &column_name) const {
|
|||||||
return it != fields_by_name_.end() ? fields_.begin() + it->second.second : fields_.end();
|
return it != fields_by_name_.end() ? fields_.begin() + it->second.second : fields_.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void record::append(field col)
|
void record::append(const field &col)
|
||||||
{
|
{
|
||||||
auto &ref = fields_.emplace_back(std::move(col));
|
const auto it = fields_by_name_.emplace(col.name(), field_index_pair {col, fields_.size()});
|
||||||
add_to_map(ref, fields_.size() - 1);
|
fields_.push_back(std::ref(it.first->second.first));
|
||||||
}
|
}
|
||||||
|
|
||||||
record::iterator record::begin()
|
record::iterator record::begin()
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ namespace matador::sql {
|
|||||||
schema::schema(std::string name)
|
schema::schema(std::string name)
|
||||||
: name_(std::move(name)) {}
|
: name_(std::move(name)) {}
|
||||||
|
|
||||||
|
void schema::create(connection &c) {
|
||||||
|
for (const auto &ti : repository_) {
|
||||||
|
// ti.second.prototype
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string schema::name() const
|
std::string schema::name() const
|
||||||
{
|
{
|
||||||
return name_;
|
return name_;
|
||||||
|
|||||||
+7
-18
@@ -105,24 +105,13 @@ std::unique_ptr<query_result_impl> session::fetch(const std::string &sql) const
|
|||||||
|
|
||||||
query_select session::build_select_query(connection_ptr<connection> &conn, entity_query_data &&data) const
|
query_select session::build_select_query(connection_ptr<connection> &conn, entity_query_data &&data) const
|
||||||
{
|
{
|
||||||
auto q = conn->query(*schema_)
|
return conn->query(*schema_)
|
||||||
.select(data.columns)
|
.select(data.columns)
|
||||||
.from(data.root_table_name);
|
.from(data.root_table_name)
|
||||||
|
.join_left(data.joins)
|
||||||
|
.where(std::move(data.where_clause))
|
||||||
|
.order_by({data.root_table_name, data.pk_column_})
|
||||||
|
.asc();
|
||||||
|
}
|
||||||
|
|
||||||
auto it = data.joins.begin();
|
|
||||||
if (it != data.joins.end()) {
|
|
||||||
auto qj = q.join_left(it->join_table).on(std::move(it->condition));
|
|
||||||
while (++it != data.joins.end()) {
|
|
||||||
qj.join_left(it->join_table).on(std::move(it->condition));
|
|
||||||
}
|
|
||||||
if (data.where_clause) {
|
|
||||||
return qj.where(std::move(data.where_clause));
|
|
||||||
}
|
|
||||||
return qj;
|
|
||||||
} else if (data.where_clause) {
|
|
||||||
return q.where(std::move(data.where_clause));
|
|
||||||
} else {
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+7
-2
@@ -25,7 +25,12 @@ utils::result<float, math_error>plus(int x, int y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
utils::result<float, std::string>error_to_string(math_error err) {
|
utils::result<float, std::string>error_to_string(math_error err) {
|
||||||
return utils::error(std::string("error"));
|
switch (err) {
|
||||||
|
case math_error::DIVISION_BY_ZERO:
|
||||||
|
return utils::error(std::string("division by zero error"));
|
||||||
|
default:
|
||||||
|
return utils::error(std::string("unknown error"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -76,7 +81,7 @@ TEST_CASE("Result tests", "[result]") {
|
|||||||
REQUIRE(!res2);
|
REQUIRE(!res2);
|
||||||
REQUIRE(!res2.is_ok());
|
REQUIRE(!res2.is_ok());
|
||||||
REQUIRE(res2.is_error());
|
REQUIRE(res2.is_error());
|
||||||
REQUIRE((res2.err() == "error"));
|
REQUIRE((res2.err() == "division by zero error"));
|
||||||
|
|
||||||
res = test::divide(4, 2)
|
res = test::divide(4, 2)
|
||||||
.and_then([](const auto &val) { return test::multiply(val, 5); })
|
.and_then([](const auto &val) { return test::multiply(val, 5); })
|
||||||
|
|||||||
Reference in New Issue
Block a user