renamed foreign class to entity, introduced interface class query_result_reader
This commit is contained in:
parent
700cbc0652
commit
c2a96f4cbd
2
Todo.md
2
Todo.md
|
|
@ -1,7 +1,7 @@
|
||||||
# Todo
|
# Todo
|
||||||
|
|
||||||
- Add is_valid() method to connection & connection_impl
|
- Add is_valid() method to connection & connection_impl
|
||||||
- Read in foreign fields
|
- Read in entity fields
|
||||||
- Add special handling for update in backends
|
- Add special handling for update in backends
|
||||||
- Add PostgreSQL backend
|
- Add PostgreSQL backend
|
||||||
- Add MySQL/MariaDB backend
|
- Add MySQL/MariaDB backend
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@ set(HEADER
|
||||||
include/sqlite_connection.hpp
|
include/sqlite_connection.hpp
|
||||||
include/sqlite_error.hpp
|
include/sqlite_error.hpp
|
||||||
include/sqlite_dialect.hpp
|
include/sqlite_dialect.hpp
|
||||||
include/sqlite_query_result.hpp
|
include/sqlite_result_reader.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
src/sqlite_connection.cpp
|
src/sqlite_connection.cpp
|
||||||
src/sqlite_error.cpp
|
src/sqlite_error.cpp
|
||||||
src/sqlite_dialect.cpp
|
src/sqlite_dialect.cpp
|
||||||
src/sqlite_query_result.cpp
|
src/sqlite_result_reader.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(matador-sqlite SHARED ${SOURCES} ${HEADER})
|
add_library(matador-sqlite SHARED ${SOURCES} ${HEADER})
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
#include "matador/sql/connection_impl.hpp"
|
#include "matador/sql/connection_impl.hpp"
|
||||||
|
|
||||||
|
#include "sqlite_result_reader.hpp"
|
||||||
|
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
|
|
||||||
namespace matador::backends::sqlite {
|
namespace matador::backends::sqlite {
|
||||||
|
|
@ -35,9 +37,18 @@ public:
|
||||||
|
|
||||||
bool exists(const std::string &table_name) override;
|
bool exists(const std::string &table_name) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct fetch_context
|
||||||
|
{
|
||||||
|
sql::record prototype;
|
||||||
|
sqlite_result_reader::rows rows;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static int parse_result(void* param, int column_count, char** values, char** columns);
|
static int parse_result(void* param, int column_count, char** values, char** columns);
|
||||||
|
|
||||||
|
fetch_context fetch_internal(const std::string &stmt);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sqlite3 *sqlite_db_{};
|
sqlite3 *sqlite_db_{};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,27 @@
|
||||||
#ifndef QUERY_SQLITE_QUERY_RESULT_HPP
|
#ifndef QUERY_SQLITE_RESULT_READER_HPP
|
||||||
#define QUERY_SQLITE_QUERY_RESULT_HPP
|
#define QUERY_SQLITE_RESULT_READER_HPP
|
||||||
|
|
||||||
#include "matador/sql/query_result_impl.hpp"
|
#include "matador/sql/query_result_reader.hpp"
|
||||||
#include "matador/sql/record.hpp"
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace matador::backends::sqlite {
|
namespace matador::backends::sqlite {
|
||||||
|
|
||||||
class sqlite_query_result : public sql::query_result_impl {
|
class sqlite_result_reader : public sql::query_result_reader
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
using columns = std::vector<char*>;
|
using columns = std::vector<char*>;
|
||||||
using rows = std::vector<columns>;
|
using rows = std::vector<columns>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
sqlite_query_result(sql::record prototype, rows result);
|
sqlite_result_reader(rows result, size_t column_count);
|
||||||
~sqlite_query_result() override;
|
~sqlite_result_reader() override;
|
||||||
|
|
||||||
size_t column_count() const override;
|
size_t column_count() const override;
|
||||||
|
|
||||||
|
[[nodiscard]] const char* column(size_t index) const override;
|
||||||
|
[[nodiscard]] bool fetch() override;
|
||||||
|
|
||||||
void read_value(const char *id, size_t index, char &value) override;
|
void read_value(const char *id, size_t index, char &value) override;
|
||||||
void read_value(const char *id, size_t index, short &value) override;
|
void read_value(const char *id, size_t index, short &value) override;
|
||||||
void read_value(const char *id, size_t index, int &value) override;
|
void read_value(const char *id, size_t index, int &value) override;
|
||||||
|
|
@ -37,20 +40,12 @@ public:
|
||||||
void read_value(const char *id, size_t index, std::string &value, size_t s) override;
|
void read_value(const char *id, size_t index, std::string &value, size_t s) override;
|
||||||
void read_value(const char *id, size_t index, sql::any_type &value, sql::data_type_t type, size_t size) override;
|
void read_value(const char *id, size_t index, sql::any_type &value, sql::data_type_t type, size_t size) override;
|
||||||
|
|
||||||
[[nodiscard]] const char* column(size_t index) const override;
|
|
||||||
[[nodiscard]] bool fetch() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class sqlite_connection;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void push_back(char **row_values, int column_count);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rows result_;
|
rows result_;
|
||||||
long long row_index_ = -1;
|
long long row_index_ = -1;
|
||||||
|
size_t column_count_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //QUERY_SQLITE_QUERY_RESULT_HPP
|
#endif //QUERY_SQLITE_RESULT_READER_HPP
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include "sqlite_connection.hpp"
|
#include "sqlite_connection.hpp"
|
||||||
#include "sqlite_error.hpp"
|
#include "sqlite_error.hpp"
|
||||||
#include "sqlite_query_result.hpp"
|
#include "sqlite_result_reader.hpp"
|
||||||
|
|
||||||
#include "matador/sql/record.hpp"
|
#include "matador/sql/record.hpp"
|
||||||
|
|
||||||
|
|
@ -37,17 +37,11 @@ bool sqlite_connection::is_open()
|
||||||
return sqlite_db_ != nullptr;
|
return sqlite_db_ != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fetch_context
|
|
||||||
{
|
|
||||||
sql::record prototype;
|
|
||||||
sqlite_query_result::rows rows;
|
|
||||||
};
|
|
||||||
|
|
||||||
int sqlite_connection::parse_result(void* param, int column_count, char** values, char** columns)
|
int sqlite_connection::parse_result(void* param, int column_count, char** values, char** columns)
|
||||||
{
|
{
|
||||||
auto *context = static_cast<fetch_context*>(param);
|
auto *context = static_cast<fetch_context*>(param);
|
||||||
|
|
||||||
sqlite_query_result::columns column;
|
sqlite_result_reader::columns column;
|
||||||
for(int i = 0; i < column_count; ++i) {
|
for(int i = 0; i < column_count; ++i) {
|
||||||
// copy and store column data;
|
// copy and store column data;
|
||||||
if (values[i] == nullptr) {
|
if (values[i] == nullptr) {
|
||||||
|
|
@ -73,6 +67,17 @@ int sqlite_connection::parse_result(void* param, int column_count, char** values
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sqlite_connection::fetch_context sqlite_connection::fetch_internal(const std::string &stmt)
|
||||||
|
{
|
||||||
|
fetch_context context;
|
||||||
|
char *errmsg = nullptr;
|
||||||
|
const int ret = sqlite3_exec(sqlite_db_, stmt.c_str(), parse_result, &context, &errmsg);
|
||||||
|
|
||||||
|
throw_sqlite_error(ret, sqlite_db_, "sqlite", stmt);
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
size_t sqlite_connection::execute(const std::string &stmt)
|
size_t sqlite_connection::execute(const std::string &stmt)
|
||||||
{
|
{
|
||||||
char *errmsg = nullptr;
|
char *errmsg = nullptr;
|
||||||
|
|
@ -85,13 +90,9 @@ size_t sqlite_connection::execute(const std::string &stmt)
|
||||||
|
|
||||||
std::unique_ptr<sql::query_result_impl> sqlite_connection::fetch(const std::string &stmt)
|
std::unique_ptr<sql::query_result_impl> sqlite_connection::fetch(const std::string &stmt)
|
||||||
{
|
{
|
||||||
fetch_context context;
|
auto context = fetch_internal(stmt);
|
||||||
char *errmsg = nullptr;
|
|
||||||
const int ret = sqlite3_exec(sqlite_db_, stmt.c_str(), parse_result, &context, &errmsg);
|
|
||||||
|
|
||||||
throw_sqlite_error(ret, sqlite_db_, "sqlite", stmt);
|
return std::move(std::make_unique<sql::query_result_impl>(std::make_unique<sqlite_result_reader>(std::move(context.rows), context.prototype.size()), std::move(context.prototype)));
|
||||||
|
|
||||||
return std::move(std::make_unique<sqlite_query_result>(std::move(context.prototype), std::move(context.rows)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqlite_connection::prepare(const std::string &stmt)
|
void sqlite_connection::prepare(const std::string &stmt)
|
||||||
|
|
@ -135,21 +136,21 @@ sql::data_type_t string2type(const char *type)
|
||||||
|
|
||||||
sql::record sqlite_connection::describe(const std::string& table)
|
sql::record sqlite_connection::describe(const std::string& table)
|
||||||
{
|
{
|
||||||
std::string stmt("PRAGMA table_info(" + table + ")");
|
const auto result = fetch_internal("PRAGMA table_info(" + table + ")");
|
||||||
const auto result = fetch("PRAGMA table_info(" + table + ")");
|
|
||||||
|
|
||||||
|
sqlite_result_reader reader(std::move(result.rows), result.prototype.size());
|
||||||
sql::record prototype;
|
sql::record prototype;
|
||||||
while (result->fetch()) {
|
while (reader.fetch()) {
|
||||||
char *end = nullptr;
|
char *end = nullptr;
|
||||||
// Todo: add index to column
|
// Todo: add index to column
|
||||||
auto index = strtoul(result->column(0), &end, 10);
|
auto index = strtoul(reader.column(0), &end, 10);
|
||||||
std::string name = result->column(1);
|
std::string name = reader.column(1);
|
||||||
|
|
||||||
// Todo: extract size
|
// Todo: extract size
|
||||||
auto type = (string2type(result->column(2)));
|
auto type = (string2type(reader.column(2)));
|
||||||
end = nullptr;
|
end = nullptr;
|
||||||
utils::constraints options{};
|
utils::constraints options{};
|
||||||
if (strtoul(result->column(3), &end, 10) == 0) {
|
if (strtoul(reader.column(3), &end, 10) == 0) {
|
||||||
options = utils::constraints::NOT_NULL;
|
options = utils::constraints::NOT_NULL;
|
||||||
}
|
}
|
||||||
// f.default_value(res->column(4));
|
// f.default_value(res->column(4));
|
||||||
|
|
@ -161,15 +162,16 @@ sql::record sqlite_connection::describe(const std::string& table)
|
||||||
|
|
||||||
bool sqlite_connection::exists(const std::string &table_name)
|
bool sqlite_connection::exists(const std::string &table_name)
|
||||||
{
|
{
|
||||||
const auto result = fetch("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND tbl_name='" + table_name + "' LIMIT 1");
|
const auto result = fetch_internal("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND tbl_name='" + table_name + "' LIMIT 1");
|
||||||
|
sqlite_result_reader reader(std::move(result.rows), result.prototype.size());
|
||||||
|
|
||||||
if (!result->fetch()) {
|
if (!reader.fetch()) {
|
||||||
// Todo: throw an exception?
|
// Todo: throw an exception?
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int v{};
|
int v{};
|
||||||
result->read_value(nullptr, 0, v);
|
reader.read_value(nullptr, 0, v);
|
||||||
|
|
||||||
return v == 1;
|
return v == 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
#include "sqlite_query_result.hpp"
|
#include "sqlite_result_reader.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <sqlite3.h>
|
|
||||||
|
|
||||||
namespace matador::backends::sqlite {
|
namespace matador::backends::sqlite {
|
||||||
|
|
||||||
template < class Type >
|
template < class Type >
|
||||||
|
|
@ -50,12 +48,11 @@ void read(Type &x, const char *val, typename std::enable_if<std::is_floating_poi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite_query_result::sqlite_query_result(sql::record prototype, sqlite_query_result::rows result)
|
sqlite_result_reader::sqlite_result_reader(sqlite_result_reader::rows result, size_t column_count)
|
||||||
: sql::query_result_impl(std::move(prototype))
|
: result_(std::move(result))
|
||||||
, result_(std::move(result))
|
, column_count_(column_count) {}
|
||||||
{}
|
|
||||||
|
|
||||||
sqlite_query_result::~sqlite_query_result()
|
sqlite_result_reader::~sqlite_result_reader()
|
||||||
{
|
{
|
||||||
std::for_each(result_.begin(), result_.end(), [](rows ::value_type& row) {
|
std::for_each(result_.begin(), result_.end(), [](rows ::value_type& row) {
|
||||||
std::for_each(row.begin(), row.end(), [](const char *val) {
|
std::for_each(row.begin(), row.end(), [](const char *val) {
|
||||||
|
|
@ -64,77 +61,87 @@ sqlite_query_result::~sqlite_query_result()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sqlite_query_result::column_count() const
|
size_t sqlite_result_reader::column_count() const
|
||||||
{
|
{
|
||||||
return prototype_.size();
|
return column_count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqlite_query_result::read_value(const char *id, size_t index, char &value)
|
const char* sqlite_result_reader::column(size_t index) const
|
||||||
|
{
|
||||||
|
return result_[row_index_][index];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sqlite_result_reader::fetch()
|
||||||
|
{
|
||||||
|
return ++row_index_ < result_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sqlite_result_reader::read_value(const char *id, size_t index, char &value)
|
||||||
{
|
{
|
||||||
read(value, result_[row_index_][index]);
|
read(value, result_[row_index_][index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqlite_query_result::read_value(const char *id, size_t index, short &value)
|
void sqlite_result_reader::read_value(const char *id, size_t index, short &value)
|
||||||
{
|
{
|
||||||
read(value, result_[row_index_][index]);
|
read(value, result_[row_index_][index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqlite_query_result::read_value(const char *id, size_t index, int &value)
|
void sqlite_result_reader::read_value(const char *id, size_t index, int &value)
|
||||||
{
|
{
|
||||||
read(value, result_[row_index_][index]);
|
read(value, result_[row_index_][index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqlite_query_result::read_value(const char *id, size_t index, long &value)
|
void sqlite_result_reader::read_value(const char *id, size_t index, long &value)
|
||||||
{
|
{
|
||||||
read(value, result_[row_index_][index]);
|
read(value, result_[row_index_][index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqlite_query_result::read_value(const char *id, size_t index, long long int &value)
|
void sqlite_result_reader::read_value(const char *id, size_t index, long long int &value)
|
||||||
{
|
{
|
||||||
read(value, result_[row_index_][index]);
|
read(value, result_[row_index_][index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqlite_query_result::read_value(const char *id, size_t index, unsigned char &value)
|
void sqlite_result_reader::read_value(const char *id, size_t index, unsigned char &value)
|
||||||
{
|
{
|
||||||
read(value, result_[row_index_][index]);
|
read(value, result_[row_index_][index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqlite_query_result::read_value(const char *id, size_t index, unsigned short &value)
|
void sqlite_result_reader::read_value(const char *id, size_t index, unsigned short &value)
|
||||||
{
|
{
|
||||||
read(value, result_[row_index_][index]);
|
read(value, result_[row_index_][index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqlite_query_result::read_value(const char *id, size_t index, unsigned int &value)
|
void sqlite_result_reader::read_value(const char *id, size_t index, unsigned int &value)
|
||||||
{
|
{
|
||||||
read(value, result_[row_index_][index]);
|
read(value, result_[row_index_][index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqlite_query_result::read_value(const char *id, size_t index, unsigned long &value)
|
void sqlite_result_reader::read_value(const char *id, size_t index, unsigned long &value)
|
||||||
{
|
{
|
||||||
read(value, result_[row_index_][index]);
|
read(value, result_[row_index_][index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqlite_query_result::read_value(const char *id, size_t index, unsigned long long int &value)
|
void sqlite_result_reader::read_value(const char *id, size_t index, unsigned long long int &value)
|
||||||
{
|
{
|
||||||
read(value, result_[row_index_][index]);
|
read(value, result_[row_index_][index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqlite_query_result::read_value(const char *id, size_t index, bool &value)
|
void sqlite_result_reader::read_value(const char *id, size_t index, bool &value)
|
||||||
{
|
{
|
||||||
read(value, result_[row_index_][index]);
|
read(value, result_[row_index_][index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqlite_query_result::read_value(const char *id, size_t index, float &value)
|
void sqlite_result_reader::read_value(const char *id, size_t index, float &value)
|
||||||
{
|
{
|
||||||
read(value, result_[row_index_][index]);
|
read(value, result_[row_index_][index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqlite_query_result::read_value(const char *id, size_t index, double &value)
|
void sqlite_result_reader::read_value(const char *id, size_t index, double &value)
|
||||||
{
|
{
|
||||||
read(value, result_[row_index_][index]);
|
read(value, result_[row_index_][index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqlite_query_result::read_value(const char *id, size_t index, char *value, size_t size)
|
void sqlite_result_reader::read_value(const char *id, size_t index, char *value, size_t size)
|
||||||
{
|
{
|
||||||
auto val = result_[row_index_][index];
|
auto val = result_[row_index_][index];
|
||||||
size_t len = strlen(val);
|
size_t len = strlen(val);
|
||||||
|
|
@ -154,47 +161,16 @@ void sqlite_query_result::read_value(const char *id, size_t index, char *value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqlite_query_result::read_value(const char *id, size_t index, std::string &value)
|
void sqlite_result_reader::read_value(const char *id, size_t index, std::string &value)
|
||||||
{
|
{
|
||||||
value.assign(result_[row_index_][index]);
|
value.assign(result_[row_index_][index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqlite_query_result::read_value(const char *id, size_t index, std::string &value, size_t s)
|
void sqlite_result_reader::read_value(const char *id, size_t index, std::string &value, size_t s)
|
||||||
{
|
{
|
||||||
value.assign(result_[row_index_][index]);
|
value.assign(result_[row_index_][index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqlite_query_result::push_back(char **row_values, int column_count)
|
|
||||||
{
|
|
||||||
columns data;
|
|
||||||
for(int i = 0; i < column_count; ++i) {
|
|
||||||
// copy and store column data;
|
|
||||||
if (row_values[i] == nullptr) {
|
|
||||||
auto val = new char[1];
|
|
||||||
val[0] = '\0';
|
|
||||||
data.push_back(val);
|
|
||||||
} else {
|
|
||||||
size_t size = strlen(row_values[i]);
|
|
||||||
auto val = new char[size + 1];
|
|
||||||
std::memcpy(val, row_values[i], size);
|
|
||||||
val[size] = '\0';
|
|
||||||
data.push_back(val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result_.emplace_back(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* sqlite_query_result::column(size_t index) const
|
|
||||||
{
|
|
||||||
return result_[row_index_][index];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sqlite_query_result::fetch()
|
|
||||||
{
|
|
||||||
column_index_ = 0;
|
|
||||||
return ++row_index_ < result_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Type >
|
template < typename Type >
|
||||||
void convert(const char *valstr, sql::any_type &value)
|
void convert(const char *valstr, sql::any_type &value)
|
||||||
{
|
{
|
||||||
|
|
@ -203,7 +179,7 @@ void convert(const char *valstr, sql::any_type &value)
|
||||||
value = val;
|
value = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sqlite_query_result::read_value(const char *id, size_t index, sql::any_type &value, sql::data_type_t type, size_t size)
|
void sqlite_result_reader::read_value(const char *id, size_t index, sql::any_type &value, sql::data_type_t type, size_t size)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case sql::data_type_t::type_char:
|
case sql::data_type_t::type_char:
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef QUERY_ENTITY_HPP
|
||||||
|
#define QUERY_ENTITY_HPP
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
template < class Type >
|
||||||
|
class entity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using value_type = Type;
|
||||||
|
using pointer = value_type*;
|
||||||
|
using reference = value_type&;
|
||||||
|
|
||||||
|
entity() = default;
|
||||||
|
explicit entity(Type *obj)
|
||||||
|
: obj_(obj) {}
|
||||||
|
entity(const entity&) = default;
|
||||||
|
entity& operator=(const entity&) = default;
|
||||||
|
entity(entity&&) noexcept = default;
|
||||||
|
entity& operator=(entity&&) noexcept = default;
|
||||||
|
~entity() = default;
|
||||||
|
|
||||||
|
void reset(Type *obj) { obj_.reset(obj); }
|
||||||
|
|
||||||
|
pointer operator->() { return obj_.get(); }
|
||||||
|
const value_type* operator->() const { return obj_.get(); }
|
||||||
|
|
||||||
|
reference operator*() { return *obj_; }
|
||||||
|
const value_type& operator*() const { return *obj_; }
|
||||||
|
|
||||||
|
pointer get() { return obj_.get(); }
|
||||||
|
const value_type* get() const { return obj_.get(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<value_type> obj_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Type, typename... Args>
|
||||||
|
[[maybe_unused]] entity<Type> make_entity(Args&&... args)
|
||||||
|
{
|
||||||
|
return entity(new Type(std::forward<Args>(args)...));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //QUERY_ENTITY_HPP
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
#ifndef QUERY_FOREIGN_HPP
|
|
||||||
#define QUERY_FOREIGN_HPP
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace matador::sql {
|
|
||||||
|
|
||||||
template < class Type >
|
|
||||||
class foreign
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using value_type = Type;
|
|
||||||
using pointer = value_type*;
|
|
||||||
using reference = value_type&;
|
|
||||||
|
|
||||||
foreign() = default;
|
|
||||||
explicit foreign(Type *obj)
|
|
||||||
: obj_(obj) {}
|
|
||||||
foreign(const foreign&) = default;
|
|
||||||
foreign& operator=(const foreign&) = default;
|
|
||||||
foreign(foreign&&) noexcept = default;
|
|
||||||
foreign& operator=(foreign&&) noexcept = default;
|
|
||||||
~foreign() = default;
|
|
||||||
|
|
||||||
pointer operator->() { return obj_.get(); }
|
|
||||||
const value_type* operator->() const { return obj_.get(); }
|
|
||||||
|
|
||||||
reference operator*() { return *obj_; }
|
|
||||||
const value_type& operator*() const { return *obj_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::shared_ptr<value_type> obj_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class Type, typename... Args>
|
|
||||||
[[maybe_unused]] foreign<Type> make_foreign(Args&&... args)
|
|
||||||
{
|
|
||||||
return foreign(new Type(std::forward<Args>(args)...));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif //QUERY_FOREIGN_HPP
|
|
||||||
|
|
@ -5,44 +5,61 @@
|
||||||
#include "matador/utils/field_attributes.hpp"
|
#include "matador/utils/field_attributes.hpp"
|
||||||
|
|
||||||
#include "matador/sql/any_type.hpp"
|
#include "matador/sql/any_type.hpp"
|
||||||
|
#include "matador/sql/query_result_reader.hpp"
|
||||||
#include "matador/sql/record.hpp"
|
#include "matador/sql/record.hpp"
|
||||||
#include "matador/sql/types.hpp"
|
#include "matador/sql/types.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
class pk_reader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit pk_reader(query_result_reader &reader);
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
void read(Type &obj, size_t column_index)
|
||||||
|
{
|
||||||
|
column_index_ = column_index;
|
||||||
|
utils::access::process(*this, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
void on_primary_key(const char *id, ValueType &value, typename std::enable_if<std::is_integral<ValueType>::value && !std::is_same<bool, ValueType>::value>::type* = 0);
|
||||||
|
void on_primary_key(const char *id, std::string &value, size_t size);
|
||||||
|
void on_revision(const char * /*id*/, unsigned long long &/*rev*/) {}
|
||||||
|
|
||||||
|
template < class Type >
|
||||||
|
void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||||
|
template < class Pointer >
|
||||||
|
void on_belongs_to(const char *id, Pointer &x, utils::cascade_type) {}
|
||||||
|
template < class Pointer >
|
||||||
|
void on_has_one(const char *id, Pointer &x, utils::cascade_type) {}
|
||||||
|
|
||||||
|
template<class ContainerType>
|
||||||
|
void on_has_many(const char *, ContainerType &, const char *, const char *, utils::cascade_type) {}
|
||||||
|
template<class ContainerType>
|
||||||
|
void on_has_many(const char *, ContainerType &, utils::cascade_type) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t column_index_{};
|
||||||
|
query_result_reader &reader_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
class query_result_impl
|
class query_result_impl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~query_result_impl() = default;
|
query_result_impl(std::unique_ptr<query_result_reader> &&reader, record prototype);
|
||||||
|
|
||||||
virtual size_t column_count() const = 0;
|
|
||||||
|
|
||||||
virtual void read_value(const char *id, size_t index, char &value) = 0;
|
|
||||||
virtual void read_value(const char *id, size_t index, short &value) = 0;
|
|
||||||
virtual void read_value(const char *id, size_t index, int &value) = 0;
|
|
||||||
virtual void read_value(const char *id, size_t index, long &value) = 0;
|
|
||||||
virtual void read_value(const char *id, size_t index, long long &value) = 0;
|
|
||||||
virtual void read_value(const char *id, size_t index, unsigned char &value) = 0;
|
|
||||||
virtual void read_value(const char *id, size_t index, unsigned short &value) = 0;
|
|
||||||
virtual void read_value(const char *id, size_t index, unsigned int &value) = 0;
|
|
||||||
virtual void read_value(const char *id, size_t index, unsigned long &value) = 0;
|
|
||||||
virtual void read_value(const char *id, size_t index, unsigned long long &value) = 0;
|
|
||||||
virtual void read_value(const char *id, size_t index, bool &value) = 0;
|
|
||||||
virtual void read_value(const char *id, size_t index, float &value) = 0;
|
|
||||||
virtual void read_value(const char *id, size_t index, double &value) = 0;
|
|
||||||
// virtual void read_value(const char *id, size_t index, matador::time &value) = 0;
|
|
||||||
// virtual void read_value(const char *id, size_t index, matador::date &value) = 0;
|
|
||||||
virtual void read_value(const char *id, size_t index, char *value, size_t s) = 0;
|
|
||||||
virtual void read_value(const char *id, size_t index, std::string &value) = 0;
|
|
||||||
virtual void read_value(const char *id, size_t index, std::string &value, size_t s) = 0;
|
|
||||||
virtual void read_value(const char *id, size_t index, any_type &value, data_type_t type, size_t size) = 0;
|
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
void on_primary_key(const char *id, ValueType &value, typename std::enable_if<std::is_integral<ValueType>::value && !std::is_same<bool, ValueType>::value>::type* = 0)
|
void on_primary_key(const char *id, ValueType &value, typename std::enable_if<std::is_integral<ValueType>::value && !std::is_same<bool, ValueType>::value>::type* = 0)
|
||||||
{
|
{
|
||||||
read_value(id, column_index_++, value);
|
reader_->read_value(id, column_index_++, value);
|
||||||
}
|
}
|
||||||
void on_primary_key(const char *id, std::string &value, size_t size);
|
void on_primary_key(const char *id, std::string &value, size_t size);
|
||||||
void on_revision(const char *id, unsigned long long &rev);
|
void on_revision(const char *id, unsigned long long &rev);
|
||||||
|
|
@ -50,16 +67,28 @@ public:
|
||||||
template < class Type >
|
template < class Type >
|
||||||
void on_attribute(const char *id, Type &x, const utils::field_attributes &/*attr*/ = utils::null_attributes)
|
void on_attribute(const char *id, Type &x, const utils::field_attributes &/*attr*/ = utils::null_attributes)
|
||||||
{
|
{
|
||||||
read_value(id, column_index_++, x);
|
reader_->read_value(id, column_index_++, x);
|
||||||
}
|
}
|
||||||
void on_attribute(const char *id, char *value, const utils::field_attributes &attr = utils::null_attributes);
|
void on_attribute(const char *id, char *value, const utils::field_attributes &attr = utils::null_attributes);
|
||||||
void on_attribute(const char *id, std::string &value, const utils::field_attributes &attr = utils::null_attributes);
|
void on_attribute(const char *id, std::string &value, const utils::field_attributes &attr = utils::null_attributes);
|
||||||
void on_attribute(const char *id, any_type &value, data_type_t type, const utils::field_attributes &attr = utils::null_attributes);
|
void on_attribute(const char *id, any_type &value, data_type_t type, const utils::field_attributes &attr = utils::null_attributes);
|
||||||
|
|
||||||
template < class Pointer >
|
template < class Pointer >
|
||||||
void on_belongs_to(const char *id, Pointer &x, utils::cascade_type) {}
|
void on_belongs_to(const char * /*id*/, Pointer &x, utils::cascade_type)
|
||||||
|
{
|
||||||
|
if (!x.get()) {
|
||||||
|
x.reset(new typename Pointer::value_type);
|
||||||
|
}
|
||||||
|
pk_reader_.read(*x, column_index_++);
|
||||||
|
}
|
||||||
template < class Pointer >
|
template < class Pointer >
|
||||||
void on_has_one(const char *id, Pointer &x, utils::cascade_type) {}
|
void on_has_one(const char * /*id*/, Pointer &x, utils::cascade_type)
|
||||||
|
{
|
||||||
|
if (!x.get()) {
|
||||||
|
x.reset(new typename Pointer::value_type);
|
||||||
|
}
|
||||||
|
pk_reader_.read(*x, column_index_++);
|
||||||
|
}
|
||||||
|
|
||||||
template<class ContainerType>
|
template<class ContainerType>
|
||||||
void on_has_many(const char *, ContainerType &, const char *, const char *, utils::cascade_type) {}
|
void on_has_many(const char *, ContainerType &, const char *, const char *, utils::cascade_type) {}
|
||||||
|
|
@ -72,26 +101,32 @@ public:
|
||||||
template<class Type>
|
template<class Type>
|
||||||
bool fetch(Type &obj)
|
bool fetch(Type &obj)
|
||||||
{
|
{
|
||||||
if (!fetch()) {
|
column_index_ = 0;
|
||||||
|
if (!reader_->fetch()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
matador::utils::access::process(*this, obj);
|
matador::utils::access::process(*this, obj);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] virtual const char* column(size_t index) const = 0;
|
[[nodiscard]] const record& prototype() const;
|
||||||
[[nodiscard]] virtual bool fetch() = 0;
|
|
||||||
|
|
||||||
const record& prototype() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
explicit query_result_impl(record prototype);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t column_index_ = 0;
|
size_t column_index_ = 0;
|
||||||
record prototype_;
|
record prototype_;
|
||||||
|
std::unique_ptr<query_result_reader> reader_;
|
||||||
|
detail::pk_reader pk_reader_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
void detail::pk_reader::on_primary_key(const char *id, ValueType &value, typename std::enable_if<std::is_integral<ValueType>::value && !std::is_same<bool, ValueType>::value>::type *)
|
||||||
|
{
|
||||||
|
reader_.read_value(id, column_index_++, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //QUERY_QUERY_RESULT_IMPL_HPP
|
#endif //QUERY_QUERY_RESULT_IMPL_HPP
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef QUERY_QUERY_RESULT_READER_HPP
|
||||||
|
#define QUERY_QUERY_RESULT_READER_HPP
|
||||||
|
|
||||||
|
#include "matador/sql/any_type.hpp"
|
||||||
|
#include "matador/sql/types.hpp"
|
||||||
|
|
||||||
|
namespace matador::sql {
|
||||||
|
|
||||||
|
class query_result_reader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~query_result_reader() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual size_t column_count() const = 0;
|
||||||
|
[[nodiscard]] virtual const char* column(size_t index) const = 0;
|
||||||
|
[[nodiscard]] virtual bool fetch() = 0;
|
||||||
|
|
||||||
|
virtual void read_value(const char *id, size_t index, char &value) = 0;
|
||||||
|
virtual void read_value(const char *id, size_t index, short &value) = 0;
|
||||||
|
virtual void read_value(const char *id, size_t index, int &value) = 0;
|
||||||
|
virtual void read_value(const char *id, size_t index, long &value) = 0;
|
||||||
|
virtual void read_value(const char *id, size_t index, long long &value) = 0;
|
||||||
|
virtual void read_value(const char *id, size_t index, unsigned char &value) = 0;
|
||||||
|
virtual void read_value(const char *id, size_t index, unsigned short &value) = 0;
|
||||||
|
virtual void read_value(const char *id, size_t index, unsigned int &value) = 0;
|
||||||
|
virtual void read_value(const char *id, size_t index, unsigned long &value) = 0;
|
||||||
|
virtual void read_value(const char *id, size_t index, unsigned long long &value) = 0;
|
||||||
|
virtual void read_value(const char *id, size_t index, bool &value) = 0;
|
||||||
|
virtual void read_value(const char *id, size_t index, float &value) = 0;
|
||||||
|
virtual void read_value(const char *id, size_t index, double &value) = 0;
|
||||||
|
// virtual void read_value(const char *id, size_t index, matador::time &value) = 0;
|
||||||
|
// virtual void read_value(const char *id, size_t index, matador::date &value) = 0;
|
||||||
|
virtual void read_value(const char *id, size_t index, char *value, size_t s) = 0;
|
||||||
|
virtual void read_value(const char *id, size_t index, std::string &value) = 0;
|
||||||
|
virtual void read_value(const char *id, size_t index, std::string &value, size_t s) = 0;
|
||||||
|
virtual void read_value(const char *id, size_t index, any_type &value, data_type_t type, size_t size) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //QUERY_QUERY_RESULT_READER_HPP
|
||||||
|
|
@ -44,10 +44,11 @@ set(SQL_HEADER
|
||||||
../include/matador/sql/value_extractor.hpp
|
../include/matador/sql/value_extractor.hpp
|
||||||
../include/matador/sql/any_type.hpp
|
../include/matador/sql/any_type.hpp
|
||||||
../include/matador/sql/key_value_generator.hpp
|
../include/matador/sql/key_value_generator.hpp
|
||||||
../include/matador/sql/foreign.hpp
|
../include/matador/sql/entity.hpp
|
||||||
../include/matador/sql/fk_value_extractor.hpp
|
../include/matador/sql/fk_value_extractor.hpp
|
||||||
"../include/matador/sql/table_repository.hpp"
|
"../include/matador/sql/table_repository.hpp"
|
||||||
../include/matador/sql/any_type_to_visitor.hpp)
|
../include/matador/sql/any_type_to_visitor.hpp
|
||||||
|
../include/matador/sql/query_result_reader.hpp)
|
||||||
|
|
||||||
set(UTILS_HEADER
|
set(UTILS_HEADER
|
||||||
../include/matador/utils/field_attributes.hpp
|
../include/matador/utils/field_attributes.hpp
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,45 @@
|
||||||
#include "matador/sql/query_result_impl.hpp"
|
#include "matador/sql/query_result_impl.hpp"
|
||||||
|
#include "matador/sql/query_result_reader.hpp"
|
||||||
|
|
||||||
namespace matador::sql {
|
namespace matador::sql {
|
||||||
|
|
||||||
|
detail::pk_reader::pk_reader(query_result_reader &reader)
|
||||||
|
: reader_(reader) {}
|
||||||
|
|
||||||
|
void detail::pk_reader::on_primary_key(const char *id, std::string &value, size_t size) {
|
||||||
|
reader_.read_value(id, column_index_, value, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
query_result_impl::query_result_impl(std::unique_ptr<query_result_reader> &&reader, record prototype)
|
||||||
|
: prototype_(std::move(prototype))
|
||||||
|
, reader_(std::move(reader))
|
||||||
|
, pk_reader_(*reader_)
|
||||||
|
{}
|
||||||
|
|
||||||
void query_result_impl::on_primary_key(const char *id, std::string &value, size_t size)
|
void query_result_impl::on_primary_key(const char *id, std::string &value, size_t size)
|
||||||
{
|
{
|
||||||
read_value(id, column_index_++, value, size);
|
reader_->read_value(id, column_index_++, value, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void query_result_impl::on_revision(const char *id, unsigned long long int &rev)
|
void query_result_impl::on_revision(const char *id, unsigned long long int &rev)
|
||||||
{
|
{
|
||||||
read_value(id, column_index_++, rev);
|
reader_->read_value(id, column_index_++, rev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void query_result_impl::on_attribute(const char *id, char *value, const utils::field_attributes &attr)
|
void query_result_impl::on_attribute(const char *id, char *value, const utils::field_attributes &attr)
|
||||||
{
|
{
|
||||||
read_value(id, column_index_++, value, attr.size());
|
reader_->read_value(id, column_index_++, value, attr.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void query_result_impl::on_attribute(const char *id, std::string &value, const utils::field_attributes &attr)
|
void query_result_impl::on_attribute(const char *id, std::string &value, const utils::field_attributes &attr)
|
||||||
{
|
{
|
||||||
read_value(id, column_index_++, value, attr.size());
|
reader_->read_value(id, column_index_++, value, attr.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
query_result_impl::on_attribute(const char *id, any_type &value, data_type_t type, const utils::field_attributes &attr)
|
query_result_impl::on_attribute(const char *id, any_type &value, data_type_t type, const utils::field_attributes &attr)
|
||||||
{
|
{
|
||||||
read_value(id, column_index_++, value, type, attr.size());
|
reader_->read_value(id, column_index_++, value, type, attr.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
const record& query_result_impl::prototype() const
|
const record& query_result_impl::prototype() const
|
||||||
|
|
@ -33,8 +47,4 @@ const record& query_result_impl::prototype() const
|
||||||
return prototype_;
|
return prototype_;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_result_impl::query_result_impl(record prototype)
|
|
||||||
: prototype_(std::move(prototype))
|
|
||||||
{}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -107,7 +107,7 @@ void logger::log(log_level lvl, const char *message) const
|
||||||
std::snprintf(timestamp_buffer + std::strftime(timestamp_buffer,
|
std::snprintf(timestamp_buffer + std::strftime(timestamp_buffer,
|
||||||
sizeof timestamp_buffer - 3,
|
sizeof timestamp_buffer - 3,
|
||||||
"%F %T.",
|
"%F %T.",
|
||||||
std::localtime(&coarse)), 4, "%03ld", fine.time_since_epoch().count() % 1000);
|
std::localtime(&coarse)), 4, "%03lld", fine.time_since_epoch().count() % 1000);
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
|
||||||
|
|
@ -122,10 +122,10 @@ TEST_CASE("Select statement with foreign key", "[session]") {
|
||||||
REQUIRE(res.first == 0);
|
REQUIRE(res.first == 0);
|
||||||
REQUIRE(res.second == R"(CREATE TABLE "flight" ("id" BIGINT, "airplane_id" BIGINT, "pilot_name" VARCHAR(255), CONSTRAINT PK_flight PRIMARY KEY (id), CONSTRAINT FK_flight_airplane_id FOREIGN KEY (airplane_id) REFERENCES airplane(id)))");
|
REQUIRE(res.second == R"(CREATE TABLE "flight" ("id" BIGINT, "airplane_id" BIGINT, "pilot_name" VARCHAR(255), CONSTRAINT PK_flight PRIMARY KEY (id), CONSTRAINT FK_flight_airplane_id FOREIGN KEY (airplane_id) REFERENCES airplane(id)))");
|
||||||
|
|
||||||
std::vector<foreign<airplane>> planes {
|
std::vector<entity<airplane>> planes {
|
||||||
make_foreign<airplane>(1, "Airbus", "A380"),
|
make_entity<airplane>(1, "Airbus", "A380"),
|
||||||
make_foreign<airplane>(2, "Boeing", "707"),
|
make_entity<airplane>(2, "Boeing", "707"),
|
||||||
make_foreign<airplane>(3, "Boeing", "747")
|
make_entity<airplane>(3, "Boeing", "747")
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto &plane : planes) {
|
for (const auto &plane : planes) {
|
||||||
|
|
@ -136,13 +136,16 @@ TEST_CASE("Select statement with foreign key", "[session]") {
|
||||||
auto count = s.select({count_all()}).from("airplane").fetch_value<int>();
|
auto count = s.select({count_all()}).from("airplane").fetch_value<int>();
|
||||||
REQUIRE(count == 3);
|
REQUIRE(count == 3);
|
||||||
|
|
||||||
flight f4711{4, *planes.begin(), "hans"};
|
flight f4711{4, planes.at(1), "hans"};
|
||||||
|
|
||||||
res = s.insert().into<flight>("flight").values(f4711).execute();
|
res = s.insert().into<flight>("flight").values(f4711).execute();
|
||||||
REQUIRE(res.first == 1);
|
REQUIRE(res.first == 1);
|
||||||
|
|
||||||
auto f = *s.select<flight>().from("flight").fetch_all<flight>().begin();
|
auto f = *s.select<flight>().from("flight").fetch_all<flight>().begin();
|
||||||
|
REQUIRE(f.id == 4);
|
||||||
|
REQUIRE(f.pilot_name == "hans");
|
||||||
|
REQUIRE(f.airplane.get() != nullptr);
|
||||||
|
REQUIRE(f.airplane->id == 2);
|
||||||
|
|
||||||
s.drop().table("flight").execute();
|
s.drop().table("flight").execute();
|
||||||
s.drop().table("airplane").execute();
|
s.drop().table("airplane").execute();
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,9 @@ TEST_CASE("Extract values object", "[value extractor]") {
|
||||||
p.units_in_stock = 100;
|
p.units_in_stock = 100;
|
||||||
p.unit_price = 49;
|
p.unit_price = 49;
|
||||||
p.quantity_per_unit = "pcs";
|
p.quantity_per_unit = "pcs";
|
||||||
p.category = make_foreign<matador::test::category>();
|
p.category = make_entity<matador::test::category>();
|
||||||
p.category->id = 7;
|
p.category->id = 7;
|
||||||
p.supplier = make_foreign<matador::test::supplier>();;
|
p.supplier = make_entity<matador::test::supplier>();;
|
||||||
p.supplier->id = 13;
|
p.supplier->id = 13;
|
||||||
p.product_name = "candle";
|
p.product_name = "candle";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
#include "matador/utils/cascade_type.hpp"
|
#include "matador/utils/cascade_type.hpp"
|
||||||
#include "matador/utils/field_attributes.hpp"
|
#include "matador/utils/field_attributes.hpp"
|
||||||
|
|
||||||
#include "matador/sql/foreign.hpp"
|
#include "matador/sql/entity.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
@ -21,7 +21,7 @@ struct airplane
|
||||||
: id(id)
|
: id(id)
|
||||||
, brand(std::move(b))
|
, brand(std::move(b))
|
||||||
, model(std::move(m)) {}
|
, model(std::move(m)) {}
|
||||||
unsigned long id;
|
unsigned long id{};
|
||||||
std::string brand;
|
std::string brand;
|
||||||
std::string model;
|
std::string model;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,15 @@
|
||||||
#include "matador/utils/cascade_type.hpp"
|
#include "matador/utils/cascade_type.hpp"
|
||||||
#include "matador/utils/field_attributes.hpp"
|
#include "matador/utils/field_attributes.hpp"
|
||||||
|
|
||||||
#include "matador/sql/foreign.hpp"
|
#include "matador/sql/entity.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace matador::test {
|
namespace matador::test {
|
||||||
|
|
||||||
struct flight {
|
struct flight {
|
||||||
unsigned long id;
|
unsigned long id{};
|
||||||
sql::foreign<test::airplane> airplane;
|
sql::entity<test::airplane> airplane;
|
||||||
std::string pilot_name;
|
std::string pilot_name;
|
||||||
|
|
||||||
template<class Operator>
|
template<class Operator>
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
#include "matador/utils/cascade_type.hpp"
|
#include "matador/utils/cascade_type.hpp"
|
||||||
#include "matador/utils/field_attributes.hpp"
|
#include "matador/utils/field_attributes.hpp"
|
||||||
|
|
||||||
#include "matador/sql/foreign.hpp"
|
#include "matador/sql/entity.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
@ -17,8 +17,8 @@ namespace matador::test {
|
||||||
struct product
|
struct product
|
||||||
{
|
{
|
||||||
std::string product_name;
|
std::string product_name;
|
||||||
sql::foreign<test::supplier> supplier;
|
sql::entity<test::supplier> supplier;
|
||||||
sql::foreign<test::category> category;
|
sql::entity<test::category> category;
|
||||||
std::string quantity_per_unit;
|
std::string quantity_per_unit;
|
||||||
unsigned int unit_price;
|
unsigned int unit_price;
|
||||||
unsigned int units_in_stock;
|
unsigned int units_in_stock;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue