entity query and record progress
This commit is contained in:
parent
830185c3c5
commit
be610ffcad
|
|
@ -37,7 +37,7 @@ public:
|
|||
|
||||
size_t execute(const std::string &stmt) override;
|
||||
|
||||
sql::record describe(const std::string& table) override;
|
||||
std::vector<sql::column_definition> describe(const std::string& table) override;
|
||||
|
||||
bool exists(const std::string &schema_name, const std::string &table_name) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -181,13 +181,13 @@ std::unique_ptr<sql::query_result_impl> mysql_connection::fetch(const std::strin
|
|||
|
||||
auto field_count = mysql_num_fields(result);
|
||||
auto fields = mysql_fetch_fields(result);
|
||||
sql::record prototype;
|
||||
std::vector<sql::column_definition> prototype;
|
||||
for (unsigned i = 0; i < field_count; ++i) {
|
||||
auto type = to_type(fields[i].type, fields[i].flags);
|
||||
auto options = to_constraints(fields[i].flags);
|
||||
auto null_opt = to_null_option(fields[i].flags);
|
||||
|
||||
prototype.append({fields[i].name, type, options, null_opt});
|
||||
prototype.emplace_back(fields[i].name, type, options, null_opt);
|
||||
}
|
||||
|
||||
return std::move(std::make_unique<sql::query_result_impl>(std::make_unique<mysql_result_reader>(result, field_count), std::move(prototype)));
|
||||
|
|
@ -216,7 +216,7 @@ size_t mysql_connection::execute(const std::string &stmt)
|
|||
return mysql_affected_rows(mysql_.get());
|
||||
}
|
||||
|
||||
sql::record mysql_connection::describe(const std::string &table)
|
||||
std::vector<sql::column_definition> mysql_connection::describe(const std::string &table)
|
||||
{
|
||||
std::string stmt("SHOW COLUMNS FROM " + table);
|
||||
|
||||
|
|
@ -230,7 +230,7 @@ sql::record mysql_connection::describe(const std::string &table)
|
|||
}
|
||||
|
||||
mysql_result_reader reader(result, mysql_num_fields(result));
|
||||
sql::record prototype;
|
||||
std::vector<sql::column_definition> prototype;
|
||||
while (reader.fetch()) {
|
||||
|
||||
char *end = nullptr;
|
||||
|
|
@ -242,7 +242,7 @@ sql::record mysql_connection::describe(const std::string &table)
|
|||
if (strtoul(reader.column(2), &end, 10) == 0) {
|
||||
null_opt = sql::null_option::NOT_NULL;
|
||||
}
|
||||
prototype.append({name, typeinfo.type, {typeinfo.size}, null_opt, prototype.size()});
|
||||
prototype.push_back({name, typeinfo.type, {typeinfo.size}, null_opt, prototype.size()});
|
||||
}
|
||||
|
||||
return prototype;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public:
|
|||
|
||||
size_t execute(const std::string &stmt) override;
|
||||
|
||||
sql::record describe(const std::string& table) override;
|
||||
std::vector<sql::column_definition> describe(const std::string& table) override;
|
||||
|
||||
bool exists(const std::string &schema_name, const std::string &table_name) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -51,14 +51,13 @@ std::unique_ptr<sql::query_result_impl> postgres_connection::fetch(const std::st
|
|||
|
||||
throw_postgres_error(res, conn_, "postgres", stmt);
|
||||
|
||||
sql::record prototype;
|
||||
std::vector<sql::column_definition> prototype;
|
||||
auto num_col = PQnfields(res);
|
||||
for (int i = 0; i < num_col; ++i) {
|
||||
const char *col_name = PQfname(res, i);
|
||||
auto type = PQftype(res, i);
|
||||
auto size = PQfmod(res, i);
|
||||
// std::cout << "column " << col_name << ", type " << type << " (size: " << size << ")\n";
|
||||
prototype.append(sql::column_definition{col_name});
|
||||
prototype.emplace_back(col_name);
|
||||
}
|
||||
return std::move(std::make_unique<sql::query_result_impl>(std::make_unique<postgres_result_reader>(res), std::move(prototype)));
|
||||
}
|
||||
|
|
@ -131,7 +130,7 @@ sql::data_type_t string2type(const char *type)
|
|||
}
|
||||
}
|
||||
|
||||
sql::record postgres_connection::describe(const std::string &table)
|
||||
std::vector<sql::column_definition> postgres_connection::describe(const std::string &table)
|
||||
{
|
||||
std::string stmt(
|
||||
"SELECT ordinal_position, column_name, udt_name, data_type, is_nullable, column_default FROM information_schema.columns WHERE table_schema='public' AND table_name='" + table + "'");
|
||||
|
|
@ -141,7 +140,7 @@ sql::record postgres_connection::describe(const std::string &table)
|
|||
throw_postgres_error(res, conn_, "postgres", stmt);
|
||||
|
||||
postgres_result_reader reader(res);
|
||||
sql::record prototype;
|
||||
std::vector<sql::column_definition> prototype;
|
||||
while (reader.fetch()) {
|
||||
char *end = nullptr;
|
||||
// Todo: Handle error
|
||||
|
|
@ -156,7 +155,7 @@ sql::record postgres_connection::describe(const std::string &table)
|
|||
null_opt = sql::null_option::NOT_NULL;
|
||||
}
|
||||
// f.default_value(res->column(4));
|
||||
prototype.append({name, type, utils::null_attributes, null_opt, index});
|
||||
prototype.emplace_back(name, type, utils::null_attributes, null_opt, index);
|
||||
}
|
||||
|
||||
return std::move(prototype);
|
||||
|
|
|
|||
|
|
@ -33,14 +33,14 @@ public:
|
|||
|
||||
size_t execute(const std::string &stmt) override;
|
||||
|
||||
sql::record describe(const std::string& table) override;
|
||||
std::vector<sql::column_definition> describe(const std::string& table) override;
|
||||
|
||||
bool exists(const std::string &schema_name, const std::string &table_name) override;
|
||||
|
||||
private:
|
||||
struct fetch_context
|
||||
{
|
||||
sql::record prototype;
|
||||
std::vector<sql::column_definition> prototype;
|
||||
sqlite_result_reader::rows rows;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ int sqlite_connection::parse_result(void* param, int column_count, char** values
|
|||
|
||||
if (context->prototype.empty()) {
|
||||
for(int i = 0; i < column_count; ++i) {
|
||||
context->prototype.append(sql::column_definition{columns[i]});
|
||||
context->prototype.emplace_back(columns[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -144,12 +144,12 @@ sql::data_type_t string2type(const char *type)
|
|||
}
|
||||
}
|
||||
|
||||
sql::record sqlite_connection::describe(const std::string& table)
|
||||
std::vector<sql::column_definition> sqlite_connection::describe(const std::string& table)
|
||||
{
|
||||
const auto result = fetch_internal("PRAGMA table_info(" + table + ")");
|
||||
|
||||
sqlite_result_reader reader(result.rows, result.prototype.size());
|
||||
sql::record prototype;
|
||||
std::vector<sql::column_definition> prototype;
|
||||
while (reader.fetch()) {
|
||||
char *end = nullptr;
|
||||
// Todo: add index to column
|
||||
|
|
@ -163,7 +163,7 @@ sql::record sqlite_connection::describe(const std::string& table)
|
|||
null_opt = sql::null_option::NOT_NULL;
|
||||
}
|
||||
// f.default_value(res->column(4));
|
||||
prototype.append({name, type, utils::null_attributes, null_opt, index});
|
||||
prototype.emplace_back(name, type, utils::null_attributes, null_opt, index);
|
||||
}
|
||||
|
||||
return std::move(prototype);
|
||||
|
|
|
|||
|
|
@ -37,10 +37,19 @@ private:
|
|||
using namespace matador;
|
||||
|
||||
TEST_CASE_METHOD(SessionFixture, "Session relation test", "[session][relation]") {
|
||||
|
||||
ses.attach<matador::test::airplane>("airplane");
|
||||
using namespace matador;
|
||||
ses.attach<test::airplane>("airplane");
|
||||
ses.create_schema();
|
||||
ses.insert<test::airplane>(1, "Boeing", "A380");
|
||||
|
||||
REQUIRE(true);
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionFixture, "Find object with id", "[session][find]") {
|
||||
ses.attach<matador::test::airplane>("airplane");
|
||||
ses.create_schema();
|
||||
auto a380 = ses.insert<test::airplane>(1, "Boeing", "A380");
|
||||
|
||||
ses.find<test::airplane>(1);
|
||||
|
||||
}
|
||||
|
|
@ -10,6 +10,17 @@
|
|||
|
||||
namespace matador::sql {
|
||||
|
||||
using any_db_type = std::variant<
|
||||
long long,
|
||||
unsigned long long,
|
||||
double,
|
||||
bool,
|
||||
const char*,
|
||||
std::string,
|
||||
utils::blob,
|
||||
placeholder,
|
||||
nullptr_t>;
|
||||
|
||||
using any_type = std::variant<
|
||||
char, short, int, long, long long,
|
||||
unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
#include "matador/sql/query_result.hpp"
|
||||
#include "matador/sql/record.hpp"
|
||||
#include "matador/sql/statement.hpp"
|
||||
#include "matador/sql/schema.hpp"
|
||||
|
||||
#include "matador/utils/logger.hpp"
|
||||
|
||||
|
|
@ -17,6 +16,8 @@
|
|||
|
||||
namespace matador::sql {
|
||||
|
||||
class schema;
|
||||
|
||||
class connection
|
||||
{
|
||||
public:
|
||||
|
|
@ -32,7 +33,7 @@ public:
|
|||
[[nodiscard]] bool is_open() const;
|
||||
[[nodiscard]] const connection_info& info() const;
|
||||
|
||||
[[nodiscard]] record describe(const std::string &table_name) const;
|
||||
[[nodiscard]] std::vector<sql::column_definition> describe(const std::string &table_name) const;
|
||||
[[nodiscard]] bool exists(const std::string &schema_name, const std::string &table_name) const;
|
||||
[[nodiscard]] bool exists(const std::string &table_name) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ public:
|
|||
virtual std::unique_ptr<query_result_impl> fetch(const std::string &stmt) = 0;
|
||||
virtual std::unique_ptr<statement_impl> prepare(query_context context) = 0;
|
||||
|
||||
virtual record describe(const std::string &table) = 0;
|
||||
virtual std::vector<sql::column_definition> describe(const std::string &table) = 0;
|
||||
virtual bool exists(const std::string &schema_name, const std::string &table_name) = 0;
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
#ifndef QUERY_ENTITY_QUERY_BUILDER_HPP
|
||||
#define QUERY_ENTITY_QUERY_BUILDER_HPP
|
||||
|
||||
#include "matador/sql/query_context.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
template < typename PrimaryKeyType >
|
||||
class entity_query_builder
|
||||
{
|
||||
public:
|
||||
// determine pk
|
||||
// collect eager relations for joins
|
||||
template<class EntityType>
|
||||
query_context build() {
|
||||
EntityType obj;
|
||||
matador::utils::access::process(*this, obj);
|
||||
return {};
|
||||
}
|
||||
|
||||
template < class V >
|
||||
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, std::string &, size_t)
|
||||
{
|
||||
|
||||
}
|
||||
void on_revision(const char * /*id*/, unsigned long long &/*rev*/) {}
|
||||
|
||||
template<typename Type>
|
||||
void on_attribute(const char * /*id*/, Type &, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
||||
|
||||
template<class Pointer>
|
||||
void on_belongs_to(const char *id, Pointer &, const utils::foreign_attributes &/*attr*/)
|
||||
{
|
||||
}
|
||||
|
||||
template<class Pointer>
|
||||
void on_has_one(const char *id, Pointer &, const utils::foreign_attributes &attr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<class ContainerType>
|
||||
void on_has_many(const char *, ContainerType &, const char *, const char *, const utils::foreign_attributes &attr)
|
||||
{
|
||||
}
|
||||
|
||||
template<class ContainerType>
|
||||
void on_has_many(const char *id, ContainerType &c, const utils::foreign_attributes &attr)
|
||||
{
|
||||
on_has_many(id, c, "", "", attr);
|
||||
}
|
||||
|
||||
private:
|
||||
PrimaryKeyType pk_;
|
||||
};
|
||||
|
||||
}
|
||||
#endif //QUERY_ENTITY_QUERY_BUILDER_HPP
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef QUERY_FIELD_HPP
|
||||
#define QUERY_FIELD_HPP
|
||||
|
||||
#include "matador/sql/any_type.hpp"
|
||||
#include "matador/sql/any_type_to_visitor.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
class field
|
||||
{
|
||||
public:
|
||||
|
||||
[[nodiscard]] const std::string& name() const;
|
||||
|
||||
template<class Type>
|
||||
Type as() const
|
||||
{
|
||||
const Type* ptr= std::get_if<Type>(&value_);
|
||||
if (ptr) {
|
||||
return *ptr;
|
||||
}
|
||||
any_type_to_visitor<Type> visitor;
|
||||
std::visit(visitor, const_cast<any_type&>(value_));
|
||||
return visitor.result;
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream &out, const field &col);
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
any_type value_;
|
||||
};
|
||||
|
||||
}
|
||||
#endif //QUERY_FIELD_HPP
|
||||
|
|
@ -16,7 +16,7 @@ public:
|
|||
size_t execute(const std::string &stmt) override;
|
||||
std::unique_ptr<query_result_impl> fetch(const std::string &stmt) override;
|
||||
std::unique_ptr<statement_impl> prepare(query_context context) override;
|
||||
record describe(const std::string &table) override;
|
||||
std::vector<sql::column_definition> describe(const std::string &table) override;
|
||||
bool exists(const std::string &schema_name, const std::string &table_name) override;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ struct query_context
|
|||
std::string sql;
|
||||
std::string command_name;
|
||||
sql::table table{""};
|
||||
record prototype;
|
||||
std::vector<column_definition> prototype;
|
||||
std::vector<std::string> result_vars;
|
||||
std::vector<std::string> bind_vars;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -107,13 +107,13 @@ private:
|
|||
namespace detail {
|
||||
|
||||
template < typename Type >
|
||||
Type* create_prototype(const record &/*prototype*/)
|
||||
Type* create_prototype(const std::vector<column_definition> &/*prototype*/)
|
||||
{
|
||||
return new Type{};
|
||||
}
|
||||
|
||||
template <>
|
||||
record* create_prototype<record>(const record &prototype);
|
||||
record* create_prototype<record>(const std::vector<column_definition> &prototype);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -128,7 +128,7 @@ public:
|
|||
explicit query_result(std::unique_ptr<query_result_impl> impl)
|
||||
: impl_(std::move(impl)) {}
|
||||
|
||||
query_result(std::unique_ptr<query_result_impl> impl, record record_prototype)
|
||||
query_result(std::unique_ptr<query_result_impl> impl, std::vector<column_definition> record_prototype)
|
||||
: record_prototype_(std::move(record_prototype))
|
||||
, impl_(std::move(impl)) {}
|
||||
|
||||
|
|
@ -151,7 +151,7 @@ private:
|
|||
}
|
||||
|
||||
private:
|
||||
record record_prototype_;
|
||||
std::vector<column_definition> record_prototype_;
|
||||
std::unique_ptr<query_result_impl> impl_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ private:
|
|||
class query_result_impl
|
||||
{
|
||||
public:
|
||||
query_result_impl(std::unique_ptr<query_result_reader> &&reader, record prototype);
|
||||
query_result_impl(std::unique_ptr<query_result_reader> &&reader, std::vector<column_definition> prototype);
|
||||
|
||||
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)
|
||||
|
|
@ -110,11 +110,11 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]] const record& prototype() const;
|
||||
[[nodiscard]] const std::vector<column_definition>& prototype() const;
|
||||
|
||||
protected:
|
||||
size_t column_index_ = 0;
|
||||
record prototype_;
|
||||
std::vector<column_definition> prototype_;
|
||||
std::unique_ptr<query_result_reader> reader_;
|
||||
detail::pk_reader pk_reader_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -31,6 +31,28 @@ public:
|
|||
return insert(new Type(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<typename Type, typename PrimaryKeyType>
|
||||
entity<Type> find(const PrimaryKeyType &pk) {
|
||||
auto c = pool_.acquire();
|
||||
if (!c.valid()) {
|
||||
throw std::logic_error("no database connection available");
|
||||
}
|
||||
// collect all columns
|
||||
// - evaluate fetch::Eager flag for relations
|
||||
|
||||
// build pk where condition
|
||||
// - check if type has pk
|
||||
// - check type
|
||||
// pk_condition_builder<Type> builder;
|
||||
// auto cond = builder.build(pk);
|
||||
|
||||
// create query with relations as requested
|
||||
//
|
||||
// c->query(*schema_).select<Type>().from("xyz").where().fetch_all();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
void drop_table();
|
||||
void drop_table(const std::string &table_name);
|
||||
|
|
@ -40,7 +62,7 @@ public:
|
|||
[[nodiscard]] size_t execute(const std::string &sql) const;
|
||||
statement prepare(query_context q) const;
|
||||
|
||||
record describe_table(const std::string &table_name) const;
|
||||
std::vector<sql::column_definition> describe_table(const std::string &table_name) const;
|
||||
bool table_exists(const std::string &table_name) const;
|
||||
|
||||
[[nodiscard]] const schema& tables() const;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ set(SQL_SOURCES
|
|||
sql/noop_connection.cpp
|
||||
sql/query_part.cpp
|
||||
sql/any_type_to_string_visitor.cpp
|
||||
sql/field.cpp
|
||||
)
|
||||
|
||||
set(SQL_HEADER
|
||||
|
|
@ -86,6 +87,8 @@ set(SQL_HEADER
|
|||
../include/matador/sql/query_part.hpp
|
||||
../include/matador/sql/any_type_to_string_visitor.hpp
|
||||
../include/matador/sql/query_helper.hpp
|
||||
../include/matador/sql/field.hpp
|
||||
../include/matador/sql/entity_query_builder.hpp
|
||||
)
|
||||
|
||||
set(QUERY_SOURCES
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
#include "matador/sql/backend_provider.hpp"
|
||||
#include "matador/sql/connection_impl.hpp"
|
||||
#include "matador/sql/schema.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
|
|
@ -68,7 +70,7 @@ const connection_info &connection::info() const
|
|||
return connection_info_;
|
||||
}
|
||||
|
||||
record connection::describe(const std::string &table_name) const
|
||||
std::vector<sql::column_definition> connection::describe(const std::string &table_name) const
|
||||
{
|
||||
return std::move(connection_->describe(table_name));
|
||||
}
|
||||
|
|
@ -94,12 +96,21 @@ sql::query connection::query(const sql::schema &schema) const
|
|||
return sql::query(*const_cast<connection*>(this), schema);
|
||||
}
|
||||
|
||||
bool is_unknown(const std::vector<sql::column_definition> &columns) {
|
||||
return std::all_of(std::begin(columns), std::end(columns), [](const auto &col) {
|
||||
return col.type() == data_type_t::type_unknown;
|
||||
});
|
||||
}
|
||||
|
||||
query_result<record> connection::fetch(const query_context &q) const
|
||||
{
|
||||
if (q.prototype.empty() || q.prototype.unknown()) {
|
||||
if (q.prototype.empty() || is_unknown(q.prototype)) {
|
||||
const auto table_prototype = describe(q.table.name);
|
||||
for (auto &col : q.prototype) {
|
||||
if (const auto rit = table_prototype.find(col.name()); col.type() == data_type_t::type_unknown && rit != table_prototype.end()) {
|
||||
const auto rit = std::find_if(std::begin(table_prototype), std::end(table_prototype), [&col](const auto &value) {
|
||||
return value.name() == col.name();
|
||||
});
|
||||
if (col.type() == data_type_t::type_unknown && rit != table_prototype.end()) {
|
||||
const_cast<column_definition&>(col).type(rit->type());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
#include "matador/sql/field.hpp"
|
||||
|
||||
namespace matador::sql {
|
||||
|
||||
const std::string &field::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const field &col)
|
||||
{
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -39,7 +39,7 @@ std::unique_ptr<statement_impl> noop_connection::prepare(query_context context)
|
|||
return {};
|
||||
}
|
||||
|
||||
record noop_connection::describe(const std::string &table)
|
||||
std::vector<sql::column_definition> noop_connection::describe(const std::string &table)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,18 +141,18 @@ query_builder &query_builder::select(const std::vector<column> &columns)
|
|||
for (const auto &col: columns) {
|
||||
result.append(dialect_.prepare_identifier(col));
|
||||
query_.result_vars.emplace_back(col.name);
|
||||
query_.prototype.append(column_definition{col.name});
|
||||
query_.prototype.emplace_back(col.name);
|
||||
}
|
||||
} else {
|
||||
auto it = columns.begin();
|
||||
result.append(dialect_.prepare_identifier(*it));
|
||||
query_.result_vars.emplace_back(it->name);
|
||||
query_.prototype.append(column_definition{(*it++).name});
|
||||
query_.prototype.emplace_back((*it++).name);
|
||||
for (; it != columns.end(); ++it) {
|
||||
result.append(", ");
|
||||
result.append(dialect_.prepare_identifier(*it));
|
||||
query_.result_vars.emplace_back(it->name);
|
||||
query_.prototype.append(column_definition{(*it).name});
|
||||
query_.prototype.emplace_back((*it).name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,18 +33,18 @@ void query_compiler::visit(query_select_part &select_part)
|
|||
for (const auto &col: columns) {
|
||||
result.append(dialect_.prepare_identifier(col));
|
||||
query_.result_vars.emplace_back(col.name);
|
||||
query_.prototype.append(column_definition{col.name});
|
||||
query_.prototype.emplace_back(col.name);
|
||||
}
|
||||
} else {
|
||||
auto it = columns.begin();
|
||||
result.append(dialect_.prepare_identifier(*it));
|
||||
query_.result_vars.emplace_back(it->name);
|
||||
query_.prototype.append(column_definition{(*it++).name});
|
||||
query_.prototype.emplace_back((*it++).name);
|
||||
for (; it != columns.end(); ++it) {
|
||||
result.append(", ");
|
||||
result.append(dialect_.prepare_identifier(*it));
|
||||
query_.result_vars.emplace_back(it->name);
|
||||
query_.prototype.append(column_definition{(*it).name});
|
||||
query_.prototype.emplace_back((*it).name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
namespace matador::sql::detail {
|
||||
|
||||
template<>
|
||||
record *create_prototype<record>(const record &prototype)
|
||||
record *create_prototype<record>(const std::vector<column_definition> &prototype)
|
||||
{
|
||||
return new record{prototype};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ void detail::pk_reader::on_primary_key(const char *id, std::string &value, size_
|
|||
data_type_traits<std::string>::read_value(reader_, id, column_index_++, value, size);
|
||||
}
|
||||
|
||||
query_result_impl::query_result_impl(std::unique_ptr<query_result_reader> &&reader, record prototype)
|
||||
query_result_impl::query_result_impl(std::unique_ptr<query_result_reader> &&reader, std::vector<column_definition> prototype)
|
||||
: prototype_(std::move(prototype))
|
||||
, reader_(std::move(reader))
|
||||
, pk_reader_(*reader_)
|
||||
|
|
@ -44,7 +44,7 @@ query_result_impl::on_attribute(const char *id, any_type &value, data_type_t typ
|
|||
reader_->read_value(id, column_index_++, value, type, attr.size());
|
||||
}
|
||||
|
||||
const record& query_result_impl::prototype() const
|
||||
const std::vector<column_definition>& query_result_impl::prototype() const
|
||||
{
|
||||
return prototype_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ statement session::prepare(query_context q) const
|
|||
return c->prepare(std::move(q));
|
||||
}
|
||||
|
||||
record session::describe_table(const std::string &table_name) const
|
||||
std::vector<sql::column_definition> session::describe_table(const std::string &table_name) const
|
||||
{
|
||||
auto c = pool_.acquire();
|
||||
if (!c.valid()) {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,10 @@ add_executable(tests
|
|||
models/optional.hpp
|
||||
ConvertTest.cpp
|
||||
DummyConnection.hpp
|
||||
DummyConnection.cpp)
|
||||
DummyConnection.cpp
|
||||
EntityQueryBuilderTest.cpp
|
||||
models/author.hpp
|
||||
models/book.hpp)
|
||||
|
||||
target_link_libraries(tests PRIVATE
|
||||
Catch2::Catch2WithMain
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include <matador/sql/connection.hpp>
|
||||
|
||||
using namespace matador::sql;
|
||||
|
||||
TEST_CASE("Create sql query for entity", "[query][entity][builder]") {
|
||||
connection noop("noop://noop.db");
|
||||
schema scm("noop");
|
||||
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@
|
|||
#include <matador/sql/condition.hpp>
|
||||
#include <matador/sql/connection.hpp>
|
||||
#include <matador/sql/dialect_builder.hpp>
|
||||
#include <matador/sql/query_builder.hpp>
|
||||
#include <matador/sql/query.hpp>
|
||||
|
||||
using namespace matador::sql;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef QUERY_AUTHOR_HPP
|
||||
#define QUERY_AUTHOR_HPP
|
||||
|
||||
#include "matador/utils/access.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace matador::test {
|
||||
|
||||
struct category
|
||||
{
|
||||
unsigned long id{};
|
||||
std::string name;
|
||||
|
||||
template<class Operator>
|
||||
void process(Operator &op)
|
||||
{
|
||||
namespace field = matador::utils::access;
|
||||
using namespace matador::utils;
|
||||
field::primary_key(op, "id", id);
|
||||
field::attribute(op, "name", name, 255);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //QUERY_AUTHOR_HPP
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef QUERY_BOOK_HPP
|
||||
#define QUERY_BOOK_HPP
|
||||
|
||||
#include "matador/sql/entity.hpp"
|
||||
|
||||
#include "matador/utils/access.hpp"
|
||||
#include "matador/utils/foreign_attributes.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace matador::test {
|
||||
|
||||
struct author;
|
||||
|
||||
struct book
|
||||
{
|
||||
unsigned long id{};
|
||||
matador::sql::entity<author> book_author;
|
||||
std::string title;
|
||||
unsigned short published_in{};
|
||||
|
||||
template<typename Operator>
|
||||
void process(Operator &op)
|
||||
{
|
||||
namespace field = matador::utils::access;
|
||||
field::primary_key(op, "id", id);
|
||||
field::attribute(op, "title", title, 511);
|
||||
field::has_one(op, "author_id", book_author, matador::utils::default_foreign_attributes);
|
||||
field::attribute(op, "published_in", published_in);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
#endif //QUERY_BOOK_HPP
|
||||
Loading…
Reference in New Issue