add column info (progress, not compiling)

This commit is contained in:
Sascha Kuehl 2024-02-08 20:09:24 +01:00
parent 78c5f64b34
commit b966a7a1a7
24 changed files with 286 additions and 99 deletions

View File

@ -12,7 +12,7 @@ list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras)
include(CTest) include(CTest)
include(Catch) include(Catch)
set(POSTGRES_CONNECTION_STRING "postgres://test:test123@127.0.0.1:5432/matador_test") set(POSTGRES_CONNECTION_STRING "postgres://test:test123@127.0.0.1:15432/test")
configure_file(Connection.hpp.in ${PROJECT_BINARY_DIR}/backends/postgres/test/connection.hpp @ONLY IMMEDIATE) configure_file(Connection.hpp.in ${PROJECT_BINARY_DIR}/backends/postgres/test/connection.hpp @ONLY IMMEDIATE)

View File

@ -121,7 +121,7 @@ TEST_CASE_METHOD(QueryFixture, " Execute insert statement", "[session]")
.execute(); .execute();
auto res = db.insert() auto res = db.insert()
.into("person", {"id", "name", "color"}) .into("person", {{"", "id", ""}, {"", "name", ""}, {"", "color", ""}})
.values({7, "george", "green"}) .values({7, "george", "green"})
.execute(); .execute();

View File

