diff --git a/backends/mysql/include/mysql_connection.hpp b/backends/mysql/include/mysql_connection.hpp index 9382c8c..c9ade35 100644 --- a/backends/mysql/include/mysql_connection.hpp +++ b/backends/mysql/include/mysql_connection.hpp @@ -37,7 +37,7 @@ public: size_t execute(const std::string &stmt) override; - sql::record describe(const std::string& table) override; + std::vector describe(const std::string& table) override; bool exists(const std::string &schema_name, const std::string &table_name) override; diff --git a/backends/mysql/src/mysql_connection.cpp b/backends/mysql/src/mysql_connection.cpp index e7796b4..8bc5a1c 100644 --- a/backends/mysql/src/mysql_connection.cpp +++ b/backends/mysql/src/mysql_connection.cpp @@ -181,13 +181,13 @@ std::unique_ptr mysql_connection::fetch(const std::strin auto field_count = mysql_num_fields(result); auto fields = mysql_fetch_fields(result); - sql::record prototype; + std::vector 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(std::make_unique(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 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 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; diff --git a/backends/postgres/include/postgres_connection.hpp b/backends/postgres/include/postgres_connection.hpp index 2f2dade..3b27ff9 100644 --- a/backends/postgres/include/postgres_connection.hpp +++ b/backends/postgres/include/postgres_connection.hpp @@ -33,7 +33,7 @@ public: size_t execute(const std::string &stmt) override; - sql::record describe(const std::string& table) override; + std::vector describe(const std::string& table) override; bool exists(const std::string &schema_name, const std::string &table_name) override; diff --git a/backends/postgres/src/postgres_connection.cpp b/backends/postgres/src/postgres_connection.cpp index 12a7aed..aa093e5 100644 --- a/backends/postgres/src/postgres_connection.cpp +++ b/backends/postgres/src/postgres_connection.cpp @@ -51,14 +51,13 @@ std::unique_ptr postgres_connection::fetch(const std::st throw_postgres_error(res, conn_, "postgres", stmt); - sql::record prototype; + std::vector 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(std::make_unique(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 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 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); diff --git a/backends/sqlite/include/sqlite_connection.hpp b/backends/sqlite/include/sqlite_connection.hpp index 38493fc..f5e3f12 100644 --- a/backends/sqlite/include/sqlite_connection.hpp +++ b/backends/sqlite/include/sqlite_connection.hpp @@ -33,14 +33,14 @@ public: size_t execute(const std::string &stmt) override; - sql::record describe(const std::string& table) override; + std::vector 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 prototype; sqlite_result_reader::rows rows; }; diff --git a/backends/sqlite/src/sqlite_connection.cpp b/backends/sqlite/src/sqlite_connection.cpp index e66a994..1034cc1 100644 --- a/backends/sqlite/src/sqlite_connection.cpp +++ b/backends/sqlite/src/sqlite_connection.cpp @@ -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 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 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); diff --git a/backends/tests/SessionTest.cpp b/backends/tests/SessionTest.cpp index 3a5df12..70e19d2 100644 --- a/backends/tests/SessionTest.cpp +++ b/backends/tests/SessionTest.cpp @@ -37,10 +37,19 @@ private: using namespace matador; TEST_CASE_METHOD(SessionFixture, "Session relation test", "[session][relation]") { - - ses.attach("airplane"); + using namespace matador; + ses.attach("airplane"); ses.create_schema(); ses.insert(1, "Boeing", "A380"); REQUIRE(true); +} + +TEST_CASE_METHOD(SessionFixture, "Find object with id", "[session][find]") { + ses.attach("airplane"); + ses.create_schema(); + auto a380 = ses.insert(1, "Boeing", "A380"); + + ses.find(1); + } \ No newline at end of file diff --git a/include/matador/sql/any_type.hpp b/include/matador/sql/any_type.hpp index e74069b..38119eb 100644 --- a/include/matador/sql/any_type.hpp +++ b/include/matador/sql/any_type.hpp @@ -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, diff --git a/include/matador/sql/connection.hpp b/include/matador/sql/connection.hpp index 04682bb..d1d72ea 100644 --- a/include/matador/sql/connection.hpp +++ b/include/matador/sql/connection.hpp @@ -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 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; diff --git a/include/matador/sql/connection_impl.hpp b/include/matador/sql/connection_impl.hpp index 6a2d1aa..f633641 100644 --- a/include/matador/sql/connection_impl.hpp +++ b/include/matador/sql/connection_impl.hpp @@ -26,7 +26,7 @@ public: virtual std::unique_ptr fetch(const std::string &stmt) = 0; virtual std::unique_ptr prepare(query_context context) = 0; - virtual record describe(const std::string &table) = 0; + virtual std::vector describe(const std::string &table) = 0; virtual bool exists(const std::string &schema_name, const std::string &table_name) = 0; protected: diff --git a/include/matador/sql/entity_query_builder.hpp b/include/matador/sql/entity_query_builder.hpp new file mode 100644 index 0000000..a9f0be6 --- /dev/null +++ b/include/matador/sql/entity_query_builder.hpp @@ -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 + 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::value && !std::is_same::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 + void on_attribute(const char * /*id*/, Type &, const utils::field_attributes &/*attr*/ = utils::null_attributes) {} + + template + void on_belongs_to(const char *id, Pointer &, const utils::foreign_attributes &/*attr*/) + { + } + + template + void on_has_one(const char *id, Pointer &, const utils::foreign_attributes &attr) + { + + } + + template + void on_has_many(const char *, ContainerType &, const char *, const char *, const utils::foreign_attributes &attr) + { + } + + template + 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 diff --git a/include/matador/sql/field.hpp b/include/matador/sql/field.hpp new file mode 100644 index 0000000..e7cc31d --- /dev/null +++ b/include/matador/sql/field.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 + +namespace matador::sql { + +class field +{ +public: + + [[nodiscard]] const std::string& name() const; + + template + Type as() const + { + const Type* ptr= std::get_if(&value_); + if (ptr) { + return *ptr; + } + any_type_to_visitor visitor; + std::visit(visitor, const_cast(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 diff --git a/include/matador/sql/noop_connection.hpp b/include/matador/sql/noop_connection.hpp index 2598eaf..182166a 100644 --- a/include/matador/sql/noop_connection.hpp +++ b/include/matador/sql/noop_connection.hpp @@ -16,7 +16,7 @@ public: size_t execute(const std::string &stmt) override; std::unique_ptr fetch(const std::string &stmt) override; std::unique_ptr prepare(query_context context) override; - record describe(const std::string &table) override; + std::vector describe(const std::string &table) override; bool exists(const std::string &schema_name, const std::string &table_name) override; private: diff --git a/include/matador/sql/query_context.hpp b/include/matador/sql/query_context.hpp index 836ac9f..c224edd 100644 --- a/include/matador/sql/query_context.hpp +++ b/include/matador/sql/query_context.hpp @@ -11,7 +11,7 @@ struct query_context std::string sql; std::string command_name; sql::table table{""}; - record prototype; + std::vector prototype; std::vector result_vars; std::vector bind_vars; }; diff --git a/include/matador/sql/query_result.hpp b/include/matador/sql/query_result.hpp index 4c10a8a..b7e2f9d 100644 --- a/include/matador/sql/query_result.hpp +++ b/include/matador/sql/query_result.hpp @@ -107,13 +107,13 @@ private: namespace detail { template < typename Type > -Type* create_prototype(const record &/*prototype*/) +Type* create_prototype(const std::vector &/*prototype*/) { return new Type{}; } template <> -record* create_prototype(const record &prototype); +record* create_prototype(const std::vector &prototype); } @@ -128,7 +128,7 @@ public: explicit query_result(std::unique_ptr impl) : impl_(std::move(impl)) {} - query_result(std::unique_ptr impl, record record_prototype) + query_result(std::unique_ptr impl, std::vector record_prototype) : record_prototype_(std::move(record_prototype)) , impl_(std::move(impl)) {} @@ -151,7 +151,7 @@ private: } private: - record record_prototype_; + std::vector record_prototype_; std::unique_ptr impl_; }; diff --git a/include/matador/sql/query_result_impl.hpp b/include/matador/sql/query_result_impl.hpp index c448488..45670c7 100644 --- a/include/matador/sql/query_result_impl.hpp +++ b/include/matador/sql/query_result_impl.hpp @@ -55,7 +55,7 @@ private: class query_result_impl { public: - query_result_impl(std::unique_ptr &&reader, record prototype); + query_result_impl(std::unique_ptr &&reader, std::vector prototype); template void on_primary_key(const char *id, ValueType &value, typename std::enable_if::value && !std::is_same::value>::type* = 0) @@ -110,11 +110,11 @@ public: return true; } - [[nodiscard]] const record& prototype() const; + [[nodiscard]] const std::vector& prototype() const; protected: size_t column_index_ = 0; - record prototype_; + std::vector prototype_; std::unique_ptr reader_; detail::pk_reader pk_reader_; }; diff --git a/include/matador/sql/session.hpp b/include/matador/sql/session.hpp index ec32cd3..6f8de4b 100644 --- a/include/matador/sql/session.hpp +++ b/include/matador/sql/session.hpp @@ -31,6 +31,28 @@ public: return insert(new Type(std::forward(args)...)); } + template + entity 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 builder; +// auto cond = builder.build(pk); + + // create query with relations as requested + // +// c->query(*schema_).select().from("xyz").where().fetch_all(); + + return {}; + } + template 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 describe_table(const std::string &table_name) const; bool table_exists(const std::string &table_name) const; [[nodiscard]] const schema& tables() const; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 626fcb0..a83d244 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/sql/connection.cpp b/src/sql/connection.cpp index 651b3da..89dabea 100644 --- a/src/sql/connection.cpp +++ b/src/sql/connection.cpp @@ -2,7 +2,9 @@ #include "matador/sql/backend_provider.hpp" #include "matador/sql/connection_impl.hpp" +#include "matador/sql/schema.hpp" +#include #include #include @@ -68,7 +70,7 @@ const connection_info &connection::info() const return connection_info_; } -record connection::describe(const std::string &table_name) const +std::vector 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(this), schema); } +bool is_unknown(const std::vector &columns) { + return std::all_of(std::begin(columns), std::end(columns), [](const auto &col) { + return col.type() == data_type_t::type_unknown; + }); +} + query_result 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(col).type(rit->type()); } } diff --git a/src/sql/field.cpp b/src/sql/field.cpp new file mode 100644 index 0000000..3e54a92 --- /dev/null +++ b/src/sql/field.cpp @@ -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; +} + +} \ No newline at end of file diff --git a/src/sql/noop_connection.cpp b/src/sql/noop_connection.cpp index 1c40e21..5985273 100644 --- a/src/sql/noop_connection.cpp +++ b/src/sql/noop_connection.cpp @@ -39,7 +39,7 @@ std::unique_ptr noop_connection::prepare(query_context context) return {}; } -record noop_connection::describe(const std::string &table) +std::vector noop_connection::describe(const std::string &table) { return {}; } diff --git a/src/sql/query_builder.cpp b/src/sql/query_builder.cpp index 9631ed2..6bec7b3 100644 --- a/src/sql/query_builder.cpp +++ b/src/sql/query_builder.cpp @@ -141,18 +141,18 @@ query_builder &query_builder::select(const std::vector &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); } } diff --git a/src/sql/query_compiler.cpp b/src/sql/query_compiler.cpp index cea385e..dec6601 100644 --- a/src/sql/query_compiler.cpp +++ b/src/sql/query_compiler.cpp @@ -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); } } diff --git a/src/sql/query_result.cpp b/src/sql/query_result.cpp index 722e471..0138f80 100644 --- a/src/sql/query_result.cpp +++ b/src/sql/query_result.cpp @@ -3,7 +3,7 @@ namespace matador::sql::detail { template<> -record *create_prototype(const record &prototype) +record *create_prototype(const std::vector &prototype) { return new record{prototype}; } diff --git a/src/sql/query_result_impl.cpp b/src/sql/query_result_impl.cpp index 1494c5b..76e2de4 100644 --- a/src/sql/query_result_impl.cpp +++ b/src/sql/query_result_impl.cpp @@ -11,7 +11,7 @@ void detail::pk_reader::on_primary_key(const char *id, std::string &value, size_ data_type_traits::read_value(reader_, id, column_index_++, value, size); } -query_result_impl::query_result_impl(std::unique_ptr &&reader, record prototype) +query_result_impl::query_result_impl(std::unique_ptr &&reader, std::vector 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& query_result_impl::prototype() const { return prototype_; } diff --git a/src/sql/session.cpp b/src/sql/session.cpp index 779cfc0..b066b45 100644 --- a/src/sql/session.cpp +++ b/src/sql/session.cpp @@ -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 session::describe_table(const std::string &table_name) const { auto c = pool_.acquire(); if (!c.valid()) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d97b6e6..f6384ee 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -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 diff --git a/test/EntityQueryBuilderTest.cpp b/test/EntityQueryBuilderTest.cpp new file mode 100644 index 0000000..a9c304a --- /dev/null +++ b/test/EntityQueryBuilderTest.cpp @@ -0,0 +1,11 @@ +#include + +#include + +using namespace matador::sql; + +TEST_CASE("Create sql query for entity", "[query][entity][builder]") { + connection noop("noop://noop.db"); + schema scm("noop"); + +} \ No newline at end of file diff --git a/test/QueryBuilderTest.cpp b/test/QueryBuilderTest.cpp index 5ff1562..e524f86 100644 --- a/test/QueryBuilderTest.cpp +++ b/test/QueryBuilderTest.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include using namespace matador::sql; diff --git a/test/models/author.hpp b/test/models/author.hpp new file mode 100644 index 0000000..82f34b9 --- /dev/null +++ b/test/models/author.hpp @@ -0,0 +1,27 @@ +#ifndef QUERY_AUTHOR_HPP +#define QUERY_AUTHOR_HPP + +#include "matador/utils/access.hpp" + +#include + +namespace matador::test { + +struct category +{ + unsigned long id{}; + std::string name; + + template + 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 diff --git a/test/models/book.hpp b/test/models/book.hpp new file mode 100644 index 0000000..41b1217 --- /dev/null +++ b/test/models/book.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 + +namespace matador::test { + +struct author; + +struct book +{ + unsigned long id{}; + matador::sql::entity book_author; + std::string title; + unsigned short published_in{}; + + template + 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