@ -13,7 +13,7 @@
namespace matador::sql { namespace matador::sql {
class table_repository; class schema;
class fk_column_generator class fk_column_generator
{ {
@ -53,13 +53,13 @@ private:
class column_generator class column_generator
{ {
private: private:
column_generator(std::vector<column> &columns, const table_repository &repo); column_generator(std::vector<column> &columns, const schema &repo);
public: public:
~column_generator() = default; ~column_generator() = default;
template < class Type > template < class Type >
static std::vector<column> generate(const table_repository &repo) static std::vector<column> generate(const schema &repo)
{ {
std::vector<column> columns; std::vector<column> columns;
column_generator gen(columns, repo); column_generator gen(columns, repo);
@ -102,7 +102,7 @@ private:
private: private:
size_t index_ = 0; size_t index_ = 0;
std::vector<column> &columns_; std::vector<column> &columns_;
const table_repository &repo_; const schema &repo_;
fk_column_generator fk_column_generator_; fk_column_generator fk_column_generator_;
}; };

View File

@ -5,24 +5,38 @@
#include "matador/utils/field_attributes.hpp" #include "matador/utils/field_attributes.hpp"
#include "matador/utils/foreign_attributes.hpp" #include "matador/utils/foreign_attributes.hpp"
#include "matador/sql/schema.hpp"
#include <string> #include <string>
#include <vector> #include <vector>
#include <stack>
namespace matador::sql { namespace matador::sql {
struct column_info
{
std::string table;
std::string name;
std::string alias;
};
class column_name_generator class column_name_generator
{ {
private: private:
explicit column_name_generator(std::vector<std::string> &column_names); column_name_generator(std::vector<column_info> &column_infos, const sql::schema &ts, const std::string &table_name);
public: public:
~column_name_generator() = default; ~column_name_generator() = default;
template < class Type > template < class Type >
static std::vector<std::string> generate() static std::vector<column_info> generate(const sql::schema &ts)
{ {
std::vector<std::string> columns; const auto info = ts.info<Type>();
column_name_generator gen(columns); if (!info) {
return {};
}
std::vector<column_info> columns;
column_name_generator gen(columns, ts, info.value().name);
Type obj; Type obj;
matador::utils::access::process(gen, obj); matador::utils::access::process(gen, obj);
return std::move(columns); return std::move(columns);
@ -31,7 +45,7 @@ public:
template < class V > 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, V &, typename std::enable_if<std::is_integral<V>::value && !std::is_same<bool, V>::value>::type* = 0)
{ {
column_names_.emplace_back(id); push(id);
} }
void on_primary_key(const char *id, std::string &, size_t); void on_primary_key(const char *id, std::string &, size_t);
void on_revision(const char *id, unsigned long long &/*rev*/); void on_revision(const char *id, unsigned long long &/*rev*/);
@ -39,26 +53,49 @@ public:
template<typename Type> template<typename Type>
void on_attribute(const char *id, Type &, const utils::field_attributes &/*attr*/ = utils::null_attributes) void on_attribute(const char *id, Type &, const utils::field_attributes &/*attr*/ = utils::null_attributes)
{ {
column_names_.emplace_back(id); push(id);
} }
template<class Pointer> template<class Pointer>
void on_belongs_to(const char *id, Pointer &, const utils::foreign_attributes &/*attr*/) void on_belongs_to(const char *id, Pointer &, const utils::foreign_attributes &/*attr*/)
{ {
column_names_.emplace_back(id); push(id);
} }
template<class Pointer> template<class Pointer>
void on_has_one(const char *id, Pointer &, const utils::foreign_attributes &/*attr*/) void on_has_one(const char *id, Pointer &, const utils::foreign_attributes &/*attr*/)
{ {
column_names_.emplace_back(id); push(id);
} }
template<class ContainerType> template<class ContainerType>
void on_has_many(const char *, ContainerType &, const char *, const char *, const utils::foreign_attributes &/*attr*/) {} void on_has_many(const char *, ContainerType &, const char *, const char *, const utils::foreign_attributes &attr)
{
if (attr.fetch() == fetch_type::LAZY) {
return;
}
const auto info = table_schema_.info<typename ContainerType::value_type::value_type>();
if (!info) {
return;
}
table_name_stack_.push(info.value().name);
typename ContainerType::value_type::value_type obj;
matador::utils::access::process(*this, obj);
table_name_stack_.pop();
}
template<class ContainerType> template<class ContainerType>
void on_has_many(const char *, ContainerType &, const utils::foreign_attributes &/*attr*/) {} void on_has_many(const char *id, ContainerType &c, const utils::foreign_attributes &attr)
{
on_has_many(id, c, "", "", attr);
}
private: private:
std::vector<std::string> &column_names_; void push(const std::string &column_name);
private:
std::stack<std::string> table_name_stack_;
std::vector<column_info> &column_infos_;
const sql::schema &table_schema_;
int column_index{0};
}; };
} }

View File

@ -19,8 +19,8 @@ namespace matador::sql {
class connection class connection
{ {
public: public:
explicit connection(connection_info info, const std::shared_ptr<table_repository> &repo = std::make_shared<table_repository>()); explicit connection(connection_info info, const std::shared_ptr<schema> &repo = std::make_shared<schema>());
explicit connection(const std::string& dns, const std::shared_ptr<table_repository> &repo = std::make_shared<table_repository>()); explicit connection(const std::string& dns, const std::shared_ptr<schema> &repo = std::make_shared<schema>());
connection(const connection &x); connection(const connection &x);
connection& operator=(const connection &x); connection& operator=(const connection &x);
connection(connection &&x) noexcept = default; connection(connection &&x) noexcept = default;
@ -51,20 +51,20 @@ public:
statement prepare(query_context &&query) const; statement prepare(query_context &&query) const;
const class dialect& dialect() const; const class dialect& dialect() const;
std::shared_ptr<table_repository> tables() const; std::shared_ptr<schema> tables() const;
private: private:
connection_info connection_info_; connection_info connection_info_;
std::unique_ptr<connection_impl> connection_; std::unique_ptr<connection_impl> connection_;
utils::logger logger_; utils::logger logger_;
const class dialect &dialect_; const class dialect &dialect_;
std::shared_ptr<table_repository> table_repository_; std::shared_ptr<schema> schema_;
}; };
template<class Type> template<class Type>
query_select_intermediate connection::select() query_select_intermediate connection::select()
{ {
return query_select_intermediate{*this, column_generator::generate<Type>(*table_repository_)}; return query_select_intermediate{*this, column_generator::generate<Type>(*schema_)};
} }
} }

View File

@ -126,8 +126,8 @@ public:
query_builder& table(const std::string &table, std::initializer_list<column> columns); query_builder& table(const std::string &table, std::initializer_list<column> columns);
query_builder& table(const std::string &table, const std::vector<column> &columns); query_builder& table(const std::string &table, const std::vector<column> &columns);
query_builder& table(const std::string &table); query_builder& table(const std::string &table);
query_builder& into(const std::string &table, std::initializer_list<std::string> column_names); query_builder& into(const std::string &table, std::initializer_list<column_info> column_names);
query_builder& into(const std::string &table, const std::vector<std::string> &column_names); query_builder& into(const std::string &table, const std::vector<column_info> &column_names);
query_builder& values(std::initializer_list<any_type> values); query_builder& values(std::initializer_list<any_type> values);
query_builder& values(const std::vector<any_type> &values); query_builder& values(const std::vector<any_type> &values);
query_builder& from(const std::string &table, const std::string &as = ""); query_builder& from(const std::string &table, const std::string &as = "");

View File

@ -11,7 +11,7 @@
#include "matador/sql/query_result.hpp" #include "matador/sql/query_result.hpp"
#include "matador/sql/record.hpp" #include "matador/sql/record.hpp"
#include "matador/sql/statement.hpp" #include "matador/sql/statement.hpp"
#include "matador/sql/table_repository.hpp" #include "matador/sql/schema.hpp"
#include "matador/sql/value_extractor.hpp" #include "matador/sql/value_extractor.hpp"
#include <string> #include <string>
@ -21,13 +21,24 @@ namespace matador::sql {
class basic_condition; class basic_condition;
class connection; class connection;
class query_intermediate class basic_query_intermediate
{
public:
explicit basic_query_intermediate(connection &db);
protected:
[[nodiscard]] std::shared_ptr<schema> tables() const;
protected:
connection &connection_;
};
class query_intermediate : public basic_query_intermediate
{ {
public: public:
query_intermediate(connection &db, query_builder &query); query_intermediate(connection &db, query_builder &query);
protected: protected:
connection &connection_;
query_builder &builder_; query_builder &builder_;
}; };
@ -149,13 +160,12 @@ public:
query_order_by_intermediate order_by(const std::string &name); query_order_by_intermediate order_by(const std::string &name);
}; };
class query_start_intermediate class query_start_intermediate : public basic_query_intermediate
{ {
public: public:
explicit query_start_intermediate(connection &s); explicit query_start_intermediate(connection &s);
protected: protected:
connection &connection_;
query_builder builder_; query_builder builder_;
}; };
@ -210,9 +220,6 @@ public:
} }
return {connection_, builder_.table(table_name, column_generator::generate<Type>(*tables()))}; return {connection_, builder_.table(table_name, column_generator::generate<Type>(*tables()))};
} }
private:
std::shared_ptr<table_repository> tables() const;
}; };
class query_drop_intermediate : query_start_intermediate class query_drop_intermediate : query_start_intermediate
@ -228,16 +235,16 @@ class query_insert_intermediate : public query_start_intermediate
public: public:
explicit query_insert_intermediate(connection &s); explicit query_insert_intermediate(connection &s);
query_into_intermediate into(const std::string &table, std::initializer_list<std::string> column_names); query_into_intermediate into(const std::string &table, std::initializer_list<column_info> column_names);
template<class Type> template<class Type>
query_into_intermediate into(const std::string &table) query_into_intermediate into(const std::string &table)
{ {
return {connection_, builder_.into(table, column_name_generator::generate<Type>())}; return {connection_, builder_.into(table, column_name_generator::generate<Type>(*tables()))};
} }
template<class Type> template<class Type>
query_execute_finish into(const std::string &table, const Type &obj) query_execute_finish into(const std::string &table, const Type &obj)
{ {
return {connection_, builder_.into(table, column_name_generator::generate<Type>()) return {connection_, builder_.into(table, column_name_generator::generate<Type>(*tables()))
.values(value_extractor::extract(obj))}; .values(value_extractor::extract(obj))};
} }
}; };

View File

@ -1,5 +1,5 @@
#ifndef QUERY_TABLE_REPOSITORY_HPP #ifndef QUERY_SCHEMA_HPP
#define QUERY_TABLE_REPOSITORY_HPP #define QUERY_SCHEMA_HPP
#include "matador/sql/column_generator.hpp" #include "matador/sql/column_generator.hpp"
#include "matador/sql/record.hpp" #include "matador/sql/record.hpp"
@ -21,7 +21,7 @@ struct table_info
void drop(connection &conn) const; void drop(connection &conn) const;
}; };
class table_repository class schema
{ {
public: public:
using repository = std::unordered_map<std::type_index, table_info>; using repository = std::unordered_map<std::type_index, table_info>;
@ -37,12 +37,12 @@ public:
const table_info& attach(std::type_index ti, const table_info& table); const table_info& attach(std::type_index ti, const table_info& table);
template<typename Type> template<typename Type>
std::optional<table_info> info() [[nodiscard]] std::optional<table_info> info() const
{ {
return info(std::type_index(typeid(Type))); return info(std::type_index(typeid(Type)));
} }
std::optional<table_info> info(std::type_index ti); [[nodiscard]] std::optional<table_info> info(std::type_index ti) const;
template<typename Type> template<typename Type>
[[nodiscard]] std::pair<std::string, std::string> reference() const [[nodiscard]] std::pair<std::string, std::string> reference() const
@ -61,11 +61,11 @@ public:
[[nodiscard]] bool exists(const std::type_index &ti) const; [[nodiscard]] bool exists(const std::type_index &ti) const;
iterator begin(); iterator begin();
const_iterator begin() const; [[nodiscard]] const_iterator begin() const;
iterator end(); iterator end();
const_iterator end() const; [[nodiscard]] const_iterator end() const;
bool empty() const; [[nodiscard]] bool empty() const;
private: private:
repository repository_; repository repository_;
@ -73,4 +73,4 @@ private:
} }
#endif //QUERY_TABLE_REPOSITORY_HPP #endif //QUERY_SCHEMA_HPP

View File

@ -5,7 +5,7 @@
#include "matador/sql/connection_pool.hpp" #include "matador/sql/connection_pool.hpp"
#include "matador/sql/entity.hpp" #include "matador/sql/entity.hpp"
#include "matador/sql/statement.hpp" #include "matador/sql/statement.hpp"
#include "matador/sql/table_repository.hpp" #include "matador/sql/schema.hpp"
#include <unordered_map> #include <unordered_map>
@ -43,7 +43,7 @@ public:
record describe_table(const std::string &table_name) const; record describe_table(const std::string &table_name) const;
bool table_exists(const std::string &table_name) const; bool table_exists(const std::string &table_name) const;
[[nodiscard]] const table_repository& tables() const; [[nodiscard]] const schema& tables() const;
const class dialect& dialect() const; const class dialect& dialect() const;
@ -56,21 +56,21 @@ private:
connection_pool<connection> &pool_; connection_pool<connection> &pool_;
const class dialect &dialect_; const class dialect &dialect_;
table_repository table_repository_; schema schema_;
mutable std::unordered_map<std::string, record> prototypes_; mutable std::unordered_map<std::string, record> prototypes_;
}; };
template<typename Type> template<typename Type>
void session::attach(const std::string &table_name) void session::attach(const std::string &table_name)
{ {
table_repository_.attach<Type>(table_name); schema_.attach<Type>(table_name);
} }
template<typename Type> template<typename Type>
entity<Type> session::insert(Type *obj) entity<Type> session::insert(Type *obj)
{ {
auto c = pool_.acquire(); auto c = pool_.acquire();
auto info = table_repository_.info<Type>(); auto info = schema_.info<Type>();
if (!info) { if (!info) {
return {}; return {};
} }
@ -82,7 +82,7 @@ entity<Type> session::insert(Type *obj)
template<typename Type> template<typename Type>
void session::drop_table() void session::drop_table()
{ {
auto info = table_repository_.info<Type>(); auto info = schema_.info<Type>();
if (info) { if (info) {
return drop_table(info.name); return drop_table(info.name);
} }

View File

@ -64,13 +64,23 @@ void belongs_to(Operator &op, const char *id, Type &value, const foreign_attribu
op.on_belongs_to(id, value, attr); op.on_belongs_to(id, value, attr);
} }
//template<class Operator, class Type, template<class ...> class ContainerType>
//void has_many(Operator &op, const char *id, container<Type, ContainerType> &container, const foreign_attributes &attr) {
// op.on_has_many(id, container, attr);
//}
template<class Operator, class Type, template<class ...> class ContainerType> template<class Operator, class Type, template<class ...> class ContainerType>
void has_many(Operator &op, const char *id, container<Type, ContainerType> &container, const foreign_attributes &attr) { void has_many(Operator &op, const char *id, ContainerType<Type> &container, const foreign_attributes &attr) {
op.on_has_many(id, container, attr); op.on_has_many(id, container, attr);
} }
//template<class Operator, class Type, template<class ...> class ContainerType>
//void has_many(Operator &op, const char *id, container<Type, ContainerType> &container, const char *left_column, const char *right_column, const foreign_attributes &attr) {
// op.on_has_many(id, container, left_column, right_column, attr);
//}
template<class Operator, class Type, template<class ...> class ContainerType> template<class Operator, class Type, template<class ...> class ContainerType>
void has_many(Operator &op, const char *id, container<Type, ContainerType> &container, const char *left_column, const char *right_column, const foreign_attributes &attr) { void has_many(Operator &op, const char *id, ContainerType<Type> &container, const char *left_column, const char *right_column, const foreign_attributes &attr) {
op.on_has_many(id, container, left_column, right_column, attr); op.on_has_many(id, container, left_column, right_column, attr);
} }

View File

@ -16,7 +16,7 @@ set(SQL_SOURCES
sql/column_name_generator.cpp sql/column_name_generator.cpp
sql/key_value_generator.cpp sql/key_value_generator.cpp
sql/fk_value_extractor.cpp sql/fk_value_extractor.cpp
sql/table_repository.cpp sql/schema.cpp
sql/query_result.cpp sql/query_result.cpp
sql/query_result_reader.cpp sql/query_result_reader.cpp
sql/statement_cache.cpp sql/statement_cache.cpp
@ -55,7 +55,7 @@ set(SQL_HEADER
../include/matador/sql/key_value_generator.hpp ../include/matador/sql/key_value_generator.hpp
../include/matador/sql/entity.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/schema.hpp
../include/matador/sql/any_type_to_visitor.hpp ../include/matador/sql/any_type_to_visitor.hpp
../include/matador/sql/query_result_reader.hpp ../include/matador/sql/query_result_reader.hpp
../include/matador/sql/to_value.hpp ../include/matador/sql/to_value.hpp

View File

@ -1,9 +1,9 @@
#include "matador/sql/column_generator.hpp" #include "matador/sql/column_generator.hpp"
#include "matador/sql/table_repository.hpp" #include "matador/sql/schema.hpp"
namespace matador::sql { namespace matador::sql {
column_generator::column_generator(std::vector<column> &columns, const table_repository &repo) column_generator::column_generator(std::vector<column> &columns, const schema &repo)
: columns_(columns) : columns_(columns)
, repo_(repo) , repo_(repo)
{} {}

View File

@ -2,18 +2,30 @@
namespace matador::sql { namespace matador::sql {
column_name_generator::column_name_generator(std::vector<std::string> &column_names) column_name_generator::column_name_generator(std::vector<column_info> &column_infos,
: column_names_(column_names) const sql::schema &ts,
{} const std::string &table_name)
: column_infos_(column_infos)
, table_schema_(ts)
{
table_name_stack_.push(table_name);
}
void column_name_generator::on_primary_key(const char *id, std::string &, size_t) void column_name_generator::on_primary_key(const char *id, std::string &, size_t)
{ {
column_names_.emplace_back(id); push(id);
} }
void column_name_generator::on_revision(const char *id, unsigned long long int &) void column_name_generator::on_revision(const char *id, unsigned long long int &)
{ {
column_names_.emplace_back(id); push(id);
}
void column_name_generator::push(const std::string &column_name)
{
char str[4];
snprintf(str, 4, "c%02d", ++column_index);
column_infos_.emplace_back(column_info{table_name_stack_.top(), column_name, str});
} }
} }

View File

@ -8,16 +8,16 @@
namespace matador::sql { namespace matador::sql {
connection::connection(connection_info info, const std::shared_ptr<table_repository> &repo) connection::connection(connection_info info, const std::shared_ptr<schema> &repo)
: connection_info_(std::move(info)) : connection_info_(std::move(info))
, logger_(stdout, "SQL") , logger_(stdout, "SQL")
, dialect_(backend_provider::instance().connection_dialect(connection_info_.type)) , dialect_(backend_provider::instance().connection_dialect(connection_info_.type))
, table_repository_(repo) , schema_(repo)
{ {
connection_.reset(backend_provider::instance().create_connection(connection_info_.type, connection_info_)); connection_.reset(backend_provider::instance().create_connection(connection_info_.type, connection_info_));
} }
connection::connection(const std::string& dns, const std::shared_ptr<table_repository> &repo) connection::connection(const std::string& dns, const std::shared_ptr<schema> &repo)
: connection(connection_info::parse(dns), repo) : connection(connection_info::parse(dns), repo)
{} {}
@ -160,9 +160,9 @@ const class dialect &connection::dialect() const
return dialect_; return dialect_;
} }
std::shared_ptr<table_repository> connection::tables() const std::shared_ptr<schema> connection::tables() const
{ {
return table_repository_; return schema_;
} }
} }

View File

@ -1,4 +1,5 @@
#include "matador/sql/query_builder.hpp" #include "matador/sql/query_builder.hpp"
#include "matador/sql/column_name_generator.hpp"
#include "matador/sql/dialect.hpp" #include "matador/sql/dialect.hpp"
#include "matador/utils/string.hpp" #include "matador/utils/string.hpp"
@ -255,12 +256,12 @@ query_builder &query_builder::table(const std::string &table)
return *this; return *this;
} }
query_builder &query_builder::into(const std::string &table, std::initializer_list<std::string> column_names) query_builder &query_builder::into(const std::string &table, std::initializer_list<column_info> column_names)
{ {
return into(table, std::vector<std::string>{column_names}); return into(table, std::vector<column_info>{column_names});
} }
query_builder &query_builder::into(const std::string &table, const std::vector<std::string> &column_names) query_builder &query_builder::into(const std::string &table, const std::vector<column_info> &column_names)
{ {
transition_to(state_t::QUERY_INTO); transition_to(state_t::QUERY_INTO);
@ -270,14 +271,14 @@ query_builder &query_builder::into(const std::string &table, const std::vector<s
std::string result{"("}; std::string result{"("};
if (column_names.size() < 2) { if (column_names.size() < 2) {
for (const auto &col: column_names) { for (const auto &col: column_names) {
result.append(dialect_.prepare_identifier(col)); result.append(dialect_.prepare_identifier(col.name));
} }
} else { } else {
auto it = column_names.begin(); auto it = column_names.begin();
result.append(dialect_.prepare_identifier(*it++)); result.append(dialect_.prepare_identifier((it++)->name));
for (; it != column_names.end(); ++it) { for (; it != column_names.end(); ++it) {
result.append(", "); result.append(", ");
result.append(dialect_.prepare_identifier(*it)); result.append(dialect_.prepare_identifier(it->name));
} }
} }
result += (")"); result += (")");

View File

@ -2,6 +2,13 @@
#include "matador/sql/session.hpp" #include "matador/sql/session.hpp"
namespace matador::sql { namespace matador::sql {
basic_query_intermediate::basic_query_intermediate(connection &db)
: connection_(db) {}
std::shared_ptr<schema> basic_query_intermediate::tables() const
{
return connection_.tables();
}
query_result<record> query_select_finish::fetch_all() query_result<record> query_select_finish::fetch_all()
{ {
@ -24,7 +31,7 @@ statement query_select_finish::prepare()
} }
query_intermediate::query_intermediate(connection &db, query_builder &query) query_intermediate::query_intermediate(connection &db, query_builder &query)
: connection_(db), builder_(query) {} : basic_query_intermediate(db), builder_(query) {}
query_offset_intermediate query_order_direction_intermediate::offset(size_t offset) query_offset_intermediate query_order_direction_intermediate::offset(size_t offset)
{ {
@ -128,7 +135,7 @@ query_insert_intermediate::query_insert_intermediate(connection &s)
builder_.insert(); builder_.insert();
} }
query_into_intermediate query_insert_intermediate::into(const std::string &table, std::initializer_list<std::string> column_names) query_into_intermediate query_insert_intermediate::into(const std::string &table, std::initializer_list<column_info> column_names)
{ {
return {connection_, builder_.into(table, column_names)}; return {connection_, builder_.into(table, column_names)};
} }
@ -163,11 +170,6 @@ query_execute_finish query_create_intermediate::table(const std::string &table_n
return {connection_, builder_.table(table_name, columns)}; return {connection_, builder_.table(table_name, columns)};
} }
std::shared_ptr<table_repository> query_create_intermediate::tables() const
{
return connection_.tables();
}
query_drop_intermediate::query_drop_intermediate(connection &s) query_drop_intermediate::query_drop_intermediate(connection &s)
: query_start_intermediate(s) : query_start_intermediate(s)
{ {
@ -217,7 +219,7 @@ query_delete_from_intermediate query_delete_intermediate::from(const std::string
} }
query_start_intermediate::query_start_intermediate(connection &s) query_start_intermediate::query_start_intermediate(connection &s)
: connection_(s) : basic_query_intermediate(s)
, builder_(s.dialect()) , builder_(s.dialect())
{} {}
} }

View File

@ -1,4 +1,4 @@
#include "matador/sql/table_repository.hpp" #include "matador/sql/schema.hpp"
#include "matador/sql/connection.hpp" #include "matador/sql/connection.hpp"
#include <stdexcept> #include <stdexcept>
@ -15,12 +15,12 @@ void table_info::drop(connection &conn) const
conn.drop().table(name).execute(); conn.drop().table(name).execute();
} }
const table_info& table_repository::attach(const std::type_index ti, const table_info& table) const table_info& schema::attach(const std::type_index ti, const table_info& table)
{ {
return repository_.try_emplace(ti, table).first->second; return repository_.try_emplace(ti, table).first->second;
} }
std::optional<table_info> table_repository::info(std::type_index ti) std::optional<table_info> schema::info(std::type_index ti) const
{ {
const auto it = repository_.find(ti); const auto it = repository_.find(ti);
if (it == repository_.end()) { if (it == repository_.end()) {
@ -29,7 +29,7 @@ std::optional<table_info> table_repository::info(std::type_index ti)
return it->second; return it->second;
} }
std::pair<std::string, std::string> table_repository::reference(const std::type_index &ti) const std::pair<std::string, std::string> schema::reference(const std::type_index &ti) const
{ {
const auto it = repository_.find(ti); const auto it = repository_.find(ti);
if (it != repository_.end()) { if (it != repository_.end()) {
@ -42,32 +42,32 @@ std::pair<std::string, std::string> table_repository::reference(const std::type_
return {}; return {};
} }
bool table_repository::exists(const std::type_index &ti) const bool schema::exists(const std::type_index &ti) const
{ {
return repository_.count(ti) > 0; return repository_.count(ti) > 0;
} }
table_repository::iterator table_repository::begin() schema::iterator schema::begin()
{ {
return repository_.begin(); return repository_.begin();
} }
table_repository::const_iterator table_repository::begin() const schema::const_iterator schema::begin() const
{ {
return repository_.begin(); return repository_.begin();
} }
table_repository::iterator table_repository::end() schema::iterator schema::end()
{ {
return repository_.end(); return repository_.end();
} }
table_repository::const_iterator table_repository::end() const schema::const_iterator schema::end() const
{ {
return repository_.end(); return repository_.end();
} }
bool table_repository::empty() const bool schema::empty() const
{ {
return repository_.empty(); return repository_.empty();
} }

View File

@ -13,7 +13,7 @@ session::session(connection_pool<connection> &pool)
void session::create_schema() void session::create_schema()
{ {
auto c = pool_.acquire(); auto c = pool_.acquire();
for (const auto &t : table_repository_) { for (const auto &t : schema_) {
t.second.create(*c); t.second.create(*c);
} }
} }
@ -88,9 +88,9 @@ bool session::table_exists(const std::string &table_name) const
return c->exists(dialect_.default_schema_name(), table_name); return c->exists(dialect_.default_schema_name(), table_name);
} }
const table_repository& session::tables() const const schema& session::tables() const
{ {
return table_repository_; return schema_;
} }
const class dialect &session::dialect() const const class dialect &session::dialect() const

View File

@ -13,6 +13,8 @@ add_executable(tests QueryBuilderTest.cpp
ConnectionPoolTest.cpp ConnectionPoolTest.cpp
BackendProviderTest.cpp BackendProviderTest.cpp
models/product.hpp models/product.hpp
models/order.hpp
models/order_details.h
ColumnGeneratorTest.cpp ColumnGeneratorTest.cpp
ColumnNameGeneratorTest.cpp ColumnNameGeneratorTest.cpp
ValueGeneratorTest.cpp ValueGeneratorTest.cpp

View File

@ -1,7 +1,7 @@
#include <catch2/catch_test_macros.hpp> #include <catch2/catch_test_macros.hpp>
#include "matador/sql/column_generator.hpp" #include "matador/sql/column_generator.hpp"
#include "matador/sql/table_repository.hpp" #include "matador/sql/schema.hpp"
#include "models/product.hpp" #include "models/product.hpp"
#include "models/optional.hpp" #include "models/optional.hpp"
@ -10,7 +10,7 @@ using namespace matador::sql;
using namespace matador::utils; using namespace matador::utils;
TEST_CASE("Generate columns from object", "[column generator]") { TEST_CASE("Generate columns from object", "[column generator]") {
table_repository repo; schema repo;
auto columns = column_generator::generate<matador::test::product>(repo); auto columns = column_generator::generate<matador::test::product>(repo);
@ -36,7 +36,7 @@ TEST_CASE("Generate columns from object", "[column generator]") {
} }
TEST_CASE("Generate columns from object with nullable columns", "[column generator]") { TEST_CASE("Generate columns from object with nullable columns", "[column generator]") {
table_repository repo; schema repo;
auto columns = column_generator::generate<matador::test::optional>(repo); auto columns = column_generator::generate<matador::test::optional>(repo);

View File

@ -1,14 +1,18 @@
#include <catch2/catch_test_macros.hpp> #include <catch2/catch_test_macros.hpp>
#include "matador/sql/column_name_generator.hpp" #include "matador/sql/column_name_generator.hpp"
#include "matador/sql/schema.hpp"
#include "models/order.hpp"
#include "models/product.hpp" #include "models/product.hpp"
using namespace matador::sql; using namespace matador::sql;
TEST_CASE("Generate column names from object", "[column name generator]") { TEST_CASE("Generate column names from object", "[column name generator]") {
schema s;
s.attach<matador::test::product>("product");
auto columns = column_name_generator::generate<matador::test::product>(); auto columns = column_name_generator::generate<matador::test::product>(s);
const std::vector<std::string> expected_columns = { const std::vector<std::string> expected_columns = {
"product_name", "product_name",
@ -25,6 +29,40 @@ TEST_CASE("Generate column names from object", "[column name generator]") {
REQUIRE(columns.size() == expected_columns.size()); REQUIRE(columns.size() == expected_columns.size());
for (size_t i = 0; i != expected_columns.size(); ++i) { for (size_t i = 0; i != expected_columns.size(); ++i) {
REQUIRE(expected_columns[i] == columns[i]); REQUIRE(expected_columns[i] == columns[i].name);
} }
} }
TEST_CASE("Generate column names for object with has many relation", "[column][relation]") {
schema s;
s.attach<matador::test::product>("product");
s.attach<matador::test::order_details>("order_details");
s.attach<matador::test::order>("order");
auto columns = column_name_generator::generate<matador::test::order>(s);
const std::vector<std::string> expected_columns = {
"order_id",
"order_date",
"required_date",
"shipped_date",
"ship_via",
"freight",
"ship_name",
"ship_address",
"ship_city",
"ship_region",
"ship_postal_code",
"ship_country",
"order_details_id",
"order_id",
"product_id",
};
REQUIRE(!columns.empty());
REQUIRE(columns.size() == expected_columns.size());
for (size_t i = 0; i != expected_columns.size(); ++i) {
REQUIRE(expected_columns[i] == columns[i].name);
}
}

View File

@ -164,7 +164,7 @@ TEST_CASE("Create, insert and select a blob column", "[query][blob]") {
REQUIRE(q.table_name == "person"); REQUIRE(q.table_name == "person");
q = query.insert().into("person", { q = query.insert().into("person", {
"id", "name", "data" {"", "id", ""}, {"", "name", ""}, {"", "data", ""}
}).values({7UL, "george", blob{1, 'A', 3, 4}}).compile(); }).values({7UL, "george", blob{1, 'A', 3, 4}}).compile();
REQUIRE(q.sql == R"(INSERT INTO "person" ("id", "name", "data") VALUES (7, 'george', X'01410304'))"); REQUIRE(q.sql == R"(INSERT INTO "person" ("id", "name", "data") VALUES (7, 'george', X'01410304'))");

50
test/models/order.hpp Normal file
View File

@ -0,0 +1,50 @@
#ifndef QUERY_ORDER_HPP
#define QUERY_ORDER_HPP
#include "order_details.h"
#include "matador/utils/access.hpp"
#include "matador/sql/entity.hpp"
#include <vector>
namespace matador::test {
struct order
{
unsigned long order_id{};
std::string order_date;
std::string required_date;
std::string shipped_date;
unsigned int ship_via{};
unsigned int freight{};
std::string ship_name;
std::string ship_address;
std::string ship_city;
std::string ship_region;
std::string ship_postal_code;
std::string ship_country;
std::vector<sql::entity<order_details>> order_details_;
template<class Operator>
void process(Operator &op) {
namespace field = matador::utils::access;
field::primary_key(op, "order_id", order_id);
field::attribute(op, "order_date", order_date, 255);
field::attribute(op, "required_date", required_date, 255);
field::attribute(op, "shipped_date", shipped_date, 255);
field::attribute(op, "ship_via", ship_via);
field::attribute(op, "freight", freight);
field::attribute(op, "ship_name", ship_name, 255);
field::attribute(op, "ship_address", ship_address, 255);
field::attribute(op, "ship_city", ship_city, 255);
field::attribute(op, "ship_region", ship_region, 255);
field::attribute(op, "ship_postal_code", ship_postal_code, 255);
field::attribute(op, "ship_country", ship_country, 255);
field::has_many(op, "order_details", order_details_, fetch_type::EAGER);
}
};
}
#endif //QUERY_ORDER_HPP

View File

@ -0,0 +1,28 @@
#ifndef QUERY_ORDER_DETAILS_H
#define QUERY_ORDER_DETAILS_H
#include "product.hpp"
#include "matador/sql/entity.hpp"
namespace matador::test {
struct order;
struct order_details
{
unsigned long order_details_id;
sql::entity<order> order_;
sql::entity<product> product_;
template<class Operator>
void process(Operator &op) {
namespace field = matador::utils::access;
field::primary_key(op, "order_details_id", order_details_id);
field::belongs_to(op, "order_id", order_, utils::default_foreign_attributes);
field::has_one(op, "product_id", product_, utils::default_foreign_attributes);
}
};
}
#endif //QUERY_ORDER_DETAILS_H